Version 2.7.0-dev.0.0

Merge commit '28cc45945867b2391778a1f3c438507cc97d1603' into dev
diff --git a/.packages b/.packages
index 5590179..cd51491 100644
--- a/.packages
+++ b/.packages
@@ -6,6 +6,7 @@
 # by DEPS into /third_party/pkg and /third_party/pkg_tested.
 # Please update this file if you add a package to DEPS or /pkg
 #
+_fe_analyzer_shared:pkg/_fe_analyzer_shared/lib
 analysis_server:pkg/analysis_server/lib
 analysis_server_client:pkg/analysis_server_client/lib
 analysis_tool:pkg/analysis_tool/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c77e474..4b3736f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,42 @@
+## Next release
+(Add new changes here, and they will be copied to the change section for the
+ next release)
+
+### Core libraries
+
+#### `dart:io`
+
+* **Breaking change**: Added `IOOverrides.serverSocketBind` to aid in writing
+  tests that wish to mock `ServerSocket.bind`.
+
+### Dart VM
+
+* New fields added to existing instances by a reload will now be initialized
+lazily, as if the field was a late field. This makes the initialization order
+program-defined, whereas previously it was undefined.
+
+### Tools
+
+#### Linter
+
+The Linter was updated to `0.1.103`, which includes:
+
+* updates to `prefer_relative_imports` to use a faster and more robust way to check for self-package references
+* updates to our approach to checking for `lib` dir contents (speeding up `avoid_renaming_method_parameters` and
+  making `prefer_relative_imports` and `public_member_api_docs` amenable to internal package formats -- w/o pubspecs)
+
+#### Pub
+
+* `pub get` generates [`.dart_tools/package_config.json`](https://github.com/dart-lang/language/blob/62c036cc41b10fb543102d2f73ee132d1e2b2a0e/accepted/future-releases/language-versioning/package-config-file-v2.md)
+  in addition to `.packages` to support language versioning.
+
+* `pub publish` now warns about the old flutter plugin registration format.
+
+* `pub publish` now warns about the `author` field in pubspec.yaml being.
+  obsolete.
+
+* Show a proper error message when `git` is not installed.
+
 ## 2.6.0 - 2019-11-05
 
 ### Language
@@ -124,7 +163,6 @@
 * new lint: `avoid_web_libraries_in_flutter` (experimental)
 * (internal) prepare `unnecessary_lambdas` for coming `MethodInvocation` vs. `FunctionExpressionInvocation` changes
 
-
 ## 2.5.1 - 2019-09-27
 
 This is a patch release that prevents type inference failures in the analyzer
diff --git a/DEPS b/DEPS
index 8dc6a83..7614351 100644
--- a/DEPS
+++ b/DEPS
@@ -56,11 +56,11 @@
   # Revisions of /third_party/* dependencies.
   "args_tag": "1.5.0",
   "async_tag": "2.0.8",
-  "bazel_worker_tag": "bazel_worker-v0.1.20",
+  "bazel_worker_tag": "v0.1.22",
   "benchmark_harness_tag": "81641290dea44c34138a109a37e215482f405f81",
   "boolean_selector_tag" : "1.0.4",
-  "boringssl_gen_rev": "bbf52f18f425e29b1185f2f6753bec02ed8c5880",
-  "boringssl_rev" : "702e2b6d3831486535e958f262a05c75a5cb312e",
+  "boringssl_gen_rev": "b9e27cff1ff0803e97ab1f88764a83be4aa94a6d",
+  "boringssl_rev" : "4dfd5af70191b068aebe567b8e29ce108cee85ce",
   "charcode_tag": "v1.1.2",
   "chrome_rev" : "19997",
   "cli_util_rev" : "4ad7ccbe3195fd2583b30f86a86697ef61e80f41",
@@ -82,10 +82,10 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_tag": "1.3.1",  # Please see the note above before updating.
+  "dart_style_tag": "1.3.2",  # Please see the note above before updating.
 
   "args_tag" : "1.5.2",
-  "dartdoc_tag" : "v0.28.8",
+  "dartdoc_tag" : "v0.29.0",
   "ffi_tag": "ea88d71b043ee14b268c3aedff14e9eb32e20959",
   "fixnum_tag": "0.10.9",
   "glob_tag": "1.1.7",
@@ -101,7 +101,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.101",
+  "linter_tag": "0.1.103",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.1.1",
@@ -117,8 +117,8 @@
   "pedantic_tag": "v1.8.0",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_tag": "1.3.6",
-  "protobuf_rev": "7d34c9e4e552a4f66acce32e4344ae27756a1949",
-  "pub_rev": "df0f72daaa724e29ed6075e0fb5549a6d6dc5daf",
+  "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
+  "pub_rev": "80ac76400ff58fde3c5a335d860d196c3febe837",
   "pub_semver_tag": "1.4.2",
   "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
@@ -148,7 +148,7 @@
   "web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
   "web_socket_channel_tag": "1.0.9",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
-  "yaml_tag": "2.1.15",
+  "yaml_tag": "2.2.0",
   "zlib_rev": "c44fb7248079cc3d5563b14b3f758aee60d6b415",
   "crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
   "minichromium_rev": "8d641e30a8b12088649606b912c2bc4947419ccc",
@@ -342,7 +342,7 @@
   Var("dart_root") + "/third_party/pkg/pool":
       Var("dart_git") + "pool.git" + "@" + Var("pool_tag"),
   Var("dart_root") + "/third_party/pkg/protobuf":
-      Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
+       Var("dart_git") + "protobuf.git" + "@" + Var("protobuf_rev"),
   Var("dart_root") + "/third_party/pkg/pub_semver":
       Var("dart_git") + "pub_semver.git" + "@" + Var("pub_semver_tag"),
   Var("dart_root") + "/third_party/pkg/pub":
@@ -458,7 +458,17 @@
     "packages": [
       {
         "package": "dart/cfe/benchmark_data",
-        "version": "sha1sum:4168b133ab7bce01c91311a8d4f25d4d6cb026f3",
+        "version": "sha1sum:4640fa0bff40726392748d1ad3147e5dd0324ea2",
+      }
+    ],
+    "dep_type": "cipd",
+  },
+
+  Var("dart_root") + "/pkg/front_end/testcases/old_dills/dills": {
+    "packages": [
+      {
+        "package": "dart/cfe/dart2js_dills",
+        "version": "binary_version:36",
       }
     ],
     "dep_type": "cipd",
diff --git a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
index c377b7f..104588e 100644
--- a/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
+++ b/benchmarks/FfiBoringssl/dart/FfiBoringssl.dart
@@ -65,9 +65,6 @@
 //    * Architecture: x64
 //      * 23000 - 52000000 us (without optimizations)
 //      * 23000 - 30000 us (with optimizations)
-//    * Architecture: SimDBC64
-//      * 23000 - 5500000 us (without optimizations)
-//      * 23000 - 30000 us (with optimizations)
 const int L = 1000; // Length of data in bytes.
 
 final hashAlgorithm = EVP_sha512();
diff --git a/benchmarks/FfiCall/dart/FfiCall.dart b/benchmarks/FfiCall/dart/FfiCall.dart
index 68d6601..a2857e4 100644
--- a/benchmarks/FfiCall/dart/FfiCall.dart
+++ b/benchmarks/FfiCall/dart/FfiCall.dart
@@ -605,8 +605,6 @@
 //  * CPU: Intel(R) Xeon(R) Gold 6154
 //    * Architecture: x64
 //      * 200 - 1100 us
-//    * Architecture: SimDBC64
-//      * 2800 - 110000 us
 const N = 1000;
 
 class Uint8x01 extends BenchmarkBase {
diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart
index 9bfad25..50f8435 100644
--- a/benchmarks/FfiMemory/dart/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart/FfiMemory.dart
@@ -203,9 +203,6 @@
 //    * Architecture: x64
 //      * 48000 - 125000 us (without optimizations)
 //      * 14 - ??? us (expected with optimizations, on par with typed data)
-//    * Architecture: SimDBC64
-//      * 52000 - 130000 us (without optimizations)
-//      * 300 - ??? us (expected with optimizations, on par with typed data)
 const N = 1000;
 
 class PointerInt8 extends BenchmarkBase {
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 9e728c5..70bb890 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -5,19 +5,21 @@
 import("//build/config/sysroot.gni")
 
 config("sdk") {
-  # Don't allow visible symbols from libc++ to be re-exported.
-  ldflags = [
-    "-nodefaultlibs",
-    "-lc++",
-    "-lc",
-    "-lm",
-    "-lpthread",
-    "-lclang_rt.builtins",
-    "-Wl,--exclude-libs=libc++.a",
-  ]
+  ldflags = []
 
   if (is_asan || is_lsan || is_msan || is_tsan || is_ubsan) {
     ldflags += [ "-lrt" ]
+  } else if (is_clang) {
+    # Don't allow visible symbols from libc++ to be re-exported.
+    ldflags = [
+      "-nodefaultlibs",
+      "-lc++",
+      "-lc",
+      "-lm",
+      "-lpthread",
+      "-lclang_rt.builtins",
+      "-Wl,--exclude-libs=libc++.a",
+    ]
   }
 
   if (sysroot != "") {
diff --git a/pkg/_fe_analyzer_shared/LICENSE b/pkg/_fe_analyzer_shared/LICENSE
new file mode 100644
index 0000000..f75d7c2
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2019, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/_fe_analyzer_shared/README.md b/pkg/_fe_analyzer_shared/README.md
new file mode 100644
index 0000000..4bab1b6
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/README.md
@@ -0,0 +1,10 @@
+# FE/analyzer shared code
+
+This package contains logic that is shared between the front_end and
+analyzer packages.  It is intended solely to facilitate development of
+the Dart SDK, and is not intended for use by end users.  In
+particular, this package has no public API, so no guarantee is made of
+compatibility between one version of the package and the next.
+
+End users should consider using the analyzer package to analyze Dart
+source code.
diff --git a/pkg/_fe_analyzer_shared/analysis_options.yaml b/pkg/_fe_analyzer_shared/analysis_options.yaml
new file mode 100644
index 0000000..9021253
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/analysis_options.yaml
@@ -0,0 +1,20 @@
+# 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.
+
+include: analysis_options_no_lints.yaml
+
+linter:
+  rules:
+    - curly_braces_in_flow_control_structures
+    - prefer_adjacent_string_concatenation
+    - unawaited_futures
+    - recursive_getters
+    - avoid_empty_else
+    - empty_statements
+    - list_remove_unrelated_type
+    - iterable_contains_unrelated_type
+    - valid_regexps
+    - package_api_docs
+    - lines_longer_than_80_chars
+    # - always_specify_types
diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
new file mode 100644
index 0000000..7bc4b9d9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
@@ -0,0 +1,14 @@
+# 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.
+
+analyzer:
+  errors:
+    # Allow having TODOs in the code
+    todo: ignore
+  exclude:
+    - test/flow_analysis/assigned_variables/data/**
+    - test/flow_analysis/definite_assignment/data/**
+    - test/flow_analysis/nullability/data/**
+    - test/flow_analysis/reachability/data/**
+    - test/flow_analysis/type_promotion/data/**
diff --git a/pkg/front_end/lib/src/base/errors.dart b/pkg/_fe_analyzer_shared/lib/src/base/errors.dart
similarity index 100%
rename from pkg/front_end/lib/src/base/errors.dart
rename to pkg/_fe_analyzer_shared/lib/src/base/errors.dart
diff --git a/pkg/front_end/lib/src/base/syntactic_entity.dart b/pkg/_fe_analyzer_shared/lib/src/base/syntactic_entity.dart
similarity index 100%
rename from pkg/front_end/lib/src/base/syntactic_entity.dart
rename to pkg/_fe_analyzer_shared/lib/src/base/syntactic_entity.dart
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
new file mode 100644
index 0000000..ee4e500
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -0,0 +1,2683 @@
+// 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:meta/meta.dart';
+
+/// [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
+/// should be used prior to running flow analysis, to compute the sets of
+/// variables to pass in to flow analysis.
+///
+/// This class is intended to be used in two phases.  In the first phase, the
+/// client should traverse the source code recursively, making calls to
+/// [beginNode] and [endNode] to indicate the constructs in which writes should
+/// be tracked, and calls to [write] to indicate when a write is encountered.
+/// The order of visiting is not important provided that nesting is respected.
+/// This phase is called the "pre-traversal" because it should happen prior to
+/// flow analysis.
+///
+/// Then, in the second phase, the client may make queries using
+/// [capturedAnywhere], [writtenInNode], and [capturedInNode].
+///
+/// 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> {
+  /// Mapping from a node to the info for that node.
+  final Map<Node, AssignedVariablesNodeInfo<Variable>> _info =
+      new Map<Node, AssignedVariablesNodeInfo<Variable>>.identity();
+
+  /// Info for the variables written or captured anywhere in the code being
+  /// analyzed.
+  final AssignedVariablesNodeInfo<Variable> _anywhere =
+      new AssignedVariablesNodeInfo<Variable>();
+
+  /// Stack of info for nodes that have been entered but not yet left.
+  final List<AssignedVariablesNodeInfo<Variable>> _stack = [
+    new AssignedVariablesNodeInfo<Variable>()
+  ];
+
+  /// When assertions are enabled, the set of info objects that have been
+  /// retrieved by [deferNode] but not yet sent to [storeNode].
+  final Set<AssignedVariablesNodeInfo<Variable>> _deferredInfos =
+      new Set<AssignedVariablesNodeInfo<Variable>>.identity();
+
+  /// This method should be called during pre-traversal, to mark the start of a
+  /// loop statement, switch statement, try statement, loop collection element,
+  /// local function, or closure which might need to be queried later.
+  ///
+  /// [isClosure] should be true if the node is a local function or closure.
+  ///
+  /// The span between the call to [beginNode] and [endNode] should cover any
+  /// statements and expressions that might be crossed by a backwards jump.  So
+  /// for instance, in a "for" loop, the condition, updaters, and body should be
+  /// covered, but the initializers should not.  Similarly, in a switch
+  /// statement, the body of the switch statement should be covered, but the
+  /// switch expression should not.
+  void beginNode() {
+    _stack.add(new AssignedVariablesNodeInfo<Variable>());
+  }
+
+  /// This method should be called during pre-traversal, to indicate that the
+  /// declaration of a variable has been found.
+  ///
+  /// It is not required for the declaration to be seen prior to its use (this
+  /// is to allow for error recovery in the analyzer).
+  void declare(Variable variable) {
+    _stack.last._declared.add(variable);
+  }
+
+  /// This method may be called during pre-traversal, to mark the end of a
+  /// loop statement, switch statement, try statement, loop collection element,
+  /// local function, or closure which might need to be queried later.
+  ///
+  /// [isClosure] should be true if the node is a local function or closure.
+  ///
+  /// In contrast to [endNode], this method doesn't store the data gathered for
+  /// the node for later use; instead it returns it to the caller.  At a later
+  /// time, the caller should pass the returned data to [storeNodeInfo].
+  ///
+  /// See [beginNode] for more details.
+  AssignedVariablesNodeInfo<Variable> deferNode({bool isClosure: false}) {
+    AssignedVariablesNodeInfo<Variable> info = _stack.removeLast();
+    info._written.removeAll(info._declared);
+    info._captured.removeAll(info._declared);
+    AssignedVariablesNodeInfo<Variable> last = _stack.last;
+    last._written.addAll(info._written);
+    last._captured.addAll(info._captured);
+    if (isClosure) {
+      last._captured.addAll(info._written);
+      _anywhere._captured.addAll(info._written);
+    }
+    // If we have already deferred this info, something has gone horribly wrong.
+    assert(_deferredInfos.add(info));
+    return info;
+  }
+
+  /// This method may be called during pre-traversal, to discard the effects of
+  /// the most recent unmatched call to [beginNode].
+  ///
+  /// This is necessary because try/catch/finally needs to be desugared into
+  /// a try/catch nested inside a try/finally, however the pre-traversal phase
+  /// of the front end happens during parsing, so when a `try` is encountered,
+  /// it is not known whether it will need to be desugared into two nested
+  /// `try`s.  To cope with this, the front end may call [beginNode] twice upon
+  /// seeing the two `try`s, and later if it turns out that no desugaring was
+  /// needed, use [discardNode] to discard the effects of one of the [beginNode]
+  /// calls.
+  void discardNode() {
+    AssignedVariablesNodeInfo<Variable> discarded = _stack.removeLast();
+    AssignedVariablesNodeInfo<Variable> last = _stack.last;
+    last._declared.addAll(discarded._declared);
+    last._written.addAll(discarded._written);
+    last._captured.addAll(discarded._captured);
+  }
+
+  /// This method should be called during pre-traversal, to mark the end of a
+  /// loop statement, switch statement, try statement, loop collection element,
+  /// local function, or closure which might need to be queried later.
+  ///
+  /// [isClosure] should be true if the node is a local function or closure.
+  ///
+  /// This is equivalent to a call to [deferNode] followed immediately by a call
+  /// to [storeInfo].
+  ///
+  /// See [beginNode] for more details.
+  void endNode(Node node, {bool isClosure: false}) {
+    storeInfo(node, deferNode(isClosure: isClosure));
+  }
+
+  /// 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);
+    assert(
+        info != null,
+        'No information for $from (${from.hashCode}) in '
+        '{${_info.keys.map((k) => '$k (${k.hashCode})').join(',')}}');
+
+    _info[to] = info;
+  }
+
+  /// Call this after visiting the code to be analyzed, to check invariants.
+  void finish() {
+    assert(() {
+      assert(
+          _deferredInfos.isEmpty, "Deferred infos not stored: $_deferredInfos");
+      assert(_stack.length == 1, "Unexpected stack: $_stack");
+      AssignedVariablesNodeInfo<Variable> last = _stack.last;
+      Set<Variable> undeclaredWrites = last._written.difference(last._declared);
+      assert(undeclaredWrites.isEmpty,
+          'Variables written to but not declared: $undeclaredWrites');
+      Set<Variable> undeclaredCaptures =
+          last._captured.difference(last._declared);
+      assert(undeclaredCaptures.isEmpty,
+          'Variables captured but not declared: $undeclaredCaptures');
+      return true;
+    }());
+  }
+
+  /// This method may be called at any time between a call to [deferNode] and
+  /// the call to [finish], to store assigned variable info for the node.
+  void storeInfo(Node node, AssignedVariablesNodeInfo<Variable> info) {
+    // Caller should not try to store the same piece of info more than once.
+    assert(_deferredInfos.remove(info));
+    _info[node] = info;
+  }
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('AssignedVariables(');
+    _printOn(sb);
+    sb.write(')');
+    return sb.toString();
+  }
+
+  /// This method should be called during pre-traversal, to mark a write to a
+  /// variable.
+  void write(Variable variable) {
+    _stack.last._written.add(variable);
+    _anywhere._written.add(variable);
+  }
+
+  /// Queries the information stored for the given [node].
+  AssignedVariablesNodeInfo<Variable> _getInfoForNode(Node node) {
+    return _info[node] ??
+        (throw new StateError('No information for $node (${node.hashCode}) in '
+            '{${_info.keys.map((k) => '$k (${k.hashCode})').join(',')}}'));
+  }
+
+  void _printOn(StringBuffer sb) {
+    sb.write('_info=$_info,');
+    sb.write('_stack=$_stack,');
+    sb.write('_anywhere=$_anywhere');
+  }
+}
+
+/// 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>
+    extends AssignedVariables<Node, Variable> {
+  Set<Variable> get capturedAnywhere => _anywhere._captured;
+
+  Set<Variable> get declaredAtTopLevel => _stack.first._declared;
+
+  Set<Variable> get writtenAnywhere => _anywhere._written;
+
+  Set<Variable> capturedInNode(Node node) => _getInfoForNode(node)._captured;
+
+  Set<Variable> declaredInNode(Node node) => _getInfoForNode(node)._declared;
+
+  bool isTracked(Node node) => _info.containsKey(node);
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('AssignedVariablesForTesting(');
+    _printOn(sb);
+    sb.write(')');
+    return sb.toString();
+  }
+
+  Set<Variable> writtenInNode(Node node) => _getInfoForNode(node)._written;
+}
+
+/// Information tracked by [AssignedVariables] for a single node.
+class AssignedVariablesNodeInfo<Variable> {
+  final Set<Variable> _written = new Set<Variable>.identity();
+
+  // The set of local variables that are potentially written in the node.
+  final Set<Variable> _captured = 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> _declared = new Set<Variable>.identity();
+
+  // The set of local variables that are declared in the node.
+  String toString() =>
+      'AssignedVariablesNodeInfo(_written=$_written, _captured=$_captured, '
+      '_declared=$_declared)';
+}
+
+/// A collection of flow models representing the possible outcomes of evaluating
+/// an expression that are relevant to flow analysis.
+class ExpressionInfo<Variable, Type> {
+  /// The state after the expression evaluates, if we don't care what it
+  /// evaluates to.
+  final FlowModel<Variable, Type> after;
+
+  /// The state after the expression evaluates, if it evaluates to `true`.
+  final FlowModel<Variable, Type> ifTrue;
+
+  /// The state after the expression evaluates, if it evaluates to `false`.
+  final FlowModel<Variable, Type> ifFalse;
+
+  ExpressionInfo(this.after, this.ifTrue, this.ifFalse);
+
+  @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
+/// front end.
+///
+/// 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> {
+  factory FlowAnalysis(TypeOperations<Variable, Type> typeOperations,
+      AssignedVariables<Node, Variable> assignedVariables) {
+    return new _FlowAnalysisImpl(typeOperations, assignedVariables);
+  }
+
+  /// Return `true` if the current state is reachable.
+  bool get isReachable;
+
+  /// Call this method after visiting an "as" expression.
+  ///
+  /// [subExpression] should be the expression to which the "as" check was
+  /// applied.  [type] should be the type being checked.
+  void asExpression_end(Expression subExpression, Type type);
+
+  /// Call this method after visiting the condition part of an assert statement
+  /// (or assert initializer).
+  ///
+  /// [condition] should be the assert statement's condition.
+  ///
+  /// See [assert_begin] for more information.
+  void assert_afterCondition(Expression condition);
+
+  /// Call this method before visiting the condition part of an assert statement
+  /// (or assert initializer).
+  ///
+  /// The order of visiting an assert statement with no "message" part should
+  /// be:
+  /// - Call [assert_begin]
+  /// - Visit the condition
+  /// - Call [assert_afterCondition]
+  /// - Call [assert_end]
+  ///
+  /// The order of visiting an assert statement with a "message" part should be:
+  /// - Call [assert_begin]
+  /// - Visit the condition
+  /// - Call [assert_afterCondition]
+  /// - Visit the message
+  /// - Call [assert_end]
+  void assert_begin();
+
+  /// Call this method after visiting an assert statement (or assert
+  /// initializer).
+  ///
+  /// See [assert_begin] for more information.
+  void assert_end();
+
+  /// Call this method when visiting a boolean literal expression.
+  void booleanLiteral(Expression expression, bool value);
+
+  /// Call this method upon reaching the ":" part of a conditional expression
+  /// ("?:").  [thenExpression] should be the expression preceding the ":".
+  void conditional_elseBegin(Expression thenExpression);
+
+  /// Call this method when finishing the visit of a conditional expression
+  /// ("?:").  [elseExpression] should be the expression preceding the ":", and
+  /// [conditionalExpression] should be the whole conditional expression.
+  void conditional_end(
+      Expression conditionalExpression, Expression elseExpression);
+
+  /// Call this method upon reaching the "?" part of a conditional expression
+  /// ("?:").  [condition] should be the expression preceding the "?".
+  void conditional_thenBegin(Expression condition);
+
+  /// Call this method before visiting the body of a "do-while" statement.
+  /// [doStatement] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the do-while statement.
+  void doStatement_bodyBegin(Statement doStatement);
+
+  /// Call this method after visiting the body of a "do-while" statement, and
+  /// before visiting its condition.
+  void doStatement_conditionBegin();
+
+  /// Call this method after visiting the condition of a "do-while" statement.
+  /// [condition] should be the condition of the loop.
+  void doStatement_end(Expression condition);
+
+  /// Call this method just after visiting a binary `==` or `!=` expression.
+  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+      {bool notEqual = false});
+
+  /// Call this method just after visiting the left hand side of a binary `==`
+  /// or `!=` expression.
+  void equalityOp_rightBegin(Expression leftOperand);
+
+  /// This method should be called at the conclusion of flow analysis for a top
+  /// level function or method.  Performs assertion checks.
+  void finish();
+
+  /// Call this method just before visiting the body of a conventional "for"
+  /// statement or collection element.  See [for_conditionBegin] for details.
+  ///
+  /// If a "for" statement is being entered, [node] is an opaque representation
+  /// of the loop, for use as the target of future calls to [handleBreak] or
+  /// [handleContinue].  If a "for" collection element is being entered, [node]
+  /// should be `null`.
+  ///
+  /// [condition] is an opaque representation of the loop condition; it is
+  /// matched against expressions passed to previous calls to determine whether
+  /// 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);
+
+  /// Call this method just before visiting the condition of a conventional
+  /// "for" statement or collection element.
+  ///
+  /// Note that a conventional "for" statement is a statement of the form
+  /// `for (initializers; condition; updaters) body`.  Statements of the form
+  /// `for (variable in iterable) body` should use [forEach_bodyBegin].  Similar
+  /// for "for" collection elements.
+  ///
+  /// The order of visiting a "for" statement or collection element should be:
+  /// - Visit the initializers.
+  /// - Call [for_conditionBegin].
+  /// - Visit the condition.
+  /// - Call [for_bodyBegin].
+  /// - Visit the body.
+  /// - Call [for_updaterBegin].
+  /// - Visit the updaters.
+  /// - Call [for_end].
+  ///
+  /// [node] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the for statement.
+  void for_conditionBegin(Node node);
+
+  /// Call this method just after visiting the updaters of a conventional "for"
+  /// statement or collection element.  See [for_conditionBegin] for details.
+  void for_end();
+
+  /// Call this method just before visiting the updaters of a conventional "for"
+  /// statement or collection element.  See [for_conditionBegin] for details.
+  void for_updaterBegin();
+
+  /// Call this method just before visiting the body of a "for-in" statement or
+  /// collection element.
+  ///
+  /// The order of visiting a "for-in" statement or collection element should
+  /// be:
+  /// - Visit the iterable expression.
+  /// - Call [forEach_bodyBegin].
+  /// - Visit the body.
+  /// - Call [forEach_end].
+  ///
+  /// [node] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the for statement.  [loopVariable] should
+  /// 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);
+
+  /// Call this method just before visiting the body of a "for-in" statement or
+  /// collection element.  See [forEach_bodyBegin] for details.
+  void forEach_end();
+
+  /// Call this method just before visiting the body of a function expression or
+  /// local function.
+  ///
+  /// [node] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the function expression.
+  void functionExpression_begin(Node node);
+
+  /// Call this method just after visiting the body of a function expression or
+  /// local function.
+  void functionExpression_end();
+
+  /// Call this method when visiting a break statement.  [target] should be the
+  /// statement targeted by the break.
+  void handleBreak(Statement target);
+
+  /// Call this method when visiting a continue statement.  [target] should be
+  /// the statement targeted by the continue.
+  void handleContinue(Statement target);
+
+  /// Register the fact that the current state definitely exists, e.g. returns
+  /// from the body, throws an exception, etc.
+  ///
+  /// Should also be called if a subexpression's type is Never.
+  void handleExit();
+
+  /// Call this method after visiting the RHS of an if-null expression ("??")
+  /// or if-null assignment ("??=").
+  ///
+  /// Note: for an if-null assignment, the call to [write] should occur before
+  /// the call to [ifNullExpression_end] (since the write only occurs if the
+  /// read resulted in a null value).
+  void ifNullExpression_end();
+
+  /// Call this method after visiting the LHS of an if-null expression ("??")
+  /// or if-null assignment ("??=").
+  void ifNullExpression_rightBegin(Expression leftHandSide);
+
+  /// Call this method after visiting the "then" part of an if statement, and
+  /// before visiting the "else" part.
+  void ifStatement_elseBegin();
+
+  /// Call this method after visiting an if statement.
+  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.
+  ///
+  /// The order of visiting an if statement with no "else" part should be:
+  /// - Visit the condition
+  /// - Call [ifStatement_thenBegin]
+  /// - Visit the "then" statement
+  /// - Call [ifStatement_end], passing `false` for `hasElse`.
+  ///
+  /// The order of visiting an if statement with an "else" part should be:
+  /// - Visit the condition
+  /// - Call [ifStatement_thenBegin]
+  /// - Visit the "then" statement
+  /// - Call [ifStatement_elseBegin]
+  /// - Visit the "else" statement
+  /// - Call [ifStatement_end], passing `true` for `hasElse`.
+  void ifStatement_thenBegin(Expression condition);
+
+  /// Register an initialized declaration of the given [variable] in the current
+  /// state.  Should also be called for function parameters.
+  void initialize(Variable variable);
+
+  /// Return whether the [variable] is definitely assigned in the current state.
+  bool isAssigned(Variable variable);
+
+  /// Call this method after visiting the LHS of an "is" expression.
+  ///
+  /// [isExpression] should be the complete expression.  [subExpression] should
+  /// be the expression to which the "is" check was applied.  [isNot] should be
+  /// a boolean indicating whether this is an "is" or an "is!" expression.
+  /// [type] should be the type being checked.
+  void isExpression_end(
+      Expression isExpression, Expression subExpression, bool isNot, Type type);
+
+  /// Call this method after visiting the RHS of a logical binary operation
+  /// ("||" or "&&").
+  /// [wholeExpression] should be the whole logical binary expression.
+  /// [rightOperand] should be the RHS.  [isAnd] should indicate whether the
+  /// logical operator is "&&" or "||".
+  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
+      {@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});
+
+  /// Call this method after visiting a logical not ("!") expression.
+  /// [notExpression] should be the complete expression.  [operand] should be
+  /// the subexpression whose logical value is being negated.
+  void logicalNot_end(Expression notExpression, Expression operand);
+
+  /// Call this method just after visiting a non-null assertion (`x!`)
+  /// expression.
+  void nonNullAssert_end(Expression operand);
+
+  /// Call this method after visiting an expression using `?.`.
+  void nullAwareAccess_end();
+
+  /// Call this method after visiting a null-aware operator such as `?.`,
+  /// `?..`, `?.[`, or `?..[`.
+  ///
+  /// [target] should be the expression just before the null-aware operator, or
+  /// `null` if the null-aware access starts a cascade section.
+  ///
+  /// Note that [nullAwareAccess_end] should be called after the conclusion
+  /// of any null-shorting that is caused by the `?.`.  So, for example, if the
+  /// 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);
+
+  /// Call this method when encountering an expression that is a `null` literal.
+  void nullLiteral(Expression expression);
+
+  /// Call this method just after visiting a parenthesized expression.
+  ///
+  /// This is only necessary if the implementation uses a different [Expression]
+  /// object to represent a parenthesized expression and its contents.
+  void parenthesizedExpression(
+      Expression outerExpression, Expression innerExpression);
+
+  /// Retrieves the type that the [variable] is promoted to, if the [variable]
+  /// is currently promoted.  Otherwise returns `null`.
+  ///
+  /// For testing only.  Please use [variableRead] instead.
+  @visibleForTesting
+  Type promotedType(Variable variable);
+
+  /// Call this method just before visiting one of the cases in the body of a
+  /// switch statement.  See [switchStatement_expressionEnd] for details.
+  ///
+  /// [hasLabel] indicates whether the case has any labels.
+  ///
+  /// [node] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the switch statement.
+  void switchStatement_beginCase(bool hasLabel, Node node);
+
+  /// Call this method just after visiting the body of a switch statement.  See
+  /// [switchStatement_expressionEnd] for details.
+  ///
+  /// [hasDefault] indicates whether the switch statement had a "default" case.
+  void switchStatement_end(bool hasDefault);
+
+  /// Call this method just after visiting the expression part of a switch
+  /// statement.
+  ///
+  /// The order of visiting a switch statement should be:
+  /// - Visit the switch expression.
+  /// - Call [switchStatement_expressionEnd].
+  /// - For each switch case (including the default case, if any):
+  ///   - Call [switchStatement_beginCase].
+  ///   - Visit the case.
+  /// - Call [switchStatement_end].
+  void switchStatement_expressionEnd(Statement switchStatement);
+
+  /// Call this method just before visiting the body of a "try/catch" statement.
+  ///
+  /// The order of visiting a "try/catch" statement should be:
+  /// - Call [tryCatchStatement_bodyBegin]
+  /// - Visit the try block
+  /// - Call [tryCatchStatement_bodyEnd]
+  /// - For each catch block:
+  ///   - Call [tryCatchStatement_catchBegin]
+  ///   - Call [initialize] for the exception and stack trace variables
+  ///   - Visit the catch block
+  ///   - Call [tryCatchStatement_catchEnd]
+  /// - Call [tryCatchStatement_end]
+  ///
+  /// The order of visiting a "try/catch/finally" statement should be:
+  /// - Call [tryFinallyStatement_bodyBegin]
+  /// - Call [tryCatchStatement_bodyBegin]
+  /// - Visit the try block
+  /// - Call [tryCatchStatement_bodyEnd]
+  /// - For each catch block:
+  ///   - Call [tryCatchStatement_catchBegin]
+  ///   - Call [initialize] for the exception and stack trace variables
+  ///   - Visit the catch block
+  ///   - Call [tryCatchStatement_catchEnd]
+  /// - Call [tryCatchStatement_end]
+  /// - Call [tryFinallyStatement_finallyBegin]
+  /// - Visit the finally block
+  /// - Call [tryFinallyStatement_end]
+  void tryCatchStatement_bodyBegin();
+
+  /// Call this method just after visiting the body of a "try/catch" statement.
+  /// See [tryCatchStatement_bodyBegin] for details.
+  ///
+  /// [body] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the "try" part of the try/catch statement.
+  void tryCatchStatement_bodyEnd(Node body);
+
+  /// Call this method just before visiting a catch clause of a "try/catch"
+  /// statement.  See [tryCatchStatement_bodyBegin] for details.
+  ///
+  /// [exceptionVariable] should be the exception variable declared by the catch
+  /// clause, or `null` if there is no exception variable.  Similar for
+  /// [stackTraceVariable].
+  void tryCatchStatement_catchBegin(
+      Variable exceptionVariable, Variable stackTraceVariable);
+
+  /// Call this method just after visiting a catch clause of a "try/catch"
+  /// statement.  See [tryCatchStatement_bodyBegin] for details.
+  void tryCatchStatement_catchEnd();
+
+  /// Call this method just after visiting a "try/catch" statement.  See
+  /// [tryCatchStatement_bodyBegin] for details.
+  void tryCatchStatement_end();
+
+  /// Call this method just before visiting the body of a "try/finally"
+  /// statement.
+  ///
+  /// The order of visiting a "try/finally" statement should be:
+  /// - Call [tryFinallyStatement_bodyBegin]
+  /// - Visit the try block
+  /// - Call [tryFinallyStatement_finallyBegin]
+  /// - Visit the finally block
+  /// - Call [tryFinallyStatement_end]
+  ///
+  /// See [tryCatchStatement_bodyBegin] for the order of visiting a
+  /// "try/catch/finally" statement.
+  void tryFinallyStatement_bodyBegin();
+
+  /// Call this method just after visiting a "try/finally" statement.
+  /// See [tryFinallyStatement_bodyBegin] for details.
+  ///
+  /// [finallyBlock] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the "finally" part of the try/finally
+  /// statement.
+  void tryFinallyStatement_end(Node finallyBlock);
+
+  /// Call this method just before visiting the finally block of a "try/finally"
+  /// statement.  See [tryFinallyStatement_bodyBegin] for details.
+  ///
+  /// [body] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the "try" part of the try/finally
+  /// statement.
+  void tryFinallyStatement_finallyBegin(Node body);
+
+  /// Call this method when encountering an expression that reads the value of
+  /// a variable.
+  ///
+  /// If the variable's type is currently promoted, the promoted type is
+  /// returned.  Otherwise `null` is returned.
+  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
+  /// be the condition part of the while statement.
+  void whileStatement_bodyBegin(Statement whileStatement, Expression condition);
+
+  /// Call this method before visiting the condition part of a "while"
+  /// statement.
+  ///
+  /// [node] should be the same node that was passed to
+  /// [AssignedVariables.endNode] for the while statement.
+  void whileStatement_conditionBegin(Node node);
+
+  /// Call this method after visiting a "while" statement.
+  void whileStatement_end();
+
+  /// Register write of the given [variable] in the current state.
+  /// [writtenType] should be the type of the value that was written.
+  void write(Variable variable, Type writtenType);
+}
+
+/// 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;
+
+  bool _exceptionOccurred = false;
+
+  factory FlowAnalysisDebug(TypeOperations<Variable, Type> typeOperations,
+      AssignedVariables<Node, Variable> assignedVariables) {
+    print('FlowAnalysisDebug()');
+    return new FlowAnalysisDebug._(
+        new _FlowAnalysisImpl(typeOperations, assignedVariables));
+  }
+
+  FlowAnalysisDebug._(this._wrapped);
+
+  @override
+  bool get isReachable =>
+      _wrap('isReachable', () => _wrapped.isReachable, isQuery: true);
+
+  @override
+  void asExpression_end(Expression subExpression, Type type) {
+    _wrap('asExpression_end($subExpression, $type)',
+        () => _wrapped.asExpression_end(subExpression, type));
+  }
+
+  @override
+  void assert_afterCondition(Expression condition) {
+    _wrap('assert_afterCondition($condition)',
+        () => _wrapped.assert_afterCondition(condition));
+  }
+
+  @override
+  void assert_begin() {
+    _wrap('assert_begin()', () => _wrapped.assert_begin());
+  }
+
+  @override
+  void assert_end() {
+    _wrap('assert_end()', () => _wrapped.assert_end());
+  }
+
+  @override
+  void booleanLiteral(Expression expression, bool value) {
+    _wrap('booleanLiteral($expression, $value)',
+        () => _wrapped.booleanLiteral(expression, value));
+  }
+
+  @override
+  void conditional_elseBegin(Expression thenExpression) {
+    _wrap('conditional_elseBegin($thenExpression',
+        () => _wrapped.conditional_elseBegin(thenExpression));
+  }
+
+  @override
+  void conditional_end(
+      Expression conditionalExpression, Expression elseExpression) {
+    _wrap('conditional_end($conditionalExpression, $elseExpression',
+        () => _wrapped.conditional_end(conditionalExpression, elseExpression));
+  }
+
+  @override
+  void conditional_thenBegin(Expression condition) {
+    _wrap('conditional_thenBegin($condition)',
+        () => _wrapped.conditional_thenBegin(condition));
+  }
+
+  @override
+  void doStatement_bodyBegin(Statement doStatement) {
+    return _wrap('doStatement_bodyBegin($doStatement)',
+        () => _wrapped.doStatement_bodyBegin(doStatement));
+  }
+
+  @override
+  void doStatement_conditionBegin() {
+    return _wrap('doStatement_conditionBegin()',
+        () => _wrapped.doStatement_conditionBegin());
+  }
+
+  @override
+  void doStatement_end(Expression condition) {
+    return _wrap('doStatement_end($condition)',
+        () => _wrapped.doStatement_end(condition));
+  }
+
+  @override
+  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+      {bool notEqual = false}) {
+    _wrap(
+        'equalityOp_end($wholeExpression, $rightOperand, notEqual: $notEqual)',
+        () => _wrapped.equalityOp_end(wholeExpression, rightOperand,
+            notEqual: notEqual));
+  }
+
+  @override
+  void equalityOp_rightBegin(Expression leftOperand) {
+    _wrap('equalityOp_rightBegin($leftOperand)',
+        () => _wrapped.equalityOp_rightBegin(leftOperand));
+  }
+
+  @override
+  void finish() {
+    if (_exceptionOccurred) {
+      print('finish() (skipped)');
+    } else {
+      print('finish()');
+      _wrapped.finish();
+    }
+  }
+
+  @override
+  void for_bodyBegin(Statement node, Expression condition) {
+    _wrap('for_bodyBegin($node, $condition)',
+        () => _wrapped.for_bodyBegin(node, condition));
+  }
+
+  @override
+  void for_conditionBegin(Node node) {
+    _wrap('for_conditionBegin($node)', () => _wrapped.for_conditionBegin(node));
+  }
+
+  @override
+  void for_end() {
+    _wrap('for_end()', () => _wrapped.for_end());
+  }
+
+  @override
+  void for_updaterBegin() {
+    _wrap('for_updaterBegin()', () => _wrapped.for_updaterBegin());
+  }
+
+  @override
+  void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
+    return _wrap('forEach_bodyBegin($node, $loopVariable, $writtenType)',
+        () => _wrapped.forEach_bodyBegin(node, loopVariable, writtenType));
+  }
+
+  @override
+  void forEach_end() {
+    return _wrap('forEach_end()', () => _wrapped.forEach_end());
+  }
+
+  @override
+  void functionExpression_begin(Node node) {
+    _wrap('functionExpression_begin($node)',
+        () => _wrapped.functionExpression_begin(node));
+  }
+
+  @override
+  void functionExpression_end() {
+    _wrap('functionExpression_end()', () => _wrapped.functionExpression_end());
+  }
+
+  @override
+  void handleBreak(Statement target) {
+    _wrap('handleBreak($target)', () => _wrapped.handleBreak(target));
+  }
+
+  @override
+  void handleContinue(Statement target) {
+    _wrap('handleContinue($target)', () => _wrapped.handleContinue(target));
+  }
+
+  @override
+  void handleExit() {
+    _wrap('handleExit()', () => _wrapped.handleExit());
+  }
+
+  @override
+  void ifNullExpression_end() {
+    return _wrap(
+        'ifNullExpression_end()', () => _wrapped.ifNullExpression_end());
+  }
+
+  @override
+  void ifNullExpression_rightBegin(Expression leftHandSide) {
+    return _wrap('ifNullExpression_rightBegin($leftHandSide)',
+        () => _wrapped.ifNullExpression_rightBegin(leftHandSide));
+  }
+
+  @override
+  void ifStatement_elseBegin() {
+    return _wrap(
+        'ifStatement_elseBegin()', () => _wrapped.ifStatement_elseBegin());
+  }
+
+  @override
+  void ifStatement_end(bool hasElse) {
+    _wrap('ifStatement_end($hasElse)', () => _wrapped.ifStatement_end(hasElse));
+  }
+
+  @override
+  void ifStatement_thenBegin(Expression condition) {
+    _wrap('ifStatement_thenBegin($condition)',
+        () => _wrapped.ifStatement_thenBegin(condition));
+  }
+
+  @override
+  void initialize(Variable variable) {
+    _wrap('initialize($variable)', () => _wrapped.initialize(variable));
+  }
+
+  @override
+  bool isAssigned(Variable variable) {
+    return _wrap('isAssigned($variable)', () => _wrapped.isAssigned(variable),
+        isQuery: true);
+  }
+
+  @override
+  void isExpression_end(Expression isExpression, Expression subExpression,
+      bool isNot, Type type) {
+    _wrap(
+        'isExpression_end($isExpression, $subExpression, $isNot, $type)',
+        () => _wrapped.isExpression_end(
+            isExpression, subExpression, isNot, type));
+  }
+
+  @override
+  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
+      {@required bool isAnd}) {
+    _wrap(
+        'logicalBinaryOp_end($wholeExpression, $rightOperand, isAnd: $isAnd)',
+        () => _wrapped.logicalBinaryOp_end(wholeExpression, rightOperand,
+            isAnd: isAnd));
+  }
+
+  @override
+  void logicalBinaryOp_rightBegin(Expression leftOperand,
+      {@required bool isAnd}) {
+    _wrap('logicalBinaryOp_rightBegin($leftOperand, isAnd: $isAnd)',
+        () => _wrapped.logicalBinaryOp_rightBegin(leftOperand, isAnd: isAnd));
+  }
+
+  @override
+  void logicalNot_end(Expression notExpression, Expression operand) {
+    return _wrap('logicalNot_end($notExpression, $operand)',
+        () => _wrapped.logicalNot_end(notExpression, operand));
+  }
+
+  @override
+  void nonNullAssert_end(Expression operand) {
+    return _wrap('nonNullAssert_end($operand)',
+        () => _wrapped.nonNullAssert_end(operand));
+  }
+
+  @override
+  void nullAwareAccess_end() {
+    _wrap('nullAwareAccess_end()', () => _wrapped.nullAwareAccess_end());
+  }
+
+  @override
+  void nullAwareAccess_rightBegin(Expression target) {
+    _wrap('nullAwareAccess_rightBegin($target)',
+        () => _wrapped.nullAwareAccess_rightBegin(target));
+  }
+
+  @override
+  void nullLiteral(Expression expression) {
+    _wrap('nullLiteral($expression)', () => _wrapped.nullLiteral(expression));
+  }
+
+  @override
+  void parenthesizedExpression(
+      Expression outerExpression, Expression innerExpression) {
+    _wrap(
+        'parenthesizedExpression($outerExpression, $innerExpression)',
+        () =>
+            _wrapped.parenthesizedExpression(outerExpression, innerExpression));
+  }
+
+  @override
+  Type promotedType(Variable variable) {
+    return _wrap(
+        'promotedType($variable)', () => _wrapped.promotedType(variable),
+        isQuery: true);
+  }
+
+  @override
+  void switchStatement_beginCase(bool hasLabel, Node node) {
+    _wrap('switchStatement_beginCase($hasLabel, $node)',
+        () => _wrapped.switchStatement_beginCase(hasLabel, node));
+  }
+
+  @override
+  void switchStatement_end(bool hasDefault) {
+    _wrap('switchStatement_end($hasDefault)',
+        () => _wrapped.switchStatement_end(hasDefault));
+  }
+
+  @override
+  void switchStatement_expressionEnd(Statement switchStatement) {
+    _wrap('switchStatement_expressionEnd($switchStatement)',
+        () => _wrapped.switchStatement_expressionEnd(switchStatement));
+  }
+
+  @override
+  void tryCatchStatement_bodyBegin() {
+    return _wrap('tryCatchStatement_bodyBegin()',
+        () => _wrapped.tryCatchStatement_bodyBegin());
+  }
+
+  @override
+  void tryCatchStatement_bodyEnd(Node body) {
+    return _wrap('tryCatchStatement_bodyEnd($body)',
+        () => _wrapped.tryCatchStatement_bodyEnd(body));
+  }
+
+  @override
+  void tryCatchStatement_catchBegin(
+      Variable exceptionVariable, Variable stackTraceVariable) {
+    return _wrap(
+        'tryCatchStatement_catchBegin($exceptionVariable, $stackTraceVariable)',
+        () => _wrapped.tryCatchStatement_catchBegin(
+            exceptionVariable, stackTraceVariable));
+  }
+
+  @override
+  void tryCatchStatement_catchEnd() {
+    return _wrap('tryCatchStatement_catchEnd()',
+        () => _wrapped.tryCatchStatement_catchEnd());
+  }
+
+  @override
+  void tryCatchStatement_end() {
+    return _wrap(
+        'tryCatchStatement_end()', () => _wrapped.tryCatchStatement_end());
+  }
+
+  @override
+  void tryFinallyStatement_bodyBegin() {
+    return _wrap('tryFinallyStatement_bodyBegin()',
+        () => _wrapped.tryFinallyStatement_bodyBegin());
+  }
+
+  @override
+  void tryFinallyStatement_end(Node finallyBlock) {
+    return _wrap('tryFinallyStatement_end($finallyBlock)',
+        () => _wrapped.tryFinallyStatement_end(finallyBlock));
+  }
+
+  @override
+  void tryFinallyStatement_finallyBegin(Node body) {
+    return _wrap('tryFinallyStatement_finallyBegin($body)',
+        () => _wrapped.tryFinallyStatement_finallyBegin(body));
+  }
+
+  @override
+  Type variableRead(Expression expression, Variable variable) {
+    return _wrap('variableRead($expression, $variable)',
+        () => _wrapped.variableRead(expression, variable),
+        isQuery: true, isPure: false);
+  }
+
+  @override
+  void whileStatement_bodyBegin(
+      Statement whileStatement, Expression condition) {
+    return _wrap('whileStatement_bodyBegin($whileStatement, $condition)',
+        () => _wrapped.whileStatement_bodyBegin(whileStatement, condition));
+  }
+
+  @override
+  void whileStatement_conditionBegin(Node node) {
+    return _wrap('whileStatement_conditionBegin($node)',
+        () => _wrapped.whileStatement_conditionBegin(node));
+  }
+
+  @override
+  void whileStatement_end() {
+    return _wrap('whileStatement_end()', () => _wrapped.whileStatement_end());
+  }
+
+  @override
+  void write(Variable variable, Type writtenType) {
+    _wrap('write($variable, $writtenType)',
+        () => _wrapped.write(variable, writtenType));
+  }
+
+  T _wrap<T>(String description, T callback(),
+      {bool isQuery: false, bool isPure}) {
+    isPure ??= isQuery;
+    print(description);
+    T result;
+    try {
+      result = callback();
+    } catch (e, st) {
+      print('  => EXCEPTION $e');
+      print('    ' + st.toString().replaceAll('\n', '\n    '));
+      _exceptionOccurred = true;
+      rethrow;
+    }
+    if (!isPure) {
+      _wrapped._dumpState();
+    }
+    if (isQuery) {
+      print('  => $result');
+    }
+    return result;
+  }
+}
+
+/// An instance of the [FlowModel] class represents the information gathered by
+/// flow analysis at a single point in the control flow of the function or
+/// method being analyzed.
+///
+/// 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> {
+  /// Indicates whether this point in the control flow is reachable.
+  final bool reachable;
+
+  /// For each variable being tracked by flow analysis, the variable's model.
+  ///
+  /// Flow analysis has no awareness of scope, so variables that are out of
+  /// scope are retained in the map until such time as their declaration no
+  /// longer dominates the control flow.  So, for example, if a variable is
+  /// declared inside the `then` branch of an `if` statement, and the `else`
+  /// branch of the `if` statement ends in a `return` statement, then the
+  /// variable remains in the map after the `if` statement ends, even though the
+  /// variable is not in scope anymore.  This should not have any effect on
+  /// analysis results for error-free code, because it is an error to refer to a
+  /// variable that is no longer in scope.
+  final Map<Variable, VariableModel<Type> /*!*/ > variableInfo;
+
+  /// Variable model for variables that have never been seen before.
+  final VariableModel<Type> _freshVariableInfo;
+
+  /// Creates a state object with the given [reachable] status.  All variables
+  /// are assumed to be unpromoted and already assigned, so joining another
+  /// state with this one will have no effect on it.
+  FlowModel(bool reachable)
+      : this._(
+          reachable,
+          const {},
+        );
+
+  FlowModel._(this.reachable, this.variableInfo)
+      : _freshVariableInfo = new VariableModel.fresh() {
+    assert(() {
+      for (VariableModel<Type> value in variableInfo.values) {
+        assert(value != null);
+      }
+      return true;
+    }());
+  }
+
+  /// Gets the info for the given [variable], creating it if it doesn't exist.
+  VariableModel<Type> infoFor(Variable variable) =>
+      variableInfo[variable] ?? _freshVariableInfo;
+
+  /// Updates the state to indicate that the given [variable] was initialized.
+  /// The variable is marked as definitely assigned, and any previous type
+  /// promotion is removed.
+  FlowModel<Variable, Type> initialize(Variable variable) {
+    VariableModel<Type> infoForVar = infoFor(variable);
+    VariableModel<Type> newInfoForVar = infoForVar.initialize();
+    if (identical(newInfoForVar, infoForVar)) return this;
+    return _updateVariableInfo(variable, newInfoForVar);
+  }
+
+  /// Updates the state to indicate that the given [writtenVariables] are no
+  /// longer promoted; they are presumed to have their declared types.
+  ///
+  /// This is used at the top of loops to conservatively cancel the promotion of
+  /// variables that are modified within the loop, so that we correctly analyze
+  /// code like the following:
+  ///
+  ///     if (x is int) {
+  ///       x.isEven; // OK, promoted to int
+  ///       while (true) {
+  ///         x.isEven; // ERROR: promotion lost
+  ///         x = 'foo';
+  ///       }
+  ///     }
+  ///
+  /// Note that a more accurate analysis would be to iterate to a fixed point,
+  /// and only remove promotions if it can be shown that they aren't restored
+  /// later in the loop body.  If we switch to a fixed point analysis, we should
+  /// be able to remove this method.
+  FlowModel<Variable, Type> removePromotedAll(
+      Iterable<Variable> writtenVariables,
+      Iterable<Variable> capturedVariables) {
+    Map<Variable, VariableModel<Type>> newVariableInfo;
+    for (Variable variable in writtenVariables) {
+      VariableModel<Type> info = infoFor(variable);
+      if (info.promotionChain != null) {
+        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
+            variableInfo))[variable] = info.discardPromotions();
+      }
+    }
+    for (Variable variable in capturedVariables) {
+      VariableModel<Type> info = variableInfo[variable];
+      if (info == null) {
+        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
+                variableInfo))[variable] =
+            new VariableModel<Type>(null, const [], false, true);
+      } else if (!info.writeCaptured) {
+        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
+            variableInfo))[variable] = info.writeCapture();
+      }
+    }
+    if (newVariableInfo == null) return this;
+    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
+  }
+
+  /// Updates the state to reflect a control path that is known to have
+  /// previously passed through some [other] state.
+  ///
+  /// Approximately, this method forms the union of the definite assignments and
+  /// promotions in `this` state and the [other] state.  More precisely:
+  ///
+  /// The control flow path is considered reachable if both this state and the
+  /// other state are reachable.  Variables are considered definitely assigned
+  /// if they were definitely assigned in either this state or the other state.
+  /// Variable type promotions are taken from this state, unless the promotion
+  /// in the other state is more specific, and the variable is "safe".  A
+  /// variable is considered safe if there is no chance that it was assigned
+  /// more recently than the "other" state.
+  ///
+  /// This is used after a `try/finally` statement to combine the promotions and
+  /// definite assignments that occurred in the `try` and `finally` blocks
+  /// (where `this` is the state from the `finally` block and `other` is the
+  /// state from the `try` block).  Variables that are assigned in the `finally`
+  /// block are considered "unsafe" because the assignment might have cancelled
+  /// the effect of any promotion that occurred inside the `try` block.
+  FlowModel<Variable, Type> restrict(
+      TypeOperations<Variable, Type> typeOperations,
+      FlowModel<Variable, Type> other,
+      Set<Variable> unsafe) {
+    bool newReachable = reachable && other.reachable;
+
+    Map<Variable, VariableModel<Type>> newVariableInfo =
+        <Variable, VariableModel<Type>>{};
+    bool variableInfoMatchesThis = true;
+    bool variableInfoMatchesOther = true;
+    for (MapEntry<Variable, VariableModel<Type>> entry
+        in variableInfo.entries) {
+      Variable variable = entry.key;
+      VariableModel<Type> thisModel = entry.value;
+      VariableModel<Type> otherModel = other.infoFor(variable);
+      VariableModel<Type> restricted = thisModel.restrict(
+          typeOperations, otherModel, unsafe.contains(variable));
+      if (!identical(restricted, _freshVariableInfo)) {
+        newVariableInfo[variable] = restricted;
+      }
+      if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
+      if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
+    }
+    for (MapEntry<Variable, VariableModel<Type>> entry
+        in other.variableInfo.entries) {
+      Variable variable = entry.key;
+      if (variableInfo.containsKey(variable)) continue;
+      VariableModel<Type> thisModel = _freshVariableInfo;
+      VariableModel<Type> otherModel = entry.value;
+      VariableModel<Type> restricted = thisModel.restrict(
+          typeOperations, otherModel, unsafe.contains(variable));
+      if (!identical(restricted, _freshVariableInfo)) {
+        newVariableInfo[variable] = restricted;
+      }
+      if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
+      if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
+    }
+    assert(variableInfoMatchesThis ==
+        _variableInfosEqual(newVariableInfo, variableInfo));
+    assert(variableInfoMatchesOther ==
+        _variableInfosEqual(newVariableInfo, other.variableInfo));
+    if (variableInfoMatchesThis) {
+      newVariableInfo = variableInfo;
+    } else if (variableInfoMatchesOther) {
+      newVariableInfo = other.variableInfo;
+    }
+
+    return _identicalOrNew(this, other, newReachable, newVariableInfo);
+  }
+
+  /// Updates the state to indicate whether the control flow path is
+  /// [reachable].
+  FlowModel<Variable, Type> setReachable(bool reachable) {
+    if (this.reachable == reachable) return this;
+
+    return new FlowModel<Variable, Type>._(reachable, variableInfo);
+  }
+
+  @override
+  String toString() => '($reachable, $variableInfo)';
+
+  /// Returns an [ExpressionInfo] indicating the result of checking whether the
+  /// given [variable] 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<Type> info = infoFor(variable);
+    if (info.writeCaptured) {
+      return new ExpressionInfo<Variable, Type>(this, this, this);
+    }
+    Type previousType = info.promotionChain?.last;
+    previousType ??= typeOperations.variableType(variable);
+    Type type = typeOperations.promoteToNonNull(previousType);
+    if (typeOperations.isSameType(type, previousType)) {
+      return new ExpressionInfo<Variable, Type>(this, this, this);
+    }
+    assert(typeOperations.isSubtypeOf(type, previousType));
+    return _finishTypeTest(typeOperations, variable, info, type);
+  }
+
+  /// Returns an [ExpressionInfo] indicating the result of checking whether the
+  /// given [variable] satisfies the given [type], e.g. as a consequence of an
+  /// `is` expression as the condition of an `if` statement.
+  ///
+  /// Note that the state is only changed if [type] is a subtype of the
+  /// variable's previous (possibly promoted) type.
+  ///
+  /// TODO(paulberry): if the type is non-nullable, should this method mark the
+  /// variable as definitely assigned?  Does it matter?
+  ExpressionInfo<Variable, Type> tryPromote(
+      TypeOperations<Variable, Type> typeOperations,
+      Variable variable,
+      Type type) {
+    VariableModel<Type> info = infoFor(variable);
+    if (info.writeCaptured) {
+      return new ExpressionInfo<Variable, Type>(this, this, this);
+    }
+    Type previousType = info.promotionChain?.last;
+    previousType ??= typeOperations.variableType(variable);
+
+    Type newType = typeOperations.tryPromoteToType(type, previousType);
+    if (newType == null || typeOperations.isSameType(newType, previousType)) {
+      return new ExpressionInfo<Variable, Type>(this, this, this);
+    }
+    assert(typeOperations.isSubtypeOf(newType, previousType));
+    return _finishTypeTest(typeOperations, variable, info, newType);
+  }
+
+  /// 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,
+      TypeOperations<Variable, Type> typeOperations) {
+    VariableModel<Type> infoForVar = infoFor(variable);
+    VariableModel<Type> newInfoForVar =
+        infoForVar.write(writtenType, typeOperations);
+    if (identical(newInfoForVar, infoForVar)) return this;
+    return _updateVariableInfo(variable, newInfoForVar);
+  }
+
+  /// Common algorithm for [tryMarkNonNullable] and [tryPromote].  Builds an
+  /// [ExpressionInfo] object describing the effect of trying to promote
+  /// [variable] to [testedType], under the following preconditions:
+  /// - [info] should be the result of calling `infoFor(variable)`
+  /// - [testedType] should be a subtype of the currently-promoted type (i.e.
+  ///   no redundant or side-promotions)
+  /// - The variable should not be write-captured.
+  ExpressionInfo<Variable, Type> _finishTypeTest(
+      TypeOperations<Variable, Type> typeOperations,
+      Variable variable,
+      VariableModel<Type> info,
+      Type testedType) {
+    List<Type> newPromotionChain =
+        VariableModel._addToPromotionChain(info.promotionChain, testedType);
+    List<Type> newTypesOfInterest = VariableModel._addTypeToUniqueList(
+        info.typesOfInterest, testedType, typeOperations);
+    FlowModel<Variable, Type> modelIfFailed =
+        identical(newTypesOfInterest, info.typesOfInterest)
+            ? this
+            : _updateVariableInfo(
+                variable,
+                new VariableModel<Type>(info.promotionChain, newTypesOfInterest,
+                    info.assigned, info.writeCaptured));
+    FlowModel<Variable, Type> modelIfSuccessful =
+        identical(newPromotionChain, info.promotionChain) &&
+                identical(newTypesOfInterest, info.typesOfInterest)
+            ? this
+            : _updateVariableInfo(
+                variable,
+                new VariableModel<Type>(newPromotionChain, newTypesOfInterest,
+                    info.assigned, info.writeCaptured));
+    return new ExpressionInfo<Variable, Type>(
+        this, modelIfSuccessful, modelIfFailed);
+  }
+
+  /// Returns a new [FlowModel] where the information for [variable] is replaced
+  /// with [model].
+  FlowModel<Variable, Type> _updateVariableInfo(
+      Variable variable, VariableModel<Type> model) {
+    Map<Variable, VariableModel<Type>> newVariableInfo =
+        new Map<Variable, VariableModel<Type>>.from(variableInfo);
+    newVariableInfo[variable] = model;
+    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
+  }
+
+  /// Forms a new state to reflect a control flow path that might have come from
+  /// either `this` or the [other] state.
+  ///
+  /// The control flow path is considered reachable if either of the input
+  /// states is reachable.  Variables are considered definitely assigned if they
+  /// were definitely assigned in both of the input states.  Variable promotions
+  /// 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>(
+    TypeOperations<Variable, Type> typeOperations,
+    FlowModel<Variable, Type> first,
+    FlowModel<Variable, Type> second,
+  ) {
+    if (first == null) return second;
+    if (second == null) return first;
+
+    if (first.reachable && !second.reachable) return first;
+    if (!first.reachable && second.reachable) return second;
+
+    bool newReachable = first.reachable || second.reachable;
+    Map<Variable, VariableModel<Type>> newVariableInfo =
+        FlowModel.joinVariableInfo(
+            typeOperations, first.variableInfo, second.variableInfo);
+
+    return FlowModel._identicalOrNew(
+        first, second, newReachable, newVariableInfo);
+  }
+
+  /// Joins two "variable info" maps.  See [join] for details.
+  @visibleForTesting
+  static Map<Variable, VariableModel<Type>> joinVariableInfo<Variable, Type>(
+    TypeOperations<Variable, Type> typeOperations,
+    Map<Variable, VariableModel<Type>> first,
+    Map<Variable, VariableModel<Type>> second,
+  ) {
+    if (identical(first, second)) return first;
+    if (first.isEmpty || second.isEmpty) return const {};
+
+    Map<Variable, VariableModel<Type>> result =
+        <Variable, VariableModel<Type>>{};
+    bool alwaysFirst = true;
+    bool alwaysSecond = true;
+    for (MapEntry<Variable, VariableModel<Type>> entry in first.entries) {
+      Variable variable = entry.key;
+      VariableModel<Type> secondModel = second[variable];
+      if (secondModel == null) {
+        alwaysFirst = false;
+      } else {
+        VariableModel<Type> joined =
+            VariableModel.join<Type>(typeOperations, entry.value, secondModel);
+        result[variable] = joined;
+        if (!identical(joined, entry.value)) alwaysFirst = false;
+        if (!identical(joined, secondModel)) alwaysSecond = false;
+      }
+    }
+
+    if (alwaysFirst) return first;
+    if (alwaysSecond && result.length == second.length) return second;
+    if (result.isEmpty) return const {};
+    return result;
+  }
+
+  /// 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,
+      bool newReachable,
+      Map<Variable, VariableModel<Type>> newVariableInfo) {
+    if (first.reachable == newReachable &&
+        identical(first.variableInfo, newVariableInfo)) {
+      return first;
+    }
+    if (second.reachable == newReachable &&
+        identical(second.variableInfo, newVariableInfo)) {
+      return second;
+    }
+
+    return new FlowModel<Variable, Type>._(newReachable, newVariableInfo);
+  }
+
+  /// Determines whether the given "variableInfo" maps are equivalent.
+  ///
+  /// The equivalence check is shallow; if two variables' models are not
+  /// identical, we return `false`.
+  static bool _variableInfosEqual<Variable, Type>(
+      Map<Variable, VariableModel<Type>> p1,
+      Map<Variable, VariableModel<Type>> p2) {
+    if (p1.length != p2.length) return false;
+    if (!p1.keys.toSet().containsAll(p2.keys)) return false;
+    for (MapEntry<Variable, VariableModel<Type>> entry in p1.entries) {
+      VariableModel<Type> p1Value = entry.value;
+      VariableModel<Type> p2Value = p2[entry.key];
+      if (!identical(p1Value, p2Value)) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
+
+/// Operations on types, abstracted from concrete type interfaces.
+abstract class TypeOperations<Variable, Type> {
+  /// Returns `true` if [type1] and [type2] are the same type.
+  bool isSameType(Type type1, Type type2);
+
+  /// Return `true` if the [leftType] is a subtype of the [rightType].
+  bool isSubtypeOf(Type leftType, Type rightType);
+
+  /// Returns the non-null promoted version of [type].
+  ///
+  /// Note that some types don't have a non-nullable version (e.g.
+  /// `FutureOr<int?>`), so [type] may be returned even if it is nullable.
+  Type /*!*/ promoteToNonNull(Type type);
+
+  /// 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);
+
+  /// Return the static type of the given [variable].
+  Type variableType(Variable variable);
+}
+
+/// An instance of the [VariableModel] class represents the information gathered
+/// by flow analysis for a single variable at a single point in the control flow
+/// of the function or method being analyzed.
+///
+/// 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<Type> {
+  /// 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> promotionChain;
+
+  /// List of types that the variable has been tested against in all code paths
+  /// leading to the given point in the source code.
+  final List<Type> typesOfInterest;
+
+  /// Indicates whether the variable has definitely been assigned.
+  final bool assigned;
+
+  /// Indicates whether the variable has been write captured.
+  final bool writeCaptured;
+
+  VariableModel(this.promotionChain, this.typesOfInterest, this.assigned,
+      this.writeCaptured) {
+    assert(promotionChain == null || promotionChain.isNotEmpty);
+    assert(!writeCaptured || promotionChain == null,
+        "Write-captured variables can't be promoted");
+    assert(typesOfInterest != null);
+  }
+
+  /// Creates a [VariableModel] representing a variable that's never been seen
+  /// before.
+  VariableModel.fresh()
+      : promotionChain = null,
+        typesOfInterest = const [],
+        assigned = false,
+        writeCaptured = false;
+
+  /// Returns a new [VariableModel] in which any promotions present have been
+  /// dropped.
+  VariableModel<Type> discardPromotions() {
+    assert(promotionChain != null, 'No promotions to discard');
+    return new VariableModel<Type>(
+        null, typesOfInterest, assigned, writeCaptured);
+  }
+
+  /// Returns a new [VariableModel] reflecting the fact that the variable was
+  /// just initialized.
+  VariableModel<Type> initialize() {
+    if (promotionChain == null && typesOfInterest.isEmpty && assigned) {
+      return this;
+    }
+    return new VariableModel<Type>(null, const [], true, writeCaptured);
+  }
+
+  /// Returns an updated model reflect a control path that is known to have
+  /// previously passed through some [other] state.  See [FlowModel.restrict]
+  /// for details.
+  VariableModel<Type> restrict(TypeOperations<Object, Type> typeOperations,
+      VariableModel<Type> otherModel, bool unsafe) {
+    List<Type> thisPromotionChain = promotionChain;
+    List<Type> otherPromotionChain = otherModel.promotionChain;
+    bool newAssigned = assigned || otherModel.assigned;
+    bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
+    List<Type> newPromotionChain;
+    if (unsafe) {
+      // There was an assignment to the variable in the "this" path, so none of
+      // the promotions from the "other" path can be used.
+      newPromotionChain = thisPromotionChain;
+    } else if (otherPromotionChain == null) {
+      // The other promotion chain contributes nothing so we just use this
+      // promotion chain directly.
+      newPromotionChain = thisPromotionChain;
+    } else if (thisPromotionChain == null) {
+      // This promotion chain contributes nothing so we just use the other
+      // promotion chain directly.
+      newPromotionChain = otherPromotionChain;
+    } else {
+      // Start with otherPromotionChain and apply each of the promotions in
+      // thisPromotionChain (discarding any that don't follow the ordering
+      // invariant)
+      newPromotionChain = otherPromotionChain;
+      Type otherPromotedType = otherPromotionChain.last;
+      for (int i = 0; i < thisPromotionChain.length; i++) {
+        Type nextType = thisPromotionChain[i];
+        if (typeOperations.isSubtypeOf(nextType, otherPromotedType) &&
+            !typeOperations.isSameType(nextType, otherPromotedType)) {
+          newPromotionChain = otherPromotionChain.toList()
+            ..addAll(thisPromotionChain.skip(i));
+          break;
+        }
+      }
+    }
+    return _identicalOrNew(this, otherModel, newPromotionChain, typesOfInterest,
+        newAssigned, newWriteCaptured);
+  }
+
+  @override
+  String toString() {
+    List<String> parts = [];
+    if (promotionChain != null) {
+      parts.add('promotionChain: $promotionChain');
+    }
+    if (typesOfInterest.isNotEmpty) {
+      parts.add('typesOfInterest: $typesOfInterest');
+    }
+    if (assigned) {
+      parts.add('assigned: true');
+    }
+    if (writeCaptured) {
+      parts.add('writeCaptured: true');
+    }
+    return 'VariableModel(${parts.join(', ')})';
+  }
+
+  /// Returns a new [VariableModel] reflecting the fact that the variable was
+  /// just written to.
+  VariableModel<Type> write(
+      Type writtenType, TypeOperations<Object, Type> typeOperations) {
+    List<Type> newPromotionChain;
+    if (promotionChain == null) {
+      newPromotionChain = null;
+    } else if (typeOperations.isSubtypeOf(writtenType, promotionChain.last)) {
+      newPromotionChain = promotionChain;
+    } else {
+      int numChainElementsToKeep = promotionChain.length - 1;
+      while (true) {
+        if (numChainElementsToKeep == 0) {
+          newPromotionChain = null;
+          break;
+        } else if (typeOperations.isSubtypeOf(
+            writtenType, promotionChain[numChainElementsToKeep - 1])) {
+          newPromotionChain = promotionChain.sublist(0, numChainElementsToKeep);
+          break;
+        } else {
+          numChainElementsToKeep--;
+        }
+      }
+    }
+    newPromotionChain = _tryPromoteToTypeOfInterest(
+        typeOperations, newPromotionChain, writtenType);
+    if (identical(promotionChain, newPromotionChain) && assigned) return this;
+    List<Type> newTypesOfInterest;
+    if (newPromotionChain == null && promotionChain != null) {
+      newTypesOfInterest = const [];
+    } else {
+      newTypesOfInterest = typesOfInterest;
+    }
+    return new VariableModel<Type>(
+        newPromotionChain, newTypesOfInterest, true, writeCaptured);
+  }
+
+  /// Returns a new [VariableModel] reflecting the fact that the variable has
+  /// been write-captured.
+  VariableModel<Type> writeCapture() {
+    return new VariableModel<Type>(null, const [], assigned, true);
+  }
+
+  /// Determines whether a variable with the given [promotionChain] should be
+  /// promoted to [writtenType] based on types of interest.  If it should,
+  /// returns an updated promotion chain; otherwise returns [promotionChain]
+  /// unchanged.
+  ///
+  /// Note that since promotions chains are considered immutable, if promotion
+  /// is required, a new promotion chain will be created and returned.
+  List<Type> _tryPromoteToTypeOfInterest(
+      TypeOperations<Object, Type> typeOperations,
+      List<Type> promotionChain,
+      Type writtenType) {
+    // 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 = promotionChain?.last;
+    List<Type> candidates = null;
+    for (int i = 0; i < typesOfInterest.length; i++) {
+      Type type = typesOfInterest[i];
+      if (!typeOperations.isSubtypeOf(writtenType, type)) {
+        // Can't promote to this type; the type written is not a subtype of
+        // it.
+      } else if (currentlyPromotedType != null &&
+          !typeOperations.isSubtypeOf(type, currentlyPromotedType)) {
+        // Can't promote to this type; it's less specific than the currently
+        // promoted type.
+      } else if (currentlyPromotedType != null &&
+          typeOperations.isSameType(type, currentlyPromotedType)) {
+        // Can't promote to this type; it's the same as the currently
+        // promoted type.
+      } else if (typeOperations.isSameType(type, writtenType)) {
+        // This is precisely the type we want to promote to; take it.
+        return _addToPromotionChain(promotionChain, writtenType);
+      } else {
+        (candidates ??= []).add(type);
+      }
+    }
+    if (candidates != null) {
+      // Figure out if we have a unique promotion candidate that's a subtype
+      // of all the others.
+      Type promoted;
+      outer:
+      for (int i = 0; i < candidates.length; i++) {
+        for (int j = 0; j < candidates.length; j++) {
+          if (j == i) continue;
+          if (!typeOperations.isSubtypeOf(candidates[i], candidates[j])) {
+            // Not a subtype of all the others.
+            continue outer;
+          }
+        }
+        if (promoted != null) {
+          // Not unique.  Do not promote.
+          return promotionChain;
+        } else {
+          promoted = candidates[i];
+        }
+      }
+      if (promoted != null) {
+        return _addToPromotionChain(promotionChain, promoted);
+      }
+    }
+    // No suitable promotion found.
+    return promotionChain;
+  }
+
+  /// Joins two variable models.  See [FlowModel.join] for details.
+  static VariableModel<Type> join<Type>(
+      TypeOperations<Object, Type> typeOperations,
+      VariableModel<Type> first,
+      VariableModel<Type> second) {
+    List<Type> newPromotionChain = joinPromotionChains(
+        first.promotionChain, second.promotionChain, typeOperations);
+    bool newAssigned = first.assigned && second.assigned;
+    bool newWriteCaptured = first.writeCaptured || second.writeCaptured;
+    List<Type> newTypesOfInterest = newWriteCaptured
+        ? const []
+        : joinTypesOfInterest(
+            first.typesOfInterest, second.typesOfInterest, typeOperations);
+    return _identicalOrNew(first, second, newPromotionChain, newTypesOfInterest,
+        newAssigned, newWriteCaptured);
+  }
+
+  /// Performs the portion of the "join" algorithm that applies to promotion
+  /// chains.  Briefly, we keep the longest initial subchain that both input
+  /// chains share, and discard all other promotions.
+  static List<Type> joinPromotionChains<Type>(List<Type> chain1,
+      List<Type> chain2, TypeOperations<Object, Type> typeOperations) {
+    if (chain1 == null) return chain1;
+    if (chain2 == null) return chain2;
+    int numCommonElements = 0;
+    while (numCommonElements < chain1.length &&
+        numCommonElements < chain2.length &&
+        typeOperations.isSameType(
+            chain1[numCommonElements], chain2[numCommonElements])) {
+      ++numCommonElements;
+    }
+    if (numCommonElements == chain1.length) return chain1;
+    if (numCommonElements == chain2.length) return chain2;
+    // For now we just discard any promotions after the first non-matching
+    // promotion.  TODO(paulberry): consider doing something smarter.
+    return numCommonElements == 0 ? null : chain1.sublist(0, numCommonElements);
+  }
+
+  /// Performs the portion of the "join" algorithm that applies to promotion
+  /// chains.  Essentially this performs a set union, with the following
+  /// caveats:
+  /// - The "sets" are represented as lists (since they are expected to be very
+  ///   small in real-world cases)
+  /// - The sense of equality for the union operation is determined by
+  ///   [TypeOperations.isSameType].
+  /// - The types of interests lists are considered immutable.
+  static List<Type> joinTypesOfInterest<Type>(List<Type> types1,
+      List<Type> types2, TypeOperations<Object, Type> typeOperations) {
+    // Ensure that types1 is the shorter list.
+    if (types1.length > types2.length) {
+      List<Type> tmp = types1;
+      types1 = types2;
+      types2 = tmp;
+    }
+    // Determine the length of the common prefix the two lists share.
+    int shared = 0;
+    for (; shared < types1.length; shared++) {
+      if (!typeOperations.isSameType(types1[shared], types2[shared])) break;
+    }
+    // Use types2 as a starting point and add any entries from types1 that are
+    // not present in it.
+    for (int i = shared; i < types1.length; i++) {
+      Type typeToAdd = types1[i];
+      if (_typeListContains(typeOperations, types2, typeToAdd)) continue;
+      List<Type> result = types2.toList()..add(typeToAdd);
+      for (i++; i < types1.length; i++) {
+        typeToAdd = types1[i];
+        if (_typeListContains(typeOperations, types2, typeToAdd)) continue;
+        result.add(typeToAdd);
+      }
+      return result;
+    }
+    // No types needed to be added.
+    return types2;
+  }
+
+  static List<Type> _addToPromotionChain<Type>(
+          List<Type> promotionChain, Type promoted) =>
+      promotionChain == null
+          ? [promoted]
+          : (promotionChain.toList()..add(promoted));
+
+  static List<Type> _addTypeToUniqueList<Type>(List<Type> types, Type newType,
+      TypeOperations<Object, 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<Type> _identicalOrNew<Type>(
+      VariableModel<Type> first,
+      VariableModel<Type> second,
+      List<Type> newPromotionChain,
+      List<Type> newTypesOfInterest,
+      bool newAssigned,
+      bool newWriteCaptured) {
+    if (identical(first.promotionChain, newPromotionChain) &&
+        identical(first.typesOfInterest, newTypesOfInterest) &&
+        first.assigned == newAssigned &&
+        first.writeCaptured == newWriteCaptured) {
+      return first;
+    } else if (identical(second.promotionChain, newPromotionChain) &&
+        identical(second.typesOfInterest, newTypesOfInterest) &&
+        second.assigned == newAssigned &&
+        second.writeCaptured == newWriteCaptured) {
+      return second;
+    } else {
+      return new VariableModel<Type>(
+          newPromotionChain, newTypesOfInterest, newAssigned, newWriteCaptured);
+    }
+  }
+
+  static bool _typeListContains<Type>(
+      TypeOperations<Object, Type> typeOperations,
+      List<Type> list,
+      Type searchType) {
+    for (Type type in list) {
+      if (typeOperations.isSameType(type, searchType)) return true;
+    }
+    return false;
+  }
+}
+
+/// [_FlowContext] representing an assert statement or assert initializer.
+class _AssertContext<Variable, Type> extends _SimpleContext<Variable, Type> {
+  /// Flow models associated with the condition being asserted.
+  ExpressionInfo<Variable, Type> _conditionInfo;
+
+  _AssertContext(FlowModel<Variable, Type> previous) : super(previous);
+
+  @override
+  String toString() =>
+      '_AssertContext(previous: $_previous, conditionInfo: $_conditionInfo)';
+}
+
+/// [_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 {
+  /// Flow models associated with the condition being branched on.
+  final ExpressionInfo<Variable, Type> _conditionInfo;
+
+  _BranchContext(this._conditionInfo);
+
+  @override
+  String toString() => '_BranchContext(conditionInfo: $_conditionInfo)';
+}
+
+/// [_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 {
+  /// Accumulated flow model for all `break` statements seen so far, or `null`
+  /// if no `break` statements have been seen yet.
+  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;
+
+  @override
+  String toString() => '_BranchTargetContext(breakModel: $_breakModel, '
+      'continueModel: $_continueModel)';
+}
+
+/// [_FlowContext] representing a conditional expression.
+class _ConditionalContext<Variable, Type>
+    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;
+
+  _ConditionalContext(ExpressionInfo<Variable, Type> conditionInfo)
+      : super(conditionInfo);
+
+  @override
+  String toString() => '_ConditionalContext(conditionInfo: $_conditionInfo, '
+      'thenInfo: $_thenInfo)';
+}
+
+class _FlowAnalysisImpl<Node, Statement extends Node, Expression, Variable,
+    Type> implements FlowAnalysis<Node, Statement, Expression, Variable, Type> {
+  /// The [TypeOperations], used to access types, and check subtyping.
+  final TypeOperations<Variable, Type> typeOperations;
+
+  /// Stack of [_FlowContext] objects representing the statements and
+  /// expressions that are currently being visited.
+  final List<_FlowContext> _stack = [];
+
+  /// The mapping from [Statement]s that can act as targets for `break` and
+  /// `continue` statements (i.e. loops and switch statements) to the to their
+  /// context information.
+  final Map<Statement, _BranchTargetContext<Variable, Type>>
+      _statementToContext = {};
+
+  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;
+
+  /// If [_expressionWithInfo] is not `null`, the [ExpressionInfo] object
+  /// corresponding to it.  Otherwise `null`.
+  ExpressionInfo<Variable, Type> _expressionInfo;
+
+  int _functionNestingLevel = 0;
+
+  final AssignedVariables<Node, Variable> _assignedVariables;
+
+  _FlowAnalysisImpl(this.typeOperations, this._assignedVariables) {
+    _current = new FlowModel<Variable, Type>(true);
+  }
+
+  @override
+  bool get isReachable => _current.reachable;
+
+  @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.tryPromote(typeOperations, variable, type).ifTrue;
+  }
+
+  @override
+  void assert_afterCondition(Expression condition) {
+    _AssertContext<Variable, Type> context =
+        _stack.last as _AssertContext<Variable, Type>;
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
+    context._conditionInfo = conditionInfo;
+    _current = conditionInfo.ifFalse;
+  }
+
+  @override
+  void assert_begin() {
+    _stack.add(new _AssertContext<Variable, Type>(_current));
+  }
+
+  @override
+  void assert_end() {
+    _AssertContext<Variable, Type> context =
+        _stack.removeLast() as _AssertContext<Variable, Type>;
+    _current = _join(context._previous, context._conditionInfo.ifTrue);
+  }
+
+  @override
+  void booleanLiteral(Expression expression, bool value) {
+    FlowModel<Variable, Type> unreachable = _current.setReachable(false);
+    _storeExpressionInfo(
+        expression,
+        value
+            ? new ExpressionInfo(_current, _current, unreachable)
+            : new ExpressionInfo(_current, unreachable, _current));
+  }
+
+  @override
+  void conditional_elseBegin(Expression thenExpression) {
+    _ConditionalContext<Variable, Type> context =
+        _stack.last as _ConditionalContext<Variable, Type>;
+    context._thenInfo = _expressionEnd(thenExpression);
+    _current = context._conditionInfo.ifFalse;
+  }
+
+  @override
+  void conditional_end(
+      Expression conditionalExpression, Expression elseExpression) {
+    _ConditionalContext<Variable, Type> context =
+        _stack.removeLast() as _ConditionalContext<Variable, Type>;
+    ExpressionInfo<Variable, Type> thenInfo = context._thenInfo;
+    ExpressionInfo<Variable, Type> elseInfo = _expressionEnd(elseExpression);
+    _storeExpressionInfo(
+        conditionalExpression,
+        new ExpressionInfo(
+            _join(thenInfo.after, elseInfo.after),
+            _join(thenInfo.ifTrue, elseInfo.ifTrue),
+            _join(thenInfo.ifFalse, elseInfo.ifFalse)));
+  }
+
+  @override
+  void conditional_thenBegin(Expression condition) {
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
+    _stack.add(new _ConditionalContext(conditionInfo));
+    _current = conditionInfo.ifTrue;
+  }
+
+  @override
+  void doStatement_bodyBegin(Statement doStatement) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(doStatement);
+    _BranchTargetContext<Variable, Type> context =
+        new _BranchTargetContext<Variable, Type>();
+    _stack.add(context);
+    _current = _current.removePromotedAll(info._written, info._captured);
+    _statementToContext[doStatement] = context;
+  }
+
+  @override
+  void doStatement_conditionBegin() {
+    _BranchTargetContext<Variable, Type> context =
+        _stack.last as _BranchTargetContext<Variable, Type>;
+    _current = _join(_current, context._continueModel);
+  }
+
+  @override
+  void doStatement_end(Expression condition) {
+    _BranchTargetContext<Variable, Type> context =
+        _stack.removeLast() as _BranchTargetContext<Variable, Type>;
+    _current = _join(_expressionEnd(condition).ifFalse, context._breakModel);
+  }
+
+  @override
+  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+      {bool notEqual = false}) {
+    _BranchContext<Variable, Type> context =
+        _stack.removeLast() as _BranchContext<Variable, Type>;
+    ExpressionInfo<Variable, Type> lhsInfo = context._conditionInfo;
+    ExpressionInfo<Variable, Type> rhsInfo = _getExpressionInfo(rightOperand);
+    Variable variable;
+    if (lhsInfo is _NullInfo<Variable, Type> &&
+        rhsInfo is _VariableReadInfo<Variable, Type>) {
+      variable = rhsInfo._variable;
+    } else if (rhsInfo is _NullInfo<Variable, Type> &&
+        lhsInfo is _VariableReadInfo<Variable, Type>) {
+      variable = lhsInfo._variable;
+    } else {
+      return;
+    }
+    ExpressionInfo<Variable, Type> expressionInfo =
+        _current.tryMarkNonNullable(typeOperations, variable);
+    _storeExpressionInfo(wholeExpression,
+        notEqual ? expressionInfo : ExpressionInfo.invert(expressionInfo));
+  }
+
+  @override
+  void equalityOp_rightBegin(Expression leftOperand) {
+    _stack.add(
+        new _BranchContext<Variable, Type>(_getExpressionInfo(leftOperand)));
+  }
+
+  @override
+  void finish() {
+    assert(_stack.isEmpty);
+  }
+
+  @override
+  void for_bodyBegin(Statement node, Expression condition) {
+    ExpressionInfo<Variable, Type> conditionInfo = condition == null
+        ? new ExpressionInfo(_current, _current, _current.setReachable(false))
+        : _expressionEnd(condition);
+    _WhileContext<Variable, Type> context =
+        new _WhileContext<Variable, Type>(conditionInfo);
+    _stack.add(context);
+    if (node != null) {
+      _statementToContext[node] = context;
+    }
+    _current = conditionInfo.ifTrue;
+  }
+
+  @override
+  void for_conditionBegin(Node node) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    _current = _current.removePromotedAll(info._written, info._captured);
+  }
+
+  @override
+  void for_end() {
+    _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> falseCondition = context._conditionInfo.ifFalse;
+
+    _current = _join(falseCondition, breakState);
+  }
+
+  @override
+  void for_updaterBegin() {
+    _WhileContext<Variable, Type> context =
+        _stack.last as _WhileContext<Variable, Type>;
+    _current = _join(_current, context._continueModel);
+  }
+
+  @override
+  void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    _SimpleStatementContext<Variable, Type> context =
+        new _SimpleStatementContext<Variable, Type>(_current);
+    _stack.add(context);
+    _current = _current.removePromotedAll(info._written, info._captured);
+    if (loopVariable != null) {
+      _current = _current.write(loopVariable, writtenType, typeOperations);
+    }
+  }
+
+  @override
+  void forEach_end() {
+    _SimpleStatementContext<Variable, Type> context =
+        _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
+    _current = _join(_current, context._previous);
+  }
+
+  @override
+  void functionExpression_begin(Node node) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    ++_functionNestingLevel;
+    _current = _current.removePromotedAll(const [], info._written);
+    _stack.add(new _SimpleContext(_current));
+    _current = _current.removePromotedAll(_assignedVariables._anywhere._written,
+        _assignedVariables._anywhere._captured);
+  }
+
+  @override
+  void functionExpression_end() {
+    --_functionNestingLevel;
+    assert(_functionNestingLevel >= 0);
+    _SimpleContext<Variable, Type> context =
+        _stack.removeLast() as _SimpleContext<Variable, Type>;
+    _current = context._previous;
+  }
+
+  @override
+  void handleBreak(Statement target) {
+    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
+    if (context != null) {
+      context._breakModel = _join(context._breakModel, _current);
+    }
+    _current = _current.setReachable(false);
+  }
+
+  @override
+  void handleContinue(Statement target) {
+    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
+    if (context != null) {
+      context._continueModel = _join(context._continueModel, _current);
+    }
+    _current = _current.setReachable(false);
+  }
+
+  @override
+  void handleExit() {
+    _current = _current.setReachable(false);
+  }
+
+  @override
+  void ifNullExpression_end() {
+    _SimpleContext<Variable, Type> context =
+        _stack.removeLast() as _SimpleContext<Variable, Type>;
+    _current = _join(_current, context._previous);
+  }
+
+  @override
+  void ifNullExpression_rightBegin(Expression leftHandSide) {
+    ExpressionInfo<Variable, Type> lhsInfo = _getExpressionInfo(leftHandSide);
+    FlowModel<Variable, Type> promoted;
+    if (lhsInfo is _VariableReadInfo<Variable, Type>) {
+      ExpressionInfo<Variable, Type> promotionInfo =
+          _current.tryMarkNonNullable(typeOperations, lhsInfo._variable);
+      _current = promotionInfo.ifFalse;
+      promoted = promotionInfo.ifTrue;
+    } else {
+      promoted = _current;
+    }
+    _stack.add(new _SimpleContext<Variable, Type>(promoted));
+  }
+
+  @override
+  void ifStatement_elseBegin() {
+    _IfContext<Variable, Type> context =
+        _stack.last as _IfContext<Variable, Type>;
+    context._afterThen = _current;
+    _current = context._conditionInfo.ifFalse;
+  }
+
+  @override
+  void ifStatement_end(bool hasElse) {
+    _IfContext<Variable, Type> context =
+        _stack.removeLast() as _IfContext<Variable, Type>;
+    FlowModel<Variable, Type> afterThen;
+    FlowModel<Variable, Type> afterElse;
+    if (hasElse) {
+      afterThen = context._afterThen;
+      afterElse = _current;
+    } else {
+      afterThen = _current; // no `else`, so `then` is still current
+      afterElse = context._conditionInfo.ifFalse;
+    }
+    _current = _join(afterThen, afterElse);
+  }
+
+  @override
+  void ifStatement_thenBegin(Expression condition) {
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
+    _stack.add(new _IfContext(conditionInfo));
+    _current = conditionInfo.ifTrue;
+  }
+
+  @override
+  void initialize(Variable variable) {
+    _current = _current.initialize(variable);
+  }
+
+  @override
+  bool isAssigned(Variable variable) {
+    return _current.infoFor(variable).assigned;
+  }
+
+  @override
+  void isExpression_end(Expression isExpression, Expression subExpression,
+      bool isNot, Type type) {
+    ExpressionInfo<Variable, Type> subExpressionInfo =
+        _getExpressionInfo(subExpression);
+    Variable variable;
+    if (subExpressionInfo is _VariableReadInfo<Variable, Type>) {
+      variable = subExpressionInfo._variable;
+    } else {
+      return;
+    }
+    ExpressionInfo<Variable, Type> expressionInfo =
+        _current.tryPromote(typeOperations, variable, type);
+    _storeExpressionInfo(isExpression,
+        isNot ? ExpressionInfo.invert(expressionInfo) : expressionInfo);
+  }
+
+  @override
+  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
+      {@required bool isAnd}) {
+    _BranchContext<Variable, Type> context =
+        _stack.removeLast() as _BranchContext<Variable, Type>;
+    ExpressionInfo<Variable, Type> rhsInfo = _expressionEnd(rightOperand);
+
+    FlowModel<Variable, Type> trueResult;
+    FlowModel<Variable, Type> falseResult;
+    if (isAnd) {
+      trueResult = rhsInfo.ifTrue;
+      falseResult = _join(context._conditionInfo.ifFalse, rhsInfo.ifFalse);
+    } else {
+      trueResult = _join(context._conditionInfo.ifTrue, rhsInfo.ifTrue);
+      falseResult = rhsInfo.ifFalse;
+    }
+    _storeExpressionInfo(
+        wholeExpression,
+        new ExpressionInfo(
+            _join(trueResult, falseResult), trueResult, falseResult));
+  }
+
+  @override
+  void logicalBinaryOp_rightBegin(Expression leftOperand,
+      {@required bool isAnd}) {
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(leftOperand);
+    _stack.add(new _BranchContext<Variable, Type>(conditionInfo));
+    _current = isAnd ? conditionInfo.ifTrue : conditionInfo.ifFalse;
+  }
+
+  @override
+  void logicalNot_end(Expression notExpression, Expression operand) {
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(operand);
+    _storeExpressionInfo(notExpression, ExpressionInfo.invert(conditionInfo));
+  }
+
+  @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;
+    }
+  }
+
+  @override
+  void nullAwareAccess_end() {
+    _SimpleContext<Variable, Type> context =
+        _stack.removeLast() as _SimpleContext<Variable, Type>;
+    _current = _join(_current, context._previous);
+  }
+
+  @override
+  void nullAwareAccess_rightBegin(Expression target) {
+    _stack.add(new _SimpleContext<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;
+      }
+    }
+  }
+
+  @override
+  void nullLiteral(Expression expression) {
+    _storeExpressionInfo(expression, new _NullInfo(_current));
+  }
+
+  @override
+  void parenthesizedExpression(
+      Expression outerExpression, Expression innerExpression) {
+    if (identical(_expressionWithInfo, innerExpression)) {
+      _expressionWithInfo = outerExpression;
+    }
+  }
+
+  @override
+  Type promotedType(Variable variable) {
+    return _current.infoFor(variable).promotionChain?.last;
+  }
+
+  @override
+  void switchStatement_beginCase(bool hasLabel, Node node) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    _SimpleStatementContext<Variable, Type> context =
+        _stack.last as _SimpleStatementContext<Variable, Type>;
+    if (hasLabel) {
+      _current =
+          context._previous.removePromotedAll(info._written, info._captured);
+    } else {
+      _current = context._previous;
+    }
+  }
+
+  @override
+  void switchStatement_end(bool hasDefault) {
+    _SimpleStatementContext<Variable, Type> context =
+        _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
+    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.
+    breakState = _join(breakState, _current);
+
+    // And, if there is an implicit fall-through default, join it to any breaks.
+    if (!hasDefault) breakState = _join(breakState, context._previous);
+
+    _current = breakState;
+  }
+
+  @override
+  void switchStatement_expressionEnd(Statement switchStatement) {
+    _SimpleStatementContext<Variable, Type> context =
+        new _SimpleStatementContext<Variable, Type>(_current);
+    _stack.add(context);
+    _statementToContext[switchStatement] = context;
+  }
+
+  @override
+  void tryCatchStatement_bodyBegin() {
+    _stack.add(new _TryContext<Variable, Type>(_current));
+  }
+
+  @override
+  void tryCatchStatement_bodyEnd(Node body) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(body);
+    _TryContext<Variable, Type> context =
+        _stack.last as _TryContext<Variable, Type>;
+    FlowModel<Variable, Type> beforeBody = context._previous;
+    FlowModel<Variable, Type> beforeCatch =
+        beforeBody.removePromotedAll(info._written, info._captured);
+    context._beforeCatch = beforeCatch;
+    context._afterBodyAndCatches = _current;
+  }
+
+  @override
+  void tryCatchStatement_catchBegin(
+      Variable exceptionVariable, Variable stackTraceVariable) {
+    _TryContext<Variable, Type> context =
+        _stack.last as _TryContext<Variable, Type>;
+    _current = context._beforeCatch;
+    if (exceptionVariable != null) {
+      _current = _current.initialize(exceptionVariable);
+    }
+    if (stackTraceVariable != null) {
+      _current = _current.initialize(stackTraceVariable);
+    }
+  }
+
+  @override
+  void tryCatchStatement_catchEnd() {
+    _TryContext<Variable, Type> context =
+        _stack.last as _TryContext<Variable, Type>;
+    context._afterBodyAndCatches =
+        _join(context._afterBodyAndCatches, _current);
+  }
+
+  @override
+  void tryCatchStatement_end() {
+    _TryContext<Variable, Type> context =
+        _stack.removeLast() as _TryContext<Variable, Type>;
+    _current = context._afterBodyAndCatches;
+  }
+
+  @override
+  void tryFinallyStatement_bodyBegin() {
+    _stack.add(new _TryContext<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);
+  }
+
+  @override
+  void tryFinallyStatement_finallyBegin(Node body) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(body);
+    _TryContext<Variable, Type> context =
+        _stack.last as _TryContext<Variable, Type>;
+    context._afterBodyAndCatches = _current;
+    _current = _join(_current,
+        context._previous.removePromotedAll(info._written, info._captured));
+  }
+
+  @override
+  Type variableRead(Expression expression, Variable variable) {
+    _storeExpressionInfo(expression, new _VariableReadInfo(_current, variable));
+    return _current.infoFor(variable).promotionChain?.last;
+  }
+
+  @override
+  void whileStatement_bodyBegin(
+      Statement whileStatement, Expression condition) {
+    ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
+    _WhileContext<Variable, Type> context =
+        new _WhileContext<Variable, Type>(conditionInfo);
+    _stack.add(context);
+    _statementToContext[whileStatement] = context;
+    _current = conditionInfo.ifTrue;
+  }
+
+  @override
+  void whileStatement_conditionBegin(Node node) {
+    AssignedVariablesNodeInfo<Variable> info =
+        _assignedVariables._getInfoForNode(node);
+    _current = _current.removePromotedAll(info._written, info._captured);
+  }
+
+  @override
+  void whileStatement_end() {
+    _WhileContext<Variable, Type> context =
+        _stack.removeLast() as _WhileContext<Variable, Type>;
+    _current = _join(context._conditionInfo.ifFalse, context._breakModel);
+  }
+
+  @override
+  void write(Variable variable, Type writtenType) {
+    assert(
+        _assignedVariables._anywhere._written.contains(variable),
+        "Variable is written to, but was not included in "
+        "_variablesWrittenAnywhere: $variable");
+    _current = _current.write(variable, writtenType, typeOperations);
+  }
+
+  void _dumpState() {
+    print('  current: $_current');
+    print('  expressionWithInfo: $_expressionWithInfo');
+    print('  expressionInfo: $_expressionInfo');
+    print('  stack:');
+    for (_FlowContext stackEntry in _stack.reversed) {
+      print('    $stackEntry');
+    }
+  }
+
+  /// 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 a fresh
+  /// [ExpressionInfo] is created recording the current flow analysis state.
+  ExpressionInfo<Variable, Type> _expressionEnd(Expression expression) =>
+      _getExpressionInfo(expression) ??
+      new ExpressionInfo(_current, _current, _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) {
+    if (identical(expression, _expressionWithInfo)) {
+      ExpressionInfo<Variable, Type> expressionInfo = _expressionInfo;
+      _expressionInfo = null;
+      return expressionInfo;
+    } else {
+      return null;
+    }
+  }
+
+  FlowModel<Variable, Type> _join(
+          FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
+      FlowModel.join(typeOperations, first, second);
+
+  /// Associates [expression], which should be the most recently visited
+  /// expression, with the given [expressionInfo] object, and updates the
+  /// current flow model state to correspond to it.
+  void _storeExpressionInfo(
+      Expression expression, ExpressionInfo<Variable, Type> expressionInfo) {
+    _expressionWithInfo = expression;
+    _expressionInfo = expressionInfo;
+    _current = expressionInfo.after;
+  }
+}
+
+/// Base class for objects representing constructs in the Dart programming
+/// language for which flow analysis information needs to be tracked.
+abstract class _FlowContext {}
+
+/// [_FlowContext] representing an `if` statement.
+class _IfContext<Variable, Type> 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;
+
+  _IfContext(ExpressionInfo<Variable, Type> conditionInfo)
+      : super(conditionInfo);
+
+  @override
+  String toString() =>
+      '_IfContext(conditionInfo: $_conditionInfo, afterThen: $_afterThen)';
+}
+
+/// [ExpressionInfo] representing a `null` literal.
+class _NullInfo<Variable, Type> implements ExpressionInfo<Variable, Type> {
+  @override
+  final FlowModel<Variable, Type> after;
+
+  _NullInfo(this.after);
+
+  @override
+  FlowModel<Variable, Type> get ifFalse => after;
+
+  @override
+  FlowModel<Variable, Type> get ifTrue => after;
+}
+
+/// [_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.
+class _SimpleContext<Variable, Type> 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"
+  /// expression, this is the state after execution of the expression before the
+  /// `??`.
+  final FlowModel<Variable, Type> _previous;
+
+  _SimpleContext(this._previous);
+
+  @override
+  String toString() => '_SimpleContext(previous: $_previous)';
+}
+
+/// [_FlowContext] representing a language construct that can be targeted by
+/// `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>
+    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
+  /// after evaluation of the switch expression.
+  final FlowModel<Variable, Type> _previous;
+
+  _SimpleStatementContext(this._previous);
+
+  @override
+  String toString() => '_SimpleStatementContext(breakModel: $_breakModel, '
+      'continueModel: $_continueModel, previous: $_previous)';
+}
+
+/// [_FlowContext] representing a try statement.
+class _TryContext<Variable, Type> 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;
+
+  /// 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;
+
+  _TryContext(FlowModel<Variable, Type> previous) : super(previous);
+
+  @override
+  String toString() =>
+      '_TryContext(previous: $_previous, beforeCatch: $_beforeCatch, '
+      '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;
+
+  /// 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)';
+}
+
+/// [_FlowContext] representing a `while` loop (or a C-style `for` loop, which
+/// is functionally similar).
+class _WhileContext<Variable, Type>
+    extends _BranchTargetContext<Variable, Type> {
+  /// Flow models associated with the loop condition.
+  final ExpressionInfo<Variable, Type> _conditionInfo;
+
+  _WhileContext(this._conditionInfo);
+
+  @override
+  String toString() => '_WhileContext(breakModel: $_breakModel, '
+      'continueModel: $_continueModel, conditionInfo: $_conditionInfo)';
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
new file mode 100644
index 0000000..0b7cc1c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -0,0 +1,288 @@
+// 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.
+
+library _fe_analyzer_shared.messages.codes;
+
+import 'dart:convert' show JsonEncoder, json;
+
+import 'diagnostic_message.dart' show DiagnosticMessage;
+
+import '../scanner/token.dart' show Token;
+
+import 'severity.dart' show Severity;
+
+import '../util/relativize.dart' show isWindows;
+
+import '../util/relativize.dart' as util show relativizeUri;
+
+part 'codes_generated.dart';
+
+const int noLength = 1;
+
+class Code<T> {
+  final String name;
+
+  /// The unique positive integer associated with this code,
+  /// or `-1` if none. This index is used when translating
+  /// this error to its corresponding Analyzer error.
+  final int index;
+
+  final Template<T> template;
+
+  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;
+
+  String toString() => name;
+}
+
+class Message {
+  final Code<dynamic> code;
+
+  final String message;
+
+  final String tip;
+
+  final Map<String, dynamic> arguments;
+
+  const Message(this.code, {this.message, this.tip, this.arguments});
+
+  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
+    return new LocatedMessage(uri, charOffset, length, this);
+  }
+
+  LocatedMessage withoutLocation() {
+    return new LocatedMessage(null, -1, noLength, this);
+  }
+
+  String toString() {
+    return "Message[$code, $message, $tip, $arguments]";
+  }
+}
+
+class MessageCode extends Code<Null> implements Message {
+  final String message;
+
+  final String tip;
+
+  const MessageCode(String name,
+      {int index,
+      List<String> analyzerCodes,
+      Severity severity: Severity.error,
+      this.message,
+      this.tip})
+      : super(name, null,
+            index: index, analyzerCodes: analyzerCodes, severity: severity);
+
+  Map<String, dynamic> get arguments => const <String, dynamic>{};
+
+  Code<dynamic> get code => this;
+
+  @override
+  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
+    return new LocatedMessage(uri, charOffset, length, this);
+  }
+
+  LocatedMessage withoutLocation() {
+    return new LocatedMessage(null, -1, noLength, this);
+  }
+}
+
+class Template<T> {
+  final String messageTemplate;
+
+  final String tipTemplate;
+
+  final T withArguments;
+
+  const Template({this.messageTemplate, this.tipTemplate, this.withArguments});
+}
+
+class LocatedMessage implements Comparable<LocatedMessage> {
+  final Uri uri;
+
+  final int charOffset;
+
+  final int length;
+
+  final Message messageObject;
+
+  const LocatedMessage(
+      this.uri, this.charOffset, this.length, this.messageObject);
+
+  Code<dynamic> get code => messageObject.code;
+
+  String get message => messageObject.message;
+
+  String get tip => messageObject.tip;
+
+  Map<String, dynamic> get arguments => messageObject.arguments;
+
+  int compareTo(LocatedMessage other) {
+    int result = "${uri}".compareTo("${other.uri}");
+    if (result != 0) return result;
+    result = charOffset.compareTo(other.charOffset);
+    if (result != 0) return result;
+    return message.compareTo(message);
+  }
+
+  FormattedMessage withFormatting(String formatted, int line, int column,
+      Severity severity, List<FormattedMessage> relatedInformation) {
+    return new FormattedMessage(
+        this, formatted, line, column, severity, relatedInformation);
+  }
+}
+
+class FormattedMessage implements DiagnosticMessage {
+  final LocatedMessage locatedMessage;
+
+  final String formatted;
+
+  final int line;
+
+  final int column;
+
+  @override
+  final Severity severity;
+
+  final List<FormattedMessage> relatedInformation;
+
+  const FormattedMessage(this.locatedMessage, this.formatted, this.line,
+      this.column, this.severity, this.relatedInformation);
+
+  Code<dynamic> get code => locatedMessage.code;
+
+  String get message => locatedMessage.message;
+
+  String get tip => locatedMessage.tip;
+
+  Map<String, dynamic> get arguments => locatedMessage.arguments;
+
+  Uri get uri => locatedMessage.uri;
+
+  int get charOffset => locatedMessage.charOffset;
+
+  int get length => locatedMessage.length;
+
+  @override
+  Iterable<String> get ansiFormatted sync* {
+    yield formatted;
+    if (relatedInformation != null) {
+      for (FormattedMessage m in relatedInformation) {
+        yield m.formatted;
+      }
+    }
+  }
+
+  @override
+  Iterable<String> get plainTextFormatted {
+    // TODO(ahe): Implement this correctly.
+    return ansiFormatted;
+  }
+
+  Map<String, Object> toJson() {
+    // This should be kept in sync with package:kernel/problems.md
+    return <String, Object>{
+      "ansiFormatted": ansiFormatted.toList(),
+      "plainTextFormatted": plainTextFormatted.toList(),
+      "severity": severity.index,
+      "uri": uri.toString(),
+    };
+  }
+
+  String toJsonString() {
+    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
+    return encoder.convert(this);
+  }
+}
+
+class DiagnosticMessageFromJson implements DiagnosticMessage {
+  @override
+  final Iterable<String> ansiFormatted;
+
+  @override
+  final Iterable<String> plainTextFormatted;
+
+  @override
+  final Severity severity;
+
+  final Uri uri;
+
+  DiagnosticMessageFromJson(
+      this.ansiFormatted, this.plainTextFormatted, this.severity, this.uri);
+
+  factory DiagnosticMessageFromJson.fromJson(String jsonString) {
+    Map<String, Object> decoded = json.decode(jsonString);
+    List<String> ansiFormatted =
+        new List<String>.from(decoded["ansiFormatted"]);
+    List<String> plainTextFormatted =
+        new List<String>.from(decoded["plainTextFormatted"]);
+    Severity severity = Severity.values[decoded["severity"]];
+    Uri uri = Uri.parse(decoded["uri"]);
+
+    return new DiagnosticMessageFromJson(
+        ansiFormatted, plainTextFormatted, severity, uri);
+  }
+
+  Map<String, Object> toJson() {
+    // This should be kept in sync with package:kernel/problems.md
+    return <String, Object>{
+      "ansiFormatted": ansiFormatted.toList(),
+      "plainTextFormatted": plainTextFormatted.toList(),
+      "severity": severity.index,
+      "uri": uri.toString(),
+    };
+  }
+
+  String toJsonString() {
+    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
+    return encoder.convert(this);
+  }
+}
+
+String relativizeUri(Uri uri) {
+  // We have this method here for two reasons:
+  //
+  // 1. It allows us to implement #uri message argument without using it
+  // (otherwise, we might get an `UNUSED_IMPORT` warning).
+  //
+  // 2. We can change `base` argument here if needed.
+  return uri == null ? null : util.relativizeUri(Uri.base, uri, isWindows);
+}
+
+typedef SummaryTemplate = Message Function(int, int, num, num, num);
+
+String itemizeNames(List<String> names) {
+  StringBuffer buffer = new StringBuffer();
+  for (int i = 0; i < names.length - 1; i++) {
+    buffer.write(" - ");
+    buffer.writeln(names[i]);
+  }
+  buffer.write(" - ");
+  buffer.write(names.last);
+  return "$buffer";
+}
+
+/// Convert the synthetic name of an implicit mixin application class
+/// into a name suitable for user-faced strings.
+///
+/// For example, when compiling "class A extends S with M1, M2", the
+/// two synthetic classes will be named "_A&S&M1" and "_A&S&M1&M2".
+/// This function will return "S with M1" and "S with M1, M2", respectively.
+///
+/// This method is copied from package:kernel/ast.dart.
+// TODO(johnniwinther): Avoid the need for this method.
+String demangleMixinApplicationName(String name) {
+  List<String> nameParts = name.split('&');
+  if (nameParts.length < 2 || name == "&") return name;
+  String demangledName = nameParts[1];
+  for (int i = 2; i < nameParts.length; i++) {
+    demangledName += (i == 2 ? " with " : ", ") + nameParts[i];
+  }
+  return demangledName;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
new file mode 100644
index 0000000..cc75d4f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -0,0 +1,8161 @@
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'pkg/front_end/messages.yaml' and run
+// 'pkg/front_end/tool/fasta generate-messages' to update.
+
+// ignore_for_file: lines_longer_than_80_chars
+
+part of _fe_analyzer_shared.messages.codes;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateAbstractClassInstantiation =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""The class '#name' is abstract and can't be instantiated.""",
+        withArguments: _withArgumentsAbstractClassInstantiation);
+
+// 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,
+        analyzerCodes: <String>["NEW_WITH_ABSTRACT_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsAbstractClassInstantiation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeAbstractClassInstantiation,
+      message: """The class '${name}' is abstract and can't be instantiated.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAbstractClassMember = messageAbstractClassMember;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAbstractClassMember = const MessageCode(
+    "AbstractClassMember",
+    index: 51,
+    message: r"""Members of classes can't be declared to be 'abstract'.""",
+    tip:
+        r"""Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAbstractNotSync = messageAbstractNotSync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAbstractNotSync = const MessageCode("AbstractNotSync",
+    analyzerCodes: <String>["NON_SYNC_ABSTRACT_METHOD"],
+    message: r"""Abstract methods can't use 'async', 'async*', or 'sync*'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateAbstractRedirectedClassInstantiation = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Factory redirects to class '#name', which is abstract and can't be instantiated.""",
+    withArguments: _withArgumentsAbstractRedirectedClassInstantiation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    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.
+Message _withArgumentsAbstractRedirectedClassInstantiation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeAbstractRedirectedClassInstantiation,
+      message:
+          """Factory redirects to class '${name}', which is abstract and can't be instantiated.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateAccessError =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Access error: '#name'.""",
+        withArguments: _withArgumentsAccessError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsAccessError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeAccessError,
+      message: """Access error: '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAnonymousBreakTargetOutsideFunction =
+    messageAnonymousBreakTargetOutsideFunction;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAnonymousBreakTargetOutsideFunction =
+    const MessageCode("AnonymousBreakTargetOutsideFunction",
+        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"],
+        message: r"""Can't break to a target in a different function.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAnonymousContinueTargetOutsideFunction =
+    messageAnonymousContinueTargetOutsideFunction;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAnonymousContinueTargetOutsideFunction =
+    const MessageCode("AnonymousContinueTargetOutsideFunction",
+        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"],
+        message: r"""Can't continue at a target in a different function.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int
+            codePoint)> templateAsciiControlCharacter = const Template<
+        Message Function(int codePoint)>(
+    messageTemplate:
+        r"""The control character #unicode can only be used in strings and comments.""",
+    withArguments: _withArgumentsAsciiControlCharacter);
+
+// 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,
+        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsAsciiControlCharacter(int codePoint) {
+  String unicode =
+      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
+  return new Message(codeAsciiControlCharacter,
+      message:
+          """The control character ${unicode} can only be used in strings and comments.""",
+      arguments: {'codePoint': codePoint});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAssertAsExpression = messageAssertAsExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAssertAsExpression = const MessageCode(
+    "AssertAsExpression",
+    message: r"""`assert` can't be used as an expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAssertExtraneousArgument = messageAssertExtraneousArgument;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAssertExtraneousArgument = const MessageCode(
+    "AssertExtraneousArgument",
+    message: r"""`assert` can't have more than two arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAwaitAsIdentifier = const MessageCode(
+    "AwaitAsIdentifier",
+    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
+    message:
+        r"""'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAwaitForNotAsync = messageAwaitForNotAsync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAwaitForNotAsync = const MessageCode(
+    "AwaitForNotAsync",
+    analyzerCodes: <String>["ASYNC_FOR_IN_WRONG_CONTEXT"],
+    message:
+        r"""The asynchronous for-in can only be used in functions marked with 'async' or 'async*'.""",
+    tip:
+        r"""Try marking the function body with either 'async' or 'async*', or removing the 'await' before the for loop.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeAwaitNotAsync = messageAwaitNotAsync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageAwaitNotAsync = const MessageCode("AwaitNotAsync",
+    analyzerCodes: <String>["AWAIT_IN_WRONG_CONTEXT"],
+    message: r"""'await' can only be used in 'async' or 'async*' methods.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateBoundIssueViaCycleNonSimplicity = const Template<
+        Message Function(String name,
+            String name2)>(
+    messageTemplate:
+        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '#name2'.""",
+    tipTemplate:
+        r"""Try providing type arguments to '#name2' here or to some other raw types in the bounds along the reference chain.""",
+    withArguments: _withArgumentsBoundIssueViaCycleNonSimplicity);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    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.
+Message _withArgumentsBoundIssueViaCycleNonSimplicity(
+    String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeBoundIssueViaCycleNonSimplicity,
+      message:
+          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '${name2}'.""",
+      tip: """Try providing type arguments to '${name2}' here or to some other raw types in the bounds along the reference chain.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateBoundIssueViaLoopNonSimplicity = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables.""",
+    tipTemplate: r"""Try providing type arguments to '#name' here.""",
+    withArguments: _withArgumentsBoundIssueViaLoopNonSimplicity);
+
+// 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.
+Message _withArgumentsBoundIssueViaLoopNonSimplicity(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeBoundIssueViaLoopNonSimplicity,
+      message:
+          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables.""",
+      tip: """Try providing type arguments to '${name}' here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateBoundIssueViaRawTypeWithNonSimpleBounds =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Generic type '#name' can't be used without type arguments in a type variable bound.""",
+        tipTemplate: r"""Try providing type arguments to '#name' here.""",
+        withArguments: _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    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.
+Message _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeBoundIssueViaRawTypeWithNonSimpleBounds,
+      message:
+          """Generic type '${name}' can't be used without type arguments in a type variable bound.""",
+      tip: """Try providing type arguments to '${name}' here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeBreakOutsideOfLoop = messageBreakOutsideOfLoop;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageBreakOutsideOfLoop = const MessageCode(
+    "BreakOutsideOfLoop",
+    index: 52,
+    message:
+        r"""A break statement can't be used outside of a loop or switch statement.""",
+    tip: r"""Try removing the break statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateBreakTargetOutsideFunction =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Can't break to '#name' in a different function.""",
+        withArguments: _withArgumentsBreakTargetOutsideFunction);
+
+// 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,
+        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBreakTargetOutsideFunction(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeBreakTargetOutsideFunction,
+      message: """Can't break to '${name}' in a different function.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateBuiltInIdentifierAsType =
+    const Template<Message Function(Token token)>(
+        messageTemplate:
+            r"""The built-in identifier '#lexeme' can't be used as a type.""",
+        withArguments: _withArgumentsBuiltInIdentifierAsType);
+
+// 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,
+        analyzerCodes: <String>["BUILT_IN_IDENTIFIER_AS_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBuiltInIdentifierAsType(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeBuiltInIdentifierAsType,
+      message:
+          """The built-in identifier '${lexeme}' can't be used as a type.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)>
+    templateBuiltInIdentifierInDeclaration =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Can't use '#lexeme' as a name here.""",
+        withArguments: _withArgumentsBuiltInIdentifierInDeclaration);
+
+// 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.
+Message _withArgumentsBuiltInIdentifierInDeclaration(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeBuiltInIdentifierInDeclaration,
+      message: """Can't use '${lexeme}' as a name here.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeBytecodeLimitExceededTooManyArguments =
+    messageBytecodeLimitExceededTooManyArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageBytecodeLimitExceededTooManyArguments =
+    const MessageCode("BytecodeLimitExceededTooManyArguments",
+        message: r"""Dart bytecode limit exceeded: too many arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCandidateFound = messageCandidateFound;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCandidateFound = const MessageCode("CandidateFound",
+    severity: Severity.context,
+    message: r"""Found this candidate, but the arguments don't match.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateCandidateFoundIsDefaultConstructor =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""The class '#name' has a constructor that takes no arguments.""",
+        withArguments: _withArgumentsCandidateFoundIsDefaultConstructor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeCandidateFoundIsDefaultConstructor =
+    const Code<Message Function(String name)>(
+        "CandidateFoundIsDefaultConstructor",
+        templateCandidateFoundIsDefaultConstructor,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCandidateFoundIsDefaultConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCandidateFoundIsDefaultConstructor,
+      message:
+          """The class '${name}' has a constructor that takes no arguments.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCannotAssignToParenthesizedExpression =
+    messageCannotAssignToParenthesizedExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCannotAssignToParenthesizedExpression =
+    const MessageCode("CannotAssignToParenthesizedExpression",
+        analyzerCodes: <String>["ASSIGNMENT_TO_PARENTHESIZED_EXPRESSION"],
+        message: r"""Can't assign to a parenthesized expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCannotAssignToSuper = messageCannotAssignToSuper;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCannotAssignToSuper = const MessageCode(
+    "CannotAssignToSuper",
+    analyzerCodes: <String>["NOT_AN_LVALUE"],
+    message: r"""Can't assign to super.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateCannotReadSdkSpecification =
+    const Template<Message Function(String string)>(
+        messageTemplate:
+            r"""Unable to read the 'libraries.json' specification file:
+  #string.""",
+        withArguments: _withArgumentsCannotReadSdkSpecification);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsCannotReadSdkSpecification(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeCannotReadSdkSpecification,
+      message: """Unable to read the 'libraries.json' specification file:
+  ${string}.""", arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateAmbiguousInformation =
+    messageCantDisambiguateAmbiguousInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateAmbiguousInformation = const MessageCode(
+    "CantDisambiguateAmbiguousInformation",
+    message:
+        r"""Both Iterable and Map spread elements encountered in ambiguous literal.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantDisambiguateNotEnoughInformation =
+    messageCantDisambiguateNotEnoughInformation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantDisambiguateNotEnoughInformation = const MessageCode(
+    "CantDisambiguateNotEnoughInformation",
+    message:
+        r"""Not enough type information to disambiguate between literal set and literal map.""",
+    tip:
+        r"""Try providing type arguments for the literal explicitly to disambiguate it.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantInferPackagesFromManyInputs =
+    messageCantInferPackagesFromManyInputs;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantInferPackagesFromManyInputs = const MessageCode(
+    "CantInferPackagesFromManyInputs",
+    message:
+        r"""Can't infer a .packages file when compiling multiple inputs.""",
+    tip: r"""Try specifying the file explicitly with the --packages option.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantInferPackagesFromPackageUri =
+    messageCantInferPackagesFromPackageUri;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantInferPackagesFromPackageUri = const MessageCode(
+    "CantInferPackagesFromPackageUri",
+    message: r"""Can't infer a .packages file from an input 'package:*' URI.""",
+    tip: r"""Try specifying the file explicitly with the --packages option.""");
+
+// 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 inherited 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 inherited 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
+            string)> templateCantInferTypeDueToCircularity = const Template<
+        Message Function(String string)>(
+    messageTemplate:
+        r"""Can't infer the type of '#string': circularity found during type inference.""",
+    tipTemplate: r"""Specify the type explicitly.""",
+    withArguments: _withArgumentsCantInferTypeDueToCircularity);
+
+// 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,
+        analyzerCodes: <String>["RECURSIVE_COMPILE_TIME_CONSTANT"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCantInferTypeDueToCircularity(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeCantInferTypeDueToCircularity,
+      message:
+          """Can't infer the type of '${string}': circularity found during type inference.""",
+      tip: """Specify the type explicitly.""",
+      arguments: {'string': string});
+}
+
+// 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 inherited 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 inherited 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(Uri uri_, String string)> templateCantReadFile =
+    const Template<Message Function(Uri uri_, String string)>(
+        messageTemplate: r"""Error when reading '#uri': #string""",
+        withArguments: _withArgumentsCantReadFile);
+
+// 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,
+        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_);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeCantReadFile,
+      message: """Error when reading '${uri}': ${string}""",
+      arguments: {'uri': uri_, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)>
+    templateCantUseControlFlowOrSpreadAsConstant =
+    const Template<Message Function(Token token)>(
+        messageTemplate:
+            r"""'#lexeme' is not supported in constant expressions.""",
+        withArguments: _withArgumentsCantUseControlFlowOrSpreadAsConstant);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Token token)>
+    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.
+Message _withArgumentsCantUseControlFlowOrSpreadAsConstant(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeCantUseControlFlowOrSpreadAsConstant,
+      message: """'${lexeme}' is not supported in constant expressions.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Token
+            token)> templateCantUseDeferredPrefixAsConstant = const Template<
+        Message Function(Token token)>(
+    messageTemplate:
+        r"""'#lexeme' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
+    tipTemplate:
+        r"""Try moving the constant from the deferred library, or removing 'deferred' from the import.
+""",
+    withArguments: _withArgumentsCantUseDeferredPrefixAsConstant);
+
+// 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.
+Message _withArgumentsCantUseDeferredPrefixAsConstant(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeCantUseDeferredPrefixAsConstant,
+      message:
+          """'${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});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantUsePrefixAsExpression =
+    messageCantUsePrefixAsExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantUsePrefixAsExpression = const MessageCode(
+    "CantUsePrefixAsExpression",
+    analyzerCodes: <String>["PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT"],
+    message: r"""A prefix can't be used as an expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCantUsePrefixWithNullAware =
+    messageCantUsePrefixWithNullAware;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCantUsePrefixWithNullAware = const MessageCode(
+    "CantUsePrefixWithNullAware",
+    analyzerCodes: <String>["PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT"],
+    message: r"""A prefix can't be used with null-aware operators.""",
+    tip: r"""Try replacing '?.' with '.'""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCatchSyntax = messageCatchSyntax;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCatchSyntax = const MessageCode("CatchSyntax",
+    index: 84,
+    message:
+        r"""'catch' must be followed by '(identifier)' or '(identifier, identifier)'.""",
+    tip:
+        r"""No types are needed, the first is given by 'on', the second is always 'StackTrace'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCatchSyntaxExtraParameters =
+    messageCatchSyntaxExtraParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCatchSyntaxExtraParameters = const MessageCode(
+    "CatchSyntaxExtraParameters",
+    index: 83,
+    message:
+        r"""'catch' must be followed by '(identifier)' or '(identifier, identifier)'.""",
+    tip:
+        r"""No types are needed, the first is given by 'on', the second is always 'StackTrace'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeClassInClass = messageClassInClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageClassInClass = const MessageCode("ClassInClass",
+    index: 53,
+    message: r"""Classes can't be declared inside other classes.""",
+    tip: r"""Try moving the class to the top-level.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeColonInPlaceOfIn = messageColonInPlaceOfIn;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageColonInPlaceOfIn = const MessageCode(
+    "ColonInPlaceOfIn",
+    index: 54,
+    message: r"""For-in loops use 'in' rather than a colon.""",
+    tip: r"""Try replacing the colon with the keyword 'in'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateCombinedMemberSignatureFailed = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""Class '#name' inherits multiple members named '#name2' with incompatible signatures.""",
+    tipTemplate: r"""Try adding a declaration of '#name2' to '#name'.""",
+    withArguments: _withArgumentsCombinedMemberSignatureFailed);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeCombinedMemberSignatureFailed =
+    const Code<Message Function(String name, String name2)>(
+        "CombinedMemberSignatureFailed", templateCombinedMemberSignatureFailed,
+        analyzerCodes: <String>["INCONSISTENT_INHERITANCE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCombinedMemberSignatureFailed(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeCombinedMemberSignatureFailed,
+      message:
+          """Class '${name}' inherits multiple members named '${name2}' with incompatible signatures.""",
+      tip: """Try adding a declaration of '${name2}' to '${name}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateConflictingModifiers = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Members can't be declared to be both '#string' and '#string2'.""",
+    tipTemplate: r"""Try removing one of the keywords.""",
+    withArguments: _withArgumentsConflictingModifiers);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeConflictingModifiers =
+    const Code<Message Function(String string, String string2)>(
+        "ConflictingModifiers", templateConflictingModifiers,
+        index: 59);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictingModifiers(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeConflictingModifiers,
+      message:
+          """Members can't be declared to be both '${string}' and '${string2}'.""",
+      tip: """Try removing one of the keywords.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateConflictsWithConstructor =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Conflicts with constructor '#name'.""",
+        withArguments: _withArgumentsConflictsWithConstructor);
+
+// 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,
+        analyzerCodes: <String>["CONFLICTS_WITH_CONSTRUCTOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictsWithConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConflictsWithConstructor,
+      message: """Conflicts with constructor '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateConflictsWithFactory =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Conflicts with factory '#name'.""",
+        withArguments: _withArgumentsConflictsWithFactory);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsConflictsWithFactory(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConflictsWithFactory,
+      message: """Conflicts with factory '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateConflictsWithMember =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Conflicts with member '#name'.""",
+        withArguments: _withArgumentsConflictsWithMember);
+
+// 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,
+        analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictsWithMember(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConflictsWithMember,
+      message: """Conflicts with member '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateConflictsWithSetter =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Conflicts with setter '#name'.""",
+        withArguments: _withArgumentsConflictsWithSetter);
+
+// 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,
+        analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictsWithSetter(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConflictsWithSetter,
+      message: """Conflicts with setter '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateConflictsWithTypeVariable =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Conflicts with type variable '#name'.""",
+        withArguments: _withArgumentsConflictsWithTypeVariable);
+
+// 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,
+        analyzerCodes: <String>["CONFLICTING_TYPE_VARIABLE_AND_MEMBER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictsWithTypeVariable(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConflictsWithTypeVariable,
+      message: """Conflicts with type variable '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConflictsWithTypeVariableCause =
+    messageConflictsWithTypeVariableCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConflictsWithTypeVariableCause = const MessageCode(
+    "ConflictsWithTypeVariableCause",
+    severity: Severity.context,
+    message: r"""This is the type variable.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstAndFinal = messageConstAndFinal;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstAndFinal = const MessageCode("ConstAndFinal",
+    index: 58,
+    message: r"""Members can't be declared to be both 'const' and 'final'.""",
+    tip: r"""Try removing either the 'const' or 'final' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstClass = messageConstClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstClass = const MessageCode("ConstClass",
+    index: 60,
+    message: r"""Classes can't be declared to be 'const'.""",
+    tip:
+        r"""Try removing the 'const' keyword. If you're trying to indicate that instances of the class can be constants, place the 'const' keyword on  the class' constructor(s).""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorNonFinalField =
+    messageConstConstructorNonFinalField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorNonFinalField = const MessageCode(
+    "ConstConstructorNonFinalField",
+    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD"],
+    message: r"""Constructor is marked 'const' so all fields must be final.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorNonFinalFieldCause =
+    messageConstConstructorNonFinalFieldCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorNonFinalFieldCause = const MessageCode(
+    "ConstConstructorNonFinalFieldCause",
+    severity: Severity.context,
+    message: r"""Field isn't final, but constructor is 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorRedirectionToNonConst =
+    messageConstConstructorRedirectionToNonConst;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorRedirectionToNonConst =
+    const MessageCode("ConstConstructorRedirectionToNonConst",
+        message:
+            r"""A constant constructor can't call a non-constant constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorWithBody = messageConstConstructorWithBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorWithBody = const MessageCode(
+    "ConstConstructorWithBody",
+    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_BODY"],
+    message: r"""A const constructor can't have a body.""",
+    tip: r"""Try removing either the 'const' keyword or the body.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorWithNonConstSuper =
+    messageConstConstructorWithNonConstSuper;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorWithNonConstSuper = const MessageCode(
+    "ConstConstructorWithNonConstSuper",
+    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER"],
+    message:
+        r"""A constant constructor can't call a non-constant super constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalCircularity = messageConstEvalCircularity;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalCircularity = const MessageCode(
+    "ConstEvalCircularity",
+    analyzerCodes: <String>["RECURSIVE_COMPILE_TIME_CONSTANT"],
+    message: r"""Constant expression depends on itself.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalContext = messageConstEvalContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalContext =
+    const MessageCode("ConstEvalContext", message: r"""While analyzing:""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateConstEvalDeferredLibrary = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""'#name' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
+    tipTemplate:
+        r"""Try moving the constant from the deferred library, or removing 'deferred' from the import.
+""",
+    withArguments: _withArgumentsConstEvalDeferredLibrary);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeConstEvalDeferredLibrary =
+    const Code<Message Function(String name)>(
+        "ConstEvalDeferredLibrary", templateConstEvalDeferredLibrary,
+        analyzerCodes: <String>[
+      "NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalDeferredLibrary(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConstEvalDeferredLibrary,
+      message:
+          """'${name}' 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: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExtension = messageConstEvalExtension;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExtension = const MessageCode(
+    "ConstEvalExtension",
+    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
+    message:
+        r"""Extension operations can't be used in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalFailedAssertion = messageConstEvalFailedAssertion;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalFailedAssertion = const MessageCode(
+    "ConstEvalFailedAssertion",
+    analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"],
+    message: r"""This assertion failed.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateConstEvalFailedAssertionWithMessage =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""This assertion failed with message: #string""",
+        withArguments: _withArgumentsConstEvalFailedAssertionWithMessage);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    codeConstEvalFailedAssertionWithMessage =
+    const Code<Message Function(String string)>(
+        "ConstEvalFailedAssertionWithMessage",
+        templateConstEvalFailedAssertionWithMessage,
+        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalFailedAssertionWithMessage(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeConstEvalFailedAssertionWithMessage,
+      message: """This assertion failed with message: ${string}""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateConstEvalInvalidStaticInvocation = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""The invocation of '#name' is not allowed in a constant expression.""",
+    withArguments: _withArgumentsConstEvalInvalidStaticInvocation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeConstEvalInvalidStaticInvocation =
+    const Code<Message Function(String name)>(
+        "ConstEvalInvalidStaticInvocation",
+        templateConstEvalInvalidStaticInvocation,
+        analyzerCodes: <String>["CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidStaticInvocation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConstEvalInvalidStaticInvocation,
+      message:
+          """The invocation of '${name}' is not allowed in a constant expression.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String string2,
+        String
+            string3)> templateConstEvalNegativeShift = const Template<
+        Message Function(String string, String string2, String string3)>(
+    messageTemplate:
+        r"""Binary operator '#string' on '#string2' requires non-negative operand, but was '#string3'.""",
+    withArguments: _withArgumentsConstEvalNegativeShift);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2, String string3)>
+    codeConstEvalNegativeShift =
+    const Code<Message Function(String string, String string2, String string3)>(
+  "ConstEvalNegativeShift",
+  templateConstEvalNegativeShift,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalNegativeShift(
+    String string, String string2, String string3) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  if (string3.isEmpty) throw 'No string provided';
+  return new Message(codeConstEvalNegativeShift,
+      message:
+          """Binary operator '${string}' on '${string2}' requires non-negative operand, but was '${string3}'.""",
+      arguments: {'string': string, 'string2': string2, 'string3': string3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            string)> templateConstEvalNonConstantVariableGet = const Template<
+        Message Function(String string)>(
+    messageTemplate:
+        r"""The variable '#string' is not a constant, only constant expressions are allowed.""",
+    withArguments: _withArgumentsConstEvalNonConstantVariableGet);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    codeConstEvalNonConstantVariableGet =
+    const Code<Message Function(String string)>(
+        "ConstEvalNonConstantVariableGet",
+        templateConstEvalNonConstantVariableGet,
+        analyzerCodes: <String>["NON_CONSTANT_VALUE_IN_INITIALIZER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalNonConstantVariableGet(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeConstEvalNonConstantVariableGet,
+      message:
+          """The variable '${string}' is not a constant, only constant expressions are allowed.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalNotListOrSetInSpread =
+    messageConstEvalNotListOrSetInSpread;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalNotListOrSetInSpread = const MessageCode(
+    "ConstEvalNotListOrSetInSpread",
+    analyzerCodes: <String>["CONST_SPREAD_EXPECTED_LIST_OR_SET"],
+    message:
+        r"""Only lists and sets can be used in spreads in constant lists and sets.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalNotMapInSpread = messageConstEvalNotMapInSpread;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalNotMapInSpread = const MessageCode(
+    "ConstEvalNotMapInSpread",
+    analyzerCodes: <String>["CONST_SPREAD_EXPECTED_MAP"],
+    message: r"""Only maps can be used in spreads in constant maps.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalNullValue = messageConstEvalNullValue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalNullValue = const MessageCode(
+    "ConstEvalNullValue",
+    analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"],
+    message: r"""Null value during constant evaluation.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalStartingPoint = messageConstEvalStartingPoint;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalStartingPoint = const MessageCode(
+    "ConstEvalStartingPoint",
+    message: r"""Constant evaluation error:""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalUnevaluated = messageConstEvalUnevaluated;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalUnevaluated = const MessageCode(
+    "ConstEvalUnevaluated",
+    message: r"""Could not evaluate constant expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateConstEvalZeroDivisor = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Binary operator '#string' on '#string2' requires non-zero divisor, but divisor was '0'.""",
+    withArguments: _withArgumentsConstEvalZeroDivisor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeConstEvalZeroDivisor =
+    const Code<Message Function(String string, String string2)>(
+        "ConstEvalZeroDivisor", templateConstEvalZeroDivisor,
+        analyzerCodes: <String>["CONST_EVAL_THROWS_IDBZE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalZeroDivisor(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeConstEvalZeroDivisor,
+      message:
+          """Binary operator '${string}' on '${string2}' requires non-zero divisor, but divisor was '0'.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstFactory = messageConstFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstFactory = const MessageCode("ConstFactory",
+    index: 62,
+    message:
+        r"""Only redirecting factory constructors can be declared to be 'const'.""",
+    tip:
+        r"""Try removing the 'const' keyword, or replacing the body with '=' followed by a valid target.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstFactoryRedirectionToNonConst =
+    messageConstFactoryRedirectionToNonConst;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstFactoryRedirectionToNonConst = const MessageCode(
+    "ConstFactoryRedirectionToNonConst",
+    analyzerCodes: <String>["REDIRECT_TO_NON_CONST_CONSTRUCTOR"],
+    message:
+        r"""Constant factory constructor can't delegate to a non-constant constructor.""",
+    tip:
+        r"""Try redirecting to a different constructor or marking the target constructor 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateConstFieldWithoutInitializer = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""The const variable '#name' must be initialized.""",
+    tipTemplate:
+        r"""Try adding an initializer ('= expression') to the declaration.""",
+    withArguments: _withArgumentsConstFieldWithoutInitializer);
+
+// 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,
+        analyzerCodes: <String>["CONST_NOT_INITIALIZED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstFieldWithoutInitializer(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConstFieldWithoutInitializer,
+      message: """The const variable '${name}' must be initialized.""",
+      tip: """Try adding an initializer ('= expression') to the declaration.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstInstanceField = messageConstInstanceField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstInstanceField = const MessageCode(
+    "ConstInstanceField",
+    analyzerCodes: <String>["CONST_INSTANCE_FIELD"],
+    message: r"""Only static fields can be declared as const.""",
+    tip:
+        r"""Try using 'final' instead of 'const', or adding the keyword 'static'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstMethod = messageConstMethod;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstMethod = const MessageCode("ConstMethod",
+    index: 63,
+    message:
+        r"""Getters, setters and methods can't be declared to be 'const'.""",
+    tip: r"""Try removing the 'const' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorCyclic = messageConstructorCyclic;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorCyclic = const MessageCode(
+    "ConstructorCyclic",
+    analyzerCodes: <String>["RECURSIVE_CONSTRUCTOR_REDIRECT"],
+    message: r"""Redirecting constructors can't be cyclic.""",
+    tip:
+        r"""Try to have all constructors eventually redirect to a non-redirecting constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateConstructorNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Couldn't find constructor '#name'.""",
+        withArguments: _withArgumentsConstructorNotFound);
+
+// 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,
+        analyzerCodes: <String>["CONSTRUCTOR_NOT_FOUND"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstructorNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConstructorNotFound,
+      message: """Couldn't find constructor '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorNotSync = messageConstructorNotSync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorNotSync = const MessageCode(
+    "ConstructorNotSync",
+    analyzerCodes: <String>["NON_SYNC_CONSTRUCTOR"],
+    message:
+        r"""Constructor bodies can't use 'async', 'async*', or 'sync*'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithReturnType =
+    messageConstructorWithReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithReturnType = const MessageCode(
+    "ConstructorWithReturnType",
+    index: 55,
+    message: r"""Constructors can't have a return type.""",
+    tip: r"""Try removing the return type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithTypeArguments =
+    messageConstructorWithTypeArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithTypeArguments = const MessageCode(
+    "ConstructorWithTypeArguments",
+    analyzerCodes: <String>["WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR"],
+    message:
+        r"""A constructor invocation can't have type arguments on the constructor name.""",
+    tip: r"""Try to place the type arguments on the class name.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithTypeParameters =
+    messageConstructorWithTypeParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithTypeParameters = const MessageCode(
+    "ConstructorWithTypeParameters",
+    analyzerCodes: <String>["TYPE_PARAMETER_ON_CONSTRUCTOR"],
+    message: r"""Constructors can't have type parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithWrongName = messageConstructorWithWrongName;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithWrongName = const MessageCode(
+    "ConstructorWithWrongName",
+    analyzerCodes: <String>["INVALID_CONSTRUCTOR_NAME"],
+    message:
+        r"""The name of a constructor must match the name of the enclosing class.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateConstructorWithWrongNameContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""The name of the enclosing class is '#name'.""",
+        withArguments: _withArgumentsConstructorWithWrongNameContext);
+
+// 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.
+Message _withArgumentsConstructorWithWrongNameContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeConstructorWithWrongNameContext,
+      message: """The name of the enclosing class is '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeContinueLabelNotTarget = messageContinueLabelNotTarget;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageContinueLabelNotTarget = const MessageCode(
+    "ContinueLabelNotTarget",
+    analyzerCodes: <String>["LABEL_UNDEFINED"],
+    message: r"""Target of continue must be a label.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeContinueOutsideOfLoop = messageContinueOutsideOfLoop;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageContinueOutsideOfLoop = const MessageCode(
+    "ContinueOutsideOfLoop",
+    index: 2,
+    message:
+        r"""A continue statement can't be used outside of a loop or switch statement.""",
+    tip: r"""Try removing the continue statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateContinueTargetOutsideFunction =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't continue at '#name' in a different function.""",
+        withArguments: _withArgumentsContinueTargetOutsideFunction);
+
+// 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,
+        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsContinueTargetOutsideFunction(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeContinueTargetOutsideFunction,
+      message: """Can't continue at '${name}' in a different function.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeContinueWithoutLabelInCase =
+    messageContinueWithoutLabelInCase;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageContinueWithoutLabelInCase = const MessageCode(
+    "ContinueWithoutLabelInCase",
+    index: 64,
+    message:
+        r"""A continue statement in a switch statement must have a label as a target.""",
+    tip:
+        r"""Try adding a label associated with one of the case clauses to the continue statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2)>
+    templateCouldNotParseUri =
+    const Template<Message Function(String string, String string2)>(
+        messageTemplate: r"""Couldn't parse URI '#string':
+  #string2.""", withArguments: _withArgumentsCouldNotParseUri);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeCouldNotParseUri =
+    const Code<Message Function(String string, String string2)>(
+  "CouldNotParseUri",
+  templateCouldNotParseUri,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCouldNotParseUri(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeCouldNotParseUri,
+      message: """Couldn't parse URI '${string}':
+  ${string2}.""", arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCovariantAndStatic = messageCovariantAndStatic;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCovariantAndStatic = const MessageCode(
+    "CovariantAndStatic",
+    index: 66,
+    message:
+        r"""Members can't be declared to be both 'covariant' and 'static'.""",
+    tip: r"""Try removing either the 'covariant' or 'static' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeCovariantMember = messageCovariantMember;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageCovariantMember = const MessageCode("CovariantMember",
+    index: 67,
+    message:
+        r"""Getters, setters and methods can't be declared to be 'covariant'.""",
+    tip: r"""Try removing the 'covariant' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            string)> templateCycleInTypeVariables = const Template<
+        Message Function(String name, String string)>(
+    messageTemplate: r"""Type '#name' is a bound of itself via '#string'.""",
+    tipTemplate:
+        r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
+    withArguments: _withArgumentsCycleInTypeVariables);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String string)>
+    codeCycleInTypeVariables =
+    const Code<Message Function(String name, String string)>(
+        "CycleInTypeVariables", templateCycleInTypeVariables,
+        analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCycleInTypeVariables(String name, String string) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeCycleInTypeVariables,
+      message: """Type '${name}' is a bound of itself via '${string}'.""",
+      tip:
+          """Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
+      arguments: {'name': name, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateCyclicClassHierarchy =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is a supertype of itself.""",
+        withArguments: _withArgumentsCyclicClassHierarchy);
+
+// 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,
+        analyzerCodes: <String>["RECURSIVE_INTERFACE_INHERITANCE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCyclicClassHierarchy(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCyclicClassHierarchy,
+      message: """'${name}' is a supertype of itself.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateCyclicRedirectingFactoryConstructors =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Cyclic definition of factory '#name'.""",
+        withArguments: _withArgumentsCyclicRedirectingFactoryConstructors);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    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.
+Message _withArgumentsCyclicRedirectingFactoryConstructors(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCyclicRedirectingFactoryConstructors,
+      message: """Cyclic definition of factory '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateCyclicTypedef =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""The typedef '#name' has a reference to itself.""",
+        withArguments: _withArgumentsCyclicTypedef);
+
+// 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,
+        analyzerCodes: <String>["TYPE_ALIAS_CANNOT_REFERENCE_ITSELF"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCyclicTypedef(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCyclicTypedef,
+      message: """The typedef '${name}' has a reference to itself.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String string)>
+    templateDebugTrace =
+    const Template<Message Function(String name, String string)>(
+        messageTemplate: r"""Fatal '#name' at:
+#string""", withArguments: _withArgumentsDebugTrace);
+
+// 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,
+        severity: Severity.ignored);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDebugTrace(String name, String string) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeDebugTrace, message: """Fatal '${name}' at:
+${string}""", arguments: {'name': name, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDeclaredMemberConflictsWithInheritedMember =
+    messageDeclaredMemberConflictsWithInheritedMember;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDeclaredMemberConflictsWithInheritedMember =
+    const MessageCode("DeclaredMemberConflictsWithInheritedMember",
+        analyzerCodes: <String>["DECLARED_MEMBER_CONFLICTS_WITH_INHERITED"],
+        message:
+            r"""Can't declare a member that conflicts with an inherited one.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDeclaredMemberConflictsWithInheritedMemberCause =
+    messageDeclaredMemberConflictsWithInheritedMemberCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDeclaredMemberConflictsWithInheritedMemberCause =
+    const MessageCode("DeclaredMemberConflictsWithInheritedMemberCause",
+        severity: Severity.context,
+        message: r"""This is the inherited member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDefaultValueInRedirectingFactoryConstructor =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't have a default value here because any default values of '#name' would be used instead.""",
+        tipTemplate: r"""Try removing the default value.""",
+        withArguments:
+            _withArgumentsDefaultValueInRedirectingFactoryConstructor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeDefaultValueInRedirectingFactoryConstructor =
+    const Code<Message Function(String name)>(
+        "DefaultValueInRedirectingFactoryConstructor",
+        templateDefaultValueInRedirectingFactoryConstructor,
+        analyzerCodes: <String>[
+      "DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDefaultValueInRedirectingFactoryConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDefaultValueInRedirectingFactoryConstructor,
+      message:
+          """Can't have a default value here because any default values of '${name}' would be used instead.""",
+      tip: """Try removing the default value.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDeferredAfterPrefix = messageDeferredAfterPrefix;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDeferredAfterPrefix = const MessageCode(
+    "DeferredAfterPrefix",
+    index: 68,
+    message:
+        r"""The deferred keyword should come immediately before the prefix ('as' clause).""",
+    tip: r"""Try moving the deferred keyword before the prefix.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateDeferredPrefixDuplicated = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Can't use the name '#name' for a deferred library, as the name is used elsewhere.""",
+    withArguments: _withArgumentsDeferredPrefixDuplicated);
+
+// 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,
+        analyzerCodes: <String>["SHARED_DEFERRED_PREFIX"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDeferredPrefixDuplicated(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDeferredPrefixDuplicated,
+      message:
+          """Can't use the name '${name}' for a deferred library, as the name is used elsewhere.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDeferredPrefixDuplicatedCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is used here.""",
+        withArguments: _withArgumentsDeferredPrefixDuplicatedCause);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDeferredPrefixDuplicatedCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDeferredPrefixDuplicatedCause,
+      message: """'${name}' is used here.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(
+            int count, int count2, num _num1, num _num2, num _num3)>
+    templateDillOutlineSummary = const Template<
+            Message Function(
+                int count, int count2, num _num1, num _num2, num _num3)>(
+        messageTemplate:
+            r"""Indexed #count libraries (#count2 bytes) in #num1%.3ms, that is,
+#num2%12.3 bytes/ms, and
+#num3%12.3 ms/libraries.""",
+        withArguments: _withArgumentsDillOutlineSummary);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+    Message Function(int count, int count2, num _num1, num _num2,
+        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) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  if (_num1 == null) throw 'No number provided';
+  String num1 = _num1.toStringAsFixed(3);
+  if (_num2 == null) throw 'No number provided';
+  String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  if (_num3 == null) throw 'No number provided';
+  String num3 = _num3.toStringAsFixed(3).padLeft(12);
+  return new Message(codeDillOutlineSummary,
+      message:
+          """Indexed ${count} libraries (${count2} bytes) in ${num1}ms, that is,
+${num2} bytes/ms, and
+${num3} ms/libraries.""",
+      arguments: {
+        'count': count,
+        'count2': count2,
+        'num1': _num1,
+        'num2': _num2,
+        'num3': _num3
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateDirectCycleInTypeVariables = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""Type '#name' can't use itself as a bound.""",
+    tipTemplate:
+        r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
+    withArguments: _withArgumentsDirectCycleInTypeVariables);
+
+// 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,
+        analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDirectCycleInTypeVariables(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDirectCycleInTypeVariables,
+      message: """Type '${name}' can't use itself as a bound.""",
+      tip:
+          """Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDirectiveAfterDeclaration =
+    messageDirectiveAfterDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDirectiveAfterDeclaration = const MessageCode(
+    "DirectiveAfterDeclaration",
+    index: 69,
+    message: r"""Directives must appear before any declarations.""",
+    tip: r"""Try moving the directive before any declarations.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDuplicateDeferred = messageDuplicateDeferred;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDuplicateDeferred = const MessageCode(
+    "DuplicateDeferred",
+    index: 71,
+    message: r"""An import directive can only have one 'deferred' keyword.""",
+    tip: r"""Try removing all but one 'deferred' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicateLabelInSwitchStatement =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""The label '#name' was already used in this switch statement.""",
+        tipTemplate: r"""Try choosing a different name for this label.""",
+        withArguments: _withArgumentsDuplicateLabelInSwitchStatement);
+
+// 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.
+Message _withArgumentsDuplicateLabelInSwitchStatement(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicateLabelInSwitchStatement,
+      message:
+          """The label '${name}' was already used in this switch statement.""",
+      tip: """Try choosing a different name for this label.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeDuplicatePrefix = messageDuplicatePrefix;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageDuplicatePrefix = const MessageCode("DuplicatePrefix",
+    index: 73,
+    message: r"""An import directive can only have one prefix ('as' clause).""",
+    tip: r"""Try removing all but one prefix.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedDeclaration =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is already declared in this scope.""",
+        withArguments: _withArgumentsDuplicatedDeclaration);
+
+// 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,
+        analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedDeclaration(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedDeclaration,
+      message: """'${name}' is already declared in this scope.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicatedDeclarationCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Previous declaration of '#name'.""",
+        withArguments: _withArgumentsDuplicatedDeclarationCause);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedDeclarationCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedDeclarationCause,
+      message: """Previous declaration of '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateDuplicatedDeclarationSyntheticCause = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Previous declaration of '#name' is implied by this definition.""",
+    withArguments: _withArgumentsDuplicatedDeclarationSyntheticCause);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeDuplicatedDeclarationSyntheticCause =
+    const Code<Message Function(String name)>(
+        "DuplicatedDeclarationSyntheticCause",
+        templateDuplicatedDeclarationSyntheticCause,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedDeclarationSyntheticCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedDeclarationSyntheticCause,
+      message:
+          """Previous declaration of '${name}' is implied by this definition.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedDeclarationUse =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't use '#name' because it is declared more than once.""",
+        withArguments: _withArgumentsDuplicatedDeclarationUse);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsDuplicatedDeclarationUse(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedDeclarationUse,
+      message: """Can't use '${name}' because it is declared more than once.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateDuplicatedExport =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""'#name' is exported from both '#uri' and '#uri2'.""",
+        withArguments: _withArgumentsDuplicatedExport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    codeDuplicatedExport =
+    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
+        "DuplicatedExport", templateDuplicatedExport,
+        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_);
+  return new Message(codeDuplicatedExport,
+      message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateDuplicatedExportInType =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""'#name' is exported from both '#uri' and '#uri2'.""",
+        withArguments: _withArgumentsDuplicatedExportInType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    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_);
+  return new Message(codeDuplicatedExportInType,
+      message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateDuplicatedImport =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""'#name' is imported from both '#uri' and '#uri2'.""",
+        withArguments: _withArgumentsDuplicatedImport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    codeDuplicatedImport =
+    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
+        "DuplicatedImport", templateDuplicatedImport,
+        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_);
+  return new Message(codeDuplicatedImport,
+      message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateDuplicatedImportInType =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""'#name' is imported from both '#uri' and '#uri2'.""",
+        withArguments: _withArgumentsDuplicatedImportInType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    codeDuplicatedImportInType =
+    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
+        "DuplicatedImportInType", templateDuplicatedImportInType,
+        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_);
+  return new Message(codeDuplicatedImportInType,
+      message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedLibraryExport =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""A library with name '#name' is exported more than once.""",
+        withArguments: _withArgumentsDuplicatedLibraryExport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeDuplicatedLibraryExport =
+    const Code<Message Function(String name)>(
+        "DuplicatedLibraryExport", templateDuplicatedLibraryExport,
+        analyzerCodes: <String>["EXPORT_DUPLICATED_LIBRARY_NAMED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedLibraryExport(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedLibraryExport,
+      message: """A library with name '${name}' is exported more than once.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicatedLibraryExportContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is also exported here.""",
+        withArguments: _withArgumentsDuplicatedLibraryExportContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeDuplicatedLibraryExportContext =
+    const Code<Message Function(String name)>("DuplicatedLibraryExportContext",
+        templateDuplicatedLibraryExportContext,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedLibraryExportContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedLibraryExportContext,
+      message: """'${name}' is also exported here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedLibraryImport =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""A library with name '#name' is imported more than once.""",
+        withArguments: _withArgumentsDuplicatedLibraryImport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeDuplicatedLibraryImport =
+    const Code<Message Function(String name)>(
+        "DuplicatedLibraryImport", templateDuplicatedLibraryImport,
+        analyzerCodes: <String>["IMPORT_DUPLICATED_LIBRARY_NAMED"],
+        severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedLibraryImport(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedLibraryImport,
+      message: """A library with name '${name}' is imported more than once.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicatedLibraryImportContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is also imported here.""",
+        withArguments: _withArgumentsDuplicatedLibraryImportContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeDuplicatedLibraryImportContext =
+    const Code<Message Function(String name)>("DuplicatedLibraryImportContext",
+        templateDuplicatedLibraryImportContext,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedLibraryImportContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedLibraryImportContext,
+      message: """'${name}' is also imported here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateDuplicatedModifier =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""The modifier '#lexeme' was already specified.""",
+        tipTemplate:
+            r"""Try removing all but one occurrence of the modifier.""",
+        withArguments: _withArgumentsDuplicatedModifier);
+
+// 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);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedModifier(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeDuplicatedModifier,
+      message: """The modifier '${lexeme}' was already specified.""",
+      tip: """Try removing all but one occurrence of the modifier.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateDuplicatedNamePreviouslyUsed = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Can't declare '#name' because it was already used in this scope.""",
+    withArguments: _withArgumentsDuplicatedNamePreviouslyUsed);
+
+// 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,
+        analyzerCodes: <String>["REFERENCED_BEFORE_DECLARATION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedNamePreviouslyUsed(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedNamePreviouslyUsed,
+      message:
+          """Can't declare '${name}' because it was already used in this scope.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicatedNamePreviouslyUsedCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Previous use of '#name'.""",
+        withArguments: _withArgumentsDuplicatedNamePreviouslyUsedCause);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeDuplicatedNamePreviouslyUsedCause =
+    const Code<Message Function(String name)>(
+        "DuplicatedNamePreviouslyUsedCause",
+        templateDuplicatedNamePreviouslyUsedCause,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedNamePreviouslyUsedCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedNamePreviouslyUsedCause,
+      message: """Previous use of '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedNamedArgument =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Duplicated named argument '#name'.""",
+        withArguments: _withArgumentsDuplicatedNamedArgument);
+
+// 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,
+        analyzerCodes: <String>["DUPLICATE_NAMED_ARGUMENT"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedNamedArgument(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedNamedArgument,
+      message: """Duplicated named argument '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateDuplicatedParameterName =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Duplicated parameter name '#name'.""",
+        withArguments: _withArgumentsDuplicatedParameterName);
+
+// 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,
+        analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedParameterName(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedParameterName,
+      message: """Duplicated parameter name '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateDuplicatedParameterNameCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Other parameter named '#name'.""",
+        withArguments: _withArgumentsDuplicatedParameterNameCause);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDuplicatedParameterNameCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeDuplicatedParameterNameCause,
+      message: """Other parameter named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEmptyNamedParameterList = messageEmptyNamedParameterList;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEmptyNamedParameterList = const MessageCode(
+    "EmptyNamedParameterList",
+    analyzerCodes: <String>["MISSING_IDENTIFIER"],
+    message: r"""Named parameter lists cannot be empty.""",
+    tip: r"""Try adding a named parameter to the list.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEmptyOptionalParameterList =
+    messageEmptyOptionalParameterList;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEmptyOptionalParameterList = const MessageCode(
+    "EmptyOptionalParameterList",
+    analyzerCodes: <String>["MISSING_IDENTIFIER"],
+    message: r"""Optional parameter lists cannot be empty.""",
+    tip: r"""Try adding an optional parameter to the list.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEncoding = messageEncoding;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEncoding = const MessageCode("Encoding",
+    message: r"""Unable to decode bytes as UTF-8.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateEnumConstantSameNameAsEnclosing = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Name of enum constant '#name' can't be the same as the enum's own name.""",
+    withArguments: _withArgumentsEnumConstantSameNameAsEnclosing);
+
+// 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.
+Message _withArgumentsEnumConstantSameNameAsEnclosing(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeEnumConstantSameNameAsEnclosing,
+      message:
+          """Name of enum constant '${name}' can't be the same as the enum's own name.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumDeclarationEmpty = messageEnumDeclarationEmpty;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumDeclarationEmpty = const MessageCode(
+    "EnumDeclarationEmpty",
+    analyzerCodes: <String>["EMPTY_ENUM_BODY"],
+    message: r"""An enum declaration can't be empty.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumInClass = messageEnumInClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumInClass = const MessageCode("EnumInClass",
+    index: 74,
+    message: r"""Enums can't be declared inside classes.""",
+    tip: r"""Try moving the enum to the top-level.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEnumInstantiation = messageEnumInstantiation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEnumInstantiation = const MessageCode(
+    "EnumInstantiation",
+    analyzerCodes: <String>["INSTANTIATE_ENUM"],
+    message: r"""Enums can't be instantiated.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeEqualityCannotBeEqualityOperand =
+    messageEqualityCannotBeEqualityOperand;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageEqualityCannotBeEqualityOperand = const MessageCode(
+    "EqualityCannotBeEqualityOperand",
+    index: 1,
+    message:
+        r"""A comparison expression can't be an operand of another comparison expression.""",
+    tip: r"""Try putting parentheses around one of the comparisons.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateExpectedAfterButGot =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Expected '#string' after this.""",
+        withArguments: _withArgumentsExpectedAfterButGot);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedAfterButGot(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExpectedAfterButGot,
+      message: """Expected '${string}' after this.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedAnInitializer = messageExpectedAnInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedAnInitializer = const MessageCode(
+    "ExpectedAnInitializer",
+    index: 36,
+    message: r"""Expected an initializer.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedBlock = messageExpectedBlock;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedBlock = const MessageCode("ExpectedBlock",
+    analyzerCodes: <String>["EXPECTED_TOKEN"],
+    message: r"""Expected a block.""",
+    tip: r"""Try adding {}.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedBlockToSkip = messageExpectedBlockToSkip;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedBlockToSkip = const MessageCode(
+    "ExpectedBlockToSkip",
+    analyzerCodes: <String>["MISSING_FUNCTION_BODY"],
+    message: r"""Expected a function body or '=>'.""",
+    tip: r"""Try adding {}.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedBody = messageExpectedBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedBody = const MessageCode("ExpectedBody",
+    analyzerCodes: <String>["MISSING_FUNCTION_BODY"],
+    message: r"""Expected a function body or '=>'.""",
+    tip: r"""Try adding {}.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateExpectedButGot =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Expected '#string' before this.""",
+        withArguments: _withArgumentsExpectedButGot);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedButGot(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExpectedButGot,
+      message: """Expected '${string}' before this.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedClassMember =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected a class member, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedClassMember);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_CLASS_MEMBER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedClassMember(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedClassMember,
+      message: """Expected a class member, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateExpectedClassOrMixinBody =
+    const Template<Message Function(String string)>(
+        messageTemplate:
+            r"""A #string must have a body, even if it is empty.""",
+        tipTemplate: r"""Try adding an empty body.""",
+        withArguments: _withArgumentsExpectedClassOrMixinBody);
+
+// 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,
+        index: 8);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedClassOrMixinBody(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExpectedClassOrMixinBody,
+      message: """A ${string} must have a body, even if it is empty.""",
+      tip: """Try adding an empty body.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedDeclaration =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected a declaration, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedDeclaration);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_EXECUTABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedDeclaration(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedDeclaration,
+      message: """Expected a declaration, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedElseOrComma = messageExpectedElseOrComma;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedElseOrComma = const MessageCode(
+    "ExpectedElseOrComma",
+    index: 46,
+    message: r"""Expected 'else' or comma.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(Token token)> templateExpectedEnumBody = const Template<
+        Message Function(Token token)>(
+    messageTemplate: r"""Expected a enum body, but got '#lexeme'.""",
+    tipTemplate:
+        r"""An enum definition must have a body with at least one constant name.""",
+    withArguments: _withArgumentsExpectedEnumBody);
+
+// 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,
+        analyzerCodes: <String>["MISSING_ENUM_BODY"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedEnumBody(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedEnumBody,
+      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});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedFunctionBody =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected a function body, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedFunctionBody);
+
+// 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,
+        analyzerCodes: <String>["MISSING_FUNCTION_BODY"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedFunctionBody(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedFunctionBody,
+      message: """Expected a function body, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedHexDigit = messageExpectedHexDigit;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedHexDigit = const MessageCode(
+    "ExpectedHexDigit",
+    analyzerCodes: <String>["MISSING_HEX_DIGIT"],
+    message: r"""A hex digit (0-9 or A-F) must follow '0x'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedIdentifier =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected an identifier, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedIdentifier);
+
+// 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,
+        analyzerCodes: <String>["MISSING_IDENTIFIER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedIdentifier(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedIdentifier,
+      message: """Expected an identifier, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateExpectedInstead =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Expected '#string' instead of this.""",
+        withArguments: _withArgumentsExpectedInstead);
+
+// 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);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedInstead(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExpectedInstead,
+      message: """Expected '${string}' instead of this.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedNamedArgument = messageExpectedNamedArgument;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedNamedArgument = const MessageCode(
+    "ExpectedNamedArgument",
+    analyzerCodes: <String>["EXTRA_POSITIONAL_ARGUMENTS"],
+    message: r"""Expected named argument.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedOneExpression = messageExpectedOneExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedOneExpression = const MessageCode(
+    "ExpectedOneExpression",
+    message: r"""Expected one expression, but found additional input.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedOpenParens = messageExpectedOpenParens;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedOpenParens =
+    const MessageCode("ExpectedOpenParens", message: r"""Expected '('.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedStatement = messageExpectedStatement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedStatement = const MessageCode(
+    "ExpectedStatement",
+    index: 29,
+    message: r"""Expected a statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedString =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected a String, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedString);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_STRING_LITERAL"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedString(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedString,
+      message: """Expected a String, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateExpectedToken =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Expected to find '#string'.""",
+        withArguments: _withArgumentsExpectedToken);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedToken(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExpectedToken,
+      message: """Expected to find '${string}'.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExpectedType =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Expected a type, but got '#lexeme'.""",
+        withArguments: _withArgumentsExpectedType);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_TYPE_NAME"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedType(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedType,
+      message: """Expected a type, but got '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpectedUri = messageExpectedUri;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpectedUri =
+    const MessageCode("ExpectedUri", message: r"""Expected a URI.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            string)> templateExperimentNotEnabled = const Template<
+        Message Function(String string)>(
+    messageTemplate:
+        r"""This requires the '#string' experiment to be enabled.""",
+    tipTemplate:
+        r"""Try enabling this experiment by adding it to the command line when compiling and running.""",
+    withArguments: _withArgumentsExperimentNotEnabled);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)> codeExperimentNotEnabled =
+    const Code<Message Function(String string)>(
+        "ExperimentNotEnabled", templateExperimentNotEnabled,
+        index: 48);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExperimentNotEnabled(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeExperimentNotEnabled,
+      message: """This requires the '${string}' experiment to be enabled.""",
+      tip:
+          """Try enabling this experiment by adding it to the command line when compiling and running.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExplicitExtensionArgumentMismatch =
+    messageExplicitExtensionArgumentMismatch;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExplicitExtensionArgumentMismatch = const MessageCode(
+    "ExplicitExtensionArgumentMismatch",
+    message:
+        r"""Explicit extension application requires exactly 1 positional argument.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExplicitExtensionAsExpression =
+    messageExplicitExtensionAsExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExplicitExtensionAsExpression = const MessageCode(
+    "ExplicitExtensionAsExpression",
+    message:
+        r"""Explicit extension application cannot be used as an expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExplicitExtensionAsLvalue =
+    messageExplicitExtensionAsLvalue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExplicitExtensionAsLvalue = const MessageCode(
+    "ExplicitExtensionAsLvalue",
+    message:
+        r"""Explicit extension application cannot be a target for assignment.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        int
+            count)> templateExplicitExtensionTypeArgumentMismatch = const Template<
+        Message Function(String name, int count)>(
+    messageTemplate:
+        r"""Explicit extension application of extension '#name' takes '#count' type argument(s).""",
+    withArguments: _withArgumentsExplicitExtensionTypeArgumentMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, int count)>
+    codeExplicitExtensionTypeArgumentMismatch =
+    const Code<Message Function(String name, int count)>(
+  "ExplicitExtensionTypeArgumentMismatch",
+  templateExplicitExtensionTypeArgumentMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExplicitExtensionTypeArgumentMismatch(
+    String name, int count) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (count == null) throw 'No count provided';
+  return new Message(codeExplicitExtensionTypeArgumentMismatch,
+      message:
+          """Explicit extension application of extension '${name}' takes '${count}' type argument(s).""",
+      arguments: {'name': name, 'count': count});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExportAfterPart = messageExportAfterPart;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExportAfterPart = const MessageCode("ExportAfterPart",
+    index: 75,
+    message: r"""Export directives must precede part directives.""",
+    tip: r"""Try moving the export directives before the part directives.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateExportHidesExport =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""Export of '#name' (from '#uri') hides export from '#uri2'.""",
+        withArguments: _withArgumentsExportHidesExport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    codeExportHidesExport =
+    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
+        "ExportHidesExport", templateExportHidesExport,
+        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_);
+  return new Message(codeExportHidesExport,
+      message:
+          """Export of '${name}' (from '${uri}') hides export from '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExpressionNotMetadata = messageExpressionNotMetadata;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExpressionNotMetadata = const MessageCode(
+    "ExpressionNotMetadata",
+    message:
+        r"""This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateExtendingEnum =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""'#name' is an enum and can't be extended or implemented.""",
+        withArguments: _withArgumentsExtendingEnum);
+
+// 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,
+        analyzerCodes: <String>["EXTENDS_ENUM"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExtendingEnum(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeExtendingEnum,
+      message: """'${name}' is an enum and can't be extended or implemented.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateExtendingRestricted =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""'#name' is restricted and can't be extended or implemented.""",
+        withArguments: _withArgumentsExtendingRestricted);
+
+// 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,
+        analyzerCodes: <String>["EXTENDS_DISALLOWED_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExtendingRestricted(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeExtendingRestricted,
+      message:
+          """'${name}' is restricted and can't be extended or implemented.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExtensionDeclaresAbstractMember =
+    messageExtensionDeclaresAbstractMember;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExtensionDeclaresAbstractMember = const MessageCode(
+    "ExtensionDeclaresAbstractMember",
+    index: 94,
+    message: r"""Extensions can't declare abstract members.""",
+    tip: r"""Try providing an implementation for the member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExtensionDeclaresConstructor =
+    messageExtensionDeclaresConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExtensionDeclaresConstructor = const MessageCode(
+    "ExtensionDeclaresConstructor",
+    index: 92,
+    message: r"""Extensions can't declare constructors.""",
+    tip: r"""Try removing the constructor declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExtensionDeclaresInstanceField =
+    messageExtensionDeclaresInstanceField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExtensionDeclaresInstanceField = const MessageCode(
+    "ExtensionDeclaresInstanceField",
+    index: 93,
+    message: r"""Extensions can't declare instance fields""",
+    tip: r"""Try removing the field declaration or making it a static field""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateExtensionMemberConflictsWithObjectMember =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""This extension member conflicts with Object member '#name'.""",
+        withArguments: _withArgumentsExtensionMemberConflictsWithObjectMember);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeExtensionMemberConflictsWithObjectMember =
+    const Code<Message Function(String name)>(
+  "ExtensionMemberConflictsWithObjectMember",
+  templateExtensionMemberConflictsWithObjectMember,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExtensionMemberConflictsWithObjectMember(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeExtensionMemberConflictsWithObjectMember,
+      message:
+          """This extension member conflicts with Object member '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalClass = messageExternalClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalClass = const MessageCode("ExternalClass",
+    index: 3,
+    message: r"""Classes can't be declared to be 'external'.""",
+    tip: r"""Try removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalConstructorWithBody =
+    messageExternalConstructorWithBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalConstructorWithBody = const MessageCode(
+    "ExternalConstructorWithBody",
+    index: 87,
+    message: r"""External constructors can't have a body.""",
+    tip:
+        r"""Try removing the body of the constructor, or removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalConstructorWithFieldInitializers =
+    messageExternalConstructorWithFieldInitializers;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalConstructorWithFieldInitializers =
+    const MessageCode("ExternalConstructorWithFieldInitializers",
+        analyzerCodes: <String>["EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS"],
+        message: r"""An external constructor can't initialize fields.""",
+        tip:
+            r"""Try removing the field initializers, or removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalEnum = messageExternalEnum;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalEnum = const MessageCode("ExternalEnum",
+    index: 5,
+    message: r"""Enums can't be declared to be 'external'.""",
+    tip: r"""Try removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalFactoryRedirection =
+    messageExternalFactoryRedirection;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalFactoryRedirection = const MessageCode(
+    "ExternalFactoryRedirection",
+    index: 85,
+    message: r"""A redirecting factory can't be external.""",
+    tip: r"""Try removing the 'external' modifier.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalFactoryWithBody = messageExternalFactoryWithBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalFactoryWithBody = const MessageCode(
+    "ExternalFactoryWithBody",
+    index: 86,
+    message: r"""External factories can't have a body.""",
+    tip:
+        r"""Try removing the body of the factory, or removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalField = messageExternalField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalField = const MessageCode("ExternalField",
+    index: 50,
+    message: r"""Fields can't be declared to be 'external'.""",
+    tip:
+        r"""Try removing the keyword 'external', or replacing the field by an external getter and/or setter.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalMethodWithBody = messageExternalMethodWithBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalMethodWithBody = const MessageCode(
+    "ExternalMethodWithBody",
+    index: 49,
+    message: r"""An external or native method can't have a body.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExternalTypedef = messageExternalTypedef;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExternalTypedef = const MessageCode("ExternalTypedef",
+    index: 76,
+    message: r"""Typedefs can't be declared to be 'external'.""",
+    tip: r"""Try removing the keyword 'external'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateExtraneousModifier =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Can't have modifier '#lexeme' here.""",
+        tipTemplate: r"""Try removing '#lexeme'.""",
+        withArguments: _withArgumentsExtraneousModifier);
+
+// 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);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExtraneousModifier(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExtraneousModifier,
+      message: """Can't have modifier '${lexeme}' here.""",
+      tip: """Try removing '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)>
+    templateExtraneousModifierInExtension =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Can't have modifier '#lexeme' in an extension.""",
+        tipTemplate: r"""Try removing '#lexeme'.""",
+        withArguments: _withArgumentsExtraneousModifierInExtension);
+
+// 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,
+        index: 98);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExtraneousModifierInExtension(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExtraneousModifierInExtension,
+      message: """Can't have modifier '${lexeme}' in an extension.""",
+      tip: """Try removing '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFactoryNotSync = messageFactoryNotSync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFactoryNotSync = const MessageCode("FactoryNotSync",
+    analyzerCodes: <String>["NON_SYNC_FACTORY"],
+    message: r"""Factory bodies can't use 'async', 'async*', or 'sync*'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFactoryTopLevelDeclaration =
+    messageFactoryTopLevelDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFactoryTopLevelDeclaration = const MessageCode(
+    "FactoryTopLevelDeclaration",
+    index: 78,
+    message: r"""Top-level declarations can't be declared to be 'factory'.""",
+    tip: r"""Try removing the keyword 'factory'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateFastaCLIArgumentRequired =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Expected value after '#name'.""",
+        withArguments: _withArgumentsFastaCLIArgumentRequired);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsFastaCLIArgumentRequired(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFastaCLIArgumentRequired,
+      message: """Expected value after '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFastaUsageLong = messageFastaUsageLong;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFastaUsageLong =
+    const MessageCode("FastaUsageLong", message: r"""Supported options:
+
+  -o <file>, --output=<file>
+    Generate the output into <file>.
+
+  -h, /h, /?, --help
+    Display this message (add -v for information about all options).
+
+  -v, --verbose
+    Display verbose information.
+
+  -Dname
+  -Dname=value
+    Define an environment variable in the compile-time environment.
+
+  --no-defines
+    Ignore all -D options and leave environment constants unevaluated.
+
+  --
+    Stop option parsing, the rest of the command line is assumed to be
+    file names or arguments to the Dart program.
+
+  --packages=<file>
+    Use package resolution configuration <file>, which should contain a mapping
+    of package names to paths.
+
+  --platform=<file>
+    Read the SDK platform from <file>, which should be in Dill/Kernel IR format
+    and contain the Dart SDK.
+
+  --target=dart2js|dart2js_server|dart_runner|dartdevc|flutter|flutter_runner|none|vm
+    Specify the target configuration.
+
+  --enable-asserts
+    Check asserts in initializers during constant evaluation.
+
+  --verify
+    Check that the generated output is free of various problems. This is mostly
+    useful for developers of this compiler or Kernel transformations.
+
+  --dump-ir
+    Print compiled libraries in Kernel source notation.
+
+  --omit-platform
+    Exclude the platform from the serialized dill file.
+
+  --bytecode
+    Generate bytecode. Supported only for SDK platform compilation.
+
+  --exclude-source
+    Do not include source code in the dill file.
+
+  --compile-sdk=<sdk>
+    Compile the SDK from scratch instead of reading it from a .dill file
+    (see --platform).
+
+  --sdk=<sdk>
+    Location of the SDK sources for use when compiling additional platform
+    libraries.
+
+  --supermixin
+    Ignored for now.
+
+  --single-root-scheme=String
+  --single-root-base=<dir>
+    Specify a custom URI scheme and a location on disk where such URIs are
+    mapped to.
+
+    When specified, the compiler can be invoked with inputs using the custom
+    URI scheme. The compiler can ignore the exact location of files on disk
+    and as a result to produce output that is independent of the absolute
+    location of files on disk. This is mostly useful for integrating with
+    build systems.
+
+  --fatal=errors
+  --fatal=warnings
+    Makes messages of the given kinds fatal, that is, immediately stop the
+    compiler with a non-zero exit-code. In --verbose mode, also display an
+    internal stack trace from the compiler. Multiple kinds can be separated by
+    commas, for example, --fatal=errors,warnings.
+
+  --fatal-skip=<number>
+  --fatal-skip=trace
+    Skip this many messages that would otherwise be fatal before aborting the
+    compilation. Default is 0, which stops at the first message. Specify
+    'trace' to print a stack trace for every message without stopping.
+
+  --enable-experiment=<flag>
+    Enable or disable an experimental flag, used to guard features currently
+    in development. Prefix an experiment name with 'no-' to disable it.
+    Multiple experiments can be separated by commas.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFastaUsageShort = messageFastaUsageShort;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFastaUsageShort =
+    const MessageCode("FastaUsageShort", message: r"""Frequently used options:
+
+  -o <file> Generate the output into <file>.
+  -h        Display this message (add -v for information about all options).""");
+
+// 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.
+const MessageCode messageFfiExceptionalReturnNull = const MessageCode(
+    "FfiExceptionalReturnNull",
+    message: r"""Exceptional return value must not be null.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFfiExpectedConstant = messageFfiExpectedConstant;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFfiExpectedConstant = const MessageCode(
+    "FfiExpectedConstant",
+    message: r"""Exceptional return value must be a constant.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateFfiExtendsOrImplementsSealedClass =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Class '#name' cannot be extended or implemented.""",
+        withArguments: _withArgumentsFfiExtendsOrImplementsSealedClass);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeFfiExtendsOrImplementsSealedClass =
+    const Code<Message Function(String name)>(
+  "FfiExtendsOrImplementsSealedClass",
+  templateFfiExtendsOrImplementsSealedClass,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiExtendsOrImplementsSealedClass(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiExtendsOrImplementsSealedClass,
+      message: """Class '${name}' cannot be extended or implemented.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiFieldAnnotation = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
+    withArguments: _withArgumentsFfiFieldAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsFfiFieldAnnotation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiFieldAnnotation,
+      message:
+          """Field '${name}' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
+      arguments: {'name': name});
+}
+
+// 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.""",
+    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.
+Message _withArgumentsFfiFieldInitializer(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiFieldInitializer,
+      message:
+          """Field '${name}' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFfiFieldNoAnnotation = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""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.""",
+    withArguments: _withArgumentsFfiFieldNoAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsFfiFieldNoAnnotation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiFieldNoAnnotation,
+      message:
+          """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.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiNotStatic = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""",
+    withArguments: _withArgumentsFfiNotStatic);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsFfiNotStatic(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiNotStatic,
+      message:
+          """${name} expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateFfiStructGeneric =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Struct '#name' should not be generic.""",
+        withArguments: _withArgumentsFfiStructGeneric);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsFfiStructGeneric(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiStructGeneric,
+      message: """Struct '${name}' should not be generic.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFieldInitializedOutsideDeclaringClass =
+    messageFieldInitializedOutsideDeclaringClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFieldInitializedOutsideDeclaringClass = const MessageCode(
+    "FieldInitializedOutsideDeclaringClass",
+    index: 88,
+    message: r"""A field can only be initialized in its declaring class""",
+    tip:
+        r"""Try passing a value into the superclass constructor, or moving the initialization into the constructor body.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFieldInitializerOutsideConstructor =
+    messageFieldInitializerOutsideConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFieldInitializerOutsideConstructor = const MessageCode(
+    "FieldInitializerOutsideConstructor",
+    index: 79,
+    message: r"""Field formal parameters can only be used in a constructor.""",
+    tip: r"""Try removing 'this.'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFinalAndCovariant = messageFinalAndCovariant;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFinalAndCovariant = const MessageCode(
+    "FinalAndCovariant",
+    index: 80,
+    message:
+        r"""Members can't be declared to be both 'final' and 'covariant'.""",
+    tip: r"""Try removing either the 'final' or 'covariant' keyword.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFinalAndVar = messageFinalAndVar;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFinalAndVar = const MessageCode("FinalAndVar",
+    index: 81,
+    message: r"""Members can't be declared to be both 'final' and 'var'.""",
+    tip: r"""Try removing the keyword 'var'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFinalFieldNotInitialized = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""Final field '#name' is not initialized.""",
+    tipTemplate:
+        r"""Try to initialize the field in the declaration or in every constructor.""",
+    withArguments: _withArgumentsFinalFieldNotInitialized);
+
+// 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,
+        analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalFieldNotInitialized(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalFieldNotInitialized,
+      message: """Final field '${name}' is not initialized.""",
+      tip:
+          """Try to initialize the field in the declaration or in every constructor.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFinalFieldNotInitializedByConstructor = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Final field '#name' is not initialized by this constructor.""",
+    tipTemplate:
+        r"""Try to initialize the field using an initializing formal or a field initializer.""",
+    withArguments: _withArgumentsFinalFieldNotInitializedByConstructor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    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.
+Message _withArgumentsFinalFieldNotInitializedByConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalFieldNotInitializedByConstructor,
+      message:
+          """Final field '${name}' is not initialized by this constructor.""",
+      tip:
+          """Try to initialize the field using an initializing formal or a field initializer.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFinalFieldWithoutInitializer = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""The final variable '#name' must be initialized.""",
+    tipTemplate:
+        r"""Try adding an initializer ('= expression') to the declaration.""",
+    withArguments: _withArgumentsFinalFieldWithoutInitializer);
+
+// 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,
+        analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalFieldWithoutInitializer(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalFieldWithoutInitializer,
+      message: """The final variable '${name}' must be initialized.""",
+      tip: """Try adding an initializer ('= expression') to the declaration.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateFinalInstanceVariableAlreadyInitialized =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""'#name' is a final instance variable that has already been initialized.""",
+        withArguments: _withArgumentsFinalInstanceVariableAlreadyInitialized);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeFinalInstanceVariableAlreadyInitialized =
+    const Code<Message Function(String name)>(
+        "FinalInstanceVariableAlreadyInitialized",
+        templateFinalInstanceVariableAlreadyInitialized,
+        analyzerCodes: <String>["FINAL_INITIALIZED_MULTIPLE_TIMES"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalInstanceVariableAlreadyInitialized(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalInstanceVariableAlreadyInitialized,
+      message:
+          """'${name}' is a final instance variable that has already been initialized.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateFinalInstanceVariableAlreadyInitializedCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' was initialized here.""",
+        withArguments:
+            _withArgumentsFinalInstanceVariableAlreadyInitializedCause);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeFinalInstanceVariableAlreadyInitializedCause =
+    const Code<Message Function(String name)>(
+        "FinalInstanceVariableAlreadyInitializedCause",
+        templateFinalInstanceVariableAlreadyInitializedCause,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalInstanceVariableAlreadyInitializedCause(
+    String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalInstanceVariableAlreadyInitializedCause,
+      message: """'${name}' was initialized here.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeForInLoopExactlyOneVariable =
+    messageForInLoopExactlyOneVariable;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageForInLoopExactlyOneVariable = const MessageCode(
+    "ForInLoopExactlyOneVariable",
+    message: r"""A for-in loop can't have more than one loop variable.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeForInLoopNotAssignable = messageForInLoopNotAssignable;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageForInLoopNotAssignable = const MessageCode(
+    "ForInLoopNotAssignable",
+    message:
+        r"""Can't assign to this, so it can't be used in a for-in loop.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeForInLoopWithConstVariable =
+    messageForInLoopWithConstVariable;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageForInLoopWithConstVariable = const MessageCode(
+    "ForInLoopWithConstVariable",
+    analyzerCodes: <String>["FOR_IN_WITH_CONST_VARIABLE"],
+    message: r"""A for-in loop-variable can't be 'const'.""",
+    tip: r"""Try removing the 'const' modifier.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFunctionTypeDefaultValue = messageFunctionTypeDefaultValue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFunctionTypeDefaultValue = const MessageCode(
+    "FunctionTypeDefaultValue",
+    analyzerCodes: <String>["DEFAULT_VALUE_IN_FUNCTION_TYPE"],
+    message: r"""Can't have a default value in a function type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFunctionTypedParameterVar =
+    messageFunctionTypedParameterVar;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFunctionTypedParameterVar = const MessageCode(
+    "FunctionTypedParameterVar",
+    analyzerCodes: <String>["FUNCTION_TYPED_PARAMETER_VAR"],
+    message:
+        r"""Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type.""",
+    tip: r"""Try replacing the keyword with a return type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageGeneratorReturnsValue = const MessageCode(
+    "GeneratorReturnsValue",
+    analyzerCodes: <String>["RETURN_IN_GENERATOR"],
+    message: r"""'sync*' and 'async*' can't return a value.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeGenericFunctionTypeInBound =
+    messageGenericFunctionTypeInBound;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageGenericFunctionTypeInBound = const MessageCode(
+    "GenericFunctionTypeInBound",
+    analyzerCodes: <String>["GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND"],
+    message:
+        r"""Type variables can't have generic function types in their bounds.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeGenericFunctionTypeUsedAsActualTypeArgument =
+    messageGenericFunctionTypeUsedAsActualTypeArgument;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageGenericFunctionTypeUsedAsActualTypeArgument =
+    const MessageCode("GenericFunctionTypeUsedAsActualTypeArgument",
+        analyzerCodes: <String>["GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT"],
+        message:
+            r"""A generic function type can't be used as a type argument.""",
+        tip: r"""Try using a non-generic function type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateGetterNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Getter not found: '#name'.""",
+        withArguments: _withArgumentsGetterNotFound);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_GETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsGetterNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeGetterNotFound,
+      message: """Getter not found: '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeGetterWithFormals = messageGetterWithFormals;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageGetterWithFormals = const MessageCode(
+    "GetterWithFormals",
+    analyzerCodes: <String>["GETTER_WITH_PARAMETERS"],
+    message: r"""A getter can't have formal parameters.""",
+    tip: r"""Try removing '(...)'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalAssignmentToNonAssignable =
+    messageIllegalAssignmentToNonAssignable;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalAssignmentToNonAssignable = const MessageCode(
+    "IllegalAssignmentToNonAssignable",
+    index: 45,
+    message: r"""Illegal assignment to non-assignable expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalAsyncGeneratorReturnType =
+    messageIllegalAsyncGeneratorReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalAsyncGeneratorReturnType = const MessageCode(
+    "IllegalAsyncGeneratorReturnType",
+    analyzerCodes: <String>["ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE"],
+    message:
+        r"""Functions marked 'async*' must have a return type assignable to 'Stream'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalAsyncGeneratorVoidReturnType =
+    messageIllegalAsyncGeneratorVoidReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalAsyncGeneratorVoidReturnType =
+    const MessageCode("IllegalAsyncGeneratorVoidReturnType",
+        message:
+            r"""Functions marked 'async*' can't have return type 'void'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalAsyncReturnType = messageIllegalAsyncReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalAsyncReturnType = const MessageCode(
+    "IllegalAsyncReturnType",
+    analyzerCodes: <String>["ILLEGAL_ASYNC_RETURN_TYPE"],
+    message:
+        r"""Functions marked 'async' must have a return type assignable to 'Future'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateIllegalMixin =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""The type '#name' can't be mixed in.""",
+        withArguments: _withArgumentsIllegalMixin);
+
+// 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,
+        analyzerCodes: <String>["ILLEGAL_MIXIN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIllegalMixin(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeIllegalMixin,
+      message: """The type '${name}' can't be mixed in.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateIllegalMixinDueToConstructors =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't use '#name' as a mixin because it has constructors.""",
+        withArguments: _withArgumentsIllegalMixinDueToConstructors);
+
+// 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,
+        analyzerCodes: <String>["MIXIN_DECLARES_CONSTRUCTOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIllegalMixinDueToConstructors(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeIllegalMixinDueToConstructors,
+      message:
+          """Can't use '${name}' as a mixin because it has constructors.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateIllegalMixinDueToConstructorsCause =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""This constructor prevents using '#name' as a mixin.""",
+        withArguments: _withArgumentsIllegalMixinDueToConstructorsCause);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeIllegalMixinDueToConstructorsCause =
+    const Code<Message Function(String name)>(
+        "IllegalMixinDueToConstructorsCause",
+        templateIllegalMixinDueToConstructorsCause,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIllegalMixinDueToConstructorsCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeIllegalMixinDueToConstructorsCause,
+      message: """This constructor prevents using '${name}' as a mixin.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalSyncGeneratorReturnType =
+    messageIllegalSyncGeneratorReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalSyncGeneratorReturnType = const MessageCode(
+    "IllegalSyncGeneratorReturnType",
+    analyzerCodes: <String>["ILLEGAL_SYNC_GENERATOR_RETURN_TYPE"],
+    message:
+        r"""Functions marked 'sync*' must have a return type assignable to 'Iterable'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIllegalSyncGeneratorVoidReturnType =
+    messageIllegalSyncGeneratorVoidReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIllegalSyncGeneratorVoidReturnType = const MessageCode(
+    "IllegalSyncGeneratorVoidReturnType",
+    message: r"""Functions marked 'sync*' can't have return type 'void'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImplementsBeforeExtends = messageImplementsBeforeExtends;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImplementsBeforeExtends = const MessageCode(
+    "ImplementsBeforeExtends",
+    index: 44,
+    message: r"""The extends clause must be before the implements clause.""",
+    tip: r"""Try moving the extends clause before the implements clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImplementsBeforeOn = messageImplementsBeforeOn;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImplementsBeforeOn = const MessageCode(
+    "ImplementsBeforeOn",
+    index: 43,
+    message: r"""The on clause must be before the implements clause.""",
+    tip: r"""Try moving the on clause before the implements clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImplementsBeforeWith = messageImplementsBeforeWith;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImplementsBeforeWith = const MessageCode(
+    "ImplementsBeforeWith",
+    index: 42,
+    message: r"""The with clause must be before the implements clause.""",
+    tip: r"""Try moving the with clause before the implements clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImplementsFutureOr = messageImplementsFutureOr;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImplementsFutureOr = const MessageCode(
+    "ImplementsFutureOr",
+    message: r"""'FutureOr' can't be used in an 'implements' clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, int count)>
+    templateImplementsRepeated =
+    const Template<Message Function(String name, int count)>(
+        messageTemplate: r"""'#name' can only be implemented once.""",
+        tipTemplate: r"""Try removing #count of the occurrences.""",
+        withArguments: _withArgumentsImplementsRepeated);
+
+// 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,
+        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);
+  if (count == null) throw 'No count provided';
+  return new Message(codeImplementsRepeated,
+      message: """'${name}' can only be implemented once.""",
+      tip: """Try removing ${count} of the occurrences.""",
+      arguments: {'name': name, 'count': count});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateImplementsSuperClass = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""'#name' can't be used in both 'extends' and 'implements' clauses.""",
+    tipTemplate: r"""Try removing one of the occurrences.""",
+    withArguments: _withArgumentsImplementsSuperClass);
+
+// 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,
+        analyzerCodes: <String>["IMPLEMENTS_SUPER_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsImplementsSuperClass(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeImplementsSuperClass,
+      message:
+          """'${name}' can't be used in both 'extends' and 'implements' clauses.""",
+      tip: """Try removing one of the occurrences.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String name2,
+        String
+            name3)> templateImplicitMixinOverride = const Template<
+        Message Function(String name, String name2, String name3)>(
+    messageTemplate:
+        r"""Applying the mixin '#name' to '#name2' introduces an erroneous override of '#name3'.""",
+    withArguments: _withArgumentsImplicitMixinOverride);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2, String name3)>
+    codeImplicitMixinOverride =
+    const Code<Message Function(String name, String name2, String name3)>(
+  "ImplicitMixinOverride",
+  templateImplicitMixinOverride,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsImplicitMixinOverride(
+    String name, String name2, String name3) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  return new Message(codeImplicitMixinOverride,
+      message:
+          """Applying the mixin '${name}' to '${name2}' introduces an erroneous override of '${name3}'.""",
+      arguments: {'name': name, 'name2': name2, 'name3': name3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImportAfterPart = messageImportAfterPart;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImportAfterPart = const MessageCode("ImportAfterPart",
+    index: 10,
+    message: r"""Import directives must precede part directives.""",
+    tip: r"""Try moving the import directives before the part directives.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateImportHidesImport =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate:
+            r"""Import of '#name' (from '#uri') hides import from '#uri2'.""",
+        withArguments: _withArgumentsImportHidesImport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    codeImportHidesImport =
+    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
+        "ImportHidesImport", templateImportHidesImport,
+        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_);
+  return new Message(codeImportHidesImport,
+      message:
+          """Import of '${name}' (from '${uri}') hides import from '${uri2}'.""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeIncorrectTypeArgumentVariable =
+    messageIncorrectTypeArgumentVariable;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageIncorrectTypeArgumentVariable = const MessageCode(
+    "IncorrectTypeArgumentVariable",
+    severity: Severity.context,
+    message: r"""This is the type variable whose bound isn't conformed to.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templateInferredPackageUri =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""Interpreting this as package URI, '#uri'.""",
+        withArguments: _withArgumentsInferredPackageUri);
+
+// 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,
+        severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInferredPackageUri(Uri uri_) {
+  String uri = relativizeUri(uri_);
+  return new Message(codeInferredPackageUri,
+      message: """Interpreting this as package URI, '${uri}'.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInheritedMembersConflict = messageInheritedMembersConflict;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInheritedMembersConflict = const MessageCode(
+    "InheritedMembersConflict",
+    analyzerCodes: <String>["CONFLICTS_WITH_INHERITED_MEMBER"],
+    message: r"""Can't inherit members that conflict with each other.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInheritedMembersConflictCause1 =
+    messageInheritedMembersConflictCause1;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInheritedMembersConflictCause1 = const MessageCode(
+    "InheritedMembersConflictCause1",
+    severity: Severity.context,
+    message: r"""This is one inherited member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInheritedMembersConflictCause2 =
+    messageInheritedMembersConflictCause2;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInheritedMembersConflictCause2 = const MessageCode(
+    "InheritedMembersConflictCause2",
+    severity: Severity.context,
+    message: r"""This is the other inherited member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        Uri
+            uri_)> templateInitializeFromDillNotSelfContained = const Template<
+        Message Function(String string, Uri uri_)>(
+    messageTemplate:
+        r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+    withArguments: _withArgumentsInitializeFromDillNotSelfContained);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, Uri uri_)>
+    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_);
+  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.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+      arguments: {'string': string, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateInitializeFromDillNotSelfContainedNoDump =
+    const Template<Message Function(String string)>(
+        messageTemplate:
+            r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+        withArguments: _withArgumentsInitializeFromDillNotSelfContainedNoDump);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    codeInitializeFromDillNotSelfContainedNoDump =
+    const Code<Message Function(String string)>(
+        "InitializeFromDillNotSelfContainedNoDump",
+        templateInitializeFromDillNotSelfContainedNoDump,
+        severity: Severity.warning);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializeFromDillNotSelfContainedNoDump(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInitializeFromDillNotSelfContainedNoDump,
+      message:
+          """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String string2,
+        String string3,
+        Uri
+            uri_)> templateInitializeFromDillUnknownProblem = const Template<
+        Message Function(
+            String string, String string2, String string3, Uri uri_)>(
+    messageTemplate:
+        r"""Tried to initialize from a previous compilation (#string), but couldn't.
+Error message was '#string2'.
+Stacktrace included '#string3'.
+This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+    withArguments: _withArgumentsInitializeFromDillUnknownProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            String string, String string2, String string3, Uri uri_)>
+    codeInitializeFromDillUnknownProblem = const Code<
+            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.
+Message _withArgumentsInitializeFromDillUnknownProblem(
+    String string, String string2, String string3, Uri uri_) {
+  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_);
+  return new Message(codeInitializeFromDillUnknownProblem,
+      message:
+          """Tried to initialize from a previous compilation (${string}), but couldn't.
+Error message was '${string2}'.
+Stacktrace included '${string3}'.
+This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
+If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
+Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
+      arguments: {
+        'string': string,
+        'string2': string2,
+        'string3': string3,
+        'uri': uri_
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2, String string3)>
+    templateInitializeFromDillUnknownProblemNoDump = const Template<
+            Message Function(String string, String string2, String string3)>(
+        messageTemplate:
+            r"""Tried to initialize from a previous compilation (#string), but couldn't.
+Error message was '#string2'.
+Stacktrace included '#string3'.
+This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+        withArguments: _withArgumentsInitializeFromDillUnknownProblemNoDump);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2, String string3)>
+    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.
+Message _withArgumentsInitializeFromDillUnknownProblemNoDump(
+    String string, String string2, String string3) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  if (string3.isEmpty) throw 'No string provided';
+  return new Message(codeInitializeFromDillUnknownProblemNoDump,
+      message:
+          """Tried to initialize from a previous compilation (${string}), but couldn't.
+Error message was '${string2}'.
+Stacktrace included '${string3}'.
+This might be a bug.
+
+The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
+      arguments: {'string': string, 'string2': string2, 'string3': string3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializedVariableInForEach =
+    messageInitializedVariableInForEach;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializedVariableInForEach = const MessageCode(
+    "InitializedVariableInForEach",
+    index: 82,
+    message: r"""The loop variable in a for-each loop can't be initialized.""",
+    tip:
+        r"""Try removing the initializer, or using a different kind of loop.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInitializerForStaticField =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' isn't an instance field of this class.""",
+        withArguments: _withArgumentsInitializerForStaticField);
+
+// 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,
+        analyzerCodes: <String>["INITIALIZER_FOR_STATIC_FIELD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializerForStaticField(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInitializerForStaticField,
+      message: """'${name}' isn't an instance field of this class.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateInitializerOutsideConstructor = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Only constructors can have initializers, and '#name' is not a constructor.""",
+    withArguments: _withArgumentsInitializerOutsideConstructor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeInitializerOutsideConstructor =
+    const Code<Message Function(String name)>(
+        "InitializerOutsideConstructor", templateInitializerOutsideConstructor,
+        analyzerCodes: <String>["INITIALIZER_OUTSIDE_CONSTRUCTOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializerOutsideConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInitializerOutsideConstructor,
+      message:
+          """Only constructors can have initializers, and '${name}' is not a constructor.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializingFormalTypeMismatchField =
+    messageInitializingFormalTypeMismatchField;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializingFormalTypeMismatchField =
+    const MessageCode("InitializingFormalTypeMismatchField",
+        severity: Severity.context,
+        message: r"""The field that corresponds to the parameter.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templateInputFileNotFound =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""Input file not found: #uri.""",
+        withArguments: _withArgumentsInputFileNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codeInputFileNotFound,
+      message: """Input file not found: ${uri}.""", arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            string)> templateIntegerLiteralIsOutOfRange = const Template<
+        Message Function(String string)>(
+    messageTemplate:
+        r"""The integer literal #string can't be represented in 64 bits.""",
+    tipTemplate:
+        r"""Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
+    withArguments: _withArgumentsIntegerLiteralIsOutOfRange);
+
+// 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,
+        analyzerCodes: <String>["INTEGER_LITERAL_OUT_OF_RANGE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIntegerLiteralIsOutOfRange(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeIntegerLiteralIsOutOfRange,
+      message:
+          """The integer literal ${string} can't be represented in 64 bits.""",
+      tip:
+          """Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateInterfaceCheck = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""The implementation of '#name' in the non-abstract class '#name2' does not conform to its interface.""",
+    withArguments: _withArgumentsInterfaceCheck);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsInterfaceCheck(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeInterfaceCheck,
+      message:
+          """The implementation of '${name}' in the non-abstract class '${name2}' does not conform to its interface.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemAlreadyInitialized =
+    messageInternalProblemAlreadyInitialized;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemAlreadyInitialized = const MessageCode(
+    "InternalProblemAlreadyInitialized",
+    severity: Severity.internalProblem,
+    message: r"""Attempt to set initializer on field without initializer.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemBodyOnAbstractMethod =
+    messageInternalProblemBodyOnAbstractMethod;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemBodyOnAbstractMethod =
+    const MessageCode("InternalProblemBodyOnAbstractMethod",
+        severity: Severity.internalProblem,
+        message: r"""Attempting to set body on abstract method.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_)>
+    templateInternalProblemConstructorNotFound =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate: r"""No constructor named '#name' in '#uri'.""",
+        withArguments: _withArgumentsInternalProblemConstructorNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_)>
+    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.
+Message _withArgumentsInternalProblemConstructorNotFound(
+    String name, Uri uri_) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  String uri = relativizeUri(uri_);
+  return new Message(codeInternalProblemConstructorNotFound,
+      message: """No constructor named '${name}' in '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateInternalProblemContextSeverity =
+    const Template<Message Function(String string)>(
+        messageTemplate:
+            r"""Non-context message has context severity: #string""",
+        withArguments: _withArgumentsInternalProblemContextSeverity);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsInternalProblemContextSeverity(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemContextSeverity,
+      message: """Non-context message has context severity: ${string}""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String string)>
+    templateInternalProblemDebugAbort =
+    const Template<Message Function(String name, String string)>(
+        messageTemplate: r"""Compilation aborted due to fatal '#name' at:
+#string""", withArguments: _withArgumentsInternalProblemDebugAbort);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String string)>
+    codeInternalProblemDebugAbort =
+    const Code<Message Function(String name, String string)>(
+        "InternalProblemDebugAbort", templateInternalProblemDebugAbort,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemDebugAbort(String name, String string) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemDebugAbort,
+      message: """Compilation aborted due to fatal '${name}' at:
+${string}""", arguments: {'name': name, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemExtendingUnmodifiableScope =
+    messageInternalProblemExtendingUnmodifiableScope;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemExtendingUnmodifiableScope =
+    const MessageCode("InternalProblemExtendingUnmodifiableScope",
+        severity: Severity.internalProblem,
+        message: r"""Can't extend an unmodifiable scope.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemLabelUsageInVariablesDeclaration =
+    messageInternalProblemLabelUsageInVariablesDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemLabelUsageInVariablesDeclaration =
+    const MessageCode("InternalProblemLabelUsageInVariablesDeclaration",
+        severity: Severity.internalProblem,
+        message:
+            r"""Unexpected usage of label inside declaration of variables.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemMissingContext =
+    messageInternalProblemMissingContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemMissingContext = const MessageCode(
+    "InternalProblemMissingContext",
+    severity: Severity.internalProblem,
+    message: r"""Compiler cannot run without a compiler context.""",
+    tip:
+        r"""Are calls to the compiler wrapped in CompilerContext.runInContext?""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateInternalProblemNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Couldn't find '#name'.""",
+        withArguments: _withArgumentsInternalProblemNotFound);
+
+// 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,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInternalProblemNotFound,
+      message: """Couldn't find '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String name2)>
+    templateInternalProblemNotFoundIn =
+    const Template<Message Function(String name, String name2)>(
+        messageTemplate: r"""Couldn't find '#name' in '#name2'.""",
+        withArguments: _withArgumentsInternalProblemNotFoundIn);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeInternalProblemNotFoundIn =
+    const Code<Message Function(String name, String name2)>(
+        "InternalProblemNotFoundIn", templateInternalProblemNotFoundIn,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemNotFoundIn(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeInternalProblemNotFoundIn,
+      message: """Couldn't find '${name}' in '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemPreviousTokenNotFound =
+    messageInternalProblemPreviousTokenNotFound;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemPreviousTokenNotFound =
+    const MessageCode("InternalProblemPreviousTokenNotFound",
+        severity: Severity.internalProblem,
+        message: r"""Couldn't find previous token.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInternalProblemPrivateConstructorAccess =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Can't access private constructor '#name'.""",
+        withArguments: _withArgumentsInternalProblemPrivateConstructorAccess);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeInternalProblemPrivateConstructorAccess =
+    const Code<Message Function(String name)>(
+        "InternalProblemPrivateConstructorAccess",
+        templateInternalProblemPrivateConstructorAccess,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemPrivateConstructorAccess(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInternalProblemPrivateConstructorAccess,
+      message: """Can't access private constructor '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInternalProblemProvidedBothCompileSdkAndSdkSummary =
+    messageInternalProblemProvidedBothCompileSdkAndSdkSummary;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInternalProblemProvidedBothCompileSdkAndSdkSummary =
+    const MessageCode("InternalProblemProvidedBothCompileSdkAndSdkSummary",
+        severity: Severity.internalProblem,
+        message:
+            r"""The compileSdk and sdkSummary options are mutually exclusive""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String string)>
+    templateInternalProblemStackNotEmpty =
+    const Template<Message Function(String name, String string)>(
+        messageTemplate: r"""#name.stack isn't empty:
+  #string""", withArguments: _withArgumentsInternalProblemStackNotEmpty);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String string)>
+    codeInternalProblemStackNotEmpty =
+    const Code<Message Function(String name, String string)>(
+        "InternalProblemStackNotEmpty", templateInternalProblemStackNotEmpty,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemStackNotEmpty(String name, String string) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemStackNotEmpty,
+      message: """${name}.stack isn't empty:
+  ${string}""", arguments: {'name': name, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2)>
+    templateInternalProblemUnexpected =
+    const Template<Message Function(String string, String string2)>(
+        messageTemplate: r"""Expected '#string', but got '#string2'.""",
+        withArguments: _withArgumentsInternalProblemUnexpected);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeInternalProblemUnexpected =
+    const Code<Message Function(String string, String string2)>(
+        "InternalProblemUnexpected", templateInternalProblemUnexpected,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemUnexpected(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemUnexpected,
+      message: """Expected '${string}', but got '${string2}'.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        Uri
+            uri_)> templateInternalProblemUnfinishedTypeVariable = const Template<
+        Message Function(String name, Uri uri_)>(
+    messageTemplate:
+        r"""Unfinished type variable '#name' found in non-source library '#uri'.""",
+    withArguments: _withArgumentsInternalProblemUnfinishedTypeVariable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_)>
+    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.
+Message _withArgumentsInternalProblemUnfinishedTypeVariable(
+    String name, Uri uri_) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  String uri = relativizeUri(uri_);
+  return new Message(codeInternalProblemUnfinishedTypeVariable,
+      message:
+          """Unfinished type variable '${name}' found in non-source library '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2)>
+    templateInternalProblemUnhandled =
+    const Template<Message Function(String string, String string2)>(
+        messageTemplate: r"""Unhandled #string in #string2.""",
+        withArguments: _withArgumentsInternalProblemUnhandled);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeInternalProblemUnhandled =
+    const Code<Message Function(String string, String string2)>(
+        "InternalProblemUnhandled", templateInternalProblemUnhandled,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemUnhandled(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemUnhandled,
+      message: """Unhandled ${string} in ${string2}.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateInternalProblemUnimplemented =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Unimplemented #string.""",
+        withArguments: _withArgumentsInternalProblemUnimplemented);
+
+// 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,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemUnimplemented(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemUnimplemented,
+      message: """Unimplemented ${string}.""", arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInternalProblemUnsupported =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Unsupported operation: '#name'.""",
+        withArguments: _withArgumentsInternalProblemUnsupported);
+
+// 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,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemUnsupported(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInternalProblemUnsupported,
+      message: """Unsupported operation: '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)>
+    templateInternalProblemUriMissingScheme =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""The URI '#uri' has no scheme.""",
+        withArguments: _withArgumentsInternalProblemUriMissingScheme);
+
+// 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_);
+  return new Message(codeInternalProblemUriMissingScheme,
+      message: """The URI '${uri}' has no scheme.""", arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateInternalProblemVerificationError =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Verification of the generated program failed:
+#string""", withArguments: _withArgumentsInternalProblemVerificationError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    codeInternalProblemVerificationError =
+    const Code<Message Function(String string)>(
+        "InternalProblemVerificationError",
+        templateInternalProblemVerificationError,
+        severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemVerificationError(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInternalProblemVerificationError,
+      message: """Verification of the generated program failed:
+${string}""", arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInterpolationInUri = messageInterpolationInUri;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInterpolationInUri = const MessageCode(
+    "InterpolationInUri",
+    analyzerCodes: <String>["INVALID_LITERAL_IN_CONFIGURATION"],
+    message: r"""Can't use string interpolation in a URI.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidAwaitFor = messageInvalidAwaitFor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidAwaitFor = const MessageCode("InvalidAwaitFor",
+    index: 9,
+    message:
+        r"""The keyword 'await' isn't allowed for a normal 'for' statement.""",
+    tip: r"""Try removing the keyword, or use a for-each statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateInvalidBreakTarget =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Can't break to '#name'.""",
+        withArguments: _withArgumentsInvalidBreakTarget);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsInvalidBreakTarget(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvalidBreakTarget,
+      message: """Can't break to '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidCatchArguments = messageInvalidCatchArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidCatchArguments = const MessageCode(
+    "InvalidCatchArguments",
+    analyzerCodes: <String>["INVALID_CATCH_ARGUMENTS"],
+    message: r"""Invalid catch arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidCodePoint = messageInvalidCodePoint;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidCodePoint = const MessageCode(
+    "InvalidCodePoint",
+    analyzerCodes: <String>["INVALID_CODE_POINT"],
+    message:
+        r"""The escape sequence starting with '\u' isn't a valid code point.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateInvalidContinueTarget =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Can't continue at '#name'.""",
+        withArguments: _withArgumentsInvalidContinueTarget);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsInvalidContinueTarget(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvalidContinueTarget,
+      message: """Can't continue at '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidHexEscape = messageInvalidHexEscape;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidHexEscape = const MessageCode(
+    "InvalidHexEscape",
+    index: 40,
+    message:
+        r"""An escape sequence starting with '\x' must be followed by 2 hexadecimal digits.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidInitializer = messageInvalidInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidInitializer = const MessageCode(
+    "InvalidInitializer",
+    index: 90,
+    message: r"""Not a valid initializer.""",
+    tip: r"""To initialize a field, use the syntax 'name = value'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidInlineFunctionType =
+    messageInvalidInlineFunctionType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidInlineFunctionType = const MessageCode(
+    "InvalidInlineFunctionType",
+    analyzerCodes: <String>["INVALID_INLINE_FUNCTION_TYPE"],
+    message:
+        r"""Inline function types cannot be used for parameters in a generic function type.""",
+    tip:
+        r"""Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateInvalidOperator =
+    const Template<Message Function(Token token)>(
+        messageTemplate:
+            r"""The string '#lexeme' isn't a user-definable operator.""",
+        withArguments: _withArgumentsInvalidOperator);
+
+// 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);
+
+// 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});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_, String string)>
+    templateInvalidPackageUri =
+    const Template<Message Function(Uri uri_, String string)>(
+        messageTemplate: r"""Invalid package URI '#uri':
+  #string.""", withArguments: _withArgumentsInvalidPackageUri);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeInvalidPackageUri,
+      message: """Invalid package URI '${uri}':
+  ${string}.""", arguments: {'uri': uri_, 'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidSuperInInitializer =
+    messageInvalidSuperInInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidSuperInInitializer = const MessageCode(
+    "InvalidSuperInInitializer",
+    index: 47,
+    message:
+        r"""Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidSyncModifier = messageInvalidSyncModifier;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidSyncModifier = const MessageCode(
+    "InvalidSyncModifier",
+    analyzerCodes: <String>["MISSING_STAR_AFTER_SYNC"],
+    message: r"""Invalid modifier 'sync'.""",
+    tip: r"""Try replacing 'sync' with 'sync*'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidThisInInitializer = messageInvalidThisInInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidThisInInitializer = const MessageCode(
+    "InvalidThisInInitializer",
+    index: 65,
+    message:
+        r"""Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String string2,
+        String
+            name2)> templateInvalidTypeVariableInSupertype = const Template<
+        Message Function(String name, String string2, String name2)>(
+    messageTemplate:
+        r"""Can't use implicitly 'out' variable '#name' in an '#string2' position in supertype '#name2'.""",
+    withArguments: _withArgumentsInvalidTypeVariableInSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String string2, String name2)>
+    codeInvalidTypeVariableInSupertype =
+    const Code<Message Function(String name, String string2, String name2)>(
+  "InvalidTypeVariableInSupertype",
+  templateInvalidTypeVariableInSupertype,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidTypeVariableInSupertype(
+    String name, String string2, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string2.isEmpty) throw 'No string provided';
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeInvalidTypeVariableInSupertype,
+      message:
+          """Can't use implicitly 'out' variable '${name}' in an '${string2}' position in supertype '${name2}'.""",
+      arguments: {'name': name, 'string2': string2, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(
+            String string, String name, String string2, String name2)>
+    templateInvalidTypeVariableInSupertypeWithVariance = const Template<
+            Message Function(
+                String string, String name, String string2, String name2)>(
+        messageTemplate:
+            r"""Can't use '#string' type variable '#name' in an '#string2' position in supertype '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidTypeVariableInSupertypeWithVariance);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            String string, String name, String string2, String name2)>
+    codeInvalidTypeVariableInSupertypeWithVariance = const Code<
+        Message Function(
+            String string, String name, String string2, String name2)>(
+  "InvalidTypeVariableInSupertypeWithVariance",
+  templateInvalidTypeVariableInSupertypeWithVariance,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidTypeVariableInSupertypeWithVariance(
+    String string, String name, String string2, String name2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string2.isEmpty) throw 'No string provided';
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeInvalidTypeVariableInSupertypeWithVariance,
+      message:
+          """Can't use '${string}' type variable '${name}' in an '${string2}' position in supertype '${name2}'.""",
+      arguments: {
+        'string': string,
+        'name': name,
+        'string2': string2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String name,
+        String
+            string2)> templateInvalidTypeVariableVariancePosition = const Template<
+        Message Function(String string, String name, String string2)>(
+    messageTemplate:
+        r"""Can't use '#string' type variable '#name' in an '#string2' position.""",
+    withArguments: _withArgumentsInvalidTypeVariableVariancePosition);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String name, String string2)>
+    codeInvalidTypeVariableVariancePosition =
+    const Code<Message Function(String string, String name, String string2)>(
+  "InvalidTypeVariableVariancePosition",
+  templateInvalidTypeVariableVariancePosition,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidTypeVariableVariancePosition(
+    String string, String name, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeInvalidTypeVariableVariancePosition,
+      message:
+          """Can't use '${string}' type variable '${name}' in an '${string2}' position.""",
+      arguments: {'string': string, 'name': name, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String name, String string2)>
+    templateInvalidTypeVariableVariancePositionInReturnType = const Template<
+            Message Function(String string, String name, String string2)>(
+        messageTemplate:
+            r"""Can't use '#string' type variable '#name' in an '#string2' position in the return type.""",
+        withArguments:
+            _withArgumentsInvalidTypeVariableVariancePositionInReturnType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String name, String string2)>
+    codeInvalidTypeVariableVariancePositionInReturnType =
+    const Code<Message Function(String string, String name, String string2)>(
+  "InvalidTypeVariableVariancePositionInReturnType",
+  templateInvalidTypeVariableVariancePositionInReturnType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidTypeVariableVariancePositionInReturnType(
+    String string, String name, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeInvalidTypeVariableVariancePositionInReturnType,
+      message:
+          """Can't use '${string}' type variable '${name}' in an '${string2}' position in the return type.""",
+      arguments: {'string': string, 'name': name, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidUnicodeEscape = messageInvalidUnicodeEscape;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidUnicodeEscape = const MessageCode(
+    "InvalidUnicodeEscape",
+    index: 38,
+    message:
+        r"""An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidUseOfNullAwareAccess =
+    messageInvalidUseOfNullAwareAccess;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidUseOfNullAwareAccess = const MessageCode(
+    "InvalidUseOfNullAwareAccess",
+    analyzerCodes: <String>["INVALID_USE_OF_NULL_AWARE_ACCESS"],
+    message: r"""Cannot use '?.' here.""",
+    tip: r"""Try using '.'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInvalidVoid = messageInvalidVoid;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInvalidVoid = const MessageCode("InvalidVoid",
+    analyzerCodes: <String>["EXPECTED_TYPE_NAME"],
+    message: r"""Type 'void' can't be used here.""",
+    tip:
+        r"""Try removing 'void' keyword or replace it with 'var', 'final', or a type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateInvokeNonFunction =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""'#name' isn't a function or method and can't be invoked.""",
+        withArguments: _withArgumentsInvokeNonFunction);
+
+// 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,
+        analyzerCodes: <String>["INVOCATION_OF_NON_FUNCTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvokeNonFunction(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvokeNonFunction,
+      message: """'${name}' isn't a function or method and can't be invoked.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateLabelNotFound = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""Can't find label '#name'.""",
+    tipTemplate:
+        r"""Try defining the label, or correcting the name to match an existing label.""",
+    withArguments: _withArgumentsLabelNotFound);
+
+// 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,
+        analyzerCodes: <String>["LABEL_UNDEFINED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsLabelNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeLabelNotFound,
+      message: """Can't find label '${name}'.""",
+      tip:
+          """Try defining the label, or correcting the name to match an existing label.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeLanguageVersionInvalidInDotPackages =
+    messageLanguageVersionInvalidInDotPackages;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageLanguageVersionInvalidInDotPackages = const MessageCode(
+    "LanguageVersionInvalidInDotPackages",
+    message:
+        r"""The language version is not specified correctly in the .packages file.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeLanguageVersionMismatchInPart =
+    messageLanguageVersionMismatchInPart;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageLanguageVersionMismatchInPart = const MessageCode(
+    "LanguageVersionMismatchInPart",
+    message:
+        r"""The language version override has to be the same in the library and its part(s).""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int count,
+        int
+            count2)> templateLanguageVersionTooHigh = const Template<
+        Message Function(int count, int count2)>(
+    messageTemplate:
+        r"""The specified language version is too high. The highest supported language version is #count.#count2.""",
+    withArguments: _withArgumentsLanguageVersionTooHigh);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  return new Message(codeLanguageVersionTooHigh,
+      message:
+          """The specified language version is too high. The highest supported language version is ${count}.${count2}.""",
+      arguments: {'count': count, 'count2': count2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeLibraryDirectiveNotFirst = messageLibraryDirectiveNotFirst;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageLibraryDirectiveNotFirst = const MessageCode(
+    "LibraryDirectiveNotFirst",
+    index: 37,
+    message:
+        r"""The library directive must appear before all other directives.""",
+    tip: r"""Try moving the library directive before any other directives.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeListLiteralTooManyTypeArguments =
+    messageListLiteralTooManyTypeArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageListLiteralTooManyTypeArguments = const MessageCode(
+    "ListLiteralTooManyTypeArguments",
+    analyzerCodes: <String>["EXPECTED_ONE_LIST_TYPE_ARGUMENTS"],
+    message: r"""List literal requires exactly one type argument.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(Uri uri_)> templateLoadLibraryHidesMember = const Template<
+        Message Function(Uri uri_)>(
+    messageTemplate:
+        r"""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.""",
+    tipTemplate: r"""Try to rename or hide the member.""",
+    withArguments: _withArgumentsLoadLibraryHidesMember);
+
+// 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,
+        severity: Severity.ignored);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsLoadLibraryHidesMember(Uri 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.""",
+      tip: """Try to rename or hide the member.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeLoadLibraryTakesNoArguments =
+    messageLoadLibraryTakesNoArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageLoadLibraryTakesNoArguments = const MessageCode(
+    "LoadLibraryTakesNoArguments",
+    analyzerCodes: <String>["LOAD_LIBRARY_TAKES_NO_ARGUMENTS"],
+    message: r"""'loadLibrary' takes no arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_)>
+    templateLocalDefinitionHidesExport =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate:
+            r"""Local definition of '#name' hides export from '#uri'.""",
+        withArguments: _withArgumentsLocalDefinitionHidesExport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_)>
+    codeLocalDefinitionHidesExport =
+    const Code<Message Function(String name, Uri uri_)>(
+        "LocalDefinitionHidesExport", templateLocalDefinitionHidesExport,
+        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_);
+  return new Message(codeLocalDefinitionHidesExport,
+      message: """Local definition of '${name}' hides export from '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_)>
+    templateLocalDefinitionHidesImport =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate:
+            r"""Local definition of '#name' hides import from '#uri'.""",
+        withArguments: _withArgumentsLocalDefinitionHidesImport);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_)>
+    codeLocalDefinitionHidesImport =
+    const Code<Message Function(String name, Uri uri_)>(
+        "LocalDefinitionHidesImport", templateLocalDefinitionHidesImport,
+        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_);
+  return new Message(codeLocalDefinitionHidesImport,
+      message: """Local definition of '${name}' hides import from '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMapLiteralTypeArgumentMismatch =
+    messageMapLiteralTypeArgumentMismatch;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMapLiteralTypeArgumentMismatch = const MessageCode(
+    "MapLiteralTypeArgumentMismatch",
+    analyzerCodes: <String>["EXPECTED_TWO_MAP_TYPE_ARGUMENTS"],
+    message: r"""A map literal requires exactly two type arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMemberWithSameNameAsClass =
+    messageMemberWithSameNameAsClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMemberWithSameNameAsClass = const MessageCode(
+    "MemberWithSameNameAsClass",
+    message:
+        r"""A class member can't have the same name as the enclosing class.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMetadataTypeArguments = messageMetadataTypeArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMetadataTypeArguments = const MessageCode(
+    "MetadataTypeArguments",
+    index: 91,
+    message: r"""An annotation (metadata) can't use type arguments.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateMethodNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Method not found: '#name'.""",
+        withArguments: _withArgumentsMethodNotFound);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_METHOD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMethodNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeMethodNotFound,
+      message: """Method not found: '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingArgumentList = messageMissingArgumentList;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingArgumentList = const MessageCode(
+    "MissingArgumentList",
+    message: r"""Constructor invocations must have an argument list.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingAssignableSelector =
+    messageMissingAssignableSelector;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingAssignableSelector = const MessageCode(
+    "MissingAssignableSelector",
+    index: 35,
+    message: r"""Missing selector such as '.identifier' or '[0]'.""",
+    tip: r"""Try adding a selector.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingAssignmentInInitializer =
+    messageMissingAssignmentInInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingAssignmentInInitializer = const MessageCode(
+    "MissingAssignmentInInitializer",
+    index: 34,
+    message: r"""Expected an assignment after the field name.""",
+    tip: r"""To initialize a field, use the syntax 'name = value'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingConstFinalVarOrType =
+    messageMissingConstFinalVarOrType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingConstFinalVarOrType = const MessageCode(
+    "MissingConstFinalVarOrType",
+    index: 33,
+    message:
+        r"""Variables must be declared using the keywords 'const', 'final', 'var' or a type name.""",
+    tip:
+        r"""Try adding the name of the type of the variable or the keyword 'var'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingExplicitConst = messageMissingExplicitConst;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingExplicitConst = const MessageCode(
+    "MissingExplicitConst",
+    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
+    message: r"""Constant expression expected.""",
+    tip: r"""Try inserting 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(int count)>
+    templateMissingExplicitTypeArguments =
+    const Template<Message Function(int count)>(
+        messageTemplate: r"""No type arguments provided, #count possible.""",
+        withArguments: _withArgumentsMissingExplicitTypeArguments);
+
+// 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,
+        severity: Severity.ignored);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMissingExplicitTypeArguments(int count) {
+  if (count == null) throw 'No count provided';
+  return new Message(codeMissingExplicitTypeArguments,
+      message: """No type arguments provided, ${count} possible.""",
+      arguments: {'count': count});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingExponent = messageMissingExponent;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingExponent = const MessageCode("MissingExponent",
+    analyzerCodes: <String>["MISSING_DIGIT"],
+    message:
+        r"""Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).""",
+    tip:
+        r"""Make sure there is an exponent, and remove any whitespace before it.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingExpressionInThrow = messageMissingExpressionInThrow;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingExpressionInThrow = const MessageCode(
+    "MissingExpressionInThrow",
+    index: 32,
+    message: r"""Missing expression after 'throw'.""",
+    tip:
+        r"""Add an expression after 'throw' or use 'rethrow' to throw a caught exception""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingFunctionParameters =
+    messageMissingFunctionParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingFunctionParameters = const MessageCode(
+    "MissingFunctionParameters",
+    analyzerCodes: <String>["MISSING_FUNCTION_PARAMETERS"],
+    message:
+        r"""A function declaration needs an explicit list of parameters.""",
+    tip: r"""Try adding a parameter list to the function declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateMissingImplementationCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' is defined here.""",
+        withArguments: _withArgumentsMissingImplementationCause);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMissingImplementationCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeMissingImplementationCause,
+      message: """'${name}' is defined here.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        List<String>
+            _names)> templateMissingImplementationNotAbstract = const Template<
+        Message Function(String name, List<String> _names)>(
+    messageTemplate:
+        r"""The non-abstract class '#name' is missing implementations for these members:
+#names""",
+    tipTemplate: r"""Try to either
+ - provide an implementation,
+ - inherit an implementation from a superclass or mixin,
+ - mark the class as abstract, or
+ - provide a 'noSuchMethod' implementation.
+""",
+    withArguments: _withArgumentsMissingImplementationNotAbstract);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, List<String> _names)>
+    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.
+Message _withArgumentsMissingImplementationNotAbstract(
+    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(codeMissingImplementationNotAbstract,
+      message:
+          """The non-abstract class '${name}' is missing implementations for these members:
+${names}""",
+      tip: """Try to either
+ - provide an implementation,
+ - inherit an implementation from a superclass or mixin,
+ - mark the class as abstract, or
+ - provide a 'noSuchMethod' implementation.
+""",
+      arguments: {'name': name, 'names': _names});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingInput = messageMissingInput;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingInput = const MessageCode("MissingInput",
+    message: r"""No input file provided to the compiler.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingMain = messageMissingMain;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingMain = const MessageCode("MissingMain",
+    message: r"""No 'main' method found.""",
+    tip: r"""Try adding a method named 'main' to your program.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingMethodParameters = messageMissingMethodParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingMethodParameters = const MessageCode(
+    "MissingMethodParameters",
+    analyzerCodes: <String>["MISSING_METHOD_PARAMETERS"],
+    message: r"""A method declaration needs an explicit list of parameters.""",
+    tip: r"""Try adding a parameter list to the method declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingOperatorKeyword = messageMissingOperatorKeyword;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingOperatorKeyword = const MessageCode(
+    "MissingOperatorKeyword",
+    index: 31,
+    message:
+        r"""Operator declarations must be preceded by the keyword 'operator'.""",
+    tip: r"""Try adding the keyword 'operator'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(Uri uri_)> templateMissingPartOf = const Template<
+        Message Function(Uri uri_)>(
+    messageTemplate:
+        r"""Can't use '#uri' as a part, because it has no 'part of' declaration.""",
+    withArguments: _withArgumentsMissingPartOf);
+
+// 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,
+        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_);
+  return new Message(codeMissingPartOf,
+      message:
+          """Can't use '${uri}' as a part, because it has no 'part of' declaration.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingPrefixInDeferredImport =
+    messageMissingPrefixInDeferredImport;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingPrefixInDeferredImport = const MessageCode(
+    "MissingPrefixInDeferredImport",
+    index: 30,
+    message: r"""Deferred imports should have a prefix.""",
+    tip: r"""Try adding a prefix to the import by adding an 'as' clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingTypedefParameters = messageMissingTypedefParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingTypedefParameters = const MessageCode(
+    "MissingTypedefParameters",
+    analyzerCodes: <String>["MISSING_TYPEDEF_PARAMETERS"],
+    message: r"""A typedef needs an explicit list of parameters.""",
+    tip: r"""Try adding a parameter list to the typedef.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMixinDeclaresConstructor = messageMixinDeclaresConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMixinDeclaresConstructor = const MessageCode(
+    "MixinDeclaresConstructor",
+    index: 95,
+    message: r"""Mixins can't declare constructors.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateModifierOutOfOrder = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""The modifier '#string' should be before the modifier '#string2'.""",
+    tipTemplate: r"""Try re-ordering the modifiers.""",
+    withArguments: _withArgumentsModifierOutOfOrder);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeModifierOutOfOrder =
+    const Code<Message Function(String string, String string2)>(
+        "ModifierOutOfOrder", templateModifierOutOfOrder,
+        index: 56);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsModifierOutOfOrder(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeModifierOutOfOrder,
+      message:
+          """The modifier '${string}' should be before the modifier '${string2}'.""",
+      tip: """Try re-ordering the modifiers.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMoreThanOneSuperOrThisInitializer =
+    messageMoreThanOneSuperOrThisInitializer;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMoreThanOneSuperOrThisInitializer = const MessageCode(
+    "MoreThanOneSuperOrThisInitializer",
+    analyzerCodes: <String>["SUPER_IN_REDIRECTING_CONSTRUCTOR"],
+    message: r"""Can't have more than one 'super' or 'this' initializer.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleExtends = messageMultipleExtends;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleExtends = const MessageCode("MultipleExtends",
+    index: 28,
+    message: r"""Each class definition can have at most one extends clause.""",
+    tip:
+        r"""Try choosing one superclass and define your class to implement (or mix in) the others.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleImplements = messageMultipleImplements;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleImplements = const MessageCode(
+    "MultipleImplements",
+    analyzerCodes: <String>["MULTIPLE_IMPLEMENTS_CLAUSES"],
+    message:
+        r"""Each class definition can have at most one implements clause.""",
+    tip:
+        r"""Try combining all of the implements clauses into a single clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleLibraryDirectives =
+    messageMultipleLibraryDirectives;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleLibraryDirectives = const MessageCode(
+    "MultipleLibraryDirectives",
+    index: 27,
+    message: r"""Only one library directive may be declared in a file.""",
+    tip: r"""Try removing all but one of the library directives.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleOnClauses = messageMultipleOnClauses;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleOnClauses = const MessageCode(
+    "MultipleOnClauses",
+    index: 26,
+    message: r"""Each mixin definition can have at most one on clause.""",
+    tip: r"""Try combining all of the on clauses into a single clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleVarianceModifiers =
+    messageMultipleVarianceModifiers;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleVarianceModifiers = const MessageCode(
+    "MultipleVarianceModifiers",
+    index: 97,
+    message: r"""Each type parameter can have at most one variance modifier.""",
+    tip: r"""Use at most one of the 'in', 'out', or 'inout' modifiers.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMultipleWith = messageMultipleWith;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMultipleWith = const MessageCode("MultipleWith",
+    index: 24,
+    message: r"""Each class definition can have at most one with clause.""",
+    tip: r"""Try combining all of the with clauses into a single clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNamedFunctionExpression = messageNamedFunctionExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNamedFunctionExpression = const MessageCode(
+    "NamedFunctionExpression",
+    analyzerCodes: <String>["NAMED_FUNCTION_EXPRESSION"],
+    message: r"""A function expression can't have a name.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateNamedMixinOverride = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""The mixin application class '#name' introduces an erroneous override of '#name2'.""",
+    withArguments: _withArgumentsNamedMixinOverride);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsNamedMixinOverride(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeNamedMixinOverride,
+      message:
+          """The mixin application class '${name}' introduces an erroneous override of '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNativeClauseShouldBeAnnotation =
+    messageNativeClauseShouldBeAnnotation;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNativeClauseShouldBeAnnotation = const MessageCode(
+    "NativeClauseShouldBeAnnotation",
+    index: 23,
+    message: r"""Native clause in this form is deprecated.""",
+    tip:
+        r"""Try removing this native clause and adding @native() or @native('native-name') before the declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(Token token)> templateNoFormals = const Template<
+        Message Function(Token token)>(
+    messageTemplate: r"""A function should have formal parameters.""",
+    tipTemplate:
+        r"""Try adding '()' after '#lexeme', or add 'get' before '#lexeme' to declare a getter.""",
+    withArguments: _withArgumentsNoFormals);
+
+// 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,
+        analyzerCodes: <String>["MISSING_FUNCTION_PARAMETERS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNoFormals(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeNoFormals,
+      message: """A function should have formal parameters.""",
+      tip:
+          """Try adding '()' after '${lexeme}', or add 'get' before '${lexeme}' to declare a getter.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateNoSuchNamedParameter =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""No named parameter with the name '#name'.""",
+        withArguments: _withArgumentsNoSuchNamedParameter);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_NAMED_PARAMETER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNoSuchNamedParameter(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNoSuchNamedParameter,
+      message: """No named parameter with the name '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNoUnnamedConstructorInObject =
+    messageNoUnnamedConstructorInObject;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNoUnnamedConstructorInObject = const MessageCode(
+    "NoUnnamedConstructorInObject",
+    message: r"""'Object' has no unnamed constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String character,
+        int
+            codePoint)> templateNonAsciiIdentifier = const Template<
+        Message Function(String character, int codePoint)>(
+    messageTemplate:
+        r"""The non-ASCII character '#character' (#unicode) can't be used in identifiers, only in strings and comments.""",
+    tipTemplate:
+        r"""Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).""",
+    withArguments: _withArgumentsNonAsciiIdentifier);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String character, int codePoint)>
+    codeNonAsciiIdentifier =
+    const Code<Message Function(String character, int codePoint)>(
+        "NonAsciiIdentifier", templateNonAsciiIdentifier,
+        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonAsciiIdentifier(String character, int codePoint) {
+  if (character.runes.length != 1) throw "Not a character '${character}'";
+  String unicode =
+      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
+  return new Message(codeNonAsciiIdentifier,
+      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});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int
+            codePoint)> templateNonAsciiWhitespace = const Template<
+        Message Function(int codePoint)>(
+    messageTemplate:
+        r"""The non-ASCII space character #unicode can only be used in strings and comments.""",
+    withArguments: _withArgumentsNonAsciiWhitespace);
+
+// 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,
+        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonAsciiWhitespace(int codePoint) {
+  String unicode =
+      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
+  return new Message(codeNonAsciiWhitespace,
+      message:
+          """The non-ASCII space character ${unicode} can only be used in strings and comments.""",
+      arguments: {'codePoint': codePoint});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonConstConstructor = messageNonConstConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonConstConstructor = const MessageCode(
+    "NonConstConstructor",
+    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
+    message:
+        r"""Cannot invoke a non-'const' constructor where a const expression is expected.""",
+    tip: r"""Try using a constructor or factory that is 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonConstFactory = messageNonConstFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonConstFactory = const MessageCode("NonConstFactory",
+    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
+    message:
+        r"""Cannot invoke a non-'const' factory where a const expression is expected.""",
+    tip: r"""Try using a constructor or factory that is 'const'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonInstanceTypeVariableUse =
+    messageNonInstanceTypeVariableUse;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonInstanceTypeVariableUse = const MessageCode(
+    "NonInstanceTypeVariableUse",
+    analyzerCodes: <String>["TYPE_PARAMETER_REFERENCED_BY_STATIC"],
+    message: r"""Can only use type variables in instance methods.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonNullAwareSpreadIsNull = messageNonNullAwareSpreadIsNull;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonNullAwareSpreadIsNull = const MessageCode(
+    "NonNullAwareSpreadIsNull",
+    message: r"""Can't spread a value with static type Null.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNonPartOfDirectiveInPart = messageNonPartOfDirectiveInPart;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNonPartOfDirectiveInPart = const MessageCode(
+    "NonPartOfDirectiveInPart",
+    analyzerCodes: <String>["NON_PART_OF_DIRECTIVE_IN_PART"],
+    message: r"""The part-of directive must be the only directive in a part.""",
+    tip:
+        r"""Try removing the other directives, or moving them to the library for which this is a part.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateNonSimpleBoundViaReference =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Bound of this variable references raw type '#name'.""",
+        withArguments: _withArgumentsNonSimpleBoundViaReference);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonSimpleBoundViaReference(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNonSimpleBoundViaReference,
+      message: """Bound of this variable references raw type '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateNonSimpleBoundViaVariable = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Bound of this variable references variable '#name' from the same declaration.""",
+    withArguments: _withArgumentsNonSimpleBoundViaVariable);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNonSimpleBoundViaVariable(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNonSimpleBoundViaVariable,
+      message:
+          """Bound of this variable references variable '${name}' from the same declaration.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNotAConstantExpression = messageNotAConstantExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNotAConstantExpression = const MessageCode(
+    "NotAConstantExpression",
+    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
+    message: r"""Not a constant expression.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateNotAPrefixInTypeAnnotation = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""'#name.#name2' can't be used as a type because '#name' doesn't refer to an import prefix.""",
+    withArguments: _withArgumentsNotAPrefixInTypeAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeNotAPrefixInTypeAnnotation =
+    const Code<Message Function(String name, String name2)>(
+        "NotAPrefixInTypeAnnotation", templateNotAPrefixInTypeAnnotation,
+        analyzerCodes: <String>["NOT_A_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNotAPrefixInTypeAnnotation(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeNotAPrefixInTypeAnnotation,
+      message:
+          """'${name}.${name2}' can't be used as a type because '${name}' doesn't refer to an import prefix.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateNotAType =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""'#name' isn't a type.""",
+        withArguments: _withArgumentsNotAType);
+
+// 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,
+        analyzerCodes: <String>["NOT_A_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNotAType(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeNotAType,
+      message: """'${name}' isn't a type.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNotATypeContext = messageNotATypeContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNotATypeContext = const MessageCode("NotATypeContext",
+    severity: Severity.context, message: r"""This isn't a type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNotAnLvalue = messageNotAnLvalue;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNotAnLvalue = const MessageCode("NotAnLvalue",
+    analyzerCodes: <String>["NOT_AN_LVALUE"],
+    message: r"""Can't assign to this.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateNotBinaryOperator =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""'#lexeme' isn't a binary operator.""",
+        withArguments: _withArgumentsNotBinaryOperator);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsNotBinaryOperator(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeNotBinaryOperator,
+      message: """'${lexeme}' isn't a binary operator.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateNotConstantExpression =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""#string is not a constant expression.""",
+        withArguments: _withArgumentsNotConstantExpression);
+
+// 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,
+        analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsNotConstantExpression(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeNotConstantExpression,
+      message: """${string} is not a constant expression.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNullAwareCascadeOutOfOrder =
+    messageNullAwareCascadeOutOfOrder;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNullAwareCascadeOutOfOrder = const MessageCode(
+    "NullAwareCascadeOutOfOrder",
+    index: 96,
+    message:
+        r"""The '?..' cascade operator must be first in the cascade sequence.""",
+    tip:
+        r"""Try moving the '?..' operator to be the first cascade operator in the sequence.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeObjectExtends = messageObjectExtends;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageObjectExtends = const MessageCode("ObjectExtends",
+    message: r"""The class 'Object' can't have a superclass.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeObjectImplements = messageObjectImplements;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageObjectImplements = const MessageCode(
+    "ObjectImplements",
+    message: r"""The class 'Object' can't implement anything.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeObjectMixesIn = messageObjectMixesIn;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageObjectMixesIn = const MessageCode("ObjectMixesIn",
+    message: r"""The class 'Object' can't use mixins.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeOnlyTry = messageOnlyTry;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageOnlyTry = const MessageCode("OnlyTry",
+    index: 20,
+    message:
+        r"""A try block must be followed by an 'on', 'catch', or 'finally' clause.""",
+    tip:
+        r"""Try adding either a catch or finally clause, or remove the try statement.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateOperatorMinusParameterMismatch = const Template<
+        Message Function(String name)>(
+    messageTemplate: r"""Operator '#name' should have zero or one parameter.""",
+    tipTemplate:
+        r"""With zero parameters, it has the syntactic form '-a', formally known as 'unary-'. With one parameter, it has the syntactic form 'a - b', formally known as '-'.""",
+    withArguments: _withArgumentsOperatorMinusParameterMismatch);
+
+// 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"
+]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOperatorMinusParameterMismatch(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeOperatorMinusParameterMismatch,
+      message: """Operator '${name}' should have zero or one parameter.""",
+      tip:
+          """With zero parameters, it has the syntactic form '-a', formally known as 'unary-'. With one parameter, it has the syntactic form 'a - b', formally known as '-'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateOperatorParameterMismatch0 =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Operator '#name' shouldn't have any parameters.""",
+        withArguments: _withArgumentsOperatorParameterMismatch0);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsOperatorParameterMismatch0(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeOperatorParameterMismatch0,
+      message: """Operator '${name}' shouldn't have any parameters.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateOperatorParameterMismatch1 =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Operator '#name' should have exactly one parameter.""",
+        withArguments: _withArgumentsOperatorParameterMismatch1);
+
+// 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,
+        analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOperatorParameterMismatch1(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeOperatorParameterMismatch1,
+      message: """Operator '${name}' should have exactly one parameter.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateOperatorParameterMismatch2 =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Operator '#name' should have exactly two parameters.""",
+        withArguments: _withArgumentsOperatorParameterMismatch2);
+
+// 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,
+        analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOperatorParameterMismatch2(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeOperatorParameterMismatch2,
+      message: """Operator '${name}' should have exactly two parameters.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeOperatorWithOptionalFormals =
+    messageOperatorWithOptionalFormals;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageOperatorWithOptionalFormals = const MessageCode(
+    "OperatorWithOptionalFormals",
+    message: r"""An operator can't have optional parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateOverriddenMethodCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""This is the overridden method ('#name').""",
+        withArguments: _withArgumentsOverriddenMethodCause);
+
+// 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,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverriddenMethodCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeOverriddenMethodCause,
+      message: """This is the overridden method ('${name}').""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateOverrideFewerNamedArguments = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""The method '#name' has fewer named arguments than those of overridden method '#name2'.""",
+    withArguments: _withArgumentsOverrideFewerNamedArguments);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeOverrideFewerNamedArguments =
+    const Code<Message Function(String name, String name2)>(
+        "OverrideFewerNamedArguments", templateOverrideFewerNamedArguments,
+        analyzerCodes: <String>["INVALID_OVERRIDE_NAMED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideFewerNamedArguments(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeOverrideFewerNamedArguments,
+      message:
+          """The method '${name}' has fewer named arguments than those of overridden method '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateOverrideFewerPositionalArguments = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""The method '#name' has fewer positional arguments than those of overridden method '#name2'.""",
+    withArguments: _withArgumentsOverrideFewerPositionalArguments);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    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.
+Message _withArgumentsOverrideFewerPositionalArguments(
+    String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeOverrideFewerPositionalArguments,
+      message:
+          """The method '${name}' has fewer positional arguments than those of overridden method '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String name2,
+        String
+            name3)> templateOverrideMismatchNamedParameter = const Template<
+        Message Function(String name, String name2, String name3)>(
+    messageTemplate:
+        r"""The method '#name' doesn't have the named parameter '#name2' of overridden method '#name3'.""",
+    withArguments: _withArgumentsOverrideMismatchNamedParameter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2, String name3)>
+    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.
+Message _withArgumentsOverrideMismatchNamedParameter(
+    String name, String name2, String name3) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  return new Message(codeOverrideMismatchNamedParameter,
+      message:
+          """The method '${name}' doesn't have the named parameter '${name2}' of overridden method '${name3}'.""",
+      arguments: {'name': name, 'name2': name2, 'name3': name3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateOverrideMoreRequiredArguments = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""The method '#name' has more required arguments than those of overridden method '#name2'.""",
+    withArguments: _withArgumentsOverrideMoreRequiredArguments);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeOverrideMoreRequiredArguments =
+    const Code<Message Function(String name, String name2)>(
+        "OverrideMoreRequiredArguments", templateOverrideMoreRequiredArguments,
+        analyzerCodes: <String>["INVALID_OVERRIDE_REQUIRED"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideMoreRequiredArguments(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeOverrideMoreRequiredArguments,
+      message:
+          """The method '${name}' has more required arguments than those of overridden method '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateOverrideTypeVariablesMismatch = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""Declared type variables of '#name' doesn't match those on overridden method '#name2'.""",
+    withArguments: _withArgumentsOverrideTypeVariablesMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    codeOverrideTypeVariablesMismatch =
+    const Code<Message Function(String name, String name2)>(
+        "OverrideTypeVariablesMismatch", templateOverrideTypeVariablesMismatch,
+        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideTypeVariablesMismatch(String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeOverrideTypeVariablesMismatch,
+      message:
+          """Declared type variables of '${name}' doesn't match those on overridden method '${name2}'.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(String name, Uri uri_)> templatePackageNotFound =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate:
+            r"""Could not resolve the package '#name' in '#uri'.""",
+        withArguments: _withArgumentsPackageNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codePackageNotFound,
+      message: """Could not resolve the package '${name}' in '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templatePackagesFileFormat =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Problem in packages configuration file: #string""",
+        withArguments: _withArgumentsPackagesFileFormat);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsPackagesFileFormat(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codePackagesFileFormat,
+      message: """Problem in packages configuration file: ${string}""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartExport = messagePartExport;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartExport = const MessageCode("PartExport",
+    analyzerCodes: <String>["EXPORT_OF_NON_LIBRARY"],
+    message:
+        r"""Can't export this file because it contains a 'part of' declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartExportContext = messagePartExportContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartExportContext = const MessageCode(
+    "PartExportContext",
+    severity: Severity.context,
+    message: r"""This is the file that can't be exported.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartInPart = messagePartInPart;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartInPart = const MessageCode("PartInPart",
+    analyzerCodes: <String>["NON_PART_OF_DIRECTIVE_IN_PART"],
+    message: r"""A file that's a part of a library can't have parts itself.""",
+    tip: r"""Try moving the 'part' declaration to the containing library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartInPartLibraryContext = messagePartInPartLibraryContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartInPartLibraryContext = const MessageCode(
+    "PartInPartLibraryContext",
+    severity: Severity.context,
+    message: r"""This is the containing library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(Uri uri_)> templatePartOfInLibrary = const Template<
+        Message Function(Uri uri_)>(
+    messageTemplate:
+        r"""Can't import '#uri', because it has a 'part of' declaration.""",
+    tipTemplate:
+        r"""Try removing the 'part of' declaration, or using '#uri' as a part.""",
+    withArguments: _withArgumentsPartOfInLibrary);
+
+// 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,
+        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_);
+  return new Message(codePartOfInLibrary,
+      message:
+          """Can't import '${uri}', because it has a 'part of' declaration.""",
+      tip:
+          """Try removing the 'part of' declaration, or using '${uri}' as a part.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Uri uri_,
+        String name,
+        String
+            name2)> templatePartOfLibraryNameMismatch = const Template<
+        Message Function(Uri uri_, String name, String name2)>(
+    messageTemplate:
+        r"""Using '#uri' as part of '#name' but its 'part of' declaration says '#name2'.""",
+    withArguments: _withArgumentsPartOfLibraryNameMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Uri uri_, String name, String name2)>
+    codePartOfLibraryNameMismatch =
+    const Code<Message Function(Uri uri_, String name, String name2)>(
+        "PartOfLibraryNameMismatch", templatePartOfLibraryNameMismatch,
+        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_);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codePartOfLibraryNameMismatch,
+      message:
+          """Using '${uri}' as part of '${name}' but its 'part of' declaration says '${name2}'.""",
+      arguments: {'uri': uri_, 'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfSelf = messagePartOfSelf;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfSelf = const MessageCode("PartOfSelf",
+    analyzerCodes: <String>["PART_OF_NON_PART"],
+    message: r"""A file can't be a part of itself.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfTwice = messagePartOfTwice;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfTwice = const MessageCode("PartOfTwice",
+    index: 25,
+    message: r"""Only one part-of directive may be declared in a file.""",
+    tip: r"""Try removing all but one of the part-of directives.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfTwoLibraries = messagePartOfTwoLibraries;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfTwoLibraries = const MessageCode(
+    "PartOfTwoLibraries",
+    analyzerCodes: <String>["PART_OF_DIFFERENT_LIBRARY"],
+    message: r"""A file can't be part of more than one library.""",
+    tip:
+        r"""Try moving the shared declarations into the libraries, or into a new library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfTwoLibrariesContext =
+    messagePartOfTwoLibrariesContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfTwoLibrariesContext = const MessageCode(
+    "PartOfTwoLibrariesContext",
+    severity: Severity.context,
+    message: r"""Used as a part in this library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Uri uri_,
+        Uri uri2_,
+        Uri
+            uri3_)> templatePartOfUriMismatch = const Template<
+        Message Function(Uri uri_, Uri uri2_, Uri uri3_)>(
+    messageTemplate:
+        r"""Using '#uri' as part of '#uri2' but its 'part of' declaration says '#uri3'.""",
+    withArguments: _withArgumentsPartOfUriMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>
+    codePartOfUriMismatch =
+    const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>(
+        "PartOfUriMismatch", templatePartOfUriMismatch,
+        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_);
+  return new Message(codePartOfUriMismatch,
+      message:
+          """Using '${uri}' as part of '${uri2}' but its 'part of' declaration says '${uri3}'.""",
+      arguments: {'uri': uri_, 'uri2': uri2_, 'uri3': uri3_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Uri uri_,
+        Uri uri2_,
+        String
+            name)> templatePartOfUseUri = const Template<
+        Message Function(Uri uri_, Uri uri2_, String name)>(
+    messageTemplate:
+        r"""Using '#uri' as part of '#uri2' but its 'part of' declaration says '#name'.""",
+    tipTemplate:
+        r"""Try changing the 'part of' declaration to use a relative file name.""",
+    withArguments: _withArgumentsPartOfUseUri);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Uri uri_, Uri uri2_, String name)>
+    codePartOfUseUri =
+    const Code<Message Function(Uri uri_, Uri uri2_, String name)>(
+        "PartOfUseUri", templatePartOfUseUri,
+        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_);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codePartOfUseUri,
+      message:
+          """Using '${uri}' as part of '${uri2}' but its 'part of' declaration says '${name}'.""",
+      tip: """Try changing the 'part of' declaration to use a relative file name.""",
+      arguments: {'uri': uri_, 'uri2': uri2_, 'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOrphan = messagePartOrphan;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOrphan = const MessageCode("PartOrphan",
+    message: r"""This part doesn't have a containing library.""",
+    tip: r"""Try removing the 'part of' declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templatePartTwice =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""Can't use '#uri' as a part more than once.""",
+        withArguments: _withArgumentsPartTwice);
+
+// 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,
+        analyzerCodes: <String>["DUPLICATE_PART"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsPartTwice(Uri uri_) {
+  String uri = relativizeUri(uri_);
+  return new Message(codePartTwice,
+      message: """Can't use '${uri}' as a part more than once.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePatchClassOrigin = messagePatchClassOrigin;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePatchClassOrigin = const MessageCode(
+    "PatchClassOrigin",
+    severity: Severity.context,
+    message: r"""This is the origin class.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePatchClassTypeVariablesMismatch =
+    messagePatchClassTypeVariablesMismatch;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePatchClassTypeVariablesMismatch = const MessageCode(
+    "PatchClassTypeVariablesMismatch",
+    message:
+        r"""A patch class must have the same number of type variables as its origin class.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePatchDeclarationMismatch = messagePatchDeclarationMismatch;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePatchDeclarationMismatch = const MessageCode(
+    "PatchDeclarationMismatch",
+    message: r"""This patch doesn't match origin declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePatchDeclarationOrigin = messagePatchDeclarationOrigin;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePatchDeclarationOrigin = const MessageCode(
+    "PatchDeclarationOrigin",
+    severity: Severity.context,
+    message: r"""This is the origin declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_)>
+    templatePatchInjectionFailed =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate: r"""Can't inject '#name' into '#uri'.""",
+        tipTemplate: r"""Try adding '@patch'.""",
+        withArguments: _withArgumentsPatchInjectionFailed);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codePatchInjectionFailed,
+      message: """Can't inject '${name}' into '${uri}'.""",
+      tip: """Try adding '@patch'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePatchNonExternal = messagePatchNonExternal;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePatchNonExternal = const MessageCode(
+    "PatchNonExternal",
+    message:
+        r"""Can't apply this patch as its origin declaration isn't external.""",
+    tip: r"""Try adding 'external' to the origin declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePlatformPrivateLibraryAccess =
+    messagePlatformPrivateLibraryAccess;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePlatformPrivateLibraryAccess = const MessageCode(
+    "PlatformPrivateLibraryAccess",
+    analyzerCodes: <String>["IMPORT_INTERNAL_LIBRARY"],
+    message: r"""Can't access platform private library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePositionalAfterNamedArgument =
+    messagePositionalAfterNamedArgument;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePositionalAfterNamedArgument = const MessageCode(
+    "PositionalAfterNamedArgument",
+    analyzerCodes: <String>["POSITIONAL_AFTER_NAMED_ARGUMENT"],
+    message: r"""Place positional arguments before named arguments.""",
+    tip:
+        r"""Try moving the positional argument before the named arguments, or add a name to the argument.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePositionalParameterWithEquals =
+    messagePositionalParameterWithEquals;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePositionalParameterWithEquals = const MessageCode(
+    "PositionalParameterWithEquals",
+    analyzerCodes: <String>["WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER"],
+    message:
+        r"""Positional optional parameters can't use ':' to specify a default value.""",
+    tip: r"""Try replacing ':' with '='.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePrefixAfterCombinator = messagePrefixAfterCombinator;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePrefixAfterCombinator = const MessageCode(
+    "PrefixAfterCombinator",
+    index: 6,
+    message:
+        r"""The prefix ('as' clause) should come before any show/hide combinators.""",
+    tip: r"""Try moving the prefix before the combinators.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePrivateNamedParameter = messagePrivateNamedParameter;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePrivateNamedParameter = const MessageCode(
+    "PrivateNamedParameter",
+    analyzerCodes: <String>["PRIVATE_OPTIONAL_PARAMETER"],
+    message: r"""An optional named parameter can't start with '_'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRedirectingConstructorWithBody =
+    messageRedirectingConstructorWithBody;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRedirectingConstructorWithBody = const MessageCode(
+    "RedirectingConstructorWithBody",
+    index: 22,
+    message: r"""Redirecting constructors can't have a body.""",
+    tip:
+        r"""Try removing the body, or not making this a redirecting constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRedirectionInNonFactory = messageRedirectionInNonFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRedirectionInNonFactory = const MessageCode(
+    "RedirectionInNonFactory",
+    index: 21,
+    message: r"""Only factory constructor can specify '=' redirection.""",
+    tip:
+        r"""Try making this a factory constructor, or remove the redirection.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateRedirectionTargetNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Redirection constructor target not found: '#name'""",
+        withArguments: _withArgumentsRedirectionTargetNotFound);
+
+// 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,
+        analyzerCodes: <String>["REDIRECT_TO_MISSING_CONSTRUCTOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsRedirectionTargetNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeRedirectionTargetNotFound,
+      message: """Redirection constructor target not found: '${name}'""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRequiredParameterWithDefault =
+    messageRequiredParameterWithDefault;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRequiredParameterWithDefault = const MessageCode(
+    "RequiredParameterWithDefault",
+    analyzerCodes: <String>["NAMED_PARAMETER_OUTSIDE_GROUP"],
+    message: r"""Non-optional parameters can't have a default value.""",
+    tip:
+        r"""Try removing the default value or making the parameter optional.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeRethrowNotCatch = messageRethrowNotCatch;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageRethrowNotCatch = const MessageCode("RethrowNotCatch",
+    analyzerCodes: <String>["RETHROW_OUTSIDE_CATCH"],
+    message: r"""'rethrow' can only be used in catch clauses.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeReturnFromVoidFunction = messageReturnFromVoidFunction;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageReturnFromVoidFunction = const MessageCode(
+    "ReturnFromVoidFunction",
+    analyzerCodes: <String>["RETURN_OF_INVALID_TYPE"],
+    message: r"""Can't return a value from a void function.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeReturnTypeFunctionExpression =
+    messageReturnTypeFunctionExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageReturnTypeFunctionExpression = const MessageCode(
+    "ReturnTypeFunctionExpression",
+    message: r"""A function expression can't have a return type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeReturnWithoutExpression = messageReturnWithoutExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageReturnWithoutExpression = const MessageCode(
+    "ReturnWithoutExpression",
+    analyzerCodes: <String>["RETURN_WITHOUT_VALUE"],
+    severity: Severity.warning,
+    message: r"""Must explicitly return a value from a non-void function.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templateSdkRootNotFound =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""SDK root directory not found: #uri.""",
+        withArguments: _withArgumentsSdkRootNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codeSdkRootNotFound,
+      message: """SDK root directory not found: ${uri}.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Uri
+            uri_)> templateSdkSpecificationNotFound = const Template<
+        Message Function(Uri uri_)>(
+    messageTemplate: r"""SDK libraries specification not found: #uri.""",
+    tipTemplate:
+        r"""Normally, the specification is a file named 'libraries.json' in the Dart SDK install location.""",
+    withArguments: _withArgumentsSdkSpecificationNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codeSdkSpecificationNotFound,
+      message: """SDK libraries specification not found: ${uri}.""",
+      tip:
+          """Normally, the specification is a file named 'libraries.json' in the Dart SDK install location.""",
+      arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templateSdkSummaryNotFound =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""SDK summary not found: #uri.""",
+        withArguments: _withArgumentsSdkSummaryNotFound);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codeSdkSummaryNotFound,
+      message: """SDK summary not found: ${uri}.""", arguments: {'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSetLiteralTooManyTypeArguments =
+    messageSetLiteralTooManyTypeArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSetLiteralTooManyTypeArguments = const MessageCode(
+    "SetLiteralTooManyTypeArguments",
+    message: r"""A set literal requires exactly one type argument.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSetOrMapLiteralTooManyTypeArguments =
+    messageSetOrMapLiteralTooManyTypeArguments;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSetOrMapLiteralTooManyTypeArguments = const MessageCode(
+    "SetOrMapLiteralTooManyTypeArguments",
+    message:
+        r"""A set or map literal requires exactly one or two type arguments, respectively.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSetterNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Setter not found: '#name'.""",
+        withArguments: _withArgumentsSetterNotFound);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_SETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSetterNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSetterNotFound,
+      message: """Setter not found: '${name}'.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSetterNotSync = messageSetterNotSync;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSetterNotSync = const MessageCode("SetterNotSync",
+    analyzerCodes: <String>["INVALID_MODIFIER_ON_SETTER"],
+    message: r"""Setters can't use 'async', 'async*', or 'sync*'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSetterWithWrongNumberOfFormals =
+    messageSetterWithWrongNumberOfFormals;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSetterWithWrongNumberOfFormals = const MessageCode(
+    "SetterWithWrongNumberOfFormals",
+    analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER"],
+    message: r"""A setter should have exactly one formal parameter.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int count,
+        int count2,
+        num _num1,
+        num _num2,
+        num
+            _num3)> templateSourceBodySummary = const Template<
+        Message Function(
+            int count, int count2, num _num1, num _num2, num _num3)>(
+    messageTemplate:
+        r"""Built bodies for #count compilation units (#count2 bytes) in #num1%.3ms, that is,
+#num2%12.3 bytes/ms, and
+#num3%12.3 ms/compilation unit.""",
+    withArguments: _withArgumentsSourceBodySummary);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+    Message Function(int count, int count2, num _num1, num _num2,
+        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) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  if (_num1 == null) throw 'No number provided';
+  String num1 = _num1.toStringAsFixed(3);
+  if (_num2 == null) throw 'No number provided';
+  String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  if (_num3 == null) throw 'No number provided';
+  String num3 = _num3.toStringAsFixed(3).padLeft(12);
+  return new Message(codeSourceBodySummary,
+      message:
+          """Built bodies for ${count} compilation units (${count2} bytes) in ${num1}ms, that is,
+${num2} bytes/ms, and
+${num3} ms/compilation unit.""",
+      arguments: {
+        'count': count,
+        'count2': count2,
+        'num1': _num1,
+        'num2': _num2,
+        'num3': _num3
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int count,
+        int count2,
+        num _num1,
+        num _num2,
+        num
+            _num3)> templateSourceOutlineSummary = const Template<
+        Message Function(
+            int count, int count2, num _num1, num _num2, num _num3)>(
+    messageTemplate:
+        r"""Built outlines for #count compilation units (#count2 bytes) in #num1%.3ms, that is,
+#num2%12.3 bytes/ms, and
+#num3%12.3 ms/compilation unit.""",
+    withArguments: _withArgumentsSourceOutlineSummary);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+    Message Function(int count, int count2, num _num1, num _num2,
+        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) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  if (_num1 == null) throw 'No number provided';
+  String num1 = _num1.toStringAsFixed(3);
+  if (_num2 == null) throw 'No number provided';
+  String num2 = _num2.toStringAsFixed(3).padLeft(12);
+  if (_num3 == null) throw 'No number provided';
+  String num3 = _num3.toStringAsFixed(3).padLeft(12);
+  return new Message(codeSourceOutlineSummary,
+      message:
+          """Built outlines for ${count} compilation units (${count2} bytes) in ${num1}ms, that is,
+${num2} bytes/ms, and
+${num3} ms/compilation unit.""",
+      arguments: {
+        'count': count,
+        'count2': count2,
+        'num1': _num1,
+        'num2': _num2,
+        'num3': _num3
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadElement = messageSpreadElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadElement = const MessageCode("SpreadElement",
+    severity: Severity.context, message: r"""Iterable spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSpreadMapElement = messageSpreadMapElement;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSpreadMapElement = const MessageCode(
+    "SpreadMapElement",
+    severity: Severity.context,
+    message: r"""Map spread.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStackOverflow = messageStackOverflow;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStackOverflow = const MessageCode("StackOverflow",
+    index: 19,
+    message: r"""The file has too many nested expressions or statements.""",
+    tip: r"""Try simplifying the code.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticAndInstanceConflict =
+    messageStaticAndInstanceConflict;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticAndInstanceConflict = const MessageCode(
+    "StaticAndInstanceConflict",
+    analyzerCodes: <String>["CONFLICTING_STATIC_AND_INSTANCE"],
+    message: r"""This static member conflicts with an instance member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticAndInstanceConflictCause =
+    messageStaticAndInstanceConflictCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticAndInstanceConflictCause = const MessageCode(
+    "StaticAndInstanceConflictCause",
+    severity: Severity.context,
+    message: r"""This is the instance member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticConstructor = messageStaticConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticConstructor = const MessageCode(
+    "StaticConstructor",
+    index: 4,
+    message: r"""Constructors can't be static.""",
+    tip: r"""Try removing the keyword 'static'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticOperator = messageStaticOperator;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticOperator = const MessageCode("StaticOperator",
+    index: 17,
+    message: r"""Operators can't be static.""",
+    tip: r"""Try removing the keyword 'static'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSuperAsExpression = messageSuperAsExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSuperAsExpression = const MessageCode(
+    "SuperAsExpression",
+    analyzerCodes: <String>["SUPER_AS_EXPRESSION"],
+    message: r"""Can't use 'super' as an expression.""",
+    tip:
+        r"""To delegate a constructor to a super constructor, put the super call as an initializer.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSuperAsIdentifier = messageSuperAsIdentifier;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSuperAsIdentifier = const MessageCode(
+    "SuperAsIdentifier",
+    analyzerCodes: <String>["SUPER_AS_EXPRESSION"],
+    message: r"""Expected identifier, but got 'super'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSuperInitializerNotLast = messageSuperInitializerNotLast;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSuperInitializerNotLast = const MessageCode(
+    "SuperInitializerNotLast",
+    analyzerCodes: <String>["INVALID_SUPER_INVOCATION"],
+    message: r"""Can't have initializers after 'super'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSuperNullAware = messageSuperNullAware;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSuperNullAware = const MessageCode("SuperNullAware",
+    index: 18,
+    message:
+        r"""The operator '?.' cannot be used with 'super' because 'super' cannot be null.""",
+    tip: r"""Try replacing '?.' with '.'""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateSuperclassHasNoConstructor =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Superclass has no constructor named '#name'.""",
+        withArguments: _withArgumentsSuperclassHasNoConstructor);
+
+// 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,
+        analyzerCodes: <String>[
+      "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER",
+      "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSuperclassHasNoConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassHasNoConstructor,
+      message: """Superclass has no constructor named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateSuperclassHasNoDefaultConstructor = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""The superclass, '#name', has no unnamed constructor that takes no arguments.""",
+    withArguments: _withArgumentsSuperclassHasNoDefaultConstructor);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    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.
+Message _withArgumentsSuperclassHasNoDefaultConstructor(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassHasNoDefaultConstructor,
+      message:
+          """The superclass, '${name}', has no unnamed constructor that takes no arguments.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSuperclassHasNoGetter =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Superclass has no getter named '#name'.""",
+        withArguments: _withArgumentsSuperclassHasNoGetter);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_SUPER_GETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSuperclassHasNoGetter(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassHasNoGetter,
+      message: """Superclass has no getter named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSuperclassHasNoMethod =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Superclass has no method named '#name'.""",
+        withArguments: _withArgumentsSuperclassHasNoMethod);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_SUPER_METHOD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSuperclassHasNoMethod(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassHasNoMethod,
+      message: """Superclass has no method named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSuperclassHasNoSetter =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Superclass has no setter named '#name'.""",
+        withArguments: _withArgumentsSuperclassHasNoSetter);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_SUPER_SETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSuperclassHasNoSetter(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassHasNoSetter,
+      message: """Superclass has no setter named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateSuperclassMethodArgumentMismatch = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Superclass doesn't have a method named '#name' with matching arguments.""",
+    withArguments: _withArgumentsSuperclassMethodArgumentMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsSuperclassMethodArgumentMismatch(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSuperclassMethodArgumentMismatch,
+      message:
+          """Superclass doesn't have a method named '${name}' with matching arguments.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSupertypeIsFunction = messageSupertypeIsFunction;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSupertypeIsFunction = const MessageCode(
+    "SupertypeIsFunction",
+    message: r"""Can't use a function type as supertype.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSupertypeIsIllegal =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""The type '#name' can't be used as supertype.""",
+        withArguments: _withArgumentsSupertypeIsIllegal);
+
+// 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,
+        analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSupertypeIsIllegal(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSupertypeIsIllegal,
+      message: """The type '${name}' can't be used as supertype.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateSupertypeIsTypeVariable =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""The type variable '#name' can't be used as supertype.""",
+        withArguments: _withArgumentsSupertypeIsTypeVariable);
+
+// 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,
+        analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSupertypeIsTypeVariable(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeSupertypeIsTypeVariable,
+      message: """The type variable '${name}' can't be used as supertype.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSwitchCaseFallThrough = messageSwitchCaseFallThrough;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSwitchCaseFallThrough = const MessageCode(
+    "SwitchCaseFallThrough",
+    analyzerCodes: <String>["CASE_BLOCK_NOT_TERMINATED"],
+    message: r"""Switch case may fall through to the next case.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSwitchExpressionNotAssignableCause =
+    messageSwitchExpressionNotAssignableCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSwitchExpressionNotAssignableCause = const MessageCode(
+    "SwitchExpressionNotAssignableCause",
+    severity: Severity.context,
+    message: r"""The switch expression is here.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSwitchHasCaseAfterDefault =
+    messageSwitchHasCaseAfterDefault;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSwitchHasCaseAfterDefault = const MessageCode(
+    "SwitchHasCaseAfterDefault",
+    index: 16,
+    message:
+        r"""The default case should be the last case in a switch statement.""",
+    tip: r"""Try moving the default case after the other case clauses.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSwitchHasMultipleDefaults =
+    messageSwitchHasMultipleDefaults;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSwitchHasMultipleDefaults = const MessageCode(
+    "SwitchHasMultipleDefaults",
+    index: 15,
+    message: r"""The 'default' case can only be declared once.""",
+    tip: r"""Try removing all but one default case.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeSyntheticToken = messageSyntheticToken;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageSyntheticToken = const MessageCode("SyntheticToken",
+    message: r"""This couldn't be parsed.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateThisAccessInFieldInitializer =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't access 'this' in a field initializer to read '#name'.""",
+        withArguments: _withArgumentsThisAccessInFieldInitializer);
+
+// 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,
+        analyzerCodes: <String>["THIS_ACCESS_FROM_FIELD_INITIALIZER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsThisAccessInFieldInitializer(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeThisAccessInFieldInitializer,
+      message:
+          """Can't access 'this' in a field initializer to read '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeThisAsIdentifier = messageThisAsIdentifier;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageThisAsIdentifier = const MessageCode(
+    "ThisAsIdentifier",
+    analyzerCodes: <String>["INVALID_REFERENCE_TO_THIS"],
+    message: r"""Expected identifier, but got 'this'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeThisInitializerNotAlone = messageThisInitializerNotAlone;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageThisInitializerNotAlone = const MessageCode(
+    "ThisInitializerNotAlone",
+    analyzerCodes: <String>["FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR"],
+    message: r"""Can't have other initializers together with 'this'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+    templateThisOrSuperAccessInFieldInitializer =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""Can't access '#string' in a field initializer.""",
+        withArguments: _withArgumentsThisOrSuperAccessInFieldInitializer);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)>
+    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.
+Message _withArgumentsThisOrSuperAccessInFieldInitializer(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeThisOrSuperAccessInFieldInitializer,
+      message: """Can't access '${string}' in a field initializer.""",
+      arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int count,
+        int
+            count2)> templateTooFewArguments = const Template<
+        Message Function(int count, int count2)>(
+    messageTemplate:
+        r"""Too few positional arguments: #count required, #count2 given.""",
+    withArguments: _withArgumentsTooFewArguments);
+
+// 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,
+        analyzerCodes: <String>["NOT_ENOUGH_REQUIRED_ARGUMENTS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsTooFewArguments(int count, int count2) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  return new Message(codeTooFewArguments,
+      message:
+          """Too few positional arguments: ${count} required, ${count2} given.""",
+      arguments: {'count': count, 'count2': count2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        int count,
+        int
+            count2)> templateTooManyArguments = const Template<
+        Message Function(int count, int count2)>(
+    messageTemplate:
+        r"""Too many positional arguments: #count allowed, but #count2 found.""",
+    tipTemplate: r"""Try removing the extra positional arguments.""",
+    withArguments: _withArgumentsTooManyArguments);
+
+// 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,
+        analyzerCodes: <String>["EXTRA_POSITIONAL_ARGUMENTS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsTooManyArguments(int count, int count2) {
+  if (count == null) throw 'No count provided';
+  if (count2 == null) throw 'No count provided';
+  return new Message(codeTooManyArguments,
+      message:
+          """Too many positional arguments: ${count} allowed, but ${count2} found.""",
+      tip: """Try removing the extra positional arguments.""",
+      arguments: {'count': count, 'count2': count2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTopLevelOperator = messageTopLevelOperator;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTopLevelOperator = const MessageCode(
+    "TopLevelOperator",
+    index: 14,
+    message: r"""Operators must be declared within a class.""",
+    tip:
+        r"""Try removing the operator, moving it to a class, or converting it to be a function.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeAfterVar = messageTypeAfterVar;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeAfterVar = const MessageCode("TypeAfterVar",
+    index: 89,
+    message:
+        r"""Variables can't be declared using both 'var' and a type name.""",
+    tip: r"""Try removing 'var.'""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(int count)> templateTypeArgumentMismatch =
+    const Template<Message Function(int count)>(
+        messageTemplate: r"""Expected #count type arguments.""",
+        withArguments: _withArgumentsTypeArgumentMismatch);
+
+// 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,
+        analyzerCodes: <String>["WRONG_NUMBER_OF_TYPE_ARGUMENTS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsTypeArgumentMismatch(int count) {
+  if (count == null) throw 'No count provided';
+  return new Message(codeTypeArgumentMismatch,
+      message: """Expected ${count} type arguments.""",
+      arguments: {'count': count});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateTypeArgumentsOnTypeVariable =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't use type arguments with type variable '#name'.""",
+        tipTemplate: r"""Try removing the type arguments.""",
+        withArguments: _withArgumentsTypeArgumentsOnTypeVariable);
+
+// 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,
+        index: 13);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsTypeArgumentsOnTypeVariable(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeTypeArgumentsOnTypeVariable,
+      message: """Can't use type arguments with type variable '${name}'.""",
+      tip: """Try removing the type arguments.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeBeforeFactory = messageTypeBeforeFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeBeforeFactory = const MessageCode(
+    "TypeBeforeFactory",
+    index: 57,
+    message: r"""Factory constructors cannot have a return type.""",
+    tip: r"""Try removing the type appearing before 'factory'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)> templateTypeNotFound =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""Type '#name' not found.""",
+        withArguments: _withArgumentsTypeNotFound);
+
+// 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,
+        analyzerCodes: <String>["UNDEFINED_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsTypeNotFound(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeTypeNotFound,
+      message: """Type '${name}' not found.""", arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_)> templateTypeOrigin =
+    const Template<Message Function(String name, Uri uri_)>(
+        messageTemplate: r"""'#name' is from '#uri'.""",
+        withArguments: _withArgumentsTypeOrigin);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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_);
+  return new Message(codeTypeOrigin,
+      message: """'${name}' is from '${uri}'.""",
+      arguments: {'name': name, 'uri': uri_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, Uri uri_, Uri uri2_)>
+    templateTypeOriginWithFileUri =
+    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
+        messageTemplate: r"""'#name' is from '#uri' ('#uri2').""",
+        withArguments: _withArgumentsTypeOriginWithFileUri);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, Uri uri_, Uri uri2_)>
+    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_);
+  return new Message(codeTypeOriginWithFileUri,
+      message: """'${name}' is from '${uri}' ('${uri2}').""",
+      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeVariableDuplicatedName =
+    messageTypeVariableDuplicatedName;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeVariableDuplicatedName = const MessageCode(
+    "TypeVariableDuplicatedName",
+    analyzerCodes: <String>["DUPLICATE_DEFINITION"],
+    message: r"""A type variable can't have the same name as another.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateTypeVariableDuplicatedNameCause =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""The other type variable named '#name'.""",
+        withArguments: _withArgumentsTypeVariableDuplicatedNameCause);
+
+// 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.
+Message _withArgumentsTypeVariableDuplicatedNameCause(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeTypeVariableDuplicatedNameCause,
+      message: """The other type variable named '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeVariableInConstantContext =
+    messageTypeVariableInConstantContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeVariableInConstantContext = const MessageCode(
+    "TypeVariableInConstantContext",
+    analyzerCodes: <String>["TYPE_PARAMETER_IN_CONST_EXPRESSION"],
+    message: r"""Type variables can't be used as constants.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeVariableInStaticContext =
+    messageTypeVariableInStaticContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeVariableInStaticContext = const MessageCode(
+    "TypeVariableInStaticContext",
+    analyzerCodes: <String>["TYPE_PARAMETER_REFERENCED_BY_STATIC"],
+    message: r"""Type variables can't be used in static members.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypeVariableSameNameAsEnclosing =
+    messageTypeVariableSameNameAsEnclosing;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypeVariableSameNameAsEnclosing = const MessageCode(
+    "TypeVariableSameNameAsEnclosing",
+    analyzerCodes: <String>["CONFLICTING_TYPE_VARIABLE_AND_CLASS"],
+    message:
+        r"""A type variable can't have the same name as its enclosing declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypedefInClass = messageTypedefInClass;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypedefInClass = const MessageCode("TypedefInClass",
+    index: 7,
+    message: r"""Typedefs can't be declared inside classes.""",
+    tip: r"""Try moving the typedef to the top-level.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypedefNotFunction = messageTypedefNotFunction;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypedefNotFunction = const MessageCode(
+    "TypedefNotFunction",
+    analyzerCodes: <String>["INVALID_GENERIC_FUNCTION_TYPE"],
+    message: r"""Can't create typedef from non-function type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeUnexpectedDollarInString = messageUnexpectedDollarInString;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageUnexpectedDollarInString = const MessageCode(
+    "UnexpectedDollarInString",
+    analyzerCodes: <String>["UNEXPECTED_DOLLAR_IN_STRING"],
+    message:
+        r"""A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).""",
+    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)> templateUnexpectedToken =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""Unexpected token '#lexeme'.""",
+        withArguments: _withArgumentsUnexpectedToken);
+
+// 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,
+        analyzerCodes: <String>["UNEXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnexpectedToken(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeUnexpectedToken,
+      message: """Unexpected token '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, Token token)>
+    templateUnmatchedToken =
+    const Template<Message Function(String string, Token token)>(
+        messageTemplate: r"""Can't find '#string' to match '#lexeme'.""",
+        withArguments: _withArgumentsUnmatchedToken);
+
+// 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,
+        analyzerCodes: <String>["EXPECTED_TOKEN"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnmatchedToken(String string, Token token) {
+  if (string.isEmpty) throw 'No string provided';
+  String lexeme = token.lexeme;
+  return new Message(codeUnmatchedToken,
+      message: """Can't find '${string}' to match '${lexeme}'.""",
+      arguments: {'string': string, 'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String
+            name2)> templateUnresolvedPrefixInTypeAnnotation = const Template<
+        Message Function(String name, String name2)>(
+    messageTemplate:
+        r"""'#name.#name2' can't be used as a type because '#name' isn't defined.""",
+    withArguments: _withArgumentsUnresolvedPrefixInTypeAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+    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.
+Message _withArgumentsUnresolvedPrefixInTypeAnnotation(
+    String name, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  return new Message(codeUnresolvedPrefixInTypeAnnotation,
+      message:
+          """'${name}.${name2}' can't be used as a type because '${name}' isn't defined.""",
+      arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)> templateUnspecified =
+    const Template<Message Function(String string)>(
+        messageTemplate: r"""#string""",
+        withArguments: _withArgumentsUnspecified);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+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.
+Message _withArgumentsUnspecified(String string) {
+  if (string.isEmpty) throw 'No string provided';
+  return new Message(codeUnspecified,
+      message: """${string}""", arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Token token)> templateUnsupportedOperator =
+    const Template<Message Function(Token token)>(
+        messageTemplate: r"""The '#lexeme' operator is not supported.""",
+        withArguments: _withArgumentsUnsupportedOperator);
+
+// 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,
+        analyzerCodes: <String>["UNSUPPORTED_OPERATOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnsupportedOperator(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeUnsupportedOperator,
+      message: """The '${lexeme}' operator is not supported.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeUnsupportedPrefixPlus = messageUnsupportedPrefixPlus;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageUnsupportedPrefixPlus = const MessageCode(
+    "UnsupportedPrefixPlus",
+    analyzerCodes: <String>["MISSING_IDENTIFIER"],
+    message: r"""'+' is not a prefix operator.""",
+    tip: r"""Try removing '+'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeUnterminatedComment = messageUnterminatedComment;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageUnterminatedComment = const MessageCode(
+    "UnterminatedComment",
+    analyzerCodes: <String>["UNTERMINATED_MULTI_LINE_COMMENT"],
+    message: r"""Comment starting with '/*' must end with '*/'.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string, String string2)>
+    templateUnterminatedString =
+    const Template<Message Function(String string, String string2)>(
+        messageTemplate:
+            r"""String starting with #string must end with #string2.""",
+        withArguments: _withArgumentsUnterminatedString);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeUnterminatedString =
+    const Code<Message Function(String string, String string2)>(
+        "UnterminatedString", templateUnterminatedString,
+        analyzerCodes: <String>["UNTERMINATED_STRING_LITERAL"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUnterminatedString(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeUnterminatedString,
+      message: """String starting with ${string} must end with ${string2}.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeUnterminatedToken = messageUnterminatedToken;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageUnterminatedToken =
+    const MessageCode("UnterminatedToken", message: r"""Incomplete token.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Uri uri_)> templateUntranslatableUri =
+    const Template<Message Function(Uri uri_)>(
+        messageTemplate: r"""Not found: '#uri'""",
+        withArguments: _withArgumentsUntranslatableUri);
+
+// 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,
+        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_);
+  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 Code<Null> codeVarAsTypeName = messageVarAsTypeName;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageVarAsTypeName = const MessageCode("VarAsTypeName",
+    index: 61, message: r"""The keyword 'var' can't be used as a type name.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeVarReturnType = messageVarReturnType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageVarReturnType = const MessageCode("VarReturnType",
+    index: 12,
+    message: r"""The return type can't be 'var'.""",
+    tip:
+        r"""Try removing the keyword 'var', or replacing it with the name of the return type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeVoidExpression = messageVoidExpression;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageVoidExpression = const MessageCode("VoidExpression",
+    analyzerCodes: <String>["USE_OF_VOID_RESULT"],
+    message: r"""This expression has type 'void' and can't be used.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateWebLiteralCannotBeRepresentedExactly = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""The integer literal #string can't be represented exactly in JavaScript.""",
+    tipTemplate:
+        r"""Try changing the literal to something that can be represented in Javascript. In Javascript #string2 is the nearest value that can be represented exactly.""",
+    withArguments: _withArgumentsWebLiteralCannotBeRepresentedExactly);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeWebLiteralCannotBeRepresentedExactly =
+    const Code<Message Function(String string, String string2)>(
+  "WebLiteralCannotBeRepresentedExactly",
+  templateWebLiteralCannotBeRepresentedExactly,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsWebLiteralCannotBeRepresentedExactly(
+    String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeWebLiteralCannotBeRepresentedExactly,
+      message:
+          """The integer literal ${string} can't be represented exactly in JavaScript.""",
+      tip: """Try changing the literal to something that can be represented in Javascript. In Javascript ${string2} is the nearest value that can be represented exactly.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeWithBeforeExtends = messageWithBeforeExtends;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageWithBeforeExtends = const MessageCode(
+    "WithBeforeExtends",
+    index: 11,
+    message: r"""The extends clause must be before the with clause.""",
+    tip: r"""Try moving the extends clause before the with clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeYieldAsIdentifier = messageYieldAsIdentifier;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageYieldAsIdentifier = const MessageCode(
+    "YieldAsIdentifier",
+    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
+    message:
+        r"""'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeYieldNotGenerator = messageYieldNotGenerator;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageYieldNotGenerator = const MessageCode(
+    "YieldNotGenerator",
+    analyzerCodes: <String>["YIELD_IN_NON_GENERATOR"],
+    message: r"""'yield' can only be used in 'sync*' or 'async*' methods.""");
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart b/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart
new file mode 100644
index 0000000..a1d5838
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/diagnostic_message.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library front_end.diagnostic_message;
+
+import 'codes.dart' show Code, DiagnosticMessageFromJson, FormattedMessage;
+
+import 'severity.dart' show Severity;
+
+/// The type of a diagnostic message callback. For example:
+///
+///    void handler(DiagnosticMessage message) {
+///      if (enableTerminalColors) { // See [terminal_color_support.dart].
+///        message.ansiFormatted.forEach(stderr.writeln);
+///      } else {
+///        message.plainTextFormatted.forEach(stderr.writeln);
+///      }
+///    }
+typedef DiagnosticMessageHandler = void Function(DiagnosticMessage);
+
+/// Represents a diagnostic message that can be reported from a tool, for
+/// example, a compiler.
+///
+/// The word *diagnostic* is used loosely here, as a tool may also use this for
+/// reporting any kind of message, including non-diagnostic messages such as
+/// licensing, informal, or logging information. This allows a well-behaved
+/// tool to never directly write to stdout or stderr.
+abstract class DiagnosticMessage {
+  DiagnosticMessage._(); // Prevent subclassing.
+
+  Iterable<String> get ansiFormatted;
+
+  Iterable<String> get plainTextFormatted;
+
+  Severity get severity;
+}
+
+/// This method is subject to change.
+Uri getMessageUri(DiagnosticMessage message) {
+  return message is FormattedMessage
+      ? message.uri
+      : message is DiagnosticMessageFromJson ? message.uri : null;
+}
+
+/// This method is subject to change.
+int getMessageCharOffset(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.charOffset : null;
+}
+
+/// This method is subject to change.
+int getMessageLength(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.length : null;
+}
+
+/// This method is subject to change.
+Code getMessageCodeObject(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.code : null;
+}
+
+/// This method is subject to change.
+String getMessageHeaderText(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.message : null;
+}
+
+/// This method is subject to change.
+int getMessageCode(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.code.index : -1;
+}
+
+/// This method is subject to change.
+Map<String, dynamic> getMessageArguments(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.arguments : null;
+}
+
+/// This method is subject to change.
+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
new file mode 100644
index 0000000..0358608
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/severity.dart
@@ -0,0 +1,43 @@
+// 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.
+
+library _fe_analyzer_shared.messages.severity;
+
+enum Severity {
+  context,
+  error,
+  ignored,
+  internalProblem,
+  warning,
+}
+
+const Map<String, String> severityEnumNames = const <String, String>{
+  'CONTEXT': 'context',
+  'ERROR': 'error',
+  'IGNORED': 'ignored',
+  'INTERNAL_PROBLEM': 'internalProblem',
+  'WARNING': 'warning',
+};
+
+const Map<String, Severity> severityEnumValues = const <String, Severity>{
+  'CONTEXT': Severity.context,
+  'ERROR': Severity.error,
+  'IGNORED': Severity.ignored,
+  'INTERNAL_PROBLEM': Severity.internalProblem,
+  'WARNING': Severity.warning,
+};
+
+const Map<Severity, String> severityPrefixes = const <Severity, String>{
+  Severity.error: "Error",
+  Severity.internalProblem: "Internal problem",
+  Severity.warning: "Warning",
+  Severity.context: "Context",
+};
+
+const Map<Severity, String> severityTexts = const <Severity, String>{
+  Severity.error: "error",
+  Severity.internalProblem: "internal problem",
+  Severity.warning: "warning",
+  Severity.context: "context",
+};
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/assert.dart b/pkg/_fe_analyzer_shared/lib/src/parser/assert.dart
new file mode 100644
index 0000000..56350c7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/assert.dart
@@ -0,0 +1,16 @@
+// 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.
+
+library _fe_analyzer_shared.parser.Assert;
+
+/// Syntactic forms of `assert`.
+///
+/// An assertion can legally occur as a statement. However, assertions are also
+/// experimentally allowed in initializers. For improved error recovery, we
+/// also attempt to parse asserts as expressions.
+enum Assert {
+  Expression,
+  Initializer,
+  Statement,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/async_modifier.dart b/pkg/_fe_analyzer_shared/lib/src/parser/async_modifier.dart
new file mode 100644
index 0000000..c141e80
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/async_modifier.dart
@@ -0,0 +1,12 @@
+// 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.
+
+library _fe_analyzer_shared.parser.async_modifier;
+
+enum AsyncModifier {
+  Sync,
+  SyncStar,
+  Async,
+  AsyncStar,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart
new file mode 100644
index 0000000..60a6461
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/block_kind.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class BlockKind {
+  final String name;
+
+  final bool useNameForMissingBlock;
+
+  const BlockKind._(this.name, this.useNameForMissingBlock);
+
+  /// Returns the name to use for this block if it is missing in
+  /// [templateExpectedClassOrMixinBody].
+  ///
+  /// If `null` the generic [templateExpectedButGot] is used instead.
+  String get missingBlockName => useNameForMissingBlock ? name : null;
+
+  String toString() => 'BlockKind($name)';
+
+  static const BlockKind catchClause = const BlockKind._('catch clause', true);
+  static const BlockKind classDeclaration =
+      const BlockKind._('class declaration', false);
+  static const BlockKind enumDeclaration =
+      const BlockKind._('enum declaration', false);
+  static const BlockKind extensionDeclaration =
+      const BlockKind._('extension declaration', false);
+  static const BlockKind finallyClause =
+      const BlockKind._('finally clause', true);
+  static const BlockKind functionBody =
+      const BlockKind._('function body', false);
+  static const BlockKind invalid = const BlockKind._('invalid', false);
+  static const BlockKind mixinDeclaration =
+      const BlockKind._('mixin declaration', false);
+  static const BlockKind statement = const BlockKind._('statement', false);
+  static const BlockKind switchStatement =
+      const BlockKind._('switch statement', false);
+  static const BlockKind tryStatement =
+      const BlockKind._('try statement', true);
+}
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
new file mode 100644
index 0000000..c41be78
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/class_member_parser.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.parser.class_member_parser;
+
+import '../scanner/token.dart' show Token;
+
+import 'error_delegation_listener.dart' show ErrorDelegationListener;
+
+import 'listener.dart' show Listener;
+
+import 'parser_impl.dart' show Parser;
+
+/// Parser similar to [TopLevelParser] but also parses class members (excluding
+/// their bodies).
+class ClassMemberParser extends Parser {
+  Parser skipParser;
+
+  ClassMemberParser(Listener listener) : super(listener);
+
+  @override
+  Token parseExpression(Token token) {
+    return skipExpression(token);
+  }
+
+  @override
+  Token parseIdentifierExpression(Token token) {
+    return token.next;
+  }
+
+  Token skipExpression(Token token) {
+    // TODO(askesc): We listen to errors occurring during expression parsing,
+    // since the parser may rewrite the token stream such that the error is
+    // 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));
+    skipParser.mayParseFunctionExpressions = mayParseFunctionExpressions;
+    skipParser.asyncState = asyncState;
+    skipParser.loopState = loopState;
+    return skipParser.parseExpression(token);
+  }
+
+  // This method is overridden for two reasons:
+  // 1. Avoid generating events for arguments.
+  // 2. Avoid calling skip expression for each argument (which doesn't work).
+  Token parseArgumentsOpt(Token token) => skipArgumentsOpt(token);
+
+  Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
+    return skipFunctionBody(token, isExpression, allowAbstract);
+  }
+
+  @override
+  Token parseInvalidBlock(Token token) => skipBlock(token);
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/declaration_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/declaration_kind.dart
similarity index 100%
rename from pkg/front_end/lib/src/fasta/parser/declaration_kind.dart
rename to pkg/_fe_analyzer_shared/lib/src/parser/declaration_kind.dart
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/directive_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/directive_context.dart
new file mode 100644
index 0000000..f0e8235
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/directive_context.dart
@@ -0,0 +1,108 @@
+// 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 '../messages/codes.dart';
+import '../scanner/token.dart';
+import 'parser_impl.dart';
+
+class DirectiveContext {
+  DirectiveState state = DirectiveState.Unknown;
+
+  void checkScriptTag(Parser parser, Token token) {
+    if (state == DirectiveState.Unknown) {
+      state = DirectiveState.Script;
+      return;
+    }
+    // The scanner only produces the SCRIPT_TAG
+    // when it is the first token in the file.
+    throw "Internal error: Unexpected script tag.";
+  }
+
+  void checkDeclaration() {
+    if (state != DirectiveState.PartOf) {
+      state = DirectiveState.Declarations;
+    }
+  }
+
+  void checkExport(Parser parser, Token token) {
+    if (state.index <= DirectiveState.ImportAndExport.index) {
+      state = DirectiveState.ImportAndExport;
+      return;
+    }
+    // Recovery
+    if (state == DirectiveState.Part) {
+      parser.reportRecoverableError(token, messageExportAfterPart);
+    } else if (state == DirectiveState.PartOf) {
+      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
+    } else {
+      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
+    }
+  }
+
+  void checkImport(Parser parser, Token token) {
+    if (state.index <= DirectiveState.ImportAndExport.index) {
+      state = DirectiveState.ImportAndExport;
+      return;
+    }
+    // Recovery
+    if (state == DirectiveState.Part) {
+      parser.reportRecoverableError(token, messageImportAfterPart);
+    } else if (state == DirectiveState.PartOf) {
+      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
+    } else {
+      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
+    }
+  }
+
+  void checkLibrary(Parser parser, Token token) {
+    if (state.index < DirectiveState.Library.index) {
+      state = DirectiveState.Library;
+      return;
+    }
+    // Recovery
+    if (state == DirectiveState.Library) {
+      parser.reportRecoverableError(token, messageMultipleLibraryDirectives);
+    } else if (state == DirectiveState.PartOf) {
+      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
+    } else {
+      parser.reportRecoverableError(token, messageLibraryDirectiveNotFirst);
+    }
+  }
+
+  void checkPart(Parser parser, Token token) {
+    if (state.index <= DirectiveState.Part.index) {
+      state = DirectiveState.Part;
+      return;
+    }
+    // Recovery
+    if (state == DirectiveState.PartOf) {
+      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
+    } else {
+      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
+    }
+  }
+
+  void checkPartOf(Parser parser, Token token) {
+    if (state == DirectiveState.Unknown) {
+      state = DirectiveState.PartOf;
+      return;
+    }
+    // Recovery
+    if (state == DirectiveState.PartOf) {
+      parser.reportRecoverableError(token, messagePartOfTwice);
+    } else {
+      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
+    }
+  }
+}
+
+enum DirectiveState {
+  Unknown,
+  Script,
+  Library,
+  ImportAndExport,
+  Part,
+  PartOf,
+  Declarations,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/error_delegation_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/error_delegation_listener.dart
new file mode 100644
index 0000000..56bd7f0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/error_delegation_listener.dart
@@ -0,0 +1,22 @@
+// 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 '../messages/codes.dart' show Message;
+
+import '../scanner/token.dart' show Token;
+
+import 'listener.dart' show Listener;
+
+/// A listener which forwards error reports to another listener but ignores
+/// all other events.
+class ErrorDelegationListener extends Listener {
+  Listener delegate;
+
+  ErrorDelegationListener(this.delegate);
+
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    return delegate.handleRecoverableError(message, startToken, endToken);
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/formal_parameter_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/formal_parameter_kind.dart
new file mode 100644
index 0000000..7e2e6f9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/formal_parameter_kind.dart
@@ -0,0 +1,24 @@
+// 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.
+
+library _fe_analyzer_shared.parser.formal_parameter_kind;
+
+// TODO(johnniwinther): Update this to support required named arguments.
+enum FormalParameterKind {
+  mandatory,
+  optionalNamed,
+  optionalPositional,
+}
+
+bool isMandatoryFormalParameterKind(FormalParameterKind type) {
+  return FormalParameterKind.mandatory == type;
+}
+
+bool isOptionalNamedFormalParameterKind(FormalParameterKind type) {
+  return FormalParameterKind.optionalNamed == type;
+}
+
+bool isOptionalPositionalFormalParameterKind(FormalParameterKind type) {
+  return FormalParameterKind.optionalPositional == type;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
new file mode 100644
index 0000000..3493bc8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -0,0 +1,1588 @@
+// 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 '../messages/codes.dart';
+import '../scanner/scanner.dart';
+import 'parser.dart';
+
+class ForwardingListener implements Listener {
+  Listener listener;
+  bool forwardErrors = true;
+
+  ForwardingListener([this.listener]);
+
+  @override
+  set suppressParseErrors(bool value) {
+    listener?.suppressParseErrors = value;
+  }
+
+  @override
+  Uri get uri => listener?.uri;
+
+  @override
+  void beginArguments(Token token) {
+    listener?.beginArguments(token);
+  }
+
+  @override
+  void beginAssert(Token assertKeyword, Assert kind) {
+    listener?.beginAssert(assertKeyword, kind);
+  }
+
+  @override
+  void beginAwaitExpression(Token token) {
+    listener?.beginAwaitExpression(token);
+  }
+
+  @override
+  void beginBinaryExpression(Token token) {
+    listener?.beginBinaryExpression(token);
+  }
+
+  @override
+  void beginBlock(Token token, BlockKind blockKind) {
+    listener?.beginBlock(token, blockKind);
+  }
+
+  @override
+  void beginBlockFunctionBody(Token token) {
+    listener?.beginBlockFunctionBody(token);
+  }
+
+  @override
+  void beginCascade(Token token) {
+    listener?.beginCascade(token);
+  }
+
+  @override
+  void beginCaseExpression(Token caseKeyword) {
+    listener?.beginCaseExpression(caseKeyword);
+  }
+
+  @override
+  void beginCatchClause(Token token) {
+    listener?.beginCatchClause(token);
+  }
+
+  @override
+  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+    listener?.beginClassDeclaration(begin, abstractToken, name);
+  }
+
+  @override
+  void beginClassOrMixinBody(DeclarationKind kind, Token token) {
+    listener?.beginClassOrMixinBody(kind, token);
+  }
+
+  @override
+  void beginClassOrNamedMixinApplicationPrelude(Token token) {
+    listener?.beginClassOrNamedMixinApplicationPrelude(token);
+  }
+
+  @override
+  void beginCombinators(Token token) {
+    listener?.beginCombinators(token);
+  }
+
+  @override
+  void beginCompilationUnit(Token token) {
+    listener?.beginCompilationUnit(token);
+  }
+
+  @override
+  void beginConditionalExpression(Token question) {
+    listener?.beginConditionalExpression(question);
+  }
+
+  @override
+  void beginConditionalUri(Token ifKeyword) {
+    listener?.beginConditionalUri(ifKeyword);
+  }
+
+  @override
+  void beginConditionalUris(Token token) {
+    listener?.beginConditionalUris(token);
+  }
+
+  @override
+  void beginConstExpression(Token constKeyword) {
+    listener?.beginConstExpression(constKeyword);
+  }
+
+  @override
+  void beginConstLiteral(Token token) {
+    listener?.beginConstLiteral(token);
+  }
+
+  @override
+  void beginConstructorReference(Token start) {
+    listener?.beginConstructorReference(start);
+  }
+
+  @override
+  void beginDoWhileStatement(Token token) {
+    listener?.beginDoWhileStatement(token);
+  }
+
+  @override
+  void beginDoWhileStatementBody(Token token) {
+    listener?.beginDoWhileStatementBody(token);
+  }
+
+  @override
+  void beginElseStatement(Token token) {
+    listener?.beginElseStatement(token);
+  }
+
+  @override
+  void beginEnum(Token enumKeyword) {
+    listener?.beginEnum(enumKeyword);
+  }
+
+  @override
+  void beginExport(Token token) {
+    listener?.beginExport(token);
+  }
+
+  @override
+  void beginExtensionDeclarationPrelude(Token extensionKeyword) {
+    listener?.beginExtensionDeclarationPrelude(extensionKeyword);
+  }
+
+  @override
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+    listener?.beginExtensionDeclaration(extensionKeyword, name);
+  }
+
+  @override
+  void beginFactoryMethod(
+      Token lastConsumed, Token externalToken, Token constToken) {
+    listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
+  }
+
+  @override
+  void beginFieldInitializer(Token token) {
+    listener?.beginFieldInitializer(token);
+  }
+
+  @override
+  void beginForControlFlow(Token awaitToken, Token forToken) {
+    listener?.beginForControlFlow(awaitToken, forToken);
+  }
+
+  @override
+  void beginForInBody(Token token) {
+    listener?.beginForInBody(token);
+  }
+
+  @override
+  void beginForInExpression(Token token) {
+    listener?.beginForInExpression(token);
+  }
+
+  @override
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {
+    listener?.beginFormalParameter(
+        token, kind, requiredToken, covariantToken, varFinalOrConst);
+  }
+
+  @override
+  void beginFormalParameterDefaultValueExpression() {
+    listener?.beginFormalParameterDefaultValueExpression();
+  }
+
+  @override
+  void beginFormalParameters(Token token, MemberKind kind) {
+    listener?.beginFormalParameters(token, kind);
+  }
+
+  @override
+  void beginForStatement(Token token) {
+    listener?.beginForStatement(token);
+  }
+
+  @override
+  void beginForStatementBody(Token token) {
+    listener?.beginForStatementBody(token);
+  }
+
+  @override
+  void beginFunctionExpression(Token token) {
+    listener?.beginFunctionExpression(token);
+  }
+
+  @override
+  void beginFunctionName(Token token) {
+    listener?.beginFunctionName(token);
+  }
+
+  @override
+  void beginFunctionType(Token beginToken) {
+    listener?.beginFunctionType(beginToken);
+  }
+
+  @override
+  void beginFunctionTypeAlias(Token token) {
+    listener?.beginFunctionTypeAlias(token);
+  }
+
+  @override
+  void beginFunctionTypedFormalParameter(Token token) {
+    listener?.beginFunctionTypedFormalParameter(token);
+  }
+
+  @override
+  void beginHide(Token hideKeyword) {
+    listener?.beginHide(hideKeyword);
+  }
+
+  @override
+  void beginIfControlFlow(Token ifToken) {
+    listener?.beginIfControlFlow(ifToken);
+  }
+
+  @override
+  void beginIfStatement(Token token) {
+    listener?.beginIfStatement(token);
+  }
+
+  @override
+  void beginImplicitCreationExpression(Token token) {
+    listener?.beginImplicitCreationExpression(token);
+  }
+
+  @override
+  void beginImport(Token importKeyword) {
+    listener?.beginImport(importKeyword);
+  }
+
+  @override
+  void beginInitializedIdentifier(Token token) {
+    listener?.beginInitializedIdentifier(token);
+  }
+
+  @override
+  void beginInitializer(Token token) {
+    listener?.beginInitializer(token);
+  }
+
+  @override
+  void beginInitializers(Token token) {
+    listener?.beginInitializers(token);
+  }
+
+  @override
+  void beginLabeledStatement(Token token, int labelCount) {
+    listener?.beginLabeledStatement(token, labelCount);
+  }
+
+  @override
+  void beginLibraryName(Token token) {
+    listener?.beginLibraryName(token);
+  }
+
+  @override
+  void beginLiteralString(Token token) {
+    listener?.beginLiteralString(token);
+  }
+
+  @override
+  void beginLiteralSymbol(Token token) {
+    listener?.beginLiteralSymbol(token);
+  }
+
+  @override
+  void beginLocalFunctionDeclaration(Token token) {
+    listener?.beginLocalFunctionDeclaration(token);
+  }
+
+  @override
+  void beginMember() {
+    listener?.beginMember();
+  }
+
+  @override
+  void beginMetadata(Token token) {
+    listener?.beginMetadata(token);
+  }
+
+  @override
+  void beginMetadataStar(Token token) {
+    listener?.beginMetadataStar(token);
+  }
+
+  @override
+  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
+      Token varFinalOrConst, Token getOrSet, Token name) {
+    listener?.beginMethod(externalToken, staticToken, covariantToken,
+        varFinalOrConst, getOrSet, name);
+  }
+
+  @override
+  void beginMixinDeclaration(Token mixinKeyword, Token name) {
+    listener?.beginMixinDeclaration(mixinKeyword, name);
+  }
+
+  @override
+  void beginNamedFunctionExpression(Token token) {
+    listener?.beginNamedFunctionExpression(token);
+  }
+
+  @override
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {
+    listener?.beginNamedMixinApplication(begin, abstractToken, name);
+  }
+
+  @override
+  void beginNewExpression(Token token) {
+    listener?.beginNewExpression(token);
+  }
+
+  @override
+  void beginOptionalFormalParameters(Token token) {
+    listener?.beginOptionalFormalParameters(token);
+  }
+
+  @override
+  void beginPart(Token token) {
+    listener?.beginPart(token);
+  }
+
+  @override
+  void beginPartOf(Token token) {
+    listener?.beginPartOf(token);
+  }
+
+  @override
+  void beginRedirectingFactoryBody(Token token) {
+    listener?.beginRedirectingFactoryBody(token);
+  }
+
+  @override
+  void beginRethrowStatement(Token token) {
+    listener?.beginRethrowStatement(token);
+  }
+
+  @override
+  void beginReturnStatement(Token token) {
+    listener?.beginReturnStatement(token);
+  }
+
+  @override
+  void beginShow(Token showKeyword) {
+    listener?.beginShow(showKeyword);
+  }
+
+  @override
+  void beginSwitchBlock(Token token) {
+    listener?.beginSwitchBlock(token);
+  }
+
+  @override
+  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
+    listener?.beginSwitchCase(labelCount, expressionCount, firstToken);
+  }
+
+  @override
+  void beginSwitchStatement(Token token) {
+    listener?.beginSwitchStatement(token);
+  }
+
+  @override
+  void beginThenControlFlow(Token token) {
+    listener?.beginThenControlFlow(token);
+  }
+
+  @override
+  void beginThenStatement(Token token) {
+    listener?.beginThenStatement(token);
+  }
+
+  @override
+  void beginTopLevelMember(Token token) {
+    listener?.beginTopLevelMember(token);
+  }
+
+  @override
+  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
+    listener?.beginTopLevelMethod(lastConsumed, externalToken);
+  }
+
+  @override
+  void beginTryStatement(Token token) {
+    listener?.beginTryStatement(token);
+  }
+
+  @override
+  void beginTypeArguments(Token token) {
+    listener?.beginTypeArguments(token);
+  }
+
+  @override
+  void beginTypeList(Token token) {
+    listener?.beginTypeList(token);
+  }
+
+  @override
+  void beginTypeVariable(Token token) {
+    listener?.beginTypeVariable(token);
+  }
+
+  @override
+  void beginTypeVariables(Token token) {
+    listener?.beginTypeVariables(token);
+  }
+
+  @override
+  void beginVariableInitializer(Token token) {
+    listener?.beginVariableInitializer(token);
+  }
+
+  @override
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
+    listener?.beginVariablesDeclaration(token, lateToken, varFinalOrConst);
+  }
+
+  @override
+  void beginWhileStatement(Token token) {
+    listener?.beginWhileStatement(token);
+  }
+
+  @override
+  void beginWhileStatementBody(Token token) {
+    listener?.beginWhileStatementBody(token);
+  }
+
+  @override
+  void beginYieldStatement(Token token) {
+    listener?.beginYieldStatement(token);
+  }
+
+  @override
+  void discardTypeReplacedWithCommentTypeAssign() {
+    listener?.discardTypeReplacedWithCommentTypeAssign();
+  }
+
+  @override
+  void endArguments(int count, Token beginToken, Token endToken) {
+    listener?.endArguments(count, beginToken, endToken);
+  }
+
+  @override
+  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+      Token commaToken, Token semicolonToken) {
+    listener?.endAssert(
+        assertKeyword, kind, leftParenthesis, commaToken, semicolonToken);
+  }
+
+  @override
+  void endAwaitExpression(Token beginToken, Token endToken) {
+    listener?.endAwaitExpression(beginToken, endToken);
+  }
+
+  @override
+  void endBinaryExpression(Token token) {
+    listener?.endBinaryExpression(token);
+  }
+
+  @override
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
+    listener?.endBlock(count, beginToken, endToken, blockKind);
+  }
+
+  @override
+  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+    listener?.endBlockFunctionBody(count, beginToken, endToken);
+  }
+
+  @override
+  void endCascade() {
+    listener?.endCascade();
+  }
+
+  @override
+  void endCaseExpression(Token colon) {
+    listener?.endCaseExpression(colon);
+  }
+
+  @override
+  void endCatchClause(Token token) {
+    listener?.endCatchClause(token);
+  }
+
+  @override
+  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    listener?.endClassConstructor(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    listener?.endClassDeclaration(beginToken, endToken);
+  }
+
+  @override
+  void endClassFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    listener?.endClassFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  @override
+  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    listener?.endClassFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
+  }
+
+  @override
+  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    listener?.endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endClassOrMixinBody(
+      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+    listener?.endClassOrMixinBody(kind, memberCount, beginToken, endToken);
+  }
+
+  @override
+  void endCombinators(int count) {
+    listener?.endCombinators(count);
+  }
+
+  @override
+  void endCompilationUnit(int count, Token token) {
+    listener?.endCompilationUnit(count, token);
+  }
+
+  @override
+  void endConditionalExpression(Token question, Token colon) {
+    listener?.endConditionalExpression(question, colon);
+  }
+
+  @override
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+    listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
+  }
+
+  @override
+  void endConditionalUris(int count) {
+    listener?.endConditionalUris(count);
+  }
+
+  @override
+  void endConstExpression(Token token) {
+    listener?.endConstExpression(token);
+  }
+
+  @override
+  void endConstLiteral(Token token) {
+    listener?.endConstLiteral(token);
+  }
+
+  @override
+  void endConstructorReference(
+      Token start, Token periodBeforeName, Token endToken) {
+    listener?.endConstructorReference(start, periodBeforeName, endToken);
+  }
+
+  @override
+  void endDoWhileStatement(
+      Token doKeyword, Token whileKeyword, Token endToken) {
+    listener?.endDoWhileStatement(doKeyword, whileKeyword, endToken);
+  }
+
+  @override
+  void endDoWhileStatementBody(Token token) {
+    listener?.endDoWhileStatementBody(token);
+  }
+
+  @override
+  void endElseStatement(Token token) {
+    listener?.endElseStatement(token);
+  }
+
+  @override
+  void endEnum(Token enumKeyword, Token leftBrace, int count) {
+    listener?.endEnum(enumKeyword, leftBrace, count);
+  }
+
+  @override
+  void endExport(Token exportKeyword, Token semicolon) {
+    listener?.endExport(exportKeyword, semicolon);
+  }
+
+  @override
+  void endExtensionConstructor(Token getOrSet, Token beginToken,
+      Token beginParam, Token beginInitializers, Token endToken) {
+    listener?.endExtensionConstructor(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endExtensionDeclaration(
+      Token extensionKeyword, Token onKeyword, Token token) {
+    listener?.endExtensionDeclaration(extensionKeyword, onKeyword, token);
+  }
+
+  @override
+  void endExtensionFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    listener?.endExtensionFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  @override
+  void endExtensionFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    listener?.endExtensionFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
+  }
+
+  @override
+  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    listener?.endExtensionMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endFieldInitializer(Token assignment, Token token) {
+    listener?.endFieldInitializer(assignment, token);
+  }
+
+  @override
+  void endForControlFlow(Token token) {
+    listener?.endForControlFlow(token);
+  }
+
+  @override
+  void endForIn(Token endToken) {
+    listener?.endForIn(endToken);
+  }
+
+  @override
+  void endForInBody(Token token) {
+    listener?.endForInBody(token);
+  }
+
+  @override
+  void endForInControlFlow(Token token) {
+    listener?.endForInControlFlow(token);
+  }
+
+  @override
+  void endForInExpression(Token token) {
+    listener?.endForInExpression(token);
+  }
+
+  @override
+  void endFormalParameter(
+      Token thisKeyword,
+      Token periodAfterThis,
+      Token nameToken,
+      Token initializerStart,
+      Token initializerEnd,
+      FormalParameterKind kind,
+      MemberKind memberKind) {
+    listener?.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
+        initializerStart, initializerEnd, kind, memberKind);
+  }
+
+  @override
+  void endFormalParameterDefaultValueExpression() {
+    listener?.endFormalParameterDefaultValueExpression();
+  }
+
+  @override
+  void endFormalParameters(
+      int count, Token beginToken, Token endToken, MemberKind kind) {
+    listener?.endFormalParameters(count, beginToken, endToken, kind);
+  }
+
+  @override
+  void endForStatement(Token endToken) {
+    listener?.endForStatement(endToken);
+  }
+
+  @override
+  void endForStatementBody(Token token) {
+    listener?.endForStatementBody(token);
+  }
+
+  @override
+  void endFunctionExpression(Token beginToken, Token token) {
+    listener?.endFunctionExpression(beginToken, token);
+  }
+
+  @override
+  void endFunctionName(Token beginToken, Token token) {
+    listener?.endFunctionName(beginToken, token);
+  }
+
+  @override
+  void endFunctionType(Token functionToken, Token questionMark) {
+    listener?.endFunctionType(functionToken, questionMark);
+  }
+
+  @override
+  void endFunctionTypeAlias(
+      Token typedefKeyword, Token equals, Token endToken) {
+    listener?.endFunctionTypeAlias(typedefKeyword, equals, endToken);
+  }
+
+  @override
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+    listener?.endFunctionTypedFormalParameter(nameToken, question);
+  }
+
+  @override
+  void endHide(Token hideKeyword) {
+    listener?.endHide(hideKeyword);
+  }
+
+  @override
+  void endIfControlFlow(Token token) {
+    listener?.endIfControlFlow(token);
+  }
+
+  @override
+  void endIfElseControlFlow(Token token) {
+    listener?.endIfElseControlFlow(token);
+  }
+
+  @override
+  void endIfStatement(Token ifToken, Token elseToken) {
+    listener?.endIfStatement(ifToken, elseToken);
+  }
+
+  @override
+  void endImplicitCreationExpression(Token token) {
+    listener?.endImplicitCreationExpression(token);
+  }
+
+  @override
+  void endImport(Token importKeyword, Token semicolon) {
+    listener?.endImport(importKeyword, semicolon);
+  }
+
+  @override
+  void endInitializedIdentifier(Token nameToken) {
+    listener?.endInitializedIdentifier(nameToken);
+  }
+
+  @override
+  void endInitializer(Token token) {
+    listener?.endInitializer(token);
+  }
+
+  @override
+  void endInitializers(int count, Token beginToken, Token endToken) {
+    listener?.endInitializers(count, beginToken, endToken);
+  }
+
+  @override
+  void endInvalidAwaitExpression(
+      Token beginToken, Token endToken, MessageCode errorCode) {
+    listener?.endInvalidAwaitExpression(beginToken, endToken, errorCode);
+  }
+
+  @override
+  void endLabeledStatement(int labelCount) {
+    listener?.endLabeledStatement(labelCount);
+  }
+
+  @override
+  void endLibraryName(Token libraryKeyword, Token semicolon) {
+    listener?.endLibraryName(libraryKeyword, semicolon);
+  }
+
+  @override
+  void endLiteralString(int interpolationCount, Token endToken) {
+    listener?.endLiteralString(interpolationCount, endToken);
+  }
+
+  @override
+  void endLiteralSymbol(Token hashToken, int identifierCount) {
+    listener?.endLiteralSymbol(hashToken, identifierCount);
+  }
+
+  @override
+  void endLocalFunctionDeclaration(Token endToken) {
+    listener?.endLocalFunctionDeclaration(endToken);
+  }
+
+  @override
+  void endMember() {
+    listener?.endMember();
+  }
+
+  @override
+  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+    listener?.endMetadata(beginToken, periodBeforeName, endToken);
+  }
+
+  @override
+  void endMetadataStar(int count) {
+    listener?.endMetadataStar(count);
+  }
+
+  @override
+  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    listener?.endMixinConstructor(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+    listener?.endMixinDeclaration(mixinKeyword, endToken);
+  }
+
+  @override
+  void endMixinFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    listener?.endMixinFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  @override
+  void endMixinFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    listener?.endMixinFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
+  }
+
+  @override
+  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    listener?.endMixinMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  @override
+  void endNamedFunctionExpression(Token endToken) {
+    listener?.endNamedFunctionExpression(endToken);
+  }
+
+  @override
+  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
+      Token implementsKeyword, Token endToken) {
+    listener?.endNamedMixinApplication(
+        begin, classKeyword, equals, implementsKeyword, endToken);
+  }
+
+  @override
+  void endNewExpression(Token token) {
+    listener?.endNewExpression(token);
+  }
+
+  @override
+  void endOptionalFormalParameters(
+      int count, Token beginToken, Token endToken) {
+    listener?.endOptionalFormalParameters(count, beginToken, endToken);
+  }
+
+  @override
+  void endPart(Token partKeyword, Token semicolon) {
+    listener?.endPart(partKeyword, semicolon);
+  }
+
+  @override
+  void endPartOf(
+      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+    listener?.endPartOf(partKeyword, ofKeyword, semicolon, hasName);
+  }
+
+  @override
+  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+    listener?.endRedirectingFactoryBody(beginToken, endToken);
+  }
+
+  @override
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    listener?.endRethrowStatement(rethrowToken, endToken);
+  }
+
+  @override
+  void endReturnStatement(
+      bool hasExpression, Token beginToken, Token endToken) {
+    listener?.endReturnStatement(hasExpression, beginToken, endToken);
+  }
+
+  @override
+  void endShow(Token showKeyword) {
+    listener?.endShow(showKeyword);
+  }
+
+  @override
+  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+    listener?.endSwitchBlock(caseCount, beginToken, endToken);
+  }
+
+  @override
+  void endSwitchCase(
+      int labelCount,
+      int expressionCount,
+      Token defaultKeyword,
+      Token colonAfterDefault,
+      int statementCount,
+      Token firstToken,
+      Token endToken) {
+    listener?.endSwitchCase(labelCount, expressionCount, defaultKeyword,
+        colonAfterDefault, statementCount, firstToken, endToken);
+  }
+
+  @override
+  void endSwitchStatement(Token switchKeyword, Token endToken) {
+    listener?.endSwitchStatement(switchKeyword, endToken);
+  }
+
+  @override
+  void endThenStatement(Token token) {
+    listener?.endThenStatement(token);
+  }
+
+  @override
+  void endTopLevelDeclaration(Token token) {
+    listener?.endTopLevelDeclaration(token);
+  }
+
+  @override
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    listener?.endTopLevelFields(staticToken, covariantToken, lateToken,
+        varFinalOrConst, count, beginToken, endToken);
+  }
+
+  @override
+  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+    listener?.endTopLevelMethod(beginToken, getOrSet, endToken);
+  }
+
+  @override
+  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+    listener?.endTryStatement(catchCount, tryKeyword, finallyKeyword);
+  }
+
+  @override
+  void endTypeArguments(int count, Token beginToken, Token endToken) {
+    listener?.endTypeArguments(count, beginToken, endToken);
+  }
+
+  @override
+  void endTypeList(int count) {
+    listener?.endTypeList(count);
+  }
+
+  @override
+  void endTypeVariable(
+      Token token, int index, Token extendsOrSuper, Token variance) {
+    listener?.endTypeVariable(token, index, extendsOrSuper, variance);
+  }
+
+  @override
+  void endTypeVariables(Token beginToken, Token endToken) {
+    listener?.endTypeVariables(beginToken, endToken);
+  }
+
+  @override
+  void endVariableInitializer(Token assignmentOperator) {
+    listener?.endVariableInitializer(assignmentOperator);
+  }
+
+  @override
+  void endVariablesDeclaration(int count, Token endToken) {
+    listener?.endVariablesDeclaration(count, endToken);
+  }
+
+  @override
+  void endWhileStatement(Token whileKeyword, Token endToken) {
+    listener?.endWhileStatement(whileKeyword, endToken);
+  }
+
+  @override
+  void endWhileStatementBody(Token token) {
+    listener?.endWhileStatementBody(token);
+  }
+
+  @override
+  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+    listener?.endYieldStatement(yieldToken, starToken, endToken);
+  }
+
+  @override
+  void handleAsOperator(Token operator) {
+    listener?.handleAsOperator(operator);
+  }
+
+  @override
+  void handleAssignmentExpression(Token token) {
+    listener?.handleAssignmentExpression(token);
+  }
+
+  @override
+  void handleAsyncModifier(Token asyncToken, Token starToken) {
+    listener?.handleAsyncModifier(asyncToken, starToken);
+  }
+
+  @override
+  void handleBreakStatement(
+      bool hasTarget, Token breakKeyword, Token endToken) {
+    listener?.handleBreakStatement(hasTarget, breakKeyword, endToken);
+  }
+
+  @override
+  void handleCaseMatch(Token caseKeyword, Token colon) {
+    listener?.handleCaseMatch(caseKeyword, colon);
+  }
+
+  @override
+  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+    listener?.handleCatchBlock(onKeyword, catchKeyword, comma);
+  }
+
+  @override
+  void handleClassExtends(Token extendsKeyword) {
+    listener?.handleClassExtends(extendsKeyword);
+  }
+
+  @override
+  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+    listener?.handleClassHeader(begin, classKeyword, nativeToken);
+  }
+
+  @override
+  void handleClassNoWithClause() {
+    listener?.handleClassNoWithClause();
+  }
+
+  @override
+  void handleClassOrMixinImplements(
+      Token implementsKeyword, int interfacesCount) {
+    listener?.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
+  }
+
+  @override
+  void handleClassWithClause(Token withKeyword) {
+    listener?.handleClassWithClause(withKeyword);
+  }
+
+  @override
+  void handleCommentReference(
+      Token newKeyword, Token prefix, Token period, Token token) {
+    listener?.handleCommentReference(newKeyword, prefix, period, token);
+  }
+
+  @override
+  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+    listener?.handleCommentReferenceText(referenceSource, referenceOffset);
+  }
+
+  @override
+  void handleConditionalExpressionColon() {
+    listener?.handleConditionalExpressionColon();
+  }
+
+  @override
+  void handleContinueStatement(
+      bool hasTarget, Token continueKeyword, Token endToken) {
+    listener?.handleContinueStatement(hasTarget, continueKeyword, endToken);
+  }
+
+  @override
+  void handleDirectivesOnly() {
+    listener?.handleDirectivesOnly();
+  }
+
+  @override
+  void handleDottedName(int count, Token firstIdentifier) {
+    listener?.handleDottedName(count, firstIdentifier);
+  }
+
+  @override
+  void handleElseControlFlow(Token elseToken) {
+    listener?.handleElseControlFlow(elseToken);
+  }
+
+  @override
+  void handleEmptyFunctionBody(Token semicolon) {
+    listener?.handleEmptyFunctionBody(semicolon);
+  }
+
+  @override
+  void handleEmptyStatement(Token token) {
+    listener?.handleEmptyStatement(token);
+  }
+
+  @override
+  void handleErrorToken(ErrorToken token) {
+    listener?.handleErrorToken(token);
+  }
+
+  @override
+  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+    listener?.handleExpressionFunctionBody(arrowToken, endToken);
+  }
+
+  @override
+  void handleExpressionStatement(Token token) {
+    listener?.handleExpressionStatement(token);
+  }
+
+  @override
+  void handleExtraneousExpression(Token token, Message message) {
+    listener?.handleExtraneousExpression(token, message);
+  }
+
+  @override
+  void handleFinallyBlock(Token finallyKeyword) {
+    listener?.handleFinallyBlock(finallyKeyword);
+  }
+
+  @override
+  void handleForInitializerEmptyStatement(Token token) {
+    listener?.handleForInitializerEmptyStatement(token);
+  }
+
+  @override
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
+    listener?.handleForInitializerExpressionStatement(token, forIn);
+  }
+
+  @override
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
+    listener?.handleForInitializerLocalVariableDeclaration(token, forIn);
+  }
+
+  @override
+  void handleForInLoopParts(Token awaitToken, Token forToken,
+      Token leftParenthesis, Token inKeyword) {
+    listener?.handleForInLoopParts(
+        awaitToken, forToken, leftParenthesis, inKeyword);
+  }
+
+  @override
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {
+    listener?.handleForLoopParts(
+        forKeyword, leftParen, leftSeparator, updateExpressionCount);
+  }
+
+  @override
+  void handleFormalParameterWithoutValue(Token token) {
+    listener?.handleFormalParameterWithoutValue(token);
+  }
+
+  @override
+  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
+    listener?.handleFunctionBodySkipped(token, isExpressionBody);
+  }
+
+  @override
+  void handleIdentifier(Token token, IdentifierContext context) {
+    listener?.handleIdentifier(token, context);
+  }
+
+  @override
+  void handleIdentifierList(int count) {
+    listener?.handleIdentifierList(count);
+  }
+
+  @override
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    listener?.handleImportPrefix(deferredKeyword, asKeyword);
+  }
+
+  @override
+  void handleIndexedExpression(
+      Token openSquareBracket, Token closeSquareBracket) {
+    listener?.handleIndexedExpression(openSquareBracket, closeSquareBracket);
+  }
+
+  @override
+  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
+    listener?.handleInterpolationExpression(leftBracket, rightBracket);
+  }
+
+  @override
+  void handleInvalidExpression(Token token) {
+    listener?.handleInvalidExpression(token);
+  }
+
+  @override
+  void handleInvalidFunctionBody(Token token) {
+    listener?.handleInvalidFunctionBody(token);
+  }
+
+  @override
+  void handleInvalidMember(Token endToken) {
+    listener?.handleInvalidMember(endToken);
+  }
+
+  @override
+  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+    listener?.handleInvalidOperatorName(operatorKeyword, token);
+  }
+
+  @override
+  void handleInvalidStatement(Token token, Message message) {
+    listener?.handleInvalidStatement(token, message);
+  }
+
+  void handleInvalidTopLevelBlock(Token token) {
+    listener?.handleInvalidTopLevelBlock(token);
+  }
+
+  @override
+  void handleInvalidTopLevelDeclaration(Token endToken) {
+    listener?.handleInvalidTopLevelDeclaration(endToken);
+  }
+
+  @override
+  void handleInvalidTypeArguments(Token token) {
+    listener?.handleInvalidTypeArguments(token);
+  }
+
+  @override
+  void handleInvalidTypeReference(Token token) {
+    listener?.handleInvalidTypeReference(token);
+  }
+
+  @override
+  void handleIsOperator(Token isOperator, Token not) {
+    listener?.handleIsOperator(isOperator, not);
+  }
+
+  @override
+  void handleLabel(Token token) {
+    listener?.handleLabel(token);
+  }
+
+  @override
+  void handleLiteralBool(Token token) {
+    listener?.handleLiteralBool(token);
+  }
+
+  @override
+  void handleLiteralDouble(Token token) {
+    listener?.handleLiteralDouble(token);
+  }
+
+  @override
+  void handleLiteralInt(Token token) {
+    listener?.handleLiteralInt(token);
+  }
+
+  @override
+  void handleLiteralList(
+      int count, Token beginToken, Token constKeyword, Token endToken) {
+    listener?.handleLiteralList(count, beginToken, constKeyword, endToken);
+  }
+
+  @override
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    listener?.handleLiteralMapEntry(colon, endToken);
+  }
+
+  @override
+  void handleLiteralNull(Token token) {
+    listener?.handleLiteralNull(token);
+  }
+
+  @override
+  void handleLiteralSetOrMap(
+    int count,
+    Token leftBrace,
+    Token constKeyword,
+    Token rightBrace,
+    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+    // behavior and will be removed once unified collection has been enabled
+    bool hasSetEntry,
+  ) {
+    listener?.handleLiteralSetOrMap(
+        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
+  }
+
+  @override
+  void handleMixinHeader(Token mixinKeyword) {
+    listener?.handleMixinHeader(mixinKeyword);
+  }
+
+  @override
+  void handleMixinOn(Token onKeyword, int typeCount) {
+    listener?.handleMixinOn(onKeyword, typeCount);
+  }
+
+  @override
+  void handleNamedArgument(Token colon) {
+    listener?.handleNamedArgument(colon);
+  }
+
+  @override
+  void handleNamedMixinApplicationWithClause(Token withKeyword) {
+    listener?.handleNamedMixinApplicationWithClause(withKeyword);
+  }
+
+  @override
+  void handleNativeClause(Token nativeToken, bool hasName) {
+    listener?.handleNativeClause(nativeToken, hasName);
+  }
+
+  @override
+  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+    listener?.handleNativeFunctionBody(nativeToken, semicolon);
+  }
+
+  @override
+  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+    listener?.handleNativeFunctionBodyIgnored(nativeToken, semicolon);
+  }
+
+  @override
+  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+    listener?.handleNativeFunctionBodySkipped(nativeToken, semicolon);
+  }
+
+  @override
+  void handleNoArguments(Token token) {
+    listener?.handleNoArguments(token);
+  }
+
+  @override
+  void handleNoCommentReference() {
+    listener?.handleNoCommentReference();
+  }
+
+  @override
+  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+    listener?.handleNoConstructorReferenceContinuationAfterTypeArguments(token);
+  }
+
+  @override
+  void handleNoFieldInitializer(Token token) {
+    listener?.handleNoFieldInitializer(token);
+  }
+
+  @override
+  void handleNoFormalParameters(Token token, MemberKind kind) {
+    listener?.handleNoFormalParameters(token, kind);
+  }
+
+  @override
+  void handleNoFunctionBody(Token token) {
+    listener?.handleNoFunctionBody(token);
+  }
+
+  @override
+  void handleNoInitializers() {
+    listener?.handleNoInitializers();
+  }
+
+  @override
+  void handleNoName(Token token) {
+    listener?.handleNoName(token);
+  }
+
+  @override
+  void handleNonNullAssertExpression(Token bang) {
+    listener?.handleNonNullAssertExpression(bang);
+  }
+
+  @override
+  void handleNoType(Token lastConsumed) {
+    listener?.handleNoType(lastConsumed);
+  }
+
+  @override
+  void handleNoTypeArguments(Token token) {
+    listener?.handleNoTypeArguments(token);
+  }
+
+  @override
+  void handleNoTypeVariables(Token token) {
+    listener?.handleNoTypeVariables(token);
+  }
+
+  @override
+  void handleNoVariableInitializer(Token token) {
+    listener?.handleNoVariableInitializer(token);
+  }
+
+  @override
+  void handleOperator(Token token) {
+    listener?.handleOperator(token);
+  }
+
+  @override
+  void handleOperatorName(Token operatorKeyword, Token token) {
+    listener?.handleOperatorName(operatorKeyword, token);
+  }
+
+  @override
+  void handleParenthesizedCondition(Token token) {
+    listener?.handleParenthesizedCondition(token);
+  }
+
+  @override
+  void handleParenthesizedExpression(Token token) {
+    listener?.handleParenthesizedExpression(token);
+  }
+
+  @override
+  void handleQualified(Token period) {
+    listener?.handleQualified(period);
+  }
+
+  @override
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    if (forwardErrors) {
+      listener?.handleRecoverableError(message, startToken, endToken);
+    }
+  }
+
+  @override
+  void handleRecoverClassHeader() {
+    listener?.handleRecoverClassHeader();
+  }
+
+  @override
+  void handleRecoverImport(Token semicolon) {
+    listener?.handleRecoverImport(semicolon);
+  }
+
+  @override
+  void handleRecoverMixinHeader() {
+    listener?.handleRecoverMixinHeader();
+  }
+
+  @override
+  void handleScript(Token token) {
+    listener?.handleScript(token);
+  }
+
+  @override
+  void handleSend(Token beginToken, Token endToken) {
+    listener?.handleSend(beginToken, endToken);
+  }
+
+  @override
+  void handleSpreadExpression(Token spreadToken) {
+    listener?.handleSpreadExpression(spreadToken);
+  }
+
+  @override
+  void handleStringJuxtaposition(int literalCount) {
+    listener?.handleStringJuxtaposition(literalCount);
+  }
+
+  @override
+  void handleStringPart(Token token) {
+    listener?.handleStringPart(token);
+  }
+
+  @override
+  void handleSuperExpression(Token token, IdentifierContext context) {
+    listener?.handleSuperExpression(token, context);
+  }
+
+  @override
+  void handleSymbolVoid(Token token) {
+    listener?.handleSymbolVoid(token);
+  }
+
+  @override
+  void handleThisExpression(Token token, IdentifierContext context) {
+    listener?.handleThisExpression(token, context);
+  }
+
+  @override
+  void handleThrowExpression(Token throwToken, Token endToken) {
+    listener?.handleThrowExpression(throwToken, endToken);
+  }
+
+  @override
+  void handleType(Token beginToken, Token questionMark) {
+    listener?.handleType(beginToken, questionMark);
+  }
+
+  @override
+  void handleTypeVariablesDefined(Token token, int count) {
+    listener?.handleTypeVariablesDefined(token, count);
+  }
+
+  @override
+  void handleUnaryPostfixAssignmentExpression(Token token) {
+    listener?.handleUnaryPostfixAssignmentExpression(token);
+  }
+
+  @override
+  void handleUnaryPrefixAssignmentExpression(Token token) {
+    listener?.handleUnaryPrefixAssignmentExpression(token);
+  }
+
+  @override
+  void handleUnaryPrefixExpression(Token token) {
+    listener?.handleUnaryPrefixExpression(token);
+  }
+
+  @override
+  void handleUnescapeError(
+      Message message, Token location, int offset, int length) {
+    listener?.handleUnescapeError(message, location, offset, length);
+  }
+
+  @override
+  void handleValuedFormalParameter(Token equals, Token token) {
+    listener?.handleValuedFormalParameter(equals, token);
+  }
+
+  @override
+  void handleVoidKeyword(Token token) {
+    listener?.handleVoidKeyword(token);
+  }
+
+  @override
+  void logEvent(String name) {
+    listener?.logEvent(name);
+  }
+
+  @override
+  void reportErrorIfNullableType(Token questionMark) {
+    listener?.reportErrorIfNullableType(questionMark);
+  }
+
+  @override
+  void reportNonNullableModifierError(Token modifierToken) {
+    listener?.reportNonNullableModifierError(modifierToken);
+  }
+
+  @override
+  void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    listener?.reportNonNullAssertExpressionNotEnabled(bang);
+  }
+
+  @override
+  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
new file mode 100644
index 0000000..d6c3b37
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context.dart
@@ -0,0 +1,334 @@
+// 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 '../messages/codes.dart'
+    show Message, Template, templateExpectedIdentifier;
+
+import '../scanner/token.dart' show Token, TokenType;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'identifier_context_impl.dart';
+
+import 'parser_impl.dart' show Parser;
+
+import 'util.dart' show isOneOfOrEof, optional;
+
+/// Information about the parser state that is passed to the listener at the
+/// time an identifier is encountered. It is also used by the parser for error
+/// recovery when a recovery template is defined.
+///
+/// This can be used by the listener to determine the context in which the
+/// identifier appears; that in turn can help the listener decide how to resolve
+/// the identifier (if the listener is doing resolution).
+class IdentifierContext {
+  /// Identifier is being declared as the name of an import prefix (i.e. `Foo`
+  /// in `import "..." as Foo;`)
+  static const ImportPrefixIdentifierContext importPrefixDeclaration =
+      const ImportPrefixIdentifierContext();
+
+  /// Identifier is the start of a dotted name in a conditional import or
+  /// export.
+  static const DottedNameIdentifierContext dottedName =
+      const DottedNameIdentifierContext();
+
+  /// Identifier is part of a dotted name in a conditional import or export, but
+  /// it's not the first identifier of the dotted name.
+  static const DottedNameIdentifierContext dottedNameContinuation =
+      const DottedNameIdentifierContext.continuation();
+
+  /// Identifier is one of the shown/hidden names in an import/export
+  /// combinator.
+  static const CombinatorIdentifierContext combinator =
+      const CombinatorIdentifierContext();
+
+  /// Identifier is the start of a name in an annotation that precedes a
+  /// declaration (i.e. it appears directly after an `@`).
+  static const MetadataReferenceIdentifierContext metadataReference =
+      const MetadataReferenceIdentifierContext();
+
+  /// Identifier is part of a name in an annotation that precedes a declaration,
+  /// but it's not the first identifier in the name.
+  static const MetadataReferenceIdentifierContext metadataContinuation =
+      const MetadataReferenceIdentifierContext.continuation();
+
+  /// Identifier is part of a name in an annotation that precedes a declaration,
+  /// but it appears after type parameters (e.g. `foo` in `@X<Y>.foo()`).
+  static const MetadataReferenceIdentifierContext
+      metadataContinuationAfterTypeArguments =
+      const MetadataReferenceIdentifierContext.continuationAfterTypeArguments();
+
+  /// Identifier is the name being declared by a typedef declaration.
+  static const TypedefDeclarationIdentifierContext typedefDeclaration =
+      const TypedefDeclarationIdentifierContext();
+
+  /// Identifier is a field initializer in a formal parameter list (i.e. it
+  /// appears directly after `this.`).
+  static const FieldInitializerIdentifierContext fieldInitializer =
+      const FieldInitializerIdentifierContext();
+
+  /// Identifier is a formal parameter being declared as part of a function,
+  /// method, or typedef declaration.
+  static const FormalParameterDeclarationIdentifierContext
+      formalParameterDeclaration =
+      const FormalParameterDeclarationIdentifierContext();
+
+  /// Identifier is a formal parameter being declared as part of a catch block
+  /// in a try/catch/finally statement.
+  static const CatchParameterIdentifierContext catchParameter =
+      const CatchParameterIdentifierContext();
+
+  /// Identifier is the start of a library name (e.g. `foo` in the directive
+  /// 'library foo;`).
+  static const LibraryIdentifierContext libraryName =
+      const LibraryIdentifierContext();
+
+  /// Identifier is part of a library name, but it's not the first identifier in
+  /// the name.
+  static const LibraryIdentifierContext libraryNameContinuation =
+      const LibraryIdentifierContext.continuation();
+
+  /// Identifier is the start of a library name referenced by a `part of`
+  /// directive (e.g. `foo` in the directive `part of foo;`).
+  static const LibraryIdentifierContext partName =
+      const LibraryIdentifierContext.partName();
+
+  /// Identifier is part of a library name referenced by a `part of` directive,
+  /// but it's not the first identifier in the name.
+  static const LibraryIdentifierContext partNameContinuation =
+      const LibraryIdentifierContext.partNameContinuation();
+
+  /// Identifier is the type name being declared by an enum declaration.
+  static const EnumDeclarationIdentifierContext enumDeclaration =
+      const EnumDeclarationIdentifierContext();
+
+  /// Identifier is an enumerated value name being declared by an enum
+  /// declaration.
+  static const EnumValueDeclarationIdentifierContext enumValueDeclaration =
+      const EnumValueDeclarationIdentifierContext();
+
+  /// Identifier is the name being declared by a class declaration, a mixin
+  /// declaration, or a named mixin application, for example,
+  /// `Foo` in `class Foo = X with Y;`.
+  static const ClassOrMixinOrExtensionIdentifierContext
+      classOrMixinOrExtensionDeclaration =
+      const ClassOrMixinOrExtensionIdentifierContext();
+
+  /// Identifier is the name of a type variable being declared (e.g. `Foo` in
+  /// `class C<Foo extends num> {}`).
+  static const TypeVariableDeclarationIdentifierContext
+      typeVariableDeclaration =
+      const TypeVariableDeclarationIdentifierContext();
+
+  /// Identifier is the start of a reference to a type that starts with prefix.
+  static const TypeReferenceIdentifierContext prefixedTypeReference =
+      const TypeReferenceIdentifierContext.prefixed();
+
+  /// Identifier is the start of a reference to a type declared elsewhere.
+  static const TypeReferenceIdentifierContext typeReference =
+      const TypeReferenceIdentifierContext();
+
+  /// Identifier is part of a reference to a type declared elsewhere, but it's
+  /// not the first identifier of the reference.
+  static const TypeReferenceIdentifierContext typeReferenceContinuation =
+      const TypeReferenceIdentifierContext.continuation();
+
+  /// Identifier is a name being declared by a top level variable declaration.
+  static const TopLevelDeclarationIdentifierContext
+      topLevelVariableDeclaration = const TopLevelDeclarationIdentifierContext(
+          'topLevelVariableDeclaration', const [';', '=', ',']);
+
+  /// Identifier is a name being declared by a field declaration.
+  static const FieldDeclarationIdentifierContext fieldDeclaration =
+      const FieldDeclarationIdentifierContext();
+
+  /// Identifier is the name being declared by a top level function declaration.
+  static const TopLevelDeclarationIdentifierContext
+      topLevelFunctionDeclaration = const TopLevelDeclarationIdentifierContext(
+          'topLevelFunctionDeclaration', const ['<', '(', '{', '=>']);
+
+  /// Identifier is the start of the name being declared by a method
+  /// declaration.
+  static const MethodDeclarationIdentifierContext methodDeclaration =
+      const MethodDeclarationIdentifierContext();
+
+  /// Identifier is part of the name being declared by a method declaration,
+  /// but it's not the first identifier of the name.
+  ///
+  /// In valid Dart, this can only happen if the identifier is the name of a
+  /// named constructor which is being declared, e.g. `foo` in
+  /// `class C { C.foo(); }`.
+  static const MethodDeclarationIdentifierContext
+      methodDeclarationContinuation =
+      const MethodDeclarationIdentifierContext.continuation();
+
+  /// Identifier appears after the word `operator` in a method declaration.
+  ///
+  /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
+  /// occur as part of error recovery?  If it's only as part of error recovery,
+  /// perhaps we should just re-use methodDeclaration.
+  static const MethodDeclarationIdentifierContext operatorName =
+      const MethodDeclarationIdentifierContext.continuation();
+
+  /// Identifier is the start of the name being declared by a local function
+  /// declaration.
+  static const LocalFunctionDeclarationIdentifierContext
+      localFunctionDeclaration =
+      const LocalFunctionDeclarationIdentifierContext();
+
+  /// Identifier is part of the name being declared by a local function
+  /// declaration, but it's not the first identifier of the name.
+  ///
+  /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
+  /// occur as part of error recovery?
+  static const LocalFunctionDeclarationIdentifierContext
+      localFunctionDeclarationContinuation =
+      const LocalFunctionDeclarationIdentifierContext.continuation();
+
+  /// Identifier is the start of a reference to a constructor declared
+  /// elsewhere.
+  static const ConstructorReferenceIdentifierContext constructorReference =
+      const ConstructorReferenceIdentifierContext();
+
+  /// Identifier is part of a reference to a constructor declared elsewhere, but
+  /// it's not the first identifier of the reference.
+  static const ConstructorReferenceIdentifierContext
+      constructorReferenceContinuation =
+      const ConstructorReferenceIdentifierContext.continuation();
+
+  /// Identifier is part of a reference to a constructor declared elsewhere, but
+  /// it appears after type parameters (e.g. `foo` in `X<Y>.foo`).
+  static const ConstructorReferenceIdentifierContext
+      constructorReferenceContinuationAfterTypeArguments =
+      const ConstructorReferenceIdentifierContext
+          .continuationAfterTypeArguments();
+
+  /// Identifier is the declaration of a label (i.e. it is followed by `:` and
+  /// then a statement).
+  static const LabelDeclarationIdentifierContext labelDeclaration =
+      const LabelDeclarationIdentifierContext();
+
+  /// Identifier is the start of a reference occurring in a literal symbol (e.g.
+  /// `foo` in `#foo`).
+  static const LiteralSymbolIdentifierContext literalSymbol =
+      const LiteralSymbolIdentifierContext();
+
+  /// Identifier is part of a reference occurring in a literal symbol, but it's
+  /// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
+  static const LiteralSymbolIdentifierContext literalSymbolContinuation =
+      const LiteralSymbolIdentifierContext.continuation();
+
+  /// Identifier appears in an expression, and it does not immediately follow a
+  /// `.`.
+  static const ExpressionIdentifierContext expression =
+      const ExpressionIdentifierContext();
+
+  /// Identifier appears in an expression, and it immediately follows a `.`.
+  static const ExpressionIdentifierContext expressionContinuation =
+      const ExpressionIdentifierContext.continuation();
+
+  /// Identifier is a reference to a named argument of a function or method
+  /// invocation (e.g. `foo` in `f(foo: 0);`.
+  static const NamedArgumentReferenceIdentifierContext namedArgumentReference =
+      const NamedArgumentReferenceIdentifierContext();
+
+  /// Identifier is a name being declared by a local variable declaration.
+  static const LocalVariableDeclarationIdentifierContext
+      localVariableDeclaration =
+      const LocalVariableDeclarationIdentifierContext();
+
+  /// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
+  /// Labels have their own scope.
+  static const LabelReferenceIdentifierContext labelReference =
+      const LabelReferenceIdentifierContext();
+
+  final String _name;
+
+  /// Indicates whether the identifier represents a name which is being
+  /// declared.
+  final bool inDeclaration;
+
+  /// Indicates whether the identifier is within a `library` or `part of`
+  /// declaration.
+  final bool inLibraryOrPartOfDeclaration;
+
+  /// Indicates whether the identifier is within a symbol literal.
+  final bool inSymbol;
+
+  /// Indicates whether the identifier follows a `.`.
+  final bool isContinuation;
+
+  /// Indicates whether the identifier should be looked up in the current scope.
+  final bool isScopeReference;
+
+  /// Indicates whether built-in identifiers are allowed in this context.
+  final bool isBuiltInIdentifierAllowed;
+
+  /// Indicated whether the identifier is allowed in a context where constant
+  /// expressions are required.
+  final bool allowedInConstantExpression;
+
+  final Template<_MessageWithArgument<Token>> recoveryTemplate;
+
+  const IdentifierContext(this._name,
+      {this.inDeclaration: false,
+      this.inLibraryOrPartOfDeclaration: false,
+      this.inSymbol: false,
+      this.isContinuation: false,
+      this.isScopeReference: false,
+      this.isBuiltInIdentifierAllowed: true,
+      bool allowedInConstantExpression,
+      this.recoveryTemplate: templateExpectedIdentifier})
+      : this.allowedInConstantExpression =
+            // Generally, declarations are legal in constant expressions.  A
+            // continuation doesn't affect constant expressions: if what it's
+            // continuing is a problem, it has already been reported.
+            allowedInConstantExpression ??
+                (inDeclaration || isContinuation || inSymbol);
+
+  String toString() => _name;
+
+  /// Ensure that the next token is an identifier (or keyword which should be
+  /// treated as an identifier) and return that identifier.
+  /// Report errors as necessary via [parser].
+  Token ensureIdentifier(Token token, Parser parser) {
+    assert(token.next.kind != IDENTIFIER_TOKEN);
+    // TODO(danrubel): Implement this method for each identifier context
+    // such that they return a non-null value.
+    return null;
+  }
+}
+
+/// Return `true` if the given [token] should be treated like the start of
+/// an expression for the purposes of recovery.
+bool looksLikeExpressionStart(Token next) =>
+    next.isIdentifier ||
+    next.isKeyword && !looksLikeStatementStart(next) ||
+    next.type == TokenType.DOUBLE ||
+    next.type == TokenType.HASH ||
+    next.type == TokenType.HEXADECIMAL ||
+    next.type == TokenType.IDENTIFIER ||
+    next.type == TokenType.INT ||
+    next.type == TokenType.STRING ||
+    optional('{', next) ||
+    optional('(', next) ||
+    optional('[', next) ||
+    optional('[]', next) ||
+    optional('<', next) ||
+    optional('!', next) ||
+    optional('-', next) ||
+    optional('~', next) ||
+    optional('++', next) ||
+    optional('--', next);
+
+/// Return `true` if the given [token] should be treated like the start of
+/// a new statement for the purposes of recovery.
+bool looksLikeStatementStart(Token token) => isOneOfOrEof(token, const [
+      '@',
+      'assert', 'break', 'continue', 'do', 'else', 'final', 'for', //
+      'if', 'return', 'switch', 'try', 'var', 'void', 'while', //
+    ]);
+
+// TODO(ahe): Remove when analyzer supports generalized function syntax.
+typedef _MessageWithArgument<T> = Message Function(T);
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
new file mode 100644
index 0000000..e8665fa
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -0,0 +1,989 @@
+// 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 '../messages/codes.dart' as codes;
+
+import '../scanner/token.dart' show Token;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN, STRING_TOKEN;
+
+import 'identifier_context.dart';
+
+import 'parser_impl.dart' show Parser;
+
+import 'type_info.dart' show isValidTypeReference;
+
+import 'util.dart' show isOneOfOrEof, optional;
+
+/// See [IdentifierContext.catchParameter].
+class CatchParameterIdentifierContext extends IdentifierContext {
+  const CatchParameterIdentifierContext() : super('catchParameter');
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    parser.reportRecoverableError(identifier, codes.messageCatchSyntax);
+    if (looksLikeStatementStart(identifier) ||
+        isOneOfOrEof(identifier, const [',', ')'])) {
+      return parser.rewriter.insertSyntheticIdentifier(token);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.rewriter.insertSyntheticIdentifier(identifier);
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.classOrMixinOrExtensionDeclaration].
+class ClassOrMixinOrExtensionIdentifierContext extends IdentifierContext {
+  const ClassOrMixinOrExtensionIdentifierContext()
+      : super('classOrMixinDeclaration',
+            inDeclaration: true, isBuiltInIdentifierAllowed: false);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.type.isPseudo) {
+      return identifier;
+    }
+
+    // Recovery
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier,
+            const ['<', '{', 'extends', 'with', 'implements', 'on'])) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else if (identifier.type.isBuiltIn) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.combinator].
+class CombinatorIdentifierContext extends IdentifierContext {
+  const CombinatorIdentifierContext() : super('combinator');
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    const List<String> followingValues = const [
+      ';',
+      ',',
+      'if',
+      'as',
+      'show',
+      'hide'
+    ];
+
+    if (identifier.isIdentifier) {
+      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+          isOneOfOrEof(identifier.next, followingValues)) {
+        return identifier;
+      }
+      // Although this is a valid identifier name, the import declaration
+      // is invalid and this looks like the start of the next declaration.
+      // In this situation, fall through to insert a synthetic identifier.
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, followingValues) ||
+        looksLikeStartOfNextTopLevelDeclaration(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.constructorReference]
+/// and [IdentifierContext.constructorReferenceContinuation]
+/// and [IdentifierContext.constructorReferenceContinuationAfterTypeArguments].
+class ConstructorReferenceIdentifierContext extends IdentifierContext {
+  const ConstructorReferenceIdentifierContext()
+      : super('constructorReference', isScopeReference: true);
+
+  const ConstructorReferenceIdentifierContext.continuation()
+      : super('constructorReferenceContinuation', isContinuation: true);
+
+  const ConstructorReferenceIdentifierContext.continuationAfterTypeArguments()
+      : super('constructorReferenceContinuationAfterTypeArguments',
+            isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (!identifier.isKeywordOrIdentifier) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.dottedName].
+class DottedNameIdentifierContext extends IdentifierContext {
+  const DottedNameIdentifierContext() : super('dottedName');
+
+  const DottedNameIdentifierContext.continuation()
+      : super('dottedNameContinuation', isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    const List<String> followingValues = const ['.', '==', ')'];
+
+    if (identifier.isIdentifier) {
+      // DottedNameIdentifierContext are only used in conditional import
+      // expressions. Although some top level keywords such as `import` can be
+      // used as identifiers, they are more likely the start of the next
+      // directive or declaration.
+      if (!identifier.isTopLevelKeyword ||
+          isOneOfOrEof(identifier.next, followingValues)) {
+        return identifier;
+      }
+    }
+
+    // Recovery
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.enumDeclaration].
+class EnumDeclarationIdentifierContext extends IdentifierContext {
+  const EnumDeclarationIdentifierContext()
+      : super('enumDeclaration',
+            inDeclaration: true, isBuiltInIdentifierAllowed: false);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.type.isPseudo) {
+      return identifier;
+    }
+
+    // Recovery
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, const ['{'])) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else if (identifier.type.isBuiltIn) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.enumValueDeclaration].
+class EnumValueDeclarationIdentifierContext extends IdentifierContext {
+  const EnumValueDeclarationIdentifierContext()
+      : super('enumValueDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        identifier, codes.templateExpectedIdentifier);
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, const [',', '}'])) {
+      return parser.rewriter.insertSyntheticIdentifier(token);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.rewriter.insertSyntheticIdentifier(identifier);
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.expression].
+class ExpressionIdentifierContext extends IdentifierContext {
+  const ExpressionIdentifierContext()
+      : super('expression', isScopeReference: true);
+
+  const ExpressionIdentifierContext.continuation()
+      : super('expressionContinuation', isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.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
+        // rather than the token following it.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateUnexpectedToken);
+
+        // 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;
+      } else {
+        checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      }
+      return identifier;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        identifier, codes.templateExpectedIdentifier);
+    if (optional(r'$', token) &&
+        identifier.isKeyword &&
+        identifier.next.kind == STRING_TOKEN) {
+      // Keyword used as identifier in string interpolation
+      return identifier;
+    } else if (!looksLikeStatementStart(identifier)) {
+      if (identifier.isKeywordOrIdentifier) {
+        if (isContinuation || !isOneOfOrEof(identifier, const ['as', 'is'])) {
+          return identifier;
+        }
+      } else if (!identifier.isOperator &&
+          !isOneOfOrEof(identifier,
+              const ['.', ',', '(', ')', '[', ']', '{', '}', '?', ':', ';'])) {
+        // When in doubt, consume the token to ensure we make progress
+        token = identifier;
+        identifier = token.next;
+      }
+    }
+    // Insert a synthetic identifier to satisfy listeners.
+    return parser.rewriter.insertSyntheticIdentifier(token);
+  }
+}
+
+/// See [IdentifierContext.fieldDeclaration].
+class FieldDeclarationIdentifierContext extends IdentifierContext {
+  const FieldDeclarationIdentifierContext()
+      : super('fieldDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const [';', '=', ',', '}']) ||
+        looksLikeStartOfNextClassMember(identifier)) {
+      return parser.insertSyntheticIdentifier(token, this);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier),
+          messageOnToken: identifier);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      return identifier;
+    }
+  }
+}
+
+/// See [IdentifierContext.fieldInitializer].
+class FieldInitializerIdentifierContext extends IdentifierContext {
+  const FieldInitializerIdentifierContext()
+      : super('fieldInitializer', isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    assert(optional('.', token));
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        identifier, codes.templateExpectedIdentifier);
+    // Insert a synthetic identifier to satisfy listeners.
+    return parser.rewriter.insertSyntheticIdentifier(token);
+  }
+}
+
+/// See [IdentifierContext.formalParameterDeclaration].
+class FormalParameterDeclarationIdentifierContext extends IdentifierContext {
+  const FormalParameterDeclarationIdentifierContext()
+      : super('formalParameterDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    const List<String> followingValues = const [
+      ':',
+      '=',
+      ',',
+      '(',
+      ')',
+      '[',
+      ']',
+      '{',
+      '}'
+    ];
+    if (looksLikeStartOfNextClassMember(identifier) ||
+        looksLikeStatementStart(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.importPrefixDeclaration].
+class ImportPrefixIdentifierContext extends IdentifierContext {
+  const ImportPrefixIdentifierContext()
+      : super('importPrefixDeclaration',
+            inDeclaration: true, isBuiltInIdentifierAllowed: false);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.type.isPseudo) {
+      return identifier;
+    }
+
+    // Recovery
+    const List<String> followingValues = const [
+      ';',
+      'if',
+      'show',
+      'hide',
+      'deferred',
+      'as'
+    ];
+    if (identifier.type.isBuiltIn &&
+        isOneOfOrEof(identifier.next, followingValues)) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+class LiteralSymbolIdentifierContext extends IdentifierContext {
+  const LiteralSymbolIdentifierContext()
+      : super('literalSymbol', inSymbol: true);
+
+  const LiteralSymbolIdentifierContext.continuation()
+      : super('literalSymbolContinuation',
+            inSymbol: true, isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+
+    // Recovery
+    return parser.insertSyntheticIdentifier(token, this,
+        message: codes.templateExpectedIdentifier.withArguments(identifier));
+  }
+}
+
+/// See [IdentifierContext.localFunctionDeclaration]
+/// and [IdentifierContext.localFunctionDeclarationContinuation].
+class LocalFunctionDeclarationIdentifierContext extends IdentifierContext {
+  const LocalFunctionDeclarationIdentifierContext()
+      : super('localFunctionDeclaration', inDeclaration: true);
+
+  const LocalFunctionDeclarationIdentifierContext.continuation()
+      : super('localFunctionDeclarationContinuation',
+            inDeclaration: true, isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const ['.', '(', '{', '=>']) ||
+        looksLikeStatementStart(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.labelDeclaration].
+class LabelDeclarationIdentifierContext extends IdentifierContext {
+  const LabelDeclarationIdentifierContext()
+      : super('labelDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const [':']) ||
+        looksLikeStatementStart(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.labelReference].
+class LabelReferenceIdentifierContext extends IdentifierContext {
+  const LabelReferenceIdentifierContext() : super('labelReference');
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const [';'])) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.libraryName],
+/// and [IdentifierContext.libraryNameContinuation]
+/// and [IdentifierContext.partName],
+/// and [IdentifierContext.partNameContinuation].
+class LibraryIdentifierContext extends IdentifierContext {
+  const LibraryIdentifierContext()
+      : super('libraryName', inLibraryOrPartOfDeclaration: true);
+
+  const LibraryIdentifierContext.continuation()
+      : super('libraryNameContinuation',
+            inLibraryOrPartOfDeclaration: true, isContinuation: true);
+
+  const LibraryIdentifierContext.partName()
+      : super('partName', inLibraryOrPartOfDeclaration: true);
+
+  const LibraryIdentifierContext.partNameContinuation()
+      : super('partNameContinuation',
+            inLibraryOrPartOfDeclaration: true, isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    const List<String> followingValues = const ['.', ';'];
+
+    if (identifier.isIdentifier) {
+      Token next = identifier.next;
+      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+          isOneOfOrEof(next, followingValues)) {
+        return identifier;
+      }
+      // Although this is a valid library name, the library declaration
+      // is invalid and this looks like the start of the next declaration.
+      // In this situation, fall through to insert a synthetic library name.
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, followingValues) ||
+        looksLikeStartOfNextTopLevelDeclaration(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.localVariableDeclaration].
+class LocalVariableDeclarationIdentifierContext extends IdentifierContext {
+  const LocalVariableDeclarationIdentifierContext()
+      : super('localVariableDeclaration', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const [';', '=', ',', '{', '}']) ||
+        looksLikeStatementStart(identifier) ||
+        identifier.kind == STRING_TOKEN) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.metadataReference]
+/// and [IdentifierContext.metadataContinuation]
+/// and [IdentifierContext.metadataContinuationAfterTypeArguments].
+class MetadataReferenceIdentifierContext extends IdentifierContext {
+  const MetadataReferenceIdentifierContext()
+      : super('metadataReference', isScopeReference: true);
+
+  const MetadataReferenceIdentifierContext.continuation()
+      : super('metadataContinuation', isContinuation: true);
+
+  const MetadataReferenceIdentifierContext.continuationAfterTypeArguments()
+      : super('metadataContinuationAfterTypeArguments', isContinuation: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const ['{', '}', '(', ')', ']']) ||
+        looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        looksLikeStartOfNextClassMember(identifier) ||
+        looksLikeStatementStart(identifier)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.methodDeclaration],
+/// and [IdentifierContext.methodDeclarationContinuation],
+/// and [IdentifierContext.operatorName].
+class MethodDeclarationIdentifierContext extends IdentifierContext {
+  const MethodDeclarationIdentifierContext()
+      : super('methodDeclaration', inDeclaration: true);
+
+  const MethodDeclarationIdentifierContext.continuation()
+      : super('methodDeclarationContinuation',
+            inDeclaration: true, isContinuation: true);
+
+  const MethodDeclarationIdentifierContext.operatorName()
+      : super('operatorName', inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      return identifier;
+    }
+
+    // Recovery
+    if (identifier.isUserDefinableOperator && !isContinuation) {
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: codes.messageMissingOperatorKeyword,
+          messageOnToken: identifier);
+    } else if (isOneOfOrEof(identifier, const ['.', '(', '{', '=>', '}']) ||
+        looksLikeStartOfNextClassMember(identifier)) {
+      return parser.insertSyntheticIdentifier(token, this);
+    } else if (!identifier.isKeywordOrIdentifier) {
+      // When in doubt, consume the token to ensure we make progress
+      // but insert a synthetic identifier to satisfy listeners.
+      return parser.insertSyntheticIdentifier(identifier, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier),
+          messageOnToken: identifier);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      return identifier;
+    }
+  }
+}
+
+/// See [IdentifierContext.namedArgumentReference].
+class NamedArgumentReferenceIdentifierContext extends IdentifierContext {
+  const NamedArgumentReferenceIdentifierContext()
+      : super('namedArgumentReference', allowedInConstantExpression: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.isIdentifier) {
+      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
+      return identifier;
+    }
+
+    // Recovery
+    if (isOneOfOrEof(identifier, const [':'])) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.topLevelFunctionDeclaration]
+/// and [IdentifierContext.topLevelVariableDeclaration].
+class TopLevelDeclarationIdentifierContext extends IdentifierContext {
+  final List<String> followingValues;
+
+  const TopLevelDeclarationIdentifierContext(String name, this.followingValues)
+      : super(name, inDeclaration: true);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+
+    if (identifier.isIdentifier) {
+      Token next = identifier.next;
+      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+          isOneOfOrEof(next, followingValues)) {
+        return identifier;
+      }
+      // Although this is a valid top level name, the declaration
+      // is invalid and this looks like the start of the next declaration.
+      // In this situation, fall through to insert a synthetic name.
+    }
+
+    // Recovery
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else if (identifier.type.isBuiltIn) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.typedefDeclaration].
+class TypedefDeclarationIdentifierContext extends IdentifierContext {
+  const TypedefDeclarationIdentifierContext()
+      : super('typedefDeclaration',
+            inDeclaration: true, isBuiltInIdentifierAllowed: false);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.type.isPseudo) {
+      if (optional('Function', identifier)) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
+      }
+      return identifier;
+    }
+
+    // Recovery
+    const List<String> followingValues = const ['(', '<', '=', ';'];
+    if (identifier.type.isBuiltIn &&
+        isOneOfOrEof(identifier.next, followingValues)) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      identifier = parser.insertSyntheticIdentifier(token, this,
+          message: codes.templateExpectedIdentifier.withArguments(identifier));
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+/// See [IdentifierContext.typeReference].
+class TypeReferenceIdentifierContext extends IdentifierContext {
+  const TypeReferenceIdentifierContext()
+      : super('typeReference',
+            isScopeReference: true,
+            isBuiltInIdentifierAllowed: false,
+            recoveryTemplate: codes.templateExpectedType);
+
+  const TypeReferenceIdentifierContext.continuation()
+      : super('typeReferenceContinuation',
+            isContinuation: true, isBuiltInIdentifierAllowed: false);
+
+  const TypeReferenceIdentifierContext.prefixed()
+      : super('prefixedTypeReference',
+            isScopeReference: true,
+            isBuiltInIdentifierAllowed: true,
+            recoveryTemplate: codes.templateExpectedType);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token next = token.next;
+    assert(next.kind != IDENTIFIER_TOKEN);
+    if (isValidTypeReference(next)) {
+      return next;
+    } else if (next.isKeywordOrIdentifier) {
+      if (optional("void", next)) {
+        parser.reportRecoverableError(next, codes.messageInvalidVoid);
+      } else if (next.type.isBuiltIn) {
+        if (!isBuiltInIdentifierAllowed) {
+          parser.reportRecoverableErrorWithToken(
+              next, codes.templateBuiltInIdentifierAsType);
+        }
+      } else if (optional('var', next)) {
+        parser.reportRecoverableError(next, codes.messageVarAsTypeName);
+      } else {
+        parser.reportRecoverableErrorWithToken(
+            next, codes.templateExpectedType);
+      }
+      return next;
+    }
+    parser.reportRecoverableErrorWithToken(next, codes.templateExpectedType);
+    if (!isOneOfOrEof(
+        next, const ['<', '>', ')', '[', ']', '[]', '{', '}', ',', ';'])) {
+      // When in doubt, consume the token to ensure we make progress
+      token = next;
+      next = token.next;
+    }
+    // Insert a synthetic identifier to satisfy listeners.
+    return parser.rewriter.insertSyntheticIdentifier(token);
+  }
+}
+
+// See [IdentifierContext.typeVariableDeclaration].
+class TypeVariableDeclarationIdentifierContext extends IdentifierContext {
+  const TypeVariableDeclarationIdentifierContext()
+      : super('typeVariableDeclaration',
+            inDeclaration: true, isBuiltInIdentifierAllowed: false);
+
+  @override
+  Token ensureIdentifier(Token token, Parser parser) {
+    Token identifier = token.next;
+    assert(identifier.kind != IDENTIFIER_TOKEN);
+    if (identifier.type.isPseudo) {
+      return identifier;
+    }
+
+    // Recovery
+    const List<String> followingValues = const [
+      '<',
+      '>',
+      ';',
+      '}',
+      'extends',
+      'super'
+    ];
+    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
+        looksLikeStartOfNextClassMember(identifier) ||
+        looksLikeStatementStart(identifier) ||
+        isOneOfOrEof(identifier, followingValues)) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      identifier = parser.rewriter.insertSyntheticIdentifier(token);
+    } else if (identifier.type.isBuiltIn) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateBuiltInIdentifierInDeclaration);
+    } else {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+      if (!identifier.isKeywordOrIdentifier) {
+        // When in doubt, consume the token to ensure we make progress
+        // but insert a synthetic identifier to satisfy listeners.
+        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      }
+    }
+    return identifier;
+  }
+}
+
+void checkAsyncAwaitYieldAsIdentifier(Token identifier, Parser parser) {
+  if (!parser.inPlainSync && identifier.type.isPseudo) {
+    if (optional('await', identifier)) {
+      parser.reportRecoverableError(identifier, codes.messageAwaitAsIdentifier);
+    } else if (optional('yield', identifier)) {
+      parser.reportRecoverableError(identifier, codes.messageYieldAsIdentifier);
+    }
+  }
+}
+
+bool looksLikeStartOfNextClassMember(Token token) =>
+    token.isModifier || isOneOfOrEof(token, const ['@', 'get', 'set', 'void']);
+
+bool looksLikeStartOfNextTopLevelDeclaration(Token token) =>
+    token.isTopLevelKeyword ||
+    isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
new file mode 100644
index 0000000..8780250
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -0,0 +1,1650 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.parser.listener;
+
+import '../messages/codes.dart'
+    show Message, MessageCode, templateExperimentNotEnabled;
+
+import '../scanner/token.dart' show Token;
+
+import '../scanner/error_token.dart' show ErrorToken;
+
+import 'assert.dart' show Assert;
+
+import 'block_kind.dart' show BlockKind;
+
+import 'formal_parameter_kind.dart' show FormalParameterKind;
+
+import 'identifier_context.dart' show IdentifierContext;
+
+import 'declaration_kind.dart' show DeclarationKind;
+
+import 'member_kind.dart' show MemberKind;
+
+import 'util.dart' show optional;
+
+abstract class UnescapeErrorListener {
+  void handleUnescapeError(
+      Message message, covariant location, int offset, int length);
+}
+
+/// A parser event listener that does nothing except throw exceptions
+/// on parser errors.
+///
+/// Events are methods that begin with one of: `begin`, `end`, or `handle`.
+///
+/// Events starting with `begin` and `end` come in pairs. Normally, a
+/// `beginFoo` event is followed by an `endFoo` event. There's a few exceptions
+/// documented below.
+///
+/// Events starting with `handle` are used when isn't possible to have a begin
+/// event.
+class Listener implements UnescapeErrorListener {
+  Uri get uri => null;
+
+  void logEvent(String name) {}
+
+  set suppressParseErrors(bool value) {}
+
+  void beginArguments(Token token) {}
+
+  void endArguments(int count, Token beginToken, Token endToken) {
+    logEvent("Arguments");
+  }
+
+  /// Handle async modifiers `async`, `async*`, `sync`.
+  void handleAsyncModifier(Token asyncToken, Token starToken) {
+    logEvent("AsyncModifier");
+  }
+
+  void beginAwaitExpression(Token token) {}
+
+  void endAwaitExpression(Token beginToken, Token endToken) {
+    logEvent("AwaitExpression");
+  }
+
+  void endInvalidAwaitExpression(
+      Token beginToken, Token endToken, MessageCode errorCode) {
+    logEvent("InvalidAwaitExpression");
+  }
+
+  void beginBlock(Token token, BlockKind blockKind) {}
+
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
+    logEvent("Block");
+  }
+
+  /// Called to handle a block that has been parsed but is not associated
+  /// with any top level function declaration. Substructures:
+  /// - block
+  void handleInvalidTopLevelBlock(Token token) {}
+
+  void beginCascade(Token token) {}
+
+  void endCascade() {
+    logEvent("Cascade");
+  }
+
+  void beginCaseExpression(Token caseKeyword) {}
+
+  void endCaseExpression(Token colon) {
+    logEvent("CaseExpression");
+  }
+
+  /// Handle the start of the body of a class, mixin or extension declaration
+  /// beginning at [token]. The actual kind of declaration is indicated by
+  /// [kind].
+  void beginClassOrMixinBody(DeclarationKind kind, Token token) {}
+
+  /// Handle the end of the body of a class, mixin or extension declaration.
+  /// The only substructures are the class, mixin or extension members.
+  ///
+  /// The actual kind of declaration is indicated by [kind].
+  void endClassOrMixinBody(
+      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
+    logEvent("ClassOrMixinBody");
+  }
+
+  /// Called before parsing a class or named mixin application.
+  ///
+  /// At this point only the `class` keyword have been seen, so we know a
+  /// declaration is coming but not its name or type parameter declarations.
+  void beginClassOrNamedMixinApplicationPrelude(Token token) {}
+
+  /// Handle the beginning of a class declaration.
+  /// [begin] may be the same as [name], or may point to modifiers
+  /// (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) {}
+
+  /// Handle an extends clause in a class declaration. Substructures:
+  /// - supertype (may be a mixin application)
+  void handleClassExtends(Token extendsKeyword) {
+    logEvent("ClassExtends");
+  }
+
+  /// Handle an implements clause in a class or mixin declaration.
+  /// Substructures:
+  /// - implemented types
+  void handleClassOrMixinImplements(
+      Token implementsKeyword, int interfacesCount) {
+    logEvent("ClassImplements");
+  }
+
+  /// Handle the header of a class declaration.  Substructures:
+  /// - metadata
+  /// - modifiers
+  /// - class name
+  /// - type variables
+  /// - supertype
+  /// - with clause
+  /// - implemented types
+  /// - native clause
+  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
+    logEvent("ClassHeader");
+  }
+
+  /// Handle recovery associated with a class header.
+  /// This may be called multiple times after [handleClassHeader]
+  /// to recover information about the previous class header.
+  /// The substructures are a subset of
+  /// and in the same order as [handleClassHeader]:
+  /// - supertype
+  /// - with clause
+  /// - implemented types
+  void handleRecoverClassHeader() {
+    logEvent("RecoverClassHeader");
+  }
+
+  /// Handle the end of a class declaration.  Substructures:
+  /// - class header
+  /// - class body
+  void endClassDeclaration(Token beginToken, Token endToken) {
+    logEvent("ClassDeclaration");
+  }
+
+  /// Handle the beginning of a mixin declaration.
+  void beginMixinDeclaration(Token mixinKeyword, Token name) {}
+
+  /// Handle an on clause in a mixin declaration. Substructures:
+  /// - implemented types
+  void handleMixinOn(Token onKeyword, int typeCount) {
+    logEvent("MixinOn");
+  }
+
+  /// Handle the header of a mixin declaration.  Substructures:
+  /// - metadata
+  /// - mixin name
+  /// - type variables
+  /// - on types
+  /// - implemented types
+  void handleMixinHeader(Token mixinKeyword) {
+    logEvent("MixinHeader");
+  }
+
+  /// Handle recovery associated with a mixin header.
+  /// This may be called multiple times after [handleMixinHeader]
+  /// to recover information about the previous mixin header.
+  /// The substructures are a subset of
+  /// and in the same order as [handleMixinHeader]
+  /// - on types
+  /// - implemented types
+  void handleRecoverMixinHeader() {
+    logEvent("RecoverMixinHeader");
+  }
+
+  /// Handle the end of a mixin declaration.  Substructures:
+  /// - mixin header
+  /// - class or mixin body
+  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
+    logEvent("MixinDeclaration");
+  }
+
+  /// Handle the beginning of an extension methods declaration.  Substructures:
+  /// - metadata
+  ///
+  /// At this point only the `extension` keyword have been seen, so we know a
+  /// declaration is coming but not its name or type parameter declarations.
+  void beginExtensionDeclarationPrelude(Token extensionKeyword) {}
+
+  /// Handle the beginning of an extension methods declaration.  Substructures:
+  /// - type variables
+  ///
+  /// At this point we have parsed the name and type parameter declarations.
+  void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
+
+  /// Handle the end of an extension methods declaration.  Substructures:
+  /// - substructures from [beginExtensionDeclaration]
+  /// - on type
+  /// - body
+  void endExtensionDeclaration(
+      Token extensionKeyword, Token onKeyword, Token token) {
+    logEvent('ExtensionDeclaration');
+  }
+
+  void beginCombinators(Token token) {}
+
+  void endCombinators(int count) {
+    logEvent("Combinators");
+  }
+
+  void beginCompilationUnit(Token token) {}
+
+  /// This method exists for analyzer compatibility only
+  /// and will be removed once analyzer/fasta integration is complete.
+  ///
+  /// This is called when [parseDirectives] has parsed all directives
+  /// and is skipping the remainder of the file.  Substructures:
+  /// - metadata
+  void handleDirectivesOnly() {}
+
+  void endCompilationUnit(int count, Token token) {
+    logEvent("CompilationUnit");
+  }
+
+  void beginConstLiteral(Token token) {}
+
+  void endConstLiteral(Token token) {
+    logEvent("ConstLiteral");
+  }
+
+  void beginConstructorReference(Token start) {}
+
+  void endConstructorReference(
+      Token start, Token periodBeforeName, Token endToken) {
+    logEvent("ConstructorReference");
+  }
+
+  void beginDoWhileStatement(Token token) {}
+
+  void endDoWhileStatement(
+      Token doKeyword, Token whileKeyword, Token endToken) {
+    logEvent("DoWhileStatement");
+  }
+
+  void beginDoWhileStatementBody(Token token) {}
+
+  void endDoWhileStatementBody(Token token) {
+    logEvent("DoWhileStatementBody");
+  }
+
+  void beginWhileStatementBody(Token token) {}
+
+  void endWhileStatementBody(Token token) {
+    logEvent("WhileStatementBody");
+  }
+
+  void beginEnum(Token enumKeyword) {}
+
+  /// Handle the end of an enum declaration.  Substructures:
+  /// - Metadata
+  /// - Enum name (identifier)
+  /// - [count] times:
+  ///   - Enum value (identifier)
+  void endEnum(Token enumKeyword, Token leftBrace, int count) {
+    logEvent("Enum");
+  }
+
+  void beginExport(Token token) {}
+
+  /// Handle the end of an export directive.  Substructures:
+  /// - metadata
+  /// - uri
+  /// - conditional uris
+  /// - combinators
+  void endExport(Token exportKeyword, Token semicolon) {
+    logEvent("Export");
+  }
+
+  /// Called by [Parser] after parsing an extraneous expression as error
+  /// recovery. For a stack-based listener, the suggested action is to discard
+  /// an expression from the stack.
+  void handleExtraneousExpression(Token token, Message message) {
+    logEvent("ExtraneousExpression");
+  }
+
+  void handleExpressionStatement(Token token) {
+    logEvent("ExpressionStatement");
+  }
+
+  void beginFactoryMethod(
+      Token lastConsumed, Token externalToken, Token constToken) {}
+
+  void endClassFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    logEvent("ClassFactoryMethod");
+  }
+
+  void endMixinFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  void endExtensionFactoryMethod(
+      Token beginToken, Token factoryKeyword, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassFactoryMethod(beginToken, factoryKeyword, endToken);
+  }
+
+  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+      Token covariantToken, Token varFinalOrConst) {}
+
+  void endFormalParameter(
+      Token thisKeyword,
+      Token periodAfterThis,
+      Token nameToken,
+      Token initializerStart,
+      Token initializerEnd,
+      FormalParameterKind kind,
+      MemberKind memberKind) {
+    logEvent("FormalParameter");
+  }
+
+  void handleNoFormalParameters(Token token, MemberKind kind) {
+    logEvent("NoFormalParameters");
+  }
+
+  void beginFormalParameters(Token token, MemberKind kind) {}
+
+  void endFormalParameters(
+      int count, Token beginToken, Token endToken, MemberKind kind) {
+    logEvent("FormalParameters");
+  }
+
+  /// Handle the end of a class field declaration.  Substructures:
+  /// - Metadata
+  /// - Modifiers
+  /// - Type
+  /// - Variable declarations (count times)
+  ///
+  /// Doesn't have a corresponding begin event, use [beginMember] instead.
+  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    logEvent("Fields");
+  }
+
+  /// Handle the end of a mixin field declaration.  Substructures:
+  /// - Metadata
+  /// - Modifiers
+  /// - Type
+  /// - Variable declarations (count times)
+  ///
+  /// Doesn't have a corresponding begin event, use [beginMember] instead.
+  void endMixinFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassFields(staticToken, covariantToken, lateToken, varFinalOrConst,
+        count, beginToken, endToken);
+  }
+
+  /// Handle the end of a extension field declaration.  Substructures:
+  /// - Metadata
+  /// - Modifiers
+  /// - Type
+  /// - Variable declarations (count times)
+  ///
+  /// Doesn't have a corresponding begin event, use [beginMember] instead.
+  void endExtensionFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassFields(staticToken, covariantToken, lateToken, varFinalOrConst,
+        count, beginToken, endToken);
+  }
+
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was an empty statement.
+  void handleForInitializerEmptyStatement(Token token) {
+    logEvent("ForInitializerEmptyStatement");
+  }
+
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was an expression statement.
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
+    logEvent("ForInitializerExpressionStatement");
+  }
+
+  /// Marks that the grammar term `forInitializerStatement` has been parsed and
+  /// it was a `localVariableDeclaration`.
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
+    logEvent("ForInitializerLocalVariableDeclaration");
+  }
+
+  /// Marks the start of a for statement which is ended by either
+  /// [endForStatement] or [endForIn].
+  void beginForStatement(Token token) {}
+
+  /// Marks the end of parsing the control structure of a for statement
+  /// or for control flow entry up to and including the closing parenthesis.
+  /// `for` `(` initialization `;` condition `;` updaters `)`
+  void handleForLoopParts(Token forKeyword, Token leftParen,
+      Token leftSeparator, int updateExpressionCount) {}
+
+  void endForStatement(Token endToken) {
+    logEvent("ForStatement");
+  }
+
+  void beginForStatementBody(Token token) {}
+
+  void endForStatementBody(Token token) {
+    logEvent("ForStatementBody");
+  }
+
+  /// 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,
+      Token leftParenthesis, Token inKeyword) {}
+
+  // One of the two possible corresponding end events for [beginForStatement].
+  void endForIn(Token endToken) {
+    logEvent("ForIn");
+  }
+
+  void beginForInExpression(Token token) {}
+
+  void endForInExpression(Token token) {
+    logEvent("ForInExpression");
+  }
+
+  void beginForInBody(Token token) {}
+
+  void endForInBody(Token token) {
+    logEvent("ForInBody");
+  }
+
+  /// Handle the beginning of a named function expression which isn't legal
+  /// syntax in Dart.  Useful for recovering from Javascript code being pasted
+  /// into a Dart program, as it will interpret `function foo() {}` as a named
+  /// function expression with return type `function` and name `foo`.
+  ///
+  /// Substructures:
+  /// - Type variables
+  void beginNamedFunctionExpression(Token token) {}
+
+  /// A named function expression which isn't legal syntax in Dart.
+  /// Useful for recovering from Javascript code being pasted into a Dart
+  /// program, as it will interpret `function foo() {}` as a named function
+  /// expression with return type `function` and name `foo`.
+  ///
+  /// Substructures:
+  /// - Type variables
+  /// - Modifiers
+  /// - Return type
+  /// - Name
+  /// - Formals
+  /// - Initializers
+  /// - Async modifier
+  /// - Function body (block or arrow expression).
+  void endNamedFunctionExpression(Token endToken) {
+    logEvent("NamedFunctionExpression");
+  }
+
+  /// Handle the beginning of a local function declaration.  Substructures:
+  /// - Metadata
+  /// - Type variables
+  void beginLocalFunctionDeclaration(Token token) {}
+
+  /// A function declaration.
+  ///
+  /// Substructures:
+  /// - Metadata
+  /// - Type variables
+  /// - Return type
+  /// - Name
+  /// - Type variables
+  /// - Formals
+  /// - Initializers
+  /// - Async modifier
+  /// - Function body (block or arrow expression).
+  void endLocalFunctionDeclaration(Token endToken) {
+    logEvent("FunctionDeclaration");
+  }
+
+  /// This method is invoked when the parser sees that a function has a
+  /// block function body.  This method is not invoked for empty or expression
+  /// function bodies, see the corresponding methods [handleEmptyFunctionBody]
+  /// and [handleExpressionFunctionBody].
+  void beginBlockFunctionBody(Token token) {}
+
+  /// This method is invoked by the parser after it finished parsing a block
+  /// function body.  This method is not invoked for empty or expression
+  /// function bodies, see the corresponding methods [handleEmptyFunctionBody]
+  /// and [handleExpressionFunctionBody].  The [beginToken] is the '{' token,
+  /// and the [endToken] is the '}' token of the block.  The number of
+  /// statements is given as the [count] parameter.
+  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
+    logEvent("BlockFunctionBody");
+  }
+
+  void handleNoFunctionBody(Token token) {
+    logEvent("NoFunctionBody");
+  }
+
+  /// Handle the end of a function body that was skipped by the parser.
+  ///
+  /// The boolean [isExpressionBody] indicates whether the function body that
+  /// was skipped used "=>" syntax.
+  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {}
+
+  void beginFunctionName(Token token) {}
+
+  void endFunctionName(Token beginToken, Token token) {
+    logEvent("FunctionName");
+  }
+
+  void beginFunctionTypeAlias(Token token) {}
+
+  /// Handle the end of a typedef declaration.
+  ///
+  /// If [equals] is null, then we have the following substructures:
+  /// - Metadata
+  /// - Return type
+  /// - Name (identifier)
+  /// - Alias type variables
+  /// - Formal parameters
+  ///
+  /// If [equals] is not null, then the have the following substructures:
+  /// - Metadata
+  /// - Name (identifier)
+  /// - Alias type variables
+  /// - Type (FunctionTypeAnnotation)
+  void endFunctionTypeAlias(
+      Token typedefKeyword, Token equals, Token endToken) {
+    logEvent("FunctionTypeAlias");
+  }
+
+  /// Handle the end of a with clause (e.g. "with B, C").
+  /// Substructures:
+  /// - mixin types (TypeList)
+  void handleClassWithClause(Token withKeyword) {
+    logEvent("ClassWithClause");
+  }
+
+  /// Handle the absence of a with clause.
+  void handleClassNoWithClause() {
+    logEvent("ClassNoWithClause");
+  }
+
+  /// Handle the beginning of a named mixin application.
+  /// [beginToken] may be the same as [name], or may point to modifiers
+  /// (or extraneous modifiers in the case of recovery) preceding [name].
+  ///
+  /// At this point we have parsed the name and type parameter declarations.
+  void beginNamedMixinApplication(
+      Token begin, Token abstractToken, Token name) {}
+
+  /// Handle a named mixin application with clause (e.g. "A with B, C").
+  /// Substructures:
+  /// - supertype
+  /// - mixin types (TypeList)
+  void handleNamedMixinApplicationWithClause(Token withKeyword) {
+    logEvent("NamedMixinApplicationWithClause");
+  }
+
+  /// Handle the end of a named mixin declaration.  Substructures:
+  /// - metadata
+  /// - modifiers
+  /// - class name
+  /// - type variables
+  /// - supertype
+  /// - with clause
+  /// - implemented types (TypeList)
+  ///
+  /// TODO(paulberry,ahe): it seems inconsistent that for a named mixin
+  /// application, the implemented types are a TypeList, whereas for a class
+  /// 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) {
+    logEvent("NamedMixinApplication");
+  }
+
+  void beginHide(Token hideKeyword) {}
+
+  /// Handle the end of a "hide" combinator.  Substructures:
+  /// - hidden names (IdentifierList)
+  void endHide(Token hideKeyword) {
+    logEvent("Hide");
+  }
+
+  void handleIdentifierList(int count) {
+    logEvent("IdentifierList");
+  }
+
+  void beginTypeList(Token token) {}
+
+  void endTypeList(int count) {
+    logEvent("TypeList");
+  }
+
+  void beginIfStatement(Token token) {}
+
+  void endIfStatement(Token ifToken, Token elseToken) {
+    logEvent("IfStatement");
+  }
+
+  void beginThenStatement(Token token) {}
+
+  void endThenStatement(Token token) {
+    logEvent("ThenStatement");
+  }
+
+  void beginElseStatement(Token token) {}
+
+  void endElseStatement(Token token) {
+    logEvent("ElseStatement");
+  }
+
+  void beginImport(Token importKeyword) {}
+
+  /// Signals that the current import is deferred and/or has a prefix
+  /// depending upon whether [deferredKeyword] and [asKeyword]
+  /// are not `null` respectively. Substructures:
+  /// - prefix identifier (only if asKeyword != null)
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    logEvent("ImportPrefix");
+  }
+
+  /// Handle the end of an import directive.  Substructures:
+  /// - metadata
+  /// - uri
+  /// - conditional uris
+  /// - prefix identifier
+  /// - combinators
+  void endImport(Token importKeyword, Token semicolon) {
+    logEvent("Import");
+  }
+
+  /// Handle recovery associated with an import directive.
+  /// This may be called multiple times after [endImport]
+  /// to recover information about the previous import directive.
+  /// The substructures are a subset of and in the same order as [endImport]:
+  /// - conditional uris
+  /// - prefix identifier
+  /// - combinators
+  void handleRecoverImport(Token semicolon) {
+    logEvent("ImportRecovery");
+  }
+
+  void beginConditionalUris(Token token) {}
+
+  void endConditionalUris(int count) {
+    logEvent("ConditionalUris");
+  }
+
+  void beginConditionalUri(Token ifKeyword) {}
+
+  /// Handle the end of a conditional URI construct.  Substructures:
+  /// - Dotted name
+  /// - Condition (literal string; only if [equalSign] != null)
+  /// - URI (literal string)
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+    logEvent("ConditionalUri");
+  }
+
+  void handleDottedName(int count, Token firstIdentifier) {
+    logEvent("DottedName");
+  }
+
+  void beginImplicitCreationExpression(Token token) {}
+
+  void endImplicitCreationExpression(Token token) {
+    logEvent("ImplicitCreationExpression");
+  }
+
+  void beginInitializedIdentifier(Token token) {}
+
+  void endInitializedIdentifier(Token nameToken) {
+    logEvent("InitializedIdentifier");
+  }
+
+  void beginFieldInitializer(Token token) {}
+
+  /// Handle the end of a field initializer.  Substructures:
+  /// - Initializer expression
+  void endFieldInitializer(Token assignment, Token token) {
+    logEvent("FieldInitializer");
+  }
+
+  /// Handle the lack of a field initializer.
+  void handleNoFieldInitializer(Token token) {
+    logEvent("NoFieldInitializer");
+  }
+
+  void beginVariableInitializer(Token token) {}
+
+  /// Handle the end of a variable initializer. Substructures:
+  /// - Initializer expression.
+  void endVariableInitializer(Token assignmentOperator) {
+    logEvent("VariableInitializer");
+  }
+
+  /// Used when a variable has no initializer.
+  void handleNoVariableInitializer(Token token) {
+    logEvent("NoVariableInitializer");
+  }
+
+  void beginInitializer(Token token) {}
+
+  void endInitializer(Token token) {
+    logEvent("ConstructorInitializer");
+  }
+
+  void beginInitializers(Token token) {}
+
+  void endInitializers(int count, Token beginToken, Token endToken) {
+    logEvent("Initializers");
+  }
+
+  void handleNoInitializers() {
+    logEvent("NoInitializers");
+  }
+
+  /// Called after the listener has recovered from an invalid expression. The
+  /// parser will resume parsing from [token]. Exactly where the parser will
+  /// resume parsing is unspecified.
+  void handleInvalidExpression(Token token) {
+    logEvent("InvalidExpression");
+  }
+
+  /// Called after the listener has recovered from an invalid function
+  /// body. The parser expected an open curly brace `{` and will resume parsing
+  /// from [token] as if a function body had preceded it.
+  void handleInvalidFunctionBody(Token token) {
+    logEvent("InvalidFunctionBody");
+  }
+
+  /// Called after the listener has recovered from an invalid type. The parser
+  /// expected an identifier, and will resume parsing type arguments from
+  /// [token].
+  void handleInvalidTypeReference(Token token) {
+    logEvent("InvalidTypeReference");
+  }
+
+  void handleLabel(Token token) {
+    logEvent("Label");
+  }
+
+  void beginLabeledStatement(Token token, int labelCount) {}
+
+  void endLabeledStatement(int labelCount) {
+    logEvent("LabeledStatement");
+  }
+
+  void beginLibraryName(Token token) {}
+
+  /// Handle the end of a library directive.  Substructures:
+  /// - Metadata
+  /// - Library name (a qualified identifier)
+  void endLibraryName(Token libraryKeyword, Token semicolon) {
+    logEvent("LibraryName");
+  }
+
+  void handleLiteralMapEntry(Token colon, Token endToken) {
+    logEvent("LiteralMapEntry");
+  }
+
+  void beginLiteralString(Token token) {}
+
+  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {}
+
+  void endLiteralString(int interpolationCount, Token endToken) {
+    logEvent("LiteralString");
+  }
+
+  void handleStringJuxtaposition(int literalCount) {
+    logEvent("StringJuxtaposition");
+  }
+
+  void beginMember() {}
+
+  /// Handle an invalid member declaration. Substructures:
+  /// - metadata
+  void handleInvalidMember(Token endToken) {
+    logEvent("InvalidMember");
+  }
+
+  /// This event is added for convenience. Normally, one should override
+  /// [endClassFields], [endMixinFields], [endExtensionFields],
+  /// [endClassMethod], [endMixinMethod], [endExtensionMethod],
+  /// [endClassConstructor], [endMixinConstructor],
+  /// or [endExtensionConstructor] instead.
+  void endMember() {
+    logEvent("Member");
+  }
+
+  /// Handle the beginning of a method declaration.  Substructures:
+  /// - metadata
+  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
+      Token varFinalOrConst, Token getOrSet, Token name) {}
+
+  /// Handle the end of a class method declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    logEvent("ClassMethod");
+  }
+
+  /// Handle the end of a mixin method declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  /// Handle the end of a extension method declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  /// Handle the end of a class constructor declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  /// Handle the end of a mixin constructor declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
+      Token beginInitializers, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  /// Handle the end of a extension constructor declaration.  Substructures:
+  /// - metadata
+  /// - return type
+  /// - method name (identifier, possibly qualified)
+  /// - type variables
+  /// - formal parameters
+  /// - initializers
+  /// - async marker
+  /// - body
+  void endExtensionConstructor(Token getOrSet, Token beginToken,
+      Token beginParam, Token beginInitializers, Token endToken) {
+    // TODO(danrubel): push implementation into subclasses
+    endClassMethod(
+        getOrSet, beginToken, beginParam, beginInitializers, endToken);
+  }
+
+  void beginMetadataStar(Token token) {}
+
+  void endMetadataStar(int count) {
+    logEvent("MetadataStar");
+  }
+
+  void beginMetadata(Token token) {}
+
+  /// Handle the end of a metadata annotation.  Substructures:
+  /// - Identifier
+  /// - Type arguments
+  /// - Constructor name (only if [periodBeforeName] is not `null`)
+  /// - Arguments
+  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+    logEvent("Metadata");
+  }
+
+  void beginOptionalFormalParameters(Token token) {}
+
+  void endOptionalFormalParameters(
+      int count, Token beginToken, Token endToken) {
+    logEvent("OptionalFormalParameters");
+  }
+
+  void beginPart(Token token) {}
+
+  /// Handle the end of a part directive.  Substructures:
+  /// - metadata
+  /// - uri
+  void endPart(Token partKeyword, Token semicolon) {
+    logEvent("Part");
+  }
+
+  void beginPartOf(Token token) {}
+
+  /// Handle the end of a "part of" directive.  Substructures:
+  /// - Metadata
+  /// - Library name (a qualified identifier)
+  ///
+  /// If [hasName] is true, this part refers to its library by name, otherwise,
+  /// by URI.
+  void endPartOf(
+      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
+    logEvent("PartOf");
+  }
+
+  void beginRedirectingFactoryBody(Token token) {}
+
+  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+    logEvent("RedirectingFactoryBody");
+  }
+
+  void beginReturnStatement(Token token) {}
+
+  /// Handle the end of a `native` function.
+  /// The [handleNativeClause] event is sent prior to this event.
+  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
+    logEvent("NativeFunctionBody");
+  }
+
+  /// Called after the [handleNativeClause] event when the parser determines
+  /// that the native clause should be discarded / ignored.
+  /// For example, this method is called a native clause is followed by
+  /// a function body.
+  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
+    logEvent("NativeFunctionBodyIgnored");
+  }
+
+  /// Handle the end of a `native` function that was skipped by the parser.
+  /// The [handleNativeClause] event is sent prior to this event.
+  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+    logEvent("NativeFunctionBodySkipped");
+  }
+
+  /// This method is invoked when a function has the empty body.
+  void handleEmptyFunctionBody(Token semicolon) {
+    logEvent("EmptyFunctionBody");
+  }
+
+  /// This method is invoked when parser finishes parsing the corresponding
+  /// expression of the expression function body.
+  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
+    logEvent("ExpressionFunctionBody");
+  }
+
+  void endReturnStatement(
+      bool hasExpression, Token beginToken, Token endToken) {
+    logEvent("ReturnStatement");
+  }
+
+  void handleSend(Token beginToken, Token endToken) {
+    logEvent("Send");
+  }
+
+  void beginShow(Token showKeyword) {}
+
+  /// Handle the end of a "show" combinator.  Substructures:
+  /// - shown names (IdentifierList)
+  void endShow(Token showKeyword) {
+    logEvent("Show");
+  }
+
+  void beginSwitchStatement(Token token) {}
+
+  void endSwitchStatement(Token switchKeyword, Token endToken) {
+    logEvent("SwitchStatement");
+  }
+
+  void beginSwitchBlock(Token token) {}
+
+  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+    logEvent("SwitchBlock");
+  }
+
+  void beginLiteralSymbol(Token token) {}
+
+  void endLiteralSymbol(Token hashToken, int identifierCount) {
+    logEvent("LiteralSymbol");
+  }
+
+  void handleThrowExpression(Token throwToken, Token endToken) {
+    logEvent("ThrowExpression");
+  }
+
+  void beginRethrowStatement(Token token) {}
+
+  void endRethrowStatement(Token rethrowToken, Token endToken) {
+    logEvent("RethrowStatement");
+  }
+
+  /// This event is added for convenience. Normally, one should use
+  /// [endClassDeclaration], [endNamedMixinApplication], [endEnum],
+  /// [endFunctionTypeAlias], [endLibraryName], [endImport], [endExport],
+  /// [endPart], [endPartOf], [endTopLevelFields], or [endTopLevelMethod].
+  void endTopLevelDeclaration(Token token) {
+    logEvent("TopLevelDeclaration");
+  }
+
+  /// Called by the [Parser] when it recovers from an invalid top level
+  /// declaration, where [endToken] is the last token in the declaration
+  /// This is called after the begin/end metadata star events,
+  /// and is followed by [endTopLevelDeclaration].
+  ///
+  /// Substructures:
+  /// - metadata
+  void handleInvalidTopLevelDeclaration(Token endToken) {
+    logEvent("InvalidTopLevelDeclaration");
+  }
+
+  /// Marks the beginning of a top level field or method declaration.
+  /// Doesn't have a corresponding end event.
+  /// See [endTopLevelFields] and [endTopLevelMethod].
+  void beginTopLevelMember(Token token) {}
+
+  /// Handle the end of a top level variable declaration.  Substructures:
+  /// - Metadata
+  /// - Type
+  /// - Repeated [count] times:
+  ///   - Variable name (identifier)
+  ///   - Field initializer
+  /// Doesn't have a corresponding begin event.
+  /// Use [beginTopLevelMember] instead.
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    logEvent("TopLevelFields");
+  }
+
+  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {}
+
+  /// Handle the end of a top level method.  Substructures:
+  /// - metadata
+  /// - modifiers
+  /// - return type
+  /// - identifier
+  /// - type variables
+  /// - formal parameters
+  /// - async marker
+  /// - body
+  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+    logEvent("TopLevelMethod");
+  }
+
+  void beginTryStatement(Token token) {}
+
+  void handleCaseMatch(Token caseKeyword, Token colon) {
+    logEvent("CaseMatch");
+  }
+
+  void beginCatchClause(Token token) {}
+
+  void endCatchClause(Token token) {
+    logEvent("CatchClause");
+  }
+
+  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
+    logEvent("CatchBlock");
+  }
+
+  void handleFinallyBlock(Token finallyKeyword) {
+    logEvent("FinallyBlock");
+  }
+
+  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+    logEvent("TryStatement");
+  }
+
+  void handleType(Token beginToken, Token questionMark) {
+    logEvent("Type");
+  }
+
+  /// Called when parser encounters a '!'
+  /// used as a non-null postfix assertion in an expression.
+  void handleNonNullAssertExpression(Token bang) {
+    logEvent("NonNullAssertExpression");
+  }
+
+  // TODO(danrubel): Remove this once all listeners have been updated
+  // to properly handle nullable types
+  void reportErrorIfNullableType(Token questionMark) {
+    if (questionMark != null) {
+      assert(optional('?', questionMark));
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments('non-nullable'),
+          questionMark,
+          questionMark);
+    }
+  }
+
+  // TODO(danrubel): Remove this once all listeners have been updated
+  // to properly handle nullable types
+  void reportNonNullableModifierError(Token modifierToken) {
+    if (modifierToken != null) {
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments('non-nullable'),
+          modifierToken,
+          modifierToken);
+    }
+  }
+
+  // TODO(danrubel): Remove this once all listeners have been updated
+  // to properly handle non-null assert expressions
+  void reportNonNullAssertExpressionNotEnabled(Token bang) {
+    handleRecoverableError(
+        templateExperimentNotEnabled.withArguments('non-nullable'), bang, bang);
+  }
+
+  void handleNoName(Token token) {
+    logEvent("NoName");
+  }
+
+  void beginFunctionType(Token beginToken) {}
+
+  /// Handle the end of a generic function type declaration.
+  ///
+  /// Substructures:
+  /// - Type variables
+  /// - Return type
+  /// - Formal parameters
+  void endFunctionType(Token functionToken, Token questionMark) {
+    logEvent("FunctionType");
+  }
+
+  void beginTypeArguments(Token token) {}
+
+  void endTypeArguments(int count, Token beginToken, Token endToken) {
+    logEvent("TypeArguments");
+  }
+
+  /// After endTypeArguments has been called,
+  /// this event is called if those type arguments are invalid.
+  void handleInvalidTypeArguments(Token token) {
+    logEvent("NoTypeArguments");
+  }
+
+  void handleNoTypeArguments(Token token) {
+    logEvent("NoTypeArguments");
+  }
+
+  /// Handle the begin of a type formal parameter (e.g. "X extends Y").
+  /// Substructures:
+  /// - Metadata
+  /// - Name (identifier)
+  void beginTypeVariable(Token token) {}
+
+  /// Called when [beginTypeVariable] has been called for all of the variables
+  /// in a group, and before [endTypeVariable] has been called for any of the
+  /// variables in that same group.
+  void handleTypeVariablesDefined(Token token, int count) {}
+
+  /// Handle the end of a type formal parameter (e.g. "X extends Y")
+  /// where [index] is the index of the type variable in the list of
+  /// type variables being declared.
+  ///
+  /// Substructures:
+  /// - Type bound
+  ///
+  /// See [beginTypeVariable] for additional substructures.
+  void endTypeVariable(
+      Token token, int index, Token extendsOrSuper, Token variance) {
+    logEvent("TypeVariable");
+  }
+
+  void beginTypeVariables(Token token) {}
+
+  void endTypeVariables(Token beginToken, Token endToken) {
+    logEvent("TypeVariables");
+  }
+
+  void reportVarianceModifierNotEnabled(Token variance) {
+    if (variance != null) {
+      handleRecoverableError(
+          templateExperimentNotEnabled.withArguments('variance'),
+          variance,
+          variance);
+    }
+  }
+
+  void beginFunctionExpression(Token token) {}
+
+  /// Handle the end of a function expression (e.g. "() { ... }").
+  /// Substructures:
+  /// - Type variables
+  /// - Formal parameters
+  /// - Async marker
+  /// - Body
+  void endFunctionExpression(Token beginToken, Token token) {
+    logEvent("FunctionExpression");
+  }
+
+  /// Handle the start of a variables declaration.  Substructures:
+  /// - Metadata
+  /// - Type
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {}
+
+  void endVariablesDeclaration(int count, Token endToken) {
+    logEvent("VariablesDeclaration");
+  }
+
+  void beginWhileStatement(Token token) {}
+
+  void endWhileStatement(Token whileKeyword, Token endToken) {
+    logEvent("WhileStatement");
+  }
+
+  void handleAsOperator(Token operator) {
+    logEvent("AsOperator");
+  }
+
+  void handleAssignmentExpression(Token token) {
+    logEvent("AssignmentExpression");
+  }
+
+  /// Called when the parser encounters a binary operator, in between the LHS
+  /// and RHS subexpressions.
+  ///
+  /// Not called when the binary operator is `.`, `?.`, or `..`.
+  void beginBinaryExpression(Token token) {}
+
+  void endBinaryExpression(Token token) {
+    logEvent("BinaryExpression");
+  }
+
+  /// Called when the parser encounters a `?` operator and begins parsing a
+  /// conditional expression.
+  void beginConditionalExpression(Token question) {}
+
+  /// Called when the parser encounters a `:` operator in a conditional
+  /// expression.
+  void handleConditionalExpressionColon() {}
+
+  /// Called when the parser finishes processing a conditional expression.
+  void endConditionalExpression(Token question, Token colon) {
+    logEvent("ConditionalExpression");
+  }
+
+  void beginConstExpression(Token constKeyword) {}
+
+  void endConstExpression(Token token) {
+    logEvent("ConstExpression");
+  }
+
+  /// Called before parsing a "for" control flow list, set, or map entry.
+  void beginForControlFlow(Token awaitToken, Token forToken) {}
+
+  /// Called after parsing a "for" control flow list, set, or map entry.
+  void endForControlFlow(Token token) {
+    logEvent('endForControlFlow');
+  }
+
+  /// Called after parsing a "for-in" control flow list, set, or map entry.
+  void endForInControlFlow(Token token) {
+    logEvent('endForInControlFlow');
+  }
+
+  /// Called before parsing an `if` control flow list, set, or map entry.
+  void beginIfControlFlow(Token ifToken) {}
+
+  /// Called before parsing the `then` portion of an `if` control flow list,
+  /// set, or map entry.
+  void beginThenControlFlow(Token token) {}
+
+  /// Called before parsing the `else` portion of an `if` control flow list,
+  /// set, or map entry.
+  void handleElseControlFlow(Token elseToken) {
+    logEvent("ElseControlFlow");
+  }
+
+  /// Called after parsing an `if` control flow list, set, or map entry.
+  /// Substructures:
+  /// - if conditional expression
+  /// - expression
+  void endIfControlFlow(Token token) {
+    logEvent("endIfControlFlow");
+  }
+
+  /// Called after parsing an if-else control flow list, set, or map entry.
+  /// Substructures:
+  /// - if conditional expression
+  /// - then expression
+  /// - else expression
+  void endIfElseControlFlow(Token token) {
+    logEvent("endIfElseControlFlow");
+  }
+
+  /// Called after parsing a list, set, or map entry that starts with
+  /// one of the spread collection tokens `...` or `...?`.  Substructures:
+  /// - expression
+  void handleSpreadExpression(Token spreadToken) {
+    logEvent("SpreadExpression");
+  }
+
+  /// Handle the start of a function typed formal parameter.  Substructures:
+  /// - type variables
+  void beginFunctionTypedFormalParameter(Token token) {}
+
+  /// Handle the end of a function typed formal parameter.  Substructures:
+  /// - type variables
+  /// - return type
+  /// - formal parameters
+  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
+    logEvent("FunctionTypedFormalParameter");
+  }
+
+  /// Handle an identifier token.
+  ///
+  /// [context] indicates what kind of construct the identifier appears in.
+  void handleIdentifier(Token token, IdentifierContext context) {
+    logEvent("Identifier");
+  }
+
+  void handleIndexedExpression(
+      Token openSquareBracket, Token closeSquareBracket) {
+    logEvent("IndexedExpression");
+  }
+
+  void handleIsOperator(Token isOperator, Token not) {
+    logEvent("IsOperator");
+  }
+
+  void handleLiteralBool(Token token) {
+    logEvent("LiteralBool");
+  }
+
+  void handleBreakStatement(
+      bool hasTarget, Token breakKeyword, Token endToken) {
+    logEvent("BreakStatement");
+  }
+
+  void handleContinueStatement(
+      bool hasTarget, Token continueKeyword, Token endToken) {
+    logEvent("ContinueStatement");
+  }
+
+  void handleEmptyStatement(Token token) {
+    logEvent("EmptyStatement");
+  }
+
+  void beginAssert(Token assertKeyword, Assert kind) {}
+
+  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
+      Token commaToken, Token semicolonToken) {
+    logEvent("Assert");
+  }
+
+  /** Called with either the token containing a double literal, or
+    * an immediately preceding "unary plus" token.
+    */
+  void handleLiteralDouble(Token token) {
+    logEvent("LiteralDouble");
+  }
+
+  /** Called with either the token containing an integer literal,
+    * or an immediately preceding "unary plus" token.
+    */
+  void handleLiteralInt(Token token) {
+    logEvent("LiteralInt");
+  }
+
+  void handleLiteralList(
+      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
+    logEvent("LiteralList");
+  }
+
+  void handleLiteralSetOrMap(
+    int count,
+    Token leftBrace,
+    Token constKeyword,
+    Token rightBrace,
+    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+    // behavior and will be removed once unified collection has been enabled
+    bool hasSetEntry,
+  ) {
+    logEvent('LiteralSetOrMap');
+  }
+
+  void handleLiteralNull(Token token) {
+    logEvent("LiteralNull");
+  }
+
+  void handleNativeClause(Token nativeToken, bool hasName) {
+    logEvent("NativeClause");
+  }
+
+  void handleNamedArgument(Token colon) {
+    logEvent("NamedArgument");
+  }
+
+  void beginNewExpression(Token token) {}
+
+  void endNewExpression(Token token) {
+    logEvent("NewExpression");
+  }
+
+  void handleNoArguments(Token token) {
+    logEvent("NoArguments");
+  }
+
+  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
+    logEvent("NoConstructorReferenceContinuationAfterTypeArguments");
+  }
+
+  void handleNoType(Token lastConsumed) {
+    logEvent("NoType");
+  }
+
+  void handleNoTypeVariables(Token token) {
+    logEvent("NoTypeVariables");
+  }
+
+  void handleOperator(Token token) {
+    logEvent("Operator");
+  }
+
+  void handleSymbolVoid(Token token) {
+    logEvent("SymbolVoid");
+  }
+
+  /// Handle the end of a construct of the form "operator <token>".
+  void handleOperatorName(Token operatorKeyword, Token token) {
+    logEvent("OperatorName");
+  }
+
+  /// Handle the end of a construct of the form "operator <token>"
+  /// where <token> is not a valid operator token.
+  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
+    logEvent("InvalidOperatorName");
+  }
+
+  /// Handle the condition in a control structure:
+  /// - if statement
+  /// - do while loop
+  /// - switch statement
+  /// - while loop
+  void handleParenthesizedCondition(Token token) {
+    logEvent("ParenthesizedCondition");
+  }
+
+  /// Handle a parenthesized expression.
+  /// These may be within the condition expression of a control structure
+  /// but will not be the condition of a control structure.
+  void handleParenthesizedExpression(Token token) {
+    logEvent("ParenthesizedExpression");
+  }
+
+  /// Handle a construct of the form "identifier.identifier" occurring in a part
+  /// of the grammar where expressions in general are not allowed.
+  /// Substructures:
+  /// - Qualified identifier (before the period)
+  /// - Identifier (after the period)
+  void handleQualified(Token period) {
+    logEvent("Qualified");
+  }
+
+  void handleStringPart(Token token) {
+    logEvent("StringPart");
+  }
+
+  void handleSuperExpression(Token token, IdentifierContext context) {
+    logEvent("SuperExpression");
+  }
+
+  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {}
+
+  void endSwitchCase(
+      int labelCount,
+      int expressionCount,
+      Token defaultKeyword,
+      Token colonAfterDefault,
+      int statementCount,
+      Token firstToken,
+      Token endToken) {
+    logEvent("SwitchCase");
+  }
+
+  void handleThisExpression(Token token, IdentifierContext context) {
+    logEvent("ThisExpression");
+  }
+
+  void handleUnaryPostfixAssignmentExpression(Token token) {
+    logEvent("UnaryPostfixAssignmentExpression");
+  }
+
+  void handleUnaryPrefixExpression(Token token) {
+    logEvent("UnaryPrefixExpression");
+  }
+
+  void handleUnaryPrefixAssignmentExpression(Token token) {
+    logEvent("UnaryPrefixAssignmentExpression");
+  }
+
+  void beginFormalParameterDefaultValueExpression() {}
+
+  void endFormalParameterDefaultValueExpression() {
+    logEvent("FormalParameterDefaultValueExpression");
+  }
+
+  void handleValuedFormalParameter(Token equals, Token token) {
+    logEvent("ValuedFormalParameter");
+  }
+
+  void handleFormalParameterWithoutValue(Token token) {
+    logEvent("FormalParameterWithoutValue");
+  }
+
+  void handleVoidKeyword(Token token) {
+    logEvent("VoidKeyword");
+  }
+
+  void beginYieldStatement(Token token) {}
+
+  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+    logEvent("YieldStatement");
+  }
+
+  /// The parser noticed a syntax error, but was able to recover from it. The
+  /// error should be reported using the [message], and the code between the
+  /// beginning of the [startToken] and the end of the [endToken] should be
+  /// highlighted. The [startToken] and [endToken] can be the same token.
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {}
+
+  /// The parser encountered an [ErrorToken] representing an error
+  /// from the scanner but recovered from it. By default, the error is reported
+  /// by calling [handleRecoverableError] with the message associated
+  /// with the error [token].
+  void handleErrorToken(ErrorToken token) {
+    handleRecoverableError(token.assertionMessage, token, token);
+  }
+
+  @override
+  void handleUnescapeError(
+      Message message, Token location, int stringOffset, int length) {
+    handleRecoverableError(message, location, location);
+  }
+
+  /// Signals to the listener that the previous statement contained a semantic
+  /// error (described by the given [message]). This method can also be called
+  /// after [handleExpressionFunctionBody], in which case it signals that the
+  /// implicit return statement of the function contained a semantic error.
+  void handleInvalidStatement(Token token, Message message) {
+    handleRecoverableError(message, token, token);
+  }
+
+  void handleScript(Token token) {
+    logEvent("Script");
+  }
+
+  /// A type has been just parsed, and the parser noticed that the next token
+  /// has a type substitution comment /*=T*. So, the type that has been just
+  /// parsed should be discarded, and a new type should be parsed instead.
+  void discardTypeReplacedWithCommentTypeAssign() {}
+
+  /// A single comment reference has been found
+  /// where [referenceSource] is the text between the `[` and `]`
+  /// and [referenceOffset] is the character offset in the token stream.
+  ///
+  /// This event is generated by the parser when the parser's
+  /// `parseCommentReferences` method is called. For further processing,
+  /// a listener may scan the [referenceSource] and then pass the resulting
+  /// token stream to the parser's `parseOneCommentReference` method.
+  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
+    logEvent("CommentReferenceText");
+  }
+
+  /// A single comment reference has been parsed.
+  /// * [newKeyword] may be null.
+  /// * [prefix] and [period] are either both tokens or both `null`.
+  /// * [token] can be an identifier or an operator.
+  ///
+  /// 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) {}
+
+  /// This event is generated by the parser when the parser's
+  /// `parseOneCommentReference` method is called.
+  void handleNoCommentReference() {}
+}
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
new file mode 100644
index 0000000..0e3bb11
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info.dart
@@ -0,0 +1,77 @@
+// 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 '../scanner/scanner.dart';
+import 'identifier_context.dart';
+import 'literal_entry_info_impl.dart';
+import 'parser_impl.dart';
+import 'util.dart';
+
+/// [simpleEntry] is the first step for parsing a literal entry
+/// without any control flow or spread collection operator.
+const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true, 0);
+
+/// [LiteralEntryInfo] represents steps for processing an entry
+/// in a literal list, map, or set. These steps will handle parsing
+/// both control flow and spreadable operators, and indicate
+/// when the client should parse the literal entry.
+///
+/// Clients should parse a single entry in a list, set, or map like this:
+/// ```
+///    LiteralEntryInfo info = computeLiteralEntry(token);
+///    while (info != null) {
+///      if (info.hasEntry) {
+///        ... parse expression (`:` expression)? ...
+///        token = lastConsumedToken;
+///      } else {
+///        token = info.parse(token, parser);
+///      }
+///      info = info.computeNext(token);
+///    }
+/// ```
+class LiteralEntryInfo {
+  /// `true` if an entry should be parsed by the caller
+  /// or `false` if this object's [parse] method should be called.
+  final bool hasEntry;
+
+  /// Used for recovery, this indicates
+  /// +1 for an `if` condition and -1 for `else`.
+  final int ifConditionDelta;
+
+  const LiteralEntryInfo(this.hasEntry, this.ifConditionDelta);
+
+  /// Parse the control flow and spread collection aspects of this entry.
+  Token parse(Token token, Parser parser) {
+    throw hasEntry
+        ? 'Internal Error: should not call parse'
+        : 'Internal Error: $runtimeType should implement parse';
+  }
+
+  /// Returns the next step when parsing an entry or `null` if none.
+  LiteralEntryInfo computeNext(Token token) => null;
+}
+
+/// Compute the [LiteralEntryInfo] for the literal list, map, or set entry.
+LiteralEntryInfo computeLiteralEntry(Token token) {
+  Token next = token.next;
+  if (optional('if', next)) {
+    return ifCondition;
+  } else if (optional('for', next) ||
+      (optional('await', next) && optional('for', next.next))) {
+    return new ForCondition();
+  } else if (optional('...', next) || optional('...?', next)) {
+    return spreadOperator;
+  }
+  return simpleEntry;
+}
+
+/// Return `true` if the given [token] should be treated like the start of
+/// a literal entry in a list, set, or map for the purposes of recovery.
+bool looksLikeLiteralEntry(Token token) =>
+    looksLikeExpressionStart(token) ||
+    optional('...', token) ||
+    optional('...?', token) ||
+    optional('if', token) ||
+    optional('for', token) ||
+    (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
new file mode 100644
index 0000000..60d378f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/literal_entry_info_impl.dart
@@ -0,0 +1,289 @@
+// 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 '../scanner/token.dart';
+import 'literal_entry_info.dart';
+import 'parser_impl.dart';
+import 'util.dart';
+
+/// [ifCondition] is the first step for parsing a literal entry
+/// starting with `if` control flow.
+const LiteralEntryInfo ifCondition = const IfCondition();
+
+/// [spreadOperator] is the first step for parsing a literal entry
+/// preceded by a '...' spread operator.
+const LiteralEntryInfo spreadOperator = const SpreadOperator();
+
+/// The first step when processing a `for` control flow collection entry.
+class ForCondition extends LiteralEntryInfo {
+  bool inStyle;
+
+  ForCondition() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    Token next = token.next;
+    Token awaitToken;
+    if (optional('await', next)) {
+      awaitToken = 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 = parser.parseForLoopPartsMid(token, awaitToken, forToken);
+
+    if (optional('in', token.next) || optional(':', token.next)) {
+      // Process `for ( ... in ... )`
+      inStyle = true;
+      token = parser.parseForInLoopPartsRest(
+          token, awaitToken, forToken, identifier);
+    } else {
+      // Process `for ( ... ; ... ; ... )`
+      inStyle = false;
+      token = parser.parseForLoopPartsRest(token, forToken, awaitToken);
+    }
+    return token;
+  }
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    Token next = token.next;
+    if (optional('for', next) ||
+        (optional('await', next) && optional('for', next.next))) {
+      return new Nested(
+        new ForCondition(),
+        inStyle ? const ForInComplete() : const ForComplete(),
+      );
+    } else if (optional('if', next)) {
+      return new Nested(
+        ifCondition,
+        inStyle ? const ForInComplete() : const ForComplete(),
+      );
+    } else if (optional('...', next) || optional('...?', next)) {
+      return inStyle ? const ForInSpread() : const ForSpread();
+    }
+    return inStyle ? const ForInEntry() : const ForEntry();
+  }
+}
+
+/// A step for parsing a spread collection
+/// as the "for" control flow's expression.
+class ForSpread extends SpreadOperator {
+  const ForSpread();
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const ForComplete();
+  }
+}
+
+/// A step for parsing a spread collection
+/// as the "for-in" control flow's expression.
+class ForInSpread extends SpreadOperator {
+  const ForInSpread();
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const ForInComplete();
+  }
+}
+
+/// A step for parsing a literal list, set, or map entry
+/// as the "for" control flow's expression.
+class ForEntry extends LiteralEntryInfo {
+  const ForEntry() : super(true, 0);
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const ForComplete();
+  }
+}
+
+/// A step for parsing a literal list, set, or map entry
+/// as the "for-in" control flow's expression.
+class ForInEntry extends LiteralEntryInfo {
+  const ForInEntry() : super(true, 0);
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const ForInComplete();
+  }
+}
+
+class ForComplete extends LiteralEntryInfo {
+  const ForComplete() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    parser.listener.endForControlFlow(token);
+    return token;
+  }
+}
+
+class ForInComplete extends LiteralEntryInfo {
+  const ForInComplete() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    parser.listener.endForInControlFlow(token);
+    return token;
+  }
+}
+
+/// The first step when processing an `if` control flow collection entry.
+class IfCondition extends LiteralEntryInfo {
+  const IfCondition() : super(false, 1);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    final Token ifToken = token.next;
+    assert(optional('if', ifToken));
+    parser.listener.beginIfControlFlow(ifToken);
+    Token result = parser.ensureParenthesizedCondition(ifToken);
+    parser.listener.beginThenControlFlow(result);
+    return result;
+  }
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    Token next = token.next;
+    if (optional('for', 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());
+    } else if (optional('...', next) || optional('...?', next)) {
+      return const IfSpread();
+    }
+    return const IfEntry();
+  }
+}
+
+/// A step for parsing a spread collection
+/// as the `if` control flow's then-expression.
+class IfSpread extends SpreadOperator {
+  const IfSpread();
+
+  @override
+  LiteralEntryInfo computeNext(Token token) => const IfComplete();
+}
+
+/// A step for parsing a literal list, set, or map entry
+/// as the `if` control flow's then-expression.
+class IfEntry extends LiteralEntryInfo {
+  const IfEntry() : super(true, 0);
+
+  @override
+  LiteralEntryInfo computeNext(Token token) => const IfComplete();
+}
+
+class IfComplete extends LiteralEntryInfo {
+  const IfComplete() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    if (!optional('else', token.next)) {
+      parser.listener.endIfControlFlow(token);
+    }
+    return token;
+  }
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return optional('else', token.next) ? const IfElse() : null;
+  }
+}
+
+/// A step for parsing the `else` portion of an `if` control flow.
+class IfElse extends LiteralEntryInfo {
+  const IfElse() : super(false, -1);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    Token elseToken = token.next;
+    assert(optional('else', elseToken));
+    parser.listener.handleElseControlFlow(elseToken);
+    return elseToken;
+  }
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    assert(optional('else', token));
+    Token next = token.next;
+    if (optional('for', 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());
+    } else if (optional('...', next) || optional('...?', next)) {
+      return const ElseSpread();
+    }
+    return const ElseEntry();
+  }
+}
+
+class ElseSpread extends SpreadOperator {
+  const ElseSpread();
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const IfElseComplete();
+  }
+}
+
+class ElseEntry extends LiteralEntryInfo {
+  const ElseEntry() : super(true, 0);
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    return const IfElseComplete();
+  }
+}
+
+class IfElseComplete extends LiteralEntryInfo {
+  const IfElseComplete() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    parser.listener.endIfElseControlFlow(token);
+    return token;
+  }
+}
+
+/// The first step when processing a spread entry.
+class SpreadOperator extends LiteralEntryInfo {
+  const SpreadOperator() : super(false, 0);
+
+  @override
+  Token parse(Token token, Parser parser) {
+    final Token operator = token.next;
+    assert(optional('...', operator) || optional('...?', operator));
+    token = parser.parseExpression(operator);
+    parser.listener.handleSpreadExpression(operator);
+    return token;
+  }
+}
+
+class Nested extends LiteralEntryInfo {
+  LiteralEntryInfo nestedStep;
+  final LiteralEntryInfo lastStep;
+
+  Nested(this.nestedStep, this.lastStep) : super(false, 0);
+
+  @override
+  bool get hasEntry => nestedStep.hasEntry;
+
+  @override
+  Token parse(Token token, Parser parser) => nestedStep.parse(token, parser);
+
+  @override
+  LiteralEntryInfo computeNext(Token token) {
+    nestedStep = nestedStep.computeNext(token);
+    return nestedStep != null ? this : lastStep;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/loop_state.dart b/pkg/_fe_analyzer_shared/lib/src/parser/loop_state.dart
new file mode 100644
index 0000000..1ba0cf3
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/loop_state.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.parser.loop_state;
+
+enum LoopState {
+  OutsideLoop,
+  InsideSwitch, // `break` statement allowed
+  InsideLoop, // `break` and `continue` statements allowed
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/member_kind.dart b/pkg/_fe_analyzer_shared/lib/src/parser/member_kind.dart
new file mode 100644
index 0000000..fba0a1c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/member_kind.dart
@@ -0,0 +1,49 @@
+// 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.
+
+library _fe_analyzer_shared.parser.member_kind;
+
+enum MemberKind {
+  /// A catch block, not a real member.
+  Catch,
+
+  /// A factory
+  Factory,
+
+  /// Old-style typedef.
+  FunctionTypeAlias,
+
+  /// Old-style function-typed parameter, not a real member.
+  FunctionTypedParameter,
+
+  /// A generalized function type, not a real member.
+  GeneralizedFunctionType,
+
+  /// A local function.
+  Local,
+
+  /// A non-static method in a class (including constructors).
+  NonStaticMethod,
+
+  /// A static method in a class.
+  StaticMethod,
+
+  /// A top-level method.
+  TopLevelMethod,
+
+  /// A non-static method in an extension.
+  ExtensionNonStaticMethod,
+
+  /// A static method in an extension.
+  ExtensionStaticMethod,
+
+  /// An instance field in a class.
+  NonStaticField,
+
+  /// A static field in a class.
+  StaticField,
+
+  /// A top-level field.
+  TopLevelField,
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
new file mode 100644
index 0000000..1ab8699
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/modifier_context.dart
@@ -0,0 +1,480 @@
+// 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 '../messages/codes.dart' as codes;
+import '../scanner/token.dart' show Keyword, Token;
+import 'formal_parameter_kind.dart';
+import 'member_kind.dart' show MemberKind;
+import 'parser_impl.dart' show Parser;
+import 'util.dart' show optional;
+
+bool isModifier(Token token) {
+  if (!token.isModifier) {
+    return false;
+  } else if (token.type.isBuiltIn) {
+    // A built-in keyword can only be a modifier as long as it is
+    // followed by another keyword or an identifier. Otherwise, it is the
+    // identifier.
+    //
+    // For example, `external` is a modifier in this declaration:
+    //   external Foo foo();
+    // but is the identifier in this declaration
+    //   external() => true;
+    // and in
+    //   for (final external in list) { }
+    Token next = token.next;
+    Keyword keyword = next.keyword;
+    if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
+      return false;
+    }
+  }
+  return true;
+}
+
+/// This class is used to parse modifiers in most locations where modifiers
+/// 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;
+
+  // Set `true` when parsing modifiers after the `factory` token.
+  bool afterFactory = false;
+
+  // TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
+  // with this class.
+
+  ModifierRecoveryContext(this.parser);
+
+  set staticOrCovariant(Token staticOrCovariant) {
+    if (staticOrCovariant == null) {
+      covariantToken = null;
+      staticToken = null;
+    } else if (optional('covariant', staticOrCovariant)) {
+      covariantToken = staticOrCovariant;
+      staticToken = null;
+    } else if (optional('static', staticOrCovariant)) {
+      covariantToken = null;
+      staticToken = staticOrCovariant;
+    } else {
+      throw "Internal error: "
+          "Unexpected staticOrCovariant '$staticOrCovariant'.";
+    }
+  }
+
+  Token get varFinalOrConst => varToken ?? finalToken ?? constToken;
+
+  set varFinalOrConst(Token varFinalOrConst) {
+    if (varFinalOrConst == null) {
+      varToken = null;
+      finalToken = null;
+      constToken = null;
+    } else if (optional('var', varFinalOrConst)) {
+      varToken = varFinalOrConst;
+      finalToken = null;
+      constToken = null;
+    } else if (optional('final', varFinalOrConst)) {
+      varToken = null;
+      finalToken = varFinalOrConst;
+      constToken = null;
+    } else if (optional('const', varFinalOrConst)) {
+      varToken = null;
+      finalToken = null;
+      constToken = varFinalOrConst;
+    } else {
+      throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
+    }
+  }
+
+  /// Parse modifiers for class methods and fields.
+  Token parseClassMemberModifiers(Token token) {
+    token = parseModifiers(token);
+    if (abstractToken != null) {
+      parser.reportRecoverableError(
+          abstractToken, codes.messageAbstractClassMember);
+    }
+    reportExtraneousModifier(requiredToken);
+    return token;
+  }
+
+  /// Parse modifiers for formal parameters.
+  Token parseFormalParameterModifiers(
+      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
+    token = parseModifiers(token);
+
+    if (parameterKind != FormalParameterKind.optionalNamed) {
+      reportExtraneousModifier(requiredToken);
+    }
+    if (memberKind == MemberKind.StaticMethod ||
+        memberKind == MemberKind.TopLevelMethod) {
+      reportExtraneousModifier(this.covariantToken);
+    } else if (memberKind == MemberKind.ExtensionNonStaticMethod ||
+        memberKind == MemberKind.ExtensionStaticMethod) {
+      reportExtraneousModifierInExtension(this.covariantToken);
+    }
+    if (constToken != null) {
+      reportExtraneousModifier(constToken);
+    } else if (memberKind == MemberKind.GeneralizedFunctionType) {
+      if (varFinalOrConst != null) {
+        parser.reportRecoverableError(
+            varFinalOrConst, codes.messageFunctionTypedParameterVar);
+      }
+    }
+    reportExtraneousModifier(abstractToken);
+    reportExtraneousModifier(externalToken);
+    reportExtraneousModifier(lateToken);
+    reportExtraneousModifier(staticToken);
+    return token;
+  }
+
+  /// Parse modifiers after the `factory` token.
+  Token parseModifiersAfterFactory(Token token) {
+    afterFactory = true;
+    token = parseModifiers(token);
+    if (abstractToken != null) {
+      parser.reportRecoverableError(
+          abstractToken, codes.messageAbstractClassMember);
+    }
+    reportExtraneousModifier(lateToken);
+    reportExtraneousModifier(requiredToken);
+    return token;
+  }
+
+  /// Parse modifiers for top level functions and fields.
+  Token parseTopLevelModifiers(Token token) {
+    token = parseModifiers(token);
+    reportExtraneousModifier(abstractToken);
+    reportExtraneousModifier(covariantToken);
+    reportExtraneousModifier(requiredToken);
+    reportExtraneousModifier(staticToken);
+    return token;
+  }
+
+  /// Parse modifiers for variable declarations.
+  Token parseVariableDeclarationModifiers(Token token) {
+    token = parseModifiers(token);
+    reportExtraneousModifier(abstractToken);
+    reportExtraneousModifier(covariantToken);
+    reportExtraneousModifier(externalToken);
+    reportExtraneousModifier(requiredToken);
+    reportExtraneousModifier(staticToken);
+    return token;
+  }
+
+  /// Parse modifiers during recovery when modifiers are out of order
+  /// or invalid. Typically clients call methods like
+  /// [parseClassMemberModifiers] which in turn calls this method,
+  /// rather than calling this method directly.
+  ///
+  /// The various modifier token parameters represent tokens of modifiers
+  /// that have already been parsed prior to recovery. The [staticOrCovariant]
+  /// parameter is for convenience if caller has a token that may be either
+  /// `static` or `covariant`. The first non-null parameter of
+  /// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
+  /// in that order, and the others ignored.
+  Token parseModifiers(Token token) {
+    // Process invalid and out-of-order modifiers
+    Token next = token.next;
+    while (true) {
+      final String value = next.stringValue;
+      if (isModifier(next)) {
+        if (identical('abstract', value)) {
+          token = parseAbstract(token);
+        } else if (identical('const', value)) {
+          token = parseConst(token);
+        } else if (identical('covariant', value)) {
+          token = parseCovariant(token);
+        } else if (identical('external', value)) {
+          token = parseExternal(token);
+        } else if (identical('final', value)) {
+          token = parseFinal(token);
+        } else if (identical('late', value)) {
+          token = parseLate(token);
+        } else if (identical('required', value)) {
+          token = parseRequired(token);
+        } else if (identical('static', value)) {
+          token = parseStatic(token);
+        } else if (identical('var', value)) {
+          token = parseVar(token);
+        } else {
+          throw 'Internal Error: Unhandled modifier: $value';
+        }
+      } else if (afterFactory && identical('factory', value)) {
+        parser.reportRecoverableErrorWithToken(
+            next, codes.templateDuplicatedModifier);
+        token = next;
+      } else {
+        break;
+      }
+      next = token.next;
+    }
+    return token;
+  }
+
+  Token parseAbstract(Token token) {
+    Token next = token.next;
+    assert(optional('abstract', next));
+    if (abstractToken == null) {
+      abstractToken = next;
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, codes.templateDuplicatedModifier);
+    return next;
+  }
+
+  Token parseConst(Token token) {
+    Token next = token.next;
+    assert(optional('const', next));
+    if (varFinalOrConst == null && covariantToken == null) {
+      constToken = next;
+
+      if (afterFactory) {
+        reportModifierOutOfOrder(next, 'factory');
+      } else if (lateToken != null) {
+        reportConflictingModifiers(next, lateToken);
+      }
+      return next;
+    }
+
+    // Recovery
+    if (constToken != null) {
+      parser.reportRecoverableErrorWithToken(
+          next, codes.templateDuplicatedModifier);
+    } else if (covariantToken != null) {
+      reportConflictingModifiers(next, covariantToken);
+    } else if (finalToken != null) {
+      parser.reportRecoverableError(next, codes.messageConstAndFinal);
+    } else if (varToken != null) {
+      reportConflictingModifiers(next, varToken);
+    } else {
+      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
+    }
+    return next;
+  }
+
+  Token parseCovariant(Token token) {
+    Token next = token.next;
+    assert(optional('covariant', next));
+    if (constToken == null &&
+        covariantToken == null &&
+        staticToken == null &&
+        !afterFactory) {
+      covariantToken = next;
+
+      if (varToken != null) {
+        reportModifierOutOfOrder(next, varToken.lexeme);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(next, finalToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    if (covariantToken != null) {
+      parser.reportRecoverableErrorWithToken(
+          next, codes.templateDuplicatedModifier);
+    } else if (afterFactory) {
+      reportExtraneousModifier(next);
+    } else if (constToken != null) {
+      reportConflictingModifiers(next, constToken);
+    } else if (staticToken != null) {
+      parser.reportRecoverableError(next, codes.messageCovariantAndStatic);
+    } else {
+      throw 'Internal Error: Unhandled recovery: $next';
+    }
+    return next;
+  }
+
+  Token parseExternal(Token token) {
+    Token next = token.next;
+    assert(optional('external', next));
+    if (externalToken == null) {
+      externalToken = next;
+
+      if (afterFactory) {
+        reportModifierOutOfOrder(next, 'factory');
+      } else if (constToken != null) {
+        reportModifierOutOfOrder(next, constToken.lexeme);
+      } else if (staticToken != null) {
+        reportModifierOutOfOrder(next, staticToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, codes.templateDuplicatedModifier);
+    return next;
+  }
+
+  Token parseFinal(Token token) {
+    Token next = token.next;
+    assert(optional('final', next));
+    if (varFinalOrConst == null && !afterFactory) {
+      finalToken = next;
+      return next;
+    }
+
+    // Recovery
+    if (finalToken != null) {
+      parser.reportRecoverableErrorWithToken(
+          next, codes.templateDuplicatedModifier);
+    } else if (afterFactory) {
+      reportExtraneousModifier(next);
+    } else if (constToken != null) {
+      parser.reportRecoverableError(next, codes.messageConstAndFinal);
+    } else if (varToken != null) {
+      parser.reportRecoverableError(next, codes.messageFinalAndVar);
+    } else if (lateToken != null) {
+      reportModifierOutOfOrder(next, lateToken.lexeme);
+    } else {
+      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
+    }
+    return next;
+  }
+
+  Token parseLate(Token token) {
+    Token next = token.next;
+    assert(optional('late', next));
+    if (lateToken == null) {
+      lateToken = next;
+
+      if (constToken != null) {
+        reportConflictingModifiers(next, constToken);
+      } else if (varToken != null) {
+        reportModifierOutOfOrder(next, varToken.lexeme);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(next, finalToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, codes.templateDuplicatedModifier);
+    return next;
+  }
+
+  Token parseRequired(Token token) {
+    Token next = token.next;
+    assert(optional('required', next));
+    if (requiredToken == null) {
+      requiredToken = next;
+
+      if (constToken != null) {
+        reportModifierOutOfOrder(requiredToken, constToken.lexeme);
+      } else if (covariantToken != null) {
+        reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
+      } else if (varToken != null) {
+        reportModifierOutOfOrder(requiredToken, varToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    parser.reportRecoverableErrorWithToken(
+        next, codes.templateDuplicatedModifier);
+    return next;
+  }
+
+  Token parseStatic(Token token) {
+    Token next = token.next;
+    assert(optional('static', next));
+    if (covariantToken == null && staticToken == null && !afterFactory) {
+      staticToken = next;
+
+      if (constToken != null) {
+        reportModifierOutOfOrder(next, constToken.lexeme);
+      } else if (finalToken != null) {
+        reportModifierOutOfOrder(next, finalToken.lexeme);
+      } else if (varToken != null) {
+        reportModifierOutOfOrder(next, varToken.lexeme);
+      } else if (lateToken != null) {
+        reportModifierOutOfOrder(next, lateToken.lexeme);
+      }
+      return next;
+    }
+
+    // Recovery
+    if (covariantToken != null) {
+      parser.reportRecoverableError(next, codes.messageCovariantAndStatic);
+    } else if (staticToken != null) {
+      parser.reportRecoverableErrorWithToken(
+          next, codes.templateDuplicatedModifier);
+    } else if (afterFactory) {
+      reportExtraneousModifier(next);
+    } else {
+      throw 'Internal Error: Unhandled recovery: $next';
+    }
+    return next;
+  }
+
+  Token parseVar(Token token) {
+    Token next = token.next;
+    assert(optional('var', next));
+    if (varFinalOrConst == null && !afterFactory) {
+      varToken = next;
+      return next;
+    }
+
+    // Recovery
+    if (varToken != null) {
+      parser.reportRecoverableErrorWithToken(
+          next, codes.templateDuplicatedModifier);
+    } else if (afterFactory) {
+      reportExtraneousModifier(next);
+    } else if (constToken != null) {
+      reportConflictingModifiers(next, constToken);
+    } else if (finalToken != null) {
+      parser.reportRecoverableError(next, codes.messageFinalAndVar);
+    } else {
+      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
+    }
+    return next;
+  }
+
+  void reportConflictingModifiers(Token modifier, Token earlierModifier) {
+    parser.reportRecoverableError(
+        modifier,
+        codes.templateConflictingModifiers
+            .withArguments(modifier.lexeme, earlierModifier.lexeme));
+  }
+
+  void reportExtraneousModifier(Token modifier) {
+    if (modifier != null) {
+      parser.reportRecoverableErrorWithToken(
+          modifier, codes.templateExtraneousModifier);
+    }
+  }
+
+  void reportExtraneousModifierInExtension(Token modifier) {
+    if (modifier != null) {
+      parser.reportRecoverableErrorWithToken(
+          modifier, codes.templateExtraneousModifierInExtension);
+    }
+  }
+
+  void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
+    parser.reportRecoverableError(
+        modifier,
+        codes.templateModifierOutOfOrder
+            .withArguments(modifier.lexeme, beforeModifier));
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser.dart
new file mode 100644
index 0000000..0bd8882
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser.dart
@@ -0,0 +1,61 @@
+// 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.md file.
+
+library _fe_analyzer_shared.parser;
+
+import '../scanner/token.dart' show Token;
+
+import 'listener.dart' show Listener;
+
+import 'parser_impl.dart' show Parser;
+
+import 'parser_error.dart' show ParserError;
+
+import '../messages/codes.dart'
+    show Message, messageNativeClauseShouldBeAnnotation;
+
+export 'assert.dart' show Assert;
+
+export 'block_kind.dart' show BlockKind;
+
+export 'class_member_parser.dart' show ClassMemberParser;
+
+export 'formal_parameter_kind.dart' show FormalParameterKind;
+
+export 'identifier_context.dart' show IdentifierContext;
+
+export 'listener.dart' show Listener;
+
+export 'declaration_kind.dart' show DeclarationKind;
+
+export 'member_kind.dart' show MemberKind;
+
+export 'parser_impl.dart' show Parser;
+
+export 'parser_error.dart' show ParserError;
+
+export 'top_level_parser.dart' show TopLevelParser;
+
+export 'util.dart' show lengthForToken, lengthOfSpan, optional;
+
+class ErrorCollectingListener extends Listener {
+  final List<ParserError> recoverableErrors = <ParserError>[];
+
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    /// TODO(danrubel): Ignore this error until we deprecate `native` support.
+    if (message == messageNativeClauseShouldBeAnnotation) {
+      return;
+    }
+    recoverableErrors
+        .add(new ParserError.fromTokens(startToken, endToken, message));
+  }
+}
+
+List<ParserError> parse(Token tokens) {
+  ErrorCollectingListener listener = new ErrorCollectingListener();
+  Parser parser = new Parser(listener);
+  parser.parseUnit(tokens);
+  return listener.recoverableErrors;
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.md b/pkg/_fe_analyzer_shared/lib/src/parser/parser.md
similarity index 100%
rename from pkg/front_end/lib/src/fasta/parser/parser.md
rename to pkg/_fe_analyzer_shared/lib/src/parser/parser.md
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_error.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_error.dart
new file mode 100644
index 0000000..8c46c13
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_error.dart
@@ -0,0 +1,26 @@
+// 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.
+
+library _fe_analyzer_shared.parser.parser_error;
+
+import '../messages/codes.dart' show Message;
+
+import '../scanner/scanner.dart' show Token;
+
+class ParserError {
+  /// Character offset from the beginning of file where this error starts.
+  final int beginOffset;
+
+  /// Character offset from the beginning of file where this error ends.
+  final int endOffset;
+
+  final Message message;
+
+  ParserError(this.beginOffset, this.endOffset, this.message);
+
+  ParserError.fromTokens(Token begin, Token end, Message message)
+      : this(begin.charOffset, end.charOffset + end.charCount, message);
+
+  String toString() => "@${beginOffset}: ${message.message}\n${message.tip}";
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
new file mode 100644
index 0000000..e838b3c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -0,0 +1,7046 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.parser.parser;
+
+import '../messages/codes.dart' show Message, Template;
+
+import '../messages/codes.dart' as codes;
+
+import '../scanner/scanner.dart' show ErrorToken, Token;
+
+import '../scanner/token.dart'
+    show
+        ASSIGNMENT_PRECEDENCE,
+        BeginToken,
+        CASCADE_PRECEDENCE,
+        EQUALITY_PRECEDENCE,
+        Keyword,
+        POSTFIX_PRECEDENCE,
+        RELATIONAL_PRECEDENCE,
+        SELECTOR_PRECEDENCE,
+        SyntheticBeginToken,
+        SyntheticKeywordToken,
+        SyntheticStringToken,
+        SyntheticToken,
+        TokenType;
+
+import '../scanner/token_constants.dart'
+    show
+        BANG_EQ_EQ_TOKEN,
+        COMMA_TOKEN,
+        DOUBLE_TOKEN,
+        EOF_TOKEN,
+        EQ_EQ_EQ_TOKEN,
+        EQ_TOKEN,
+        FUNCTION_TOKEN,
+        HASH_TOKEN,
+        HEXADECIMAL_TOKEN,
+        IDENTIFIER_TOKEN,
+        INT_TOKEN,
+        KEYWORD_TOKEN,
+        LT_TOKEN,
+        OPEN_CURLY_BRACKET_TOKEN,
+        OPEN_PAREN_TOKEN,
+        OPEN_SQUARE_BRACKET_TOKEN,
+        SEMICOLON_TOKEN,
+        STRING_INTERPOLATION_IDENTIFIER_TOKEN,
+        STRING_INTERPOLATION_TOKEN,
+        STRING_TOKEN;
+
+import 'assert.dart' show Assert;
+
+import 'async_modifier.dart' show AsyncModifier;
+
+import 'block_kind.dart';
+
+import 'declaration_kind.dart' show DeclarationKind;
+
+import 'directive_context.dart';
+
+import 'formal_parameter_kind.dart'
+    show
+        FormalParameterKind,
+        isMandatoryFormalParameterKind,
+        isOptionalPositionalFormalParameterKind;
+
+import 'forwarding_listener.dart' show ForwardingListener;
+
+import 'identifier_context.dart'
+    show IdentifierContext, looksLikeExpressionStart;
+
+import 'listener.dart' show Listener;
+
+import 'literal_entry_info.dart'
+    show
+        LiteralEntryInfo,
+        computeLiteralEntry,
+        looksLikeLiteralEntry,
+        simpleEntry;
+
+import 'loop_state.dart' show LoopState;
+
+import 'member_kind.dart' show MemberKind;
+
+import 'modifier_context.dart' show ModifierRecoveryContext, isModifier;
+
+import 'recovery_listeners.dart'
+    show
+        ClassHeaderRecoveryListener,
+        ImportRecoveryListener,
+        MixinHeaderRecoveryListener;
+
+import 'token_stream_rewriter.dart' show TokenStreamRewriter;
+
+import 'type_info.dart'
+    show
+        TypeInfo,
+        TypeParamOrArgInfo,
+        computeMethodTypeArguments,
+        computeType,
+        computeTypeParamOrArg,
+        isValidTypeReference,
+        noType,
+        noTypeParamOrArg;
+
+import 'util.dart'
+    show
+        findNonZeroLengthToken,
+        findPreviousNonZeroLengthToken,
+        isLetter,
+        isLetterOrDigit,
+        isOneOf,
+        isOneOfOrEof,
+        isWhitespace,
+        optional;
+
+/// An event generating parser of Dart programs. This parser expects all tokens
+/// in a linked list (aka a token stream).
+///
+/// The class [Scanner] is used to generate a token stream. See the file
+/// [scanner.dart](../scanner.dart).
+///
+/// Subclasses of the class [Listener] are used to listen to events.
+///
+/// Most methods of this class belong in one of four major categories: parse
+/// methods, peek methods, ensure methods, and skip methods.
+///
+/// Parse methods all have the prefix `parse`, generate events
+/// (by calling methods on [listener]), and return the next token to parse.
+/// Some exceptions to this last point are methods such as [parseFunctionBody]
+/// and [parseClassOrMixinOrExtensionBody] which return the last token parsed
+/// rather than the next token to be parsed.
+/// Parse methods are generally named `parseGrammarProductionSuffix`.
+/// The suffix can be one of `opt`, or `star`.
+/// `opt` means zero or one matches, `star` means zero or more matches.
+/// For example, [parseMetadataStar] corresponds to this grammar snippet:
+/// `metadata*`, and [parseArgumentsOpt] corresponds to: `arguments?`.
+///
+/// Peek methods all have the prefix `peek`, do not generate events
+/// (except for errors) and may return null.
+///
+/// Ensure methods all have the prefix `ensure` and may generate events.
+/// They return the current token, or insert and return a synthetic token
+/// if the current token does not match. For example,
+/// [ensureSemicolon] returns the current token if the current token is a
+/// semicolon, otherwise inserts a synthetic semicolon in the token stream
+/// before the current token and then returns that new synthetic token.
+///
+/// Skip methods are like parse methods, but all have the prefix `skip`
+/// and skip over some parts of the file being parsed.
+/// Typically, skip methods generate an event for the structure being skipped,
+/// but not for its substructures.
+///
+/// ## Current Token
+///
+/// The current token is always to be found in a formal parameter named
+/// `token`. This parameter should be the first as this increases the chance
+/// that a compiler will place it in a register.
+///
+/// ## Implementation Notes
+///
+/// The parser assumes that keywords, built-in identifiers, and other special
+/// words (pseudo-keywords) are all canonicalized. To extend the parser to
+/// recognize a new identifier, one should modify
+/// [keyword.dart](../scanner/keyword.dart) and ensure the identifier is added
+/// to the keyword table.
+///
+/// As a consequence of this, one should not use `==` to compare strings in the
+/// parser. One should favor the methods [optional] and [expect] to recognize
+/// keywords or identifiers. In some cases, it's possible to compare a token's
+/// `stringValue` using [identical], but normally [optional] will suffice.
+///
+/// Historically, we over-used identical, and when identical is used on objects
+/// other than strings, it can often be replaced by `==`.
+///
+/// ## Flexibility, Extensibility, and Specification
+///
+/// The parser is designed to be flexible and extensible. Its methods are
+/// designed to be overridden in subclasses, so it can be extended to handle
+/// unspecified language extension or experiments while everything in this file
+/// attempts to follow the specification (unless when it interferes with error
+/// recovery).
+///
+/// We achieve flexibility, extensible, and specification compliance by
+/// following a few rules-of-thumb:
+///
+/// 1. All methods in the parser should be public.
+///
+/// 2. The methods follow the specified grammar, and do not implement custom
+/// extensions, for example, `native`.
+///
+/// 3. The parser doesn't rewrite the token stream (when dealing with `>>`).
+///
+/// ### Implementing Extensions
+///
+/// For various reasons, some Dart language implementations have used
+/// custom/unspecified extensions to the Dart grammar. Examples of this
+/// includes diet parsing, patch files, `native` keyword, and generic
+/// comments. This class isn't supposed to implement any of these
+/// features. Instead it provides hooks for those extensions to be implemented
+/// in subclasses or listeners. Let's examine how diet parsing and `native`
+/// keyword is currently supported by Fasta.
+///
+/// #### Legacy Implementation of `native` Keyword
+///
+/// TODO(ahe,danrubel): Remove this section.
+///
+/// Both dart2js and the Dart VM have used the `native` keyword to mark methods
+/// that couldn't be implemented in the Dart language and needed to be
+/// implemented in JavaScript or C++, respectively. An example of the syntax
+/// extension used by the Dart VM is:
+///
+///     nativeFunction() native "NativeFunction";
+///
+/// When attempting to parse this function, the parser eventually calls
+/// [parseFunctionBody]. This method will report an unrecoverable error to the
+/// listener with the code [fasta.messageExpectedFunctionBody]. The listener can
+/// then look at the error code and the token and use the methods in
+/// [native_support.dart](native_support.dart) to parse the native syntax.
+///
+/// #### Implementation of Diet Parsing
+///
+/// We call it _diet_ _parsing_ when the parser skips parts of a file. Both
+/// dart2js and the Dart VM have been relying on this from early on as it allows
+/// them to more quickly compile small programs that use small parts of big
+/// libraries. It's also become an integrated part of how Fasta builds up
+/// outlines before starting to parse method bodies.
+///
+/// When looking through this parser, you'll find a number of unused methods
+/// starting with `skip`. These methods are only used by subclasses, such as
+/// [ClassMemberParser](class_member_parser.dart) and
+/// [TopLevelParser](top_level_parser.dart). These methods violate the
+/// principle above about following the specified grammar, and originally lived
+/// in subclasses. However, we realized that these methods were so widely used
+/// and hard to maintain in subclasses, that it made sense to move them here.
+///
+/// ### Specification and Error Recovery
+///
+/// To improve error recovery, the parser will inform the listener of
+/// recoverable errors and continue to parse.  An example of a recoverable
+/// error is:
+///
+///     Error: Asynchronous for-loop can only be used in 'async' or 'async*'...
+///     main() { await for (var x in []) {} }
+///              ^^^^^
+///
+/// ### Legacy Error Recovery
+///
+/// What's described below will be phased out in preference of the parser
+/// reporting and recovering from syntax errors. The motivation for this is
+/// that we have multiple listeners that use the parser, and this will ensure
+/// consistency.
+///
+/// For unrecoverable errors, the parser will ask the listener for help to
+/// recover from the error. We haven't made much progress on these kinds of
+/// errors, so in most cases, the parser aborts by skipping to the end of file.
+///
+/// Historically, this parser has been rather lax in what it allows, and
+/// deferred the enforcement of some syntactical rules to subsequent phases. It
+/// doesn't matter how we got there, only that we've identified that it's
+/// easier if the parser reports as many errors it can, but informs the
+/// listener if the error is recoverable or not.
+class Parser {
+  Listener listener;
+
+  Uri get uri => listener.uri;
+
+  bool mayParseFunctionExpressions = true;
+
+  /// Represents parser state: what asynchronous syntax is allowed in the
+  /// function being currently parsed. In rare situations, this can be set by
+  /// external clients, for example, to parse an expression outside a function.
+  AsyncModifier asyncState = AsyncModifier.Sync;
+
+  // TODO(danrubel): The [loopState] and associated functionality in the
+  // [Parser] duplicates work that the resolver needs to do when resolving
+  // break/continue targets. Long term, this state and functionality will be
+  // removed from the [Parser] class and the resolver will be responsible
+  // for generating all break/continue error messages.
+
+  /// Represents parser state: whether parsing outside a loop,
+  /// inside a loop, or inside a switch. This is used to determine whether
+  /// break and continue statements are allowed.
+  LoopState loopState = LoopState.OutsideLoop;
+
+  /// A rewriter for inserting synthetic tokens.
+  /// Access using [rewriter] for lazy initialization.
+  TokenStreamRewriter cachedRewriter;
+
+  TokenStreamRewriter get rewriter {
+    cachedRewriter ??= new TokenStreamRewriter();
+    return cachedRewriter;
+  }
+
+  Parser(this.listener);
+
+  bool get inGenerator {
+    return asyncState == AsyncModifier.AsyncStar ||
+        asyncState == AsyncModifier.SyncStar;
+  }
+
+  bool get inAsync {
+    return asyncState == AsyncModifier.Async ||
+        asyncState == AsyncModifier.AsyncStar;
+  }
+
+  bool get inPlainSync => asyncState == AsyncModifier.Sync;
+
+  bool get isBreakAllowed => loopState != LoopState.OutsideLoop;
+
+  bool get isContinueAllowed => loopState == LoopState.InsideLoop;
+
+  bool get isContinueWithLabelAllowed => loopState != LoopState.OutsideLoop;
+
+  /// Parse a compilation unit.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  ///
+  /// ```
+  /// libraryDefinition:
+  ///   scriptTag?
+  ///   libraryName?
+  ///   importOrExport*
+  ///   partDirective*
+  ///   topLevelDefinition*
+  /// ;
+  ///
+  /// partDeclaration:
+  ///   partHeader topLevelDefinition*
+  /// ;
+  /// ```
+  Token parseUnit(Token token) {
+    // Skip over error tokens and report them at the end
+    // so that the parser has the chance to adjust the error location.
+    Token errorToken = token;
+    token = skipErrorTokens(errorToken);
+
+    listener.beginCompilationUnit(token);
+    int count = 0;
+    DirectiveContext directiveState = new DirectiveContext();
+    token = syntheticPreviousToken(token);
+    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;
+      token = parseTopLevelDeclarationImpl(token, directiveState);
+      listener.endTopLevelDeclaration(token.next);
+      count++;
+      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;
+        listener.beginMetadataStar(token);
+        listener.endMetadataStar(0);
+        reportRecoverableErrorWithToken(
+            token, codes.templateExpectedDeclaration);
+        listener.handleInvalidTopLevelDeclaration(token);
+        listener.endTopLevelDeclaration(token.next);
+        count++;
+      }
+    }
+    token = token.next;
+    reportAllErrorTokens(errorToken);
+    listener.endCompilationUnit(count, token);
+    // Clear fields that could lead to memory leak.
+    cachedRewriter = null;
+    return token;
+  }
+
+  /// This method exists for analyzer compatibility only
+  /// and will be removed once analyzer/fasta integration is complete.
+  ///
+  /// Similar to [parseUnit], this method parses a compilation unit,
+  /// but stops when it reaches the first declaration or EOF.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseDirectives(Token token) {
+    listener.beginCompilationUnit(token);
+    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;
+
+      // If a built-in keyword is being used as function name, then stop.
+      if (identical(nextValue, '.') ||
+          identical(nextValue, '<') ||
+          identical(nextValue, '(')) {
+        break;
+      }
+
+      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;
+        if (identical(value, 'import')) {
+          directiveState?.checkImport(this, keyword);
+          token = parseImport(keyword);
+        } else if (identical(value, 'export')) {
+          directiveState?.checkExport(this, keyword);
+          token = parseExport(keyword);
+        } else if (identical(value, 'library')) {
+          directiveState?.checkLibrary(this, keyword);
+          token = parseLibraryName(keyword);
+        } else if (identical(value, 'part')) {
+          token = parsePartOrPartOf(keyword, directiveState);
+        } else if (identical(value, ';')) {
+          token = start;
+        } else {
+          listener.handleDirectivesOnly();
+          break;
+        }
+      }
+      listener.endTopLevelDeclaration(token.next);
+    }
+    token = token.next;
+    listener.endCompilationUnit(count, token);
+    // Clear fields that could lead to memory leak.
+    cachedRewriter = null;
+    return token;
+  }
+
+  /// Parse a top-level declaration.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseTopLevelDeclaration(Token token) {
+    token =
+        parseTopLevelDeclarationImpl(syntheticPreviousToken(token), null).next;
+    listener.endTopLevelDeclaration(token);
+    return token;
+  }
+
+  /// ```
+  /// topLevelDefinition:
+  ///   classDefinition |
+  ///   enumType |
+  ///   typeAlias |
+  ///   'external'? functionSignature ';' |
+  ///   'external'? getterSignature ';' |
+  ///   'external''? setterSignature ';' |
+  ///   functionSignature functionBody |
+  ///   returnType? 'get' identifier functionBody |
+  ///   returnType? 'set' identifier formalParameterList functionBody |
+  ///   ('final' | 'const') type? staticFinalDeclarationList ';' |
+  ///   variableDeclaration ';'
+  /// ;
+  /// ```
+  Token parseTopLevelDeclarationImpl(
+      Token token, DirectiveContext directiveState) {
+    token = parseMetadataStar(token);
+    Token next = token.next;
+    if (next.isTopLevelKeyword) {
+      return parseTopLevelKeywordDeclaration(token, next, directiveState);
+    }
+    Token start = token;
+    // Skip modifiers to find a top level keyword or identifier
+    if (next.isModifier) {
+      if (optional('var', next) ||
+          optional('late', next) ||
+          ((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))) {
+        directiveState?.checkDeclaration();
+        return parseTopLevelMemberImpl(token);
+      }
+      while (token.next.isModifier) {
+        token = token.next;
+      }
+    }
+    next = token.next;
+    if (next.isTopLevelKeyword) {
+      return parseTopLevelKeywordDeclaration(start, next, directiveState);
+    } else if (next.isKeywordOrIdentifier) {
+      // TODO(danrubel): improve parseTopLevelMember
+      // so that we don't parse modifiers twice.
+      directiveState?.checkDeclaration();
+      return parseTopLevelMemberImpl(start);
+    } else if (start.next != next) {
+      directiveState?.checkDeclaration();
+      // Handle the edge case where a modifier is being used as an identifier
+      return parseTopLevelMemberImpl(start);
+    }
+    // Recovery
+    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
+      // and continue parsing as a top level function.
+      rewriter.insertSyntheticIdentifier(
+          next, '#synthetic_function_${next.charOffset}');
+      return parseTopLevelMemberImpl(next);
+    }
+    // Ignore any preceding modifiers and just report the unexpected token
+    listener.beginTopLevelMember(next);
+    return parseInvalidTopLevelDeclaration(token);
+  }
+
+  /// 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;
+    while (modifier != keyword) {
+      if (optional('abstract', modifier)) {
+        parseTopLevelKeywordModifiers(modifier, keyword);
+        return modifier;
+      } else {
+        // Recovery
+        reportTopLevelModifierError(modifier, keyword);
+      }
+      modifier = modifier.next;
+    }
+    return null;
+  }
+
+  /// Report errors on any modifiers before the specified keyword.
+  void parseTopLevelKeywordModifiers(Token start, Token keyword) {
+    Token modifier = start.next;
+    while (modifier != keyword) {
+      // Recovery
+      reportTopLevelModifierError(modifier, keyword);
+      modifier = modifier.next;
+    }
+  }
+
+  // Report an error for the given modifier preceding a top level keyword
+  // such as `import` or `class`.
+  void reportTopLevelModifierError(Token modifier, Token afterModifiers) {
+    if (optional('const', modifier) && optional('class', afterModifiers)) {
+      reportRecoverableError(modifier, codes.messageConstClass);
+    } else if (optional('external', modifier)) {
+      if (optional('class', afterModifiers)) {
+        reportRecoverableError(modifier, codes.messageExternalClass);
+      } else if (optional('enum', afterModifiers)) {
+        reportRecoverableError(modifier, codes.messageExternalEnum);
+      } else if (optional('typedef', afterModifiers)) {
+        reportRecoverableError(modifier, codes.messageExternalTypedef);
+      } else {
+        reportRecoverableErrorWithToken(
+            modifier, codes.templateExtraneousModifier);
+      }
+    } else {
+      reportRecoverableErrorWithToken(
+          modifier, codes.templateExtraneousModifier);
+    }
+  }
+
+  /// 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) {
+    assert(keyword.isTopLevelKeyword);
+    final String value = keyword.stringValue;
+    if (identical(value, 'class')) {
+      directiveState?.checkDeclaration();
+      Token abstractToken = parseClassDeclarationModifiers(start, keyword);
+      return parseClassOrNamedMixinApplication(abstractToken, keyword);
+    } else if (identical(value, 'enum')) {
+      directiveState?.checkDeclaration();
+      parseTopLevelKeywordModifiers(start, keyword);
+      return parseEnum(keyword);
+    } else {
+      // The remaining top level keywords are built-in keywords
+      // 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;
+      if (identical(nextValue, '(') || identical(nextValue, '.')) {
+        directiveState?.checkDeclaration();
+        return parseTopLevelMemberImpl(start);
+      } else if (identical(nextValue, '<')) {
+        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)) {
+            directiveState?.checkDeclaration();
+            return parseExtension(keyword);
+          }
+        }
+        directiveState?.checkDeclaration();
+        return parseTopLevelMemberImpl(start);
+      } else {
+        parseTopLevelKeywordModifiers(start, keyword);
+        if (identical(value, 'import')) {
+          directiveState?.checkImport(this, keyword);
+          return parseImport(keyword);
+        } else if (identical(value, 'export')) {
+          directiveState?.checkExport(this, keyword);
+          return parseExport(keyword);
+        } else if (identical(value, 'typedef')) {
+          directiveState?.checkDeclaration();
+          return parseTypedef(keyword);
+        } else if (identical(value, 'mixin')) {
+          directiveState?.checkDeclaration();
+          return parseMixin(keyword);
+        } else if (identical(value, 'extension')) {
+          directiveState?.checkDeclaration();
+          return parseExtension(keyword);
+        } else if (identical(value, 'part')) {
+          return parsePartOrPartOf(keyword, directiveState);
+        } else if (identical(value, 'library')) {
+          directiveState?.checkLibrary(this, keyword);
+          return parseLibraryName(keyword);
+        }
+      }
+    }
+
+    throw "Internal error: Unhandled top level keyword '$value'.";
+  }
+
+  /// ```
+  /// libraryDirective:
+  ///   'library' qualified ';'
+  /// ;
+  /// ```
+  Token parseLibraryName(Token libraryKeyword) {
+    assert(optional('library', libraryKeyword));
+    listener.beginLibraryName(libraryKeyword);
+    Token token = parseQualified(libraryKeyword, IdentifierContext.libraryName,
+        IdentifierContext.libraryNameContinuation);
+    token = ensureSemicolon(token);
+    listener.endLibraryName(libraryKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// importPrefix:
+  ///   'deferred'? 'as' identifier
+  /// ;
+  /// ```
+  Token parseImportPrefixOpt(Token token) {
+    Token next = token.next;
+    if (optional('deferred', next) && optional('as', next.next)) {
+      Token deferredToken = next;
+      Token asKeyword = next.next;
+      token = ensureIdentifier(
+          asKeyword, IdentifierContext.importPrefixDeclaration);
+      listener.handleImportPrefix(deferredToken, asKeyword);
+    } else if (optional('as', next)) {
+      Token asKeyword = next;
+      token = ensureIdentifier(next, IdentifierContext.importPrefixDeclaration);
+      listener.handleImportPrefix(null, asKeyword);
+    } else {
+      listener.handleImportPrefix(null, null);
+    }
+    return token;
+  }
+
+  /// ```
+  /// importDirective:
+  ///   'import' uri ('if' '(' test ')' uri)* importPrefix? combinator* ';'
+  /// ;
+  /// ```
+  Token parseImport(Token importKeyword) {
+    assert(optional('import', importKeyword));
+    listener.beginImport(importKeyword);
+    Token token = ensureLiteralString(importKeyword);
+    Token uri = token;
+    token = parseConditionalUriStar(token);
+    token = parseImportPrefixOpt(token);
+    token = parseCombinatorStar(token).next;
+    if (optional(';', token)) {
+      listener.endImport(importKeyword, token);
+      return token;
+    } else {
+      // Recovery
+      listener.endImport(importKeyword, null);
+      return parseImportRecovery(uri);
+    }
+  }
+
+  /// Recover given out-of-order clauses in an import directive where [token] is
+  /// the import keyword.
+  Token parseImportRecovery(Token token) {
+    final Listener primaryListener = listener;
+    final ImportRecoveryListener recoveryListener =
+        new ImportRecoveryListener();
+
+    // Reparse to determine which clauses have already been parsed
+    // but intercept the events so they are not sent to the primary listener
+    listener = recoveryListener;
+    token = parseConditionalUriStar(token);
+    token = parseImportPrefixOpt(token);
+    token = parseCombinatorStar(token);
+
+    Token firstDeferredKeyword = recoveryListener.deferredKeyword;
+    bool hasPrefix = recoveryListener.asKeyword != null;
+    bool hasCombinator = recoveryListener.hasCombinator;
+
+    // Update the recovery listener to forward subsequent events
+    // to the primary listener
+    recoveryListener.listener = primaryListener;
+
+    // Parse additional out-of-order clauses.
+    Token semicolon;
+    do {
+      Token start = token.next;
+
+      // Check for extraneous token in the middle of an import statement.
+      token = skipUnexpectedTokenOpt(
+          token, const <String>['if', 'deferred', 'as', 'hide', 'show', ';']);
+
+      // During recovery, clauses are parsed in the same order
+      // and generate the same events as in the parseImport method above.
+      recoveryListener.clear();
+      token = parseConditionalUriStar(token);
+      if (recoveryListener.ifKeyword != null) {
+        if (firstDeferredKeyword != null) {
+          // TODO(danrubel): report error indicating conditional should
+          // be moved before deferred keyword
+        } else if (hasPrefix) {
+          // TODO(danrubel): report error indicating conditional should
+          // be moved before prefix clause
+        } else if (hasCombinator) {
+          // TODO(danrubel): report error indicating conditional should
+          // be moved before combinators
+        }
+      }
+
+      if (optional('deferred', token.next) &&
+          !optional('as', token.next.next)) {
+        listener.handleImportPrefix(token.next, null);
+        token = token.next;
+      } else {
+        token = parseImportPrefixOpt(token);
+      }
+      if (recoveryListener.deferredKeyword != null) {
+        if (firstDeferredKeyword != null) {
+          reportRecoverableError(
+              recoveryListener.deferredKeyword, codes.messageDuplicateDeferred);
+        } else {
+          if (hasPrefix) {
+            reportRecoverableError(recoveryListener.deferredKeyword,
+                codes.messageDeferredAfterPrefix);
+          }
+          firstDeferredKeyword = recoveryListener.deferredKeyword;
+        }
+      }
+      if (recoveryListener.asKeyword != null) {
+        if (hasPrefix) {
+          reportRecoverableError(
+              recoveryListener.asKeyword, codes.messageDuplicatePrefix);
+        } else {
+          if (hasCombinator) {
+            reportRecoverableError(
+                recoveryListener.asKeyword, codes.messagePrefixAfterCombinator);
+          }
+          hasPrefix = true;
+        }
+      }
+
+      token = parseCombinatorStar(token);
+      hasCombinator = hasCombinator || recoveryListener.hasCombinator;
+
+      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);
+      }
+      listener.handleRecoverImport(semicolon);
+    } while (semicolon == null);
+
+    if (firstDeferredKeyword != null && !hasPrefix) {
+      reportRecoverableError(
+          firstDeferredKeyword, codes.messageMissingPrefixInDeferredImport);
+    }
+
+    return semicolon;
+  }
+
+  /// ```
+  /// conditionalUris:
+  ///   conditionalUri*
+  /// ;
+  /// ```
+  Token parseConditionalUriStar(Token token) {
+    listener.beginConditionalUris(token.next);
+    int count = 0;
+    while (optional('if', token.next)) {
+      count++;
+      token = parseConditionalUri(token);
+    }
+    listener.endConditionalUris(count);
+    return token;
+  }
+
+  /// ```
+  /// conditionalUri:
+  ///   'if' '(' dottedName ('==' literalString)? ')' uri
+  /// ;
+  /// ```
+  Token parseConditionalUri(Token token) {
+    Token ifKeyword = token = token.next;
+    assert(optional('if', token));
+    listener.beginConditionalUri(token);
+    Token leftParen = token.next;
+    if (!optional('(', leftParen)) {
+      reportRecoverableError(
+          leftParen, codes.templateExpectedButGot.withArguments('('));
+      leftParen = rewriter.insertParens(token, true);
+    }
+    token = parseDottedName(leftParen);
+    Token next = token.next;
+    Token equalitySign;
+    if (optional('==', next)) {
+      equalitySign = next;
+      token = ensureLiteralString(next);
+      next = token.next;
+    }
+    if (next != 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);
+      } else {
+        reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+        next = endGroup;
+      }
+    }
+    token = next;
+    assert(optional(')', token));
+
+    token = ensureLiteralString(token);
+    listener.endConditionalUri(ifKeyword, leftParen, equalitySign);
+    return token;
+  }
+
+  /// ```
+  /// dottedName:
+  ///   identifier ('.' identifier)*
+  /// ;
+  /// ```
+  Token parseDottedName(Token token) {
+    token = ensureIdentifier(token, IdentifierContext.dottedName);
+    Token firstIdentifier = token;
+    int count = 1;
+    while (optional('.', token.next)) {
+      token = ensureIdentifier(
+          token.next, IdentifierContext.dottedNameContinuation);
+      count++;
+    }
+    listener.handleDottedName(count, firstIdentifier);
+    return token;
+  }
+
+  /// ```
+  /// exportDirective:
+  ///   'export' uri conditional-uris* combinator* ';'
+  /// ;
+  /// ```
+  Token parseExport(Token exportKeyword) {
+    assert(optional('export', exportKeyword));
+    listener.beginExport(exportKeyword);
+    Token token = ensureLiteralString(exportKeyword);
+    token = parseConditionalUriStar(token);
+    token = parseCombinatorStar(token);
+    token = ensureSemicolon(token);
+    listener.endExport(exportKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// combinators:
+  ///   (hideCombinator | showCombinator)*
+  /// ;
+  /// ```
+  Token parseCombinatorStar(Token token) {
+    Token next = token.next;
+    listener.beginCombinators(next);
+    int count = 0;
+    while (true) {
+      String value = next.stringValue;
+      if (identical('hide', value)) {
+        token = parseHide(token);
+      } else if (identical('show', value)) {
+        token = parseShow(token);
+      } else {
+        listener.endCombinators(count);
+        break;
+      }
+      next = token.next;
+      count++;
+    }
+    return token;
+  }
+
+  /// ```
+  /// hideCombinator:
+  ///   'hide' identifierList
+  /// ;
+  /// ```
+  Token parseHide(Token token) {
+    Token hideKeyword = token.next;
+    assert(optional('hide', hideKeyword));
+    listener.beginHide(hideKeyword);
+    token = parseIdentifierList(hideKeyword);
+    listener.endHide(hideKeyword);
+    return token;
+  }
+
+  /// ```
+  /// showCombinator:
+  ///   'show' identifierList
+  /// ;
+  /// ```
+  Token parseShow(Token token) {
+    Token showKeyword = token.next;
+    assert(optional('show', showKeyword));
+    listener.beginShow(showKeyword);
+    token = parseIdentifierList(showKeyword);
+    listener.endShow(showKeyword);
+    return token;
+  }
+
+  /// ```
+  /// identifierList:
+  ///   identifier (',' identifier)*
+  /// ;
+  /// ```
+  Token parseIdentifierList(Token token) {
+    token = ensureIdentifier(token, IdentifierContext.combinator);
+    int count = 1;
+    while (optional(',', token.next)) {
+      token = ensureIdentifier(token.next, IdentifierContext.combinator);
+      count++;
+    }
+    listener.handleIdentifierList(count);
+    return token;
+  }
+
+  /// ```
+  /// typeList:
+  ///   type (',' type)*
+  /// ;
+  /// ```
+  Token parseTypeList(Token token) {
+    listener.beginTypeList(token.next);
+    token = computeType(token, true).ensureTypeOrVoid(token, this);
+    int count = 1;
+    while (optional(',', token.next)) {
+      token = computeType(token.next, true).ensureTypeOrVoid(token.next, this);
+      count++;
+    }
+    listener.endTypeList(count);
+    return token;
+  }
+
+  Token parsePartOrPartOf(Token partKeyword, DirectiveContext directiveState) {
+    assert(optional('part', partKeyword));
+    if (optional('of', partKeyword.next)) {
+      directiveState?.checkPartOf(this, partKeyword);
+      return parsePartOf(partKeyword);
+    } else {
+      directiveState?.checkPart(this, partKeyword);
+      return parsePart(partKeyword);
+    }
+  }
+
+  /// ```
+  /// partDirective:
+  ///   'part' uri ';'
+  /// ;
+  /// ```
+  Token parsePart(Token partKeyword) {
+    assert(optional('part', partKeyword));
+    listener.beginPart(partKeyword);
+    Token token = ensureLiteralString(partKeyword);
+    token = ensureSemicolon(token);
+    listener.endPart(partKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// partOfDirective:
+  ///   'part' 'of' (qualified | uri) ';'
+  /// ;
+  /// ```
+  Token parsePartOf(Token partKeyword) {
+    Token ofKeyword = partKeyword.next;
+    assert(optional('part', partKeyword));
+    assert(optional('of', ofKeyword));
+    listener.beginPartOf(partKeyword);
+    bool hasName = ofKeyword.next.isIdentifier;
+    Token token;
+    if (hasName) {
+      token = parseQualified(ofKeyword, IdentifierContext.partName,
+          IdentifierContext.partNameContinuation);
+    } else {
+      token = ensureLiteralString(ofKeyword);
+    }
+    token = ensureSemicolon(token);
+    listener.endPartOf(partKeyword, ofKeyword, token, hasName);
+    return token;
+  }
+
+  /// ```
+  /// metadata:
+  ///   annotation*
+  /// ;
+  /// ```
+  Token parseMetadataStar(Token token) {
+    listener.beginMetadataStar(token.next);
+    int count = 0;
+    while (optional('@', token.next)) {
+      token = parseMetadata(token);
+      count++;
+    }
+    listener.endMetadataStar(count);
+    return token;
+  }
+
+  /// ```
+  /// annotation:
+  ///   '@' qualified ('.' identifier)? arguments?
+  /// ;
+  /// ```
+  Token parseMetadata(Token token) {
+    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);
+    }
+    token = computeTypeParamOrArg(token).parseArguments(token, this);
+    Token period = null;
+    if (optional('.', token.next)) {
+      period = token.next;
+      token = ensureIdentifier(
+          period, IdentifierContext.metadataContinuationAfterTypeArguments);
+    }
+    token = parseArgumentsOpt(token);
+    listener.endMetadata(atToken, period, token.next);
+    return token;
+  }
+
+  /// ```
+  /// scriptTag:
+  ///   '#!' (˜NEWLINE)* NEWLINE
+  /// ;
+  /// ```
+  Token parseScript(Token token) {
+    token = token.next;
+    assert(identical(token.type, TokenType.SCRIPT_TAG));
+    listener.handleScript(token);
+    return token;
+  }
+
+  /// ```
+  /// typeAlias:
+  ///   metadata 'typedef' typeAliasBody |
+  ///   metadata 'typedef' identifier typeParameters? '=' functionType ';'
+  /// ;
+  ///
+  /// functionType:
+  ///   returnType? 'Function' typeParameters? parameterTypeList
+  ///
+  /// typeAliasBody:
+  ///   functionTypeAlias
+  /// ;
+  ///
+  /// functionTypeAlias:
+  ///   functionPrefix typeParameters? formalParameterList ‘;’
+  /// ;
+  ///
+  /// functionPrefix:
+  ///   returnType? identifier
+  /// ;
+  /// ```
+  Token parseTypedef(Token typedefKeyword) {
+    assert(optional('typedef', typedefKeyword));
+    listener.beginFunctionTypeAlias(typedefKeyword);
+    TypeInfo typeInfo = computeType(typedefKeyword, false);
+    Token token = typeInfo.skipType(typedefKeyword).next;
+    Token equals;
+    TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token, true);
+    if (typeInfo == noType &&
+        (token.kind == IDENTIFIER_TOKEN || token.type.isPseudo) &&
+        optional('=', typeParam.skip(token).next)) {
+      listener.handleIdentifier(token, IdentifierContext.typedefDeclaration);
+      token = typeParam.parseVariables(token, this).next;
+      // parseVariables rewrites so even though we checked in the if,
+      // we might not have an equal here now.
+      if (!optional('=', token) && optional('=', token.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.
+        token = token.next;
+      }
+      if (optional('=', token)) {
+        equals = token;
+        token = computeType(equals, true).ensureTypeOrVoid(equals, this);
+      } else {
+        // A rewrite caused the = to disappear
+        token = parseFormalParametersRequiredOpt(
+            token, MemberKind.FunctionTypeAlias);
+      }
+    } else {
+      token = typeInfo.parseType(typedefKeyword, this);
+      token = ensureIdentifier(token, IdentifierContext.typedefDeclaration);
+      token = typeParam.parseVariables(token, this);
+      token =
+          parseFormalParametersRequiredOpt(token, MemberKind.FunctionTypeAlias);
+    }
+    token = ensureSemicolon(token);
+    listener.endFunctionTypeAlias(typedefKeyword, equals, token);
+    return token;
+  }
+
+  /// Parse a mixin application starting from `with`. Assumes that the first
+  /// type has already been parsed.
+  Token parseMixinApplicationRest(Token token) {
+    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)) {
+        rewriter.insertSyntheticIdentifier(withKeyword);
+      }
+    }
+    token = parseTypeList(withKeyword);
+    listener.handleNamedMixinApplicationWithClause(withKeyword);
+    return token;
+  }
+
+  Token parseWithClauseOpt(Token token) {
+    Token withKeyword = token.next;
+    if (optional('with', withKeyword)) {
+      token = parseTypeList(withKeyword);
+      listener.handleClassWithClause(withKeyword);
+    } else {
+      listener.handleClassNoWithClause();
+    }
+    return token;
+  }
+
+  /// Parse the formal parameters of a getter (which shouldn't have parameters)
+  /// or function or method.
+  Token parseGetterOrFormalParameters(
+      Token token, Token name, bool isGetter, MemberKind kind) {
+    Token next = token.next;
+    if (optional("(", next)) {
+      if (isGetter) {
+        reportRecoverableError(next, codes.messageGetterWithFormals);
+      }
+      token = parseFormalParameters(token, kind);
+    } else if (isGetter) {
+      listener.handleNoFormalParameters(next, kind);
+    } else {
+      // Recovery
+      if (optional('operator', name)) {
+        Token next = name.next;
+        if (next.isOperator) {
+          name = next;
+        } else if (isUnaryMinus(next)) {
+          name = next.next;
+        }
+      }
+      reportRecoverableError(name, missingParameterMessage(kind));
+      token = rewriter.insertParens(token, false);
+      token = parseFormalParametersRest(token, kind);
+    }
+    return token;
+  }
+
+  Token parseFormalParametersOpt(Token token, MemberKind kind) {
+    Token next = token.next;
+    if (optional('(', next)) {
+      token = parseFormalParameters(token, kind);
+    } else {
+      listener.handleNoFormalParameters(next, kind);
+    }
+    return token;
+  }
+
+  Token skipFormalParameters(Token token, MemberKind 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;
+    assert(optional(')', closeBrace));
+    listener.endFormalParameters(0, token, closeBrace, kind);
+    return closeBrace;
+  }
+
+  /// Parses the formal parameter list of a function.
+  ///
+  /// 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;
+    if (!optional('(', next)) {
+      reportRecoverableError(next, missingParameterMessage(kind));
+      next = rewriter.insertParens(token, false);
+    }
+    return parseFormalParametersRest(next, kind);
+  }
+
+  /// Parses the formal parameter list of a function given that the left
+  /// parenthesis is known to exist.
+  ///
+  /// 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);
+  }
+
+  /// Parses the formal parameter list of a function given that the left
+  /// parenthesis passed in as [token].
+  ///
+  /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
+  /// omitted (except for named arguments). Otherwise, types may be omitted.
+  Token parseFormalParametersRest(Token token, MemberKind kind) {
+    Token begin = token;
+    assert(optional('(', token));
+    listener.beginFormalParameters(begin, kind);
+    int parameterCount = 0;
+    while (true) {
+      Token next = token.next;
+      if (optional(')', next)) {
+        token = next;
+        break;
+      }
+      ++parameterCount;
+      String value = next.stringValue;
+      if (identical(value, '[')) {
+        token = parseOptionalPositionalParameters(token, kind);
+        token = ensureCloseParen(token, begin);
+        break;
+      } else if (identical(value, '{')) {
+        token = parseOptionalNamedParameters(token, kind);
+        token = ensureCloseParen(token, begin);
+        break;
+      } else if (identical(value, '[]')) {
+        // Recovery
+        token = rewriteSquareBrackets(token);
+        token = parseOptionalPositionalParameters(token, kind);
+        token = ensureCloseParen(token, begin);
+        break;
+      }
+      token = parseFormalParameter(token, FormalParameterKind.mandatory, kind);
+      next = token.next;
+      if (!optional(',', next)) {
+        Token next = token.next;
+        if (optional(')', next)) {
+          token = next;
+        } else {
+          // Recovery
+          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);
+          } else if (next.kind == IDENTIFIER_TOKEN &&
+              next.next.kind == IDENTIFIER_TOKEN) {
+            // Looks like a missing comma
+            token = rewriteAndRecover(
+                token,
+                codes.templateExpectedButGot.withArguments(','),
+                new SyntheticToken(TokenType.COMMA, next.charOffset));
+            continue;
+          } else {
+            token = ensureCloseParen(token, begin);
+          }
+        }
+        break;
+      }
+      token = next;
+    }
+    assert(optional(')', token));
+    listener.endFormalParameters(parameterCount, begin, token, kind);
+    return token;
+  }
+
+  /// Return the message that should be produced when the formal parameters are
+  /// missing.
+  Message missingParameterMessage(MemberKind kind) {
+    if (kind == MemberKind.FunctionTypeAlias) {
+      return codes.messageMissingTypedefParameters;
+    } else if (kind == MemberKind.NonStaticMethod ||
+        kind == MemberKind.StaticMethod) {
+      return codes.messageMissingMethodParameters;
+    }
+    return codes.messageMissingFunctionParameters;
+  }
+
+  /// ```
+  /// normalFormalParameter:
+  ///   functionFormalParameter |
+  ///   fieldFormalParameter |
+  ///   simpleFormalParameter
+  /// ;
+  ///
+  /// functionFormalParameter:
+  ///   metadata 'covariant'? returnType? identifier formalParameterList
+  /// ;
+  ///
+  /// simpleFormalParameter:
+  ///   metadata 'covariant'? finalConstVarOrType? identifier |
+  /// ;
+  ///
+  /// fieldFormalParameter:
+  ///   metadata finalConstVarOrType? 'this' '.' identifier formalParameterList?
+  /// ;
+  /// ```
+  Token parseFormalParameter(
+      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
+    assert(parameterKind != null);
+    token = parseMetadataStar(token);
+    Token next = token.next;
+    Token start = next;
+
+    final bool inFunctionType =
+        memberKind == MemberKind.GeneralizedFunctionType;
+
+    Token requiredToken;
+    Token covariantToken;
+    Token varFinalOrConst;
+    if (isModifier(next)) {
+      if (optional('required', next)) {
+        if (parameterKind == FormalParameterKind.optionalNamed) {
+          requiredToken = token = next;
+          next = token.next;
+        }
+      }
+
+      if (isModifier(next)) {
+        if (optional('covariant', next)) {
+          if (memberKind != MemberKind.StaticMethod &&
+              memberKind != MemberKind.TopLevelMethod &&
+              memberKind != MemberKind.ExtensionNonStaticMethod &&
+              memberKind != MemberKind.ExtensionStaticMethod) {
+            covariantToken = token = next;
+            next = token.next;
+          }
+        }
+
+        if (isModifier(next)) {
+          if (!inFunctionType) {
+            if (optional('var', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            } else if (optional('final', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            }
+          }
+
+          if (isModifier(next)) {
+            // Recovery
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..covariantToken = covariantToken
+              ..requiredToken = requiredToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseFormalParameterModifiers(
+                token, parameterKind, memberKind);
+            next = token.next;
+
+            covariantToken = context.covariantToken;
+            requiredToken = context.requiredToken;
+            varFinalOrConst = context.varFinalOrConst;
+
+            context = null;
+          }
+        }
+      }
+    }
+
+    listener.beginFormalParameter(
+        start, memberKind, requiredToken, covariantToken, varFinalOrConst);
+
+    // Type is required in a generalized function type, but optional otherwise.
+    final Token beforeType = token;
+    TypeInfo typeInfo = computeType(token, inFunctionType);
+    token = typeInfo.skipType(token);
+    next = token.next;
+    if (typeInfo == noType &&
+        (optional('.', next) ||
+            (next.isIdentifier && optional('.', next.next)))) {
+      // Recovery: Malformed type reference.
+      typeInfo = computeType(beforeType, true);
+      token = typeInfo.skipType(beforeType);
+      next = token.next;
+    }
+
+    final bool isNamedParameter =
+        parameterKind == FormalParameterKind.optionalNamed;
+
+    Token thisKeyword;
+    Token periodAfterThis;
+    IdentifierContext nameContext =
+        IdentifierContext.formalParameterDeclaration;
+
+    if (!inFunctionType && optional('this', next)) {
+      thisKeyword = token = next;
+      next = token.next;
+      if (!optional('.', next)) {
+        // Recover from a missing period by inserting one.
+        next = rewriteAndRecover(
+            token,
+            codes.templateExpectedButGot.withArguments('.'),
+            new SyntheticToken(TokenType.PERIOD, next.charOffset));
+      }
+      periodAfterThis = token = next;
+      next = token.next;
+      nameContext = IdentifierContext.fieldInitializer;
+    }
+
+    if (next.isIdentifier) {
+      token = next;
+      next = token.next;
+    }
+    Token beforeInlineFunctionType;
+    TypeParamOrArgInfo typeParam = noTypeParamOrArg;
+    if (optional("<", next)) {
+      typeParam = computeTypeParamOrArg(token);
+      if (typeParam != noTypeParamOrArg) {
+        Token closer = typeParam.skip(token);
+        if (optional("(", closer.next)) {
+          if (varFinalOrConst != null) {
+            reportRecoverableError(
+                varFinalOrConst, codes.messageFunctionTypedParameterVar);
+          }
+          beforeInlineFunctionType = token;
+          token = closer.next.endGroup;
+          next = token.next;
+        }
+      }
+    } else if (optional("(", next)) {
+      if (varFinalOrConst != null) {
+        reportRecoverableError(
+            varFinalOrConst, codes.messageFunctionTypedParameterVar);
+      }
+      beforeInlineFunctionType = token;
+      token = next.endGroup;
+      next = token.next;
+    }
+    if (typeInfo != noType &&
+        varFinalOrConst != null &&
+        optional('var', varFinalOrConst)) {
+      reportRecoverableError(varFinalOrConst, codes.messageTypeAfterVar);
+    }
+
+    Token endInlineFunctionType;
+    if (beforeInlineFunctionType != null) {
+      endInlineFunctionType =
+          typeParam.parseVariables(beforeInlineFunctionType, this);
+      listener.beginFunctionTypedFormalParameter(beforeInlineFunctionType.next);
+      token = typeInfo.parseType(beforeType, this);
+      endInlineFunctionType = parseFormalParametersRequiredOpt(
+          endInlineFunctionType, MemberKind.FunctionTypedParameter);
+      Token question;
+      if (optional('?', endInlineFunctionType.next)) {
+        question = endInlineFunctionType = endInlineFunctionType.next;
+      }
+      listener.endFunctionTypedFormalParameter(
+          beforeInlineFunctionType, question);
+
+      // Generalized function types don't allow inline function types.
+      // The following isn't allowed:
+      //    int Function(int bar(String x)).
+      if (inFunctionType) {
+        reportRecoverableError(beforeInlineFunctionType.next,
+            codes.messageInvalidInlineFunctionType);
+      }
+    } else if (inFunctionType) {
+      token = typeInfo.ensureTypeOrVoid(beforeType, this);
+    } else {
+      token = typeInfo.parseType(beforeType, this);
+    }
+
+    Token nameToken;
+    if (periodAfterThis != null) {
+      token = periodAfterThis;
+    }
+    next = token.next;
+    if (inFunctionType &&
+        !isNamedParameter &&
+        !next.isKeywordOrIdentifier &&
+        beforeInlineFunctionType == null) {
+      nameToken = token.next;
+      listener.handleNoName(nameToken);
+    } else {
+      nameToken = token = ensureIdentifier(token, nameContext);
+      if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
+        reportRecoverableError(nameToken, codes.messagePrivateNamedParameter);
+      }
+    }
+    if (endInlineFunctionType != null) {
+      token = endInlineFunctionType;
+    }
+    next = token.next;
+
+    String value = next.stringValue;
+    Token initializerStart, initializerEnd;
+    if ((identical('=', value)) || (identical(':', value))) {
+      Token equal = next;
+      initializerStart = equal.next;
+      listener.beginFormalParameterDefaultValueExpression();
+      token = initializerEnd = parseExpression(equal);
+      next = token.next;
+      listener.endFormalParameterDefaultValueExpression();
+      // TODO(danrubel): Consider removing the last parameter from the
+      // handleValuedFormalParameter event... it appears to be unused.
+      listener.handleValuedFormalParameter(equal, next);
+      if (isMandatoryFormalParameterKind(parameterKind)) {
+        reportRecoverableError(
+            equal, codes.messageRequiredParameterWithDefault);
+      } else if (isOptionalPositionalFormalParameterKind(parameterKind) &&
+          identical(':', value)) {
+        reportRecoverableError(
+            equal, codes.messagePositionalParameterWithEquals);
+      } else if (inFunctionType ||
+          memberKind == MemberKind.FunctionTypeAlias ||
+          memberKind == MemberKind.FunctionTypedParameter) {
+        reportRecoverableError(equal, codes.messageFunctionTypeDefaultValue);
+      }
+    } else {
+      listener.handleFormalParameterWithoutValue(next);
+    }
+    listener.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
+        initializerStart, initializerEnd, parameterKind, memberKind);
+    return token;
+  }
+
+  /// ```
+  /// defaultFormalParameter:
+  ///   normalFormalParameter ('=' expression)?
+  /// ;
+  /// ```
+  Token parseOptionalPositionalParameters(Token token, MemberKind kind) {
+    Token begin = token = token.next;
+    assert(optional('[', token));
+    listener.beginOptionalFormalParameters(begin);
+    int parameterCount = 0;
+    while (true) {
+      Token next = token.next;
+      if (optional(']', next)) {
+        break;
+      }
+      token = parseFormalParameter(
+          token, FormalParameterKind.optionalPositional, kind);
+      next = token.next;
+      ++parameterCount;
+      if (!optional(',', next)) {
+        if (!optional(']', next)) {
+          // Recovery
+          reportRecoverableError(
+              next, codes.templateExpectedButGot.withArguments(']'));
+          // Scanner guarantees a closing bracket.
+          next = begin.endGroup;
+          while (token.next != next) {
+            token = token.next;
+          }
+        }
+        break;
+      }
+      token = next;
+    }
+    if (parameterCount == 0) {
+      rewriteAndRecover(
+          token,
+          codes.messageEmptyOptionalParameterList,
+          new SyntheticStringToken(
+              TokenType.IDENTIFIER, '', token.next.charOffset, 0));
+      token = parseFormalParameter(
+          token, FormalParameterKind.optionalPositional, kind);
+      ++parameterCount;
+    }
+    token = token.next;
+    assert(optional(']', token));
+    listener.endOptionalFormalParameters(parameterCount, begin, token);
+    return token;
+  }
+
+  /// ```
+  /// defaultNamedParameter:
+  ///   normalFormalParameter ('=' expression)? |
+  ///   normalFormalParameter (':' expression)?
+  /// ;
+  /// ```
+  Token parseOptionalNamedParameters(Token token, MemberKind kind) {
+    Token begin = token = token.next;
+    assert(optional('{', token));
+    listener.beginOptionalFormalParameters(begin);
+    int parameterCount = 0;
+    while (true) {
+      Token next = token.next;
+      if (optional('}', next)) {
+        break;
+      }
+      token =
+          parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
+      next = token.next;
+      ++parameterCount;
+      if (!optional(',', next)) {
+        if (!optional('}', next)) {
+          // Recovery
+          reportRecoverableError(
+              next, codes.templateExpectedButGot.withArguments('}'));
+          // Scanner guarantees a closing bracket.
+          next = begin.endGroup;
+          while (token.next != next) {
+            token = token.next;
+          }
+        }
+        break;
+      }
+      token = next;
+    }
+    if (parameterCount == 0) {
+      rewriteAndRecover(
+          token,
+          codes.messageEmptyNamedParameterList,
+          new SyntheticStringToken(
+              TokenType.IDENTIFIER, '', token.next.charOffset, 0));
+      token =
+          parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
+      ++parameterCount;
+    }
+    token = token.next;
+    assert(optional('}', token));
+    listener.endOptionalFormalParameters(parameterCount, begin, token);
+    return token;
+  }
+
+  /// ```
+  /// qualified:
+  ///   identifier qualifiedRest*
+  /// ;
+  /// ```
+  Token parseQualified(Token token, IdentifierContext context,
+      IdentifierContext continuationContext) {
+    token = ensureIdentifier(token, context);
+    while (optional('.', token.next)) {
+      token = parseQualifiedRest(token, continuationContext);
+    }
+    return token;
+  }
+
+  /// ```
+  /// qualifiedRestOpt:
+  ///   qualifiedRest?
+  /// ;
+  /// ```
+  Token parseQualifiedRestOpt(
+      Token token, IdentifierContext continuationContext) {
+    if (optional('.', token.next)) {
+      return parseQualifiedRest(token, continuationContext);
+    } else {
+      return token;
+    }
+  }
+
+  /// ```
+  /// qualifiedRest:
+  ///   '.' identifier
+  /// ;
+  /// ```
+  Token parseQualifiedRest(Token token, IdentifierContext context) {
+    token = token.next;
+    assert(optional('.', token));
+    Token period = token;
+    token = ensureIdentifier(token, context);
+    listener.handleQualified(period);
+    return token;
+  }
+
+  Token skipBlock(Token token) {
+    // The scanner ensures that `{` always has a closing `}`.
+    return ensureBlock(token, null, null).endGroup;
+  }
+
+  /// ```
+  /// enumType:
+  ///   metadata 'enum' id '{' metadata id [',' metadata id]* [','] '}'
+  /// ;
+  /// ```
+  Token parseEnum(Token enumKeyword) {
+    assert(optional('enum', enumKeyword));
+    listener.beginEnum(enumKeyword);
+    Token token =
+        ensureIdentifier(enumKeyword, IdentifierContext.enumDeclaration);
+    Token leftBrace = token.next;
+    int count = 0;
+    if (optional('{', leftBrace)) {
+      token = leftBrace;
+      while (true) {
+        Token next = token.next;
+        if (optional('}', next)) {
+          token = next;
+          if (count == 0) {
+            reportRecoverableError(token, codes.messageEnumDeclarationEmpty);
+          }
+          break;
+        }
+        token = parseMetadataStar(token);
+        token = ensureIdentifier(token, IdentifierContext.enumValueDeclaration);
+        next = token.next;
+        count++;
+        if (optional(',', next)) {
+          token = next;
+        } else if (optional('}', next)) {
+          token = next;
+          break;
+        } else {
+          // Recovery
+          Token endGroup = leftBrace.endGroup;
+          if (endGroup.isSynthetic) {
+            // The scanner did not place the synthetic '}' correctly.
+            token = rewriter.moveSynthetic(token, endGroup);
+            break;
+          } else if (next.isIdentifier) {
+            // If the next token is an identifier, assume a missing comma.
+            // TODO(danrubel): Consider improved recovery for missing `}`
+            // both here and when the scanner inserts a synthetic `}`
+            // for situations such as `enum Letter {a, b   Letter e;`.
+            reportRecoverableError(
+                next, codes.templateExpectedButGot.withArguments(','));
+          } else {
+            // Otherwise assume a missing `}` and exit the loop
+            reportRecoverableError(
+                next, codes.templateExpectedButGot.withArguments('}'));
+            token = leftBrace.endGroup;
+            break;
+          }
+        }
+      }
+    } else {
+      // TODO(danrubel): merge this error message with missing class/mixin body
+      leftBrace = ensureBlock(token, codes.templateExpectedEnumBody, null);
+      token = leftBrace.endGroup;
+    }
+    assert(optional('}', token));
+    listener.endEnum(enumKeyword, leftBrace, count);
+    return token;
+  }
+
+  Token parseClassOrNamedMixinApplication(
+      Token abstractToken, Token classKeyword) {
+    assert(optional('class', classKeyword));
+    Token begin = abstractToken ?? classKeyword;
+    listener.beginClassOrNamedMixinApplicationPrelude(begin);
+    Token name = ensureIdentifier(
+        classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
+    Token token =
+        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
+    if (optional('=', token.next)) {
+      listener.beginNamedMixinApplication(begin, abstractToken, name);
+      return parseNamedMixinApplication(token, begin, classKeyword);
+    } else {
+      listener.beginClassDeclaration(begin, abstractToken, name);
+      return parseClass(token, begin, classKeyword, name.lexeme);
+    }
+  }
+
+  Token parseNamedMixinApplication(
+      Token token, Token begin, Token classKeyword) {
+    Token equals = token = token.next;
+    assert(optional('=', equals));
+    token = computeType(token, true).ensureTypeNotVoid(token, this);
+    token = parseMixinApplicationRest(token);
+    Token implementsKeyword = null;
+    if (optional('implements', token.next)) {
+      implementsKeyword = token.next;
+      token = parseTypeList(implementsKeyword);
+    }
+    token = ensureSemicolon(token);
+    listener.endNamedMixinApplication(
+        begin, classKeyword, equals, implementsKeyword, token);
+    return token;
+  }
+
+  /// Parse the portion of a class declaration (not a mixin application) that
+  /// follows the end of the type parameters.
+  ///
+  /// ```
+  /// classDefinition:
+  ///   metadata abstract? 'class' identifier typeParameters?
+  ///       (superclass mixins?)? interfaces?
+  ///       '{' (metadata classMemberDefinition)* '}' |
+  ///   metadata abstract? 'class' mixinApplicationClass
+  /// ;
+  /// ```
+  Token parseClass(
+      Token token, Token begin, Token classKeyword, String className) {
+    Token start = token;
+    token = parseClassHeaderOpt(token, begin, classKeyword);
+    if (!optional('{', token.next)) {
+      // Recovery
+      token = parseClassHeaderRecovery(start, begin, classKeyword);
+      ensureBlock(token, null, 'class declaration');
+    }
+    token = parseClassOrMixinOrExtensionBody(
+        token, DeclarationKind.Class, className);
+    listener.endClassDeclaration(begin, token);
+    return token;
+  }
+
+  Token parseClassHeaderOpt(Token token, Token begin, Token classKeyword) {
+    token = parseClassExtendsOpt(token);
+    token = parseWithClauseOpt(token);
+    token = parseClassOrMixinImplementsOpt(token);
+    Token nativeToken;
+    if (optional('native', token.next)) {
+      nativeToken = token.next;
+      token = parseNativeClause(token);
+    }
+    listener.handleClassHeader(begin, classKeyword, nativeToken);
+    return token;
+  }
+
+  /// Recover given out-of-order clauses in a class header.
+  Token parseClassHeaderRecovery(Token token, Token begin, Token classKeyword) {
+    final Listener primaryListener = listener;
+    final ClassHeaderRecoveryListener recoveryListener =
+        new ClassHeaderRecoveryListener();
+
+    // Reparse to determine which clauses have already been parsed
+    // but intercept the events so they are not sent to the primary listener.
+    listener = recoveryListener;
+    token = parseClassHeaderOpt(token, begin, classKeyword);
+    bool hasExtends = recoveryListener.extendsKeyword != null;
+    bool hasImplements = recoveryListener.implementsKeyword != null;
+    bool hasWith = recoveryListener.withKeyword != null;
+
+    // Update the recovery listener to forward subsequent events
+    // to the primary listener.
+    recoveryListener.listener = primaryListener;
+
+    // Parse additional out-of-order clauses
+    Token start;
+    do {
+      start = token;
+
+      // Check for extraneous token in the middle of a class header.
+      token = skipUnexpectedTokenOpt(
+          token, const <String>['extends', 'with', 'implements', '{']);
+
+      // During recovery, clauses are parsed in the same order
+      // 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 incorrectExtendsKeyword = token.next;
+        token = computeType(incorrectExtendsKeyword, true)
+            .ensureTypeNotVoid(incorrectExtendsKeyword, this);
+        listener.handleClassExtends(incorrectExtendsKeyword);
+      } else {
+        token = parseClassExtendsOpt(token);
+      }
+
+      if (recoveryListener.extendsKeyword != null) {
+        if (hasExtends) {
+          reportRecoverableError(
+              recoveryListener.extendsKeyword, codes.messageMultipleExtends);
+        } else {
+          if (hasWith) {
+            reportRecoverableError(recoveryListener.extendsKeyword,
+                codes.messageWithBeforeExtends);
+          } else if (hasImplements) {
+            reportRecoverableError(recoveryListener.extendsKeyword,
+                codes.messageImplementsBeforeExtends);
+          }
+          hasExtends = true;
+        }
+      }
+
+      token = parseWithClauseOpt(token);
+
+      if (recoveryListener.withKeyword != null) {
+        if (hasWith) {
+          reportRecoverableError(
+              recoveryListener.withKeyword, codes.messageMultipleWith);
+        } else {
+          if (hasImplements) {
+            reportRecoverableError(recoveryListener.withKeyword,
+                codes.messageImplementsBeforeWith);
+          }
+          hasWith = true;
+        }
+      }
+
+      token = parseClassOrMixinImplementsOpt(token);
+
+      if (recoveryListener.implementsKeyword != null) {
+        if (hasImplements) {
+          reportRecoverableError(recoveryListener.implementsKeyword,
+              codes.messageMultipleImplements);
+        } else {
+          hasImplements = true;
+        }
+      }
+
+      listener.handleRecoverClassHeader();
+
+      // Exit if a class body is detected, or if no progress has been made
+    } while (!optional('{', token.next) && start != token);
+
+    listener = primaryListener;
+    return token;
+  }
+
+  Token parseClassExtendsOpt(Token token) {
+    Token next = token.next;
+    if (optional('extends', next)) {
+      Token extendsKeyword = next;
+      token = computeType(next, true).ensureTypeNotVoid(next, this);
+      listener.handleClassExtends(extendsKeyword);
+    } else {
+      listener.handleNoType(token);
+      listener.handleClassExtends(null);
+    }
+    return token;
+  }
+
+  /// ```
+  /// implementsClause:
+  ///   'implements' typeName (',' typeName)*
+  /// ;
+  /// ```
+  Token parseClassOrMixinImplementsOpt(Token token) {
+    Token implementsKeyword;
+    int interfacesCount = 0;
+    if (optional('implements', token.next)) {
+      implementsKeyword = token.next;
+      do {
+        token =
+            computeType(token.next, true).ensureTypeNotVoid(token.next, this);
+        ++interfacesCount;
+      } while (optional(',', token.next));
+    }
+    listener.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
+    return token;
+  }
+
+  /// Parse a mixin declaration.
+  ///
+  /// ```
+  /// mixinDeclaration:
+  ///   metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
+  ///        [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
+  /// ;
+  /// ```
+  Token parseMixin(Token mixinKeyword) {
+    assert(optional('mixin', mixinKeyword));
+    listener.beginClassOrNamedMixinApplicationPrelude(mixinKeyword);
+    Token name = ensureIdentifier(
+        mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
+    Token headerStart =
+        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
+    listener.beginMixinDeclaration(mixinKeyword, name);
+    Token token = parseMixinHeaderOpt(headerStart, mixinKeyword);
+    if (!optional('{', token.next)) {
+      // Recovery
+      token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
+      ensureBlock(token, null, 'mixin declaration');
+    }
+    token = parseClassOrMixinOrExtensionBody(
+        token, DeclarationKind.Mixin, name.lexeme);
+    listener.endMixinDeclaration(mixinKeyword, token);
+    return token;
+  }
+
+  Token parseMixinHeaderOpt(Token token, Token mixinKeyword) {
+    token = parseMixinOnOpt(token);
+    token = parseClassOrMixinImplementsOpt(token);
+    listener.handleMixinHeader(mixinKeyword);
+    return token;
+  }
+
+  Token parseMixinHeaderRecovery(
+      Token token, Token mixinKeyword, Token headerStart) {
+    final Listener primaryListener = listener;
+    final MixinHeaderRecoveryListener recoveryListener =
+        new MixinHeaderRecoveryListener();
+
+    // Reparse to determine which clauses have already been parsed
+    // but intercept the events so they are not sent to the primary listener.
+    listener = recoveryListener;
+    token = parseMixinHeaderOpt(headerStart, mixinKeyword);
+    bool hasOn = recoveryListener.onKeyword != null;
+    bool hasImplements = recoveryListener.implementsKeyword != null;
+
+    // Update the recovery listener to forward subsequent events
+    // to the primary listener.
+    recoveryListener.listener = primaryListener;
+
+    // Parse additional out-of-order clauses
+    Token start;
+    do {
+      start = token;
+
+      // Check for extraneous token in the middle of a class header.
+      token = skipUnexpectedTokenOpt(
+          token, const <String>['on', 'implements', '{']);
+
+      // During recovery, clauses are parsed in the same order and
+      // generate the same events as in the parseMixinHeaderOpt method above.
+      recoveryListener.clear();
+
+      if (token.next.isKeywordOrIdentifier &&
+          const ['extend', 'extends'].contains(token.next.lexeme)) {
+        reportRecoverableError(
+            token.next, codes.templateExpectedInstead.withArguments('on'));
+        token = parseMixinOn(token);
+      } else {
+        token = parseMixinOnOpt(token);
+      }
+
+      if (recoveryListener.onKeyword != null) {
+        if (hasOn) {
+          reportRecoverableError(
+              recoveryListener.onKeyword, codes.messageMultipleOnClauses);
+        } else {
+          if (hasImplements) {
+            reportRecoverableError(
+                recoveryListener.onKeyword, codes.messageImplementsBeforeOn);
+          }
+          hasOn = true;
+        }
+      }
+
+      token = parseClassOrMixinImplementsOpt(token);
+
+      if (recoveryListener.implementsKeyword != null) {
+        if (hasImplements) {
+          reportRecoverableError(recoveryListener.implementsKeyword,
+              codes.messageMultipleImplements);
+        } else {
+          hasImplements = true;
+        }
+      }
+
+      listener.handleRecoverMixinHeader();
+
+      // Exit if a mixin body is detected, or if no progress has been made
+    } while (!optional('{', token.next) && start != token);
+
+    listener = primaryListener;
+    return token;
+  }
+
+  /// ```
+  /// onClause:
+  ///   'on' typeName (',' typeName)*
+  /// ;
+  /// ```
+  Token parseMixinOnOpt(Token token) {
+    if (!optional('on', token.next)) {
+      listener.handleMixinOn(null, 0);
+      return token;
+    }
+    return parseMixinOn(token);
+  }
+
+  Token parseMixinOn(Token token) {
+    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, true).ensureTypeNotVoid(token.next, this);
+      ++typeCount;
+    } while (optional(',', token.next));
+    listener.handleMixinOn(onKeyword, typeCount);
+    return token;
+  }
+
+  /// ```
+  /// 'extension' <identifier>? <typeParameters>? 'on' <type> '?'?
+  //   `{'
+  //     <memberDeclaration>*
+  //   `}'
+  /// ```
+  Token parseExtension(Token extensionKeyword) {
+    assert(optional('extension', extensionKeyword));
+    Token token = extensionKeyword;
+    listener.beginExtensionDeclarationPrelude(extensionKeyword);
+    Token name = token.next;
+    if (name.isIdentifier && !optional('on', name)) {
+      token = name;
+      if (name.type.isBuiltIn) {
+        reportRecoverableErrorWithToken(
+            token, codes.templateBuiltInIdentifierInDeclaration);
+      }
+    } else {
+      name = null;
+    }
+    token = computeTypeParamOrArg(token, true).parseVariables(token, this);
+    listener.beginExtensionDeclaration(extensionKeyword, name);
+    Token onKeyword = token.next;
+    if (!optional('on', onKeyword)) {
+      // Recovery
+      if (optional('extends', onKeyword) ||
+          optional('implements', onKeyword) ||
+          optional('with', onKeyword)) {
+        reportRecoverableError(
+            onKeyword, codes.templateExpectedInstead.withArguments('on'));
+      } else {
+        reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments('on'));
+        onKeyword = rewriter.insertSyntheticKeyword(token, Keyword.ON);
+      }
+    }
+    TypeInfo typeInfo = computeType(onKeyword, true);
+    token = typeInfo.ensureTypeOrVoid(onKeyword, this);
+    if (!optional('{', token.next)) {
+      // Recovery
+      Token next = token.next;
+      while (!next.isEof) {
+        if (optional(',', next) ||
+            optional('extends', next) ||
+            optional('implements', next) ||
+            optional('on', next) ||
+            optional('with', next)) {
+          // Report an error and skip `,` or specific keyword
+          // optionally followed by an identifier
+          reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+          token = next;
+          next = token.next;
+          if (next.isIdentifier) {
+            token = next;
+            next = token.next;
+          }
+        } else {
+          break;
+        }
+      }
+      ensureBlock(token, null, 'extension declaration');
+    }
+    token = parseClassOrMixinOrExtensionBody(
+        token, DeclarationKind.Extension, name?.lexeme);
+    listener.endExtensionDeclaration(extensionKeyword, onKeyword, token);
+    return token;
+  }
+
+  Token parseStringPart(Token token) {
+    Token next = token.next;
+    if (next.kind != STRING_TOKEN) {
+      reportRecoverableErrorWithToken(next, codes.templateExpectedString);
+      next = rewriter.insertToken(token,
+          new SyntheticStringToken(TokenType.STRING, '', next.charOffset));
+    }
+    listener.handleStringPart(next);
+    return next;
+  }
+
+  /// Insert a synthetic identifier after the given [token] and create an error
+  /// message based on the given [context]. Return the synthetic identifier that
+  /// was inserted.
+  Token insertSyntheticIdentifier(Token token, IdentifierContext context,
+      {Message message, Token messageOnToken}) {
+    Token next = token.next;
+    reportRecoverableError(messageOnToken ?? next,
+        message ?? context.recoveryTemplate.withArguments(next));
+    return rewriter.insertSyntheticIdentifier(token);
+  }
+
+  /// Parse a simple identifier at the given [token], and return the identifier
+  /// that was parsed.
+  ///
+  /// If the token is not an identifier, or is not appropriate for use as an
+  /// identifier in the given [context], create a synthetic identifier, report
+  /// an error, and return the synthetic identifier.
+  Token ensureIdentifier(Token token, IdentifierContext context) {
+    assert(context != null);
+    Token identifier = token.next;
+    if (identifier.kind != IDENTIFIER_TOKEN) {
+      identifier = context.ensureIdentifier(token, this);
+      assert(identifier != null);
+      assert(identifier.isKeywordOrIdentifier);
+    }
+    listener.handleIdentifier(identifier, context);
+    return identifier;
+  }
+
+  bool notEofOrValue(String value, Token token) {
+    return !identical(token.kind, EOF_TOKEN) &&
+        !identical(value, token.stringValue);
+  }
+
+  Token parseTypeVariablesOpt(Token token) {
+    return computeTypeParamOrArg(token, true).parseVariables(token, this);
+  }
+
+  /// Parse a top level field or function.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseTopLevelMember(Token token) {
+    token = parseMetadataStar(syntheticPreviousToken(token));
+    return parseTopLevelMemberImpl(token).next;
+  }
+
+  Token parseTopLevelMemberImpl(Token token) {
+    Token beforeStart = token;
+    Token next = token.next;
+    listener.beginTopLevelMember(next);
+
+    Token externalToken;
+    Token lateToken;
+    Token varFinalOrConst;
+
+    if (isModifier(next)) {
+      if (optional('external', next)) {
+        externalToken = token = next;
+        next = token.next;
+      }
+      if (isModifier(next)) {
+        if (optional('final', next)) {
+          varFinalOrConst = token = next;
+          next = token.next;
+        } else if (optional('var', next)) {
+          varFinalOrConst = token = next;
+          next = token.next;
+        } else if (optional('const', next)) {
+          varFinalOrConst = token = next;
+          next = token.next;
+        } else if (optional('late', next)) {
+          lateToken = token = next;
+          next = token.next;
+          if (isModifier(next) && optional('final', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          }
+        }
+        if (isModifier(next)) {
+          // Recovery
+          if (varFinalOrConst != null &&
+              (optional('final', next) ||
+                  optional('var', next) ||
+                  optional('const', next))) {
+            // If another `var`, `final`, or `const` then fall through
+            // to parse that as part of the next top level declaration.
+          } else {
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..externalToken = externalToken
+              ..lateToken = lateToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseTopLevelModifiers(token);
+            next = token.next;
+
+            externalToken = context.externalToken;
+            lateToken = context.lateToken;
+            varFinalOrConst = context.varFinalOrConst;
+
+            context = null;
+          }
+        }
+      }
+    }
+
+    Token beforeType = token;
+    TypeInfo typeInfo = computeType(token, false, true);
+    token = typeInfo.skipType(token);
+    next = token.next;
+
+    Token getOrSet;
+    String value = next.stringValue;
+    if (identical(value, 'get') || identical(value, 'set')) {
+      if (next.next.isIdentifier) {
+        getOrSet = token = next;
+        next = token.next;
+      }
+    }
+
+    if (next.type != TokenType.IDENTIFIER) {
+      value = next.stringValue;
+      if (identical(value, 'factory') || identical(value, 'operator')) {
+        // `factory` and `operator` can be used as an identifier.
+        value = next.next.stringValue;
+        if (getOrSet == null &&
+            !identical(value, '(') &&
+            !identical(value, '{') &&
+            !identical(value, '<') &&
+            !identical(value, '=>') &&
+            !identical(value, '=') &&
+            !identical(value, ';') &&
+            !identical(value, ',')) {
+          // Recovery
+          value = next.stringValue;
+          if (identical(value, 'factory')) {
+            reportRecoverableError(
+                next, codes.messageFactoryTopLevelDeclaration);
+          } else {
+            reportRecoverableError(next, codes.messageTopLevelOperator);
+            if (next.next.isOperator) {
+              token = next;
+              next = token.next;
+              if (optional('(', next.next)) {
+                rewriter.insertSyntheticIdentifier(
+                    next, '#synthetic_identifier_${next.charOffset}');
+              }
+            }
+          }
+          listener.handleInvalidTopLevelDeclaration(next);
+          return next;
+        }
+        // Fall through and continue parsing
+      } else if (!next.isIdentifier) {
+        // Recovery
+        if (next.isKeyword) {
+          // Fall through to parse the keyword as the identifier.
+          // ensureIdentifier will report the error.
+        } else if (token == beforeStart) {
+          // Ensure we make progress.
+          return parseInvalidTopLevelDeclaration(token);
+        } else {
+          // Looks like a declaration missing an identifier.
+          // Insert synthetic identifier and fall through.
+          insertSyntheticIdentifier(token, IdentifierContext.methodDeclaration);
+          next = token.next;
+        }
+      }
+    }
+    // At this point, `token` is beforeName.
+
+    next = next.next;
+    value = next.stringValue;
+    if (getOrSet != null ||
+        identical(value, '(') ||
+        identical(value, '{') ||
+        identical(value, '<') ||
+        identical(value, '.') ||
+        identical(value, '=>')) {
+      if (varFinalOrConst != null) {
+        if (optional('var', varFinalOrConst)) {
+          reportRecoverableError(varFinalOrConst, codes.messageVarReturnType);
+        } else {
+          reportRecoverableErrorWithToken(
+              varFinalOrConst, codes.templateExtraneousModifier);
+        }
+      } else if (lateToken != null) {
+        reportRecoverableErrorWithToken(
+            lateToken, codes.templateExtraneousModifier);
+      }
+      return parseTopLevelMethod(beforeStart, externalToken, beforeType,
+          typeInfo, getOrSet, token.next);
+    }
+
+    if (getOrSet != null) {
+      reportRecoverableErrorWithToken(
+          getOrSet, codes.templateExtraneousModifier);
+    }
+    return parseFields(
+        beforeStart,
+        externalToken,
+        null,
+        null,
+        lateToken,
+        varFinalOrConst,
+        beforeType,
+        typeInfo,
+        token.next,
+        DeclarationKind.TopLevel);
+  }
+
+  Token parseFields(
+      Token beforeStart,
+      Token externalToken,
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      Token beforeType,
+      TypeInfo typeInfo,
+      Token name,
+      DeclarationKind kind) {
+    if (externalToken != null) {
+      reportRecoverableError(externalToken, codes.messageExternalField);
+    }
+    if (covariantToken != null) {
+      if (varFinalOrConst != null && optional('final', varFinalOrConst)) {
+        reportRecoverableError(covariantToken, codes.messageFinalAndCovariant);
+        covariantToken = null;
+      }
+    }
+    if (typeInfo == noType) {
+      if (varFinalOrConst == null && lateToken == null) {
+        reportRecoverableError(name, codes.messageMissingConstFinalVarOrType);
+      }
+    } else {
+      if (varFinalOrConst != null && optional('var', varFinalOrConst)) {
+        reportRecoverableError(varFinalOrConst, codes.messageTypeAfterVar);
+      }
+    }
+
+    Token token = typeInfo.parseType(beforeType, this);
+    assert(token.next == name);
+
+    IdentifierContext context = kind == DeclarationKind.TopLevel
+        ? IdentifierContext.topLevelVariableDeclaration
+        : IdentifierContext.fieldDeclaration;
+    Token firstName = name = ensureIdentifier(token, context);
+
+    int fieldCount = 1;
+    token =
+        parseFieldInitializerOpt(name, name, lateToken, varFinalOrConst, kind);
+    while (optional(',', token.next)) {
+      name = ensureIdentifier(token.next, context);
+      token = parseFieldInitializerOpt(
+          name, name, lateToken, varFinalOrConst, kind);
+      ++fieldCount;
+    }
+    Token semicolon = token.next;
+    if (optional(';', semicolon)) {
+      token = semicolon;
+    } else {
+      // Recovery
+      if (kind == DeclarationKind.TopLevel &&
+          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,
+            codes.templateExperimentNotEnabled
+                .withArguments('extension-methods'));
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+      } else {
+        token = ensureSemicolon(token);
+      }
+    }
+    switch (kind) {
+      case DeclarationKind.TopLevel:
+        listener.endTopLevelFields(staticToken, covariantToken, lateToken,
+            varFinalOrConst, fieldCount, beforeStart.next, token);
+        break;
+      case DeclarationKind.Class:
+        listener.endClassFields(staticToken, covariantToken, lateToken,
+            varFinalOrConst, fieldCount, beforeStart.next, token);
+        break;
+      case DeclarationKind.Mixin:
+        listener.endMixinFields(staticToken, covariantToken, lateToken,
+            varFinalOrConst, fieldCount, beforeStart.next, token);
+        break;
+      case DeclarationKind.Extension:
+        if (staticToken == null) {
+          reportRecoverableError(
+              firstName, codes.messageExtensionDeclaresInstanceField);
+        }
+        listener.endExtensionFields(staticToken, covariantToken, lateToken,
+            varFinalOrConst, fieldCount, beforeStart.next, token);
+        break;
+    }
+    return token;
+  }
+
+  Token parseTopLevelMethod(Token beforeStart, Token externalToken,
+      Token beforeType, TypeInfo typeInfo, Token getOrSet, Token name) {
+    listener.beginTopLevelMethod(beforeStart, externalToken);
+
+    Token token = typeInfo.parseType(beforeType, this);
+    assert(token.next == (getOrSet ?? name) || token.next.isEof);
+    name = ensureIdentifier(
+        getOrSet ?? token, IdentifierContext.topLevelFunctionDeclaration);
+
+    bool isGetter = false;
+    if (getOrSet == null) {
+      token = parseMethodTypeVar(name);
+    } else {
+      isGetter = optional("get", getOrSet);
+      token = name;
+      listener.handleNoTypeVariables(token.next);
+    }
+    token = parseGetterOrFormalParameters(
+        token, name, isGetter, MemberKind.TopLevelMethod);
+    AsyncModifier savedAsyncModifier = asyncState;
+    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);
+    }
+    token = parseFunctionBody(token, false, isExternal);
+    asyncState = savedAsyncModifier;
+    listener.endTopLevelMethod(beforeStart.next, getOrSet, token);
+    return token;
+  }
+
+  Token parseMethodTypeVar(Token name) {
+    if (!optional('<', name.next)) {
+      return noTypeParamOrArg.parseVariables(name, this);
+    }
+    TypeParamOrArgInfo typeVar = computeTypeParamOrArg(name, true);
+    Token token = typeVar.parseVariables(name, this);
+    if (optional('=', token.next)) {
+      // Recovery
+      token = token.next;
+      reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
+    }
+    return token;
+  }
+
+  Token parseFieldInitializerOpt(Token token, Token name, Token lateToken,
+      Token varFinalOrConst, DeclarationKind kind) {
+    Token next = token.next;
+    if (optional('=', next)) {
+      Token assignment = next;
+      listener.beginFieldInitializer(next);
+      token = parseExpression(next);
+      listener.endFieldInitializer(assignment, token.next);
+    } else {
+      if (varFinalOrConst != null && !name.isSynthetic) {
+        if (optional("const", varFinalOrConst)) {
+          reportRecoverableError(
+              name,
+              codes.templateConstFieldWithoutInitializer
+                  .withArguments(name.lexeme));
+        } else if (kind == DeclarationKind.TopLevel &&
+            optional("final", varFinalOrConst) &&
+            lateToken == null) {
+          reportRecoverableError(
+              name,
+              codes.templateFinalFieldWithoutInitializer
+                  .withArguments(name.lexeme));
+        }
+      }
+      listener.handleNoFieldInitializer(token.next);
+    }
+    return token;
+  }
+
+  Token parseVariableInitializerOpt(Token token) {
+    if (optional('=', token.next)) {
+      Token assignment = token.next;
+      listener.beginVariableInitializer(assignment);
+      token = parseExpression(assignment);
+      listener.endVariableInitializer(assignment);
+    } else {
+      listener.handleNoVariableInitializer(token.next);
+    }
+    return token;
+  }
+
+  Token parseInitializersOpt(Token token) {
+    if (optional(':', token.next)) {
+      return parseInitializers(token.next);
+    } else {
+      listener.handleNoInitializers();
+      return token;
+    }
+  }
+
+  /// ```
+  /// initializers:
+  ///   ':' initializerListEntry (',' initializerListEntry)*
+  /// ;
+  /// ```
+  Token parseInitializers(Token token) {
+    Token begin = token;
+    assert(optional(':', begin));
+    listener.beginInitializers(begin);
+    int count = 0;
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = false;
+    Token next = begin;
+    while (true) {
+      token = parseInitializer(next);
+      ++count;
+      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;
+          if (!optional('(', next)) {
+            break;
+          }
+          // Looks like assert expression ... fall through to insert comma
+        } else if (!next.isIdentifier && !optional('this', next)) {
+          // An identifier that wasn't an initializer. Break.
+          break;
+        } else {
+          if (optional('this', next)) {
+            next = next.next;
+            if (!optional('.', next)) {
+              break;
+            }
+            next = next.next;
+            if (!next.isIdentifier && !optional('assert', next)) {
+              break;
+            }
+          }
+          next = next.next;
+          if (!optional('=', next)) {
+            break;
+          }
+          // Looks like field assignment... fall through to insert comma
+        }
+        // TODO(danrubel): Consider enhancing this to indicate that we are
+        // expecting one of `,` or `;` or `{`
+        reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments(','));
+        next = rewriter.insertSyntheticToken(token, TokenType.COMMA);
+      }
+    }
+    mayParseFunctionExpressions = old;
+    listener.endInitializers(count, begin, token.next);
+    return token;
+  }
+
+  /// ```
+  /// initializerListEntry:
+  ///   'super' ('.' identifier)? arguments |
+  ///   fieldInitializer |
+  ///   assertion
+  /// ;
+  ///
+  /// fieldInitializer:
+  ///   ('this' '.')? identifier '=' conditionalExpression cascadeSection*
+  /// ;
+  /// ```
+  Token parseInitializer(Token token) {
+    Token next = token.next;
+    listener.beginInitializer(next);
+    Token beforeExpression = token;
+    if (optional('assert', next)) {
+      token = parseAssert(token, Assert.Initializer);
+      listener.endInitializer(token.next);
+      return token;
+    } else if (optional('super', next)) {
+      return parseSuperInitializerExpression(token);
+    } else if (optional('this', next)) {
+      token = next;
+      next = token.next;
+      if (optional('.', next)) {
+        token = next;
+        next = token.next;
+        if (next.isIdentifier) {
+          token = next;
+        } else {
+          // Recovery
+          token = insertSyntheticIdentifier(
+              token, IdentifierContext.fieldInitializer);
+        }
+        next = token.next;
+        if (optional('=', next)) {
+          return parseInitializerExpressionRest(beforeExpression);
+        }
+      }
+      if (optional('(', next)) {
+        token = parseInitializerExpressionRest(beforeExpression);
+        next = token.next;
+        if (optional('{', next) || optional('=>', next)) {
+          reportRecoverableError(
+              next, codes.messageRedirectingConstructorWithBody);
+        }
+        return token;
+      }
+      // Recovery
+      if (optional('this', token)) {
+        // TODO(danrubel): Consider a better error message indicating that
+        // `this.<fieldname>=` is expected.
+        reportRecoverableError(
+            next, codes.templateExpectedButGot.withArguments('.'));
+        rewriter.insertSyntheticToken(token, TokenType.PERIOD);
+        token = rewriter.insertSyntheticIdentifier(token.next);
+        next = token.next;
+      }
+      // Fall through to recovery
+    } else if (next.isIdentifier) {
+      Token next2 = next.next;
+      if (optional('=', next2)) {
+        return parseInitializerExpressionRest(token);
+      }
+      // Recovery: If this looks like an expression,
+      // then fall through to insert the LHS and `=` of the assignment,
+      // otherwise insert an `=` and synthetic identifier.
+      if (!next2.isOperator && !optional('.', next2)) {
+        token = rewriter.insertSyntheticToken(next, TokenType.EQ);
+        token = insertSyntheticIdentifier(token, IdentifierContext.expression,
+            message: codes.messageMissingAssignmentInInitializer,
+            messageOnToken: next);
+        return parseInitializerExpressionRest(beforeExpression);
+      }
+    } else {
+      // Recovery: Insert a synthetic assignment.
+      token = insertSyntheticIdentifier(
+          token, IdentifierContext.fieldInitializer,
+          message: codes.messageExpectedAnInitializer, messageOnToken: token);
+      token = rewriter.insertSyntheticToken(token, TokenType.EQ);
+      token = rewriter.insertSyntheticIdentifier(token);
+      return parseInitializerExpressionRest(beforeExpression);
+    }
+    // Recovery:
+    // Insert a synthetic identifier and assignment operator
+    // to ensure that the expression is indeed an assignment.
+    // Failing to do so causes this test to fail:
+    // pkg/front_end/testcases/regress/issue_31192.dart
+    // TODO(danrubel): Investigate better recovery.
+    token = insertSyntheticIdentifier(
+        beforeExpression, IdentifierContext.fieldInitializer,
+        message: codes.messageMissingAssignmentInInitializer);
+    rewriter.insertSyntheticToken(token, TokenType.EQ);
+    return parseInitializerExpressionRest(beforeExpression);
+  }
+
+  /// Parse the `super` initializer:
+  /// ```
+  ///   'super' ('.' identifier)? arguments ;
+  /// ```
+  Token parseSuperInitializerExpression(final Token start) {
+    Token token = start.next;
+    assert(optional('super', token));
+    Token next = token.next;
+    if (optional('.', next)) {
+      token = next;
+      next = token.next;
+      if (next.kind != IDENTIFIER_TOKEN) {
+        next = IdentifierContext.expressionContinuation
+            .ensureIdentifier(token, this);
+      }
+      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;
+        if (!next.isIdentifier) {
+          // Insert a synthetic identifier but don't report another error.
+          next = rewriter.insertSyntheticIdentifier(token);
+        }
+        token = next;
+        next = token.next;
+      }
+      if (optional('=', next)) {
+        if (optional('super', token)) {
+          // parseExpression will report error on assignment to super
+        } else {
+          reportRecoverableError(
+              token, codes.messageFieldInitializedOutsideDeclaringClass);
+        }
+      } else if (!optional('(', next)) {
+        reportRecoverableError(
+            next, codes.templateExpectedAfterButGot.withArguments('('));
+        rewriter.insertParens(token, false);
+      }
+    }
+    return parseInitializerExpressionRest(start);
+  }
+
+  Token parseInitializerExpressionRest(Token token) {
+    token = parseExpression(token);
+    listener.endInitializer(token.next);
+    return token;
+  }
+
+  /// If the next token is an opening curly brace, return it. Otherwise, use the
+  /// given [template] or [missingBlockName] to report an error, insert an
+  /// opening and a closing curly brace, and return the newly inserted opening
+  /// curly brace. If  [template] and [missingBlockName] are `null`, then use
+  /// a default error message instead.
+  Token ensureBlock(
+      Token token,
+      Template<Message Function(Token token)> template,
+      String missingBlockName) {
+    Token next = token.next;
+    if (optional('{', next)) return next;
+    if (template == null) {
+      if (missingBlockName == null) {
+        // TODO(danrubel): rename ExpectedButGot to ExpectedBefore
+        reportRecoverableError(
+            next, codes.templateExpectedButGot.withArguments('{'));
+      } else {
+        // TODO(danrubel): rename ExpectedClassOrMixinBody
+        //  to ExpectedDeclarationOrClauseBody
+        reportRecoverableError(
+            token,
+            codes.templateExpectedClassOrMixinBody
+                .withArguments(missingBlockName));
+      }
+    } else {
+      reportRecoverableError(next, template.withArguments(next));
+    }
+    return insertBlock(token);
+  }
+
+  Token insertBlock(Token token) {
+    Token next = token.next;
+    BeginToken beginGroup = rewriter.insertToken(token,
+        new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset));
+    Token endGroup = rewriter.insertToken(beginGroup,
+        new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, next.offset));
+    beginGroup.endGroup = endGroup;
+    return beginGroup;
+  }
+
+  /// If the next token is a closing parenthesis, return it.
+  /// 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;
+    if (optional(')', next)) {
+      return next;
+    }
+    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);
+    }
+
+    // TODO(danrubel): Pass in context for better error message.
+    reportRecoverableError(
+        next, codes.templateExpectedButGot.withArguments(')'));
+
+    // Scanner guarantees a closing parenthesis
+    // TODO(danrubel): Improve recovery by having callers parse tokens
+    // between `token` and `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;
+    if (optional(':', next)) return next;
+    Message message = codes.templateExpectedButGot.withArguments(':');
+    Token newToken = new SyntheticToken(TokenType.COLON, next.charOffset);
+    return rewriteAndRecover(token, message, newToken);
+  }
+
+  /// If the token after [token] is a not literal string,
+  /// then insert a synthetic literal string.
+  /// Call `parseLiteralString` and return the result.
+  Token ensureLiteralString(Token token) {
+    Token next = token.next;
+    if (!identical(next.kind, STRING_TOKEN)) {
+      Message message = codes.templateExpectedString.withArguments(next);
+      Token newToken =
+          new SyntheticStringToken(TokenType.STRING, '""', next.charOffset, 0);
+      rewriteAndRecover(token, message, newToken);
+    }
+    return parseLiteralString(token);
+  }
+
+  /// If the token after [token] is a semi-colon, return it.
+  /// Otherwise, report an error, insert a synthetic semi-colon,
+  /// and return the inserted semi-colon.
+  Token ensureSemicolon(Token token) {
+    // 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;
+    if (optional(';', next)) return next;
+
+    // Find a token on the same line as where the ';' should be inserted.
+    // Reporting the error on this token makes it easier
+    // for users to understand and fix the error.
+    reportRecoverableError(findPreviousNonZeroLengthToken(token),
+        codes.templateExpectedAfterButGot.withArguments(';'));
+    return rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+  }
+
+  /// 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, Message message, Token newToken) {
+    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;
+    assert(optional('[]', next));
+    Token replacement;
+    if (next.isSynthetic) {
+      replacement = link(
+          new SyntheticBeginToken(TokenType.OPEN_SQUARE_BRACKET, next.offset),
+          new SyntheticToken(TokenType.CLOSE_SQUARE_BRACKET, next.offset));
+    } else {
+      replacement = link(
+          new BeginToken(TokenType.OPEN_SQUARE_BRACKET, next.offset),
+          new Token(TokenType.CLOSE_SQUARE_BRACKET, next.offset + 1));
+    }
+    rewriter.replaceTokenFollowing(token, replacement);
+    return token;
+  }
+
+  /// 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;
+    if (next.keyword == null) {
+      final String nextValue = next.next.stringValue;
+      for (String expectedValue in expectedNext) {
+        if (identical(nextValue, expectedValue)) {
+          reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+          return next;
+        }
+      }
+    }
+    return token;
+  }
+
+  Token parseNativeClause(Token token) {
+    Token nativeToken = token = token.next;
+    assert(optional('native', nativeToken));
+    bool hasName = false;
+    if (token.next.kind == STRING_TOKEN) {
+      hasName = true;
+      token = parseLiteralString(token);
+    }
+    listener.handleNativeClause(nativeToken, hasName);
+    reportRecoverableError(
+        nativeToken, codes.messageNativeClauseShouldBeAnnotation);
+    return token;
+  }
+
+  Token skipClassOrMixinOrExtensionBody(Token token) {
+    // The scanner ensures that `{` always has a closing `}`.
+    return ensureBlock(token, null, null);
+  }
+
+  /// ```
+  /// classBody:
+  ///   '{' classMember* '}'
+  /// ;
+  /// ```
+  Token parseClassOrMixinOrExtensionBody(
+      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)) {
+      token = parseClassOrMixinOrExtensionMemberImpl(
+          token, kind, enclosingDeclarationName);
+      ++count;
+    }
+    token = token.next;
+    assert(token.isEof || optional('}', token));
+    listener.endClassOrMixinBody(kind, count, begin, token);
+    return token;
+  }
+
+  bool isUnaryMinus(Token token) =>
+      token.kind == IDENTIFIER_TOKEN &&
+      token.lexeme == 'unary' &&
+      optional('-', token.next);
+
+  /// Parse a class member.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseClassMember(Token token, String className) {
+    return parseClassOrMixinOrExtensionMemberImpl(
+            syntheticPreviousToken(token), DeclarationKind.Class, className)
+        .next;
+  }
+
+  /// Parse a mixin member.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseMixinMember(Token token, String mixinName) {
+    return parseClassOrMixinOrExtensionMemberImpl(
+            syntheticPreviousToken(token), DeclarationKind.Mixin, mixinName)
+        .next;
+  }
+
+  /// Parse an extension member.
+  ///
+  /// This method is only invoked from outside the parser. As a result, this
+  /// method takes the next token to be consumed rather than the last consumed
+  /// token and returns the token after the last consumed token rather than the
+  /// last consumed token.
+  Token parseExtensionMember(Token token, String extensionName) {
+    return parseClassOrMixinOrExtensionMemberImpl(syntheticPreviousToken(token),
+            DeclarationKind.Extension, extensionName)
+        .next;
+  }
+
+  /// ```
+  /// classMember:
+  ///   fieldDeclaration |
+  ///   constructorDeclaration |
+  ///   methodDeclaration
+  /// ;
+  ///
+  /// mixinMember:
+  ///   fieldDeclaration |
+  ///   methodDeclaration
+  /// ;
+  ///
+  /// extensionMember:
+  ///   staticFieldDeclaration |
+  ///   methodDeclaration
+  /// ;
+  /// ```
+  Token parseClassOrMixinOrExtensionMemberImpl(
+      Token token, DeclarationKind kind, String enclosingDeclarationName) {
+    Token beforeStart = token = parseMetadataStar(token);
+
+    Token covariantToken;
+    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;
+      }
+      if (isModifier(next)) {
+        if (optional('static', next)) {
+          staticToken = token = next;
+          next = token.next;
+        } else if (optional('covariant', next)) {
+          covariantToken = token = next;
+          next = token.next;
+        }
+        if (isModifier(next)) {
+          if (optional('final', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          } else if (optional('var', next)) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          } else if (optional('const', next) && covariantToken == null) {
+            varFinalOrConst = token = next;
+            next = token.next;
+          } else if (optional('late', next)) {
+            lateToken = token = next;
+            next = token.next;
+            if (isModifier(next) && optional('final', next)) {
+              varFinalOrConst = token = next;
+              next = token.next;
+            }
+          }
+          if (isModifier(next)) {
+            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+              ..covariantToken = covariantToken
+              ..externalToken = externalToken
+              ..lateToken = lateToken
+              ..staticToken = staticToken
+              ..varFinalOrConst = varFinalOrConst;
+
+            token = context.parseClassMemberModifiers(token);
+            next = token.next;
+
+            covariantToken = context.covariantToken;
+            externalToken = context.externalToken;
+            lateToken = context.lateToken;
+            staticToken = context.staticToken;
+            varFinalOrConst = context.varFinalOrConst;
+
+            context = null;
+          }
+        }
+      }
+    }
+
+    listener.beginMember();
+
+    Token beforeType = token;
+    TypeInfo typeInfo = computeType(token, false, true);
+    token = typeInfo.skipType(token);
+    next = token.next;
+
+    Token getOrSet;
+    if (next.type != TokenType.IDENTIFIER) {
+      String value = next.stringValue;
+      if (identical(value, 'get') || identical(value, 'set')) {
+        if (next.next.isIdentifier) {
+          getOrSet = token = next;
+          next = token.next;
+        }
+        // Fall through to continue parsing `get` or `set` as an identifier.
+      } else if (identical(value, 'factory')) {
+        Token next2 = next.next;
+        if (next2.isIdentifier || next2.isModifier) {
+          if (beforeType != token) {
+            reportRecoverableError(token, codes.messageTypeBeforeFactory);
+          }
+          token = parseFactoryMethod(token, kind, beforeStart, externalToken,
+              staticToken ?? covariantToken, varFinalOrConst);
+          listener.endMember();
+          return token;
+        }
+        // Fall through to continue parsing `factory` as an identifier.
+      } else if (identical(value, 'operator')) {
+        Token next2 = next.next;
+        TypeParamOrArgInfo typeParam = computeTypeParamOrArg(next);
+        // `operator` can be used as an identifier as in
+        // `int operator<T>()` or `int operator = 2`
+        if (next2.isUserDefinableOperator && typeParam == noTypeParamOrArg) {
+          token = parseMethod(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType,
+              typeInfo,
+              getOrSet,
+              token.next,
+              kind,
+              enclosingDeclarationName);
+          listener.endMember();
+          return token;
+        } else if (optional('===', next2) ||
+            optional('!==', next2) ||
+            (next2.isOperator &&
+                !optional('=', next2) &&
+                !optional('<', next2))) {
+          // Recovery: Invalid operator
+          return parseInvalidOperatorDeclaration(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType,
+              kind,
+              enclosingDeclarationName);
+        } else if (isUnaryMinus(next2)) {
+          // Recovery
+          token = parseMethod(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType,
+              typeInfo,
+              getOrSet,
+              token.next,
+              kind,
+              enclosingDeclarationName);
+          listener.endMember();
+          return token;
+        }
+        // Fall through to continue parsing `operator` as an identifier.
+      } else if (!next.isIdentifier ||
+          (identical(value, 'typedef') &&
+              token == beforeStart &&
+              next.next.isIdentifier)) {
+        // Recovery
+        return recoverFromInvalidMember(
+            token,
+            beforeStart,
+            externalToken,
+            staticToken,
+            covariantToken,
+            lateToken,
+            varFinalOrConst,
+            beforeType,
+            typeInfo,
+            getOrSet,
+            kind,
+            enclosingDeclarationName);
+      }
+    } else if (typeInfo == noType && varFinalOrConst == null) {
+      Token next2 = next.next;
+      if (next2.isUserDefinableOperator && next2.endGroup == null) {
+        String value = next2.next.stringValue;
+        if (identical(value, '(') ||
+            identical(value, '{') ||
+            identical(value, '=>')) {
+          // Recovery: Missing `operator` keyword
+          return parseInvalidOperatorDeclaration(
+              beforeStart,
+              externalToken,
+              staticToken,
+              covariantToken,
+              lateToken,
+              varFinalOrConst,
+              beforeType,
+              kind,
+              enclosingDeclarationName);
+        }
+      }
+    }
+
+    // At this point, token is before the name, and next is the name
+    next = next.next;
+    String value = next.stringValue;
+    if (getOrSet != null ||
+        identical(value, '(') ||
+        identical(value, '{') ||
+        identical(value, '<') ||
+        identical(value, '.') ||
+        identical(value, '=>')) {
+      token = parseMethod(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          lateToken,
+          varFinalOrConst,
+          beforeType,
+          typeInfo,
+          getOrSet,
+          token.next,
+          kind,
+          enclosingDeclarationName);
+    } else {
+      if (getOrSet != null) {
+        reportRecoverableErrorWithToken(
+            getOrSet, codes.templateExtraneousModifier);
+      }
+      token = parseFields(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          lateToken,
+          varFinalOrConst,
+          beforeType,
+          typeInfo,
+          token.next,
+          kind);
+    }
+    listener.endMember();
+    return token;
+  }
+
+  Token parseMethod(
+      Token beforeStart,
+      Token externalToken,
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      Token beforeType,
+      TypeInfo typeInfo,
+      Token getOrSet,
+      Token name,
+      DeclarationKind kind,
+      String enclosingDeclarationName) {
+    if (lateToken != null) {
+      reportRecoverableErrorWithToken(
+          lateToken, codes.templateExtraneousModifier);
+    }
+    bool isOperator = false;
+    if (getOrSet == null && optional('operator', name)) {
+      Token operator = name.next;
+      if (operator.isOperator ||
+          identical(operator.kind, EQ_EQ_EQ_TOKEN) ||
+          identical(operator.kind, BANG_EQ_EQ_TOKEN) ||
+          isUnaryMinus(operator)) {
+        isOperator = true;
+      }
+    }
+
+    if (staticToken != null) {
+      if (isOperator) {
+        reportRecoverableError(staticToken, codes.messageStaticOperator);
+        staticToken = null;
+      }
+    } else if (covariantToken != null) {
+      if (getOrSet == null || optional('get', getOrSet)) {
+        reportRecoverableError(covariantToken, codes.messageCovariantMember);
+        covariantToken = null;
+      }
+    }
+    if (varFinalOrConst != null) {
+      if (optional('const', varFinalOrConst)) {
+        if (getOrSet != null) {
+          reportRecoverableErrorWithToken(
+              varFinalOrConst, codes.templateExtraneousModifier);
+          varFinalOrConst = null;
+        }
+      } else if (optional('var', varFinalOrConst)) {
+        reportRecoverableError(varFinalOrConst, codes.messageVarReturnType);
+        varFinalOrConst = null;
+      } else {
+        assert(optional('final', varFinalOrConst));
+        reportRecoverableErrorWithToken(
+            varFinalOrConst, codes.templateExtraneousModifier);
+        varFinalOrConst = null;
+      }
+    }
+
+    // TODO(danrubel): Consider parsing the name before calling beginMethod
+    // rather than passing the name token into beginMethod.
+    listener.beginMethod(externalToken, staticToken, covariantToken,
+        varFinalOrConst, getOrSet, name);
+
+    Token token = typeInfo.parseType(beforeType, this);
+    assert(token.next == (getOrSet ?? name));
+    token = getOrSet ?? token;
+
+    if (isOperator) {
+      token = parseOperatorName(token);
+    } else {
+      token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
+      if (getOrSet == null) {
+        token = parseQualifiedRestOpt(
+            token, IdentifierContext.methodDeclarationContinuation);
+      }
+    }
+
+    bool isGetter = false;
+    if (getOrSet == null) {
+      token = parseMethodTypeVar(token);
+    } else {
+      isGetter = optional("get", getOrSet);
+      listener.handleNoTypeVariables(token.next);
+    }
+
+    Token beforeParam = token;
+    Token beforeInitializers = parseGetterOrFormalParameters(
+        token,
+        name,
+        isGetter,
+        kind == DeclarationKind.Extension
+            ? staticToken != null
+                ? MemberKind.ExtensionStaticMethod
+                : MemberKind.ExtensionNonStaticMethod
+            : staticToken != null
+                ? MemberKind.StaticMethod
+                : MemberKind.NonStaticMethod);
+    token = parseInitializersOpt(beforeInitializers);
+    if (token == beforeInitializers) beforeInitializers = null;
+
+    AsyncModifier savedAsyncModifier = asyncState;
+    Token asyncToken = token.next;
+    token = parseAsyncModifierOpt(token);
+    if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
+      reportRecoverableError(asyncToken, codes.messageSetterNotSync);
+    }
+    final Token bodyStart = token.next;
+    if (externalToken != null) {
+      if (!optional(';', bodyStart)) {
+        reportRecoverableError(bodyStart, codes.messageExternalMethodWithBody);
+      }
+    }
+    if (optional('=', bodyStart)) {
+      reportRecoverableError(bodyStart, codes.messageRedirectionInNonFactory);
+      token = parseRedirectingFactoryBody(token);
+    } else {
+      token = parseFunctionBody(token, false,
+          (staticToken == null || externalToken != null) && inPlainSync);
+    }
+    asyncState = savedAsyncModifier;
+
+    bool isConstructor = false;
+    if (optional('.', name.next) || beforeInitializers != null) {
+      isConstructor = true;
+      if (name.lexeme != enclosingDeclarationName) {
+        // Recovery: The name does not match,
+        // but the name is prefixed or the declaration contains initializers.
+        // Report an error and continue with invalid name.
+        // TODO(danrubel): report invalid constructor name
+        // Currently multiple listeners report this error, but that logic should
+        // be removed and the error reported here instead.
+      }
+      if (getOrSet != null) {
+        // Recovery
+        if (optional('.', name.next)) {
+          // Unexpected get/set before constructor.
+          // Report an error and skip over the token.
+          // TODO(danrubel): report an error on get/set token
+          // This is currently reported by listeners other than AstBuilder.
+          // It should be reported here rather than in the listeners.
+        } else {
+          isConstructor = false;
+          if (beforeInitializers != null) {
+            // Unexpected initializers after get/set declaration.
+            // Report an error on the initializers
+            // and continue with the get/set declaration.
+            // TODO(danrubel): report invalid initializers error
+            // Currently multiple listeners report this error, but that logic
+            // should be removed and the error reported here instead.
+          }
+        }
+      }
+    } else if (name.lexeme == enclosingDeclarationName) {
+      if (getOrSet != null) {
+        // Recovery: The get/set member name is invalid.
+        // Report an error and continue with invalid name.
+        // TODO(danrubel): report invalid get/set member name
+        // Currently multiple listeners report this error, but that logic should
+        // be removed and the error reported here instead.
+      } else {
+        isConstructor = true;
+      }
+    }
+
+    if (isConstructor) {
+      //
+      // constructor
+      //
+      if (staticToken != null) {
+        reportRecoverableError(staticToken, codes.messageStaticConstructor);
+      }
+      switch (kind) {
+        case DeclarationKind.Class:
+          // TODO(danrubel): Remove getOrSet from constructor events
+          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);
+          break;
+        case DeclarationKind.Extension:
+          reportRecoverableError(
+              name, codes.messageExtensionDeclaresConstructor);
+          listener.endExtensionConstructor(getOrSet, beforeStart.next,
+              beforeParam.next, beforeInitializers?.next, token);
+          break;
+        case DeclarationKind.TopLevel:
+          throw "Internal error: TopLevel constructor.";
+          break;
+      }
+    } else {
+      //
+      // method
+      //
+      if (varFinalOrConst != null) {
+        assert(optional('const', varFinalOrConst));
+        reportRecoverableError(varFinalOrConst, codes.messageConstMethod);
+      }
+      switch (kind) {
+        case DeclarationKind.Class:
+          // TODO(danrubel): Remove beginInitializers token from method events
+          listener.endClassMethod(getOrSet, beforeStart.next, beforeParam.next,
+              beforeInitializers?.next, token);
+          break;
+        case DeclarationKind.Mixin:
+          listener.endMixinMethod(getOrSet, beforeStart.next, beforeParam.next,
+              beforeInitializers?.next, token);
+          break;
+        case DeclarationKind.Extension:
+          if (optional(';', bodyStart) && externalToken == null) {
+            reportRecoverableError(isOperator ? name.next : name,
+                codes.messageExtensionDeclaresAbstractMember);
+          }
+          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;
+    assert(optional('factory', factoryKeyword));
+
+    if (!isValidTypeReference(token.next)) {
+      // Recovery
+      ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+        ..externalToken = externalToken
+        ..staticOrCovariant = staticOrCovariant
+        ..varFinalOrConst = varFinalOrConst;
+
+      token = context.parseModifiersAfterFactory(token);
+
+      externalToken = context.externalToken;
+      staticOrCovariant = context.staticToken ?? context.covariantToken;
+      varFinalOrConst = context.varFinalOrConst;
+
+      context = null;
+    }
+
+    if (staticOrCovariant != null) {
+      reportRecoverableErrorWithToken(
+          staticOrCovariant, codes.templateExtraneousModifier);
+    }
+    if (varFinalOrConst != null && !optional('const', varFinalOrConst)) {
+      reportRecoverableErrorWithToken(
+          varFinalOrConst, codes.templateExtraneousModifier);
+      varFinalOrConst = null;
+    }
+
+    listener.beginFactoryMethod(beforeStart, externalToken, varFinalOrConst);
+    token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
+    token = parseQualifiedRestOpt(
+        token, IdentifierContext.methodDeclarationContinuation);
+    token = parseMethodTypeVar(token);
+    token = parseFormalParametersRequiredOpt(token, MemberKind.Factory);
+    Token asyncToken = token.next;
+    token = parseAsyncModifierOpt(token);
+    Token next = token.next;
+    if (!inPlainSync) {
+      reportRecoverableError(asyncToken, codes.messageFactoryNotSync);
+    }
+    if (optional('=', next)) {
+      if (externalToken != null) {
+        reportRecoverableError(next, codes.messageExternalFactoryRedirection);
+      }
+      token = parseRedirectingFactoryBody(token);
+    } else if (externalToken != null) {
+      if (!optional(';', next)) {
+        reportRecoverableError(next, codes.messageExternalFactoryWithBody);
+      }
+      token = parseFunctionBody(token, false, true);
+    } else {
+      if (varFinalOrConst != null && !optional('native', next)) {
+        if (optional('const', varFinalOrConst)) {
+          reportRecoverableError(varFinalOrConst, codes.messageConstFactory);
+        }
+      }
+      token = parseFunctionBody(token, false, false);
+    }
+    switch (kind) {
+      case DeclarationKind.Class:
+        listener.endClassFactoryMethod(beforeStart.next, factoryKeyword, token);
+        break;
+      case DeclarationKind.Mixin:
+        reportRecoverableError(
+            factoryKeyword, codes.messageMixinDeclaresConstructor);
+        listener.endMixinFactoryMethod(beforeStart.next, factoryKeyword, token);
+        break;
+      case DeclarationKind.Extension:
+        reportRecoverableError(
+            factoryKeyword, codes.messageExtensionDeclaresConstructor);
+        listener.endExtensionFactoryMethod(
+            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;
+    assert(optional('operator', token));
+    Token next = token.next;
+    if (next.isUserDefinableOperator) {
+      if (computeTypeParamOrArg(token) != noTypeParamOrArg) {
+        // `operator` is being used as an identifier.
+        // For example: `int operator<T>(foo) => 0;`
+        listener.handleIdentifier(token, IdentifierContext.methodDeclaration);
+        return token;
+      } else {
+        listener.handleOperatorName(token, next);
+        return next;
+      }
+    } else if (optional('(', next)) {
+      return ensureIdentifier(beforeToken, IdentifierContext.operatorName);
+    } else if (isUnaryMinus(next)) {
+      // Recovery
+      reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+      next = next.next;
+      listener.handleOperatorName(token, next);
+      return next;
+    } else {
+      // Recovery
+      // Scanner reports an error for `===` and `!==`.
+      if (next.type != TokenType.EQ_EQ_EQ &&
+          next.type != TokenType.BANG_EQ_EQ) {
+        // The user has specified an invalid operator name.
+        // Report the error, accept the invalid operator name, and move on.
+        reportRecoverableErrorWithToken(next, codes.templateInvalidOperator);
+      }
+      listener.handleInvalidOperatorName(token, next);
+      return next;
+    }
+  }
+
+  Token parseFunctionExpression(Token token) {
+    Token beginToken = token.next;
+    listener.beginFunctionExpression(beginToken);
+    token = parseFormalParametersRequiredOpt(token, MemberKind.Local);
+    token = parseAsyncOptBody(token, true, false);
+    listener.endFunctionExpression(beginToken, token.next);
+    return token;
+  }
+
+  Token parseFunctionLiteral(
+      Token start,
+      Token beforeName,
+      Token name,
+      TypeInfo typeInfo,
+      TypeParamOrArgInfo typeParam,
+      IdentifierContext context) {
+    Token formals = typeParam.parseVariables(name, this);
+    listener.beginNamedFunctionExpression(start.next);
+    typeInfo.parseType(start, this);
+    return parseNamedFunctionRest(beforeName, start.next, formals, true);
+  }
+
+  /// Parses the rest of a named function declaration starting from its [name]
+  /// but then skips any type parameters and continue parsing from [formals]
+  /// (the formal parameters).
+  ///
+  /// If [isFunctionExpression] is true, this method parses the rest of named
+  /// function expression which isn't legal syntax in Dart.  Useful for
+  /// recovering from Javascript code being pasted into a Dart program, as it
+  /// will interpret `function foo() {}` as a named function expression with
+  /// return type `function` and name `foo`.
+  ///
+  /// Precondition: the parser has previously generated these events:
+  ///
+  /// - Type variables.
+  /// - `beginLocalFunctionDeclaration` if [isFunctionExpression] is false,
+  ///   otherwise `beginNamedFunctionExpression`.
+  /// - Return type.
+  Token parseNamedFunctionRest(
+      Token beforeName, Token begin, Token formals, bool isFunctionExpression) {
+    Token token = beforeName.next;
+    listener.beginFunctionName(token);
+    token =
+        ensureIdentifier(beforeName, IdentifierContext.localFunctionDeclaration)
+            .next;
+    if (isFunctionExpression) {
+      reportRecoverableError(
+          beforeName.next, codes.messageNamedFunctionExpression);
+    }
+    listener.endFunctionName(begin, token);
+    token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
+    token = parseInitializersOpt(token);
+    token = parseAsyncOptBody(token, isFunctionExpression, false);
+    if (isFunctionExpression) {
+      listener.endNamedFunctionExpression(token);
+    } else {
+      listener.endLocalFunctionDeclaration(token);
+    }
+    return token;
+  }
+
+  /// Parses a function body optionally preceded by an async modifier (see
+  /// [parseAsyncModifierOpt]).  This method is used in both expression context
+  /// (when [ofFunctionExpression] is true) and statement context. In statement
+  /// context (when [ofFunctionExpression] is false), and if the function body
+  /// is on the form `=> expression`, a trailing semicolon is required.
+  ///
+  /// It's an error if there's no function body unless [allowAbstract] is true.
+  Token parseAsyncOptBody(
+      Token token, bool ofFunctionExpression, bool allowAbstract) {
+    AsyncModifier savedAsyncModifier = asyncState;
+    token = parseAsyncModifierOpt(token);
+    token = parseFunctionBody(token, ofFunctionExpression, allowAbstract);
+    asyncState = savedAsyncModifier;
+    return token;
+  }
+
+  Token parseConstructorReference(Token token, [TypeParamOrArgInfo typeArg]) {
+    Token start =
+        ensureIdentifier(token, IdentifierContext.constructorReference);
+    listener.beginConstructorReference(start);
+    token = parseQualifiedRestOpt(
+        start, IdentifierContext.constructorReferenceContinuation);
+    typeArg ??= computeTypeParamOrArg(token);
+    token = typeArg.parseArguments(token, this);
+    Token period = null;
+    if (optional('.', token.next)) {
+      period = token.next;
+      token = ensureIdentifier(period,
+          IdentifierContext.constructorReferenceContinuationAfterTypeArguments);
+    } else {
+      listener.handleNoConstructorReferenceContinuationAfterTypeArguments(
+          token.next);
+    }
+    listener.endConstructorReference(start, period, token.next);
+    return token;
+  }
+
+  Token parseRedirectingFactoryBody(Token token) {
+    token = token.next;
+    assert(optional('=', token));
+    listener.beginRedirectingFactoryBody(token);
+    Token equals = token;
+    token = parseConstructorReference(token);
+    token = ensureSemicolon(token);
+    listener.endRedirectingFactoryBody(equals, token);
+    return token;
+  }
+
+  Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) {
+    assert(!isExpression);
+    token = skipAsyncModifier(token);
+    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;
+      if (optional(';', next)) {
+        listener.handleNativeFunctionBodySkipped(nativeToken, next);
+        return token.next;
+      }
+      listener.handleNativeFunctionBodyIgnored(nativeToken, next);
+      // Fall through to recover and skip function body
+    }
+    String value = next.stringValue;
+    if (identical(value, ';')) {
+      token = next;
+      if (!allowAbstract) {
+        reportRecoverableError(token, codes.messageExpectedBody);
+      }
+      listener.handleNoFunctionBody(token);
+    } else if (identical(value, '=>')) {
+      token = parseExpression(next);
+      // 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;
+      }
+      listener.handleFunctionBodySkipped(token, true);
+    } else if (identical(value, '=')) {
+      token = next;
+      reportRecoverableError(token, codes.messageExpectedBody);
+      token = parseExpression(token);
+      // 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;
+      }
+      listener.handleFunctionBodySkipped(token, true);
+    } else {
+      token = skipBlock(token);
+      listener.handleFunctionBodySkipped(token, false);
+    }
+    return token;
+  }
+
+  /// Parses a function body.  This method is used in both expression context
+  /// (when [ofFunctionExpression] is true) and statement context. In statement
+  /// context (when [ofFunctionExpression] is false), and if the function body
+  /// is on the form `=> expression`, a trailing semicolon is required.
+  ///
+  /// 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;
+    if (optional('native', next)) {
+      Token nativeToken = next;
+      token = parseNativeClause(token);
+      next = token.next;
+      if (optional(';', next)) {
+        listener.handleNativeFunctionBody(nativeToken, next);
+        return next;
+      }
+      reportRecoverableError(next, codes.messageExternalMethodWithBody);
+      listener.handleNativeFunctionBodyIgnored(nativeToken, next);
+      // Ignore the native keyword and fall through to parse the body
+    }
+    if (optional(';', next)) {
+      if (!allowAbstract) {
+        reportRecoverableError(next, codes.messageExpectedBody);
+      }
+      listener.handleEmptyFunctionBody(next);
+      return next;
+    } else if (optional('=>', next)) {
+      return parseExpressionFunctionBody(next, ofFunctionExpression);
+    } else if (optional('=', next)) {
+      // Recover from a bad factory method.
+      reportRecoverableError(next, codes.messageExpectedBody);
+      next = rewriter.insertToken(
+          next, new SyntheticToken(TokenType.FUNCTION, next.next.charOffset));
+      Token begin = next;
+      token = parseExpression(next);
+      if (!ofFunctionExpression) {
+        token = ensureSemicolon(token);
+        listener.handleExpressionFunctionBody(begin, token);
+      } else {
+        listener.handleExpressionFunctionBody(begin, null);
+      }
+      return token;
+    }
+    Token begin = next;
+    int statementCount = 0;
+    if (!optional('{', next)) {
+      // Recovery
+      // 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));
+        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)) {
+        reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+        return parseExpressionFunctionBody(next.next, ofFunctionExpression);
+      }
+      if (next.isKeywordOrIdentifier && optional('{', next.next)) {
+        reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+        token = next;
+        begin = next = token.next;
+        // Fall through to parse the block.
+      } else {
+        token = ensureBlock(token, codes.templateExpectedFunctionBody, null);
+        listener.handleInvalidFunctionBody(token);
+        return token.endGroup;
+      }
+    }
+
+    LoopState savedLoopState = loopState;
+    loopState = LoopState.OutsideLoop;
+    listener.beginBlockFunctionBody(begin);
+    token = next;
+    while (notEofOrValue('}', token.next)) {
+      Token startToken = token.next;
+      token = parseStatement(token);
+      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;
+      }
+      ++statementCount;
+    }
+    token = token.next;
+    assert(token.isEof || optional('}', token));
+    listener.endBlockFunctionBody(statementCount, begin, token);
+    loopState = savedLoopState;
+    return token;
+  }
+
+  Token parseExpressionFunctionBody(Token token, bool ofFunctionExpression) {
+    assert(optional('=>', token));
+    Token begin = token;
+    token = parseExpression(token);
+    if (!ofFunctionExpression) {
+      token = ensureSemicolon(token);
+      listener.handleExpressionFunctionBody(begin, token);
+    } else {
+      listener.handleExpressionFunctionBody(begin, null);
+    }
+    if (inGenerator) {
+      listener.handleInvalidStatement(
+          begin, codes.messageGeneratorReturnsValue);
+    }
+    return token;
+  }
+
+  Token skipAsyncModifier(Token token) {
+    String value = token.next.stringValue;
+    if (identical(value, 'async')) {
+      token = token.next;
+      value = token.next.stringValue;
+
+      if (identical(value, '*')) {
+        token = token.next;
+      }
+    } else if (identical(value, 'sync')) {
+      token = token.next;
+      value = token.next.stringValue;
+
+      if (identical(value, '*')) {
+        token = token.next;
+      }
+    }
+    return token;
+  }
+
+  Token parseAsyncModifierOpt(Token token) {
+    Token async;
+    Token star;
+    asyncState = AsyncModifier.Sync;
+    Token next = token.next;
+    if (optional('async', next)) {
+      async = token = next;
+      next = token.next;
+      if (optional('*', next)) {
+        asyncState = AsyncModifier.AsyncStar;
+        star = next;
+        token = next;
+      } else {
+        asyncState = AsyncModifier.Async;
+      }
+    } else if (optional('sync', next)) {
+      async = token = next;
+      next = token.next;
+      if (optional('*', next)) {
+        asyncState = AsyncModifier.SyncStar;
+        star = next;
+        token = next;
+      } else {
+        reportRecoverableError(async, codes.messageInvalidSyncModifier);
+      }
+    }
+    listener.handleAsyncModifier(async, star);
+    if (!inPlainSync && optional(';', token.next)) {
+      reportRecoverableError(token.next, codes.messageAbstractNotSync);
+    }
+    return token;
+  }
+
+  int statementDepth = 0;
+  Token parseStatement(Token token) {
+    if (statementDepth++ > 500) {
+      // This happens for degenerate programs, for example, a lot of nested
+      // if-statements. The language test deep_nesting2_negative_test, for
+      // example, provokes this.
+      return recoverFromStackOverflow(token);
+    }
+    Token result = parseStatementX(token);
+    statementDepth--;
+    return result;
+  }
+
+  Token parseStatementX(Token token) {
+    if (identical(token.next.kind, IDENTIFIER_TOKEN)) {
+      if (optional(':', token.next.next)) {
+        return parseLabeledStatement(token);
+      }
+      return parseExpressionStatementOrDeclarationAfterModifiers(
+          token, token, null, null, null, false);
+    }
+    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)) {
+        return parseExpressionStatementOrDeclarationAfterModifiers(
+            varOrFinal, token, null, varOrFinal, null, false);
+      }
+      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, 'for')) {
+      return parseForStatement(token, null);
+    } else if (identical(value, 'rethrow')) {
+      return parseRethrowStatement(token);
+    } else if (identical(value, 'while')) {
+      return parseWhileStatement(token);
+    } else if (identical(value, 'do')) {
+      return parseDoWhileStatement(token);
+    } else if (identical(value, 'try')) {
+      return parseTryStatement(token);
+    } else if (identical(value, 'switch')) {
+      return parseSwitchStatement(token);
+    } else if (identical(value, 'break')) {
+      return parseBreakStatement(token);
+    } else if (identical(value, 'continue')) {
+      return parseContinueStatement(token);
+    } else if (identical(value, 'assert')) {
+      return parseAssertStatement(token);
+    } else if (identical(value, ';')) {
+      return parseEmptyStatement(token);
+    } else if (identical(value, 'yield')) {
+      switch (asyncState) {
+        case AsyncModifier.Sync:
+          if (optional(':', token.next.next)) {
+            return parseLabeledStatement(token);
+          }
+          return parseExpressionStatementOrDeclaration(token);
+
+        case AsyncModifier.SyncStar:
+        case AsyncModifier.AsyncStar:
+          return parseYieldStatement(token);
+
+        case AsyncModifier.Async:
+          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')) {
+      if (inPlainSync) {
+        if (!looksLikeAwaitExpression(token)) {
+          return parseExpressionStatementOrDeclaration(token);
+        }
+        // Recovery: looks like an expression preceded by `await`
+        // but not inside an async context.
+        // Fall through to parseExpressionStatement
+        // and parseAwaitExpression will report the error.
+      }
+      return parseExpressionStatement(token);
+    } 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)) {
+        return parseLabeledStatement(token);
+      }
+      return parseExpressionStatementOrDeclaration(token);
+    } else {
+      return parseExpressionStatementOrDeclaration(token);
+    }
+  }
+
+  /// ```
+  /// yieldStatement:
+  ///   'yield' expression? ';'
+  /// ;
+  /// ```
+  Token parseYieldStatement(Token token) {
+    Token begin = token = token.next;
+    assert(optional('yield', token));
+    listener.beginYieldStatement(begin);
+    Token starToken;
+    if (optional('*', token.next)) {
+      starToken = token = token.next;
+    }
+    token = parseExpression(token);
+    token = ensureSemicolon(token);
+    listener.endYieldStatement(begin, starToken, token);
+    return token;
+  }
+
+  /// ```
+  /// returnStatement:
+  ///   'return' expression? ';'
+  /// ;
+  /// ```
+  Token parseReturnStatement(Token token) {
+    Token begin = token = token.next;
+    assert(optional('return', token));
+    listener.beginReturnStatement(begin);
+    Token next = token.next;
+    if (optional(';', next)) {
+      listener.endReturnStatement(false, begin, next);
+      return next;
+    }
+    token = parseExpression(token);
+    token = ensureSemicolon(token);
+    listener.endReturnStatement(true, begin, token);
+    if (inGenerator) {
+      listener.handleInvalidStatement(
+          begin, codes.messageGeneratorReturnsValue);
+    }
+    return token;
+  }
+
+  /// ```
+  /// label:
+  ///   identifier ':'
+  /// ;
+  /// ```
+  Token parseLabel(Token token) {
+    assert(token.next.isIdentifier);
+    token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next;
+    assert(optional(':', token));
+    listener.handleLabel(token);
+    return token;
+  }
+
+  /// ```
+  /// statement:
+  ///   label* nonLabelledStatement
+  /// ;
+  /// ```
+  Token parseLabeledStatement(Token token) {
+    Token next = token.next;
+    assert(next.isIdentifier);
+    assert(optional(':', next.next));
+    int labelCount = 0;
+    do {
+      token = parseLabel(token);
+      next = token.next;
+      labelCount++;
+    } while (next.isIdentifier && optional(':', next.next));
+    listener.beginLabeledStatement(next, labelCount);
+    token = parseStatement(token);
+    listener.endLabeledStatement(labelCount);
+    return token;
+  }
+
+  /// ```
+  /// expressionStatement:
+  ///   expression? ';'
+  /// ;
+  /// ```
+  ///
+  /// Note: This method can fail to make progress. If there is neither an
+  /// expression nor a semi-colon, then a synthetic identifier and synthetic
+  /// semicolon will be inserted before [token] and the semicolon will be
+  /// returned.
+  Token parseExpressionStatement(Token token) {
+    // TODO(brianwilkerson): If the next token is not the start of a valid
+    // expression, then this method shouldn't report that we have an expression
+    // statement.
+    token = parseExpression(token);
+    token = ensureSemicolon(token);
+    listener.handleExpressionStatement(token);
+    return token;
+  }
+
+  int expressionDepth = 0;
+  Token parseExpression(Token token) {
+    if (expressionDepth++ > 500) {
+      // 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;
+      reportRecoverableError(next, codes.messageStackOverflow);
+
+      // Recovery
+      Token endGroup = next.endGroup;
+      if (endGroup != null) {
+        while (!next.isEof && !identical(next, endGroup)) {
+          token = next;
+          next = token.next;
+        }
+      } else {
+        while (!isOneOf(next, const [')', ']', '}', ';'])) {
+          token = next;
+          next = token.next;
+        }
+      }
+      if (!token.isEof) {
+        token = rewriter.insertSyntheticIdentifier(token);
+        listener.handleIdentifier(token, IdentifierContext.expression);
+      }
+    } else {
+      token = optional('throw', token.next)
+          ? parseThrowExpression(token, true)
+          : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true);
+    }
+    expressionDepth--;
+    return token;
+  }
+
+  Token parseExpressionWithoutCascade(Token token) {
+    return optional('throw', token.next)
+        ? parseThrowExpression(token, false)
+        : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, false);
+  }
+
+  Token parseConditionalExpressionRest(Token token) {
+    Token question = token = token.next;
+    assert(optional('?', question));
+    listener.beginConditionalExpression(token);
+    token = parseExpressionWithoutCascade(token);
+    Token colon = ensureColon(token);
+    listener.handleConditionalExpressionColon();
+    token = parseExpressionWithoutCascade(colon);
+    listener.endConditionalExpression(question, colon);
+    return token;
+  }
+
+  Token parsePrecedenceExpression(
+      Token token, int precedence, bool allowCascades) {
+    assert(precedence >= 1);
+    assert(precedence <= SELECTOR_PRECEDENCE);
+    token = parseUnaryExpression(token, allowCascades);
+    TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
+    if (typeArg != noTypeParamOrArg) {
+      // For example a(b)<T>(c), where token is before '<'.
+      token = typeArg.parseArguments(token, this);
+      assert(optional('(', token.next));
+    }
+    Token next = token.next;
+    TokenType type = next.type;
+    int tokenLevel = _computePrecedence(next);
+    for (int level = tokenLevel; level >= precedence; --level) {
+      int lastBinaryExpressionLevel = -1;
+      Token lastCascade;
+      while (identical(tokenLevel, level)) {
+        Token operator = next;
+        if (identical(tokenLevel, CASCADE_PRECEDENCE)) {
+          if (!allowCascades) {
+            return token;
+          } else if (lastCascade != null && optional('?..', next)) {
+            reportRecoverableError(
+                next, codes.messageNullAwareCascadeOutOfOrder);
+          }
+          lastCascade = next;
+          token = parseCascadeExpression(token);
+        } 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)
+              ? parseThrowExpression(next, 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);
+            token = next;
+          } else if (identical(type, TokenType.BANG)) {
+            listener.handleNonNullAssertExpression(next);
+            token = next;
+          }
+        } else if (identical(tokenLevel, SELECTOR_PRECEDENCE)) {
+          if (identical(type, TokenType.PERIOD) ||
+              identical(type, TokenType.QUESTION_PERIOD)) {
+            // Left associative, so we recurse at the next higher precedence
+            // level. However, SELECTOR_PRECEDENCE is the highest level, so we
+            // should just call [parseUnaryExpression] directly. However, a
+            // unary expression isn't legal after a period, so we call
+            // [parsePrimary] instead.
+            token = parsePrimary(
+                token.next, IdentifierContext.expressionContinuation);
+            listener.endBinaryExpression(operator);
+          } else if (identical(type, TokenType.OPEN_PAREN) ||
+              identical(type, TokenType.OPEN_SQUARE_BRACKET) ||
+              identical(type, TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET)) {
+            token = parseArgumentOrIndexStar(token, typeArg);
+          } else if (identical(type, TokenType.INDEX)) {
+            BeginToken replacement = link(
+                new BeginToken(TokenType.OPEN_SQUARE_BRACKET, next.charOffset,
+                    next.precedingComments),
+                new Token(TokenType.CLOSE_SQUARE_BRACKET, next.charOffset + 1));
+            rewriter.replaceTokenFollowing(token, replacement);
+            replacement.endToken = replacement.next;
+            token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
+          } else if (identical(type, TokenType.BANG)) {
+            listener.handleNonNullAssertExpression(token.next);
+            token = next;
+          } else {
+            // Recovery
+            reportRecoverableErrorWithToken(
+                token.next, codes.templateUnexpectedToken);
+            token = next;
+          }
+        } else if (identical(type, TokenType.IS)) {
+          token = parseIsOperatorRest(token);
+        } else if (identical(type, TokenType.AS)) {
+          token = parseAsOperatorRest(token);
+        } else if (identical(type, TokenType.QUESTION)) {
+          token = parseConditionalExpressionRest(token);
+        } else {
+          if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) {
+            // We don't allow (a == b == c) or (a < b < c).
+            if (lastBinaryExpressionLevel == level) {
+              // Report an error, then continue parsing as if it is legal.
+              reportRecoverableError(
+                  next, codes.messageEqualityCannotBeEqualityOperand);
+            } else {
+              // Set a flag to catch subsequent binary expressions of this type.
+              lastBinaryExpressionLevel = level;
+            }
+          }
+          listener.beginBinaryExpression(next);
+          // Left associative, so we recurse at the next higher
+          // precedence level.
+          token =
+              parsePrecedenceExpression(token.next, level + 1, allowCascades);
+          listener.endBinaryExpression(operator);
+        }
+        next = token.next;
+        type = next.type;
+        tokenLevel = _computePrecedence(next);
+      }
+    }
+    return token;
+  }
+
+  int _computePrecedence(Token token) {
+    TokenType type = token.type;
+    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;
+      if (identical(nextType, TokenType.PERIOD) ||
+          identical(nextType, TokenType.OPEN_PAREN) ||
+          identical(nextType, TokenType.OPEN_SQUARE_BRACKET)) {
+        return SELECTOR_PRECEDENCE;
+      }
+      return POSTFIX_PRECEDENCE;
+    }
+    return type.precedence;
+  }
+
+  Token parseCascadeExpression(Token token) {
+    Token cascadeOperator = token = token.next;
+    assert(optional('..', cascadeOperator) || optional('?..', cascadeOperator));
+    listener.beginCascade(cascadeOperator);
+    if (optional('[', token.next)) {
+      token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
+    } else {
+      token = parseSend(token, IdentifierContext.expressionContinuation);
+      listener.endBinaryExpression(cascadeOperator);
+    }
+    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;
+        listener.endBinaryExpression(period);
+      }
+      TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
+      if (typeArg != noTypeParamOrArg) {
+        // For example a(b)..<T>(c), where token is '<'.
+        token = typeArg.parseArguments(token, this);
+        next = token.next;
+        assert(optional('(', next));
+      }
+      token = parseArgumentOrIndexStar(token, typeArg);
+      next = token.next;
+    } while (!identical(mark, token));
+
+    if (identical(next.type.precedence, ASSIGNMENT_PRECEDENCE)) {
+      Token assignment = next;
+      token = parseExpressionWithoutCascade(next);
+      listener.handleAssignmentExpression(assignment);
+    }
+    listener.endCascade();
+    return token;
+  }
+
+  Token parseUnaryExpression(Token token, bool allowCascades) {
+    String value = token.next.stringValue;
+    // Prefix:
+    if (identical(value, 'await')) {
+      if (inPlainSync) {
+        if (!looksLikeAwaitExpression(token)) {
+          return parsePrimary(token, IdentifierContext.expression);
+        }
+        // Recovery: Looks like an expression preceded by `await`.
+        // Fall through and let parseAwaitExpression report the error.
+      }
+      return parseAwaitExpression(token, allowCascades);
+    } else if (identical(value, '+')) {
+      // Dart no longer allows prefix-plus.
+      rewriteAndRecover(
+          token,
+          // TODO(danrubel): Consider reporting "missing identifier" instead.
+          codes.messageUnsupportedPrefixPlus,
+          new SyntheticStringToken(
+              TokenType.IDENTIFIER, '', token.next.offset));
+      return parsePrimary(token, IdentifierContext.expression);
+    } else if ((identical(value, '!')) ||
+        (identical(value, '-')) ||
+        (identical(value, '~'))) {
+      Token operator = token.next;
+      // Right associative, so we recurse at the same precedence
+      // level.
+      token = parsePrecedenceExpression(
+          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;
+      // Right associative, so we recurse at the same precedence
+      // level.
+      token = parsePrecedenceExpression(
+          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;
+      }
+      if (identifier.isIdentifier) {
+        // Looking at `identifier ('.' identifier)?`.
+        if (optional("<", identifier.next)) {
+          TypeParamOrArgInfo typeArg = computeTypeParamOrArg(identifier);
+          if (typeArg != noTypeParamOrArg) {
+            Token endTypeArguments = typeArg.skip(identifier);
+            if (optional(".", endTypeArguments.next)) {
+              return parseImplicitCreationExpression(token, typeArg);
+            }
+          }
+        }
+      }
+    }
+    return parsePrimary(token, IdentifierContext.expression);
+  }
+
+  Token parseArgumentOrIndexStar(Token token, TypeParamOrArgInfo typeArg) {
+    Token next = token.next;
+    Token beginToken = next;
+    while (true) {
+      if (optional('[', next) || optional('?.[', next)) {
+        assert(typeArg == noTypeParamOrArg);
+        Token openSquareBracket = next;
+        bool old = mayParseFunctionExpressions;
+        mayParseFunctionExpressions = true;
+        token = parseExpression(next);
+        next = token.next;
+        mayParseFunctionExpressions = old;
+        if (!optional(']', next)) {
+          // Recovery
+          reportRecoverableError(
+              next, codes.templateExpectedButGot.withArguments(']'));
+          // Scanner ensures a closing ']'
+          Token endGroup = openSquareBracket.endGroup;
+          if (endGroup.isSynthetic) {
+            // Scanner inserted closing ']' in the wrong place, so move it.
+            next = rewriter.moveSynthetic(token, endGroup);
+          } else {
+            // Skip over unexpected tokens to where the user placed the `]`.
+            next = endGroup;
+          }
+        }
+        listener.handleIndexedExpression(openSquareBracket, next);
+        token = next;
+        typeArg = computeMethodTypeArguments(token);
+        if (typeArg != noTypeParamOrArg) {
+          // For example a[b]<T>(c), where token is before '<'.
+          token = typeArg.parseArguments(token, this);
+          assert(optional('(', token.next));
+        }
+        next = token.next;
+      } else if (optional('(', next)) {
+        if (typeArg == noTypeParamOrArg) {
+          listener.handleNoTypeArguments(next);
+        }
+        token = parseArguments(token);
+        listener.handleSend(beginToken, token);
+        typeArg = computeMethodTypeArguments(token);
+        if (typeArg != noTypeParamOrArg) {
+          // For example a(b)<T>(c), where token is before '<'.
+          token = typeArg.parseArguments(token, this);
+          assert(optional('(', token.next));
+        }
+        next = token.next;
+      } else {
+        break;
+      }
+    }
+    return token;
+  }
+
+  Token parsePrimary(Token token, IdentifierContext context) {
+    final int kind = token.next.kind;
+    if (kind == IDENTIFIER_TOKEN) {
+      return parseSendOrFunctionLiteral(token, context);
+    } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) {
+      return parseLiteralInt(token);
+    } else if (kind == DOUBLE_TOKEN) {
+      return parseLiteralDouble(token);
+    } else if (kind == STRING_TOKEN) {
+      return parseLiteralString(token);
+    } else if (kind == HASH_TOKEN) {
+      return parseLiteralSymbol(token);
+    } else if (kind == KEYWORD_TOKEN) {
+      final String value = token.next.stringValue;
+      if (identical(value, "true") || identical(value, "false")) {
+        return parseLiteralBool(token);
+      } else if (identical(value, "null")) {
+        return parseLiteralNull(token);
+      } else if (identical(value, "this")) {
+        return parseThisExpression(token, context);
+      } else if (identical(value, "super")) {
+        return parseSuperExpression(token, context);
+      } else if (identical(value, "new")) {
+        return parseNewExpression(token);
+      } else if (identical(value, "const")) {
+        return parseConstExpression(token);
+      } else if (identical(value, "void")) {
+        return parseSendOrFunctionLiteral(token, context);
+      } else if (!inPlainSync &&
+          (identical(value, "yield") || identical(value, "async"))) {
+        // Fall through to the recovery code.
+      } else if (identical(value, "assert")) {
+        return parseAssert(token, Assert.Expression);
+      } else if (token.next.isIdentifier) {
+        return parseSendOrFunctionLiteral(token, context);
+      } else if (identical(value, "return")) {
+        // Recovery
+        token = token.next;
+        reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
+        return parsePrimary(token, context);
+      } else {
+        // Fall through to the recovery code.
+      }
+    } else if (kind == OPEN_PAREN_TOKEN) {
+      return parseParenthesizedExpressionOrFunctionLiteral(token);
+    } else if (kind == OPEN_SQUARE_BRACKET_TOKEN ||
+        optional('[]', token.next)) {
+      listener.handleNoTypeArguments(token.next);
+      return parseLiteralListSuffix(token, null);
+    } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
+      listener.handleNoTypeArguments(token.next);
+      return parseLiteralSetOrMapSuffix(token, null);
+    } else if (kind == LT_TOKEN) {
+      return parseLiteralListSetMapOrFunction(token, null);
+    } else {
+      // Fall through to the recovery code.
+    }
+    //
+    // Recovery code.
+    //
+    return parseSend(token, context);
+  }
+
+  Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
+    Token next = token.next;
+    assert(optional('(', next));
+    Token nextToken = next.endGroup.next;
+    int kind = nextToken.kind;
+    if (mayParseFunctionExpressions) {
+      if ((identical(kind, FUNCTION_TOKEN) ||
+          identical(kind, OPEN_CURLY_BRACKET_TOKEN))) {
+        listener.handleNoTypeVariables(next);
+        return parseFunctionExpression(token);
+      } else if (identical(kind, KEYWORD_TOKEN) ||
+          identical(kind, IDENTIFIER_TOKEN)) {
+        if (optional('async', nextToken) || optional('sync', nextToken)) {
+          listener.handleNoTypeVariables(next);
+          return parseFunctionExpression(token);
+        }
+        // Recovery
+        // 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;
+        if ((identical(kind, FUNCTION_TOKEN) ||
+            identical(kind, OPEN_CURLY_BRACKET_TOKEN))) {
+          listener.handleNoTypeVariables(next);
+          return parseFunctionExpression(token);
+        }
+      }
+    }
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    token = parseParenthesizedExpression(token);
+    mayParseFunctionExpressions = old;
+    return token;
+  }
+
+  Token ensureParenthesizedCondition(Token token) {
+    Token openParen = token.next;
+    if (!optional('(', openParen)) {
+      // Recover
+      reportRecoverableError(
+          openParen, codes.templateExpectedToken.withArguments('('));
+      openParen = rewriter.insertParens(token, false);
+    }
+    token = parseExpressionInParenthesisRest(openParen);
+    listener.handleParenthesizedCondition(openParen);
+    return token;
+  }
+
+  Token parseParenthesizedExpression(Token token) {
+    Token begin = token.next;
+    token = parseExpressionInParenthesis(token);
+    listener.handleParenthesizedExpression(begin);
+    return token;
+  }
+
+  Token parseExpressionInParenthesis(Token token) {
+    return parseExpressionInParenthesisRest(token.next);
+  }
+
+  Token parseExpressionInParenthesisRest(Token token) {
+    assert(optional('(', token));
+    BeginToken begin = token;
+    token = parseExpression(token);
+    token = ensureCloseParen(token, begin);
+    assert(optional(')', token));
+    return token;
+  }
+
+  Token parseThisExpression(Token token, IdentifierContext context) {
+    Token thisToken = token = token.next;
+    assert(optional('this', thisToken));
+    listener.handleThisExpression(thisToken, context);
+    Token next = token.next;
+    if (optional('(', next)) {
+      // Constructor forwarding.
+      listener.handleNoTypeArguments(next);
+      token = parseArguments(token);
+      listener.handleSend(thisToken, token.next);
+    }
+    return token;
+  }
+
+  Token parseSuperExpression(Token token, IdentifierContext context) {
+    Token superToken = token = token.next;
+    assert(optional('super', token));
+    listener.handleSuperExpression(superToken, context);
+    Token next = token.next;
+    if (optional('(', next)) {
+      // Super constructor.
+      listener.handleNoTypeArguments(next);
+      token = parseArguments(token);
+      listener.handleSend(superToken, token.next);
+    } else if (optional("?.", next)) {
+      reportRecoverableError(next, codes.messageSuperNullAware);
+    }
+    return token;
+  }
+
+  /// This method parses the portion of a list literal starting with the left
+  /// square bracket.
+  ///
+  /// ```
+  /// listLiteral:
+  ///   'const'? typeArguments? '[' (expressionList ','?)? ']'
+  /// ;
+  /// ```
+  ///
+  /// 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 beforeToken = token;
+    Token beginToken = token = token.next;
+    assert(optional('[', token) || optional('[]', token));
+    int count = 0;
+    if (optional('[]', token)) {
+      token = rewriteSquareBrackets(beforeToken).next;
+      listener.handleLiteralList(0, token, constKeyword, token.next);
+      return token.next;
+    }
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    while (true) {
+      Token next = token.next;
+      if (optional(']', next)) {
+        token = next;
+        break;
+      }
+      int ifCount = 0;
+      LiteralEntryInfo info = computeLiteralEntry(token);
+      while (info != null) {
+        if (info.hasEntry) {
+          token = parseExpression(token);
+        } else {
+          token = info.parse(token, this);
+        }
+        ifCount += info.ifConditionDelta;
+        info = info.computeNext(token);
+      }
+      next = token.next;
+      ++count;
+      if (!optional(',', next)) {
+        if (optional(']', next)) {
+          token = next;
+          break;
+        }
+
+        // Recovery
+        if (!looksLikeLiteralEntry(next)) {
+          if (beginToken.endGroup.isSynthetic) {
+            // The scanner has already reported an error,
+            // but inserted `]` in the wrong place.
+            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;
+          }
+          break;
+        }
+        // This looks like the start of an expression.
+        // Report an error, insert the comma, and continue parsing.
+        SyntheticToken comma = new SyntheticToken(TokenType.COMMA, next.offset);
+        Message message = ifCount > 0
+            ? codes.messageExpectedElseOrComma
+            : codes.templateExpectedButGot.withArguments(',');
+        next = rewriteAndRecover(token, message, comma);
+      }
+      token = next;
+    }
+    mayParseFunctionExpressions = old;
+    listener.handleLiteralList(count, beginToken, constKeyword, token);
+    return token;
+  }
+
+  /// 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;
+    assert(optional('{', leftBrace));
+    Token next = token.next;
+    if (optional('}', next)) {
+      listener.handleLiteralSetOrMap(0, leftBrace, constKeyword, next, false);
+      return next;
+    }
+
+    final bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    int count = 0;
+    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+    // behavior and will be removed once unified collection has been enabled
+    bool hasSetEntry;
+
+    while (true) {
+      int ifCount = 0;
+      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);
+        hasSetEntry ??= !isMapEntry;
+        if (isMapEntry) {
+          Token colon = token.next;
+          token = parseExpression(colon);
+          listener.handleLiteralMapEntry(colon, token.next);
+        }
+      } else {
+        while (info != null) {
+          if (info.hasEntry) {
+            token = parseExpression(token);
+            if (optional(':', token.next)) {
+              Token colon = token.next;
+              token = parseExpression(colon);
+              listener.handleLiteralMapEntry(colon, token.next);
+            }
+          } else {
+            token = info.parse(token, this);
+          }
+          ifCount += info.ifConditionDelta;
+          info = info.computeNext(token);
+        }
+      }
+      ++count;
+      next = token.next;
+
+      Token comma;
+      if (optional(',', next)) {
+        comma = token = next;
+        next = token.next;
+      }
+      if (optional('}', next)) {
+        listener.handleLiteralSetOrMap(
+            count, leftBrace, constKeyword, next, hasSetEntry ?? false);
+        mayParseFunctionExpressions = old;
+        return next;
+      }
+
+      if (comma == null) {
+        // Recovery
+        if (looksLikeLiteralEntry(next)) {
+          // If this looks like the start of an expression,
+          // then report an error, insert the comma, and continue parsing.
+          // TODO(danrubel): Consider better error message
+          SyntheticToken comma =
+              new SyntheticToken(TokenType.COMMA, next.offset);
+          Message message = ifCount > 0
+              ? codes.messageExpectedElseOrComma
+              : codes.templateExpectedButGot.withArguments(',');
+          token = rewriteAndRecover(token, message, comma);
+        } else {
+          reportRecoverableError(
+              next, codes.templateExpectedButGot.withArguments('}'));
+          // Scanner guarantees a closing curly bracket
+          next = leftBrace.endGroup;
+          listener.handleLiteralSetOrMap(
+              count, leftBrace, constKeyword, next, hasSetEntry ?? false);
+          mayParseFunctionExpressions = old;
+          return next;
+        }
+      }
+    }
+  }
+
+  /// formalParameterList functionBody.
+  ///
+  /// 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));
+    // Scanner ensures `(` has matching `)`.
+    Token next = token.next.endGroup.next;
+    int kind = next.kind;
+    if (!identical(kind, FUNCTION_TOKEN) &&
+        !identical(kind, OPEN_CURLY_BRACKET_TOKEN) &&
+        (!identical(kind, KEYWORD_TOKEN) ||
+            !optional('async', next) && !optional('sync', next))) {
+      reportRecoverableErrorWithToken(next, codes.templateUnexpectedToken);
+    }
+    return parseFunctionExpression(token);
+  }
+
+  /// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
+  ///
+  /// Where
+  ///   genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']'
+  ///   genericMapLiteral ::=
+  ///       typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
+  ///   genericFunctionLiteral ::=
+  ///       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));
+    TypeParamOrArgInfo typeParamOrArg = computeTypeParamOrArg(start, true);
+    Token token = typeParamOrArg.skip(start);
+    if (optional('(', token.next)) {
+      if (constKeyword != null) {
+        reportRecoverableErrorWithToken(
+            constKeyword, codes.templateUnexpectedToken);
+      }
+      token = typeParamOrArg.parseVariables(start, this);
+      return parseLiteralFunctionSuffix(token);
+    }
+    // Note that parseArguments can rewrite the token stream!
+    token = typeParamOrArg.parseArguments(start, this);
+    Token next = token.next;
+    if (optional('{', next)) {
+      if (typeParamOrArg.typeArgumentCount > 2) {
+        listener.handleRecoverableError(
+            codes.messageSetOrMapLiteralTooManyTypeArguments,
+            start.next,
+            token);
+      }
+      return parseLiteralSetOrMapSuffix(token, constKeyword);
+    }
+    if (!optional('[', next) && !optional('[]', next)) {
+      // TODO(danrubel): Improve this error message.
+      reportRecoverableError(
+          next, codes.templateExpectedButGot.withArguments('['));
+      rewriter.insertSyntheticToken(token, TokenType.INDEX);
+    }
+    return parseLiteralListSuffix(token, constKeyword);
+  }
+
+  /// ```
+  /// mapLiteralEntry:
+  ///   expression ':' expression |
+  ///   'if' '(' expression ')' mapLiteralEntry ( 'else' mapLiteralEntry )? |
+  ///   'await'? 'for' '(' forLoopParts ')' mapLiteralEntry |
+  ///   ( '...' | '...?' ) expression
+  /// ;
+  /// ```
+  Token parseMapLiteralEntry(Token token) {
+    // 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);
+    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);
+      } else {
+        token = info.parse(token, this);
+      }
+      info = info.computeNext(token);
+    }
+    return token;
+  }
+
+  Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) {
+    if (!mayParseFunctionExpressions) {
+      return parseSend(token, context);
+    }
+    TypeInfo typeInfo = computeType(token, false);
+    Token beforeName = typeInfo.skipType(token);
+    Token name = beforeName.next;
+    if (name.isIdentifier) {
+      TypeParamOrArgInfo typeParam = computeTypeParamOrArg(name);
+      Token next = typeParam.skip(name).next;
+      if (optional('(', next)) {
+        if (looksLikeFunctionBody(next.endGroup.next)) {
+          return parseFunctionLiteral(
+              token, beforeName, name, typeInfo, typeParam, context);
+        }
+      }
+    }
+    return parseSend(token, context);
+  }
+
+  Token ensureArguments(Token token) {
+    Token next = token.next;
+    if (!optional('(', next)) {
+      reportRecoverableError(
+          token, codes.templateExpectedAfterButGot.withArguments('('));
+      next = rewriter.insertParens(token, false);
+    }
+    return parseArgumentsRest(next);
+  }
+
+  Token parseConstructorInvocationArguments(Token token) {
+    Token next = token.next;
+    if (!optional('(', next)) {
+      // Recovery: Check for invalid type parameters
+      TypeParamOrArgInfo typeArg = computeTypeParamOrArg(token);
+      if (typeArg == noTypeParamOrArg) {
+        reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments('('));
+      } else {
+        reportRecoverableError(
+            token, codes.messageConstructorWithTypeArguments);
+        token = typeArg.parseArguments(token, this);
+        listener.handleInvalidTypeArguments(token);
+        next = token.next;
+      }
+      if (!optional('(', next)) {
+        next = rewriter.insertParens(token, false);
+      }
+    }
+    return parseArgumentsRest(next);
+  }
+
+  /// ```
+  /// newExpression:
+  ///   'new' type ('.' identifier)? arguments
+  /// ;
+  /// ```
+  Token parseNewExpression(Token token) {
+    Token newKeyword = token.next;
+    assert(optional('new', newKeyword));
+    listener.beginNewExpression(newKeyword);
+    token = parseConstructorReference(newKeyword);
+    token = parseConstructorInvocationArguments(token);
+    listener.endNewExpression(newKeyword);
+    return token;
+  }
+
+  Token parseImplicitCreationExpression(
+      Token token, TypeParamOrArgInfo typeArg) {
+    Token begin = token;
+    listener.beginImplicitCreationExpression(token);
+    token = parseConstructorReference(token, typeArg);
+    token = parseConstructorInvocationArguments(token);
+    listener.endImplicitCreationExpression(begin);
+    return token;
+  }
+
+  /// This method parses a list or map literal that is known to start with the
+  /// keyword 'const'.
+  ///
+  /// ```
+  /// listLiteral:
+  ///   'const'? typeArguments? '[' (expressionList ','?)? ']'
+  /// ;
+  ///
+  /// mapLiteral:
+  ///   'const'? typeArguments?
+  ///     '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
+  /// ;
+  ///
+  /// mapLiteralEntry:
+  ///   expression ':' expression
+  /// ;
+  /// ```
+  Token parseConstExpression(Token token) {
+    Token constKeyword = token = token.next;
+    assert(optional('const', constKeyword));
+    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);
+      return token;
+    }
+    if (identical(value, '{')) {
+      listener.beginConstLiteral(next);
+      listener.handleNoTypeArguments(next);
+      token = parseLiteralSetOrMapSuffix(token, constKeyword);
+      listener.endConstLiteral(token.next);
+      return token;
+    }
+    if (identical(value, '<')) {
+      listener.beginConstLiteral(next);
+      token = parseLiteralListSetMapOrFunction(token, constKeyword);
+      listener.endConstLiteral(token.next);
+      return token;
+    }
+    listener.beginConstExpression(constKeyword);
+    token = parseConstructorReference(token);
+    token = parseConstructorInvocationArguments(token);
+    listener.endConstExpression(constKeyword);
+    return token;
+  }
+
+  /// ```
+  /// intLiteral:
+  ///   integer
+  /// ;
+  /// ```
+  Token parseLiteralInt(Token token) {
+    token = token.next;
+    assert(identical(token.kind, INT_TOKEN) ||
+        identical(token.kind, HEXADECIMAL_TOKEN));
+    listener.handleLiteralInt(token);
+    return token;
+  }
+
+  /// ```
+  /// doubleLiteral:
+  ///   double
+  /// ;
+  /// ```
+  Token parseLiteralDouble(Token token) {
+    token = token.next;
+    assert(identical(token.kind, DOUBLE_TOKEN));
+    listener.handleLiteralDouble(token);
+    return token;
+  }
+
+  /// ```
+  /// stringLiteral:
+  ///   (multilineString | singleLineString)+
+  /// ;
+  /// ```
+  Token parseLiteralString(Token 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)) {
+      token = parseSingleLiteralString(token);
+      count++;
+    }
+    if (count > 1) {
+      listener.handleStringJuxtaposition(count);
+    }
+    mayParseFunctionExpressions = old;
+    return token;
+  }
+
+  /// ```
+  /// symbolLiteral:
+  ///   '#' (operator | (identifier ('.' identifier)*))
+  /// ;
+  /// ```
+  Token parseLiteralSymbol(Token token) {
+    Token hashToken = token = token.next;
+    assert(optional('#', hashToken));
+    listener.beginLiteralSymbol(hashToken);
+    Token next = token.next;
+    if (next.isUserDefinableOperator) {
+      listener.handleOperator(next);
+      listener.endLiteralSymbol(hashToken, 1);
+      return next;
+    } else if (optional('void', next)) {
+      listener.handleSymbolVoid(next);
+      listener.endLiteralSymbol(hashToken, 1);
+      return next;
+    } else {
+      int count = 1;
+      token = ensureIdentifier(token, IdentifierContext.literalSymbol);
+      while (optional('.', token.next)) {
+        count++;
+        token = ensureIdentifier(
+            token.next, IdentifierContext.literalSymbolContinuation);
+      }
+      listener.endLiteralSymbol(hashToken, count);
+      return token;
+    }
+  }
+
+  Token parseSingleLiteralString(Token token) {
+    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;
+    int kind = next.kind;
+    while (kind != EOF_TOKEN) {
+      if (identical(kind, STRING_INTERPOLATION_TOKEN)) {
+        // Parsing ${expression}.
+        token = parseExpression(next).next;
+        if (!optional('}', token)) {
+          reportRecoverableError(
+              token, codes.templateExpectedButGot.withArguments('}'));
+          token = next.endGroup;
+        }
+        listener.handleInterpolationExpression(next, token);
+      } else if (identical(kind, STRING_INTERPOLATION_IDENTIFIER_TOKEN)) {
+        // Parsing $identifier.
+        token = parseIdentifierExpression(next);
+        listener.handleInterpolationExpression(next, null);
+      } else {
+        break;
+      }
+      ++interpolationCount;
+      // Parsing the infix/suffix, for instance y and z' of 'x${id}y${id}z'
+      token = parseStringPart(token);
+      next = token.next;
+      kind = next.kind;
+    }
+    listener.endLiteralString(interpolationCount, next);
+    return token;
+  }
+
+  Token parseIdentifierExpression(Token token) {
+    Token next = token.next;
+    if (next.kind == KEYWORD_TOKEN && identical(next.stringValue, "this")) {
+      listener.handleThisExpression(next, IdentifierContext.expression);
+      return next;
+    } else {
+      return parseSend(token, IdentifierContext.expression);
+    }
+  }
+
+  /// ```
+  /// booleanLiteral:
+  ///   'true' |
+  ///   'false'
+  /// ;
+  /// ```
+  Token parseLiteralBool(Token token) {
+    token = token.next;
+    assert(optional('false', token) || optional('true', token));
+    listener.handleLiteralBool(token);
+    return token;
+  }
+
+  /// ```
+  /// nullLiteral:
+  ///   'null'
+  /// ;
+  /// ```
+  Token parseLiteralNull(Token token) {
+    token = token.next;
+    assert(optional('null', token));
+    listener.handleLiteralNull(token);
+    return token;
+  }
+
+  Token parseSend(Token token, IdentifierContext context) {
+    Token beginToken = token = ensureIdentifier(token, context);
+    TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
+    if (typeArg != noTypeParamOrArg) {
+      token = typeArg.parseArguments(token, this);
+    } else {
+      listener.handleNoTypeArguments(token.next);
+    }
+    token = parseArgumentsOpt(token);
+    listener.handleSend(beginToken, token.next);
+    return token;
+  }
+
+  Token skipArgumentsOpt(Token token) {
+    Token next = token.next;
+    listener.handleNoArguments(next);
+    if (optional('(', next)) {
+      return next.endGroup;
+    } else {
+      return token;
+    }
+  }
+
+  Token parseArgumentsOpt(Token token) {
+    Token next = token.next;
+    if (!optional('(', next)) {
+      listener.handleNoArguments(next);
+      return token;
+    } else {
+      return parseArguments(token);
+    }
+  }
+
+  /// ```
+  /// arguments:
+  ///   '(' (argumentList ','?)? ')'
+  /// ;
+  ///
+  /// argumentList:
+  ///   namedArgument (',' namedArgument)* |
+  ///   expressionList (',' namedArgument)*
+  /// ;
+  ///
+  /// namedArgument:
+  ///   label expression
+  /// ;
+  /// ```
+  Token parseArguments(Token token) {
+    return parseArgumentsRest(token.next);
+  }
+
+  Token parseArgumentsRest(Token token) {
+    Token begin = token;
+    assert(optional('(', begin));
+    listener.beginArguments(begin);
+    int argumentCount = 0;
+    bool hasSeenNamedArgument = false;
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+    while (true) {
+      Token next = token.next;
+      if (optional(')', next)) {
+        token = next;
+        break;
+      }
+      Token colon = null;
+      if (optional(':', next.next)) {
+        token =
+            ensureIdentifier(token, IdentifierContext.namedArgumentReference)
+                .next;
+        colon = token;
+        hasSeenNamedArgument = true;
+      } else if (hasSeenNamedArgument) {
+        // Positional argument after named argument.
+        reportRecoverableError(next, codes.messagePositionalAfterNamedArgument);
+      }
+      token = parseExpression(token);
+      next = token.next;
+      if (colon != null) listener.handleNamedArgument(colon);
+      ++argumentCount;
+      if (!optional(',', next)) {
+        if (optional(')', next)) {
+          token = next;
+          break;
+        }
+        // Recovery
+        if (looksLikeExpressionStart(next)) {
+          // If this looks like the start of an expression,
+          // then report an error, insert the comma, and continue parsing.
+          next = rewriteAndRecover(
+              token,
+              codes.templateExpectedButGot.withArguments(','),
+              new SyntheticToken(TokenType.COMMA, next.offset));
+        } else {
+          token = ensureCloseParen(token, begin);
+          break;
+        }
+      }
+      token = next;
+    }
+    assert(optional(')', token));
+    mayParseFunctionExpressions = old;
+    listener.endArguments(argumentCount, begin, token);
+    return token;
+  }
+
+  /// ```
+  /// typeTest::
+  ///   'is' '!'? type
+  /// ;
+  /// ```
+  Token parseIsOperatorRest(Token token) {
+    Token operator = token = token.next;
+    assert(optional('is', operator));
+    Token not = null;
+    if (optional('!', token.next)) {
+      not = token = token.next;
+    }
+    TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
+    token = typeInfo.ensureTypeNotVoid(token, this);
+    listener.handleIsOperator(operator, not);
+    return skipChainedAsIsOperators(token);
+  }
+
+  TypeInfo computeTypeAfterIsOrAs(Token token) {
+    TypeInfo typeInfo = computeType(token, true);
+    if (typeInfo.isNullable) {
+      Token next = typeInfo.skipType(token).next;
+      if (!isOneOfOrEof(next, const [')', '?', ';', 'is', 'as'])) {
+        // TODO(danrubel): investigate other situations
+        // where `?` should be considered part of the type info
+        // rather than the start of a conditional expression.
+        typeInfo = typeInfo.asNonNullable;
+      }
+    }
+    return typeInfo;
+  }
+
+  /// ```
+  /// typeCast:
+  ///   'as' type
+  /// ;
+  /// ```
+  Token parseAsOperatorRest(Token token) {
+    Token operator = token = token.next;
+    assert(optional('as', operator));
+    TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
+    token = typeInfo.ensureTypeNotVoid(token, this);
+    listener.handleAsOperator(operator);
+    return skipChainedAsIsOperators(token);
+  }
+
+  Token skipChainedAsIsOperators(Token token) {
+    while (true) {
+      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;
+      }
+      TypeInfo typeInfo = computeTypeAfterIsOrAs(next);
+      token = typeInfo.skipType(next);
+      next = token.next;
+      value = next.stringValue;
+    }
+  }
+
+  /// Returns true if [token] could be the start of a function declaration
+  /// without a return type.
+  bool looksLikeLocalFunction(Token token) {
+    if (token.isIdentifier) {
+      if (optional('<', token.next)) {
+        TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token);
+        if (typeParam == noTypeParamOrArg) {
+          return false;
+        }
+        token = typeParam.skip(token);
+      }
+      token = token.next;
+      if (optional('(', token)) {
+        token = token.endGroup.next;
+        return optional('{', token) ||
+            optional('=>', token) ||
+            optional('async', token) ||
+            optional('sync', token);
+      } else if (optional('=>', token)) {
+        // Recovery: Looks like a local function that is missing parenthesis.
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Returns true if [token] could be the start of a function body.
+  bool looksLikeFunctionBody(Token token) {
+    return optional('{', token) ||
+        optional('=>', token) ||
+        optional('async', token) ||
+        optional('sync', token);
+  }
+
+  Token parseExpressionStatementOrConstDeclaration(final Token start) {
+    Token constToken = start.next;
+    assert(optional('const', constToken));
+    if (!isModifier(constToken.next)) {
+      TypeInfo typeInfo = computeType(constToken, false);
+      if (typeInfo == noType) {
+        Token next = constToken.next;
+        if (!next.isIdentifier) {
+          return parseExpressionStatement(start);
+        }
+        next = next.next;
+        if (!(optional('=', next) ||
+            // Recovery
+            next.isKeywordOrIdentifier ||
+            optional(';', next) ||
+            optional(',', next) ||
+            optional('{', next))) {
+          return parseExpressionStatement(start);
+        }
+      }
+      return parseExpressionStatementOrDeclarationAfterModifiers(
+          constToken, start, null, constToken, typeInfo, false);
+    }
+    return parseExpressionStatementOrDeclaration(start);
+  }
+
+  /// This method has two modes based upon [onlyParseVariableDeclarationStart].
+  ///
+  /// If [onlyParseVariableDeclarationStart] is `false` (the default) then this
+  /// method will parse a local variable declaration, a local function,
+  /// or an expression statement, and then return the last consumed token.
+  ///
+  /// If [onlyParseVariableDeclarationStart] is `true` then this method
+  /// will only parse the metadata, modifiers, and type of a local variable
+  /// declaration if it exists. It is the responsibility of the caller to
+  /// call [parseVariablesDeclarationRest] to finish parsing the local variable
+  /// declaration. If a local variable declaration is not found then this
+  /// method will return [start].
+  Token parseExpressionStatementOrDeclaration(final Token start,
+      [bool onlyParseVariableDeclarationStart = false]) {
+    Token token = start;
+    Token next = token.next;
+    if (optional('@', next)) {
+      token = parseMetadataStar(token);
+      next = token.next;
+    }
+
+    Token lateToken;
+    Token varFinalOrConst;
+
+    if (isModifier(next)) {
+      if (optional('var', next) ||
+          optional('final', next) ||
+          optional('const', next)) {
+        varFinalOrConst = token = token.next;
+        next = token.next;
+      } else if (optional('late', next)) {
+        lateToken = token = next;
+        next = token.next;
+        if (isModifier(next) &&
+            (optional('var', next) || optional('final', next))) {
+          varFinalOrConst = token = next;
+          next = token.next;
+        }
+      }
+
+      if (isModifier(next)) {
+        // Recovery
+        ModifierRecoveryContext context = new ModifierRecoveryContext(this)
+          ..lateToken = lateToken
+          ..varFinalOrConst = varFinalOrConst;
+
+        token = context.parseVariableDeclarationModifiers(token);
+        next = token.next;
+
+        lateToken = context.lateToken;
+        varFinalOrConst = context.varFinalOrConst;
+
+        context = null;
+      }
+    }
+
+    return parseExpressionStatementOrDeclarationAfterModifiers(token, start,
+        lateToken, varFinalOrConst, null, onlyParseVariableDeclarationStart);
+  }
+
+  /// See [parseExpressionStatementOrDeclaration]
+  Token parseExpressionStatementOrDeclarationAfterModifiers(
+      final Token beforeType,
+      final Token start,
+      final Token lateToken,
+      Token varFinalOrConst,
+      TypeInfo typeInfo,
+      bool onlyParseVariableDeclarationStart) {
+    typeInfo ??= computeType(beforeType, false);
+
+    Token token = typeInfo.skipType(beforeType);
+    Token next = token.next;
+
+    if (onlyParseVariableDeclarationStart) {
+      if (lateToken != null) {
+        reportRecoverableErrorWithToken(
+            lateToken, codes.templateExtraneousModifier);
+      }
+    } else {
+      if (looksLikeLocalFunction(next)) {
+        // Parse a local function declaration.
+        if (varFinalOrConst != null) {
+          reportRecoverableErrorWithToken(
+              varFinalOrConst, codes.templateExtraneousModifier);
+        } else if (lateToken != null) {
+          reportRecoverableErrorWithToken(
+              lateToken, codes.templateExtraneousModifier);
+        }
+        if (!optional('@', start.next)) {
+          listener.beginMetadataStar(start.next);
+          listener.endMetadataStar(0);
+        }
+        Token beforeFormals =
+            computeTypeParamOrArg(next).parseVariables(next, this);
+        listener.beginLocalFunctionDeclaration(start.next);
+        token = typeInfo.parseType(beforeType, this);
+        return parseNamedFunctionRest(token, start.next, beforeFormals, false);
+      }
+    }
+
+    if (beforeType == start &&
+        typeInfo.isNullable &&
+        typeInfo.couldBeExpression) {
+      assert(optional('?', token));
+      assert(next.isKeywordOrIdentifier);
+      if (!next.isIdentifier) {
+        reportRecoverableError(
+            next, codes.templateExpectedIdentifier.withArguments(next));
+        next = rewriter.insertSyntheticIdentifier(next);
+      }
+      Token afterIdentifier = next.next;
+      //
+      // found <typeref> `?` <identifier>
+      // with no annotations or modifiers preceeding it
+      //
+      if (optional('=', afterIdentifier)) {
+        //
+        // look past the next expression
+        // to determine if this is part of a conditional expression
+        //
+        Listener originalListener = listener;
+        listener = new ForwardingListener();
+        // TODO(danrubel): consider using TokenStreamGhostWriter here
+        Token afterExpression =
+            parseExpressionWithoutCascade(afterIdentifier).next;
+        listener = originalListener;
+
+        if (optional(':', afterExpression)) {
+          // Looks like part of a conditional expression.
+          // Drop the type information and reset the last consumed token.
+          typeInfo = noType;
+          token = start;
+          next = token.next;
+        }
+      } else if (!afterIdentifier.isKeyword &&
+          !isOneOfOrEof(afterIdentifier, const [';', ',', ')'])) {
+        // Looks like part of a conditional expression.
+        // Drop the type information and reset the last consumed token.
+        typeInfo = noType;
+        token = start;
+        next = token.next;
+      }
+    }
+
+    if (token == start) {
+      // If no annotation, modifier, or type, and this is not a local function
+      // then this must be an expression statement.
+      if (onlyParseVariableDeclarationStart) {
+        return start;
+      } else {
+        return parseExpressionStatement(start);
+      }
+    }
+
+    if (next.type.isBuiltIn &&
+        beforeType == start &&
+        typeInfo.couldBeExpression) {
+      // Detect expressions such as identifier `as` identifier
+      // and treat those as expressions.
+      if (optional('as', next) || optional('is', next)) {
+        int kind = next.next.kind;
+        if (EQ_TOKEN != kind &&
+            SEMICOLON_TOKEN != kind &&
+            COMMA_TOKEN != kind) {
+          if (onlyParseVariableDeclarationStart) {
+            if (!optional('in', next.next)) {
+              return start;
+            }
+          } else {
+            return parseExpressionStatement(start);
+          }
+        }
+      }
+    }
+
+    if (next.isIdentifier) {
+      // Only report these errors if there is an identifier. If there is not an
+      // identifier, then allow ensureIdentifier to report an error
+      // and don't report errors here.
+      if (varFinalOrConst == null) {
+        if (typeInfo == noType && lateToken == null) {
+          reportRecoverableError(next, codes.messageMissingConstFinalVarOrType);
+        }
+      } else if (optional('var', varFinalOrConst)) {
+        if (typeInfo != noType) {
+          reportRecoverableError(varFinalOrConst, codes.messageTypeAfterVar);
+        }
+      }
+    }
+
+    if (!optional('@', start.next)) {
+      listener.beginMetadataStar(start.next);
+      listener.endMetadataStar(0);
+    }
+    token = typeInfo.parseType(beforeType, this);
+    next = token.next;
+    listener.beginVariablesDeclaration(next, lateToken, varFinalOrConst);
+    if (!onlyParseVariableDeclarationStart) {
+      token = parseVariablesDeclarationRest(token, true);
+    }
+    return token;
+  }
+
+  Token parseVariablesDeclarationRest(Token token, bool endWithSemicolon) {
+    int count = 1;
+    token = parseOptionallyInitializedIdentifier(token);
+    while (optional(',', token.next)) {
+      token = parseOptionallyInitializedIdentifier(token.next);
+      ++count;
+    }
+    if (endWithSemicolon) {
+      Token semicolon = ensureSemicolon(token);
+      listener.endVariablesDeclaration(count, semicolon);
+      return semicolon;
+    } else {
+      listener.endVariablesDeclaration(count, null);
+      return token;
+    }
+  }
+
+  Token parseOptionallyInitializedIdentifier(Token token) {
+    Token nameToken =
+        ensureIdentifier(token, IdentifierContext.localVariableDeclaration);
+    listener.beginInitializedIdentifier(nameToken);
+    token = parseVariableInitializerOpt(nameToken);
+    listener.endInitializedIdentifier(nameToken);
+    return token;
+  }
+
+  /// ```
+  /// ifStatement:
+  ///   'if' '(' expression ')' statement ('else' statement)?
+  /// ;
+  /// ```
+  Token parseIfStatement(Token token) {
+    Token ifToken = token.next;
+    assert(optional('if', ifToken));
+    listener.beginIfStatement(ifToken);
+    token = ensureParenthesizedCondition(ifToken);
+    listener.beginThenStatement(token.next);
+    token = parseStatement(token);
+    listener.endThenStatement(token);
+    Token elseToken = null;
+    if (optional('else', token.next)) {
+      elseToken = token.next;
+      listener.beginElseStatement(elseToken);
+      token = parseStatement(elseToken);
+      listener.endElseStatement(elseToken);
+    }
+    listener.endIfStatement(ifToken, elseToken);
+    return token;
+  }
+
+  /// ```
+  /// forStatement:
+  ///   'await'? 'for' '(' forLoopParts ')' statement
+  /// ;
+  ///
+  ///  forLoopParts:
+  ///      localVariableDeclaration ';' expression? ';' expressionList?
+  ///    | expression? ';' expression? ';' expressionList?
+  ///    | localVariableDeclaration 'in' expression
+  ///    | identifier 'in' expression
+  /// ;
+  ///
+  /// forInitializerStatement:
+  ///   localVariableDeclaration |
+  ///   expression? ';'
+  /// ;
+  /// ```
+  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 = parseForLoopPartsMid(token, awaitToken, forToken);
+    if (optional('in', token.next) || optional(':', token.next)) {
+      // Process `for ( ... in ... )`
+      return parseForInRest(token, awaitToken, forToken, identifier);
+    } else {
+      // Process `for ( ... ; ... ; ... )`
+      return parseForRest(awaitToken, token, forToken);
+    }
+  }
+
+  /// 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;
+    if (!optional('(', leftParenthesis)) {
+      // Recovery
+      reportRecoverableError(
+          leftParenthesis, codes.templateExpectedButGot.withArguments('('));
+
+      BeginToken openParen = rewriter.insertToken(
+          forToken,
+          new SyntheticBeginToken(
+              TokenType.OPEN_PAREN, leftParenthesis.offset));
+
+      Token token;
+      if (awaitToken != null) {
+        token = rewriter.insertSyntheticIdentifier(openParen);
+        token = rewriter.insertSyntheticKeyword(token, Keyword.IN);
+        token = rewriter.insertSyntheticIdentifier(token);
+      } else {
+        token = rewriter.insertSyntheticToken(openParen, TokenType.SEMICOLON);
+        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+      }
+
+      openParen.endGroup = token = rewriter.insertToken(token,
+          new SyntheticToken(TokenType.CLOSE_PAREN, leftParenthesis.offset));
+
+      token = rewriter.insertSyntheticIdentifier(token);
+      rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+
+      leftParenthesis = openParen;
+    }
+
+    // Pass `true` so that the [parseExpressionStatementOrDeclaration] only
+    // parses the metadata, modifiers, and type of a local variable
+    // declaration if it exists. This enables capturing [beforeIdentifier]
+    // for later error reporting.
+    return parseExpressionStatementOrDeclaration(leftParenthesis, true);
+  }
+
+  /// 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) {
+    if (token != forToken.next) {
+      token = parseVariablesDeclarationRest(token, false);
+      listener.handleForInitializerLocalVariableDeclaration(
+          token, optional('in', 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) ||
+              // If this is an empty `await for`, we rewrite it into an
+              // `await for (_ in _)`.
+              (awaitToken != null && optional(')', token.next)));
+    }
+    Token next = token.next;
+    if (optional(';', next)) {
+      if (awaitToken != null) {
+        reportRecoverableError(awaitToken, codes.messageInvalidAwaitFor);
+      }
+    } else if (!optional('in', next)) {
+      // Recovery
+      if (optional(':', next)) {
+        reportRecoverableError(next, codes.messageColonInPlaceOfIn);
+      } else if (awaitToken != null) {
+        reportRecoverableError(
+            next, codes.templateExpectedButGot.withArguments('in'));
+        token.setNext(
+            new SyntheticKeywordToken(Keyword.IN, next.offset)..setNext(next));
+      }
+    }
+    return token;
+  }
+
+  /// This method parses the portion of the forLoopParts that starts with the
+  /// first semicolon (the one that terminates the forInitializerStatement).
+  ///
+  /// ```
+  ///  forLoopParts:
+  ///      localVariableDeclaration ';' expression? ';' expressionList?
+  ///    | expression? ';' expression? ';' expressionList?
+  ///    | localVariableDeclaration 'in' expression
+  ///    | identifier 'in' expression
+  /// ;
+  /// ```
+  Token parseForRest(Token awaitToken, Token token, Token forToken) {
+    token = parseForLoopPartsRest(token, forToken, awaitToken);
+    listener.beginForStatementBody(token.next);
+    LoopState savedLoopState = loopState;
+    loopState = LoopState.InsideLoop;
+    token = parseStatement(token);
+    loopState = savedLoopState;
+    listener.endForStatementBody(token.next);
+    listener.endForStatement(token.next);
+    return token;
+  }
+
+  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)) {
+      token = parseEmptyStatement(leftSeparator);
+    } else {
+      token = parseExpressionStatement(leftSeparator);
+    }
+    int expressionCount = 0;
+    while (true) {
+      Token next = token.next;
+      if (optional(')', next)) {
+        token = next;
+        break;
+      }
+      token = parseExpression(token).next;
+      ++expressionCount;
+      if (!optional(',', token)) {
+        break;
+      }
+    }
+    if (token != leftParenthesis.endGroup) {
+      reportRecoverableErrorWithToken(token, codes.templateUnexpectedToken);
+      token = leftParenthesis.endGroup;
+    }
+    listener.handleForLoopParts(
+        forToken, leftParenthesis, leftSeparator, expressionCount);
+    return token;
+  }
+
+  /// This method parses the portion of the forLoopParts that starts with the
+  /// keyword 'in'. For the sake of recovery, we accept a colon in place of the
+  /// keyword.
+  ///
+  /// ```
+  ///  forLoopParts:
+  ///      localVariableDeclaration ';' expression? ';' expressionList?
+  ///    | expression? ';' expression? ';' expressionList?
+  ///    | localVariableDeclaration 'in' expression
+  ///    | identifier 'in' expression
+  /// ;
+  /// ```
+  Token parseForInRest(
+      Token token, Token awaitToken, Token forToken, Token identifier) {
+    token = parseForInLoopPartsRest(token, awaitToken, forToken, identifier);
+    listener.beginForInBody(token.next);
+    LoopState savedLoopState = loopState;
+    loopState = LoopState.InsideLoop;
+    token = parseStatement(token);
+    loopState = savedLoopState;
+    listener.endForInBody(token.next);
+    listener.endForIn(token.next);
+    return token;
+  }
+
+  Token parseForInLoopPartsRest(
+      Token token, Token awaitToken, Token forToken, Token identifier) {
+    Token inKeyword = token.next;
+    assert(optional('for', forToken));
+    assert(optional('(', forToken.next));
+    assert(optional('in', inKeyword) || optional(':', inKeyword));
+
+    if (!identifier.isIdentifier) {
+      reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
+    } else if (identifier != token) {
+      if (optional('=', identifier.next)) {
+        reportRecoverableError(
+            identifier.next, codes.messageInitializedVariableInForEach);
+      } else {
+        reportRecoverableErrorWithToken(
+            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);
+    token = parseExpression(inKeyword);
+    token = ensureCloseParen(token, forToken.next);
+    listener.endForInExpression(token);
+    listener.handleForInLoopParts(
+        awaitToken, forToken, forToken.next, inKeyword);
+    return token;
+  }
+
+  /// ```
+  /// whileStatement:
+  ///   'while' '(' expression ')' statement
+  /// ;
+  /// ```
+  Token parseWhileStatement(Token token) {
+    Token whileToken = token.next;
+    assert(optional('while', whileToken));
+    listener.beginWhileStatement(whileToken);
+    token = ensureParenthesizedCondition(whileToken);
+    listener.beginWhileStatementBody(token.next);
+    LoopState savedLoopState = loopState;
+    loopState = LoopState.InsideLoop;
+    token = parseStatement(token);
+    loopState = savedLoopState;
+    listener.endWhileStatementBody(token.next);
+    listener.endWhileStatement(whileToken, token.next);
+    return token;
+  }
+
+  /// ```
+  /// doStatement:
+  ///   'do' statement 'while' '(' expression ')' ';'
+  /// ;
+  /// ```
+  Token parseDoWhileStatement(Token token) {
+    Token doToken = token.next;
+    assert(optional('do', doToken));
+    listener.beginDoWhileStatement(doToken);
+    listener.beginDoWhileStatementBody(doToken.next);
+    LoopState savedLoopState = loopState;
+    loopState = LoopState.InsideLoop;
+    token = parseStatement(doToken);
+    loopState = savedLoopState;
+    listener.endDoWhileStatementBody(token);
+    Token whileToken = token.next;
+    if (!optional('while', whileToken)) {
+      reportRecoverableError(
+          whileToken, codes.templateExpectedButGot.withArguments('while'));
+      whileToken = rewriter.insertSyntheticKeyword(token, Keyword.WHILE);
+    }
+    token = ensureParenthesizedCondition(whileToken);
+    token = ensureSemicolon(token);
+    listener.endDoWhileStatement(doToken, whileToken, token);
+    return token;
+  }
+
+  /// ```
+  /// block:
+  ///   '{' statement* '}'
+  /// ;
+  /// ```
+  Token parseBlock(Token token, BlockKind blockKind) {
+    Token begin = token = ensureBlock(token, null, blockKind.missingBlockName);
+    listener.beginBlock(begin, blockKind);
+    int statementCount = 0;
+    Token startToken = token.next;
+    while (notEofOrValue('}', startToken)) {
+      token = parseStatement(token);
+      if (identical(token.next, startToken)) {
+        // No progress was made, so we report the current token as being invalid
+        // and move forward.
+        token = token.next;
+        reportRecoverableError(
+            token, codes.templateUnexpectedToken.withArguments(token));
+      }
+      ++statementCount;
+      startToken = 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;
+    assert(optional('{', begin));
+    // Parse and report the invalid block, but suppress errors
+    // because an error has already been reported by the caller.
+    Listener originalListener = listener;
+    listener = new ForwardingListener(listener)..forwardErrors = false;
+    // The scanner ensures that `{` always has a closing `}`.
+    token = parseBlock(token, BlockKind.invalid);
+    listener = originalListener;
+    listener.handleInvalidTopLevelBlock(begin);
+    return token;
+  }
+
+  /// 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;
+    assert(optional('await', token));
+    token = token.next;
+
+    // TODO(danrubel): Consider parsing the potential expression following
+    // the `await` token once doing so does not modify the token stream.
+    // For now, use simple look ahead and ensure no false positives.
+
+    if (token.isIdentifier) {
+      token = token.next;
+      if (optional('(', token)) {
+        token = token.endGroup.next;
+        if (isOneOf(token, [';', '.', '..', '?', '?.'])) {
+          return true;
+        }
+      } else if (isOneOf(token, ['.', ')', ']'])) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// ```
+  /// awaitExpression:
+  ///   'await' unaryExpression
+  /// ;
+  /// ```
+  Token parseAwaitExpression(Token token, bool allowCascades) {
+    Token awaitToken = token.next;
+    assert(optional('await', awaitToken));
+    listener.beginAwaitExpression(awaitToken);
+    token = parsePrecedenceExpression(
+        awaitToken, POSTFIX_PRECEDENCE, allowCascades);
+    if (inAsync) {
+      listener.endAwaitExpression(awaitToken, token.next);
+    } else {
+      codes.MessageCode errorCode = codes.messageAwaitNotAsync;
+      reportRecoverableError(awaitToken, errorCode);
+      listener.endInvalidAwaitExpression(awaitToken, token.next, errorCode);
+    }
+    return token;
+  }
+
+  /// ```
+  /// throwExpression:
+  ///   'throw' expression
+  /// ;
+  ///
+  /// throwExpressionWithoutCascade:
+  ///   'throw' expressionWithoutCascade
+  /// ;
+  /// ```
+  Token parseThrowExpression(Token token, bool allowCascades) {
+    Token throwToken = token.next;
+    assert(optional('throw', throwToken));
+    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);
+      rewriter.insertToken(
+          throwToken,
+          new SyntheticStringToken(
+              TokenType.STRING, '""', throwToken.next.charOffset, 0));
+    }
+    token = allowCascades
+        ? parseExpression(throwToken)
+        : parseExpressionWithoutCascade(throwToken);
+    listener.handleThrowExpression(throwToken, token.next);
+    return token;
+  }
+
+  /// ```
+  /// rethrowStatement:
+  ///   'rethrow' ';'
+  /// ;
+  /// ```
+  Token parseRethrowStatement(Token token) {
+    Token throwToken = token.next;
+    assert(optional('rethrow', throwToken));
+    listener.beginRethrowStatement(throwToken);
+    token = ensureSemicolon(throwToken);
+    listener.endRethrowStatement(throwToken, token);
+    return token;
+  }
+
+  /// ```
+  /// tryStatement:
+  ///   'try' block (onPart+ finallyPart? | finallyPart)
+  /// ;
+  ///
+  /// onPart:
+  ///   catchPart block |
+  ///   'on' type catchPart? block
+  /// ;
+  ///
+  /// catchPart:
+  ///   'catch' '(' identifier (',' identifier)? ')'
+  /// ;
+  ///
+  /// finallyPart:
+  ///   'finally' block
+  /// ;
+  /// ```
+  Token parseTryStatement(Token token) {
+    Token tryKeyword = token.next;
+    assert(optional('try', tryKeyword));
+    listener.beginTryStatement(tryKeyword);
+    Token lastConsumed = parseBlock(tryKeyword, BlockKind.tryStatement);
+    token = lastConsumed.next;
+    int catchCount = 0;
+
+    String value = token.stringValue;
+    while (identical(value, 'catch') || identical(value, 'on')) {
+      listener.beginCatchClause(token);
+      Token onKeyword = null;
+      if (identical(value, 'on')) {
+        // 'on' type catchPart?
+        onKeyword = token;
+        lastConsumed = computeType(token, true).ensureTypeNotVoid(token, this);
+        token = lastConsumed.next;
+        value = token.stringValue;
+      }
+      Token catchKeyword = null;
+      Token comma = null;
+      if (identical(value, 'catch')) {
+        catchKeyword = token;
+
+        Token openParens = catchKeyword.next;
+        if (!optional("(", openParens)) {
+          reportRecoverableError(openParens, codes.messageCatchSyntax);
+          openParens = rewriter.insertParens(catchKeyword, true);
+        }
+
+        Token exceptionName = openParens.next;
+        if (exceptionName.kind != IDENTIFIER_TOKEN) {
+          exceptionName = IdentifierContext.catchParameter
+              .ensureIdentifier(openParens, this);
+        }
+
+        if (optional(")", exceptionName.next)) {
+          // OK: `catch (identifier)`.
+        } else {
+          comma = exceptionName.next;
+          if (!optional(",", comma)) {
+            // Recovery
+            if (!exceptionName.isSynthetic) {
+              reportRecoverableError(comma, codes.messageCatchSyntax);
+            }
+
+            // TODO(danrubel): Consider inserting `on` clause if
+            // exceptionName is preceded by type and followed by a comma.
+            // Then this
+            //   } catch (E e, t) {
+            // will recover to
+            //   } on E catch (e, t) {
+            // with a detailed explanation for the user in the error
+            // indicating what they should do to fix the code.
+
+            // TODO(danrubel): Consider inserting synthetic identifier if
+            // exceptionName is a non-synthetic identifier followed by `.`.
+            // Then this
+            //   } catch (
+            //   e.f();
+            // will recover to
+            //   } catch (_s_) {}
+            //   e.f();
+            // rather than
+            //   } catch (e) {}
+            //   _s_.f();
+
+            if (openParens.endGroup.isSynthetic) {
+              // The scanner did not place the synthetic ')' correctly.
+              rewriter.moveSynthetic(exceptionName, openParens.endGroup);
+              comma = null;
+            } else {
+              comma =
+                  rewriter.insertSyntheticToken(exceptionName, TokenType.COMMA);
+            }
+          }
+          if (comma != null) {
+            Token traceName = comma.next;
+            if (traceName.kind != IDENTIFIER_TOKEN) {
+              traceName = IdentifierContext.catchParameter
+                  .ensureIdentifier(comma, this);
+            }
+            if (!optional(")", traceName.next)) {
+              // Recovery
+              if (!traceName.isSynthetic) {
+                reportRecoverableError(
+                    traceName.next, codes.messageCatchSyntaxExtraParameters);
+              }
+              if (openParens.endGroup.isSynthetic) {
+                // The scanner did not place the synthetic ')' correctly.
+                rewriter.moveSynthetic(traceName, openParens.endGroup);
+              }
+            }
+          }
+        }
+        lastConsumed = parseFormalParameters(catchKeyword, MemberKind.Catch);
+        token = lastConsumed.next;
+      }
+      listener.endCatchClause(token);
+      lastConsumed = parseBlock(lastConsumed, BlockKind.catchClause);
+      token = lastConsumed.next;
+      ++catchCount;
+      listener.handleCatchBlock(onKeyword, catchKeyword, comma);
+      value = token.stringValue; // while condition
+    }
+
+    Token finallyKeyword = null;
+    if (optional('finally', token)) {
+      finallyKeyword = token;
+      lastConsumed = parseBlock(token, BlockKind.finallyClause);
+      token = lastConsumed.next;
+      listener.handleFinallyBlock(finallyKeyword);
+    } else {
+      if (catchCount == 0) {
+        reportRecoverableError(tryKeyword, codes.messageOnlyTry);
+      }
+    }
+    listener.endTryStatement(catchCount, tryKeyword, finallyKeyword);
+    return lastConsumed;
+  }
+
+  /// ```
+  /// switchStatement:
+  ///   'switch' parenthesizedExpression switchBlock
+  /// ;
+  /// ```
+  Token parseSwitchStatement(Token token) {
+    Token switchKeyword = token.next;
+    assert(optional('switch', switchKeyword));
+    listener.beginSwitchStatement(switchKeyword);
+    token = ensureParenthesizedCondition(switchKeyword);
+    LoopState savedLoopState = loopState;
+    if (loopState == LoopState.OutsideLoop) {
+      loopState = LoopState.InsideSwitch;
+    }
+    token = parseSwitchBlock(token);
+    loopState = savedLoopState;
+    listener.endSwitchStatement(switchKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// switchBlock:
+  ///   '{' switchCase* defaultCase? '}'
+  /// ;
+  /// ```
+  Token parseSwitchBlock(Token token) {
+    Token beginSwitch = token = ensureBlock(token, null, 'switch statement');
+    listener.beginSwitchBlock(beginSwitch);
+    int caseCount = 0;
+    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;
+        if (identical(value, 'default')) {
+          while (!identical(token.next, peek)) {
+            token = parseLabel(token);
+            labelCount++;
+          }
+          if (defaultKeyword != null) {
+            reportRecoverableError(
+                token.next, codes.messageSwitchHasMultipleDefaults);
+          }
+          defaultKeyword = token.next;
+          colonAfterDefault = token = ensureColon(defaultKeyword);
+          peek = token.next;
+          break;
+        } else if (identical(value, 'case')) {
+          while (!identical(token.next, peek)) {
+            token = parseLabel(token);
+            labelCount++;
+          }
+          Token caseKeyword = token.next;
+          if (defaultKeyword != null) {
+            reportRecoverableError(
+                caseKeyword, codes.messageSwitchHasCaseAfterDefault);
+          }
+          listener.beginCaseExpression(caseKeyword);
+          token = parseExpression(caseKeyword);
+          token = ensureColon(token);
+          listener.endCaseExpression(token);
+          listener.handleCaseMatch(caseKeyword, token);
+          expressionCount++;
+          peek = peekPastLabels(token.next);
+        } else if (expressionCount > 0) {
+          break;
+        } else {
+          // Recovery
+          reportRecoverableError(
+              peek, codes.templateExpectedToken.withArguments("case"));
+          Token endGroup = beginSwitch.endGroup;
+          while (token.next != endGroup) {
+            token = token.next;
+          }
+          peek = peekPastLabels(token.next);
+          break;
+        }
+      }
+      token = parseStatementsInSwitchCase(token, peek, beginCase, labelCount,
+          expressionCount, defaultKeyword, colonAfterDefault);
+      ++caseCount;
+    }
+    token = token.next;
+    listener.endSwitchBlock(caseCount, beginSwitch, token);
+    assert(token.isEof || optional('}', token));
+    return token;
+  }
+
+  /// Peek after the following labels (if any). The following token
+  /// 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;
+    }
+    return token;
+  }
+
+  /// Parse statements after a switch `case:` or `default:`.
+  Token parseStatementsInSwitchCase(
+      Token token,
+      Token peek,
+      Token begin,
+      int labelCount,
+      int expressionCount,
+      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;
+      if ((identical(value, 'case')) ||
+          (identical(value, 'default')) ||
+          ((identical(value, '}')) && (identical(token.next, peek)))) {
+        // A label just before "}" will be handled as a statement error.
+        break;
+      } else {
+        Token startToken = token.next;
+        token = parseStatement(token);
+        Token next = token.next;
+        if (identical(next, startToken)) {
+          // No progress was made, so we report the current token as being
+          // invalid and move forward.
+          reportRecoverableError(
+              next, codes.templateUnexpectedToken.withArguments(next));
+          token = next;
+        }
+        ++statementCount;
+      }
+      peek = peekPastLabels(token.next);
+    }
+    listener.endSwitchCase(labelCount, expressionCount, defaultKeyword,
+        colonAfterDefault, statementCount, begin, token.next);
+    return token;
+  }
+
+  /// ```
+  /// breakStatement:
+  ///   'break' identifier? ';'
+  /// ;
+  /// ```
+  Token parseBreakStatement(Token token) {
+    Token breakKeyword = token = token.next;
+    assert(optional('break', breakKeyword));
+    bool hasTarget = false;
+    if (token.next.isIdentifier) {
+      token = ensureIdentifier(token, IdentifierContext.labelReference);
+      hasTarget = true;
+    } else if (!isBreakAllowed) {
+      reportRecoverableError(breakKeyword, codes.messageBreakOutsideOfLoop);
+    }
+    token = ensureSemicolon(token);
+    listener.handleBreakStatement(hasTarget, breakKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// assertion:
+  ///   'assert' '(' expression (',' expression)? ','? ')'
+  /// ;
+  /// ```
+  Token parseAssert(Token token, Assert kind) {
+    token = token.next;
+    assert(optional('assert', token));
+    listener.beginAssert(token, kind);
+    Token assertKeyword = token;
+    Token leftParenthesis = token.next;
+    if (!optional('(', leftParenthesis)) {
+      // Recovery
+      reportRecoverableError(
+          leftParenthesis, codes.templateExpectedButGot.withArguments('('));
+      leftParenthesis = rewriter.insertParens(token, true);
+    }
+    token = leftParenthesis;
+    Token commaToken = null;
+    bool old = mayParseFunctionExpressions;
+    mayParseFunctionExpressions = true;
+
+    token = parseExpression(token);
+    if (optional(',', token.next)) {
+      token = token.next;
+      if (!optional(')', token.next)) {
+        commaToken = token;
+        token = parseExpression(token);
+        if (optional(',', token.next)) {
+          // Trailing comma is ignored.
+          token = token.next;
+        }
+      }
+    }
+
+    Token endGroup = leftParenthesis.endGroup;
+    if (token.next == endGroup) {
+      token = endGroup;
+    } else {
+      // Recovery
+      if (endGroup.isSynthetic) {
+        // The scanner did not place the synthetic ')' correctly, so move it.
+        token = rewriter.moveSynthetic(token, endGroup);
+      } else {
+        reportRecoverableErrorWithToken(
+            token.next, codes.templateUnexpectedToken);
+        token = endGroup;
+      }
+    }
+
+    assert(optional(')', token));
+    mayParseFunctionExpressions = old;
+    if (kind == Assert.Expression) {
+      reportRecoverableError(assertKeyword, codes.messageAssertAsExpression);
+    } else if (kind == Assert.Statement) {
+      ensureSemicolon(token);
+    }
+    listener.endAssert(
+        assertKeyword, kind, leftParenthesis, commaToken, token.next);
+    return token;
+  }
+
+  /// ```
+  /// assertStatement:
+  ///   assertion ';'
+  /// ;
+  /// ```
+  Token parseAssertStatement(Token token) {
+    assert(optional('assert', token.next));
+    // parseAssert ensures that there is a trailing semicolon.
+    return parseAssert(token, Assert.Statement).next;
+  }
+
+  /// ```
+  /// continueStatement:
+  ///   'continue' identifier? ';'
+  /// ;
+  /// ```
+  Token parseContinueStatement(Token token) {
+    Token continueKeyword = token = token.next;
+    assert(optional('continue', continueKeyword));
+    bool hasTarget = false;
+    if (token.next.isIdentifier) {
+      token = ensureIdentifier(token, IdentifierContext.labelReference);
+      hasTarget = true;
+      if (!isContinueWithLabelAllowed) {
+        reportRecoverableError(
+            continueKeyword, codes.messageContinueOutsideOfLoop);
+      }
+    } else if (!isContinueAllowed) {
+      reportRecoverableError(
+          continueKeyword,
+          loopState == LoopState.InsideSwitch
+              ? codes.messageContinueWithoutLabelInCase
+              : codes.messageContinueOutsideOfLoop);
+    }
+    token = ensureSemicolon(token);
+    listener.handleContinueStatement(hasTarget, continueKeyword, token);
+    return token;
+  }
+
+  /// ```
+  /// emptyStatement:
+  ///   ';'
+  /// ;
+  /// ```
+  Token parseEmptyStatement(Token token) {
+    token = token.next;
+    assert(optional(';', token));
+    listener.handleEmptyStatement(token);
+    return token;
+  }
+
+  /// 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;
+    while (next != token && next != beforeToken) {
+      beforeToken = next;
+      next = beforeToken.next;
+    }
+    return beforeToken;
+  }
+
+  /// Recover from finding an operator declaration missing the `operator`
+  /// keyword. The metadata for the member, if any, has already been parsed
+  /// (and events have already been generated).
+  Token parseInvalidOperatorDeclaration(
+      Token beforeStart,
+      Token externalToken,
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      Token beforeType,
+      DeclarationKind kind,
+      String enclosingDeclarationName) {
+    TypeInfo typeInfo = computeType(beforeStart, false, true);
+    Token beforeName = typeInfo.skipType(beforeType);
+    Token next = beforeName.next;
+
+    if (optional('operator', 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) {
+        beforeName = next;
+        operator = next.next;
+      }
+      reportRecoverableError(operator, codes.messageMissingOperatorKeyword);
+      rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
+
+      // Having inserted the keyword the type now possibly compute differently.
+      typeInfo = computeType(beforeStart, true, true);
+      beforeName = typeInfo.skipType(beforeType);
+      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 &&
+          identical(next.stringValue, 'operator')) {
+        next = next.next;
+      }
+    }
+
+    assert((next.isOperator && next.endGroup == null) ||
+        optional('===', next) ||
+        optional('!==', next));
+
+    Token token = parseMethod(
+        beforeStart,
+        externalToken,
+        staticToken,
+        covariantToken,
+        lateToken,
+        varFinalOrConst,
+        beforeType,
+        typeInfo,
+        null,
+        beforeName.next,
+        kind,
+        enclosingDeclarationName);
+    listener.endMember();
+    return token;
+  }
+
+  /// Recover from finding an invalid class member. The metadata for the member,
+  /// if any, has already been parsed (and events have already been generated).
+  /// The member was expected to start with the token after [token].
+  Token recoverFromInvalidMember(
+      Token token,
+      Token beforeStart,
+      Token externalToken,
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      Token beforeType,
+      TypeInfo typeInfo,
+      Token getOrSet,
+      DeclarationKind kind,
+      String enclosingDeclarationName) {
+    Token next = token.next;
+    String value = next.stringValue;
+
+    if (identical(value, 'class')) {
+      return reportAndSkipClassInClass(next);
+    } else if (identical(value, 'enum')) {
+      return reportAndSkipEnumInClass(next);
+    } else if (identical(value, 'typedef')) {
+      return reportAndSkipTypedefInClass(next);
+    } else if (next.isOperator && next.endGroup == null) {
+      return parseInvalidOperatorDeclaration(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          lateToken,
+          varFinalOrConst,
+          beforeType,
+          kind,
+          enclosingDeclarationName);
+    }
+
+    if (getOrSet != null ||
+        identical(value, '(') ||
+        identical(value, '=>') ||
+        identical(value, '{')) {
+      token = parseMethod(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          lateToken,
+          varFinalOrConst,
+          beforeType,
+          typeInfo,
+          getOrSet,
+          token.next,
+          kind,
+          enclosingDeclarationName);
+    } else if (token == beforeStart) {
+      // TODO(danrubel): Provide a more specific error message for extra ';'.
+      reportRecoverableErrorWithToken(next, codes.templateExpectedClassMember);
+      listener.handleInvalidMember(next);
+      if (!identical(value, '}')) {
+        // Ensure we make progress.
+        token = next;
+      }
+    } else {
+      token = parseFields(
+          beforeStart,
+          externalToken,
+          staticToken,
+          covariantToken,
+          lateToken,
+          varFinalOrConst,
+          beforeType,
+          typeInfo,
+          token.next,
+          kind);
+    }
+
+    listener.endMember();
+    return token;
+  }
+
+  /// 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;
+    reportRecoverableError(next, codes.messageStackOverflow);
+    next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+    listener.handleEmptyStatement(next);
+
+    while (notEofOrValue('}', next)) {
+      token = next;
+      next = token.next;
+    }
+    return token;
+  }
+
+  void reportRecoverableError(Token token, Message message) {
+    // Find a non-synthetic token on which to report the error.
+    token = findNonZeroLengthToken(token);
+    listener.handleRecoverableError(message, token, token);
+  }
+
+  void reportRecoverableErrorWithToken(
+      Token token, Template<_MessageWithArgument<Token>> template) {
+    // Find a non-synthetic token on which to report the error.
+    token = findNonZeroLengthToken(token);
+    listener.handleRecoverableError(
+        template.withArguments(token), token, token);
+  }
+
+  Token reportAllErrorTokens(Token token) {
+    while (token is ErrorToken) {
+      listener.handleErrorToken(token);
+      token = token.next;
+    }
+    return token;
+  }
+
+  Token skipErrorTokens(Token token) {
+    while (token is ErrorToken) {
+      token = token.next;
+    }
+    return token;
+  }
+
+  Token parseInvalidTopLevelDeclaration(Token token) {
+    Token next = token.next;
+    reportRecoverableErrorWithToken(
+        next,
+        optional(';', next)
+            ? codes.templateUnexpectedToken
+            : codes.templateExpectedDeclaration);
+    if (optional('{', next)) {
+      next = parseInvalidBlock(token);
+    }
+    listener.handleInvalidTopLevelDeclaration(next);
+    return next;
+  }
+
+  Token reportAndSkipClassInClass(Token token) {
+    assert(optional('class', token));
+    reportRecoverableError(token, codes.messageClassInClass);
+    listener.handleInvalidMember(token);
+    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;
+      // 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;
+      }
+    }
+    return token;
+  }
+
+  Token reportAndSkipEnumInClass(Token token) {
+    assert(optional('enum', token));
+    reportRecoverableError(token, codes.messageEnumInClass);
+    listener.handleInvalidMember(token);
+    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;
+      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;
+      }
+    }
+    return token;
+  }
+
+  Token reportAndSkipTypedefInClass(Token token) {
+    assert(optional('typedef', token));
+    reportRecoverableError(token, codes.messageTypedefInClass);
+    listener.handleInvalidMember(token);
+    // TODO(brianwilkerson): If the declaration appears to be a valid typedef
+    // then skip the entire declaration so that we generate a single error
+    // (above) rather than many unhelpful errors.
+    return token;
+  }
+
+  /// Create a short token chain from the [beginToken] and [endToken] and return
+  /// the [beginToken].
+  Token link(BeginToken beginToken, Token endToken) {
+    beginToken.setNext(endToken);
+    beginToken.endGroup = endToken;
+    return beginToken;
+  }
+
+  /// Create and return a token whose next token is the given [token].
+  Token syntheticPreviousToken(Token token) {
+    // Return the previous token if there is one so that any token inserted
+    // before `token` will be properly inserted into the token stream.
+    // TODO(danrubel): remove this once all methods have been converted to
+    // use and return the last token consumed and the `previous` field
+    // has been removed.
+    if (token.previous != null) {
+      return token.previous;
+    }
+    Token before = new Token.eof(-1);
+    before.next = token;
+    return before;
+  }
+
+  /// 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;
+    bool isMultiline = false;
+    while (comments != null) {
+      String lexeme = comments.lexeme;
+      if (lexeme.startsWith('///')) {
+        if (!isMultiline) {
+          dartdoc = comments;
+          isMultiline = true;
+        }
+      } else if (lexeme.startsWith('/**')) {
+        dartdoc = comments;
+        isMultiline = false;
+      }
+      comments = comments.next;
+    }
+    return dartdoc;
+  }
+
+  /// Parse the comment references in a sequence of comment tokens
+  /// where [dartdoc] (not null) is the first token in the sequence.
+  /// Return the number of comment references parsed.
+  int parseCommentReferences(Token dartdoc) {
+    return dartdoc.lexeme.startsWith('///')
+        ? parseReferencesInSingleLineComments(dartdoc)
+        : parseReferencesInMultiLineComment(dartdoc);
+  }
+
+  /// Parse the comment references in a multi-line comment token.
+  /// Return the number of comment references parsed.
+  int parseReferencesInMultiLineComment(Token multiLineDoc) {
+    String comment = multiLineDoc.lexeme;
+    assert(comment.startsWith('/**'));
+    int count = 0;
+    int length = comment.length;
+    int start = 3;
+    bool inCodeBlock = false;
+    int codeBlock = comment.indexOf('```', 3);
+    if (codeBlock == -1) {
+      codeBlock = length;
+    }
+    while (start < length) {
+      if (isWhitespace(comment.codeUnitAt(start))) {
+        ++start;
+        continue;
+      }
+      int end = comment.indexOf('\n', start);
+      if (end == -1) {
+        end = length;
+      }
+      if (codeBlock < end) {
+        inCodeBlock = !inCodeBlock;
+        codeBlock = comment.indexOf('```', end);
+        if (codeBlock == -1) {
+          codeBlock = length;
+        }
+      }
+      if (!inCodeBlock && !comment.startsWith('*     ', start)) {
+        count += parseCommentReferencesInText(multiLineDoc, start, end);
+      }
+      start = end + 1;
+    }
+    return count;
+  }
+
+  /// 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 count = 0;
+    bool inCodeBlock = false;
+    while (token != null && !token.isEof) {
+      String comment = token.lexeme;
+      if (comment.startsWith('///')) {
+        if (comment.indexOf('```', 3) != -1) {
+          inCodeBlock = !inCodeBlock;
+        }
+        if (!inCodeBlock && !comment.startsWith('///    ')) {
+          count += parseCommentReferencesInText(token, 3, comment.length);
+        }
+      }
+      token = token.next;
+    }
+    return count;
+  }
+
+  /// Parse the comment references in the text between [start] inclusive
+  /// and [end] exclusive. Return a count indicating how many were parsed.
+  int parseCommentReferencesInText(Token commentToken, int start, int end) {
+    String comment = commentToken.lexeme;
+    int count = 0;
+    int index = start;
+    while (index < end) {
+      int ch = comment.codeUnitAt(index);
+      if (ch == 0x5B /* `[` */) {
+        ++index;
+        if (index < end && comment.codeUnitAt(index) == 0x3A /* `:` */) {
+          // Skip old-style code block.
+          index = comment.indexOf(':]', index + 1) + 1;
+          if (index == 0 || index > end) {
+            break;
+          }
+        } else {
+          int referenceStart = index;
+          index = comment.indexOf(']', index);
+          if (index == -1 || index >= end) {
+            // Recovery: terminating ']' is not typed yet.
+            index = findReferenceEnd(comment, referenceStart, end);
+          }
+          if (ch != 0x27 /* `'` */ && ch != 0x22 /* `"` */) {
+            if (isLinkText(comment, index)) {
+              // TODO(brianwilkerson) Handle the case where there's a library
+              // URI in the link text.
+            } else {
+              listener.handleCommentReferenceText(
+                  comment.substring(referenceStart, index),
+                  commentToken.charOffset + referenceStart);
+              ++count;
+            }
+          }
+        }
+      } else if (ch == 0x60 /* '`' */) {
+        // Skip inline code block if there is both starting '`' and ending '`'
+        int endCodeBlock = comment.indexOf('`', index + 1);
+        if (endCodeBlock != -1 && endCodeBlock < end) {
+          index = endCodeBlock;
+        }
+      }
+      ++index;
+    }
+    return count;
+  }
+
+  /// Given a comment reference without a closing `]`,
+  /// search for a possible place where `]` should be.
+  int findReferenceEnd(String comment, int index, int end) {
+    // Find the end of the identifier if there is one
+    if (index >= end || !isLetter(comment.codeUnitAt(index))) {
+      return index;
+    }
+    while (index < end && isLetterOrDigit(comment.codeUnitAt(index))) {
+      ++index;
+    }
+
+    // Check for a trailing `.`
+    if (index >= end || comment.codeUnitAt(index) != 0x2E /* `.` */) {
+      return index;
+    }
+    ++index;
+
+    // Find end of the identifier after the `.`
+    if (index >= end || !isLetter(comment.codeUnitAt(index))) {
+      return index;
+    }
+    ++index;
+    while (index < end && isLetterOrDigit(comment.codeUnitAt(index))) {
+      ++index;
+    }
+    return index;
+  }
+
+  /// Parse the tokens in a single comment reference and generate either a
+  /// `handleCommentReference` or `handleNoCommentReference` event.
+  /// Return `true` if a comment reference was successfully parsed.
+  bool parseOneCommentReference(Token token, int referenceOffset) {
+    Token begin = token;
+    Token newKeyword = null;
+    if (optional('new', token)) {
+      newKeyword = token;
+      token = token.next;
+    }
+    Token prefix, period;
+    if (token.isIdentifier && optional('.', token.next)) {
+      prefix = token;
+      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) {
+        begin = token;
+      }
+    }
+    Token operatorKeyword = null;
+    if (optional('operator', token)) {
+      operatorKeyword = token;
+      token = token.next;
+    }
+    if (token.isUserDefinableOperator) {
+      if (token.next.isEof) {
+        parseOneCommentReferenceRest(
+            begin, referenceOffset, newKeyword, prefix, period, token);
+        return true;
+      }
+    } else {
+      token = operatorKeyword ?? token;
+      if (token.next.isEof) {
+        if (token.isIdentifier) {
+          parseOneCommentReferenceRest(
+              begin, referenceOffset, newKeyword, prefix, period, token);
+          return true;
+        }
+        Keyword keyword = token.keyword;
+        if (newKeyword == null &&
+            prefix == null &&
+            (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.
+        }
+      }
+    }
+    listener.handleNoCommentReference();
+    return false;
+  }
+
+  void parseOneCommentReferenceRest(
+      Token begin,
+      int referenceOffset,
+      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;
+    } while (!token.isEof);
+
+    listener.handleCommentReference(
+        newKeyword, prefix, period, identifierOrOperator);
+  }
+
+  /// 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 ch = comment.codeUnitAt(index);
+    if (ch == 0x28 || ch == 0x3A) {
+      return true;
+    }
+    while (isWhitespace(ch)) {
+      index = index + 1;
+      if (index >= length) {
+        return false;
+      }
+      ch = comment.codeUnitAt(index);
+    }
+    return ch == 0x5B;
+  }
+}
+
+// TODO(ahe): Remove when analyzer supports generalized function syntax.
+typedef _MessageWithArgument<T> = Message Function(T);
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_main.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_main.dart
new file mode 100644
index 0000000..eadd81c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_main.dart
@@ -0,0 +1,53 @@
+// 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 _fe_analyzer_shared.parser.main;
+
+import 'dart:convert' show LineSplitter, utf8;
+
+import 'dart:io' show File;
+
+import '../scanner/token.dart' show Token;
+
+import '../scanner/io.dart' show readBytesFromFileSync;
+
+import '../scanner/scanner.dart' show scan;
+
+import 'listener.dart' show Listener;
+
+import 'top_level_parser.dart' show TopLevelParser;
+
+import 'identifier_context.dart' show IdentifierContext;
+
+class DebugListener extends Listener {
+  void handleIdentifier(Token token, IdentifierContext context) {
+    logEvent("Identifier: ${token.lexeme}");
+  }
+
+  void logEvent(String name) {
+    print(name);
+  }
+}
+
+mainEntryPoint(List<String> arguments) async {
+  for (String argument in arguments) {
+    if (argument.startsWith("@")) {
+      Uri uri = Uri.base.resolve(argument.substring(1));
+      await for (String file in new File.fromUri(uri)
+          .openRead()
+          .cast<List<int>>()
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())) {
+        outLine(uri.resolve(file));
+      }
+    } else {
+      outLine(Uri.base.resolve(argument));
+    }
+  }
+}
+
+void outLine(Uri uri) {
+  new TopLevelParser(new DebugListener())
+      .parseUnit(scan(readBytesFromFileSync(uri)).tokens);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart b/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart
new file mode 100644
index 0000000..4c1921b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/recovery_listeners.dart
@@ -0,0 +1,96 @@
+// 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 '../scanner/token.dart' show Token;
+
+import 'forwarding_listener.dart' show ForwardingListener;
+
+class ClassHeaderRecoveryListener extends ForwardingListener {
+  Token extendsKeyword;
+  Token implementsKeyword;
+  Token withKeyword;
+
+  void clear() {
+    extendsKeyword = null;
+    implementsKeyword = null;
+    withKeyword = null;
+  }
+
+  @override
+  void handleClassExtends(Token extendsKeyword) {
+    this.extendsKeyword = extendsKeyword;
+    super.handleClassExtends(extendsKeyword);
+  }
+
+  @override
+  void handleClassOrMixinImplements(
+      Token implementsKeyword, int interfacesCount) {
+    this.implementsKeyword = implementsKeyword;
+    super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
+  }
+
+  @override
+  void handleClassWithClause(Token withKeyword) {
+    this.withKeyword = withKeyword;
+    super.handleClassWithClause(withKeyword);
+  }
+}
+
+class ImportRecoveryListener extends ForwardingListener {
+  Token asKeyword;
+  Token deferredKeyword;
+  Token ifKeyword;
+  bool hasCombinator = false;
+
+  void clear() {
+    asKeyword = null;
+    deferredKeyword = null;
+    ifKeyword = null;
+    hasCombinator = false;
+  }
+
+  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
+    this.ifKeyword = ifKeyword;
+    super.endConditionalUri(ifKeyword, leftParen, equalSign);
+  }
+
+  void endHide(Token hideKeyword) {
+    this.hasCombinator = true;
+    super.endHide(hideKeyword);
+  }
+
+  void endShow(Token showKeyword) {
+    this.hasCombinator = true;
+    super.endShow(showKeyword);
+  }
+
+  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+    this.deferredKeyword = deferredKeyword;
+    this.asKeyword = asKeyword;
+    super.handleImportPrefix(deferredKeyword, asKeyword);
+  }
+}
+
+class MixinHeaderRecoveryListener extends ForwardingListener {
+  Token onKeyword;
+  Token implementsKeyword;
+
+  void clear() {
+    onKeyword = null;
+    implementsKeyword = null;
+  }
+
+  @override
+  void handleClassOrMixinImplements(
+      Token implementsKeyword, int interfacesCount) {
+    this.implementsKeyword = implementsKeyword;
+    super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
+  }
+
+  @override
+  void handleMixinOn(Token onKeyword, int typeCount) {
+    this.onKeyword = onKeyword;
+    super.handleMixinOn(onKeyword, typeCount);
+  }
+}
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
new file mode 100644
index 0000000..1641885
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
@@ -0,0 +1,220 @@
+// 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 '../scanner/error_token.dart' show UnmatchedToken;
+
+import '../scanner/token.dart'
+    show
+        BeginToken,
+        Keyword,
+        SimpleToken,
+        SyntheticBeginToken,
+        SyntheticKeywordToken,
+        SyntheticStringToken,
+        SyntheticToken,
+        Token,
+        TokenType;
+
+/// Provides the capability of inserting tokens into a token stream. This
+/// implementation does this by rewriting the previous token to point to the
+/// inserted token.
+class TokenStreamRewriter with _TokenStreamMixin {
+  // TODO(brianwilkerson):
+  //
+  // When we get to the point of removing `token.previous`, the plan is to
+  // convert this into an interface and provide two implementations.
+  //
+  // One, used by Fasta, will connect the inserted tokens to the following token
+  // without modifying the previous token.
+  //
+  // The other, used by 'analyzer', will be created with the first token in the
+  // stream (actually with the BOF marker at the beginning of the stream). It
+  // will be created only when invoking 'analyzer' specific parse methods (in
+  // `Parser`), such as
+  //
+  // Token parseUnitWithRewrite(Token bof) {
+  //   rewriter = AnalyzerTokenStreamRewriter(bof);
+  //   return parseUnit(bof.next);
+  // }
+  //
+
+  /// Insert a synthetic open and close parenthesis and return the new synthetic
+  /// 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;
+    int offset = next.charOffset;
+    BeginToken leftParen =
+        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
+    if (includeIdentifier) {
+      next = next.setNext(
+          new SyntheticStringToken(TokenType.IDENTIFIER, '', offset, 0));
+    }
+    next = next.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
+    leftParen.endGroup = next;
+    next.setNext(token.next);
+
+    // A no-op rewriter could skip this step.
+    token.setNext(leftParen);
+
+    return leftParen;
+  }
+
+  /// Insert [newToken] after [token] and return [newToken].
+  Token insertToken(Token token, Token newToken) {
+    newToken.setNext(token.next);
+
+    // A no-op rewriter could skip this step.
+    token.setNext(newToken);
+
+    return newToken;
+  }
+
+  /// 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(endGroup.beforeSynthetic != null);
+    if (token == endGroup) return endGroup;
+    Token errorToken;
+    if (endGroup.next is UnmatchedToken) {
+      errorToken = endGroup.next;
+    }
+
+    // Remove endGroup from its current location
+    endGroup.beforeSynthetic.setNext((errorToken ?? endGroup).next);
+
+    // Insert endGroup into its new location
+    Token next = token.next;
+    token.setNext(endGroup);
+    (errorToken ?? endGroup).setNext(next);
+    endGroup.offset = next.offset;
+    if (errorToken != null) {
+      errorToken.offset = next.offset;
+    }
+
+    return endGroup;
+  }
+
+  /// Replace the single token immediately following the [previousToken] with
+  /// the chain of tokens starting at the [replacementToken]. Return the
+  /// [replacementToken].
+  Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
+    Token replacedToken = previousToken.next;
+    previousToken.setNext(replacementToken);
+
+    (replacementToken as SimpleToken).precedingComments =
+        replacedToken.precedingComments;
+
+    _lastTokenInChain(replacementToken).setNext(replacedToken.next);
+
+    return replacementToken;
+  }
+
+  /// Given the [firstToken] in a chain of tokens to be inserted, return the
+  /// last token in the chain.
+  ///
+  /// 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 current = firstToken;
+    while (current.next != null && current.next.type != TokenType.EOF) {
+      if (previous != null) {
+        current.previous = previous;
+      }
+      previous = current;
+      current = current.next;
+    }
+    if (previous != null) {
+      current.previous = previous;
+    }
+    return current;
+  }
+}
+
+/// Provides the capability of adding tokens that lead into a token stream
+/// without modifying the original token stream and not setting the any token's
+/// `previous` field.
+class TokenStreamGhostWriter
+    with _TokenStreamMixin
+    implements TokenStreamRewriter {
+  @override
+  Token insertParens(Token token, bool includeIdentifier) {
+    Token next = token.next;
+    int offset = next.charOffset;
+    BeginToken leftParen =
+        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
+    if (includeIdentifier) {
+      Token identifier =
+          new SyntheticStringToken(TokenType.IDENTIFIER, '', offset, 0);
+      next.next = identifier;
+      next = identifier;
+    }
+    Token rightParen = new SyntheticToken(TokenType.CLOSE_PAREN, offset);
+    next.next = rightParen;
+    rightParen.next = token.next;
+
+    return leftParen;
+  }
+
+  @override
+  Token insertToken(Token token, Token newToken) {
+    newToken.next = token.next;
+    return newToken;
+  }
+
+  @override
+  Token moveSynthetic(Token token, Token endGroup) {
+    Token newEndGroup =
+        new SyntheticToken(endGroup.type, token.next.charOffset);
+    newEndGroup.next = token.next;
+    return newEndGroup;
+  }
+
+  @override
+  Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
+    Token replacedToken = previousToken.next;
+
+    (replacementToken as SimpleToken).precedingComments =
+        replacedToken.precedingComments;
+
+    _lastTokenInChain(replacementToken).next = replacedToken.next;
+    return replacementToken;
+  }
+
+  /// Given the [firstToken] in a chain of tokens to be inserted, return the
+  /// last token in the chain.
+  Token _lastTokenInChain(Token firstToken) {
+    Token current = firstToken;
+    while (current.next != null && current.next.type != TokenType.EOF) {
+      current = current.next;
+    }
+    return current;
+  }
+}
+
+mixin _TokenStreamMixin {
+  /// Insert a synthetic identifier after [token] and return the new identifier.
+  Token insertSyntheticIdentifier(Token token, [String value]) {
+    return insertToken(
+        token,
+        new SyntheticStringToken(
+            TokenType.IDENTIFIER, value ?? '', token.next.charOffset, 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));
+
+  /// 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));
+  }
+
+  /// Insert [newToken] after [token] and return [newToken].
+  Token insertToken(Token token, Token newToken);
+}
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
new file mode 100644
index 0000000..b8b39e0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/top_level_parser.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.parser.top_level_parser;
+
+import '../scanner/token.dart' show Token;
+
+import 'declaration_kind.dart' show DeclarationKind;
+
+import 'class_member_parser.dart' show ClassMemberParser;
+
+import 'listener.dart' show Listener;
+
+/// Parser which only parses top-level elements, but ignores their bodies.
+/// Use [Parser] to parse everything.
+class TopLevelParser extends ClassMemberParser {
+  TopLevelParser(Listener listener) : super(listener);
+
+  @override
+  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
new file mode 100644
index 0000000..39c2633
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info.dart
@@ -0,0 +1,346 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.parser.type_info;
+
+import '../scanner/token.dart' show Token, TokenType;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN, KEYWORD_TOKEN;
+
+import 'parser_impl.dart' show Parser;
+
+import 'type_info_impl.dart';
+
+import 'util.dart' show isOneOf, optional;
+
+/// [TypeInfo] provides information collected by [computeType]
+/// about a particular type reference.
+abstract class TypeInfo {
+  /// Return type info representing the receiver without the trailing `?`
+  /// or the receiver if the receiver does not represent a nullable type.
+  TypeInfo get asNonNullable;
+
+  /// Return `true` if the tokens comprising the type represented by the
+  /// receiver could be interpreted as a valid standalone expression.
+  /// For example, `A` or `A.b` could be interpreted as type references
+  /// or expressions, while `A<T>` only looks like a type reference.
+  bool get couldBeExpression;
+
+  /// Return true if the receiver has a trailing `?`.
+  bool get isNullable;
+
+  /// Call this function when the token after [token] must be a type (not void).
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the type, inserting a synthetic type reference if
+  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
+  /// or `>>>=` in valid code or during recovery.
+  Token ensureTypeNotVoid(Token token, Parser parser);
+
+  /// Call this function when the token after [token] must be a type or void.
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the type, inserting a synthetic type reference if
+  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
+  /// or `>>>=` in valid code or during recovery.
+  Token ensureTypeOrVoid(Token token, Parser parser);
+
+  /// Call this function to parse an optional type (not void) after [token].
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the type. This may modify the token stream
+  /// when parsing `>>` or `>>>` or `>>>=`  in valid code or during recovery.
+  Token parseTypeNotVoid(Token token, Parser parser);
+
+  /// Call this function to parse an optional type or void after [token].
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the type. This may modify the token stream
+  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
+  Token parseType(Token token, Parser parser);
+
+  /// Call this function with the [token] before the type to obtain
+  /// the last token in the type. If there is no type, then this method
+  /// will return [token]. This does not modify the token stream.
+  Token skipType(Token token);
+}
+
+/// [TypeParamOrArgInfo] provides information collected by
+/// [computeTypeParamOrArg] about a particular group of type arguments
+/// or type parameters.
+abstract class TypeParamOrArgInfo {
+  const TypeParamOrArgInfo();
+
+  /// Return `true` if the receiver represents a single type argument
+  bool get isSimpleTypeArgument => false;
+
+  /// Return the number of type arguments
+  int get typeArgumentCount;
+
+  /// Return the simple type associated with this simple type argument
+  /// or throw an exception if this is not a simple type argument.
+  TypeInfo get typeInfo {
+    throw "Internal error: $runtimeType is not a SimpleTypeArgument.";
+  }
+
+  /// Call this function to parse optional type arguments after [token].
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the arguments. This may modify the token stream
+  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
+  Token parseArguments(Token token, Parser parser);
+
+  /// Call this function to parse optional type parameters
+  /// (also known as type variables) after [token].
+  /// This function will call the appropriate event methods on the [Parser]'s
+  /// listener to handle the parameters. This may modify the token stream
+  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
+  Token parseVariables(Token token, Parser parser);
+
+  /// Call this function with the [token] before the type var to obtain
+  /// the last token in the type var. If there is no type var, then this method
+  /// will return [token]. This does not modify the token stream.
+  Token skip(Token token);
+}
+
+/// [NoType] is a specialized [TypeInfo] returned by [computeType] when
+/// there is no type information in the source.
+const TypeInfo noType = const NoType();
+
+/// [NoTypeParamOrArg] is a specialized [TypeParamOrArgInfo] returned by
+/// [computeTypeParamOrArg] when no type parameters or arguments are found.
+const TypeParamOrArgInfo noTypeParamOrArg = const NoTypeParamOrArg();
+
+/// [VoidType] is a specialized [TypeInfo] returned by [computeType] when
+/// `void` appears in the source.
+const TypeInfo voidType = const VoidType();
+
+bool isGeneralizedFunctionType(Token token) {
+  return optional('Function', token) &&
+      (optional('<', token.next) || optional('(', token.next));
+}
+
+bool isValidTypeReference(Token token) {
+  int kind = token.kind;
+  if (IDENTIFIER_TOKEN == kind) return true;
+  if (KEYWORD_TOKEN == kind) {
+    TokenType type = token.type;
+    String value = type.lexeme;
+    return type.isPseudo ||
+        (type.isBuiltIn && optional('.', token.next)) ||
+        (identical(value, 'dynamic')) ||
+        (identical(value, 'void'));
+  }
+  return false;
+}
+
+/// Called by the parser to obtain information about a possible type reference
+/// that follows [token]. This does not modify the token stream.
+///
+/// If [inDeclaration] is `true`, then this will more aggressively recover
+/// given unbalanced `<` `>` and invalid parameters or arguments.
+TypeInfo computeType(final Token token, bool required,
+    [bool inDeclaration = false]) {
+  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)) {
+          return new ComplexTypeInfo(token, typeParamOrArg)
+              .computeBuiltinOrVarAsType(required);
+        }
+      } 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))) {
+          return new ComplexTypeInfo(token, typeParamOrArg)
+              .computeBuiltinOrVarAsType(required);
+        }
+      }
+    } else if (required) {
+      // Recovery
+      if (optional('.', next)) {
+        // Looks like prefixed type missing the prefix
+        return new ComplexTypeInfo(
+                token, computeTypeParamOrArg(next, inDeclaration))
+            .computePrefixedType(required);
+      } else if (optional('var', next) &&
+          isOneOf(next.next, const ['<', ',', '>'])) {
+        return new ComplexTypeInfo(
+                token, computeTypeParamOrArg(next, inDeclaration))
+            .computeBuiltinOrVarAsType(required);
+      }
+    }
+    return noType;
+  }
+
+  if (optional('void', next)) {
+    next = next.next;
+    if (isGeneralizedFunctionType(next)) {
+      // `void` `Function` ...
+      return new ComplexTypeInfo(token, noTypeParamOrArg)
+          .computeVoidGFT(required);
+    }
+    // `void`
+    return voidType;
+  }
+
+  if (isGeneralizedFunctionType(next)) {
+    // `Function` ...
+    return new ComplexTypeInfo(token, noTypeParamOrArg)
+        .computeNoTypeGFT(token, required);
+  }
+
+  // We've seen an identifier.
+
+  TypeParamOrArgInfo typeParamOrArg =
+      computeTypeParamOrArg(next, inDeclaration);
+  if (typeParamOrArg != noTypeParamOrArg) {
+    if (typeParamOrArg.isSimpleTypeArgument) {
+      // We've seen identifier `<` identifier `>`
+      next = typeParamOrArg.skip(next).next;
+      if (optional('?', next)) {
+        next = next.next;
+        if (!isGeneralizedFunctionType(next)) {
+          if ((required || looksLikeName(next)) &&
+              typeParamOrArg == simpleTypeArgument1) {
+            // identifier `<` identifier `>` `?` identifier
+            return simpleNullableTypeWith1Argument;
+          }
+          // identifier `<` identifier `>` `?` non-identifier
+          return noType;
+        }
+      } else if (!isGeneralizedFunctionType(next)) {
+        if (required || looksLikeName(next)) {
+          // identifier `<` identifier `>` identifier
+          return typeParamOrArg.typeInfo;
+        }
+        // identifier `<` identifier `>` non-identifier
+        return noType;
+      }
+    }
+    // TODO(danrubel): Consider adding a const for
+    // identifier `<` identifier `,` identifier `>`
+    // if that proves to be a common case.
+
+    // identifier `<` ... `>`
+    return new ComplexTypeInfo(token, typeParamOrArg)
+        .computeSimpleWithTypeArguments(required);
+  }
+
+  assert(typeParamOrArg == noTypeParamOrArg);
+  next = next.next;
+  if (optional('.', next)) {
+    next = next.next;
+    if (isValidTypeReference(next)) {
+      // We've seen identifier `.` identifier
+      typeParamOrArg = computeTypeParamOrArg(next, inDeclaration);
+      next = next.next;
+      if (typeParamOrArg == noTypeParamOrArg) {
+        if (optional('?', next)) {
+          next = next.next;
+          if (!isGeneralizedFunctionType(next)) {
+            if (required || looksLikeName(next)) {
+              // identifier `.` identifier `?` identifier
+              // TODO(danrubel): consider adding PrefixedNullableType
+              // Fall through to build complex type
+            } else {
+              // identifier `.` identifier `?` non-identifier
+              return noType;
+            }
+          }
+        } else {
+          if (!isGeneralizedFunctionType(next)) {
+            if (required || looksLikeName(next)) {
+              // identifier `.` identifier identifier
+              return prefixedType;
+            } else {
+              // identifier `.` identifier non-identifier
+              return noType;
+            }
+          }
+        }
+      }
+      // identifier `.` identifier
+      return new ComplexTypeInfo(token, typeParamOrArg)
+          .computePrefixedType(required);
+    }
+    // identifier `.` non-identifier
+    if (required) {
+      typeParamOrArg = computeTypeParamOrArg(token.next.next, inDeclaration);
+      return new ComplexTypeInfo(token, typeParamOrArg)
+          .computePrefixedType(required);
+    }
+    return noType;
+  }
+
+  assert(typeParamOrArg == noTypeParamOrArg);
+  if (isGeneralizedFunctionType(next)) {
+    // identifier `Function`
+    return new ComplexTypeInfo(token, noTypeParamOrArg)
+        .computeIdentifierGFT(required);
+  }
+
+  if (optional('?', next)) {
+    next = next.next;
+    if (isGeneralizedFunctionType(next)) {
+      // identifier `?` Function `(`
+      return new ComplexTypeInfo(token, noTypeParamOrArg)
+          .computeIdentifierQuestionGFT(required);
+    } else if (required || looksLikeName(next)) {
+      // identifier `?`
+      return simpleNullableType;
+    }
+  } else if (required || looksLikeName(next)) {
+    // identifier identifier
+    return simpleType;
+  }
+  return noType;
+}
+
+/// Called by the parser to obtain information about a possible group of type
+/// parameters or type arguments that follow [token].
+/// This does not modify the token stream.
+///
+/// If [inDeclaration] is `true`, then this will more aggressively recover
+/// given unbalanced `<` `>` and invalid parameters or arguments.
+TypeParamOrArgInfo computeTypeParamOrArg(Token token,
+    [bool inDeclaration = false, bool allowsVariance = false]) {
+  Token beginGroup = token.next;
+  if (!optional('<', beginGroup)) {
+    return noTypeParamOrArg;
+  }
+
+  // identifier `<` `void` `>` and `<` `dynamic` `>`
+  // are handled by ComplexTypeInfo.
+  Token next = beginGroup.next;
+  if ((next.kind == IDENTIFIER_TOKEN || next.type.isPseudo)) {
+    if (optional('>', next.next)) {
+      return simpleTypeArgument1;
+    } else if (optional('>>', next.next)) {
+      return simpleTypeArgument1GtGt;
+    } else if (optional('>=', next.next)) {
+      return simpleTypeArgument1GtEq;
+    }
+  } else if (optional('(', next)) {
+    return noTypeParamOrArg;
+  }
+
+  // TODO(danrubel): Consider adding additional const for common situations.
+  return new ComplexTypeParamOrArgInfo(token, inDeclaration, allowsVariance)
+      .compute();
+}
+
+/// Called by the parser to obtain information about a possible group of type
+/// type arguments that follow [token] and that are followed by '('.
+/// Returns the type arguments if [token] matches '<' type (',' type)* '>' '(',
+/// and otherwise returns [noTypeParamOrArg]. The final '(' is not part of the
+/// grammar construct `typeArguments`, but it is required here such that type
+/// arguments in generic method invocations can be recognized, and as few as
+/// 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;
+}
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
new file mode 100644
index 0000000..465402a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/type_info_impl.dart
@@ -0,0 +1,1263 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.parser.type_info_impl;
+
+import '../messages/codes.dart' as codes;
+
+import '../scanner/token.dart' show SyntheticToken, Token, TokenType;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import '../util/link.dart' show Link;
+
+import 'forwarding_listener.dart' show ForwardingListener;
+
+import 'identifier_context.dart' show IdentifierContext;
+
+import 'member_kind.dart' show MemberKind;
+
+import 'listener.dart' show Listener;
+
+import 'parser_impl.dart' show Parser;
+
+import 'type_info.dart';
+
+import 'util.dart'
+    show
+        optional,
+        skipMetadata,
+        splitGtEq,
+        splitGtFromGtGtEq,
+        splitGtFromGtGtGt,
+        splitGtFromGtGtGtEq,
+        splitGtGt,
+        syntheticGt;
+
+/// [SimpleType] is a specialized [TypeInfo] returned by [computeType]
+/// when there is a single identifier as the type reference.
+const TypeInfo simpleType = const SimpleType();
+
+/// [SimpleNullableType] is a specialized [TypeInfo] returned by [computeType]
+/// when there is a single identifier followed by `?` as the type reference.
+const TypeInfo simpleNullableType = const SimpleNullableType();
+
+/// [PrefixedType] is a specialized [TypeInfo] returned by [computeType]
+/// when the type reference is of the form: identifier `.` identifier.
+const TypeInfo prefixedType = const PrefixedType();
+
+/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
+/// [computeType] when the type reference is of the form:
+/// identifier `<` identifier `>`.
+const TypeInfo simpleTypeWith1Argument =
+    const SimpleTypeWith1Argument(simpleTypeArgument1);
+
+/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
+/// [computeType] when the type reference is of the form:
+/// identifier `<` identifier `>=`.
+const TypeInfo simpleTypeWith1ArgumentGtEq =
+    const SimpleTypeWith1Argument(simpleTypeArgument1GtEq);
+
+/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
+/// [computeType] when the type reference is of the form:
+/// identifier `<` identifier `>>`.
+const TypeInfo simpleTypeWith1ArgumentGtGt =
+    const SimpleTypeWith1Argument(simpleTypeArgument1GtGt);
+
+/// [SimpleNullableTypeWith1Argument] is a specialized [TypeInfo] returned by
+/// [computeType] when the type reference is of the form:
+/// identifier `<` identifier `>` `?`.
+const TypeInfo simpleNullableTypeWith1Argument =
+    const SimpleNullableTypeWith1Argument();
+
+/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
+/// [computeTypeParamOrArg] when the type reference is of the form:
+/// `<` identifier `>`.
+const TypeParamOrArgInfo simpleTypeArgument1 = const SimpleTypeArgument1();
+
+/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
+/// [computeTypeParamOrArg] when the type reference is of the form:
+/// `<` identifier `>=`.
+const TypeParamOrArgInfo simpleTypeArgument1GtEq =
+    const SimpleTypeArgument1GtEq();
+
+/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
+/// [computeTypeParamOrArg] when the type reference is of the form:
+/// `<` identifier `>>`.
+const TypeParamOrArgInfo simpleTypeArgument1GtGt =
+    const SimpleTypeArgument1GtGt();
+
+/// See documentation on the [noType] const.
+class NoType implements TypeInfo {
+  const NoType();
+
+  @override
+  TypeInfo get asNonNullable => this;
+
+  @override
+  bool get couldBeExpression => false;
+
+  @override
+  bool get isNullable => false;
+
+  @override
+  Token ensureTypeNotVoid(Token token, Parser parser) {
+    parser.reportRecoverableErrorWithToken(
+        token.next, codes.templateExpectedType);
+    parser.rewriter.insertSyntheticIdentifier(token);
+    return simpleType.parseType(token, parser);
+  }
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      ensureTypeNotVoid(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    parser.listener.handleNoType(token);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return token;
+  }
+}
+
+/// See documentation on the [prefixedType] const.
+class PrefixedType implements TypeInfo {
+  const PrefixedType();
+
+  @override
+  TypeInfo get asNonNullable => this;
+
+  @override
+  bool get couldBeExpression => true;
+
+  @override
+  bool get isNullable => false;
+
+  @override
+  Token ensureTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    Token start = token = token.next;
+    assert(token.isKeywordOrIdentifier);
+    Listener listener = parser.listener;
+    listener.handleIdentifier(token, IdentifierContext.prefixedTypeReference);
+
+    Token period = token = token.next;
+    assert(optional('.', token));
+
+    token = token.next;
+    assert(token.isKeywordOrIdentifier);
+    listener.handleIdentifier(
+        token, IdentifierContext.typeReferenceContinuation);
+    listener.handleQualified(period);
+
+    listener.handleNoTypeArguments(token.next);
+    listener.handleType(start, null);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return token.next.next.next;
+  }
+}
+
+/// See documentation on the [simpleNullableTypeWith1Argument] const.
+class SimpleNullableTypeWith1Argument extends SimpleTypeWith1Argument {
+  const SimpleNullableTypeWith1Argument() : super(simpleTypeArgument1);
+
+  @override
+  TypeInfo get asNonNullable => simpleTypeWith1Argument;
+
+  @override
+  bool get isNullable => true;
+
+  @override
+  Token parseTypeRest(Token start, Token token, Parser parser) {
+    token = token.next;
+    assert(optional('?', token));
+    parser.listener.handleType(start, token);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    token = super.skipType(token).next;
+    assert(optional('?', token));
+    return token;
+  }
+}
+
+/// See documentation on the [simpleTypeWith1Argument] const.
+class SimpleTypeWith1Argument implements TypeInfo {
+  final TypeParamOrArgInfo typeArg;
+
+  const SimpleTypeWith1Argument(this.typeArg);
+
+  @override
+  TypeInfo get asNonNullable => this;
+
+  @override
+  bool get couldBeExpression => false;
+
+  @override
+  bool get isNullable => false;
+
+  @override
+  Token ensureTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    Token start = token = token.next;
+    assert(token.isKeywordOrIdentifier);
+    parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
+    token = typeArg.parseArguments(token, parser);
+    return parseTypeRest(start, token, parser);
+  }
+
+  Token parseTypeRest(Token start, Token token, Parser parser) {
+    parser.listener.handleType(start, null);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    token = token.next;
+    assert(token.isKeywordOrIdentifier);
+    return typeArg.skip(token);
+  }
+}
+
+/// See documentation on the [simpleNullableType] const.
+class SimpleNullableType extends SimpleType {
+  const SimpleNullableType();
+
+  @override
+  TypeInfo get asNonNullable => simpleType;
+
+  @override
+  bool get isNullable => true;
+
+  @override
+  Token parseTypeRest(Token start, Parser parser) {
+    Token token = start.next;
+    assert(optional('?', token));
+    parser.listener.handleType(start, token);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return token.next.next;
+  }
+}
+
+/// See documentation on the [simpleType] const.
+class SimpleType implements TypeInfo {
+  const SimpleType();
+
+  @override
+  TypeInfo get asNonNullable => this;
+
+  @override
+  bool get couldBeExpression => true;
+
+  @override
+  bool get isNullable => false;
+
+  @override
+  Token ensureTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    token = token.next;
+    assert(isValidTypeReference(token));
+    parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
+    token = noTypeParamOrArg.parseArguments(token, parser);
+    return parseTypeRest(token, parser);
+  }
+
+  Token parseTypeRest(Token token, Parser parser) {
+    parser.listener.handleType(token, null);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return token.next;
+  }
+}
+
+/// See documentation on the [voidType] const.
+class VoidType implements TypeInfo {
+  const VoidType();
+
+  @override
+  TypeInfo get asNonNullable => this;
+
+  @override
+  bool get couldBeExpression => false;
+
+  @override
+  bool get isNullable => false;
+
+  @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);
+    return simpleType.parseTypeNotVoid(token, parser);
+  }
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      ensureTypeNotVoid(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    token = token.next;
+    parser.listener.handleVoidKeyword(token);
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return token.next;
+  }
+}
+
+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));
+
+/// 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;
+    if (next.kind == IDENTIFIER_TOKEN ||
+        optional(',', next) ||
+        isCloser(next)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/// Instances of [ComplexTypeInfo] are returned by [computeType] to represent
+/// type references that cannot be represented by the constants above.
+class ComplexTypeInfo implements TypeInfo {
+  /// The first token in the type reference.
+  Token start;
+
+  /// Type arguments were seen during analysis.
+  final TypeParamOrArgInfo typeArguments;
+
+  /// 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;
+
+  /// The last token in the type reference.
+  Token end;
+
+  /// The `Function` tokens before the start of type variables of function types
+  /// as seen during analysis.
+  Link<Token> typeVariableStarters = const Link<Token>();
+
+  /// If the receiver represents a generalized function type then this indicates
+  /// whether it has a return type, otherwise this is `null`.
+  bool gftHasReturnType;
+
+  ComplexTypeInfo(Token beforeStart, this.typeArguments)
+      : this.start = beforeStart.next {
+    assert(typeArguments != null);
+  }
+
+  ComplexTypeInfo._nonNullable(this.start, this.typeArguments, this.end,
+      this.typeVariableStarters, this.gftHasReturnType);
+
+  @override
+  TypeInfo get asNonNullable {
+    return beforeQuestionMark == null
+        ? this
+        : new ComplexTypeInfo._nonNullable(start, typeArguments,
+            beforeQuestionMark, typeVariableStarters, gftHasReturnType);
+  }
+
+  @override
+  bool get couldBeExpression =>
+      typeArguments == noTypeParamOrArg && typeVariableStarters.isEmpty;
+
+  @override
+  bool get isNullable => beforeQuestionMark != null;
+
+  @override
+  Token ensureTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token ensureTypeOrVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseTypeNotVoid(Token token, Parser parser) =>
+      parseType(token, parser);
+
+  @override
+  Token parseType(Token token, Parser parser) {
+    assert(identical(token.next, start));
+
+    if (optional('.', start)) {
+      // Recovery: Insert missing identifier without sending events
+      start = parser.insertSyntheticIdentifier(
+          token, IdentifierContext.prefixedTypeReference);
+    }
+
+    final List<Token> typeVariableEndGroups = <Token>[];
+    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
+      typeVariableEndGroups.add(
+          computeTypeParamOrArg(t.head, true).parseVariables(t.head, parser));
+      parser.listener.beginFunctionType(start);
+    }
+
+    if (gftHasReturnType == false) {
+      // A function type without return type.
+      // Push the non-existing return type first. The loop below will
+      // generate the full type.
+      noType.parseType(token, parser);
+    } else {
+      Token typeRefOrPrefix = token.next;
+      if (optional('void', typeRefOrPrefix)) {
+        token = voidType.parseType(token, parser);
+      } else {
+        if (!optional('.', typeRefOrPrefix) &&
+            !optional('.', typeRefOrPrefix.next)) {
+          token =
+              parser.ensureIdentifier(token, IdentifierContext.typeReference);
+        } else {
+          token = parser.ensureIdentifier(
+              token, IdentifierContext.prefixedTypeReference);
+          token = parser.parseQualifiedRest(
+              token, IdentifierContext.typeReferenceContinuation);
+          if (token.isSynthetic && end == typeRefOrPrefix.next) {
+            // Recovery: Update `end` if a synthetic identifier was inserted.
+            end = token;
+          }
+        }
+        token = typeArguments.parseArguments(token, parser);
+
+        // Only consume the `?` if it is part of the complex type
+        Token questionMark = token.next;
+        if (optional('?', questionMark) &&
+            (typeVariableEndGroups.isNotEmpty || beforeQuestionMark != null)) {
+          token = questionMark;
+        } else {
+          questionMark = null;
+        }
+
+        parser.listener.handleType(typeRefOrPrefix, questionMark);
+      }
+    }
+
+    int endGroupIndex = typeVariableEndGroups.length - 1;
+    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
+      token = token.next;
+      assert(optional('Function', token));
+      Token functionToken = token;
+
+      if (optional("<", token.next)) {
+        // Skip type parameters, they were parsed above.
+        token = typeVariableEndGroups[endGroupIndex];
+        assert(optional('>', token));
+      }
+      token = parser.parseFormalParametersRequiredOpt(
+          token, MemberKind.GeneralizedFunctionType);
+
+      // Only consume the `?` if it is part of the complex type
+      Token questionMark = token.next;
+      if (optional('?', questionMark) &&
+          (endGroupIndex > 0 || beforeQuestionMark != null)) {
+        token = questionMark;
+      } else {
+        questionMark = null;
+      }
+
+      --endGroupIndex;
+      parser.listener.endFunctionType(functionToken, questionMark);
+    }
+
+    // There are two situations in which the [token] != [end]:
+    // Valid code:    identifier `<` identifier `<` identifier `>>`
+    //    where `>>` is replaced by two tokens.
+    // Invalid code:  identifier `<` identifier identifier `>`
+    //    where a synthetic `>` is inserted between the identifiers.
+    assert(identical(token, end) || optional('>', token));
+
+    // During recovery, [token] may be a synthetic that was inserted in the
+    // middle of the type reference.
+    end = token;
+    return token;
+  }
+
+  @override
+  Token skipType(Token token) {
+    return end;
+  }
+
+  /// Given `Function` non-identifier, compute the type
+  /// and return the receiver or one of the [TypeInfo] constants.
+  TypeInfo computeNoTypeGFT(Token beforeStart, bool required) {
+    assert(optional('Function', start));
+    assert(beforeStart.next == start);
+
+    computeRest(beforeStart, required);
+    if (gftHasReturnType == null) {
+      return required ? simpleType : noType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  /// Given void `Function` non-identifier, compute the type
+  /// and return the receiver or one of the [TypeInfo] constants.
+  TypeInfo computeVoidGFT(bool required) {
+    assert(optional('void', start));
+    assert(optional('Function', start.next));
+
+    computeRest(start, required);
+    if (gftHasReturnType == null) {
+      return voidType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  /// Given identifier `Function` non-identifier, compute the type
+  /// and return the receiver or one of the [TypeInfo] constants.
+  TypeInfo computeIdentifierGFT(bool required) {
+    assert(isValidTypeReference(start));
+    assert(optional('Function', start.next));
+
+    computeRest(start, required);
+    if (gftHasReturnType == null) {
+      return simpleType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  /// Given identifier `?` `Function` non-identifier, compute the type
+  /// 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));
+
+    computeRest(start, required);
+    if (gftHasReturnType == null) {
+      return simpleNullableType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  /// Given a builtin, return the receiver so that parseType will report
+  /// an error for the builtin used as a type.
+  TypeInfo computeBuiltinOrVarAsType(bool required) {
+    assert(start.type.isBuiltIn || optional('var', start));
+
+    end = typeArguments.skip(start);
+    computeRest(end, required);
+    assert(end != null);
+    return this;
+  }
+
+  /// Given identifier `<` ... `>`, compute the type
+  /// and return the receiver or one of the [TypeInfo] constants.
+  TypeInfo computeSimpleWithTypeArguments(bool required) {
+    assert(isValidTypeReference(start));
+    assert(optional('<', start.next));
+    assert(typeArguments != noTypeParamOrArg);
+
+    end = typeArguments.skip(start);
+    computeRest(end, required);
+
+    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
+      return noType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  /// Given identifier `.` identifier (or `.` identifier or identifier `.`
+  /// for recovery), compute the type and return the receiver or one of the
+  /// [TypeInfo] constants.
+  TypeInfo computePrefixedType(bool required) {
+    Token token = start;
+    if (!optional('.', token)) {
+      assert(token.isKeywordOrIdentifier);
+      token = token.next;
+    }
+    assert(optional('.', token));
+    if (token.next.isKeywordOrIdentifier) {
+      token = token.next;
+    }
+
+    end = typeArguments.skip(token);
+    computeRest(end, required);
+    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
+      return noType;
+    }
+    assert(end != null);
+    return this;
+  }
+
+  void computeRest(Token token, bool required) {
+    if (optional('?', token.next)) {
+      beforeQuestionMark = token;
+      end = token = token.next;
+    }
+    token = token.next;
+    while (optional('Function', token)) {
+      Token typeVariableStart = token;
+      // TODO(danrubel): Consider caching TypeParamOrArgInfo
+      token = computeTypeParamOrArg(token, true).skip(token);
+      token = token.next;
+      if (!optional('(', token)) {
+        break; // Not a function type.
+      }
+      token = token.endGroup;
+      if (token == null) {
+        break; // Not a function type.
+      }
+      if (!required) {
+        Token next = token.next;
+        if (optional('?', next)) {
+          next = next.next;
+        }
+        if (!(next.isIdentifier || optional('this', next))) {
+          break; // `Function` used as the name in a function declaration.
+        }
+      }
+      assert(optional(')', token));
+      gftHasReturnType ??= typeVariableStart != start;
+      typeVariableStarters = typeVariableStarters.prepend(typeVariableStart);
+
+      beforeQuestionMark = null;
+      end = token;
+      token = token.next;
+
+      if (optional('?', token)) {
+        beforeQuestionMark = end;
+        end = token;
+        token = token.next;
+      }
+    }
+  }
+}
+
+/// See [noTypeParamOrArg].
+class NoTypeParamOrArg extends TypeParamOrArgInfo {
+  const NoTypeParamOrArg();
+
+  @override
+  int get typeArgumentCount => 0;
+
+  @override
+  Token parseArguments(Token token, Parser parser) {
+    parser.listener.handleNoTypeArguments(token.next);
+    return token;
+  }
+
+  @override
+  Token parseVariables(Token token, Parser parser) {
+    parser.listener.handleNoTypeVariables(token.next);
+    return token;
+  }
+
+  @override
+  Token skip(Token token) => token;
+}
+
+class SimpleTypeArgument1 extends TypeParamOrArgInfo {
+  const SimpleTypeArgument1();
+
+  @override
+  bool get isSimpleTypeArgument => true;
+
+  @override
+  int get typeArgumentCount => 1;
+
+  @override
+  TypeInfo get typeInfo => simpleTypeWith1Argument;
+
+  @override
+  Token parseArguments(Token token, Parser parser) {
+    Token beginGroup = token.next;
+    assert(optional('<', beginGroup));
+    Token endGroup = parseEndGroup(beginGroup, beginGroup.next);
+    Listener listener = parser.listener;
+    listener.beginTypeArguments(beginGroup);
+    simpleType.parseType(beginGroup, parser);
+    parser.listener.endTypeArguments(1, beginGroup, endGroup);
+    return endGroup;
+  }
+
+  @override
+  Token parseVariables(Token token, Parser parser) {
+    Token beginGroup = token.next;
+    assert(optional('<', beginGroup));
+    token = beginGroup.next;
+    Token endGroup = parseEndGroup(beginGroup, token);
+    Listener listener = parser.listener;
+    listener.beginTypeVariables(beginGroup);
+    listener.beginMetadataStar(token);
+    listener.endMetadataStar(0);
+    listener.handleIdentifier(token, IdentifierContext.typeVariableDeclaration);
+    listener.beginTypeVariable(token);
+    listener.handleTypeVariablesDefined(token, 1);
+    listener.handleNoType(token);
+    listener.endTypeVariable(endGroup, 0, null, null);
+    listener.endTypeVariables(beginGroup, endGroup);
+    return endGroup;
+  }
+
+  @override
+  Token skip(Token token) {
+    token = token.next;
+    assert(optional('<', token));
+    token = token.next;
+    assert(token.isKeywordOrIdentifier);
+    return skipEndGroup(token);
+  }
+
+  Token skipEndGroup(Token token) {
+    token = token.next;
+    assert(optional('>', token));
+    return token;
+  }
+
+  Token parseEndGroup(Token beginGroup, Token token) {
+    token = token.next;
+    assert(optional('>', token));
+    return token;
+  }
+}
+
+class SimpleTypeArgument1GtEq extends SimpleTypeArgument1 {
+  const SimpleTypeArgument1GtEq();
+
+  @override
+  TypeInfo get typeInfo => simpleTypeWith1ArgumentGtEq;
+
+  Token skipEndGroup(Token token) {
+    token = token.next;
+    assert(optional('>=', token));
+    return splitGtEq(token);
+  }
+
+  Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
+    Token endGroup = beforeEndGroup.next;
+    if (!optional('>', endGroup)) {
+      endGroup = splitGtEq(endGroup);
+      endGroup.next.setNext(endGroup.next.next);
+    }
+    beforeEndGroup.setNext(endGroup);
+    return endGroup;
+  }
+}
+
+class SimpleTypeArgument1GtGt extends SimpleTypeArgument1 {
+  const SimpleTypeArgument1GtGt();
+
+  @override
+  TypeInfo get typeInfo => simpleTypeWith1ArgumentGtGt;
+
+  Token skipEndGroup(Token token) {
+    token = token.next;
+    assert(optional('>>', token));
+    return splitGtGt(token);
+  }
+
+  Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
+    Token endGroup = beforeEndGroup.next;
+    if (!optional('>', endGroup)) {
+      endGroup = splitGtGt(endGroup);
+      endGroup.next.setNext(endGroup.next.next);
+    }
+    beforeEndGroup.setNext(endGroup);
+    return endGroup;
+  }
+}
+
+class ComplexTypeParamOrArgInfo extends TypeParamOrArgInfo {
+  /// The first token in the type var.
+  final Token start;
+
+  /// If [inDeclaration] is `true`, then this will more aggressively recover
+  /// given unbalanced `<` `>` and invalid parameters or arguments.
+  final bool inDeclaration;
+
+  // Only support variance parsing if it makes sense.
+  // Allows parsing of variance for certain structures.
+  // See https://github.com/dart-lang/language/issues/524
+  final bool allowsVariance;
+
+  @override
+  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;
+
+  ComplexTypeParamOrArgInfo(
+      Token token, this.inDeclaration, this.allowsVariance)
+      : assert(optional('<', token.next)),
+        assert(inDeclaration != null),
+        assert(allowsVariance != null),
+        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
+  /// stream.
+  TypeParamOrArgInfo compute() {
+    Token token;
+    Token next = start;
+    typeArgumentCount = 0;
+    while (true) {
+      TypeInfo typeInfo = computeType(next, true, inDeclaration);
+      if (typeInfo == noType) {
+        while (typeInfo == noType && optional('@', next.next)) {
+          next = skipMetadata(next);
+          typeInfo = computeType(next, true, inDeclaration);
+        }
+        if (typeInfo == noType) {
+          if (next == start && !inDeclaration && !isCloser(next.next)) {
+            return noTypeParamOrArg;
+          }
+          if (!optional(',', next.next)) {
+            token = next;
+            next = token.next;
+            break;
+          }
+        }
+        assert(typeInfo != noType || optional(',', next.next));
+        // Fall through to process type (if any) and consume `,`
+      }
+      ++typeArgumentCount;
+      token = typeInfo.skipType(next);
+      next = token.next;
+      if (optional('extends', next)) {
+        token = computeType(next, true, inDeclaration).skipType(next);
+        next = token.next;
+      }
+      if (!optional(',', next)) {
+        skipEnd = splitCloser(next);
+        if (skipEnd != null) {
+          return this;
+        }
+        if (!inDeclaration) {
+          return noTypeParamOrArg;
+        }
+
+        // Recovery
+        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+          break;
+        }
+        // Looks like missing comma. Continue looping.
+        next = token;
+      }
+    }
+
+    // Recovery
+    skipEnd = splitCloser(next);
+    if (skipEnd == null) {
+      if (optional('(', next)) {
+        token = next.endGroup;
+        next = token.next;
+      }
+      skipEnd = splitCloser(next);
+      if (skipEnd == null) {
+        skipEnd = splitCloser(next.next);
+      }
+      if (skipEnd == null) {
+        skipEnd = syntheticGt(next);
+      }
+    }
+    return this;
+  }
+
+  @override
+  Token parseArguments(Token token, Parser parser) {
+    assert(identical(token.next, start));
+    Token next = start;
+    parser.listener.beginTypeArguments(start);
+    int count = 0;
+    while (true) {
+      TypeInfo typeInfo = computeType(next, true, inDeclaration);
+      if (typeInfo == noType) {
+        // Recovery
+        while (typeInfo == noType && optional('@', next.next)) {
+          parser.reportRecoverableErrorWithToken(
+              next.next, codes.templateUnexpectedToken);
+          next = skipMetadata(next);
+          typeInfo = computeType(next, true, inDeclaration);
+        }
+        // Fall through to process type (if any) and consume `,`
+      }
+      token = typeInfo.ensureTypeOrVoid(next, parser);
+      next = token.next;
+      ++count;
+      if (!optional(',', next)) {
+        if (parseCloser(token)) {
+          break;
+        }
+
+        // Recovery
+        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+          token = parseUnexpectedEnd(token, true, parser);
+          break;
+        }
+        // Missing comma. Report error, insert comma, and continue looping.
+        next = parseMissingComma(token, parser);
+      }
+    }
+    Token endGroup = token.next;
+    parser.listener.endTypeArguments(count, start, endGroup);
+    return endGroup;
+  }
+
+  @override
+  Token parseVariables(Token token, Parser parser) {
+    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>();
+
+    while (true) {
+      token = parser.parseMetadataStar(next);
+
+      Token variance = next.next;
+      Token identifier = variance.next;
+      if (allowsVariance &&
+          isVariance(variance) &&
+          identifier != null &&
+          identifier.isKeywordOrIdentifier) {
+        variances = variances.prepend(variance);
+
+        // Recovery for multiple variance modifiers
+        while (isVariance(identifier) &&
+            identifier.next != null &&
+            identifier.next.isKeywordOrIdentifier) {
+          // Report an error and skip actual identifier
+          parser.reportRecoverableError(
+              identifier, codes.messageMultipleVarianceModifiers);
+          variance = variance.next;
+          identifier = identifier.next;
+        }
+
+        token = variance;
+      } else {
+        variances = variances.prepend(null);
+      }
+
+      next = parser.ensureIdentifier(
+          token, IdentifierContext.typeVariableDeclaration);
+      token = next;
+      listener.beginTypeVariable(token);
+      typeStarts = typeStarts.prepend(token);
+
+      next = token.next;
+      if (optional('extends', next)) {
+        TypeInfo typeInfo = computeType(next, true, inDeclaration);
+        token = typeInfo.skipType(next);
+        next = token.next;
+        superTypeInfos = superTypeInfos.prepend(typeInfo);
+      } else {
+        superTypeInfos = superTypeInfos.prepend(null);
+      }
+
+      ++count;
+      if (!optional(',', next)) {
+        if (isCloser(token)) {
+          break;
+        }
+
+        // Recovery
+        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
+          break;
+        }
+        // Missing comma. Report error, insert comma, and continue looping.
+        next = parseMissingComma(token, parser);
+      }
+    }
+
+    assert(count > 0);
+    assert(typeStarts.slowLength() == count);
+    assert(superTypeInfos.slowLength() == count);
+    assert(variances.slowLength() == count);
+    listener.handleTypeVariablesDefined(token, count);
+
+    token = null;
+    while (typeStarts.isNotEmpty) {
+      Token token2 = typeStarts.head;
+      TypeInfo typeInfo = superTypeInfos.head;
+      Token variance = variances.head;
+
+      Token extendsOrSuper = null;
+      Token next2 = token2.next;
+      if (typeInfo != null) {
+        assert(optional('extends', next2));
+        extendsOrSuper = next2;
+        token2 = typeInfo.ensureTypeNotVoid(next2, parser);
+        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;
+      listener.endTypeVariable(next2, --count, extendsOrSuper, variance);
+
+      typeStarts = typeStarts.tail;
+      superTypeInfos = superTypeInfos.tail;
+      variances = variances.tail;
+    }
+
+    if (!parseCloser(token)) {
+      token = parseUnexpectedEnd(token, false, parser);
+    }
+    Token endGroup = token.next;
+    listener.endTypeVariables(start, endGroup);
+    return endGroup;
+  }
+
+  Token parseMissingComma(Token token, Parser parser) {
+    Token next = token.next;
+    parser.reportRecoverableError(
+        next, codes.templateExpectedButGot.withArguments(','));
+    return parser.rewriter.insertToken(
+        token, new SyntheticToken(TokenType.COMMA, next.charOffset));
+  }
+
+  Token parseUnexpectedEnd(Token token, bool isArguments, Parser parser) {
+    Token next = token.next;
+    bool errorReported = token.isSynthetic || (next.isSynthetic && !next.isEof);
+
+    bool typeFollowsExtends = false;
+    if (optional('extends', next)) {
+      if (!errorReported) {
+        parser.reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments('>'));
+        errorReported = true;
+      }
+      token = next;
+      next = token.next;
+      typeFollowsExtends = isValidTypeReference(next);
+
+      if (parseCloser(token)) {
+        return token;
+      }
+    }
+
+    if (typeFollowsExtends ||
+        optional('dynamic', next) ||
+        optional('void', next) ||
+        optional('Function', next)) {
+      TypeInfo invalidType = computeType(token, true);
+      if (invalidType != noType) {
+        if (!errorReported) {
+          parser.reportRecoverableError(
+              token, codes.templateExpectedAfterButGot.withArguments('>'));
+          errorReported = true;
+        }
+
+        // Parse the type so that the token stream is properly modified,
+        // but ensure that parser events are ignored by replacing the listener.
+        final Listener originalListener = parser.listener;
+        parser.listener = new ForwardingListener();
+        token = invalidType.parseType(token, parser);
+        next = token.next;
+        parser.listener = originalListener;
+
+        if (parseCloser(token)) {
+          return token;
+        }
+      }
+    }
+
+    TypeParamOrArgInfo invalidTypeVar =
+        computeTypeParamOrArg(token, inDeclaration);
+    if (invalidTypeVar != noTypeParamOrArg) {
+      if (!errorReported) {
+        parser.reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments('>'));
+        errorReported = true;
+      }
+
+      // Parse the type so that the token stream is properly modified,
+      // but ensure that parser events are ignored by replacing the listener.
+      final Listener originalListener = parser.listener;
+      parser.listener = new ForwardingListener();
+      token = isArguments
+          ? invalidTypeVar.parseArguments(token, parser)
+          : invalidTypeVar.parseVariables(token, parser);
+      next = token.next;
+      parser.listener = originalListener;
+
+      if (parseCloser(token)) {
+        return token;
+      }
+    }
+
+    if (optional('(', next) && next.endGroup != null) {
+      if (!errorReported) {
+        // Only report an error if one has not already been reported.
+        parser.reportRecoverableError(
+            token, codes.templateExpectedAfterButGot.withArguments('>'));
+        errorReported = true;
+      }
+      token = next.endGroup;
+      next = token.next;
+
+      if (parseCloser(token)) {
+        return token;
+      }
+    }
+
+    if (!errorReported) {
+      // Only report an error if one has not already been reported.
+      parser.reportRecoverableError(
+          token, codes.templateExpectedAfterButGot.withArguments('>'));
+    }
+    if (parseCloser(next)) {
+      return next;
+    }
+    Token endGroup = start.endGroup;
+    if (endGroup != null) {
+      while (token.next != endGroup && !token.isEof) {
+        token = token.next;
+      }
+    } else {
+      endGroup = syntheticGt(next);
+      endGroup.setNext(next);
+      token.setNext(endGroup);
+    }
+    return token;
+  }
+
+  @override
+  Token skip(Token token) {
+    assert(skipEnd != null);
+    return skipEnd;
+  }
+}
+
+// Return `true` if [token] is one of `in`, `inout`, or `out`
+bool isVariance(Token token) {
+  return optional('in', token) ||
+      optional('inout', token) ||
+      optional('out', token);
+}
+
+/// Return `true` if [token] is one of `>`, `>>`, `>>>`, `>=`, `>>=`, or `>>>=`.
+bool isCloser(Token token) {
+  final String value = token.stringValue;
+  return identical(value, '>') ||
+      identical(value, '>>') ||
+      identical(value, '>=') ||
+      identical(value, '>>>') ||
+      identical(value, '>>=') ||
+      identical(value, '>>>=');
+}
+
+/// 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);
+  if (split == unsplit) {
+    return true;
+  } else if (split == null) {
+    return false;
+  }
+  split.next.setNext(unsplit.next);
+  beforeCloser.setNext(split);
+  return true;
+}
+
+/// If [closer] is `>` then return it.
+/// 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;
+  if (identical(value, '>')) {
+    return closer;
+  } else if (identical(value, '>>')) {
+    return splitGtGt(closer);
+  } else if (identical(value, '>=')) {
+    return splitGtEq(closer);
+  } else if (identical(value, '>>>')) {
+    return splitGtFromGtGtGt(closer);
+  } else if (identical(value, '>>=')) {
+    return splitGtFromGtGtEq(closer);
+  } else if (identical(value, '>>>=')) {
+    return splitGtFromGtGtGtEq(closer);
+  }
+  return null;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/util.dart b/pkg/_fe_analyzer_shared/lib/src/parser/util.dart
new file mode 100644
index 0000000..dfe02c8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/util.dart
@@ -0,0 +1,207 @@
+// 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.
+
+library _fe_analyzer_shared.parser.util;
+
+import '../messages/codes.dart' show noLength;
+
+import '../scanner/scanner.dart' show Token;
+
+import '../scanner/token.dart'
+    show BeginToken, SimpleToken, SyntheticToken, TokenType;
+
+/// Returns true if [token] is the symbol or keyword [value].
+bool optional(String value, Token token) {
+  return identical(value, token.stringValue);
+}
+
+/// 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;
+  if (endToken == null) {
+    return null;
+  }
+  Token token = left;
+  Token next = token.next;
+  while (next != endToken && next != next.next) {
+    token = next;
+    next = token.next;
+  }
+  return token;
+}
+
+/// Return [token] or a token before [token] which is either
+/// not synthetic or synthetic with non-zero length.
+Token findPreviousNonZeroLengthToken(Token token) {
+  while (token.isSynthetic && token.length == 0) {
+    Token previous = token.beforeSynthetic;
+    if (previous == token) {
+      throw new StateError("token == token.beforeSynthetic");
+    }
+    if (previous == null) {
+      break;
+    }
+    token = previous;
+  }
+  return token;
+}
+
+/// Return [token] or a token after [token] which is either
+/// not synthetic or synthetic with non-zero length.
+/// 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;
+  }
+  return token;
+}
+
+bool isDigit(int c) => c >= 0x30 && c <= 0x39;
+
+bool isLetter(int c) => c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
+
+bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
+
+bool isWhitespace(int c) => c == 0x20 || c == 0xA || c == 0xD || c == 0x9;
+
+/// Return true if the given token matches one of the given values.
+bool isOneOf(Token token, Iterable<String> values) {
+  for (String tokenValue in values) {
+    if (optional(tokenValue, token)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+/// Return true if the given token matches one of the given values or is EOF.
+bool isOneOfOrEof(Token token, Iterable<String> values) {
+  for (String tokenValue in values) {
+    if (optional(tokenValue, token)) {
+      return true;
+    }
+  }
+  return token.isEof;
+}
+
+/// A null-aware alternative to `token.length`.  If [token] is `null`, returns
+/// [noLength].
+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) {
+  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;
+  assert(optional('@', token));
+  Token next = token.next;
+  if (next.isIdentifier) {
+    token = next;
+    next = token.next;
+    while (optional('.', next)) {
+      token = next;
+      next = token.next;
+      if (next.isIdentifier) {
+        token = next;
+        next = token.next;
+      }
+    }
+    if (optional('(', next) && !next.endGroup.isSynthetic) {
+      token = next.endGroup;
+      next = token.next;
+    }
+  }
+  return token;
+}
+
+/// Split `>=` into two separate tokens.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtEq(Token token) {
+  assert(optional('>=', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.EQ, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
+/// Split `>>` into two separate tokens.
+/// Call [Token.setNext] to add the token to the stream.
+SimpleToken splitGtGt(Token token) {
+  assert(optional('>>', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
+/// Split `>>=` into three separate tokens.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtGtEq(Token token) {
+  assert(optional('>>=', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT, token.charOffset + 1)
+      ..setNext(new SimpleToken(TokenType.EQ, token.charOffset + 2)
+        // Set next rather than calling Token.setNext
+        // so that the previous token is not set.
+        ..next = token.next));
+}
+
+/// Split `>>=` into two separate tokens... `>` followed by `>=`.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtFromGtGtEq(Token token) {
+  assert(optional('>>=', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT_EQ, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
+/// Split `>>>` into two separate tokens... `>` followed by `>>`.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtFromGtGtGt(Token token) {
+  assert(optional('>>>', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT_GT, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
+/// Split `>>>=` into two separate tokens... `>` followed by `>>=`.
+/// Call [Token.setNext] to add the token to the stream.
+Token splitGtFromGtGtGtEq(Token token) {
+  assert(optional('>>>=', token));
+  return new SimpleToken(
+      TokenType.GT, token.charOffset, token.precedingComments)
+    ..setNext(new SimpleToken(TokenType.GT_GT_EQ, token.charOffset + 1)
+      // Set next rather than calling Token.setNext
+      // so that the previous token is not set.
+      ..next = token.next);
+}
+
+/// Return a synthetic `>` followed by [next].
+/// Call [Token.setNext] to add the token to the stream.
+Token syntheticGt(Token next) {
+  return new SyntheticToken(TokenType.GT, next.charOffset)
+    // Set next rather than calling Token.setNext
+    // so that the previous token is not set.
+    ..next = next;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
new file mode 100644
index 0000000..b56e507
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/abstract_scanner.dart
@@ -0,0 +1,1925 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library _fe_analyzer_shared.scanner.abstract_scanner;
+
+import 'dart:collection' show ListMixin;
+
+import 'dart:typed_data' show Uint16List, Uint32List;
+
+import 'token.dart'
+    show BeginToken, Keyword, KeywordToken, SyntheticToken, Token, TokenType;
+
+import 'token.dart' as analyzer show StringToken;
+
+import '../messages/codes.dart'
+    show
+        messageExpectedHexDigit,
+        messageMissingExponent,
+        messageUnexpectedDollarInString,
+        messageUnterminatedComment;
+
+import '../util/link.dart' show Link;
+
+import 'characters.dart';
+
+import 'error_token.dart'
+    show
+        NonAsciiIdentifierToken,
+        UnmatchedToken,
+        UnsupportedOperator,
+        UnterminatedString,
+        UnterminatedToken;
+
+import 'keyword_state.dart' show KeywordState;
+
+import 'token_impl.dart'
+    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
+
+import 'token_constants.dart';
+
+import 'scanner.dart'
+    show ErrorToken, Keyword, Scanner, buildUnexpectedCharacterToken;
+
+typedef void LanguageVersionChanged(
+    Scanner scanner, LanguageVersionToken languageVersion);
+
+abstract class AbstractScanner implements Scanner {
+  /**
+   * A flag indicating whether character sequences `&&=` and `||=`
+   * should be tokenized as the assignment operators
+   * [AMPERSAND_AMPERSAND_EQ_TOKEN] and [BAR_BAR_EQ_TOKEN] respectively.
+   * See issue https://github.com/dart-lang/sdk/issues/30340
+   */
+  static const bool LAZY_ASSIGNMENT_ENABLED = false;
+
+  final bool includeComments;
+
+  /// 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;
+
+  /// Experimental flag for enabling scanning of the `extension` token.
+  bool _enableExtensionMethods = false;
+
+  /// Experimental flag for enabling scanning of NNBD tokens
+  /// such as 'required' and 'late'.
+  bool _enableNonNullable = false;
+
+  /// Experimental flag for enabling scanning of `>>>`.
+  /// See https://github.com/dart-lang/language/issues/61
+  /// and https://github.com/dart-lang/language/issues/60
+  bool _enableTripleShift = false;
+
+  /**
+   * The string offset for the next token that will be created.
+   *
+   * Note that in the [Utf8BytesScanner], [stringOffset] and [scanOffset] values
+   * are different. One string character can be encoded using multiple UTF-8
+   * bytes.
+   */
+  int tokenStart = -1;
+
+  /**
+   * A pointer to the token stream created by this scanner. The first token
+   * is a special token and not part of the source file. This is an
+   * implementation detail to avoids special cases in the scanner. This token
+   * is not exposed to clients of the scanner, which are expected to invoke
+   * [firstToken] to access the token stream.
+   */
+  final Token tokens = new Token.eof(-1);
+
+  /**
+   * A pointer to the last scanned token.
+   */
+  Token tail;
+
+  /**
+   * A pointer to the last prepended error token.
+   */
+  Token errorTail;
+
+  bool hasErrors = false;
+
+  /**
+   * A pointer to the stream of comment tokens created by this scanner
+   * before they are assigned to the [Token] precedingComments field
+   * of a non-comment token. A value of `null` indicates no comment tokens.
+   */
+  CommentToken comments;
+
+  /**
+   * A pointer to the last scanned comment token or `null` if none.
+   */
+  Token commentsTail;
+
+  final List<int> lineStarts;
+
+  /**
+   * The stack of open groups, e.g [: { ... ( .. :]
+   * Each BeginToken has a pointer to the token where the group
+   * ends. This field is set when scanning the end group token.
+   */
+  Link<BeginToken> groupingStack = const Link<BeginToken>();
+
+  AbstractScanner(ScannerConfiguration config, this.includeComments,
+      this.languageVersionChanged,
+      {int numberOfBytesHint})
+      : lineStarts = new LineStarts(numberOfBytesHint) {
+    this.tail = this.tokens;
+    this.errorTail = this.tokens;
+    this.configuration = config;
+  }
+
+  @override
+  set configuration(ScannerConfiguration config) {
+    if (config != null) {
+      _enableExtensionMethods = config.enableExtensionMethods;
+      _enableNonNullable = config.enableNonNullable;
+      _enableTripleShift = config.enableTripleShift;
+    }
+  }
+
+  /**
+   * Advances and returns the next character.
+   *
+   * If the next character is non-ASCII, then the returned value depends on the
+   * scanner implementation. The [Utf8BytesScanner] returns a UTF-8 byte, while
+   * the [StringScanner] returns a UTF-16 code unit.
+   *
+   * The scanner ensures that [advance] is not invoked after it returned [$EOF].
+   * This allows implementations to omit bound checks if the data structure ends
+   * with '0'.
+   */
+  int advance();
+
+  /**
+   * Returns the current unicode character.
+   *
+   * If the current character is ASCII, then it is returned unchanged.
+   *
+   * The [Utf8BytesScanner] decodes the next unicode code point starting at the
+   * current position. Note that every unicode character is returned as a single
+   * code point, that is, for '\u{1d11e}' it returns 119070, and the following
+   * [advance] returns the next character.
+   *
+   * The [StringScanner] returns the current character unchanged, which might
+   * be a surrogate character. In the case of '\u{1d11e}', it returns the first
+   * code unit 55348, and the following [advance] returns the second code unit
+   * 56606.
+   *
+   * Invoking [currentAsUnicode] multiple times is safe, i.e.,
+   * [:currentAsUnicode(next) == currentAsUnicode(currentAsUnicode(next)):].
+   */
+  int currentAsUnicode(int next);
+
+  /**
+   * Returns the character at the next position. Like in [advance], the
+   * [Utf8BytesScanner] returns a UTF-8 byte, while the [StringScanner] returns
+   * a UTF-16 code unit.
+   */
+  int peek();
+
+  /**
+   * Notifies the scanner that unicode characters were detected in either a
+   * comment or a string literal between [startScanOffset] and the current
+   * scan offset.
+   */
+  void handleUnicode(int startScanOffset);
+
+  /**
+   * Returns the current scan offset.
+   *
+   * In the [Utf8BytesScanner] this is the offset into the byte list, in the
+   * [StringScanner] the offset in the source string.
+   */
+  int get scanOffset;
+
+  /**
+   * Returns the current string offset.
+   *
+   * In the [StringScanner] this is identical to the [scanOffset]. In the
+   * [Utf8BytesScanner] it is computed based on encountered UTF-8 characters.
+   */
+  int get stringOffset;
+
+  /**
+   * Returns the first token scanned by this [Scanner].
+   */
+  Token firstToken() => tokens.next;
+
+  /**
+   * Notifies that a new token starts at current offset.
+   */
+  void beginToken() {
+    tokenStart = stringOffset;
+  }
+
+  /**
+   * Appends a substring from the scan offset [:start:] to the current
+   * [:scanOffset:] plus the [:extraOffset:]. For example, if the current
+   * scanOffset is 10, then [:appendSubstringToken(5, -1):] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  void appendSubstringToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    appendToken(createSubstringToken(type, start, asciiOnly, extraOffset));
+  }
+
+  /**
+   * Returns a new substring from the scan offset [start] to the current
+   * [scanOffset] plus the [extraOffset]. For example, if the current
+   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  analyzer.StringToken createSubstringToken(
+      TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]);
+
+  /**
+   * Appends a substring from the scan offset [start] to the current
+   * [scanOffset] plus [syntheticChars]. The additional char(s) will be added
+   * to the unterminated string literal's lexeme but the returned
+   * token's length will *not* include those additional char(s)
+   * so as to be true to the original source.
+   */
+  void appendSyntheticSubstringToken(
+      TokenType type, int start, bool asciiOnly, String syntheticChars) {
+    appendToken(
+        createSyntheticSubstringToken(type, start, asciiOnly, syntheticChars));
+  }
+
+  /**
+   * Returns a new synthetic substring from the scan offset [start]
+   * to the current [scanOffset] plus the [syntheticChars].
+   * The [syntheticChars] are appended to the unterminated string
+   * literal's lexeme but the returned token's length will *not* include
+   * those additional characters so as to be true to the original source.
+   */
+  analyzer.StringToken createSyntheticSubstringToken(
+      TokenType type, int start, bool asciiOnly, String syntheticChars);
+  /**
+   * Appends a fixed token whose kind and content is determined by [type].
+   * Appends an *operator* token from [type].
+   *
+   * An operator token represent operators like ':', '.', ';', '&&', '==', '--',
+   * '=>', etc.
+   */
+  void appendPrecedenceToken(TokenType type) {
+    appendToken(new Token(type, tokenStart, comments));
+  }
+
+  /**
+   * Appends a fixed token based on whether the current char is [choice] or not.
+   * If the current char is [choice] a fixed token whose kind and content
+   * is determined by [yes] is appended, otherwise a fixed token whose kind
+   * and content is determined by [no] is appended.
+   */
+  int select(int choice, TokenType yes, TokenType no) {
+    int next = advance();
+    if (identical(next, choice)) {
+      appendPrecedenceToken(yes);
+      return advance();
+    } else {
+      appendPrecedenceToken(no);
+      return next;
+    }
+  }
+
+  /**
+   * Appends a keyword token whose kind is determined by [keyword].
+   */
+  void appendKeywordToken(Keyword keyword) {
+    String syntax = keyword.lexeme;
+    // Type parameters and arguments cannot contain 'this'.
+    if (identical(syntax, 'this')) {
+      discardOpenLt();
+    }
+    appendToken(new KeywordToken(keyword, tokenStart, comments));
+  }
+
+  void appendEofToken() {
+    beginToken();
+    discardOpenLt();
+    while (!groupingStack.isEmpty) {
+      unmatchedBeginGroup(groupingStack.head);
+      groupingStack = groupingStack.tail;
+    }
+    appendToken(new Token.eof(tokenStart, comments));
+  }
+
+  /**
+   * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is
+   * not always invoked for [$SPACE] characters.
+   *
+   * This method is used by the scanners to track line breaks and create the
+   * [lineStarts] map.
+   */
+  void appendWhiteSpace(int next) {
+    if (next == $LF) {
+      lineStarts.add(stringOffset + 1); // +1, the line starts after the $LF.
+    }
+  }
+
+  /**
+   * Notifies on [$LF] characters in multi-line comments or strings.
+   *
+   * This method is used by the scanners to track line breaks and create the
+   * [lineStarts] map.
+   */
+  void lineFeedInMultiline() {
+    lineStarts.add(stringOffset + 1);
+  }
+
+  /**
+   * Appends a token that begins a new group, represented by [type].
+   * Group begin tokens are '{', '(', '[', '<' and '${'.
+   */
+  void appendBeginGroup(TokenType type) {
+    Token token = new BeginToken(type, tokenStart, comments);
+    appendToken(token);
+
+    // { [ ${ cannot appear inside a type parameters / arguments.
+    if (!identical(type.kind, LT_TOKEN) &&
+        !identical(type.kind, OPEN_PAREN_TOKEN)) {
+      discardOpenLt();
+    }
+    groupingStack = groupingStack.prepend(token);
+  }
+
+  /**
+   * Appends a token that begins an end group, represented by [type].
+   * It handles the group end tokens '}', ')' and ']'. The tokens '>' and
+   * '>>' are handled separately by [appendGt] and [appendGtGt].
+   */
+  int appendEndGroup(TokenType type, int openKind) {
+    assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
+    if (!discardBeginGroupUntil(openKind)) {
+      // No begin group found. Just continue.
+      appendPrecedenceToken(type);
+      return advance();
+    }
+    appendPrecedenceToken(type);
+    Token close = tail;
+    BeginToken begin = groupingStack.head;
+    if (!identical(begin.kind, openKind) &&
+        !(begin.kind == QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN &&
+            openKind == OPEN_SQUARE_BRACKET_TOKEN)) {
+      assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
+          openKind == OPEN_CURLY_BRACKET_TOKEN);
+      // We're ending an interpolated expression.
+      begin.endGroup = close;
+      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;
+    return advance();
+  }
+
+  /**
+   * Appends a token for '>'.
+   * This method does not issue unmatched errors, because > is also the
+   * greater-than operator. It does not necessarily have to close a group.
+   */
+  void appendGt(TokenType type) {
+    appendPrecedenceToken(type);
+    if (groupingStack.isEmpty) return;
+    if (identical(groupingStack.head.kind, LT_TOKEN)) {
+      groupingStack.head.endGroup = tail;
+      groupingStack = groupingStack.tail;
+    }
+  }
+
+  /**
+   * Appends a token for '>>'.
+   * This method does not issue unmatched errors, because >> is also the
+   * shift operator. It does not necessarily have to close a group.
+   */
+  void appendGtGt(TokenType type) {
+    appendPrecedenceToken(type);
+    if (groupingStack.isEmpty) return;
+    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;
+    }
+    if (groupingStack.isEmpty) return;
+    if (identical(groupingStack.head.kind, LT_TOKEN)) {
+      groupingStack.head.endGroup = tail;
+      groupingStack = groupingStack.tail;
+    }
+  }
+
+  /// Prepend [token] to the token stream.
+  void prependErrorToken(ErrorToken token) {
+    hasErrors = true;
+    if (errorTail == tail) {
+      appendToken(token);
+      errorTail = tail;
+    } else {
+      token.next = errorTail.next;
+      token.next.previous = token;
+      errorTail.next = token;
+      token.previous = errorTail;
+      errorTail = errorTail.next;
+    }
+  }
+
+  /**
+   * Returns a new comment from the scan offset [start] to the current
+   * [scanOffset] plus the [extraOffset]. For example, if the current
+   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]);
+
+  /**
+   * Returns a new dartdoc from the scan offset [start] to the current
+   * [scanOffset] plus the [extraOffset]. For example, if the current
+   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
+   * substring string [5,9).
+   *
+   * Note that [extraOffset] can only be used if the covered character(s) are
+   * known to be ASCII.
+   */
+  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]);
+
+  /**
+   * Returns a new language version token from the scan offset [start]
+   * to the current [scanOffset] similar to createCommentToken.
+   */
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor);
+
+  /**
+   * If a begin group token matches [openKind],
+   * then discard begin group tokens up to that match and return `true`,
+   * otherwise return `false`.
+   * This recovers nicely from from situations like "{[}" and "{foo());}",
+   * but not "foo(() {bar());});
+   */
+  bool discardBeginGroupUntil(int openKind) {
+    Link<BeginToken> originalStack = groupingStack;
+
+    bool first = true;
+    do {
+      // Don't report unmatched errors for <; it is also the less-than operator.
+      discardOpenLt();
+      if (groupingStack.isEmpty) break; // recover
+      BeginToken begin = groupingStack.head;
+      if (openKind == begin.kind ||
+          (openKind == OPEN_CURLY_BRACKET_TOKEN &&
+              begin.kind == STRING_INTERPOLATION_TOKEN) ||
+          (openKind == OPEN_SQUARE_BRACKET_TOKEN &&
+              begin.kind == QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN)) {
+        if (first) {
+          // If the expected opener has been found on the first pass
+          // then no recovery necessary.
+          return true;
+        }
+        break; // recover
+      }
+      first = false;
+      groupingStack = groupingStack.tail;
+    } while (!groupingStack.isEmpty);
+
+    // If the stack does not have any opener of the given type,
+    // then return without discarding anything.
+    // This recovers nicely from from situations like "{foo());}".
+    if (groupingStack.isEmpty) {
+      groupingStack = originalStack;
+      return false;
+    }
+
+    // Insert synthetic closers and report errors for any unbalanced openers.
+    // This recovers nicely from from situations like "{[}".
+    while (!identical(originalStack, groupingStack)) {
+      // Don't report unmatched errors for <; it is also the less-than operator.
+      if (!identical(groupingStack.head.kind, LT_TOKEN)) {
+        unmatchedBeginGroup(originalStack.head);
+      }
+      originalStack = originalStack.tail;
+    }
+    return true;
+  }
+
+  /**
+   * This method is called to discard '<' from the "grouping" stack.
+   *
+   * [PartialParser.skipExpression] relies on the fact that we do not
+   * create groups for stuff like:
+   * [:a = b < c, d = e > f:].
+   *
+   * In other words, this method is called when the scanner recognizes
+   * something which cannot possibly be part of a type parameter/argument
+   * list, like the '=' in the above example.
+   */
+  void discardOpenLt() {
+    while (!groupingStack.isEmpty &&
+        identical(groupingStack.head.kind, LT_TOKEN)) {
+      groupingStack = groupingStack.tail;
+    }
+  }
+
+  /**
+   * This method is called to discard '${' from the "grouping" stack.
+   *
+   * This method is called when the scanner finds an unterminated
+   * interpolation expression.
+   */
+  void discardInterpolation() {
+    while (!groupingStack.isEmpty) {
+      BeginToken beginToken = groupingStack.head;
+      unmatchedBeginGroup(beginToken);
+      groupingStack = groupingStack.tail;
+      if (identical(beginToken.kind, STRING_INTERPOLATION_TOKEN)) break;
+    }
+  }
+
+  void unmatchedBeginGroup(BeginToken begin) {
+    // We want to ensure that unmatched BeginTokens are reported as
+    // errors.  However, the diet parser assumes that groups are well-balanced
+    // and will never look at the endGroup token.  This is a nice property that
+    // allows us to skip quickly over correct code. By inserting an additional
+    // synthetic token in the stream, we can keep ignoring endGroup tokens.
+    //
+    // [begin] --next--> [tail]
+    // [begin] --endG--> [synthetic] --next--> [next] --next--> [tail]
+    //
+    // This allows the diet parser to skip from [begin] via endGroup to
+    // [synthetic] and ignore the [synthetic] token (assuming it's correct),
+    // then the error will be reported when parsing the [next] token.
+    //
+    // For example, tokenize("{[1};") produces:
+    //
+    // SymbolToken({) --endGroup------------------------+
+    //      |                                           |
+    //     next                                         |
+    //      v                                           |
+    // SymbolToken([) --endGroup--+                     |
+    //      |                     |                     |
+    //     next                   |                     |
+    //      v                     |                     |
+    // StringToken(1)             |                     |
+    //      |                     |                     |
+    //     next                   |                     |
+    //      v                     |                     |
+    // SymbolToken(])<------------+ <-- Synthetic token |
+    //      |                                           |
+    //     next                                         |
+    //      v                                           |
+    // UnmatchedToken([)                                |
+    //      |                                           |
+    //     next                                         |
+    //      v                                           |
+    // SymbolToken(})<----------------------------------+
+    //      |
+    //     next
+    //      v
+    // SymbolToken(;)
+    //      |
+    //     next
+    //      v
+    //     EOF
+    TokenType type = closeBraceInfoFor(begin);
+    appendToken(new SyntheticToken(type, tokenStart)..beforeSynthetic = tail);
+    begin.endGroup = tail;
+    prependErrorToken(new UnmatchedToken(begin));
+  }
+
+  /// Return true when at EOF.
+  bool atEndOfFile();
+
+  Token tokenize() {
+    while (!atEndOfFile()) {
+      int next = advance();
+
+      // Scan the header looking for a language version
+      if (!identical(next, $EOF)) {
+        Token oldTail = tail;
+        next = bigHeaderSwitch(next);
+        if (!identical(next, $EOF) && tail.kind == SCRIPT_TOKEN) {
+          oldTail = tail;
+          next = bigHeaderSwitch(next);
+        }
+        while (!identical(next, $EOF) && tail == oldTail) {
+          next = bigHeaderSwitch(next);
+        }
+        next = next;
+      }
+
+      while (!identical(next, $EOF)) {
+        next = bigSwitch(next);
+      }
+      if (atEndOfFile()) {
+        appendEofToken();
+      } else {
+        unexpected($EOF);
+      }
+    }
+
+    // Always pretend that there's a line at the end of the file.
+    lineStarts.add(stringOffset + 1);
+
+    return firstToken();
+  }
+
+  int bigHeaderSwitch(int next) {
+    if (!identical(next, $SLASH)) {
+      return bigSwitch(next);
+    }
+    beginToken();
+    if (!identical($SLASH, peek())) {
+      return tokenizeSlashOrComment(next);
+    }
+    return tokenizeLanguageVersionOrSingleLineComment(next);
+  }
+
+  int bigSwitch(int next) {
+    beginToken();
+    if (identical(next, $SPACE) ||
+        identical(next, $TAB) ||
+        identical(next, $LF) ||
+        identical(next, $CR)) {
+      appendWhiteSpace(next);
+      next = advance();
+      // Sequences of spaces are common, so advance through them fast.
+      while (identical(next, $SPACE)) {
+        // We don't invoke [:appendWhiteSpace(next):] here for efficiency,
+        // assuming that it does not do anything for space characters.
+        next = advance();
+      }
+      return next;
+    }
+
+    int nextLower = next | 0x20;
+
+    if ($a <= nextLower && nextLower <= $z) {
+      if (identical($r, next)) {
+        return tokenizeRawStringKeywordOrIdentifier(next);
+      }
+      return tokenizeKeywordOrIdentifier(next, true);
+    }
+
+    if (identical(next, $CLOSE_PAREN)) {
+      return appendEndGroup(TokenType.CLOSE_PAREN, OPEN_PAREN_TOKEN);
+    }
+
+    if (identical(next, $OPEN_PAREN)) {
+      appendBeginGroup(TokenType.OPEN_PAREN);
+      return advance();
+    }
+
+    if (identical(next, $SEMICOLON)) {
+      appendPrecedenceToken(TokenType.SEMICOLON);
+      // Type parameters and arguments cannot contain semicolon.
+      discardOpenLt();
+      return advance();
+    }
+
+    if (identical(next, $PERIOD)) {
+      return tokenizeDotsOrNumber(next);
+    }
+
+    if (identical(next, $COMMA)) {
+      appendPrecedenceToken(TokenType.COMMA);
+      return advance();
+    }
+
+    if (identical(next, $EQ)) {
+      return tokenizeEquals(next);
+    }
+
+    if (identical(next, $CLOSE_CURLY_BRACKET)) {
+      return appendEndGroup(
+          TokenType.CLOSE_CURLY_BRACKET, OPEN_CURLY_BRACKET_TOKEN);
+    }
+
+    if (identical(next, $SLASH)) {
+      return tokenizeSlashOrComment(next);
+    }
+
+    if (identical(next, $OPEN_CURLY_BRACKET)) {
+      appendBeginGroup(TokenType.OPEN_CURLY_BRACKET);
+      return advance();
+    }
+
+    if (identical(next, $DQ) || identical(next, $SQ)) {
+      return tokenizeString(next, scanOffset, false);
+    }
+
+    if (identical(next, $_)) {
+      return tokenizeKeywordOrIdentifier(next, true);
+    }
+
+    if (identical(next, $COLON)) {
+      appendPrecedenceToken(TokenType.COLON);
+      return advance();
+    }
+
+    if (identical(next, $LT)) {
+      return tokenizeLessThan(next);
+    }
+
+    if (identical(next, $GT)) {
+      return tokenizeGreaterThan(next);
+    }
+
+    if (identical(next, $BANG)) {
+      return tokenizeExclamation(next);
+    }
+
+    if (identical(next, $OPEN_SQUARE_BRACKET)) {
+      return tokenizeOpenSquareBracket(next);
+    }
+
+    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
+      return appendEndGroup(
+          TokenType.CLOSE_SQUARE_BRACKET, OPEN_SQUARE_BRACKET_TOKEN);
+    }
+
+    if (identical(next, $AT)) {
+      return tokenizeAt(next);
+    }
+
+    if (next >= $1 && next <= $9) {
+      return tokenizeNumber(next);
+    }
+
+    if (identical(next, $AMPERSAND)) {
+      return tokenizeAmpersand(next);
+    }
+
+    if (identical(next, $0)) {
+      return tokenizeHexOrNumber(next);
+    }
+
+    if (identical(next, $QUESTION)) {
+      return tokenizeQuestion(next);
+    }
+
+    if (identical(next, $BAR)) {
+      return tokenizeBar(next);
+    }
+
+    if (identical(next, $PLUS)) {
+      return tokenizePlus(next);
+    }
+
+    if (identical(next, $$)) {
+      return tokenizeKeywordOrIdentifier(next, true);
+    }
+
+    if (identical(next, $MINUS)) {
+      return tokenizeMinus(next);
+    }
+
+    if (identical(next, $STAR)) {
+      return tokenizeMultiply(next);
+    }
+
+    if (identical(next, $CARET)) {
+      return tokenizeCaret(next);
+    }
+
+    if (identical(next, $TILDE)) {
+      return tokenizeTilde(next);
+    }
+
+    if (identical(next, $PERCENT)) {
+      return tokenizePercent(next);
+    }
+
+    if (identical(next, $BACKPING)) {
+      appendPrecedenceToken(TokenType.BACKPING);
+      return advance();
+    }
+
+    if (identical(next, $BACKSLASH)) {
+      appendPrecedenceToken(TokenType.BACKSLASH);
+      return advance();
+    }
+
+    if (identical(next, $HASH)) {
+      return tokenizeTag(next);
+    }
+
+    if (next < 0x1f) {
+      return unexpected(next);
+    }
+
+    next = currentAsUnicode(next);
+
+    return unexpected(next);
+  }
+
+  int tokenizeTag(int next) {
+    // # or #!.*[\n\r]
+    if (scanOffset == 0) {
+      if (identical(peek(), $BANG)) {
+        int start = scanOffset;
+        bool asciiOnly = true;
+        do {
+          next = advance();
+          if (next > 127) asciiOnly = false;
+        } while (!identical(next, $LF) &&
+            !identical(next, $CR) &&
+            !identical(next, $EOF));
+        if (!asciiOnly) handleUnicode(start);
+        appendSubstringToken(TokenType.SCRIPT_TAG, start, asciiOnly);
+        return next;
+      }
+    }
+    appendPrecedenceToken(TokenType.HASH);
+    return advance();
+  }
+
+  int tokenizeTilde(int next) {
+    // ~ ~/ ~/=
+    next = advance();
+    if (identical(next, $SLASH)) {
+      return select($EQ, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
+    } else {
+      appendPrecedenceToken(TokenType.TILDE);
+      return next;
+    }
+  }
+
+  int tokenizeOpenSquareBracket(int next) {
+    // [ [] []=
+    next = advance();
+    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
+      return select($EQ, TokenType.INDEX_EQ, TokenType.INDEX);
+    }
+    appendBeginGroup(TokenType.OPEN_SQUARE_BRACKET);
+    return next;
+  }
+
+  int tokenizeCaret(int next) {
+    // ^ ^=
+    return select($EQ, TokenType.CARET_EQ, TokenType.CARET);
+  }
+
+  int tokenizeQuestion(int next) {
+    // ? ?. ?.. ?? ??=
+    next = advance();
+    if (identical(next, $QUESTION)) {
+      return select(
+          $EQ, TokenType.QUESTION_QUESTION_EQ, TokenType.QUESTION_QUESTION);
+    } else if (identical(next, $PERIOD)) {
+      next = advance();
+      if (_enableNonNullable) {
+        if (identical($PERIOD, next)) {
+          appendPrecedenceToken(TokenType.QUESTION_PERIOD_PERIOD);
+          return advance();
+        }
+        if (identical($OPEN_SQUARE_BRACKET, next)) {
+          appendBeginGroup(TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET);
+          return advance();
+        }
+      }
+      appendPrecedenceToken(TokenType.QUESTION_PERIOD);
+      return next;
+    } else {
+      appendPrecedenceToken(TokenType.QUESTION);
+      return next;
+    }
+  }
+
+  int tokenizeBar(int next) {
+    // | || |= ||=
+    next = advance();
+    if (identical(next, $BAR)) {
+      next = advance();
+      if (LAZY_ASSIGNMENT_ENABLED && identical(next, $EQ)) {
+        appendPrecedenceToken(TokenType.BAR_BAR_EQ);
+        return advance();
+      }
+      appendPrecedenceToken(TokenType.BAR_BAR);
+      return next;
+    } else if (identical(next, $EQ)) {
+      appendPrecedenceToken(TokenType.BAR_EQ);
+      return advance();
+    } else {
+      appendPrecedenceToken(TokenType.BAR);
+      return next;
+    }
+  }
+
+  int tokenizeAmpersand(int next) {
+    // && &= & &&=
+    next = advance();
+    if (identical(next, $AMPERSAND)) {
+      next = advance();
+      if (LAZY_ASSIGNMENT_ENABLED && identical(next, $EQ)) {
+        appendPrecedenceToken(TokenType.AMPERSAND_AMPERSAND_EQ);
+        return advance();
+      }
+      appendPrecedenceToken(TokenType.AMPERSAND_AMPERSAND);
+      return next;
+    } else if (identical(next, $EQ)) {
+      appendPrecedenceToken(TokenType.AMPERSAND_EQ);
+      return advance();
+    } else {
+      appendPrecedenceToken(TokenType.AMPERSAND);
+      return next;
+    }
+  }
+
+  int tokenizePercent(int next) {
+    // % %=
+    return select($EQ, TokenType.PERCENT_EQ, TokenType.PERCENT);
+  }
+
+  int tokenizeMultiply(int next) {
+    // * *=
+    return select($EQ, TokenType.STAR_EQ, TokenType.STAR);
+  }
+
+  int tokenizeMinus(int next) {
+    // - -- -=
+    next = advance();
+    if (identical(next, $MINUS)) {
+      appendPrecedenceToken(TokenType.MINUS_MINUS);
+      return advance();
+    } else if (identical(next, $EQ)) {
+      appendPrecedenceToken(TokenType.MINUS_EQ);
+      return advance();
+    } else {
+      appendPrecedenceToken(TokenType.MINUS);
+      return next;
+    }
+  }
+
+  int tokenizePlus(int next) {
+    // + ++ +=
+    next = advance();
+    if (identical($PLUS, next)) {
+      appendPrecedenceToken(TokenType.PLUS_PLUS);
+      return advance();
+    } else if (identical($EQ, next)) {
+      appendPrecedenceToken(TokenType.PLUS_EQ);
+      return advance();
+    } else {
+      appendPrecedenceToken(TokenType.PLUS);
+      return next;
+    }
+  }
+
+  int tokenizeExclamation(int next) {
+    // ! !=
+    // !== is kept for user-friendly error reporting.
+
+    next = advance();
+    if (identical(next, $EQ)) {
+      //was `return select($EQ, TokenType.BANG_EQ_EQ, TokenType.BANG_EQ);`
+      int next = advance();
+      if (identical(next, $EQ)) {
+        appendPrecedenceToken(TokenType.BANG_EQ_EQ);
+        prependErrorToken(new UnsupportedOperator(tail, tokenStart));
+        return advance();
+      } else {
+        appendPrecedenceToken(TokenType.BANG_EQ);
+        return next;
+      }
+    }
+    appendPrecedenceToken(TokenType.BANG);
+    return next;
+  }
+
+  int tokenizeEquals(int next) {
+    // = == =>
+    // === is kept for user-friendly error reporting.
+
+    // Type parameters and arguments cannot contain any token that
+    // starts with '='.
+    discardOpenLt();
+
+    next = advance();
+    if (identical(next, $EQ)) {
+      // was `return select($EQ, TokenType.EQ_EQ_EQ, TokenType.EQ_EQ);`
+      int next = advance();
+      if (identical(next, $EQ)) {
+        appendPrecedenceToken(TokenType.EQ_EQ_EQ);
+        prependErrorToken(new UnsupportedOperator(tail, tokenStart));
+        return advance();
+      } else {
+        appendPrecedenceToken(TokenType.EQ_EQ);
+        return next;
+      }
+    } else if (identical(next, $GT)) {
+      appendPrecedenceToken(TokenType.FUNCTION);
+      return advance();
+    }
+    appendPrecedenceToken(TokenType.EQ);
+    return next;
+  }
+
+  int tokenizeGreaterThan(int next) {
+    // > >= >> >>= >>> >>>=
+    next = advance();
+    if (identical($EQ, next)) {
+      appendPrecedenceToken(TokenType.GT_EQ);
+      return advance();
+    } else if (identical($GT, next)) {
+      next = advance();
+      if (identical($EQ, next)) {
+        appendPrecedenceToken(TokenType.GT_GT_EQ);
+        return advance();
+      } else if (_enableTripleShift && identical($GT, next)) {
+        next = advance();
+        if (_enableTripleShift && identical($EQ, next)) {
+          appendPrecedenceToken(TokenType.GT_GT_GT_EQ);
+          return advance();
+        }
+        appendPrecedenceToken(TokenType.GT_GT_GT);
+        return next;
+      } else {
+        appendGtGt(TokenType.GT_GT);
+        return next;
+      }
+    } else {
+      appendGt(TokenType.GT);
+      return next;
+    }
+  }
+
+  int tokenizeLessThan(int next) {
+    // < <= << <<=
+    next = advance();
+    if (identical($EQ, next)) {
+      appendPrecedenceToken(TokenType.LT_EQ);
+      return advance();
+    } else if (identical($LT, next)) {
+      return select($EQ, TokenType.LT_LT_EQ, TokenType.LT_LT);
+    } else {
+      appendBeginGroup(TokenType.LT);
+      return next;
+    }
+  }
+
+  int tokenizeNumber(int next) {
+    int start = scanOffset;
+    while (true) {
+      next = advance();
+      if ($0 <= next && next <= $9) {
+        continue;
+      } else if (identical(next, $e) || identical(next, $E)) {
+        return tokenizeFractionPart(next, start);
+      } else {
+        if (identical(next, $PERIOD)) {
+          int nextnext = peek();
+          if ($0 <= nextnext && nextnext <= $9) {
+            return tokenizeFractionPart(advance(), start);
+          }
+        }
+        appendSubstringToken(TokenType.INT, start, true);
+        return next;
+      }
+    }
+  }
+
+  int tokenizeHexOrNumber(int next) {
+    int x = peek();
+    if (identical(x, $x) || identical(x, $X)) {
+      return tokenizeHex(next);
+    }
+    return tokenizeNumber(next);
+  }
+
+  int tokenizeHex(int next) {
+    int start = scanOffset;
+    next = advance(); // Advance past the $x or $X.
+    bool hasDigits = false;
+    while (true) {
+      next = advance();
+      if (($0 <= next && next <= $9) ||
+          ($A <= next && next <= $F) ||
+          ($a <= next && next <= $f)) {
+        hasDigits = true;
+      } else {
+        if (!hasDigits) {
+          prependErrorToken(new UnterminatedToken(
+              messageExpectedHexDigit, start, stringOffset));
+          // Recovery
+          appendSyntheticSubstringToken(
+              TokenType.HEXADECIMAL, start, true, "0");
+          return next;
+        }
+        appendSubstringToken(TokenType.HEXADECIMAL, start, true);
+        return next;
+      }
+    }
+  }
+
+  int tokenizeDotsOrNumber(int next) {
+    int start = scanOffset;
+    next = advance();
+    if (($0 <= next && next <= $9)) {
+      return tokenizeFractionPart(next, start);
+    } else if (identical($PERIOD, next)) {
+      next = advance();
+      if (identical(next, $PERIOD)) {
+        next = advance();
+        if (identical(next, $QUESTION)) {
+          appendPrecedenceToken(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
+          return advance();
+        } else {
+          appendPrecedenceToken(TokenType.PERIOD_PERIOD_PERIOD);
+          return next;
+        }
+      } else {
+        appendPrecedenceToken(TokenType.PERIOD_PERIOD);
+        return next;
+      }
+    } else {
+      appendPrecedenceToken(TokenType.PERIOD);
+      return next;
+    }
+  }
+
+  int tokenizeFractionPart(int next, int start) {
+    bool done = false;
+    bool hasDigit = false;
+    LOOP:
+    while (!done) {
+      if ($0 <= next && next <= $9) {
+        hasDigit = true;
+      } else if (identical($e, next) || identical($E, next)) {
+        hasDigit = true;
+        next = advance();
+        if (identical(next, $PLUS) || identical(next, $MINUS)) {
+          next = advance();
+        }
+        bool hasExponentDigits = false;
+        while (true) {
+          if ($0 <= next && next <= $9) {
+            hasExponentDigits = true;
+          } else {
+            if (!hasExponentDigits) {
+              appendSyntheticSubstringToken(TokenType.DOUBLE, start, true, '0');
+              prependErrorToken(new UnterminatedToken(
+                  messageMissingExponent, tokenStart, stringOffset));
+              return next;
+            }
+            break;
+          }
+          next = advance();
+        }
+
+        done = true;
+        continue LOOP;
+      } else {
+        done = true;
+        continue LOOP;
+      }
+      next = advance();
+    }
+    if (!hasDigit) {
+      // Reduce offset, we already advanced to the token past the period.
+      appendSubstringToken(TokenType.INT, start, true, -1);
+
+      // TODO(ahe): Wrong offset for the period. Cannot call beginToken because
+      // the scanner already advanced past the period.
+      if (identical($PERIOD, next)) {
+        return select(
+            $PERIOD, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
+      }
+      appendPrecedenceToken(TokenType.PERIOD);
+      return next;
+    }
+    appendSubstringToken(TokenType.DOUBLE, start, true);
+    return next;
+  }
+
+  int tokenizeSlashOrComment(int next) {
+    int start = scanOffset;
+    next = advance();
+    if (identical($STAR, next)) {
+      return tokenizeMultiLineComment(next, start);
+    } else if (identical($SLASH, next)) {
+      return tokenizeSingleLineComment(next, start);
+    } else if (identical($EQ, next)) {
+      appendPrecedenceToken(TokenType.SLASH_EQ);
+      return advance();
+    } else {
+      appendPrecedenceToken(TokenType.SLASH);
+      return next;
+    }
+  }
+
+  int tokenizeLanguageVersionOrSingleLineComment(int next) {
+    int start = scanOffset;
+    next = advance();
+
+    // Dart doc
+    if (identical($SLASH, peek())) {
+      return tokenizeSingleLineComment(next, start);
+    }
+
+    // "@dart"
+    next = advance();
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    if (!identical($AT, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($d, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($a, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($r, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    if (!identical($t, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+
+    // "="
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    if (!identical($EQ, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+
+    // major
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    int major = 0;
+    int majorStart = scanOffset;
+    while (isDigit(next)) {
+      major = major * 10 + next - $0;
+      next = advance();
+    }
+    if (scanOffset == majorStart) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    // minor
+    if (!identical($PERIOD, next)) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+    next = advance();
+    int minor = 0;
+    int minorStart = scanOffset;
+    while (isDigit(next)) {
+      minor = minor * 10 + next - $0;
+      next = advance();
+    }
+    if (scanOffset == minorStart) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    // trailing spaces
+    while (identical($SPACE, next)) {
+      next = advance();
+    }
+    if (next != $LF && next != $CR && next != $EOF) {
+      return tokenizeSingleLineCommentRest(next, start, false);
+    }
+
+    LanguageVersionToken languageVersion =
+        createLanguageVersionToken(start, major, minor);
+    if (languageVersionChanged != null) {
+      // TODO(danrubel): make this required and remove the languageVersion field
+      languageVersionChanged(this, languageVersion);
+    } else {
+      // TODO(danrubel): remove this hack and require listener to update
+      // the scanner's configuration.
+      configuration = ScannerConfiguration.classic;
+    }
+    if (includeComments) {
+      _appendToCommentStream(languageVersion);
+    }
+    return next;
+  }
+
+  int tokenizeSingleLineComment(int next, int start) {
+    bool dartdoc = identical($SLASH, peek());
+    next = advance();
+    return tokenizeSingleLineCommentRest(next, start, dartdoc);
+  }
+
+  int tokenizeSingleLineCommentRest(int next, int start, bool dartdoc) {
+    bool asciiOnly = true;
+    while (true) {
+      if (next > 127) asciiOnly = false;
+      if (identical($LF, next) ||
+          identical($CR, next) ||
+          identical($EOF, next)) {
+        if (!asciiOnly) handleUnicode(start);
+        if (dartdoc) {
+          appendDartDoc(start, TokenType.SINGLE_LINE_COMMENT, asciiOnly);
+        } else {
+          appendComment(start, TokenType.SINGLE_LINE_COMMENT, asciiOnly);
+        }
+        return next;
+      }
+      next = advance();
+    }
+  }
+
+  int tokenizeMultiLineComment(int next, int start) {
+    bool asciiOnlyComment = true; // Track if the entire comment is ASCII.
+    bool asciiOnlyLines = true; // Track ASCII since the last handleUnicode.
+    int unicodeStart = start;
+    int nesting = 1;
+    next = advance();
+    bool dartdoc = identical($STAR, next);
+    while (true) {
+      if (identical($EOF, next)) {
+        if (!asciiOnlyLines) handleUnicode(unicodeStart);
+        prependErrorToken(new UnterminatedToken(
+            messageUnterminatedComment, tokenStart, stringOffset));
+        advanceAfterError(true);
+        break;
+      } else if (identical($STAR, next)) {
+        next = advance();
+        if (identical($SLASH, next)) {
+          --nesting;
+          if (0 == nesting) {
+            if (!asciiOnlyLines) handleUnicode(unicodeStart);
+            next = advance();
+            if (dartdoc) {
+              appendDartDoc(
+                  start, TokenType.MULTI_LINE_COMMENT, asciiOnlyComment);
+            } else {
+              appendComment(
+                  start, TokenType.MULTI_LINE_COMMENT, asciiOnlyComment);
+            }
+            break;
+          } else {
+            next = advance();
+          }
+        }
+      } else if (identical($SLASH, next)) {
+        next = advance();
+        if (identical($STAR, next)) {
+          next = advance();
+          ++nesting;
+        }
+      } else if (identical(next, $LF)) {
+        if (!asciiOnlyLines) {
+          // Synchronize the string offset in the utf8 scanner.
+          handleUnicode(unicodeStart);
+          asciiOnlyLines = true;
+          unicodeStart = scanOffset;
+        }
+        lineFeedInMultiline();
+        next = advance();
+      } else {
+        if (next > 127) {
+          asciiOnlyLines = false;
+          asciiOnlyComment = false;
+        }
+        next = advance();
+      }
+    }
+    return next;
+  }
+
+  void appendComment(int start, TokenType type, bool asciiOnly) {
+    if (!includeComments) return;
+    CommentToken newComment = createCommentToken(type, start, asciiOnly);
+    _appendToCommentStream(newComment);
+  }
+
+  void appendDartDoc(int start, TokenType type, bool asciiOnly) {
+    if (!includeComments) return;
+    Token newComment = createDartDocToken(type, start, asciiOnly);
+    _appendToCommentStream(newComment);
+  }
+
+  /**
+   * Append the given token to the [tail] of the current stream of tokens.
+   */
+  void appendToken(Token token) {
+    tail.next = token;
+    token.previous = tail;
+    tail = token;
+    if (comments != null && comments == token.precedingComments) {
+      comments = null;
+      commentsTail = null;
+    } else {
+      // It is the responsibility of the caller to construct the token
+      // being appended with preceding comments if any
+      assert(comments == null || token.isSynthetic || token is ErrorToken);
+    }
+  }
+
+  void _appendToCommentStream(Token newComment) {
+    if (comments == null) {
+      comments = newComment;
+      commentsTail = comments;
+    } else {
+      commentsTail.next = newComment;
+      commentsTail.next.previous = commentsTail;
+      commentsTail = commentsTail.next;
+    }
+  }
+
+  int tokenizeRawStringKeywordOrIdentifier(int next) {
+    // [next] is $r.
+    int nextnext = peek();
+    if (identical(nextnext, $DQ) || identical(nextnext, $SQ)) {
+      int start = scanOffset;
+      next = advance();
+      return tokenizeString(next, start, true);
+    }
+    return tokenizeKeywordOrIdentifier(next, true);
+  }
+
+  int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
+    KeywordState state = KeywordState.KEYWORD_STATE;
+    int start = scanOffset;
+    // We allow a leading capital character.
+    if ($A <= next && next <= $Z) {
+      state = state.nextCapital(next);
+      next = advance();
+    } else if ($a <= next && next <= $z) {
+      // Do the first next call outside the loop to avoid an additional test
+      // and to make the loop monomorphic.
+      state = state.next(next);
+      next = advance();
+    }
+    while (state != null && $a <= next && next <= $z) {
+      state = state.next(next);
+      next = advance();
+    }
+    if (state == null || state.keyword == null) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
+    if (!_enableExtensionMethods && state.keyword == Keyword.EXTENSION) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
+    if (!_enableNonNullable &&
+        (state.keyword == Keyword.LATE || state.keyword == Keyword.REQUIRED)) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    }
+    if (($A <= next && next <= $Z) ||
+        ($0 <= next && next <= $9) ||
+        identical(next, $_) ||
+        identical(next, $$)) {
+      return tokenizeIdentifier(next, start, allowDollar);
+    } else {
+      appendKeywordToken(state.keyword);
+      return next;
+    }
+  }
+
+  /**
+   * [allowDollar] can exclude '$', which is not allowed as part of a string
+   * interpolation identifier.
+   */
+  int tokenizeIdentifier(int next, int start, bool allowDollar) {
+    while (true) {
+      if (_isIdentifierChar(next, allowDollar)) {
+        next = advance();
+      } else {
+        // Identifier ends here.
+        if (start == scanOffset) {
+          return unexpected(next);
+        } else {
+          appendSubstringToken(TokenType.IDENTIFIER, start, true);
+        }
+        break;
+      }
+    }
+    return next;
+  }
+
+  int tokenizeAt(int next) {
+    appendPrecedenceToken(TokenType.AT);
+    return advance();
+  }
+
+  int tokenizeString(int next, int start, bool raw) {
+    int quoteChar = next;
+    next = advance();
+    if (identical(quoteChar, next)) {
+      next = advance();
+      if (identical(quoteChar, next)) {
+        // Multiline string.
+        return tokenizeMultiLineString(quoteChar, start, raw);
+      } else {
+        // Empty string.
+        appendSubstringToken(TokenType.STRING, start, true);
+        return next;
+      }
+    }
+    if (raw) {
+      return tokenizeSingleLineRawString(next, quoteChar, start);
+    } else {
+      return tokenizeSingleLineString(next, quoteChar, start);
+    }
+  }
+
+  /**
+   * [next] is the first character after the quote.
+   * [quoteStart] is the scanOffset of the quote.
+   *
+   * The token contains a substring of the source file, including the
+   * string quotes, backslashes for escaping. For interpolated strings,
+   * the parts before and after are separate tokens.
+   *
+   *   "a $b c"
+   *
+   * gives StringToken("a $), StringToken(b) and StringToken( c").
+   */
+  int tokenizeSingleLineString(int next, int quoteChar, int quoteStart) {
+    int start = quoteStart;
+    bool asciiOnly = true;
+    while (!identical(next, quoteChar)) {
+      if (identical(next, $BACKSLASH)) {
+        next = advance();
+      } else if (identical(next, $$)) {
+        if (!asciiOnly) handleUnicode(start);
+        next = tokenizeStringInterpolation(start, asciiOnly);
+        start = scanOffset;
+        asciiOnly = true;
+        continue;
+      }
+      if (next <= $CR &&
+          (identical(next, $LF) ||
+              identical(next, $CR) ||
+              identical(next, $EOF))) {
+        if (!asciiOnly) handleUnicode(start);
+        unterminatedString(quoteChar, quoteStart, start,
+            asciiOnly: asciiOnly, isMultiLine: false, isRaw: false);
+        return next;
+      }
+      if (next > 127) asciiOnly = false;
+      next = advance();
+    }
+    if (!asciiOnly) handleUnicode(start);
+    // Advance past the quote character.
+    next = advance();
+    appendSubstringToken(TokenType.STRING, start, asciiOnly);
+    return next;
+  }
+
+  int tokenizeStringInterpolation(int start, bool asciiOnly) {
+    appendSubstringToken(TokenType.STRING, start, asciiOnly);
+    beginToken(); // $ starts here.
+    int next = advance();
+    if (identical(next, $OPEN_CURLY_BRACKET)) {
+      return tokenizeInterpolatedExpression(next);
+    } else {
+      return tokenizeInterpolatedIdentifier(next);
+    }
+  }
+
+  int tokenizeInterpolatedExpression(int next) {
+    appendBeginGroup(TokenType.STRING_INTERPOLATION_EXPRESSION);
+    beginToken(); // The expression starts here.
+    next = advance(); // Move past the curly bracket.
+    while (!identical(next, $EOF) && !identical(next, $STX)) {
+      next = bigSwitch(next);
+    }
+    if (identical(next, $EOF)) {
+      beginToken();
+      discardInterpolation();
+      return next;
+    }
+    next = advance(); // Move past the $STX.
+    beginToken(); // The string interpolation suffix starts here.
+    return next;
+  }
+
+  int tokenizeInterpolatedIdentifier(int next) {
+    appendPrecedenceToken(TokenType.STRING_INTERPOLATION_IDENTIFIER);
+
+    if ($a <= next && next <= $z ||
+        $A <= next && next <= $Z ||
+        identical(next, $_)) {
+      beginToken(); // The identifier starts here.
+      next = tokenizeKeywordOrIdentifier(next, false);
+    } else {
+      beginToken(); // The synthetic identifier starts here.
+      appendSyntheticSubstringToken(TokenType.IDENTIFIER, scanOffset, true, '');
+      prependErrorToken(new UnterminatedToken(
+          messageUnexpectedDollarInString, tokenStart, stringOffset));
+    }
+    beginToken(); // The string interpolation suffix starts here.
+    return next;
+  }
+
+  int tokenizeSingleLineRawString(int next, int quoteChar, int quoteStart) {
+    bool asciiOnly = true;
+    while (next != $EOF) {
+      if (identical(next, quoteChar)) {
+        if (!asciiOnly) handleUnicode(quoteStart);
+        next = advance();
+        appendSubstringToken(TokenType.STRING, quoteStart, asciiOnly);
+        return next;
+      } else if (identical(next, $LF) || identical(next, $CR)) {
+        if (!asciiOnly) handleUnicode(quoteStart);
+        unterminatedString(quoteChar, quoteStart, quoteStart,
+            asciiOnly: asciiOnly, isMultiLine: false, isRaw: true);
+        return next;
+      } else if (next > 127) {
+        asciiOnly = false;
+      }
+      next = advance();
+    }
+    if (!asciiOnly) handleUnicode(quoteStart);
+    unterminatedString(quoteChar, quoteStart, quoteStart,
+        asciiOnly: asciiOnly, isMultiLine: false, isRaw: true);
+    return next;
+  }
+
+  int tokenizeMultiLineRawString(int quoteChar, int quoteStart) {
+    bool asciiOnlyString = true;
+    bool asciiOnlyLine = true;
+    int unicodeStart = quoteStart;
+    int next = advance(); // Advance past the (last) quote (of three).
+    outer:
+    while (!identical(next, $EOF)) {
+      while (!identical(next, quoteChar)) {
+        if (identical(next, $LF)) {
+          if (!asciiOnlyLine) {
+            // Synchronize the string offset in the utf8 scanner.
+            handleUnicode(unicodeStart);
+            asciiOnlyLine = true;
+            unicodeStart = scanOffset;
+          }
+          lineFeedInMultiline();
+        } else if (next > 127) {
+          asciiOnlyLine = false;
+          asciiOnlyString = false;
+        }
+        next = advance();
+        if (identical(next, $EOF)) break outer;
+      }
+      next = advance();
+      if (identical(next, quoteChar)) {
+        next = advance();
+        if (identical(next, quoteChar)) {
+          if (!asciiOnlyLine) handleUnicode(unicodeStart);
+          next = advance();
+          appendSubstringToken(TokenType.STRING, quoteStart, asciiOnlyString);
+          return next;
+        }
+      }
+    }
+    if (!asciiOnlyLine) handleUnicode(unicodeStart);
+    unterminatedString(quoteChar, quoteStart, quoteStart,
+        asciiOnly: asciiOnlyLine, isMultiLine: true, isRaw: true);
+    return next;
+  }
+
+  int tokenizeMultiLineString(int quoteChar, int quoteStart, bool raw) {
+    if (raw) return tokenizeMultiLineRawString(quoteChar, quoteStart);
+    int start = quoteStart;
+    bool asciiOnlyString = true;
+    bool asciiOnlyLine = true;
+    int unicodeStart = start;
+    int next = advance(); // Advance past the (last) quote (of three).
+    while (!identical(next, $EOF)) {
+      if (identical(next, $$)) {
+        if (!asciiOnlyLine) handleUnicode(unicodeStart);
+        next = tokenizeStringInterpolation(start, asciiOnlyString);
+        start = scanOffset;
+        unicodeStart = start;
+        asciiOnlyString = true; // A new string token is created for the rest.
+        asciiOnlyLine = true;
+        continue;
+      }
+      if (identical(next, quoteChar)) {
+        next = advance();
+        if (identical(next, quoteChar)) {
+          next = advance();
+          if (identical(next, quoteChar)) {
+            if (!asciiOnlyLine) handleUnicode(unicodeStart);
+            next = advance();
+            appendSubstringToken(TokenType.STRING, start, asciiOnlyString);
+            return next;
+          }
+        }
+        continue;
+      }
+      if (identical(next, $BACKSLASH)) {
+        next = advance();
+        if (identical(next, $EOF)) break;
+      }
+      if (identical(next, $LF)) {
+        if (!asciiOnlyLine) {
+          // Synchronize the string offset in the utf8 scanner.
+          handleUnicode(unicodeStart);
+          asciiOnlyLine = true;
+          unicodeStart = scanOffset;
+        }
+        lineFeedInMultiline();
+      } else if (next > 127) {
+        asciiOnlyString = false;
+        asciiOnlyLine = false;
+      }
+      next = advance();
+    }
+    if (!asciiOnlyLine) handleUnicode(unicodeStart);
+    unterminatedString(quoteChar, quoteStart, start,
+        asciiOnly: asciiOnlyString, isMultiLine: true, isRaw: false);
+    return next;
+  }
+
+  int unexpected(int character) {
+    ErrorToken errorToken =
+        buildUnexpectedCharacterToken(character, tokenStart);
+    if (errorToken is NonAsciiIdentifierToken) {
+      int charOffset;
+      List<int> codeUnits = <int>[];
+      if (tail.type == TokenType.IDENTIFIER && tail.charEnd == tokenStart) {
+        charOffset = tail.charOffset;
+        codeUnits.addAll(tail.lexeme.codeUnits);
+        tail = tail.previous;
+      } else {
+        charOffset = errorToken.charOffset;
+      }
+      codeUnits.add(errorToken.character);
+      prependErrorToken(errorToken);
+      int next = advanceAfterError(true);
+      while (_isIdentifierChar(next, true)) {
+        codeUnits.add(next);
+        next = advance();
+      }
+      appendToken(new StringToken.fromString(TokenType.IDENTIFIER,
+          new String.fromCharCodes(codeUnits), charOffset));
+      return next;
+    } else {
+      prependErrorToken(errorToken);
+      return advanceAfterError(true);
+    }
+  }
+
+  void unterminatedString(int quoteChar, int quoteStart, int start,
+      {bool asciiOnly, bool isMultiLine, bool isRaw}) {
+    String suffix = new String.fromCharCodes(
+        isMultiLine ? [quoteChar, quoteChar, quoteChar] : [quoteChar]);
+    String prefix = isRaw ? 'r$suffix' : suffix;
+
+    appendSyntheticSubstringToken(TokenType.STRING, start, asciiOnly, suffix);
+    // Ensure that the error is reported on a visible token
+    int errorStart = tokenStart < stringOffset ? tokenStart : quoteStart;
+    prependErrorToken(new UnterminatedString(prefix, errorStart, stringOffset));
+  }
+
+  int advanceAfterError(bool shouldAdvance) {
+    if (atEndOfFile()) return $EOF;
+    if (shouldAdvance) {
+      return advance(); // Ensure progress.
+    } else {
+      return -1;
+    }
+  }
+}
+
+TokenType closeBraceInfoFor(BeginToken begin) {
+  return const {
+    '(': TokenType.CLOSE_PAREN,
+    '[': TokenType.CLOSE_SQUARE_BRACKET,
+    '{': TokenType.CLOSE_CURLY_BRACKET,
+    '<': TokenType.GT,
+    r'${': TokenType.CLOSE_CURLY_BRACKET,
+    '?.[': TokenType.CLOSE_SQUARE_BRACKET,
+  }[begin.lexeme];
+}
+
+class LineStarts extends Object with ListMixin<int> {
+  List<int> array;
+  int arrayLength = 0;
+
+  LineStarts(int numberOfBytesHint) {
+    // Let's assume the average Dart file is 300 bytes.
+    if (numberOfBytesHint == null) numberOfBytesHint = 300;
+
+    // Let's assume we have on average 22 bytes per line.
+    final int expectedNumberOfLines = 1 + (numberOfBytesHint ~/ 22);
+
+    if (numberOfBytesHint > 65535) {
+      array = new Uint32List(expectedNumberOfLines);
+    } else {
+      array = new Uint16List(expectedNumberOfLines);
+    }
+
+    // The first line starts at character offset 0.
+    add(0);
+  }
+
+  // Implement abstract members used by [ListMixin]
+
+  int get length => arrayLength;
+
+  int operator [](int index) {
+    assert(index < arrayLength);
+    return array[index];
+  }
+
+  void set length(int newLength) {
+    if (newLength > array.length) {
+      grow(newLength);
+    }
+    arrayLength = newLength;
+  }
+
+  void operator []=(int index, int value) {
+    if (value > 65535 && array is! Uint32List) {
+      switchToUint32(array.length);
+    }
+    array[index] = value;
+  }
+
+  // Specialize methods from [ListMixin].
+  void add(int value) {
+    if (arrayLength >= array.length) {
+      grow(0);
+    }
+    if (value > 65535 && array is! Uint32List) {
+      switchToUint32(array.length);
+    }
+    array[arrayLength++] = value;
+  }
+
+  // Helper methods.
+
+  void grow(int newLengthMinimum) {
+    int newLength = array.length * 2;
+    if (newLength < newLengthMinimum) newLength = newLengthMinimum;
+
+    if (array is Uint16List) {
+      final Uint16List newArray = new Uint16List(newLength);
+      newArray.setRange(0, arrayLength, array);
+      array = newArray;
+    } else {
+      switchToUint32(newLength);
+    }
+  }
+
+  void switchToUint32(int newLength) {
+    final Uint32List newArray = new Uint32List(newLength);
+    newArray.setRange(0, arrayLength, array);
+    array = newArray;
+  }
+}
+
+/// [ScannerConfiguration] contains information for configuring which tokens
+/// the scanner produces based upon the Dart language level.
+class ScannerConfiguration {
+  static const ScannerConfiguration classic = const ScannerConfiguration();
+  static const ScannerConfiguration nonNullable =
+      const ScannerConfiguration(enableNonNullable: true);
+
+  /// Experimental flag for enabling scanning of the `extension` keyword.
+  final bool enableExtensionMethods;
+
+  /// Experimental flag for enabling scanning of NNBD tokens
+  /// such as 'required' and 'late'
+  final bool enableNonNullable;
+
+  /// Experimental flag for enabling scanning of `>>>`.
+  /// See https://github.com/dart-lang/language/issues/61
+  /// and https://github.com/dart-lang/language/issues/60
+  final bool enableTripleShift;
+
+  const ScannerConfiguration({
+    bool enableExtensionMethods,
+    bool enableNonNullable,
+    bool enableTripleShift,
+  })  : this.enableExtensionMethods = enableExtensionMethods ?? false,
+        this.enableNonNullable = enableNonNullable ?? false,
+        this.enableTripleShift = enableTripleShift ?? false;
+}
+
+bool _isIdentifierChar(int next, bool allowDollar) {
+  return ($a <= next && next <= $z) ||
+      ($A <= next && next <= $Z) ||
+      ($0 <= next && next <= $9) ||
+      identical(next, $_) ||
+      (identical(next, $$) && allowDollar);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/characters.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/characters.dart
new file mode 100644
index 0000000..6e0710a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/characters.dart
@@ -0,0 +1,147 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.scanner.characters;
+
+const int $EOF = 0;
+const int $STX = 2;
+const int $BS = 8;
+const int $TAB = 9;
+const int $LF = 10;
+const int $VTAB = 11;
+const int $FF = 12;
+const int $CR = 13;
+const int $SPACE = 32;
+const int $BANG = 33;
+const int $DQ = 34;
+const int $HASH = 35;
+const int $$ = 36;
+const int $PERCENT = 37;
+const int $AMPERSAND = 38;
+const int $SQ = 39;
+const int $OPEN_PAREN = 40;
+const int $CLOSE_PAREN = 41;
+const int $STAR = 42;
+const int $PLUS = 43;
+const int $COMMA = 44;
+const int $MINUS = 45;
+const int $PERIOD = 46;
+const int $SLASH = 47;
+const int $0 = 48;
+const int $1 = 49;
+const int $2 = 50;
+const int $3 = 51;
+const int $4 = 52;
+const int $5 = 53;
+const int $6 = 54;
+const int $7 = 55;
+const int $8 = 56;
+const int $9 = 57;
+const int $COLON = 58;
+const int $SEMICOLON = 59;
+const int $LT = 60;
+const int $EQ = 61;
+const int $GT = 62;
+const int $QUESTION = 63;
+const int $AT = 64;
+const int $A = 65;
+const int $B = 66;
+const int $C = 67;
+const int $D = 68;
+const int $E = 69;
+const int $F = 70;
+const int $G = 71;
+const int $H = 72;
+const int $I = 73;
+const int $J = 74;
+const int $K = 75;
+const int $L = 76;
+const int $M = 77;
+const int $N = 78;
+const int $O = 79;
+const int $P = 80;
+const int $Q = 81;
+const int $R = 82;
+const int $S = 83;
+const int $T = 84;
+const int $U = 85;
+const int $V = 86;
+const int $W = 87;
+const int $X = 88;
+const int $Y = 89;
+const int $Z = 90;
+const int $OPEN_SQUARE_BRACKET = 91;
+const int $BACKSLASH = 92;
+const int $CLOSE_SQUARE_BRACKET = 93;
+const int $CARET = 94;
+const int $_ = 95;
+const int $BACKPING = 96;
+const int $a = 97;
+const int $b = 98;
+const int $c = 99;
+const int $d = 100;
+const int $e = 101;
+const int $f = 102;
+const int $g = 103;
+const int $h = 104;
+const int $i = 105;
+const int $j = 106;
+const int $k = 107;
+const int $l = 108;
+const int $m = 109;
+const int $n = 110;
+const int $o = 111;
+const int $p = 112;
+const int $q = 113;
+const int $r = 114;
+const int $s = 115;
+const int $t = 116;
+const int $u = 117;
+const int $v = 118;
+const int $w = 119;
+const int $x = 120;
+const int $y = 121;
+const int $z = 122;
+const int $OPEN_CURLY_BRACKET = 123;
+const int $BAR = 124;
+const int $CLOSE_CURLY_BRACKET = 125;
+const int $TILDE = 126;
+const int $DEL = 127;
+const int $NBSP = 160;
+const int $LS = 0x2028;
+const int $PS = 0x2029;
+
+const int $FIRST_SURROGATE = 0xd800;
+const int $LAST_SURROGATE = 0xdfff;
+const int $LAST_CODE_POINT = 0x10ffff;
+
+bool isDigit(int characterCode) {
+  return $0 <= characterCode && characterCode <= $9;
+}
+
+bool isHexDigit(int characterCode) {
+  if (characterCode <= $9) return $0 <= characterCode;
+  characterCode |= $a ^ $A;
+  return ($a <= characterCode && characterCode <= $f);
+}
+
+int hexDigitValue(int hexDigit) {
+  assert(isHexDigit(hexDigit));
+  // hexDigit is one of '0'..'9', 'A'..'F' and 'a'..'f'.
+  if (hexDigit <= $9) return hexDigit - $0;
+  return (hexDigit | ($a ^ $A)) - ($a - 10);
+}
+
+bool isUnicodeScalarValue(int value) {
+  return value < $FIRST_SURROGATE ||
+      (value > $LAST_SURROGATE && value <= $LAST_CODE_POINT);
+}
+
+bool isUtf16LeadSurrogate(int value) {
+  return value >= 0xd800 && value <= 0xdbff;
+}
+
+bool isUtf16TrailSurrogate(int value) {
+  return value >= 0xdc00 && value <= 0xdfff;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart
new file mode 100644
index 0000000..f7d9d66
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/error_token.dart
@@ -0,0 +1,217 @@
+// 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.
+
+library dart_scanner.error_token;
+
+import '../messages/codes.dart'
+    show
+        Code,
+        Message,
+        messageEncoding,
+        templateAsciiControlCharacter,
+        templateNonAsciiIdentifier,
+        templateNonAsciiWhitespace,
+        templateUnmatchedToken,
+        templateUnsupportedOperator,
+        templateUnterminatedString;
+
+import 'recover.dart' show closeBraceFor, closeQuoteFor;
+
+import 'scanner.dart' show Token, unicodeReplacementCharacter;
+
+import 'token.dart' show BeginToken, SimpleToken, TokenType;
+
+ErrorToken buildUnexpectedCharacterToken(int character, int charOffset) {
+  if (character < 0x1f) {
+    return new AsciiControlCharacterToken(character, charOffset);
+  }
+  switch (character) {
+    case unicodeReplacementCharacter:
+      return new EncodingErrorToken(charOffset);
+
+    /// See [General Punctuation]
+    /// (http://www.unicode.org/charts/PDF/U2000.pdf).
+    case 0x00A0: // No-break space.
+    case 0x1680: // Ogham space mark.
+    case 0x180E: // Mongolian vowel separator.
+    case 0x2000: // En quad.
+    case 0x2001: // Em quad.
+    case 0x2002: // En space.
+    case 0x2003: // Em space.
+    case 0x2004: // Three-per-em space.
+    case 0x2005: // Four-per-em space.
+    case 0x2006: // Six-per-em space.
+    case 0x2007: // Figure space.
+    case 0x2008: // Punctuation space.
+    case 0x2009: // Thin space.
+    case 0x200A: // Hair space.
+    case 0x200B: // Zero width space.
+    case 0x2028: // Line separator.
+    case 0x2029: // Paragraph separator.
+    case 0x202F: // Narrow no-break space.
+    case 0x205F: // Medium mathematical space.
+    case 0x3000: // Ideographic space.
+    case 0xFEFF: // Zero width no-break space.
+      return new NonAsciiWhitespaceToken(character, charOffset);
+
+    default:
+      return new NonAsciiIdentifierToken(character, charOffset);
+  }
+}
+
+/// Common superclass for all error tokens.
+///
+/// It's considered an implementation error to access [lexeme] of an
+/// [ErrorToken].
+abstract class ErrorToken extends SimpleToken {
+  ErrorToken(int offset) : super(TokenType.BAD_INPUT, offset, null);
+
+  /// This is a token that wraps around an error message. Return 1
+  /// instead of the size of the length of the error message.
+  @override
+  int get length => 1;
+
+  String get lexeme {
+    String errorMsg = assertionMessage.message;
+
+    // Attempt to include the location which is calling the parser
+    // in an effort to debug https://github.com/dart-lang/sdk/issues/37528
+    RegExp pattern = new RegExp('^#[0-9]* *Parser');
+    List<String> traceLines = StackTrace.current.toString().split('\n');
+    for (int index = traceLines.length - 2; index >= 0; --index) {
+      String line = traceLines[index];
+      if (line.startsWith(pattern)) {
+        errorMsg = '$errorMsg - ${traceLines[index + 1]}';
+        break;
+      }
+    }
+
+    throw errorMsg;
+  }
+
+  Message get assertionMessage;
+
+  Code<dynamic> get errorCode => assertionMessage.code;
+
+  int get character => null;
+
+  String get start => null;
+
+  int get endOffset => null;
+
+  BeginToken get begin => null;
+
+  @override
+  Token copy() {
+    throw 'unsupported operation';
+  }
+}
+
+/// Represents an encoding error.
+class EncodingErrorToken extends ErrorToken {
+  EncodingErrorToken(int charOffset) : super(charOffset);
+
+  String toString() => "EncodingErrorToken()";
+
+  Message get assertionMessage => messageEncoding;
+}
+
+/// Represents a non-ASCII character outside a string or comment.
+class NonAsciiIdentifierToken extends ErrorToken {
+  final int character;
+
+  NonAsciiIdentifierToken(this.character, int charOffset) : super(charOffset);
+
+  String toString() => "NonAsciiIdentifierToken($character)";
+
+  Message get assertionMessage => templateNonAsciiIdentifier.withArguments(
+      new String.fromCharCodes([character]), character);
+}
+
+/// Represents a non-ASCII whitespace outside a string or comment.
+class NonAsciiWhitespaceToken extends ErrorToken {
+  final int character;
+
+  NonAsciiWhitespaceToken(this.character, int charOffset) : super(charOffset);
+
+  String toString() => "NonAsciiWhitespaceToken($character)";
+
+  Message get assertionMessage =>
+      templateNonAsciiWhitespace.withArguments(character);
+}
+
+/// Represents an ASCII control character outside a string or comment.
+class AsciiControlCharacterToken extends ErrorToken {
+  final int character;
+
+  AsciiControlCharacterToken(this.character, int charOffset)
+      : super(charOffset);
+
+  String toString() => "AsciiControlCharacterToken($character)";
+
+  Message get assertionMessage =>
+      templateAsciiControlCharacter.withArguments(character);
+}
+
+/// Denotes an operator that is not supported in the Dart language.
+class UnsupportedOperator extends ErrorToken {
+  Token token;
+
+  UnsupportedOperator(this.token, int charOffset) : super(charOffset);
+
+  @override
+  Message get assertionMessage =>
+      templateUnsupportedOperator.withArguments(token);
+
+  @override
+  String toString() => "UnsupportedOperator(${token.lexeme})";
+}
+
+/// Represents an unterminated string.
+class UnterminatedString extends ErrorToken {
+  final String start;
+  final int endOffset;
+
+  UnterminatedString(this.start, int charOffset, this.endOffset)
+      : super(charOffset);
+
+  String toString() => "UnterminatedString($start)";
+
+  int get charCount => endOffset - charOffset;
+
+  int get length => charCount;
+
+  Message get assertionMessage =>
+      templateUnterminatedString.withArguments(start, closeQuoteFor(start));
+}
+
+/// Represents an unterminated token.
+class UnterminatedToken extends ErrorToken {
+  final Message assertionMessage;
+  final int endOffset;
+
+  UnterminatedToken(this.assertionMessage, int charOffset, this.endOffset)
+      : super(charOffset);
+
+  String toString() => "UnterminatedToken(${assertionMessage.code.name})";
+
+  int get charCount => endOffset - charOffset;
+}
+
+/// Represents an open brace without a matching close brace.
+///
+/// In this case, brace means any of `(`, `{`, `[`, and `<`, parenthesis, curly
+/// brace, square brace, and angle brace, respectively.
+class UnmatchedToken extends ErrorToken {
+  final BeginToken begin;
+
+  UnmatchedToken(BeginToken begin)
+      : this.begin = begin,
+        super(begin.charOffset);
+
+  String toString() => "UnmatchedToken(${begin.lexeme})";
+
+  Message get assertionMessage =>
+      templateUnmatchedToken.withArguments(closeBraceFor(begin.lexeme), begin);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart
new file mode 100644
index 0000000..df5ab6d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/errors.dart
@@ -0,0 +1,193 @@
+// 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.
+
+import '../base/errors.dart';
+import '../messages/codes.dart';
+import 'error_token.dart';
+import 'token_constants.dart';
+import 'token.dart' show Token, TokenType;
+
+/**
+ * The error codes used for errors detected by the scanner.
+ */
+class ScannerErrorCode extends ErrorCode {
+  /**
+   * Parameters:
+   * 0: the token that was expected but not found
+   */
+  static const ScannerErrorCode EXPECTED_TOKEN =
+      const ScannerErrorCode('EXPECTED_TOKEN', "Expected to find '{0}'.");
+
+  /**
+   * Parameters:
+   * 0: the illegal character
+   */
+  static const ScannerErrorCode ILLEGAL_CHARACTER =
+      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character '{0}'.");
+
+  static const ScannerErrorCode MISSING_DIGIT =
+      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected.");
+
+  static const ScannerErrorCode MISSING_HEX_DIGIT = const ScannerErrorCode(
+      'MISSING_HEX_DIGIT', "Hexadecimal digit expected.");
+
+  static const ScannerErrorCode MISSING_IDENTIFIER =
+      const ScannerErrorCode('MISSING_IDENTIFIER', "Expected an identifier.");
+
+  static const ScannerErrorCode MISSING_QUOTE =
+      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \").");
+
+  /**
+   * Parameters:
+   * 0: the path of the file that cannot be read
+   */
+  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
+      'UNABLE_GET_CONTENT', "Unable to get content of '{0}'.");
+
+  static const ScannerErrorCode UNEXPECTED_DOLLAR_IN_STRING =
+      const ScannerErrorCode(
+          'UNEXPECTED_DOLLAR_IN_STRING',
+          "A '\$' has special meaning inside a string, and must be followed by "
+              "an identifier or an expression in curly braces ({}).",
+          correction: "Try adding a backslash (\\) to escape the '\$'.");
+
+  /**
+   * Parameters:
+   * 0: the unsupported operator
+   */
+  static const ScannerErrorCode UNSUPPORTED_OPERATOR = const ScannerErrorCode(
+      'UNSUPPORTED_OPERATOR', "The '{0}' operator is not supported.");
+
+  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
+      const ScannerErrorCode(
+          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment.",
+          correction: "Try terminating the comment with '*/', or "
+              "removing any unbalanced occurrences of '/*'"
+              " (because comments nest in Dart).");
+
+  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
+      const ScannerErrorCode(
+          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal.");
+
+  /**
+   * Initialize a newly created error code to have the given [name]. The message
+   * associated with the error will be created from the given [message]
+   * template. The correction associated with the error will be created from the
+   * given [correction] template.
+   */
+  const ScannerErrorCode(String name, String message, {String correction})
+      : super.temporary(name, message, correction: correction);
+
+  @override
+  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
+
+  @override
+  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
+}
+
+/**
+ * Used to report a scan error at the given offset.
+ * The [errorCode] is the error code indicating the nature of the error.
+ * The [arguments] are any arguments needed to complete the error message.
+ */
+typedef ReportError(
+    ScannerErrorCode errorCode, int offset, List<Object> arguments);
+
+/**
+ *  Translates the given error [token] into an analyzer error and reports it
+ *  using [reportError].
+ */
+void translateErrorToken(ErrorToken token, ReportError reportError) {
+  int charOffset = token.charOffset;
+  // TODO(paulberry,ahe): why is endOffset sometimes null?
+  int endOffset = token.endOffset ?? charOffset;
+  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.
+      // TODO(paulberry,ahe): would it make sense to replicate this behavior
+      // in fasta, or move it elsewhere in analyzer?
+      charOffset--;
+    }
+    reportError(errorCode, charOffset, arguments);
+  }
+
+  Code<dynamic> errorCode = token.errorCode;
+  switch (errorCode.analyzerCodes?.first) {
+    case "UNTERMINATED_STRING_LITERAL":
+      // TODO(paulberry,ahe): Fasta reports the error location as the entire
+      // string; analyzer expects the end of the string.
+      reportError(
+          ScannerErrorCode.UNTERMINATED_STRING_LITERAL, endOffset - 1, null);
+      return;
+
+    case "UNTERMINATED_MULTI_LINE_COMMENT":
+      // TODO(paulberry,ahe): Fasta reports the error location as the entire
+      // comment; analyzer expects the end of the comment.
+      reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT,
+          endOffset - 1, null);
+      return;
+
+    case "MISSING_DIGIT":
+      // TODO(paulberry,ahe): Fasta reports the error location as the entire
+      // number; analyzer expects the end of the number.
+      charOffset = endOffset - 1;
+      return _makeError(ScannerErrorCode.MISSING_DIGIT, null);
+
+    case "MISSING_HEX_DIGIT":
+      // TODO(paulberry,ahe): Fasta reports the error location as the entire
+      // number; analyzer expects the end of the number.
+      charOffset = endOffset - 1;
+      return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null);
+
+    case "ILLEGAL_CHARACTER":
+      return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
+
+    case "UNSUPPORTED_OPERATOR":
+      return _makeError(ScannerErrorCode.UNSUPPORTED_OPERATOR,
+          [(token as UnsupportedOperator).token.lexeme]);
+
+    default:
+      if (errorCode == codeUnmatchedToken) {
+        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, ['}']);
+        }
+        if (type == TokenType.OPEN_SQUARE_BRACKET ||
+            type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET) {
+          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, [']']);
+        }
+        if (type == TokenType.OPEN_PAREN) {
+          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, [')']);
+        }
+        if (type == TokenType.LT) {
+          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, ['>']);
+        }
+      } else if (errorCode == codeUnexpectedDollarInString) {
+        return _makeError(ScannerErrorCode.MISSING_IDENTIFIER, null);
+      }
+      throw new UnimplementedError(
+          '$errorCode "${errorCode.analyzerCodes?.first}"');
+  }
+}
+
+/**
+ * Determines whether the given [charOffset], which came from the non-EOF token
+ * [token], represents the end of the input.
+ */
+bool _isAtEnd(Token token, int charOffset) {
+  while (true) {
+    // Skip to the next token.
+    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;
+    // If we've found a non-error token, then we know there is additional input
+    // text after [charOffset].
+    if (token.type.kind != BAD_INPUT_TOKEN) return false;
+    // Otherwise keep looking.
+  }
+}
diff --git a/pkg/front_end/lib/src/scanner/interner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/interner.dart
similarity index 100%
rename from pkg/front_end/lib/src/scanner/interner.dart
rename to pkg/_fe_analyzer_shared/lib/src/scanner/interner.dart
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/io.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/io.dart
new file mode 100644
index 0000000..93b0141
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/io.dart
@@ -0,0 +1,43 @@
+// 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.md file.
+
+library _fe_analyzer_shared.scanner.io;
+
+import 'dart:async' show Future;
+
+import 'dart:io' show File, RandomAccessFile;
+
+import 'dart:typed_data' show Uint8List;
+
+List<int> readBytesFromFileSync(Uri uri) {
+  RandomAccessFile file = new File.fromUri(uri).openSync();
+  Uint8List list;
+  try {
+    int length = file.lengthSync();
+    // +1 to have a 0 terminated list, see [Scanner].
+    list = new Uint8List(length + 1);
+    file.readIntoSync(list, 0, length);
+  } finally {
+    file.closeSync();
+  }
+  return list;
+}
+
+Future<List<int>> readBytesFromFile(Uri uri,
+    {bool ensureZeroTermination: true}) async {
+  RandomAccessFile file = await new File.fromUri(uri).open();
+  Uint8List list;
+  try {
+    int length = await file.length();
+    // +1 to have a 0 terminated list, see [Scanner].
+    list = new Uint8List(ensureZeroTermination ? length + 1 : length);
+    int read = await file.readInto(list);
+    if (read != length) {
+      throw "Error reading file: ${uri}";
+    }
+  } finally {
+    await file.close();
+  }
+  return list;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart
new file mode 100644
index 0000000..0899d1f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/keyword_state.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.scanner.keywords;
+
+import 'token.dart' as analyzer;
+
+import 'characters.dart' show $a, $z, $A, $Z;
+
+/**
+ * Abstract state in a state machine for scanning keywords.
+ */
+abstract class KeywordState {
+  KeywordState next(int c);
+  KeywordState nextCapital(int c);
+
+  analyzer.Keyword get keyword;
+
+  static KeywordState _KEYWORD_STATE;
+  static KeywordState get KEYWORD_STATE {
+    if (_KEYWORD_STATE == null) {
+      List<String> strings = new List<String>(analyzer.Keyword.values.length);
+      for (int i = 0; i < analyzer.Keyword.values.length; i++) {
+        strings[i] = analyzer.Keyword.values[i].lexeme;
+      }
+      strings.sort((a, b) => a.compareTo(b));
+      _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length);
+    }
+    return _KEYWORD_STATE;
+  }
+
+  static KeywordState computeKeywordStateTable(
+      int start, List<String> strings, int offset, int length) {
+    bool isLowercase = true;
+
+    List<KeywordState> table = new List<KeywordState>($z - $A + 1);
+    assert(length != 0);
+    int chunk = 0;
+    int chunkStart = -1;
+    bool isLeaf = false;
+    for (int i = offset; i < offset + length; i++) {
+      if (strings[i].length == start) {
+        isLeaf = true;
+      }
+      if (strings[i].length > start) {
+        int c = strings[i].codeUnitAt(start);
+        if ($A <= c && c <= $Z) {
+          isLowercase = false;
+        }
+        if (chunk != c) {
+          if (chunkStart != -1) {
+            assert(table[chunk - $A] == null);
+            table[chunk - $A] = computeKeywordStateTable(
+                start + 1, strings, chunkStart, i - chunkStart);
+          }
+          chunkStart = i;
+          chunk = c;
+        }
+      }
+    }
+    if (chunkStart != -1) {
+      assert(table[chunk - $A] == null);
+      table[chunk - $A] = computeKeywordStateTable(
+          start + 1, strings, chunkStart, offset + length - chunkStart);
+    } else {
+      assert(length == 1);
+      return new LeafKeywordState(strings[offset]);
+    }
+    String syntax = isLeaf ? strings[offset] : null;
+    if (isLowercase) {
+      table = table.sublist($a - $A);
+      return new LowerCaseArrayKeywordState(table, syntax);
+    } else {
+      return new UpperCaseArrayKeywordState(table, syntax);
+    }
+  }
+}
+
+/**
+ * A state with multiple outgoing transitions.
+ */
+abstract class ArrayKeywordState implements KeywordState {
+  final List<KeywordState> table;
+  final analyzer.Keyword keyword;
+
+  ArrayKeywordState(this.table, String syntax)
+      : keyword = ((syntax == null) ? null : analyzer.Keyword.keywords[syntax]);
+
+  KeywordState next(int c);
+
+  KeywordState nextCapital(int c);
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write("[");
+    if (keyword != null) {
+      sb.write("*");
+      sb.write(keyword);
+      sb.write(" ");
+    }
+    List<KeywordState> foo = table;
+    for (int i = 0; i < foo.length; i++) {
+      if (foo[i] != null) {
+        sb.write("${new String.fromCharCodes([i + $a])}: "
+            "${foo[i]}; ");
+      }
+    }
+    sb.write("]");
+    return sb.toString();
+  }
+}
+
+class LowerCaseArrayKeywordState extends ArrayKeywordState {
+  LowerCaseArrayKeywordState(List<KeywordState> table, String syntax)
+      : super(table, syntax) {
+    assert(table.length == $z - $a + 1);
+  }
+
+  KeywordState next(int c) => table[c - $a];
+
+  KeywordState nextCapital(int c) => null;
+}
+
+class UpperCaseArrayKeywordState extends ArrayKeywordState {
+  UpperCaseArrayKeywordState(List<KeywordState> table, String syntax)
+      : super(table, syntax) {
+    assert(table.length == $z - $A + 1);
+  }
+
+  KeywordState next(int c) => table[c - $A];
+
+  KeywordState nextCapital(int c) => table[c - $A];
+}
+
+/**
+ * A state that has no outgoing transitions.
+ */
+class LeafKeywordState implements KeywordState {
+  final analyzer.Keyword keyword;
+
+  LeafKeywordState(String syntax) : keyword = analyzer.Keyword.keywords[syntax];
+
+  KeywordState next(int c) => null;
+  KeywordState nextCapital(int c) => null;
+
+  String toString() => keyword.lexeme;
+}
diff --git a/pkg/front_end/lib/src/scanner/reader.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart
similarity index 100%
rename from pkg/front_end/lib/src/scanner/reader.dart
rename to pkg/_fe_analyzer_shared/lib/src/scanner/reader.dart
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart
new file mode 100644
index 0000000..09e7cce
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/recover.dart
@@ -0,0 +1,84 @@
+// 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.
+
+library _fe_analyzer_shared.scanner.recover;
+
+import 'token.dart' show Token, TokenType;
+
+import 'token_impl.dart' show StringToken;
+
+import 'error_token.dart' show ErrorToken;
+
+/// Recover from errors in [tokens]. The original sources are provided as
+/// [bytes]. [lineStarts] are the beginning character offsets of lines, and
+/// must be updated if recovery is performed rewriting the original source
+/// code.
+Token scannerRecovery(List<int> bytes, Token tokens, List<int> lineStarts) {
+  // Sanity check that all error tokens are prepended.
+
+  // TODO(danrubel): Remove this in a while after the dust has settled.
+
+  // Skip over prepended error tokens
+  Token token = tokens;
+  while (token is ErrorToken) {
+    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;
+        if (previous.isEof) break;
+        token = previous;
+      }
+      StringBuffer msg = new StringBuffer(
+          "Internal error: All error tokens should have been prepended:");
+      for (int count = 0; count < 7; ++count) {
+        if (token.isEof) break;
+        msg.write(' ${token.runtimeType},');
+        token = token.next;
+      }
+      throw msg.toString();
+    }
+    token = token.next;
+  }
+
+  return tokens;
+}
+
+Token synthesizeToken(int charOffset, String value, TokenType type) {
+  return new StringToken.fromString(type, value, charOffset);
+}
+
+Token skipToEof(Token token) {
+  while (!token.isEof) {
+    token = token.next;
+  }
+  return token;
+}
+
+String closeBraceFor(String openBrace) {
+  return const {
+    '(': ')',
+    '[': ']',
+    '{': '}',
+    '<': '>',
+    r'${': '}',
+    '?.[': ']',
+  }[openBrace];
+}
+
+String closeQuoteFor(String openQuote) {
+  return const {
+    '"': '"',
+    "'": "'",
+    '"""': '"""',
+    "'''": "'''",
+    'r"': '"',
+    "r'": "'",
+    'r"""': '"""',
+    "r'''": "'''",
+  }[openQuote];
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
new file mode 100644
index 0000000..f8184e1
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner.dart
@@ -0,0 +1,105 @@
+// 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.md file.
+
+library _fe_analyzer_shared.scanner;
+
+import 'dart:convert' show unicodeReplacementCharacterRune, utf8;
+
+import 'token.dart' show Token;
+
+import 'abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
+
+import 'string_scanner.dart' show StringScanner;
+
+import 'utf8_bytes_scanner.dart' show Utf8BytesScanner;
+
+import 'recover.dart' show scannerRecovery;
+
+export 'abstract_scanner.dart'
+    show LanguageVersionChanged, ScannerConfiguration;
+
+export 'token_impl.dart'
+    show
+        LanguageVersionToken,
+        StringToken,
+        isBinaryOperator,
+        isMinusOperator,
+        isTernaryOperator,
+        isUnaryOperator,
+        isUserDefinableOperator;
+
+export 'error_token.dart' show ErrorToken, buildUnexpectedCharacterToken;
+
+export 'token_impl.dart' show LanguageVersionToken;
+
+export 'token_constants.dart' show EOF_TOKEN;
+
+export 'utf8_bytes_scanner.dart' show Utf8BytesScanner;
+
+export 'string_scanner.dart' show StringScanner;
+
+export 'token.dart' show Keyword, Token;
+
+const int unicodeReplacementCharacter = unicodeReplacementCharacterRune;
+
+typedef Token Recover(List<int> bytes, Token tokens, List<int> lineStarts);
+
+abstract class Scanner {
+  /// Returns true if an error occurred during [tokenize].
+  bool get hasErrors;
+
+  List<int> get lineStarts;
+
+  /// Configure which tokens are produced.
+  set configuration(ScannerConfiguration config);
+
+  Token tokenize();
+}
+
+class ScannerResult {
+  final Token tokens;
+  final List<int> lineStarts;
+  final bool hasErrors;
+
+  ScannerResult(this.tokens, this.lineStarts, this.hasErrors);
+}
+
+/// Scan/tokenize the given UTF8 [bytes].
+ScannerResult scan(List<int> bytes,
+    {ScannerConfiguration configuration,
+    bool includeComments: false,
+    LanguageVersionChanged languageVersionChanged}) {
+  if (bytes.last != 0) {
+    throw new ArgumentError("[bytes]: the last byte must be null.");
+  }
+  Scanner scanner = new Utf8BytesScanner(bytes,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
+  return _tokenizeAndRecover(scanner, bytes: bytes);
+}
+
+/// Scan/tokenize the given [source].
+ScannerResult scanString(String source,
+    {ScannerConfiguration configuration,
+    bool includeComments: false,
+    LanguageVersionChanged languageVersionChanged}) {
+  assert(source != null, 'source must not be null');
+  StringScanner scanner = new StringScanner(source,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
+  return _tokenizeAndRecover(scanner, source: source);
+}
+
+ScannerResult _tokenizeAndRecover(Scanner scanner,
+    {List<int> bytes, String source}) {
+  Token tokens = scanner.tokenize();
+  if (scanner.hasErrors) {
+    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
new file mode 100644
index 0000000..b0232dd
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/scanner_main.dart
@@ -0,0 +1,98 @@
+// 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.md file.
+
+library _fe_analyzer_shared.scanner.main;
+
+import 'io.dart' show readBytesFromFileSync;
+
+import 'scanner.dart' show ErrorToken, Token, scan;
+
+scanAll(Map<Uri, List<int>> files, {bool verbose: false, bool verify: false}) {
+  Stopwatch sw = new Stopwatch()..start();
+  int byteCount = 0;
+  files.forEach((Uri uri, List<int> bytes) {
+    Token token = scan(bytes).tokens;
+    if (verbose) printTokens(token);
+    if (verify) verifyErrorTokens(token, uri);
+    byteCount += bytes.length - 1;
+  });
+  sw.stop();
+  print("Scanning files took: ${sw.elapsed}");
+  print("Bytes/ms: ${byteCount / sw.elapsedMilliseconds}");
+}
+
+void printTokens(Token token) {
+  while (!token.isEof) {
+    print("${token.charOffset}: $token");
+    token = token.next;
+  }
+}
+
+/// Verify that the fasta scanner recovery has moved all of the ErrorTokens
+/// to the beginning of the stream. If an out-of-order ErrorToken is
+/// found, then print some diagnostic information and throw an exception.
+void verifyErrorTokens(Token firstToken, Uri uri) {
+  Token token = firstToken;
+  while (token is ErrorToken) {
+    token = token.next;
+  }
+
+  while (!token.isEof) {
+    if (token is ErrorToken) {
+      print('Found out-of-order ErrorTokens when scanning:\n  $uri');
+
+      // Rescan the token stream up to the error token to find the 10 tokens
+      // before the out of order ErrorToken.
+      Token errorToken = token;
+      Token start = firstToken;
+      int count = 0;
+      token = firstToken;
+      while (token != errorToken) {
+        token = token.next;
+        if (count < 10) {
+          ++count;
+        } else {
+          start = start.next;
+        }
+      }
+
+      // Print the out of order error token plus some tokens before and after.
+      count = 0;
+      token = start;
+      while (count < 20 && !token.isEof) {
+        print("${token.charOffset}: $token");
+        token = token.next;
+        ++count;
+      }
+      throw 'Out of order ErrorToken: $errorToken';
+    }
+    token = token.next;
+  }
+}
+
+mainEntryPoint(List<String> arguments) {
+  Map<Uri, List<int>> files = <Uri, List<int>>{};
+  Stopwatch sw = new Stopwatch()..start();
+  bool verbose = const bool.fromEnvironment("printTokens");
+  bool verify = const bool.fromEnvironment('verifyErrorTokens');
+  for (String arg in arguments) {
+    if (arg.startsWith('--')) {
+      if (arg == '--print-tokens') {
+        verbose = true;
+      } else if (arg == '--verify-error-tokens') {
+        verify = true;
+      } else {
+        print('Unrecognized option: $arg');
+      }
+      continue;
+    }
+
+    Uri uri = Uri.base.resolve(arg);
+    List<int> bytes = readBytesFromFileSync(uri);
+    files[uri] = bytes;
+  }
+  sw.stop();
+  print("Reading files took: ${sw.elapsed}");
+  scanAll(files, verbose: verbose, verify: verify);
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart
new file mode 100644
index 0000000..2b127b7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/string_canonicalizer.dart
@@ -0,0 +1,123 @@
+// 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.
+
+library _fe_analyzer_shared.scanner.string_canonicalizer;
+
+import 'dart:convert';
+
+class Node {
+  dynamic /* String | List<int> */ data;
+  int start;
+  int end;
+  String payload;
+  Node next;
+  Node(this.data, this.start, this.end, this.payload, this.next);
+}
+
+/// A hash table for triples:
+/// (list of bytes, start, end) --> canonicalized string
+/// Using triples avoids allocating string slices before checking if they
+/// are canonical.
+///
+/// Gives about 3% speedup on dart2js.
+class StringCanonicalizer {
+  /// Mask away top bits to keep hash calculation within 32-bit SMI range.
+  static const int MASK = 16 * 1024 * 1024 - 1;
+
+  static const int INITIAL_SIZE = 8 * 1024;
+
+  /// Linear size of a hash table.
+  int _size = INITIAL_SIZE;
+
+  /// Items in a hash table.
+  int _count = 0;
+
+  /// The table itself.
+  List<Node> _nodes = new List<Node>(INITIAL_SIZE);
+
+  static String decode(List<int> data, int start, int end, bool asciiOnly) {
+    String s;
+    if (asciiOnly) {
+      s = new String.fromCharCodes(data, start, end);
+    } else {
+      s = new Utf8Decoder(allowMalformed: true).convert(data, start, end);
+    }
+    return s;
+  }
+
+  static int hashBytes(List<int> data, int start, int end) {
+    int h = 5381;
+    for (int i = start; i < end; i++) {
+      h = ((h << 5) + h + data[i]) & MASK;
+    }
+    return h;
+  }
+
+  static int hashString(String data, int start, int end) {
+    int h = 5381;
+    for (int i = start; i < end; i++) {
+      h = ((h << 5) + h + data.codeUnitAt(i)) & MASK;
+    }
+    return h;
+  }
+
+  rehash() {
+    int newSize = _size * 2;
+    List<Node> newNodes = new List<Node>(newSize);
+    for (int i = 0; i < _size; i++) {
+      Node t = _nodes[i];
+      while (t != null) {
+        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];
+        t.next = s;
+        newNodes[newIndex] = t;
+        t = n;
+      }
+    }
+    _size = newSize;
+    _nodes = newNodes;
+  }
+
+  String canonicalize(data, int start, int end, bool asciiOnly) {
+    if (_count > _size) rehash();
+    int index = data is String
+        ? hashString(data, start, end)
+        : hashBytes(data, start, end);
+    index = index & (_size - 1);
+    Node s = _nodes[index];
+    Node t = s;
+    int len = end - start;
+    while (t != null) {
+      if (t.end - t.start == len) {
+        int i = start, j = t.start;
+        while (i < end && data[i] == t.data[j]) {
+          i++;
+          j++;
+        }
+        if (i == end) {
+          return t.payload;
+        }
+      }
+      t = t.next;
+    }
+    String payload;
+    if (data is String) {
+      payload = data.substring(start, end);
+    } else {
+      payload = decode(data, start, end, asciiOnly);
+    }
+    _nodes[index] = new Node(data, start, end, payload, s);
+    _count++;
+    return payload;
+  }
+
+  clear() {
+    _size = INITIAL_SIZE;
+    _nodes = new List<Node>(_size);
+    _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
new file mode 100644
index 0000000..aabe361
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.scanner.string_scanner;
+
+import 'token.dart' show Token, SyntheticStringToken, TokenType;
+
+import 'token.dart' as analyzer show StringToken;
+
+import 'abstract_scanner.dart'
+    show AbstractScanner, LanguageVersionChanged, ScannerConfiguration;
+
+import 'token_impl.dart'
+    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
+
+import 'error_token.dart' show ErrorToken;
+
+/**
+ * Scanner that reads from a String and creates tokens that points to
+ * substrings.
+ */
+class StringScanner extends AbstractScanner {
+  /** The file content. */
+  String string;
+
+  /** The current offset in [string]. */
+  int scanOffset = -1;
+
+  StringScanner(String string,
+      {ScannerConfiguration configuration,
+      bool includeComments: false,
+      LanguageVersionChanged languageVersionChanged})
+      : string = ensureZeroTermination(string),
+        super(configuration, includeComments, languageVersionChanged);
+
+  static String ensureZeroTermination(String string) {
+    return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
+        // TODO(lry): abort instead of copying the array, or warn?
+        ? string + '\x00'
+        : string;
+  }
+
+  static bool isLegalIdentifier(String identifier) {
+    StringScanner scanner = new StringScanner(identifier);
+    Token startToken = scanner.tokenize();
+    return startToken is! ErrorToken && startToken.next.isEof;
+  }
+
+  int advance() => string.codeUnitAt(++scanOffset);
+  int peek() => string.codeUnitAt(scanOffset + 1);
+
+  int get stringOffset => scanOffset;
+
+  int currentAsUnicode(int next) => next;
+
+  void handleUnicode(int startScanOffset) {}
+
+  @override
+  analyzer.StringToken createSubstringToken(
+      TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new StringToken.fromSubstring(
+        type, string, start, scanOffset + extraOffset, tokenStart,
+        canonicalize: true, precedingComments: comments);
+  }
+
+  @override
+  analyzer.StringToken createSyntheticSubstringToken(
+      TokenType type, int start, bool asciiOnly, String syntheticChars) {
+    String source = string.substring(start, scanOffset);
+    return new SyntheticStringToken(
+        type, source + syntheticChars, tokenStart, source.length);
+  }
+
+  @override
+  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new CommentToken.fromSubstring(
+        type, string, start, scanOffset + extraOffset, tokenStart,
+        canonicalize: true);
+  }
+
+  @override
+  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new DartDocToken.fromSubstring(
+        type, string, start, scanOffset + extraOffset, tokenStart,
+        canonicalize: true);
+  }
+
+  @override
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor) {
+    return new LanguageVersionToken.fromSubstring(
+        string, start, scanOffset, tokenStart, major, minor,
+        canonicalize: true);
+  }
+
+  bool atEndOfFile() => scanOffset >= string.length - 1;
+}
diff --git a/pkg/front_end/lib/src/scanner/string_utilities.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/string_utilities.dart
similarity index 100%
rename from pkg/front_end/lib/src/scanner/string_utilities.dart
rename to pkg/_fe_analyzer_shared/lib/src/scanner/string_utilities.dart
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
new file mode 100644
index 0000000..bf06c11
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -0,0 +1,1737 @@
+// 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.
+
+/**
+ * Defines the tokens that are produced by the scanner, used by the parser, and
+ * referenced from the [AST structure](ast.dart).
+ */
+import 'dart:collection';
+
+import '../base/syntactic_entity.dart';
+import 'string_utilities.dart';
+import 'token_constants.dart';
+
+const int NO_PRECEDENCE = 0;
+const int ASSIGNMENT_PRECEDENCE = 1;
+const int CASCADE_PRECEDENCE = 2;
+const int CONDITIONAL_PRECEDENCE = 3;
+const int IF_NULL_PRECEDENCE = 4;
+const int LOGICAL_OR_PRECEDENCE = 5;
+const int LOGICAL_AND_PRECEDENCE = 6;
+const int EQUALITY_PRECEDENCE = 7;
+const int RELATIONAL_PRECEDENCE = 8;
+const int BITWISE_OR_PRECEDENCE = 9;
+const int BITWISE_XOR_PRECEDENCE = 10;
+const int BITWISE_AND_PRECEDENCE = 11;
+const int SHIFT_PRECEDENCE = 12;
+const int ADDITIVE_PRECEDENCE = 13;
+const int MULTIPLICATIVE_PRECEDENCE = 14;
+const int PREFIX_PRECEDENCE = 15;
+const int POSTFIX_PRECEDENCE = 16;
+const int SELECTOR_PRECEDENCE = 17;
+
+/**
+ * The opening half of a grouping pair of tokens. This is used for curly
+ * brackets ('{'), parentheses ('('), and square brackets ('[').
+ */
+class BeginToken extends SimpleToken {
+  /**
+   * The token that corresponds to this token.
+   */
+  Token endToken;
+
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset].
+   */
+  BeginToken(TokenType type, int offset, [CommentToken precedingComment])
+      : super(type, offset, precedingComment) {
+    assert(type == TokenType.LT ||
+        type == TokenType.OPEN_CURLY_BRACKET ||
+        type == TokenType.OPEN_PAREN ||
+        type == TokenType.OPEN_SQUARE_BRACKET ||
+        type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
+        type == TokenType.STRING_INTERPOLATION_EXPRESSION);
+  }
+
+  @override
+  Token copy() => new BeginToken(type, offset, copyComments(precedingComments));
+
+  @override
+  Token get endGroup => endToken;
+
+  /**
+   * Set the token that corresponds to this token.
+   */
+  set endGroup(Token token) {
+    endToken = token;
+  }
+}
+
+/**
+ * A token representing a comment.
+ */
+class CommentToken extends StringToken {
+  /**
+   * The token that contains this comment.
+   */
+  SimpleToken parent;
+
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  CommentToken(TokenType type, String value, int offset)
+      : super(type, value, offset);
+
+  @override
+  CommentToken copy() => new CommentToken(type, _value, offset);
+
+  /**
+   * Remove this comment token from the list.
+   *
+   * This is used when we decide to interpret the comment as syntax.
+   */
+  void remove() {
+    if (previous != null) {
+      previous.setNextWithoutSettingPrevious(next);
+      next?.previous = previous;
+    } else {
+      assert(parent.precedingComments == this);
+      parent.precedingComments = next;
+    }
+  }
+}
+
+/**
+ * A documentation comment token.
+ */
+class DocumentationCommentToken extends CommentToken {
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset].
+   */
+  DocumentationCommentToken(TokenType type, String value, int offset)
+      : super(type, value, offset);
+
+  @override
+  CommentToken copy() => new DocumentationCommentToken(type, _value, offset);
+}
+
+/**
+ * The keywords in the Dart programming language.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class Keyword extends TokenType {
+  static const Keyword ABSTRACT =
+      const Keyword("abstract", "ABSTRACT", isBuiltIn: true, isModifier: true);
+
+  static const Keyword AS = const Keyword("as", "AS",
+      precedence: RELATIONAL_PRECEDENCE, isBuiltIn: true);
+
+  static const Keyword ASSERT = const Keyword("assert", "ASSERT");
+
+  static const Keyword ASYNC = const Keyword("async", "ASYNC", isPseudo: true);
+
+  static const Keyword AWAIT = const Keyword("await", "AWAIT", isPseudo: true);
+
+  static const Keyword BREAK = const Keyword("break", "BREAK");
+
+  static const Keyword CASE = const Keyword("case", "CASE");
+
+  static const Keyword CATCH = const Keyword("catch", "CATCH");
+
+  static const Keyword CLASS =
+      const Keyword("class", "CLASS", isTopLevelKeyword: true);
+
+  static const Keyword CONST =
+      const Keyword("const", "CONST", isModifier: true);
+
+  static const Keyword CONTINUE = const Keyword("continue", "CONTINUE");
+
+  static const Keyword COVARIANT = const Keyword("covariant", "COVARIANT",
+      isBuiltIn: true, isModifier: true);
+
+  static const Keyword DEFAULT = const Keyword("default", "DEFAULT");
+
+  static const Keyword DEFERRED =
+      const Keyword("deferred", "DEFERRED", isBuiltIn: true);
+
+  static const Keyword DO = const Keyword("do", "DO");
+
+  static const Keyword DYNAMIC =
+      const Keyword("dynamic", "DYNAMIC", isBuiltIn: true);
+
+  static const Keyword ELSE = const Keyword("else", "ELSE");
+
+  static const Keyword ENUM =
+      const Keyword("enum", "ENUM", isTopLevelKeyword: true);
+
+  static const Keyword EXPORT = const Keyword("export", "EXPORT",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword EXTENDS = const Keyword("extends", "EXTENDS");
+
+  static const Keyword EXTENSION = const Keyword("extension", "EXTENSION",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword EXTERNAL =
+      const Keyword("external", "EXTERNAL", isBuiltIn: true, isModifier: true);
+
+  static const Keyword FACTORY =
+      const Keyword("factory", "FACTORY", isBuiltIn: true);
+
+  static const Keyword FALSE = const Keyword("false", "FALSE");
+
+  static const Keyword FINAL =
+      const Keyword("final", "FINAL", isModifier: true);
+
+  static const Keyword FINALLY = const Keyword("finally", "FINALLY");
+
+  static const Keyword FOR = const Keyword("for", "FOR");
+
+  static const Keyword FUNCTION =
+      const Keyword("Function", "FUNCTION", isPseudo: true);
+
+  static const Keyword GET = const Keyword("get", "GET", isBuiltIn: true);
+
+  static const Keyword HIDE = const Keyword("hide", "HIDE", isPseudo: true);
+
+  static const Keyword IF = const Keyword("if", "IF");
+
+  static const Keyword IMPLEMENTS =
+      const Keyword("implements", "IMPLEMENTS", isBuiltIn: true);
+
+  static const Keyword IMPORT = const Keyword("import", "IMPORT",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword IN = const Keyword("in", "IN");
+
+  static const Keyword INOUT = const Keyword("inout", "INOUT", isPseudo: true);
+
+  static const Keyword INTERFACE =
+      const Keyword("interface", "INTERFACE", isBuiltIn: true);
+
+  static const Keyword IS =
+      const Keyword("is", "IS", precedence: RELATIONAL_PRECEDENCE);
+
+  static const Keyword LATE =
+      const Keyword("late", "LATE", isModifier: true, isBuiltIn: true);
+
+  static const Keyword LIBRARY = const Keyword("library", "LIBRARY",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword MIXIN =
+      const Keyword("mixin", "MIXIN", isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword NATIVE =
+      const Keyword("native", "NATIVE", isPseudo: true);
+
+  static const Keyword NEW = const Keyword("new", "NEW");
+
+  static const Keyword NULL = const Keyword("null", "NULL");
+
+  static const Keyword OF = const Keyword("of", "OF", isPseudo: true);
+
+  static const Keyword ON = const Keyword("on", "ON", isPseudo: true);
+
+  static const Keyword OPERATOR =
+      const Keyword("operator", "OPERATOR", isBuiltIn: true);
+
+  static const Keyword OUT = const Keyword("out", "OUT", isPseudo: true);
+
+  static const Keyword PART =
+      const Keyword("part", "PART", isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword PATCH = const Keyword("patch", "PATCH", isPseudo: true);
+
+  static const Keyword REQUIRED =
+      const Keyword("required", "REQUIRED", isBuiltIn: true, isModifier: true);
+
+  static const Keyword RETHROW = const Keyword("rethrow", "RETHROW");
+
+  static const Keyword RETURN = const Keyword("return", "RETURN");
+
+  static const Keyword SET = const Keyword("set", "SET", isBuiltIn: true);
+
+  static const Keyword SHOW = const Keyword("show", "SHOW", isPseudo: true);
+
+  static const Keyword SOURCE =
+      const Keyword("source", "SOURCE", isPseudo: true);
+
+  static const Keyword STATIC =
+      const Keyword("static", "STATIC", isBuiltIn: true, isModifier: true);
+
+  static const Keyword SUPER = const Keyword("super", "SUPER");
+
+  static const Keyword SWITCH = const Keyword("switch", "SWITCH");
+
+  static const Keyword SYNC = const Keyword("sync", "SYNC", isPseudo: true);
+
+  static const Keyword THIS = const Keyword("this", "THIS");
+
+  static const Keyword THROW = const Keyword("throw", "THROW");
+
+  static const Keyword TRUE = const Keyword("true", "TRUE");
+
+  static const Keyword TRY = const Keyword("try", "TRY");
+
+  static const Keyword TYPEDEF = const Keyword("typedef", "TYPEDEF",
+      isBuiltIn: true, isTopLevelKeyword: true);
+
+  static const Keyword VAR = const Keyword("var", "VAR", isModifier: true);
+
+  static const Keyword VOID = const Keyword("void", "VOID");
+
+  static const Keyword WHILE = const Keyword("while", "WHILE");
+
+  static const Keyword WITH = const Keyword("with", "WITH");
+
+  static const Keyword YIELD = const Keyword("yield", "YIELD", isPseudo: true);
+
+  static const List<Keyword> values = const <Keyword>[
+    ABSTRACT,
+    AS,
+    ASSERT,
+    ASYNC,
+    AWAIT,
+    BREAK,
+    CASE,
+    CATCH,
+    CLASS,
+    CONST,
+    CONTINUE,
+    COVARIANT,
+    DEFAULT,
+    DEFERRED,
+    DO,
+    DYNAMIC,
+    ELSE,
+    ENUM,
+    EXPORT,
+    EXTENDS,
+    EXTENSION,
+    EXTERNAL,
+    FACTORY,
+    FALSE,
+    FINAL,
+    FINALLY,
+    FOR,
+    FUNCTION,
+    GET,
+    HIDE,
+    IF,
+    IMPLEMENTS,
+    IMPORT,
+    IN,
+    INOUT,
+    INTERFACE,
+    IS,
+    LATE,
+    LIBRARY,
+    MIXIN,
+    NATIVE,
+    NEW,
+    NULL,
+    OF,
+    ON,
+    OPERATOR,
+    OUT,
+    PART,
+    PATCH,
+    REQUIRED,
+    RETHROW,
+    RETURN,
+    SET,
+    SHOW,
+    SOURCE,
+    STATIC,
+    SUPER,
+    SWITCH,
+    SYNC,
+    THIS,
+    THROW,
+    TRUE,
+    TRY,
+    TYPEDEF,
+    VAR,
+    VOID,
+    WHILE,
+    WITH,
+    YIELD,
+  ];
+
+  /**
+   * A table mapping the lexemes of keywords to the corresponding keyword.
+   */
+  static final Map<String, Keyword> keywords = _createKeywordMap();
+
+  /**
+   * A flag indicating whether the keyword is "built-in" identifier.
+   */
+  @override
+  final bool isBuiltIn;
+
+  @override
+  final bool isPseudo;
+
+  /**
+   * Initialize a newly created keyword.
+   */
+  const Keyword(String lexeme, String name,
+      {this.isBuiltIn: false,
+      bool isModifier: false,
+      this.isPseudo: false,
+      bool isTopLevelKeyword: false,
+      int precedence: NO_PRECEDENCE})
+      : super(lexeme, name, precedence, KEYWORD_TOKEN,
+            isModifier: isModifier, isTopLevelKeyword: isTopLevelKeyword);
+
+  bool get isBuiltInOrPseudo => isBuiltIn || isPseudo;
+
+  /**
+   * A flag indicating whether the keyword is "built-in" identifier.
+   * This method exists for backward compatibility and will be removed.
+   * Use [isBuiltIn] instead.
+   */
+  @deprecated
+  bool get isPseudoKeyword => isBuiltIn; // TODO (danrubel): remove this
+
+  /**
+   * The name of the keyword type.
+   */
+  String get name => lexeme.toUpperCase();
+
+  /**
+   * The lexeme for the keyword.
+   *
+   * Deprecated - use [lexeme] instead.
+   */
+  @deprecated
+  String get syntax => lexeme;
+
+  @override
+  String toString() => name;
+
+  /**
+   * Create a table mapping the lexemes of keywords to the corresponding keyword
+   * and return the table that was created.
+   */
+  static Map<String, Keyword> _createKeywordMap() {
+    LinkedHashMap<String, Keyword> result =
+        new LinkedHashMap<String, Keyword>();
+    for (Keyword keyword in values) {
+      result[keyword.lexeme] = keyword;
+    }
+    return result;
+  }
+}
+
+/**
+ * A token representing a keyword in the language.
+ */
+class KeywordToken extends SimpleToken {
+  @override
+  final Keyword keyword;
+
+  /**
+   * Initialize a newly created token to represent the given [keyword] at the
+   * given [offset].
+   */
+  KeywordToken(this.keyword, int offset, [CommentToken precedingComment])
+      : super(keyword, offset, precedingComment);
+
+  @override
+  Token copy() =>
+      new KeywordToken(keyword, offset, copyComments(precedingComments));
+
+  @override
+  bool get isIdentifier => keyword.isPseudo || keyword.isBuiltIn;
+
+  @override
+  bool get isKeyword => true;
+
+  @override
+  bool get isKeywordOrIdentifier => true;
+
+  @override
+  Object value() => keyword;
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ */
+class SimpleToken implements Token {
+  /**
+   * The type of the token.
+   */
+  @override
+  final TokenType type;
+
+  /**
+   * The offset from the beginning of the file to the first character in the
+   * token.
+   */
+  @override
+  int offset = 0;
+
+  /**
+   * The previous token in the token stream.
+   */
+  @override
+  Token previous;
+
+  @override
+  Token next;
+
+  /**
+   * The first comment in the list of comments that precede this token.
+   */
+  CommentToken _precedingComment;
+
+  /**
+   * Initialize a newly created token to have the given [type] and [offset].
+   */
+  SimpleToken(this.type, this.offset, [this._precedingComment]) {
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  int get charCount => length;
+
+  @override
+  int get charOffset => offset;
+
+  @override
+  int get charEnd => end;
+
+  @override
+  Token get beforeSynthetic => null;
+
+  @override
+  set beforeSynthetic(Token previous) {
+    // ignored
+  }
+
+  @override
+  int get end => offset + length;
+
+  @override
+  Token get endGroup => null;
+
+  @override
+  bool get isEof => type == TokenType.EOF;
+
+  @override
+  bool get isIdentifier => false;
+
+  @override
+  bool get isKeyword => false;
+
+  @override
+  bool get isKeywordOrIdentifier => isIdentifier;
+
+  @override
+  bool get isModifier => type.isModifier;
+
+  @override
+  bool get isOperator => type.isOperator;
+
+  @override
+  bool get isSynthetic => length == 0;
+
+  @override
+  bool get isTopLevelKeyword => type.isTopLevelKeyword;
+
+  @override
+  bool get isUserDefinableOperator => type.isUserDefinableOperator;
+
+  @override
+  Keyword get keyword => null;
+
+  @override
+  int get kind => type.kind;
+
+  @override
+  int get length => lexeme.length;
+
+  @override
+  String get lexeme => type.lexeme;
+
+  @override
+  CommentToken get precedingComments => _precedingComment;
+
+  void set precedingComments(CommentToken comment) {
+    _precedingComment = comment;
+    _setCommentParent(_precedingComment);
+  }
+
+  @override
+  String get stringValue => type.stringValue;
+
+  @override
+  Token copy() =>
+      new SimpleToken(type, offset, copyComments(precedingComments));
+
+  @override
+  Token copyComments(Token token) {
+    if (token == null) {
+      return null;
+    }
+    Token head = token.copy();
+    Token tail = head;
+    token = token.next;
+    while (token != null) {
+      tail = tail.setNext(token.copy());
+      token = token.next;
+    }
+    return head;
+  }
+
+  @override
+  bool matchesAny(List<TokenType> types) {
+    for (TokenType type in types) {
+      if (this.type == type) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  Token setNext(Token token) {
+    next = token;
+    token.previous = this;
+    token.beforeSynthetic = this;
+    return token;
+  }
+
+  @override
+  Token setNextWithoutSettingPrevious(Token token) {
+    next = token;
+    return token;
+  }
+
+  @override
+  String toString() => lexeme;
+
+  @override
+  Object value() => lexeme;
+
+  /**
+   * Sets the `parent` property to `this` for the given [comment] and all the
+   * next tokens.
+   */
+  void _setCommentParent(CommentToken comment) {
+    while (comment != null) {
+      comment.parent = this;
+      comment = comment.next;
+    }
+  }
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class StringToken extends SimpleToken {
+  /**
+   * The lexeme represented by this token.
+   */
+  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])
+      : super(type, offset, precedingComment) {
+    this._value = StringUtilities.intern(value);
+  }
+
+  @override
+  bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN);
+
+  @override
+  String get lexeme => _value;
+
+  @override
+  Token copy() =>
+      new StringToken(type, _value, offset, copyComments(precedingComments));
+
+  @override
+  String value() => _value;
+}
+
+/**
+ * A synthetic begin token.
+ */
+class SyntheticBeginToken extends BeginToken {
+  /**
+   * Initialize a newly created token to have the given [type] at the given
+   * [offset].
+   */
+  SyntheticBeginToken(TokenType type, int offset,
+      [CommentToken precedingComment])
+      : super(type, offset, precedingComment);
+
+  @override
+  Token copy() =>
+      new SyntheticBeginToken(type, offset, copyComments(precedingComments));
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
+  int get length => 0;
+}
+
+/**
+ * A synthetic keyword token.
+ */
+class SyntheticKeywordToken extends KeywordToken {
+  /**
+   * Initialize a newly created token to represent the given [keyword] at the
+   * given [offset].
+   */
+  SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, offset);
+
+  @override
+  int get length => 0;
+
+  @override
+  Token copy() => new SyntheticKeywordToken(keyword, offset);
+}
+
+/**
+ * A token whose value is independent of it's type.
+ */
+class SyntheticStringToken extends StringToken {
+  final int _length;
+
+  /**
+   * Initialize a newly created token to represent a token of the given [type]
+   * with the given [value] at the given [offset]. If the [length] is
+   * not specified, then it defaults to the length of [value].
+   */
+  SyntheticStringToken(TokenType type, String value, int offset, [this._length])
+      : super(type, value, offset);
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
+  int get length => _length ?? super.length;
+
+  @override
+  Token copy() => new SyntheticStringToken(type, _value, offset, _length);
+}
+
+/**
+ * A synthetic token.
+ */
+class SyntheticToken extends SimpleToken {
+  SyntheticToken(TokenType type, int offset) : super(type, offset);
+
+  @override
+  Token beforeSynthetic;
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
+  int get length => 0;
+
+  @override
+  Token copy() => new SyntheticToken(type, offset);
+}
+
+/**
+ * A token that was scanned from the input. Each token knows which tokens
+ * precede and follow it, acting as a link in a doubly linked list of tokens.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class Token implements SyntacticEntity {
+  /**
+   * Initialize a newly created token to have the given [type] and [offset].
+   */
+  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]) {
+    Token eof = new SimpleToken(TokenType.EOF, offset, precedingComments);
+    // EOF points to itself so there's always infinite look-ahead.
+    eof.previous = eof;
+    eof.next = eof;
+    return eof;
+  }
+
+  /**
+   * The number of characters parsed by this token.
+   */
+  int get charCount;
+
+  /**
+   * The character offset of the start of this token within the source text.
+   */
+  int get charOffset;
+
+  /**
+   * The character offset of the end of this token within the source text.
+   */
+  int get charEnd;
+
+  /**
+   * The token before this synthetic token,
+   * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token.
+   */
+  Token get beforeSynthetic;
+
+  /**
+   * Set token before this synthetic `)`, `]`, `}`, or `>` token,
+   * and ignored otherwise.
+   */
+  set beforeSynthetic(Token previous);
+
+  @override
+  int get end;
+
+  /**
+   * 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;
+
+  /**
+   * Return `true` if this token represents an end of file.
+   */
+  bool get isEof;
+
+  /**
+   * True if this token is an identifier. Some keywords allowed as identifiers,
+   * see implementation in [KeywordToken].
+   */
+  bool get isIdentifier;
+
+  /**
+   * True if this token is a keyword. Some keywords allowed as identifiers,
+   * see implementation in [KeywordToken].
+   */
+  bool get isKeyword;
+
+  /**
+   * True if this token is a keyword or an identifier.
+   */
+  bool get isKeywordOrIdentifier;
+
+  /**
+   * Return `true` if this token is a modifier such as `abstract` or `const`.
+   */
+  bool get isModifier;
+
+  /**
+   * Return `true` if this token represents an operator.
+   */
+  bool get isOperator;
+
+  /**
+   * Return `true` if this token is a synthetic token. A synthetic token is a
+   * token that was introduced by the parser in order to recover from an error
+   * in the code.
+   */
+  bool get isSynthetic;
+
+  /**
+   * Return `true` if this token is a keyword starting a top level declaration
+   * such as `class`, `enum`, `import`, etc.
+   */
+  bool get isTopLevelKeyword;
+
+  /**
+   * Return `true` if this token represents an operator that can be defined by
+   * users.
+   */
+  bool get isUserDefinableOperator;
+
+  /**
+   * Return the keyword, if a keyword token, or `null` otherwise.
+   */
+  Keyword get keyword;
+
+  /**
+   * The kind enum of this token as determined by its [type].
+   */
+  int get kind;
+
+  @override
+  int get length;
+
+  /**
+   * Return the lexeme that represents this token.
+   *
+   * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc.
+   */
+  String get lexeme;
+
+  /**
+   * Return the next token in the token stream.
+   */
+  Token get next;
+
+  /**
+   * Return the next token in the token stream.
+   */
+  void set next(Token next);
+
+  @override
+  int get offset;
+
+  /**
+   * Set the offset from the beginning of the file to the first character in
+   * the token to the given [offset].
+   */
+  void set offset(int offset);
+
+  /**
+   * Return the first comment in the list of comments that precede this token,
+   * or `null` if there are no comments preceding this token. Additional
+   * comments can be reached by following the token stream using [next] until
+   * `null` is returned.
+   *
+   * For example, if the original contents were `/* one */ /* two */ id`, then
+   * the first preceding comment token will have a lexeme of `/* one */` and
+   * the next comment token will have a lexeme of `/* two */`.
+   */
+  Token get precedingComments;
+
+  /**
+   * Return the previous token in the token stream.
+   */
+  Token get previous;
+
+  /**
+   * Set the previous token in the token stream to the given [token].
+   */
+  void set previous(Token token);
+
+  /**
+   * For symbol and keyword tokens, returns the string value represented by this
+   * token. For [StringToken]s this method returns [:null:].
+   *
+   * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
+   * constant originating in the [TokenType] or in the [Keyword] instance.
+   * This allows testing for keywords and symbols using [:identical:], e.g.,
+   * [:identical('class', token.value):].
+   *
+   * Note that returning [:null:] for string tokens is important to identify
+   * symbols and keywords, we cannot use [lexeme] instead. The string literal
+   *   "$a($b"
+   * produces ..., SymbolToken($), StringToken(a), StringToken((), ...
+   *
+   * After parsing the identifier 'a', the parser tests for a function
+   * declaration using [:identical(next.stringValue, '('):], which (rightfully)
+   * returns false because stringValue returns [:null:].
+   */
+  String get stringValue;
+
+  /**
+   * Return the type of the token.
+   */
+  TokenType get type;
+
+  /**
+   * Return a newly created token that is a copy of this tokens
+   * including any [preceedingComment] tokens,
+   * but that is not a part of any token stream.
+   */
+  Token copy();
+
+  /**
+   * Copy a linked list of comment tokens identical to the given comment tokens.
+   */
+  Token copyComments(Token token);
+
+  /**
+   * Return `true` if this token has any one of the given [types].
+   */
+  bool matchesAny(List<TokenType> types);
+
+  /**
+   * Set the next token in the token stream to the given [token]. This has the
+   * side-effect of setting this token to be the previous token for the given
+   * token. Return the token that was passed in.
+   */
+  Token setNext(Token token);
+
+  /**
+   * Set the next token in the token stream to the given token without changing
+   * which token is the previous token for the given token. Return the token
+   * that was passed in.
+   */
+  Token setNextWithoutSettingPrevious(Token token);
+
+  /**
+   * Returns a textual representation of this token to be used for debugging
+   * purposes. The resulting string might contain information about the
+   * structure of the token, for example 'StringToken(foo)' for the identifier
+   * token 'foo'.
+   *
+   * Use [lexeme] for the text actually parsed by the token.
+   */
+  @override
+  String toString();
+
+  /**
+   * Return the value of this token. For keyword tokens, this is the keyword
+   * associated with the token, for other tokens it is the lexeme associated
+   * with the token.
+   */
+  Object value();
+
+  /**
+   * Compare the given [tokens] to find the token that appears first in the
+   * source being parsed. That is, return the left-most of all of the tokens.
+   * The list must be non-`null`, but the elements of the list are allowed to be
+   * `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;
+    int offset = -1;
+    int length = tokens.length;
+    for (int i = 0; i < length; i++) {
+      Token token = tokens[i];
+      if (token != null && (offset < 0 || token.offset < offset)) {
+        first = token;
+        offset = token.offset;
+      }
+    }
+    return first;
+  }
+}
+
+/**
+ * The classes (or groups) of tokens with a similar use.
+ */
+class TokenClass {
+  /**
+   * A value used to indicate that the token type is not part of any specific
+   * class of token.
+   */
+  static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
+
+  /**
+   * A value used to indicate that the token type is an additive operator.
+   */
+  static const TokenClass ADDITIVE_OPERATOR =
+      const TokenClass('ADDITIVE_OPERATOR', ADDITIVE_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is an assignment operator.
+   */
+  static const TokenClass ASSIGNMENT_OPERATOR =
+      const TokenClass('ASSIGNMENT_OPERATOR', ASSIGNMENT_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-and operator.
+   */
+  static const TokenClass BITWISE_AND_OPERATOR =
+      const TokenClass('BITWISE_AND_OPERATOR', BITWISE_AND_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-or operator.
+   */
+  static const TokenClass BITWISE_OR_OPERATOR =
+      const TokenClass('BITWISE_OR_OPERATOR', BITWISE_OR_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a bitwise-xor operator.
+   */
+  static const TokenClass BITWISE_XOR_OPERATOR =
+      const TokenClass('BITWISE_XOR_OPERATOR', BITWISE_XOR_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a cascade operator.
+   */
+  static const TokenClass CASCADE_OPERATOR =
+      const TokenClass('CASCADE_OPERATOR', CASCADE_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a conditional operator.
+   */
+  static const TokenClass CONDITIONAL_OPERATOR =
+      const TokenClass('CONDITIONAL_OPERATOR', CONDITIONAL_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is an equality operator.
+   */
+  static const TokenClass EQUALITY_OPERATOR =
+      const TokenClass('EQUALITY_OPERATOR', EQUALITY_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is an if-null operator.
+   */
+  static const TokenClass IF_NULL_OPERATOR =
+      const TokenClass('IF_NULL_OPERATOR', IF_NULL_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a logical-and operator.
+   */
+  static const TokenClass LOGICAL_AND_OPERATOR =
+      const TokenClass('LOGICAL_AND_OPERATOR', LOGICAL_AND_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a logical-or operator.
+   */
+  static const TokenClass LOGICAL_OR_OPERATOR =
+      const TokenClass('LOGICAL_OR_OPERATOR', LOGICAL_OR_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a multiplicative operator.
+   */
+  static const TokenClass MULTIPLICATIVE_OPERATOR =
+      const TokenClass('MULTIPLICATIVE_OPERATOR', MULTIPLICATIVE_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a relational operator.
+   */
+  static const TokenClass RELATIONAL_OPERATOR =
+      const TokenClass('RELATIONAL_OPERATOR', RELATIONAL_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a shift operator.
+   */
+  static const TokenClass SHIFT_OPERATOR =
+      const TokenClass('SHIFT_OPERATOR', SHIFT_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a unary operator.
+   */
+  static const TokenClass UNARY_POSTFIX_OPERATOR =
+      const TokenClass('UNARY_POSTFIX_OPERATOR', POSTFIX_PRECEDENCE);
+
+  /**
+   * A value used to indicate that the token type is a unary operator.
+   */
+  static const TokenClass UNARY_PREFIX_OPERATOR =
+      const TokenClass('UNARY_PREFIX_OPERATOR', PREFIX_PRECEDENCE);
+
+  /**
+   * The name of the token class.
+   */
+  final String name;
+
+  /**
+   * The precedence of tokens of this class, or `0` if the such tokens do not
+   * represent an operator.
+   */
+  final int precedence;
+
+  /**
+   * Initialize a newly created class of tokens to have the given [name] and
+   * [precedence].
+   */
+  const TokenClass(this.name, [this.precedence = NO_PRECEDENCE]);
+
+  @override
+  String toString() => name;
+}
+
+/**
+ * The types of tokens that can be returned by the scanner.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class TokenType {
+  /**
+   * The type of the token that marks the start or end of the input.
+   */
+  static const TokenType EOF =
+      const TokenType('', 'EOF', NO_PRECEDENCE, EOF_TOKEN);
+
+  static const TokenType DOUBLE = const TokenType(
+      'double', 'DOUBLE', NO_PRECEDENCE, DOUBLE_TOKEN,
+      stringValue: null);
+
+  static const TokenType HEXADECIMAL = const TokenType(
+      'hexadecimal', 'HEXADECIMAL', NO_PRECEDENCE, HEXADECIMAL_TOKEN,
+      stringValue: null);
+
+  static const TokenType IDENTIFIER = const TokenType(
+      'identifier', 'IDENTIFIER', NO_PRECEDENCE, IDENTIFIER_TOKEN,
+      stringValue: null);
+
+  static const TokenType INT = const TokenType(
+      'int', 'INT', NO_PRECEDENCE, INT_TOKEN,
+      stringValue: null);
+
+  static const TokenType MULTI_LINE_COMMENT = const TokenType(
+      'comment', 'MULTI_LINE_COMMENT', NO_PRECEDENCE, COMMENT_TOKEN,
+      stringValue: null);
+
+  static const TokenType SCRIPT_TAG =
+      const TokenType('script', 'SCRIPT_TAG', NO_PRECEDENCE, SCRIPT_TOKEN);
+
+  static const TokenType SINGLE_LINE_COMMENT = const TokenType(
+      'comment', 'SINGLE_LINE_COMMENT', NO_PRECEDENCE, COMMENT_TOKEN,
+      stringValue: null);
+
+  static const TokenType STRING = const TokenType(
+      'string', 'STRING', NO_PRECEDENCE, STRING_TOKEN,
+      stringValue: null);
+
+  static const TokenType AMPERSAND = const TokenType(
+      '&', 'AMPERSAND', BITWISE_AND_PRECEDENCE, AMPERSAND_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType AMPERSAND_AMPERSAND = const TokenType('&&',
+      'AMPERSAND_AMPERSAND', LOGICAL_AND_PRECEDENCE, AMPERSAND_AMPERSAND_TOKEN,
+      isOperator: true);
+
+  // This is not yet part of the language and not supported by fasta
+  static const TokenType AMPERSAND_AMPERSAND_EQ = const TokenType(
+      '&&=',
+      'AMPERSAND_AMPERSAND_EQ',
+      ASSIGNMENT_PRECEDENCE,
+      AMPERSAND_AMPERSAND_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType AMPERSAND_EQ = const TokenType(
+      '&=', 'AMPERSAND_EQ', ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType AT =
+      const TokenType('@', 'AT', NO_PRECEDENCE, AT_TOKEN);
+
+  static const TokenType BANG = const TokenType(
+      '!', 'BANG', PREFIX_PRECEDENCE, BANG_TOKEN,
+      isOperator: true);
+
+  static const TokenType BANG_EQ = const TokenType(
+      '!=', 'BANG_EQ', EQUALITY_PRECEDENCE, BANG_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType BANG_EQ_EQ = const TokenType(
+      '!==', 'BANG_EQ_EQ', EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
+
+  static const TokenType BAR = const TokenType(
+      '|', 'BAR', BITWISE_OR_PRECEDENCE, BAR_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType BAR_BAR = const TokenType(
+      '||', 'BAR_BAR', LOGICAL_OR_PRECEDENCE, BAR_BAR_TOKEN,
+      isOperator: true);
+
+  // This is not yet part of the language and not supported by fasta
+  static const TokenType BAR_BAR_EQ = const TokenType(
+      '||=', 'BAR_BAR_EQ', ASSIGNMENT_PRECEDENCE, BAR_BAR_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType BAR_EQ = const TokenType(
+      '|=', 'BAR_EQ', ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType COLON =
+      const TokenType(':', 'COLON', NO_PRECEDENCE, COLON_TOKEN);
+
+  static const TokenType COMMA =
+      const TokenType(',', 'COMMA', NO_PRECEDENCE, COMMA_TOKEN);
+
+  static const TokenType CARET = const TokenType(
+      '^', 'CARET', BITWISE_XOR_PRECEDENCE, CARET_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType CARET_EQ = const TokenType(
+      '^=', 'CARET_EQ', ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType CLOSE_CURLY_BRACKET = const TokenType(
+      '}', 'CLOSE_CURLY_BRACKET', NO_PRECEDENCE, CLOSE_CURLY_BRACKET_TOKEN);
+
+  static const TokenType CLOSE_PAREN =
+      const TokenType(')', 'CLOSE_PAREN', NO_PRECEDENCE, CLOSE_PAREN_TOKEN);
+
+  static const TokenType CLOSE_SQUARE_BRACKET = const TokenType(
+      ']', 'CLOSE_SQUARE_BRACKET', NO_PRECEDENCE, CLOSE_SQUARE_BRACKET_TOKEN);
+
+  static const TokenType EQ = const TokenType(
+      '=', 'EQ', ASSIGNMENT_PRECEDENCE, EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType EQ_EQ = const TokenType(
+      '==', 'EQ_EQ', EQUALITY_PRECEDENCE, EQ_EQ_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  /// The `===` operator is not supported in the Dart language
+  /// but is parsed as such by the scanner to support better recovery
+  /// when a JavaScript code snippet is pasted into a Dart file.
+  static const TokenType EQ_EQ_EQ =
+      const TokenType('===', 'EQ_EQ_EQ', EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
+
+  static const TokenType FUNCTION =
+      const TokenType('=>', 'FUNCTION', NO_PRECEDENCE, FUNCTION_TOKEN);
+
+  static const TokenType GT = const TokenType(
+      '>', 'GT', RELATIONAL_PRECEDENCE, GT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType GT_EQ = const TokenType(
+      '>=', 'GT_EQ', RELATIONAL_PRECEDENCE, GT_EQ_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType GT_GT = const TokenType(
+      '>>', 'GT_GT', SHIFT_PRECEDENCE, GT_GT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType GT_GT_EQ = const TokenType(
+      '>>=', 'GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType GT_GT_GT = const TokenType(
+      '>>>', 'GT_GT_GT', SHIFT_PRECEDENCE, GT_GT_GT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType GT_GT_GT_EQ = const TokenType(
+      '>>>=', 'GT_GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_GT_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType HASH =
+      const TokenType('#', 'HASH', NO_PRECEDENCE, HASH_TOKEN);
+
+  static const TokenType INDEX = const TokenType(
+      '[]', 'INDEX', SELECTOR_PRECEDENCE, INDEX_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType INDEX_EQ = const TokenType(
+      '[]=', 'INDEX_EQ', NO_PRECEDENCE, INDEX_EQ_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType LT = const TokenType(
+      '<', 'LT', RELATIONAL_PRECEDENCE, LT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType LT_EQ = const TokenType(
+      '<=', 'LT_EQ', RELATIONAL_PRECEDENCE, LT_EQ_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType LT_LT = const TokenType(
+      '<<', 'LT_LT', SHIFT_PRECEDENCE, LT_LT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType LT_LT_EQ = const TokenType(
+      '<<=', 'LT_LT_EQ', ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType MINUS = const TokenType(
+      '-', 'MINUS', ADDITIVE_PRECEDENCE, MINUS_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType MINUS_EQ = const TokenType(
+      '-=', 'MINUS_EQ', ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType MINUS_MINUS = const TokenType(
+      '--', 'MINUS_MINUS', POSTFIX_PRECEDENCE, MINUS_MINUS_TOKEN,
+      isOperator: true);
+
+  static const TokenType OPEN_CURLY_BRACKET = const TokenType(
+      '{', 'OPEN_CURLY_BRACKET', NO_PRECEDENCE, OPEN_CURLY_BRACKET_TOKEN);
+
+  static const TokenType OPEN_PAREN =
+      const TokenType('(', 'OPEN_PAREN', SELECTOR_PRECEDENCE, OPEN_PAREN_TOKEN);
+
+  static const TokenType OPEN_SQUARE_BRACKET = const TokenType('[',
+      'OPEN_SQUARE_BRACKET', SELECTOR_PRECEDENCE, OPEN_SQUARE_BRACKET_TOKEN);
+
+  static const TokenType PERCENT = const TokenType(
+      '%', 'PERCENT', MULTIPLICATIVE_PRECEDENCE, PERCENT_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType PERCENT_EQ = const TokenType(
+      '%=', 'PERCENT_EQ', ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType PERIOD =
+      const TokenType('.', 'PERIOD', SELECTOR_PRECEDENCE, PERIOD_TOKEN);
+
+  static const TokenType PERIOD_PERIOD = const TokenType(
+      '..', 'PERIOD_PERIOD', CASCADE_PRECEDENCE, PERIOD_PERIOD_TOKEN,
+      isOperator: true);
+
+  static const TokenType PLUS = const TokenType(
+      '+', 'PLUS', ADDITIVE_PRECEDENCE, PLUS_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType PLUS_EQ = const TokenType(
+      '+=', 'PLUS_EQ', ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType PLUS_PLUS = const TokenType(
+      '++', 'PLUS_PLUS', POSTFIX_PRECEDENCE, PLUS_PLUS_TOKEN,
+      isOperator: true);
+
+  static const TokenType QUESTION = const TokenType(
+      '?', 'QUESTION', CONDITIONAL_PRECEDENCE, QUESTION_TOKEN,
+      isOperator: true);
+
+  static const TokenType QUESTION_PERIOD = const TokenType(
+      '?.', 'QUESTION_PERIOD', SELECTOR_PRECEDENCE, QUESTION_PERIOD_TOKEN,
+      isOperator: true);
+
+  static const TokenType QUESTION_QUESTION = const TokenType(
+      '??', 'QUESTION_QUESTION', IF_NULL_PRECEDENCE, QUESTION_QUESTION_TOKEN,
+      isOperator: true);
+
+  static const TokenType QUESTION_QUESTION_EQ = const TokenType('??=',
+      'QUESTION_QUESTION_EQ', ASSIGNMENT_PRECEDENCE, QUESTION_QUESTION_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType SEMICOLON =
+      const TokenType(';', 'SEMICOLON', NO_PRECEDENCE, SEMICOLON_TOKEN);
+
+  static const TokenType SLASH = const TokenType(
+      '/', 'SLASH', MULTIPLICATIVE_PRECEDENCE, SLASH_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType SLASH_EQ = const TokenType(
+      '/=', 'SLASH_EQ', ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType STAR = const TokenType(
+      '*', 'STAR', MULTIPLICATIVE_PRECEDENCE, STAR_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType STAR_EQ = const TokenType(
+      '*=', 'STAR_EQ', ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType(
+      '\${',
+      'STRING_INTERPOLATION_EXPRESSION',
+      NO_PRECEDENCE,
+      STRING_INTERPOLATION_TOKEN);
+
+  static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType(
+      '\$',
+      'STRING_INTERPOLATION_IDENTIFIER',
+      NO_PRECEDENCE,
+      STRING_INTERPOLATION_IDENTIFIER_TOKEN);
+
+  static const TokenType TILDE = const TokenType(
+      '~', 'TILDE', PREFIX_PRECEDENCE, TILDE_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType TILDE_SLASH = const TokenType(
+      '~/', 'TILDE_SLASH', MULTIPLICATIVE_PRECEDENCE, TILDE_SLASH_TOKEN,
+      isOperator: true, isUserDefinableOperator: true);
+
+  static const TokenType TILDE_SLASH_EQ = const TokenType(
+      '~/=', 'TILDE_SLASH_EQ', ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN,
+      isOperator: true);
+
+  static const TokenType BACKPING =
+      const TokenType('`', 'BACKPING', NO_PRECEDENCE, BACKPING_TOKEN);
+
+  static const TokenType BACKSLASH =
+      const TokenType('\\', 'BACKSLASH', NO_PRECEDENCE, BACKSLASH_TOKEN);
+
+  static const TokenType PERIOD_PERIOD_PERIOD = const TokenType(
+      '...', 'PERIOD_PERIOD_PERIOD', NO_PRECEDENCE, PERIOD_PERIOD_PERIOD_TOKEN);
+
+  static const TokenType PERIOD_PERIOD_PERIOD_QUESTION = const TokenType(
+      '...?',
+      'PERIOD_PERIOD_PERIOD_QUESTION',
+      NO_PRECEDENCE,
+      PERIOD_PERIOD_PERIOD_QUESTION_TOKEN);
+
+  static const TokenType QUESTION_PERIOD_OPEN_SQUARE_BRACKET = const TokenType(
+      '?.[',
+      'QUESTION_PERIOD_OPEN_SQUARE_BRACKET',
+      SELECTOR_PRECEDENCE,
+      QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN);
+
+  static const TokenType QUESTION_PERIOD_PERIOD = const TokenType(
+      '?..',
+      'QUESTION_PERIOD_PERIOD',
+      CASCADE_PRECEDENCE,
+      QUESTION_PERIOD_PERIOD_TOKEN);
+
+  static const TokenType AS = Keyword.AS;
+
+  static const TokenType IS = Keyword.IS;
+
+  /**
+   * Token type used by error tokens.
+   */
+  static const TokenType BAD_INPUT = const TokenType(
+      'malformed input', 'BAD_INPUT', NO_PRECEDENCE, BAD_INPUT_TOKEN,
+      stringValue: null);
+
+  /**
+   * Token type used by synthetic tokens that are created during parser
+   * recovery (non-analyzer use case).
+   */
+  static const TokenType RECOVERY = const TokenType(
+      'recovery', 'RECOVERY', NO_PRECEDENCE, RECOVERY_TOKEN,
+      stringValue: null);
+
+  // TODO(danrubel): "all" is misleading
+  // because this list does not include all TokenType instances.
+  static const List<TokenType> all = const <TokenType>[
+    TokenType.EOF,
+    TokenType.DOUBLE,
+    TokenType.HEXADECIMAL,
+    TokenType.IDENTIFIER,
+    TokenType.INT,
+    TokenType.MULTI_LINE_COMMENT,
+    TokenType.SCRIPT_TAG,
+    TokenType.SINGLE_LINE_COMMENT,
+    TokenType.STRING,
+    TokenType.AMPERSAND,
+    TokenType.AMPERSAND_AMPERSAND,
+    TokenType.AMPERSAND_EQ,
+    TokenType.AT,
+    TokenType.BANG,
+    TokenType.BANG_EQ,
+    TokenType.BAR,
+    TokenType.BAR_BAR,
+    TokenType.BAR_EQ,
+    TokenType.COLON,
+    TokenType.COMMA,
+    TokenType.CARET,
+    TokenType.CARET_EQ,
+    TokenType.CLOSE_CURLY_BRACKET,
+    TokenType.CLOSE_PAREN,
+    TokenType.CLOSE_SQUARE_BRACKET,
+    TokenType.EQ,
+    TokenType.EQ_EQ,
+    TokenType.FUNCTION,
+    TokenType.GT,
+    TokenType.GT_EQ,
+    TokenType.GT_GT,
+    TokenType.GT_GT_EQ,
+    TokenType.HASH,
+    TokenType.INDEX,
+    TokenType.INDEX_EQ,
+    TokenType.LT,
+    TokenType.LT_EQ,
+    TokenType.LT_LT,
+    TokenType.LT_LT_EQ,
+    TokenType.MINUS,
+    TokenType.MINUS_EQ,
+    TokenType.MINUS_MINUS,
+    TokenType.OPEN_CURLY_BRACKET,
+    TokenType.OPEN_PAREN,
+    TokenType.OPEN_SQUARE_BRACKET,
+    TokenType.PERCENT,
+    TokenType.PERCENT_EQ,
+    TokenType.PERIOD,
+    TokenType.PERIOD_PERIOD,
+    TokenType.PLUS,
+    TokenType.PLUS_EQ,
+    TokenType.PLUS_PLUS,
+    TokenType.QUESTION,
+    TokenType.QUESTION_PERIOD,
+    TokenType.QUESTION_QUESTION,
+    TokenType.QUESTION_QUESTION_EQ,
+    TokenType.SEMICOLON,
+    TokenType.SLASH,
+    TokenType.SLASH_EQ,
+    TokenType.STAR,
+    TokenType.STAR_EQ,
+    TokenType.STRING_INTERPOLATION_EXPRESSION,
+    TokenType.STRING_INTERPOLATION_IDENTIFIER,
+    TokenType.TILDE,
+    TokenType.TILDE_SLASH,
+    TokenType.TILDE_SLASH_EQ,
+    TokenType.BACKPING,
+    TokenType.BACKSLASH,
+    TokenType.PERIOD_PERIOD_PERIOD,
+    TokenType.PERIOD_PERIOD_PERIOD_QUESTION,
+
+    // TODO(danrubel): Should these be added to the "all" list?
+    //TokenType.IS,
+    //TokenType.AS,
+
+    // These are not yet part of the language and not supported by fasta
+    //TokenType.AMPERSAND_AMPERSAND_EQ,
+    //TokenType.BAR_BAR_EQ,
+
+    // Supported by fasta but not part of the language
+    //TokenType.BANG_EQ_EQ,
+    //TokenType.EQ_EQ_EQ,
+
+    // Used by synthetic tokens generated during recovery
+    //TokenType.BAD_INPUT,
+    //TokenType.RECOVERY,
+  ];
+
+  final int kind;
+
+  /**
+   * `true` if this token type represents a modifier
+   * such as `abstract` or `const`.
+   */
+  final bool isModifier;
+
+  /**
+   * `true` if this token type represents an operator.
+   */
+  final bool isOperator;
+
+  /**
+   * `true` if this token type represents a keyword starting a top level
+   * declaration such as `class`, `enum`, `import`, etc.
+   */
+  final bool isTopLevelKeyword;
+
+  /**
+   * `true` if this token type represents an operator
+   * that can be defined by users.
+   */
+  final bool isUserDefinableOperator;
+
+  /**
+   * The lexeme that defines this type of token,
+   * or `null` if there is more than one possible lexeme for this type of token.
+   */
+  final String lexeme;
+
+  /**
+   * The name of the token type.
+   */
+  final String name;
+
+  /**
+   * The precedence of this type of token,
+   * or `0` if the token does not represent an operator.
+   */
+  final int precedence;
+
+  /**
+   * See [Token.stringValue] for an explanation.
+   */
+  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'})
+      : this.stringValue = stringValue == 'unspecified' ? lexeme : stringValue;
+
+  /**
+   * Return `true` if this type of token represents an additive operator.
+   */
+  bool get isAdditiveOperator => precedence == ADDITIVE_PRECEDENCE;
+
+  /**
+   * Return `true` if this type of token represents an assignment operator.
+   */
+  bool get isAssignmentOperator => precedence == ASSIGNMENT_PRECEDENCE;
+
+  /**
+   * Return `true` if this type of token represents an associative operator. An
+   * associative operator is an operator for which the following equality is
+   * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
+   * applying the operator to multiple operands does not depend on the order in
+   * which those applications occur.
+   *
+   * Note: This method considers the logical-and and logical-or operators to be
+   * associative, even though the order in which the application of those
+   * operators can have an effect because evaluation of the right-hand operand
+   * is conditional.
+   */
+  bool get isAssociativeOperator =>
+      this == TokenType.AMPERSAND ||
+      this == TokenType.AMPERSAND_AMPERSAND ||
+      this == TokenType.BAR ||
+      this == TokenType.BAR_BAR ||
+      this == TokenType.CARET ||
+      this == TokenType.PLUS ||
+      this == TokenType.STAR;
+
+  /**
+   * A flag indicating whether the keyword is a "built-in" identifier.
+   */
+  bool get isBuiltIn => false;
+
+  /**
+   * Return `true` if this type of token represents an equality operator.
+   */
+  bool get isEqualityOperator =>
+      this == TokenType.BANG_EQ || this == TokenType.EQ_EQ;
+
+  /**
+   * Return `true` if this type of token represents an increment operator.
+   */
+  bool get isIncrementOperator =>
+      this == TokenType.PLUS_PLUS || this == TokenType.MINUS_MINUS;
+
+  /**
+   * Return `true` if this type of token is a keyword.
+   */
+  bool get isKeyword => kind == KEYWORD_TOKEN;
+
+  /**
+   * A flag indicating whether the keyword can be used as an identifier
+   * in some situations.
+   */
+  bool get isPseudo => false;
+
+  /**
+   * Return `true` if this type of token represents a multiplicative operator.
+   */
+  bool get isMultiplicativeOperator => precedence == MULTIPLICATIVE_PRECEDENCE;
+
+  /**
+   * Return `true` if this type of token represents a relational operator.
+   */
+  bool get isRelationalOperator =>
+      this == TokenType.LT ||
+      this == TokenType.LT_EQ ||
+      this == TokenType.GT ||
+      this == TokenType.GT_EQ;
+
+  /**
+   * Return `true` if this type of token represents a shift operator.
+   */
+  bool get isShiftOperator => precedence == SHIFT_PRECEDENCE;
+
+  /**
+   * Return `true` if this type of token represents a unary postfix operator.
+   */
+  bool get isUnaryPostfixOperator => precedence == POSTFIX_PRECEDENCE;
+
+  /**
+   * Return `true` if this type of token represents a unary prefix operator.
+   */
+  bool get isUnaryPrefixOperator =>
+      precedence == PREFIX_PRECEDENCE ||
+      this == TokenType.MINUS ||
+      this == TokenType.PLUS_PLUS ||
+      this == TokenType.MINUS_MINUS;
+
+  /**
+   * Return `true` if this type of token represents a selector operator
+   * (starting token of a selector).
+   */
+  bool get isSelectorOperator => precedence == SELECTOR_PRECEDENCE;
+
+  @override
+  String toString() => name;
+
+  /**
+   * Use [lexeme] instead of this method
+   */
+  @deprecated
+  String get value => lexeme;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token_constants.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token_constants.dart
new file mode 100644
index 0000000..a0a82ea
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token_constants.dart
@@ -0,0 +1,94 @@
+// 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.
+
+library _fe_analyzer_shared.scanner.token_constants;
+
+import 'characters.dart';
+
+const int EOF_TOKEN = 0;
+
+const int KEYWORD_TOKEN = $k;
+const int IDENTIFIER_TOKEN = $a;
+const int SCRIPT_TOKEN = $b;
+const int BAD_INPUT_TOKEN = $X;
+const int DOUBLE_TOKEN = $d;
+const int INT_TOKEN = $i;
+const int RECOVERY_TOKEN = $r;
+const int HEXADECIMAL_TOKEN = $x;
+const int STRING_TOKEN = $SQ;
+
+const int AMPERSAND_TOKEN = $AMPERSAND;
+const int BACKPING_TOKEN = $BACKPING;
+const int BACKSLASH_TOKEN = $BACKSLASH;
+const int BANG_TOKEN = $BANG;
+const int BAR_TOKEN = $BAR;
+const int COLON_TOKEN = $COLON;
+const int COMMA_TOKEN = $COMMA;
+const int EQ_TOKEN = $EQ;
+const int GT_TOKEN = $GT;
+const int HASH_TOKEN = $HASH;
+const int OPEN_CURLY_BRACKET_TOKEN = $OPEN_CURLY_BRACKET;
+const int OPEN_SQUARE_BRACKET_TOKEN = $OPEN_SQUARE_BRACKET;
+const int OPEN_PAREN_TOKEN = $OPEN_PAREN;
+const int LT_TOKEN = $LT;
+const int MINUS_TOKEN = $MINUS;
+const int PERIOD_TOKEN = $PERIOD;
+const int PLUS_TOKEN = $PLUS;
+const int QUESTION_TOKEN = $QUESTION;
+const int AT_TOKEN = $AT;
+const int CLOSE_CURLY_BRACKET_TOKEN = $CLOSE_CURLY_BRACKET;
+const int CLOSE_SQUARE_BRACKET_TOKEN = $CLOSE_SQUARE_BRACKET;
+const int CLOSE_PAREN_TOKEN = $CLOSE_PAREN;
+const int SEMICOLON_TOKEN = $SEMICOLON;
+const int SLASH_TOKEN = $SLASH;
+const int TILDE_TOKEN = $TILDE;
+const int STAR_TOKEN = $STAR;
+const int PERCENT_TOKEN = $PERCENT;
+const int CARET_TOKEN = $CARET;
+
+const int STRING_INTERPOLATION_TOKEN = 128;
+const int LT_EQ_TOKEN = STRING_INTERPOLATION_TOKEN + 1;
+const int FUNCTION_TOKEN = LT_EQ_TOKEN + 1;
+const int SLASH_EQ_TOKEN = FUNCTION_TOKEN + 1;
+const int PERIOD_PERIOD_PERIOD_TOKEN = SLASH_EQ_TOKEN + 1;
+const int PERIOD_PERIOD_TOKEN = PERIOD_PERIOD_PERIOD_TOKEN + 1;
+const int EQ_EQ_EQ_TOKEN = PERIOD_PERIOD_TOKEN + 1;
+const int EQ_EQ_TOKEN = EQ_EQ_EQ_TOKEN + 1;
+const int LT_LT_EQ_TOKEN = EQ_EQ_TOKEN + 1;
+const int LT_LT_TOKEN = LT_LT_EQ_TOKEN + 1;
+const int GT_EQ_TOKEN = LT_LT_TOKEN + 1;
+const int GT_GT_EQ_TOKEN = GT_EQ_TOKEN + 1;
+const int INDEX_EQ_TOKEN = GT_GT_EQ_TOKEN + 1;
+const int INDEX_TOKEN = INDEX_EQ_TOKEN + 1;
+const int BANG_EQ_EQ_TOKEN = INDEX_TOKEN + 1;
+const int BANG_EQ_TOKEN = BANG_EQ_EQ_TOKEN + 1;
+const int AMPERSAND_AMPERSAND_TOKEN = BANG_EQ_TOKEN + 1;
+const int AMPERSAND_AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_TOKEN + 1;
+const int AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_EQ_TOKEN + 1;
+const int BAR_BAR_TOKEN = AMPERSAND_EQ_TOKEN + 1;
+const int BAR_BAR_EQ_TOKEN = BAR_BAR_TOKEN + 1;
+const int BAR_EQ_TOKEN = BAR_BAR_EQ_TOKEN + 1;
+const int STAR_EQ_TOKEN = BAR_EQ_TOKEN + 1;
+const int PLUS_PLUS_TOKEN = STAR_EQ_TOKEN + 1;
+const int PLUS_EQ_TOKEN = PLUS_PLUS_TOKEN + 1;
+const int MINUS_MINUS_TOKEN = PLUS_EQ_TOKEN + 1;
+const int MINUS_EQ_TOKEN = MINUS_MINUS_TOKEN + 1;
+const int TILDE_SLASH_EQ_TOKEN = MINUS_EQ_TOKEN + 1;
+const int TILDE_SLASH_TOKEN = TILDE_SLASH_EQ_TOKEN + 1;
+const int PERCENT_EQ_TOKEN = TILDE_SLASH_TOKEN + 1;
+const int GT_GT_TOKEN = PERCENT_EQ_TOKEN + 1;
+const int CARET_EQ_TOKEN = GT_GT_TOKEN + 1;
+const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1;
+const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1;
+const int QUESTION_PERIOD_TOKEN = STRING_INTERPOLATION_IDENTIFIER_TOKEN + 1;
+const int QUESTION_QUESTION_TOKEN = QUESTION_PERIOD_TOKEN + 1;
+const int QUESTION_QUESTION_EQ_TOKEN = QUESTION_QUESTION_TOKEN + 1;
+const int GENERIC_METHOD_TYPE_ASSIGN_TOKEN = QUESTION_QUESTION_EQ_TOKEN + 1;
+const int GENERIC_METHOD_TYPE_LIST_TOKEN = GENERIC_METHOD_TYPE_ASSIGN_TOKEN + 1;
+const int GT_GT_GT_TOKEN = GENERIC_METHOD_TYPE_LIST_TOKEN + 1;
+const int PERIOD_PERIOD_PERIOD_QUESTION_TOKEN = GT_GT_GT_TOKEN + 1;
+const int GT_GT_GT_EQ_TOKEN = PERIOD_PERIOD_PERIOD_QUESTION_TOKEN + 1;
+const int QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN = GT_GT_GT_EQ_TOKEN + 1;
+const int QUESTION_PERIOD_PERIOD_TOKEN =
+    QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN + 1;
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
new file mode 100644
index 0000000..11187f7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token_impl.dart
@@ -0,0 +1,349 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.scanner.token;
+
+import 'token.dart' as analyzer;
+import 'token.dart' show Token, TokenType;
+
+import 'token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'string_canonicalizer.dart';
+
+/**
+ * A String-valued token. Represents identifiers, string literals,
+ * number literals, comments, and error tokens, using the corresponding
+ * precedence info.
+ */
+class StringToken extends analyzer.SimpleToken implements analyzer.StringToken {
+  /**
+   * The length threshold above which substring tokens are computed lazily.
+   *
+   * For string tokens that are substrings of the program source, the actual
+   * substring extraction is performed lazily. This is beneficial because
+   * not all scanned code are actually used. For unused parts, the substrings
+   * are never computed and allocated.
+   */
+  static const int LAZY_THRESHOLD = 4;
+
+  dynamic /* String | LazySubstring */ valueOrLazySubstring;
+
+  /**
+   * Creates a non-lazy string token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  StringToken.fromString(TokenType type, String value, int charOffset,
+      {bool canonicalize: false, analyzer.CommentToken precedingComments})
+      : valueOrLazySubstring =
+            canonicalizedString(value, 0, value.length, canonicalize),
+        super(type, charOffset, precedingComments);
+
+  /**
+   * Creates a lazy string token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  StringToken.fromSubstring(
+      TokenType type, String data, int start, int end, int charOffset,
+      {bool canonicalize: false, analyzer.CommentToken precedingComments})
+      : super(type, charOffset, precedingComments) {
+    int length = end - start;
+    if (length <= LAZY_THRESHOLD) {
+      valueOrLazySubstring =
+          canonicalizedString(data, start, end, canonicalize);
+    } else {
+      valueOrLazySubstring =
+          new _LazySubstring(data, start, length, canonicalize);
+    }
+  }
+
+  /**
+   * Creates a lazy string token. If [asciiOnly] is false, the byte array
+   * is passed through a UTF-8 decoder.
+   */
+  StringToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
+      bool asciiOnly, int charOffset,
+      {analyzer.CommentToken precedingComments})
+      : super(type, charOffset, precedingComments) {
+    int length = end - start;
+    if (length <= LAZY_THRESHOLD) {
+      valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly);
+    } else {
+      valueOrLazySubstring = new _LazySubstring(data, start, length, asciiOnly);
+    }
+  }
+
+  StringToken._(TokenType type, this.valueOrLazySubstring, int charOffset,
+      [analyzer.CommentToken precedingComments])
+      : super(type, charOffset, precedingComments);
+
+  @override
+  String get lexeme {
+    if (valueOrLazySubstring is String) {
+      return valueOrLazySubstring;
+    } else {
+      assert(valueOrLazySubstring is _LazySubstring);
+      dynamic data = valueOrLazySubstring.data;
+      int start = valueOrLazySubstring.start;
+      int end = start + valueOrLazySubstring.length;
+      if (data is String) {
+        valueOrLazySubstring = canonicalizedString(
+            data, start, end, valueOrLazySubstring.boolValue);
+      } else {
+        valueOrLazySubstring =
+            decodeUtf8(data, start, end, valueOrLazySubstring.boolValue);
+      }
+      return valueOrLazySubstring;
+    }
+  }
+
+  @override
+  bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN);
+
+  @override
+  String toString() => lexeme;
+
+  static final StringCanonicalizer canonicalizer = new StringCanonicalizer();
+
+  static String canonicalizedString(
+      String s, int start, int end, bool canonicalize) {
+    if (!canonicalize) return s;
+    return canonicalizer.canonicalize(s, start, end, false);
+  }
+
+  static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
+    return canonicalizer.canonicalize(data, start, end, asciiOnly);
+  }
+
+  @override
+  Token copy() => new StringToken._(
+      type, valueOrLazySubstring, charOffset, copyComments(precedingComments));
+
+  @override
+  String value() => lexeme;
+}
+
+/**
+ * A String-valued token that does not exist in the original source.
+ */
+class SyntheticStringToken extends StringToken
+    implements analyzer.SyntheticStringToken {
+  SyntheticStringToken(TokenType type, String value, int offset,
+      [analyzer.CommentToken precedingComments])
+      : super._(type, value, offset, precedingComments);
+
+  @override
+  int get length => 0;
+
+  @override
+  Token copy() => new SyntheticStringToken(
+      type, valueOrLazySubstring, offset, copyComments(precedingComments));
+}
+
+class CommentToken extends StringToken implements analyzer.CommentToken {
+  @override
+  analyzer.SimpleToken parent;
+
+  /**
+   * Creates a lazy comment token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  CommentToken.fromSubstring(
+      TokenType type, String data, int start, int end, int charOffset,
+      {bool canonicalize: false})
+      : super.fromSubstring(type, data, start, end, charOffset,
+            canonicalize: canonicalize);
+
+  /**
+   * Creates a non-lazy comment token.
+   */
+  CommentToken.fromString(TokenType type, String lexeme, int charOffset)
+      : super.fromString(type, lexeme, charOffset);
+
+  /**
+   * Creates a lazy string token. If [asciiOnly] is false, the byte array
+   * is passed through a UTF-8 decoder.
+   */
+  CommentToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
+      bool asciiOnly, int charOffset)
+      : super.fromUtf8Bytes(type, data, start, end, asciiOnly, charOffset);
+
+  CommentToken._(TokenType type, valueOrLazySubstring, int charOffset)
+      : super._(type, valueOrLazySubstring, charOffset);
+
+  @override
+  CommentToken copy() =>
+      new CommentToken._(type, valueOrLazySubstring, charOffset);
+
+  @override
+  void remove() {
+    if (previous != null) {
+      previous.setNextWithoutSettingPrevious(next);
+      next?.previous = previous;
+    } else {
+      assert(parent.precedingComments == this);
+      parent.precedingComments = next as CommentToken;
+    }
+  }
+}
+
+/**
+ * A specialized comment token representing a language version
+ * (e.g. '// @dart = 2.1').
+ */
+class LanguageVersionToken extends CommentToken {
+  /**
+   * The major language version.
+   */
+  int major;
+
+  /**
+   * The minor language version.
+   */
+  int minor;
+
+  LanguageVersionToken.from(String text, int offset, this.major, this.minor)
+      : super.fromString(TokenType.SINGLE_LINE_COMMENT, text, offset);
+
+  LanguageVersionToken.fromSubstring(
+      String string, int start, int end, int tokenStart, this.major, this.minor,
+      {bool canonicalize})
+      : super.fromSubstring(
+            TokenType.SINGLE_LINE_COMMENT, string, start, end, tokenStart,
+            canonicalize: canonicalize);
+
+  LanguageVersionToken.fromUtf8Bytes(List<int> bytes, int start, int end,
+      int tokenStart, this.major, this.minor)
+      : super.fromUtf8Bytes(
+            TokenType.SINGLE_LINE_COMMENT, bytes, start, end, true, tokenStart);
+
+  @override
+  LanguageVersionToken copy() =>
+      new LanguageVersionToken.from(lexeme, offset, major, minor);
+}
+
+class DartDocToken extends CommentToken
+    implements analyzer.DocumentationCommentToken {
+  /**
+   * Creates a lazy comment token. If [canonicalize] is true, the string
+   * is canonicalized before the token is created.
+   */
+  DartDocToken.fromSubstring(
+      TokenType type, String data, int start, int end, int charOffset,
+      {bool canonicalize: false})
+      : super.fromSubstring(type, data, start, end, charOffset,
+            canonicalize: canonicalize);
+
+  /**
+   * Creates a lazy string token. If [asciiOnly] is false, the byte array
+   * is passed through a UTF-8 decoder.
+   */
+  DartDocToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
+      bool asciiOnly, int charOffset)
+      : super.fromUtf8Bytes(type, data, start, end, asciiOnly, charOffset);
+
+  DartDocToken._(TokenType type, valueOrLazySubstring, int charOffset)
+      : super._(type, valueOrLazySubstring, charOffset);
+
+  @override
+  DartDocToken copy() =>
+      new DartDocToken._(type, valueOrLazySubstring, charOffset);
+}
+
+/**
+ * This class represents the necessary information to compute a substring
+ * lazily. The substring can either originate from a string or from
+ * a [:List<int>:] of UTF-8 bytes.
+ */
+abstract class _LazySubstring {
+  /** The original data, either a string or a List<int> */
+  get data;
+
+  int get start;
+  int get length;
+
+  /**
+   * If this substring is based on a String, the [boolValue] indicates whether
+   * the resulting substring should be canonicalized.
+   *
+   * For substrings based on a byte array, the [boolValue] is true if the
+   * array only holds ASCII characters. The resulting substring will be
+   * canonicalized after decoding.
+   */
+  bool get boolValue;
+
+  _LazySubstring.internal();
+
+  factory _LazySubstring(data, int start, int length, bool b) {
+    // See comment on [CompactLazySubstring].
+    if (start < 0x100000 && length < 0x200) {
+      int fields = (start << 9);
+      fields = fields | length;
+      fields = fields << 1;
+      if (b) fields |= 1;
+      return new _CompactLazySubstring(data, fields);
+    } else {
+      return new _FullLazySubstring(data, start, length, b);
+    }
+  }
+}
+
+/**
+ * This class encodes [start], [length] and [boolValue] in a single
+ * 30 bit integer. It uses 20 bits for [start], which covers source files
+ * of 1MB. [length] has 9 bits, which covers 512 characters.
+ *
+ * The file html_dart2js.dart is currently around 1MB.
+ */
+class _CompactLazySubstring extends _LazySubstring {
+  final dynamic data;
+  final int fields;
+
+  _CompactLazySubstring(this.data, this.fields) : super.internal();
+
+  int get start => fields >> 10;
+  int get length => (fields >> 1) & 0x1ff;
+  bool get boolValue => (fields & 1) == 1;
+}
+
+class _FullLazySubstring extends _LazySubstring {
+  final dynamic data;
+  final int start;
+  final int length;
+  final bool boolValue;
+  _FullLazySubstring(this.data, this.start, this.length, this.boolValue)
+      : super.internal();
+}
+
+bool isUserDefinableOperator(String value) {
+  return isBinaryOperator(value) ||
+      isMinusOperator(value) ||
+      isTernaryOperator(value) ||
+      isUnaryOperator(value);
+}
+
+bool isUnaryOperator(String value) => identical(value, "~");
+
+bool isBinaryOperator(String value) {
+  return identical(value, "==") ||
+      identical(value, "[]") ||
+      identical(value, "*") ||
+      identical(value, "/") ||
+      identical(value, "%") ||
+      identical(value, "~/") ||
+      identical(value, "+") ||
+      identical(value, "<<") ||
+      identical(value, ">>") ||
+      identical(value, ">>>") ||
+      identical(value, ">=") ||
+      identical(value, ">") ||
+      identical(value, "<=") ||
+      identical(value, "<") ||
+      identical(value, "&") ||
+      identical(value, "^") ||
+      identical(value, "|");
+}
+
+bool isTernaryOperator(String value) => identical(value, "[]=");
+
+bool isMinusOperator(String value) => identical(value, "-");
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
new file mode 100644
index 0000000..8619c6f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart
@@ -0,0 +1,252 @@
+// 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 _fe_analyzer_shared.scanner.utf8_bytes_scanner;
+
+import 'dart:convert' show unicodeBomCharacterRune, utf8;
+
+import 'token.dart' show SyntheticStringToken, TokenType;
+
+import 'token.dart' as analyzer show StringToken;
+
+import 'scanner.dart' show unicodeReplacementCharacter;
+
+import 'abstract_scanner.dart'
+    show AbstractScanner, LanguageVersionChanged, ScannerConfiguration;
+
+import 'token_impl.dart'
+    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
+
+/**
+ * Scanner that reads from a UTF-8 encoded list of bytes and creates tokens
+ * that points to substrings.
+ */
+class Utf8BytesScanner extends AbstractScanner {
+  /**
+   * The file content.
+   *
+   * The content is zero-terminated.
+   */
+  List<int> bytes;
+
+  /**
+   * Points to the offset of the last byte returned by [advance].
+   *
+   * After invoking [currentAsUnicode], the [byteOffset] points to the last
+   * byte that is part of the (unicode or ASCII) character. That way, [advance]
+   * can always increase the byte offset by 1.
+   */
+  int byteOffset = -1;
+
+  /**
+   * The getter [scanOffset] is expected to return the index where the current
+   * character *starts*. In case of a non-ascii character, after invoking
+   * [currentAsUnicode], the byte offset points to the *last* byte.
+   *
+   * This field keeps track of the number of bytes for the current unicode
+   * character. For example, if bytes 7,8,9 encode one unicode character, the
+   * [byteOffset] is 9 (after invoking [currentAsUnicode]). The [scanSlack]
+   * will be 2, so that [scanOffset] returns 7.
+   */
+  int scanSlack = 0;
+
+  /**
+   * Holds the [byteOffset] value for which the current [scanSlack] is valid.
+   */
+  int scanSlackOffset = -1;
+
+  /**
+   * Returns the byte offset of the first byte that belongs to the current
+   * character.
+   */
+  int get scanOffset {
+    if (byteOffset == scanSlackOffset) {
+      return byteOffset - scanSlack;
+    } else {
+      return byteOffset;
+    }
+  }
+
+  /**
+   * The difference between the number of bytes and the number of corresponding
+   * string characters, up to the current [byteOffset].
+   */
+  int utf8Slack = 0;
+
+  /**
+   * Creates a new Utf8BytesScanner. The source file is expected to be a
+   * [Utf8BytesSourceFile] that holds a list of UTF-8 bytes. Otherwise the
+   * string text of the source file is decoded.
+   *
+   * The list of UTF-8 bytes [file.slowUtf8Bytes()] is expected to return an
+   * array whose last element is '0' to signal the end of the file. If this
+   * is not the case, the entire array is copied before scanning.
+   */
+  Utf8BytesScanner(this.bytes,
+      {ScannerConfiguration configuration,
+      bool includeComments: false,
+      LanguageVersionChanged languageVersionChanged})
+      : super(configuration, includeComments, languageVersionChanged,
+            numberOfBytesHint: bytes.length) {
+    assert(bytes.last == 0);
+    // Skip a leading BOM.
+    if (containsBomAt(0)) {
+      byteOffset += 3;
+      utf8Slack += 3;
+    }
+  }
+
+  bool containsBomAt(int offset) {
+    const List<int> BOM_UTF8 = const [0xEF, 0xBB, 0xBF];
+
+    return offset + 3 < bytes.length &&
+        bytes[offset] == BOM_UTF8[0] &&
+        bytes[offset + 1] == BOM_UTF8[1] &&
+        bytes[offset + 2] == BOM_UTF8[2];
+  }
+
+  int advance() => bytes[++byteOffset];
+
+  int peek() => bytes[byteOffset + 1];
+
+  /// Returns the unicode code point starting at the byte offset [startOffset]
+  /// with the byte [nextByte].
+  int nextCodePoint(int startOffset, int nextByte) {
+    int expectedHighBytes;
+    if (nextByte < 0xC2) {
+      expectedHighBytes = 1; // Bad code unit.
+    } else if (nextByte < 0xE0) {
+      expectedHighBytes = 2;
+    } else if (nextByte < 0xF0) {
+      expectedHighBytes = 3;
+    } else if (nextByte < 0xF5) {
+      expectedHighBytes = 4;
+    } else {
+      expectedHighBytes = 1; // Bad code unit.
+    }
+    int numBytes = 0;
+    for (int i = 0; i < expectedHighBytes; i++) {
+      if (bytes[byteOffset + i] < 0x80) {
+        break;
+      }
+      numBytes++;
+    }
+    int end = startOffset + numBytes;
+    byteOffset = end - 1;
+    if (expectedHighBytes == 1 || numBytes != expectedHighBytes) {
+      return unicodeReplacementCharacter;
+    }
+    // TODO(lry): measurably slow, decode creates first a Utf8Decoder and a
+    // _Utf8Decoder instance. Also the sublist is eagerly allocated.
+    String codePoint =
+        utf8.decode(bytes.sublist(startOffset, end), allowMalformed: true);
+    if (codePoint.length == 0) {
+      // The UTF-8 decoder discards leading BOM characters.
+      // TODO(floitsch): don't just assume that removed characters were the
+      // BOM.
+      assert(containsBomAt(startOffset));
+      codePoint = new String.fromCharCode(unicodeBomCharacterRune);
+    }
+    if (codePoint.length == 1) {
+      utf8Slack += (numBytes - 1);
+      scanSlack = numBytes - 1;
+      scanSlackOffset = byteOffset;
+      return codePoint.codeUnitAt(0);
+    } else if (codePoint.length == 2) {
+      utf8Slack += (numBytes - 2);
+      scanSlack = numBytes - 1;
+      scanSlackOffset = byteOffset;
+      stringOffsetSlackOffset = byteOffset;
+      // In case of a surrogate pair, return a single code point.
+      // Gracefully degrade given invalid UTF-8.
+      RuneIterator runes = codePoint.runes.iterator;
+      if (!runes.moveNext()) return unicodeReplacementCharacter;
+      int codeUnit = runes.current;
+      return !runes.moveNext() ? codeUnit : unicodeReplacementCharacter;
+    } else {
+      return unicodeReplacementCharacter;
+    }
+  }
+
+  int lastUnicodeOffset = -1;
+  int currentAsUnicode(int next) {
+    if (next < 128) return next;
+    // Check if currentAsUnicode was already invoked.
+    if (byteOffset == lastUnicodeOffset) return next;
+    int res = nextCodePoint(byteOffset, next);
+    lastUnicodeOffset = byteOffset;
+    return res;
+  }
+
+  void handleUnicode(int startScanOffset) {
+    int end = byteOffset;
+    // TODO(lry): this measurably slows down the scanner for files with unicode.
+    String s =
+        utf8.decode(bytes.sublist(startScanOffset, end), allowMalformed: true);
+    utf8Slack += (end - startScanOffset) - s.length;
+  }
+
+  /**
+   * This field remembers the byte offset of the last character decoded with
+   * [nextCodePoint] that used two code units in UTF-16.
+   *
+   * [nextCodePoint] returns a single code point for each unicode character,
+   * even if it needs two code units in UTF-16.
+   *
+   * For example, '\u{1d11e}' uses 4 bytes in UTF-8, and two code units in
+   * UTF-16. The [utf8Slack] is therefore 2. After invoking [nextCodePoint], the
+   * [byteOffset] points to the last (of 4) bytes. The [stringOffset] should
+   * return the offset of the first one, which is one position more left than
+   * the [utf8Slack].
+   */
+  int stringOffsetSlackOffset = -1;
+
+  int get stringOffset {
+    if (stringOffsetSlackOffset == byteOffset) {
+      return byteOffset - utf8Slack - 1;
+    } else {
+      return byteOffset - utf8Slack;
+    }
+  }
+
+  @override
+  analyzer.StringToken createSubstringToken(
+      TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new StringToken.fromUtf8Bytes(
+        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart,
+        precedingComments: comments);
+  }
+
+  @override
+  analyzer.StringToken createSyntheticSubstringToken(
+      TokenType type, int start, bool asciiOnly, String syntheticChars) {
+    String source = StringToken.decodeUtf8(bytes, start, byteOffset, asciiOnly);
+    return new SyntheticStringToken(
+        type, source + syntheticChars, tokenStart, source.length);
+  }
+
+  @override
+  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new CommentToken.fromUtf8Bytes(
+        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
+  }
+
+  @override
+  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
+      [int extraOffset = 0]) {
+    return new DartDocToken.fromUtf8Bytes(
+        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
+  }
+
+  @override
+  LanguageVersionToken createLanguageVersionToken(
+      int start, int major, int minor) {
+    return new LanguageVersionToken.fromUtf8Bytes(
+        bytes, start, byteOffset, tokenStart, major, minor);
+  }
+
+  bool atEndOfFile() => byteOffset >= bytes.length - 1;
+}
diff --git a/pkg/front_end/lib/src/testing/annotated_code_helper.dart b/pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart
similarity index 100%
rename from pkg/front_end/lib/src/testing/annotated_code_helper.dart
rename to pkg/_fe_analyzer_shared/lib/src/testing/annotated_code_helper.dart
diff --git a/pkg/front_end/lib/src/testing/id.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id.dart
similarity index 100%
rename from pkg/front_end/lib/src/testing/id.dart
rename to pkg/_fe_analyzer_shared/lib/src/testing/id.dart
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
new file mode 100644
index 0000000..58acca5
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -0,0 +1,663 @@
+// 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:io';
+import 'annotated_code_helper.dart';
+import 'id.dart';
+import '../util/colors.dart' as colors;
+
+const String cfeMarker = 'cfe';
+const String cfeWithNnbdMarker = '$cfeMarker:nnbd';
+const String dart2jsMarker = 'dart2js';
+const String analyzerMarker = 'analyzer';
+
+/// Markers used in annotated tests shard by CFE, analyzer and dart2js.
+const List<String> sharedMarkers = [
+  cfeMarker,
+  dart2jsMarker,
+  analyzerMarker,
+];
+
+/// Markers used in annotated tests shard by CFE, analyzer and dart2js.
+const List<String> sharedMarkersWithNnbd = [
+  cfeMarker,
+  cfeWithNnbdMarker,
+  dart2jsMarker,
+  analyzerMarker,
+];
+
+/// `true` if ANSI colors are supported by stdout.
+bool useColors = stdout.supportsAnsiEscapes;
+
+/// Colorize a message [text], if ANSI colors are supported.
+String colorizeMessage(String text) {
+  if (useColors) {
+    return '${colors.YELLOW_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize a matching annotation [text], if ANSI colors are supported.
+String colorizeMatch(String text) {
+  if (useColors) {
+    return '${colors.BLUE_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize a single annotation [text], if ANSI colors are supported.
+String colorizeSingle(String text) {
+  if (useColors) {
+    return '${colors.GREEN_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize the actual annotation [text], if ANSI colors are supported.
+String colorizeActual(String text) {
+  if (useColors) {
+    return '${colors.RED_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize an expected annotation [text], if ANSI colors are supported.
+String colorizeExpected(String text) {
+  if (useColors) {
+    return '${colors.GREEN_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize delimiter [text], if ANSI colors are supported.
+String colorizeDelimiter(String text) {
+  if (useColors) {
+    return '${colors.YELLOW_COLOR}${text}${colors.DEFAULT_COLOR}';
+  } else {
+    return text;
+  }
+}
+
+/// Colorize diffs [expected] and [actual] and [delimiter], if ANSI colors are
+/// supported.
+String colorizeDiff(String expected, String delimiter, String actual) {
+  return '${colorizeExpected(expected)}'
+      '${colorizeDelimiter(delimiter)}${colorizeActual(actual)}';
+}
+
+/// Colorize annotation delimiters [start] and [end] surrounding [text], if
+/// ANSI colors are supported.
+String colorizeAnnotation(String start, String text, String end) {
+  return '${colorizeDelimiter(start)}$text${colorizeDelimiter(end)}';
+}
+
+/// Encapsulates the member data computed for each source file of interest.
+/// It's a glorified wrapper around a map of maps, but written this way to
+/// provide a little more information about what it's doing. [DataType] refers
+/// to the type this map is holding -- it is either [IdValue] or [ActualData].
+class MemberAnnotations<DataType> {
+  /// For each Uri, we create a map associating an element id with its
+  /// corresponding annotations.
+  final Map<Uri, Map<Id, DataType>> _computedDataForEachFile =
+      new Map<Uri, Map<Id, DataType>>();
+
+  /// Member or class annotations that don't refer to any of the user files.
+  final Map<Id, DataType> globalData = <Id, DataType>{};
+
+  void operator []=(Uri file, Map<Id, DataType> computedData) {
+    _computedDataForEachFile[file] = computedData;
+  }
+
+  void forEach(void f(Uri file, Map<Id, DataType> computedData)) {
+    _computedDataForEachFile.forEach(f);
+  }
+
+  Map<Id, DataType> operator [](Uri file) {
+    if (!_computedDataForEachFile.containsKey(file)) {
+      _computedDataForEachFile[file] = <Id, DataType>{};
+    }
+    return _computedDataForEachFile[file];
+  }
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write('MemberAnnotations(');
+    String comma = '';
+    if (_computedDataForEachFile.isNotEmpty &&
+        (_computedDataForEachFile.length > 1 ||
+            _computedDataForEachFile.values.single.isNotEmpty)) {
+      sb.write('data:{');
+      _computedDataForEachFile.forEach((Uri uri, Map<Id, DataType> data) {
+        sb.write(comma);
+        sb.write('$uri:');
+        sb.write(data);
+        comma = ',';
+      });
+      sb.write('}');
+    }
+    if (globalData.isNotEmpty) {
+      sb.write(comma);
+      sb.write('global:');
+      sb.write(globalData);
+    }
+    sb.write(')');
+    return sb.toString();
+  }
+}
+
+/// Compute a [MemberAnnotations] object from [code] for each marker in [maps]
+/// specifying the expected annotations.
+///
+/// If an annotation starts with a marker, it is only expected for the
+/// corresponding test configuration. Otherwise it is expected for all
+/// configurations.
+// TODO(johnniwinther): Support an empty marker set.
+void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
+    Map<String, MemberAnnotations<IdValue>> maps,
+    {void onFailure(String message)}) {
+  List<String> mapKeys = maps.keys.toList();
+  Map<String, AnnotatedCode> split = splitByPrefixes(code, mapKeys);
+
+  split.forEach((String marker, AnnotatedCode code) {
+    MemberAnnotations<IdValue> fileAnnotations = maps[marker];
+    assert(fileAnnotations != null, "No annotations for $marker in $maps");
+    Map<Id, IdValue> expectedValues = fileAnnotations[sourceUri];
+    for (Annotation annotation in code.annotations) {
+      String text = annotation.text;
+      IdValue idValue = IdValue.decode(sourceUri, annotation.offset, text);
+      if (idValue.id.isGlobal) {
+        if (fileAnnotations.globalData.containsKey(idValue.id)) {
+          onFailure("Error in test '$filename': "
+              "Duplicate annotations for ${idValue.id} in $marker: "
+              "${idValue} and ${fileAnnotations.globalData[idValue.id]}.");
+        }
+        fileAnnotations.globalData[idValue.id] = idValue;
+      } else {
+        if (expectedValues.containsKey(idValue.id)) {
+          onFailure("Error in test '$filename': "
+              "Duplicate annotations for ${idValue.id} in $marker: "
+              "${idValue} and ${expectedValues[idValue.id]}.");
+        }
+        expectedValues[idValue.id] = idValue;
+      }
+    }
+  });
+}
+
+/// Creates a [TestData] object for the annotated test in [testFile].
+///
+/// If [testFile] is a file, use that directly. If it's a directory include
+/// everything in that directory.
+///
+/// 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 createUriForFileName(String fileName),
+    void onFailure(String message)}) {
+  Uri entryPoint = createUriForFileName('main.dart');
+
+  String testName;
+  File mainTestFile;
+  Uri testFileUri = testFile.uri;
+  Map<String, File> additionalFiles;
+  if (testFile is File) {
+    testName = testFileUri.pathSegments.last;
+    mainTestFile = testFile;
+  } else if (testFile is Directory) {
+    testName = testFileUri.pathSegments[testFileUri.pathSegments.length - 2];
+    additionalFiles = new Map<String, File>();
+    for (FileSystemEntity entry in testFile.listSync(recursive: true)) {
+      if (entry is! File) continue;
+      if (entry.uri.pathSegments.last == "main.dart") {
+        mainTestFile = entry;
+      } else {
+        additionalFiles[entry.uri.path.substring(testFile.uri.path.length)] =
+            entry;
+      }
+    }
+    assert(
+        mainTestFile != null, "No 'main.dart' test file found for $testFile.");
+  }
+
+  String annotatedCode = new File.fromUri(mainTestFile.uri).readAsStringSync();
+  Map<Uri, AnnotatedCode> code = {
+    entryPoint:
+        new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd)
+  };
+  Map<String, MemberAnnotations<IdValue>> expectedMaps = {};
+  for (String testMarker in supportedMarkers) {
+    expectedMaps[testMarker] = new MemberAnnotations<IdValue>();
+  }
+  computeExpectedMap(entryPoint, testFile.uri.pathSegments.last,
+      code[entryPoint], expectedMaps,
+      onFailure: onFailure);
+  Map<String, String> memorySourceFiles = {
+    entryPoint.path: code[entryPoint].sourceCode
+  };
+
+  if (additionalFiles != null) {
+    for (MapEntry<String, File> additionalFileData in additionalFiles.entries) {
+      String libFileName = additionalFileData.key;
+      File libEntity = additionalFileData.value;
+      Uri libFileUri = createUriForFileName(libFileName);
+      String libCode = libEntity.readAsStringSync();
+      AnnotatedCode annotatedLibCode =
+          new AnnotatedCode.fromText(libCode, commentStart, commentEnd);
+      memorySourceFiles[libFileUri.path] = annotatedLibCode.sourceCode;
+      code[libFileUri] = annotatedLibCode;
+      computeExpectedMap(
+          libFileUri, libFileName, annotatedLibCode, expectedMaps,
+          onFailure: onFailure);
+    }
+  }
+
+  return new TestData(
+      testName, testFileUri, entryPoint, memorySourceFiles, code, expectedMaps);
+}
+
+/// Data for an annotated test.
+class TestData {
+  final String name;
+  final Uri testFileUri;
+  final Uri entryPoint;
+  final Map<String, String> memorySourceFiles;
+  final Map<Uri, AnnotatedCode> code;
+  final Map<String, MemberAnnotations<IdValue>> expectedMaps;
+
+  TestData(this.name, this.testFileUri, this.entryPoint, this.memorySourceFiles,
+      this.code, this.expectedMaps);
+}
+
+/// The actual result computed for an annotated test.
+abstract class CompiledData<T> {
+  final Uri mainUri;
+
+  /// For each Uri, a map associating an element id with the instrumentation
+  /// data we've collected for it.
+  final Map<Uri, Map<Id, ActualData<T>>> actualMaps;
+
+  /// Collected instrumentation data that doesn't refer to any of the user
+  /// files.  (E.g. information the test has collected about files in
+  /// `dart:core`).
+  final Map<Id, ActualData<T>> globalData;
+
+  CompiledData(this.mainUri, this.actualMaps, this.globalData);
+
+  Map<int, List<String>> computeAnnotations(Uri 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}';
+      annotations
+          .putIfAbsent(data.offset, () => [])
+          .add(colorizeActual(value1));
+    });
+    return annotations;
+  }
+
+  Map<int, List<String>> computeDiffAnnotationsAgainst(
+      Map<Id, ActualData<T>> thisMap, Map<Id, ActualData<T>> otherMap, Uri uri,
+      {bool includeMatches: false}) {
+    Map<int, List<String>> annotations = <int, List<String>>{};
+    thisMap.forEach((Id id, ActualData<T> thisData) {
+      ActualData<T> otherData = otherMap[id];
+      String thisValue = '${thisData.value}';
+      if (thisData.value != otherData?.value) {
+        String otherValue = '${otherData?.value ?? '---'}';
+        annotations
+            .putIfAbsent(thisData.offset, () => [])
+            .add(colorizeDiff(thisValue, ' | ', otherValue));
+      } else if (includeMatches) {
+        annotations
+            .putIfAbsent(thisData.offset, () => [])
+            .add(colorizeMatch(thisValue));
+      }
+    });
+    otherMap.forEach((Id id, ActualData<T> otherData) {
+      if (!thisMap.containsKey(id)) {
+        String thisValue = '---';
+        String otherValue = '${otherData.value}';
+        annotations
+            .putIfAbsent(otherData.offset, () => [])
+            .add(colorizeDiff(thisValue, ' | ', otherValue));
+      }
+    });
+    return annotations;
+  }
+
+  int getOffsetFromId(Id id, Uri uri);
+
+  void reportError(Uri uri, int offset, String message, {bool succinct: false});
+}
+
+/// Interface used for interpreting annotations.
+abstract class DataInterpreter<T> {
+  /// 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);
+
+  /// Returns `true` if [actualData] corresponds to empty data.
+  bool isEmpty(T actualData);
+
+  /// Returns a textual representation of [actualData].
+  String getText(T actualData);
+}
+
+/// Default data interpreter for string data.
+class StringDataInterpreter implements DataInterpreter<String> {
+  const StringDataInterpreter();
+
+  @override
+  String isAsExpected(String actualData, String expectedData) {
+    actualData ??= '';
+    expectedData ??= '';
+    if (actualData != expectedData) {
+      return "Expected $expectedData, found $actualData";
+    }
+    return null;
+  }
+
+  @override
+  bool isEmpty(String actualData) {
+    return actualData == '';
+  }
+
+  @override
+  String getText(String actualData) {
+    return actualData;
+  }
+}
+
+String withAnnotations(String sourceCode, Map<int, List<String>> annotations) {
+  StringBuffer sb = new StringBuffer();
+  int end = 0;
+  for (int offset in annotations.keys.toList()..sort()) {
+    if (offset >= sourceCode.length) {
+      sb.write('...');
+      return sb.toString();
+    }
+    if (offset > end) {
+      sb.write(sourceCode.substring(end, offset));
+    }
+    for (String annotation in annotations[offset]) {
+      sb.write(colorizeAnnotation('/*', annotation, '*/'));
+    }
+    end = offset;
+  }
+  if (end < sourceCode.length) {
+    sb.write(sourceCode.substring(end));
+  }
+  return sb.toString();
+}
+
+/// Computed and expected data for an annotated test. This is used for checking
+/// and displaying results of an annotated test.
+class IdData<T> {
+  final Map<Uri, AnnotatedCode> code;
+  final MemberAnnotations<IdValue> expectedMaps;
+  final CompiledData<T> _compiledData;
+  final MemberAnnotations<ActualData<T>> _actualMaps = new MemberAnnotations();
+
+  IdData(this.code, this.expectedMaps, this._compiledData) {
+    for (Uri uri in code.keys) {
+      _actualMaps[uri] = _compiledData.actualMaps[uri] ?? <Id, ActualData<T>>{};
+    }
+    _actualMaps.globalData.addAll(_compiledData.globalData);
+  }
+
+  Uri get mainUri => _compiledData.mainUri;
+  MemberAnnotations<ActualData<T>> get actualMaps => _actualMaps;
+
+  String actualCode(Uri uri) {
+    Map<int, List<String>> annotations = <int, List<String>>{};
+    actualMaps[uri].forEach((Id id, ActualData<T> data) {
+      annotations.putIfAbsent(data.offset, () => []).add('${data.value}');
+    });
+    return withAnnotations(code[uri].sourceCode, annotations);
+  }
+
+  String diffCode(Uri uri, DataInterpreter<T> dataValidator) {
+    Map<int, List<String>> annotations = <int, List<String>>{};
+    actualMaps[uri].forEach((Id id, ActualData<T> data) {
+      IdValue expectedValue = expectedMaps[uri][id];
+      T actualValue = data.value;
+      String unexpectedMessage =
+          dataValidator.isAsExpected(actualValue, expectedValue?.value);
+      if (unexpectedMessage != null) {
+        String expected = expectedValue?.toString() ?? '';
+        String actual = dataValidator.getText(actualValue);
+        int offset = getOffsetFromId(id, uri);
+        if (offset != null) {
+          String value1 = '${expected}';
+          String value2 = IdValue.idToString(id, '${actual}');
+          annotations
+              .putIfAbsent(offset, () => [])
+              .add(colorizeDiff(value1, ' | ', value2));
+        }
+      }
+    });
+    expectedMaps[uri].forEach((Id id, IdValue expected) {
+      if (!actualMaps[uri].containsKey(id)) {
+        int offset = getOffsetFromId(id, uri);
+        if (offset != null) {
+          String value1 = '${expected}';
+          String value2 = '---';
+          annotations
+              .putIfAbsent(offset, () => [])
+              .add(colorizeDiff(value1, ' | ', value2));
+        }
+      }
+    });
+    return withAnnotations(code[uri].sourceCode, annotations);
+  }
+
+  int getOffsetFromId(Id id, Uri uri) {
+    return _compiledData.getOffsetFromId(id, uri);
+  }
+}
+
+/// Checks [compiledData] against the expected data in [expectedMaps] derived
+/// from [code].
+Future<bool> checkCode<T>(
+    String modeName,
+    Uri mainFileUri,
+    Map<Uri, AnnotatedCode> code,
+    MemberAnnotations<IdValue> expectedMaps,
+    CompiledData<T> compiledData,
+    DataInterpreter<T> dataValidator,
+    {bool filterActualData(IdValue expected, ActualData<T> actualData),
+    bool fatalErrors: true,
+    bool succinct: false,
+    void onFailure(String message)}) async {
+  IdData<T> data = new IdData<T>(code, expectedMaps, compiledData);
+  bool hasFailure = false;
+  Set<Uri> neededDiffs = new Set<Uri>();
+
+  void checkActualMap(
+      Map<Id, ActualData<T>> actualMap, Map<Id, IdValue> expectedMap,
+      [Uri uri]) {
+    bool hasLocalFailure = false;
+    actualMap.forEach((Id id, ActualData<T> actualData) {
+      T actual = actualData.value;
+      String actualText = dataValidator.getText(actual);
+
+      if (!expectedMap.containsKey(id)) {
+        if (!dataValidator.isEmpty(actual)) {
+          String actualValueText = IdValue.idToString(id, actualText);
+          compiledData.reportError(
+              actualData.uri,
+              actualData.offset,
+              succinct
+                  ? 'EXTRA $modeName DATA for ${id.descriptor}'
+                  : 'EXTRA $modeName DATA for ${id.descriptor}:\n '
+                      'object   : ${actualData.objectText}\n '
+                      'actual   : ${colorizeActual(actualValueText)}\n '
+                      'Data was expected for these ids: ${expectedMap.keys}',
+              succinct: succinct);
+          if (filterActualData == null || filterActualData(null, actualData)) {
+            hasLocalFailure = true;
+          }
+        }
+      } else {
+        IdValue expected = expectedMap[id];
+        String unexpectedMessage =
+            dataValidator.isAsExpected(actual, expected.value);
+        if (unexpectedMessage != null) {
+          String actualValueText = IdValue.idToString(id, actualText);
+          compiledData.reportError(
+              actualData.uri,
+              actualData.offset,
+              succinct
+                  ? 'UNEXPECTED $modeName DATA for ${id.descriptor}'
+                  : 'UNEXPECTED $modeName DATA for ${id.descriptor}:\n '
+                      'detail  : ${colorizeMessage(unexpectedMessage)}\n '
+                      'object  : ${actualData.objectText}\n '
+                      'expected: ${colorizeExpected('$expected')}\n '
+                      'actual  : ${colorizeActual(actualValueText)}',
+              succinct: succinct);
+          if (filterActualData == null ||
+              filterActualData(expected, actualData)) {
+            hasLocalFailure = true;
+          }
+        }
+      }
+    });
+    if (hasLocalFailure) {
+      hasFailure = true;
+      if (uri != null) {
+        neededDiffs.add(uri);
+      }
+    }
+  }
+
+  data.actualMaps.forEach((Uri uri, Map<Id, ActualData<T>> actualMap) {
+    checkActualMap(actualMap, data.expectedMaps[uri], uri);
+  });
+  checkActualMap(data.actualMaps.globalData, data.expectedMaps.globalData);
+
+  Set<Id> missingIds = new Set<Id>();
+  void checkMissing(
+      Map<Id, IdValue> expectedMap, Map<Id, ActualData<T>> actualMap,
+      [Uri uri]) {
+    expectedMap.forEach((Id id, IdValue expected) {
+      if (!actualMap.containsKey(id)) {
+        missingIds.add(id);
+        String message = 'MISSING $modeName DATA for ${id.descriptor}: '
+            'Expected ${colorizeExpected('$expected')}';
+        if (uri != null) {
+          compiledData.reportError(
+              uri, compiledData.getOffsetFromId(id, uri), message,
+              succinct: succinct);
+        } else {
+          print(message);
+        }
+      }
+    });
+    if (missingIds.isNotEmpty && uri != null) {
+      neededDiffs.add(uri);
+    }
+  }
+
+  data.expectedMaps.forEach((Uri uri, Map<Id, IdValue> expectedMap) {
+    checkMissing(expectedMap, data.actualMaps[uri], uri);
+  });
+  checkMissing(data.expectedMaps.globalData, data.actualMaps.globalData);
+  if (!succinct) {
+    for (Uri uri in neededDiffs) {
+      print('--annotations diff [${uri.pathSegments.last}]-------------');
+      print(data.diffCode(uri, dataValidator));
+      print('----------------------------------------------------------');
+    }
+  }
+  if (missingIds.isNotEmpty) {
+    print("MISSING ids: ${missingIds}.");
+    hasFailure = true;
+  }
+  if (hasFailure && fatalErrors) {
+    onFailure('Errors found.');
+  }
+  return hasFailure;
+}
+
+typedef Future<bool> RunTestFunction(TestData testData,
+    {bool testAfterFailures, bool verbose, bool succinct, bool printCode});
+
+/// Check code for all tests in [dataDir] using [runTest].
+Future runTests(Directory dataDir,
+    {List<String> args: const <String>[],
+    int shards: 1,
+    int shardIndex: 0,
+    void onTest(Uri uri),
+    Iterable<String> supportedMarkers,
+    Uri createUriForFileName(String fileName),
+    void onFailure(String message),
+    RunTestFunction runTest,
+    List<String> skipList}) async {
+  // TODO(johnniwinther): Support --show to show actual data for an input.
+  args = args.toList();
+  bool verbose = args.remove('-v');
+  bool succinct = args.remove('-s');
+  bool shouldContinue = args.remove('-c');
+  bool testAfterFailures = args.remove('-a');
+  bool printCode = args.remove('-p');
+  bool continued = false;
+  bool hasFailures = false;
+
+  String relativeDir = dataDir.uri.path.replaceAll(Uri.base.path, '');
+  print('Data dir: ${relativeDir}');
+  List<FileSystemEntity> entities =
+      dataDir.listSync().where((entity) => !entity.path.endsWith('~')).toList();
+  if (shards > 1) {
+    int start = entities.length * shardIndex ~/ shards;
+    int end = entities.length * (shardIndex + 1) ~/ shards;
+    entities = entities.sublist(start, end);
+  }
+  int testCount = 0;
+  for (FileSystemEntity entity in entities) {
+    String name = entity.uri.pathSegments.last;
+    if (entity is Directory) {
+      name = entity.uri.pathSegments[entity.uri.pathSegments.length - 2];
+    }
+    if (args.isNotEmpty && !args.contains(name) && !continued) continue;
+    if (shouldContinue) continued = true;
+    testCount++;
+
+    if (skipList != null && skipList.contains(name) && !args.contains(name)) {
+      print('Skip: ${name}');
+      continue;
+    }
+    if (onTest != null) {
+      onTest(entity.uri);
+    }
+    print('----------------------------------------------------------------');
+
+    TestData testData = computeTestData(entity,
+        supportedMarkers: supportedMarkers,
+        createUriForFileName: createUriForFileName,
+        onFailure: onFailure);
+    print('Test: ${testData.testFileUri}');
+
+    if (await runTest(testData,
+        testAfterFailures: testAfterFailures,
+        verbose: verbose,
+        succinct: succinct,
+        printCode: printCode)) {
+      hasFailures = true;
+    }
+  }
+  if (hasFailures) {
+    onFailure('Errors found.');
+  }
+  if (testCount == 0) {
+    onFailure("No files were tested.");
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/colors.dart b/pkg/_fe_analyzer_shared/lib/src/util/colors.dart
new file mode 100644
index 0000000..f4f1b1b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/util/colors.dart
@@ -0,0 +1,200 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// TODO(ahe): Originally copied from sdk/pkg/compiler/lib/src/colors.dart,
+// merge these two packages.
+library colors;
+
+import 'dart:convert' show jsonEncode;
+
+import 'dart:io' show Platform, Process, ProcessResult, stderr, stdout;
+
+/// ANSI/xterm termcap for setting default colors. Output from Unix
+/// command-line program `tput op`.
+const String DEFAULT_COLOR = "\x1b[39;49m";
+
+/// ANSI/xterm termcap for setting black text color. Output from Unix
+/// command-line program `tput setaf 0`.
+const String BLACK_COLOR = "\x1b[30m";
+
+/// ANSI/xterm termcap for setting red text color. Output from Unix
+/// command-line program `tput setaf 1`.
+const String RED_COLOR = "\x1b[31m";
+
+/// ANSI/xterm termcap for setting green text color. Output from Unix
+/// command-line program `tput setaf 2`.
+const String GREEN_COLOR = "\x1b[32m";
+
+/// ANSI/xterm termcap for setting yellow text color. Output from Unix
+/// command-line program `tput setaf 3`.
+const String YELLOW_COLOR = "\x1b[33m";
+
+/// ANSI/xterm termcap for setting blue text color. Output from Unix
+/// command-line program `tput setaf 4`.
+const String BLUE_COLOR = "\x1b[34m";
+
+/// ANSI/xterm termcap for setting magenta text color. Output from Unix
+/// command-line program `tput setaf 5`.
+const String MAGENTA_COLOR = "\x1b[35m";
+
+/// ANSI/xterm termcap for setting cyan text color. Output from Unix
+/// command-line program `tput setaf 6`.
+const String CYAN_COLOR = "\x1b[36m";
+
+/// ANSI/xterm termcap for setting white text color. Output from Unix
+/// command-line program `tput setaf 7`.
+const String WHITE_COLOR = "\x1b[37m";
+
+/// All the above codes. This is used to compare the above codes to the
+/// terminal's. Printing this string should have the same effect as just
+/// printing [DEFAULT_COLOR].
+const String ALL_CODES = BLACK_COLOR +
+    RED_COLOR +
+    GREEN_COLOR +
+    YELLOW_COLOR +
+    BLUE_COLOR +
+    MAGENTA_COLOR +
+    CYAN_COLOR +
+    WHITE_COLOR +
+    DEFAULT_COLOR;
+
+const String TERMINAL_CAPABILITIES = """
+colors
+setaf 0
+setaf 1
+setaf 2
+setaf 3
+setaf 4
+setaf 5
+setaf 6
+setaf 7
+op
+""";
+
+/// 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;
+
+/// Finds out whether we are displaying ANSI colors.
+///
+/// The first time this getter is invoked (either by a client or by an attempt
+/// to use a color), it decides whether colors should be used based on the
+/// logic in [_computeEnableColors] (unless a value has previously been set).
+bool get enableColors => _enableColors ??= _computeEnableColors();
+
+/// Allows the client to override the decision of whether to disable ANSI
+/// colors.
+void set enableColors(bool value) {
+  assert(value != null);
+  _enableColors = value;
+}
+
+String wrap(String string, String color) {
+  return enableColors ? "${color}$string${DEFAULT_COLOR}" : string;
+}
+
+String black(String string) => wrap(string, BLACK_COLOR);
+String red(String string) => wrap(string, RED_COLOR);
+String green(String string) => wrap(string, GREEN_COLOR);
+String yellow(String string) => wrap(string, YELLOW_COLOR);
+String blue(String string) => wrap(string, BLUE_COLOR);
+String magenta(String string) => wrap(string, MAGENTA_COLOR);
+String cyan(String string) => wrap(string, CYAN_COLOR);
+String white(String string) => wrap(string, WHITE_COLOR);
+
+/// Returns whether [sink] supports ANSI escapes or `null` if it could not be
+/// determined.
+bool _supportsAnsiEscapes(sink) {
+  try {
+    // ignore: undefined_getter
+    return sink.supportsAnsiEscapes;
+  } on NoSuchMethodError {
+    // Ignored: We're running on an older version of the Dart VM which doesn't
+    // implement `supportsAnsiEscapes`.
+    return null;
+  }
+}
+
+/// Callback used by [_computeEnableColors] to report why it has or hasn't
+/// chosen to use ANSI colors.
+void Function(String) printEnableColorsReason = (_) {};
+
+/// True if we should enable colors in output.
+///
+/// We enable colors when both `stdout` and `stderr` support ANSI escapes.
+///
+/// On non-Windows platforms, this functions checks the terminal capabilities,
+/// on Windows we only enable colors if the VM getters are present and returned
+/// `true`.
+///
+/// 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);
+
+  if (stdoutSupportsColors == false) {
+    printEnableColorsReason(
+        "Not enabling colors, stdout does not support ANSI colors.");
+    return false;
+  }
+  if (stderrSupportsColors == false) {
+    printEnableColorsReason(
+        "Not enabling colors, stderr does not support ANSI colors.");
+    return false;
+  }
+
+  if (Platform.isWindows) {
+    if (stderrSupportsColors != true || stdoutSupportsColors != true) {
+      // In this case, either [stdout] or [stderr] did not support the
+      // property `supportsAnsiEscapes`. Since we do not have another way
+      // to determine support for colors, we disable them.
+      printEnableColorsReason("Not enabling colors as ANSI is not supported.");
+      return false;
+    }
+    printEnableColorsReason("Enabling colors as OS is Windows.");
+    return true;
+  }
+
+  // We have to check if the terminal actually supports colors. Currently,
+  // to avoid linking the Dart VM with ncurses, ANSI escape support is reduced
+  // to `Platform.environment['TERM'].contains("xterm")`.
+
+  // The `-S` option of `tput` allows us to query multiple capabilities at
+  // once.
+  ProcessResult result = Process.runSync(
+      "/bin/sh", ["-c", "printf '%s' '$TERMINAL_CAPABILITIES' | tput -S"]);
+
+  if (result.exitCode != 0) {
+    printEnableColorsReason("Not enabling colors, running tput failed.");
+    return false;
+  }
+
+  List<String> lines = result.stdout.split("\n");
+
+  if (lines.length != 2) {
+    printEnableColorsReason("Not enabling colors, unexpected output from tput: "
+        "${jsonEncode(result.stdout)}.");
+    return false;
+  }
+
+  String numberOfColors = lines[0];
+  if ((int.tryParse(numberOfColors) ?? -1) < 8) {
+    printEnableColorsReason(
+        "Not enabling colors, less than 8 colors supported: "
+        "${jsonEncode(numberOfColors)}.");
+    return false;
+  }
+
+  String allCodes = lines[1].trim();
+  if (ALL_CODES != allCodes) {
+    printEnableColorsReason("Not enabling colors, color codes don't match: "
+        "${jsonEncode(ALL_CODES)} != ${jsonEncode(allCodes)}.");
+    return false;
+  }
+
+  printEnableColorsReason("Enabling colors.");
+  return true;
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/link.dart b/pkg/_fe_analyzer_shared/lib/src/util/link.dart
new file mode 100644
index 0000000..8cb8dd0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/util/link.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.util.link;
+
+import 'link_implementation.dart'
+    show LinkBuilderImplementation, LinkEntry, LinkIterator, MappedLinkIterable;
+
+class Link<T> implements Iterable<T> {
+  T get head => throw new StateError("no elements");
+  Link<T> get tail => null;
+
+  const Link();
+
+  Link<T> prepend(T element) {
+    return new LinkEntry<T>(element, this);
+  }
+
+  Iterator<T> get iterator => new LinkIterator<T>(this);
+
+  void printOn(StringBuffer buffer, [separatedBy]) {}
+
+  List<T> toList({bool growable: true}) {
+    List<T> result;
+    if (!growable) {
+      result = new List<T>(slowLength());
+    } else {
+      result = new List<T>();
+      result.length = slowLength();
+    }
+    int i = 0;
+    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+      result[i++] = link.head;
+    }
+    return result;
+  }
+
+  /// Lazily maps over this linked list, returning an [Iterable].
+  Iterable<K> map<K>(K fn(T item)) {
+    return new MappedLinkIterable<T, K>(this, fn);
+  }
+
+  /// 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;
+    if (!growable) {
+      result = new List<E>(slowLength());
+    } else {
+      result = new List<E>();
+      result.length = slowLength();
+    }
+    int i = 0;
+    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+      result[i++] = fn(link.head);
+    }
+    return result;
+  }
+
+  bool get isEmpty => true;
+  bool get isNotEmpty => false;
+
+  Link<T> reverse(Link<T> tail) => this;
+
+  Link<T> reversePrependAll(Link<T> from) {
+    if (from.isEmpty) return this;
+    return this.prepend(from.head).reversePrependAll(from.tail);
+  }
+
+  Link<T> skip(int n) {
+    if (n == 0) return this;
+    throw new RangeError('Index $n out of range');
+  }
+
+  void forEach(void f(T element)) {}
+
+  bool operator ==(other) {
+    if (other is! Link<T>) return false;
+    return other.isEmpty;
+  }
+
+  int get hashCode => throw new UnsupportedError('Link.hashCode');
+
+  String toString() => "[]";
+
+  get length {
+    throw new UnsupportedError('get:length');
+  }
+
+  int slowLength() => 0;
+
+  // TODO(ahe): Remove this method?
+  bool contains(Object element) {
+    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+      if (link.head == element) return true;
+    }
+    return false;
+  }
+
+  // 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');
+    return head;
+  }
+
+  // TODO(ahe): Remove this method?
+  T get first {
+    if (isEmpty) throw new StateError('No elements');
+    return head;
+  }
+
+  /// Returns true if f returns true for all elements of this list.
+  ///
+  /// Returns true for the empty list.
+  bool every(bool f(T e)) {
+    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
+      if (!f(link.head)) return false;
+    }
+    return true;
+  }
+
+  //
+  // Unsupported Iterable<T> methods.
+  //
+  bool any(bool f(T e)) => _unsupported('any');
+  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');
+  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');
+  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');
+  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');
+  Set<T> toSet() => _unsupported('toSet');
+  Iterable<T> whereType<T>() => _unsupported('whereType');
+  Iterable<T> where(bool f(T e)) => _unsupported('where');
+
+  _unsupported(String method) => throw new UnsupportedError(method);
+}
+
+/// Builder object for creating linked lists using [Link] or fixed-length [List]
+/// objects.
+abstract class LinkBuilder<T> {
+  factory LinkBuilder() = LinkBuilderImplementation<T>;
+
+  /// Prepends all elements added to the builder to [tail]. The resulting list
+  /// is returned and the builder is cleared.
+  Link<T> toLink(Link<T> tail);
+
+  /// Creates a new fixed length containing all added elements. The
+  /// resulting list is returned and the builder is cleared.
+  List<T> toList();
+
+  /// Adds the element [t] to the end of the list being built.
+  Link<T> addLast(T t);
+
+  /// Returns the first element in the list being built.
+  T get first;
+
+  /// Returns the number of elements in the list being built.
+  final int length;
+
+  /// Returns `true` if the list being built is empty.
+  final bool 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
new file mode 100644
index 0000000..e9d97ec
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/util/link_implementation.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
+// for 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 _fe_analyzer_shared.util.link_implementation;
+
+import 'dart:collection' show IterableBase;
+
+import 'link.dart' show Link, LinkBuilder;
+
+class LinkIterator<T> implements Iterator<T> {
+  T _current;
+  Link<T> _link;
+
+  LinkIterator(this._link);
+
+  T get current => _current;
+
+  bool moveNext() {
+    if (_link.isEmpty) {
+      _current = null;
+      return false;
+    }
+    _current = _link.head;
+    _link = _link.tail;
+    return true;
+  }
+}
+
+typedef T Transformation<S, T>(S input);
+
+class MappedLinkIterator<S, T> extends Iterator<T> {
+  Transformation<S, T> _transformation;
+  Link<S> _link;
+  T _current;
+
+  MappedLinkIterator(this._link, this._transformation);
+
+  T get current => _current;
+
+  bool moveNext() {
+    if (_link.isEmpty) {
+      _current = null;
+      return false;
+    }
+    _current = _transformation(_link.head);
+    _link = _link.tail;
+    return true;
+  }
+}
+
+class MappedLinkIterable<S, T> extends IterableBase<T> {
+  Transformation<S, T> _transformation;
+  Link<S> _link;
+
+  MappedLinkIterable(this._link, this._transformation);
+
+  Iterator<T> get iterator {
+    return new MappedLinkIterator<S, T>(_link, _transformation);
+  }
+}
+
+class LinkEntry<T> extends Link<T> {
+  final T head;
+  Link<T> tail;
+
+  LinkEntry(this.head, [Link<T> tail]) : tail = tail ?? const Link<Null>();
+
+  Link<T> prepend(T element) {
+    // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
+    return new LinkEntry<T>(element, this);
+  }
+
+  void printOn(StringBuffer buffer, [separatedBy]) {
+    buffer.write(head);
+    if (separatedBy == null) separatedBy = '';
+    for (Link<T> link = tail; link.isNotEmpty; link = link.tail) {
+      buffer.write(separatedBy);
+      buffer.write(link.head);
+    }
+  }
+
+  String toString() {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write('[ ');
+    printOn(buffer, ', ');
+    buffer.write(' ]');
+    return buffer.toString();
+  }
+
+  @override
+  Link<T> reverse(Link<T> tail) {
+    Link<T> result = tail;
+    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
+      result = result.prepend(link.head);
+    }
+    return result;
+  }
+
+  Link<T> reversePrependAll(Link<T> from) {
+    Link<T> result;
+    for (result = this; from.isNotEmpty; from = from.tail) {
+      result = result.prepend(from.head);
+    }
+    return result;
+  }
+
+  Link<T> skip(int n) {
+    Link<T> link = this;
+    for (int i = 0; i < n; i++) {
+      if (link.isEmpty) {
+        throw new RangeError('Index $n out of range');
+      }
+      link = link.tail;
+    }
+    return link;
+  }
+
+  bool get isEmpty => false;
+  bool get isNotEmpty => true;
+
+  void forEach(void f(T element)) {
+    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
+      f(link.head);
+    }
+  }
+
+  bool operator ==(other) {
+    if (other is! Link<T>) return false;
+    Link<T> myElements = this;
+    while (myElements.isNotEmpty && other.isNotEmpty) {
+      if (myElements.head != other.head) {
+        return false;
+      }
+      myElements = myElements.tail;
+      other = other.tail;
+    }
+    return myElements.isEmpty && other.isEmpty;
+  }
+
+  int get hashCode => throw new UnsupportedError('LinkEntry.hashCode');
+
+  int slowLength() {
+    int length = 0;
+    for (Link<T> current = this; current.isNotEmpty; current = current.tail) {
+      ++length;
+    }
+    return length;
+  }
+}
+
+class LinkBuilderImplementation<T> implements LinkBuilder<T> {
+  LinkEntry<T> head = null;
+  LinkEntry<T> lastLink = null;
+  int length = 0;
+
+  LinkBuilderImplementation();
+
+  @override
+  Link<T> toLink(Link<T> tail) {
+    if (head == null) return tail;
+    lastLink.tail = tail;
+    Link<T> link = head;
+    lastLink = null;
+    head = null;
+    length = 0;
+    return link;
+  }
+
+  List<T> toList() {
+    if (length == 0) return new List<T>(0);
+    List<T> list = new List<T>(length);
+    int index = 0;
+    Link<T> link = head;
+    while (link.isNotEmpty) {
+      list[index] = link.head;
+      link = link.tail;
+      index++;
+    }
+    lastLink = null;
+    head = null;
+    length = 0;
+    return list;
+  }
+
+  Link<T> addLast(T t) {
+    length++;
+    LinkEntry<T> entry = new LinkEntry<T>(t, null);
+    if (head == null) {
+      head = entry;
+    } else {
+      lastLink.tail = entry;
+    }
+    lastLink = entry;
+    return entry;
+  }
+
+  bool get isEmpty => length == 0;
+
+  T get first {
+    if (head != null) {
+      return head.head;
+    }
+    throw new StateError("no elements");
+  }
+
+  void clear() {
+    head = null;
+    lastLink = null;
+    length = 0;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/lib/src/util/relativize.dart b/pkg/_fe_analyzer_shared/lib/src/util/relativize.dart
new file mode 100644
index 0000000..0ecd442
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/lib/src/util/relativize.dart
@@ -0,0 +1,77 @@
+// 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.
+
+library _fe_analyzer_shared.util.relativize;
+
+import 'dart:math';
+
+/// Detect if we're on Windows without importing `dart:io`.
+bool isWindows = new Uri.directory("C:\\").path ==
+    new Uri.directory("C:\\", windows: true).path;
+
+String relativizeUri(Uri base, Uri uri, bool isWindows) {
+  bool equalsNCS(String a, String b) {
+    return a.toLowerCase() == b.toLowerCase();
+  }
+
+  if (!equalsNCS(base.scheme, uri.scheme) ||
+      equalsNCS(base.scheme, 'dart') ||
+      equalsNCS(base.scheme, 'package')) {
+    return uri.toString();
+  }
+
+  if (!equalsNCS(base.scheme, 'file')) {
+    isWindows = false;
+  }
+
+  String normalize(String path) {
+    if (isWindows) {
+      return path.toLowerCase();
+    } else {
+      return path;
+    }
+  }
+
+  if (base.userInfo == uri.userInfo &&
+      equalsNCS(base.host, uri.host) &&
+      base.port == uri.port &&
+      uri.query == "" &&
+      uri.fragment == "") {
+    if (normalize(uri.path).startsWith(normalize(base.path))) {
+      return uri.path.substring(base.path.lastIndexOf('/') + 1);
+    }
+
+    if (!base.path.startsWith('/') || !uri.path.startsWith('/')) {
+      return uri.toString();
+    }
+
+    List<String> uriParts = uri.path.split('/');
+    List<String> baseParts = base.path.split('/');
+    int common = 0;
+    int length = min(uriParts.length, baseParts.length);
+    while (common < length &&
+        normalize(uriParts[common]) == normalize(baseParts[common])) {
+      common++;
+    }
+    if (common == 1 || (isWindows && common == 2)) {
+      // The first part will always be an empty string because the
+      // paths are absolute. On Windows, we must also consider drive
+      // letters or hostnames.
+      if (baseParts.length > common + 1) {
+        // Avoid using '..' to go to the root, unless we are already there.
+        return uri.path;
+      }
+    }
+    StringBuffer sb = new StringBuffer();
+    for (int i = common + 1; i < baseParts.length; i++) {
+      sb.write('../');
+    }
+    for (int i = common; i < uriParts.length - 1; i++) {
+      sb.write('${uriParts[i]}/');
+    }
+    sb.write('${uriParts.last}');
+    return sb.toString();
+  }
+  return uri.toString();
+}
diff --git a/pkg/front_end/lib/src/base/resolve_relative_uri.dart b/pkg/_fe_analyzer_shared/lib/src/util/resolve_relative_uri.dart
similarity index 100%
rename from pkg/front_end/lib/src/base/resolve_relative_uri.dart
rename to pkg/_fe_analyzer_shared/lib/src/util/resolve_relative_uri.dart
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
new file mode 100644
index 0000000..8845901
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -0,0 +1,12 @@
+name: _fe_analyzer_shared
+version: 1.0.0
+author: Dart Team <misc@dartlang.org>
+description: Logic that is shared between the front_end and analyzer packages.
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
+
+environment:
+  sdk: '>=2.2.2 <3.0.0'
+dependencies:
+  meta: ^1.0.2
+dev_dependencies:
+  test: ^1.3.4
diff --git a/pkg/front_end/test/constants/data/basic.dart b/pkg/_fe_analyzer_shared/test/constants/data/basic.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/basic.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/basic.dart
diff --git a/pkg/front_end/test/constants/data/errors.dart b/pkg/_fe_analyzer_shared/test/constants/data/errors.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/errors.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/errors.dart
diff --git a/pkg/front_end/test/constants/data/function.dart b/pkg/_fe_analyzer_shared/test/constants/data/function.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/function.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/function.dart
diff --git a/pkg/front_end/test/constants/data/list.dart b/pkg/_fe_analyzer_shared/test/constants/data/list.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/list.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/list.dart
diff --git a/pkg/front_end/test/constants/data/map.dart b/pkg/_fe_analyzer_shared/test/constants/data/map.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/map.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/map.dart
diff --git a/pkg/front_end/test/constants/data/set.dart b/pkg/_fe_analyzer_shared/test/constants/data/set.dart
similarity index 100%
rename from pkg/front_end/test/constants/data/set.dart
rename to pkg/_fe_analyzer_shared/test/constants/data/set.dart
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
new file mode 100644
index 0000000..08d699d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/assignment.dart
@@ -0,0 +1,18 @@
+// 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.
+
+/*member: ordinary:declared={x, y}, assigned={x}*/
+ordinary(int x, int y) {
+  x = y;
+}
+
+/*member: nullAware:declared={x, y}, assigned={x}*/
+nullAware(int? x, int y) {
+  x ??= y;
+}
+
+/*member: compound:declared={x, y}, assigned={x}*/
+compound(int x, int y) {
+  x += y;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/closure.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/closure.dart
new file mode 100644
index 0000000..b4daa9c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/closure.dart
@@ -0,0 +1,34 @@
+// 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.
+
+/*member: singleNesting:declared={a, b, c, fn}, assigned={a, b, c, d}, captured={b}*/
+singleNesting(int a, int b, int c) {
+  a = 0;
+  // Note: for a closure, "assigned" and "captured" are restricted to
+  // variables declared in enclosing contexts, so d is not included.
+  var fn = /*declared={d, e}, assigned={b}*/ (int d, int e) {
+    b = 0;
+    d = 0;
+  };
+  c = 0;
+}
+
+/*member: doubleNesting:declared={a, b, c, fn1}, assigned={a, b, c, d, e, f}, captured={b, c, e}*/
+doubleNesting(int a, int b, int c) {
+  a = 0;
+  // Note: for a closure, "assigned" and "captured" are restricted to
+  // variables declared in enclosing contexts, so d, e, and f are not
+  // included.
+  var fn1 = /*declared={d, e, fn2}, assigned={b, c}, captured={c}*/ (int d,
+      int e) {
+    b = 0;
+    d = 0;
+    // Similarly, f is not included in "assigned" here.
+    var fn2 = /*declared={f}, assigned={c, e}*/ (int f) {
+      c = 0;
+      e = 0;
+      f = 0;
+    };
+  };
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart
new file mode 100644
index 0000000..5dd4825
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/constructor.dart
@@ -0,0 +1,10 @@
+// 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.
+
+class C {
+  /*member: C.constructor:declared={a, b}, assigned={a}*/
+  C.constructor(int a, int b) {
+    a = 0;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/do.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/do.dart
new file mode 100644
index 0000000..7c83e44
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/do.dart
@@ -0,0 +1,10 @@
+// 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.
+
+/*member: doStatement:declared={a, b}, assigned={a, b}*/
+doStatement(int a, int b) {
+  /*assigned={a, b}*/ do {
+    a = 0;
+  } while ((b = 0) != 0);
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/field.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/field.dart
new file mode 100644
index 0000000..70280fe
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/field.dart
@@ -0,0 +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.
+
+class C {
+  dynamic /*member: C.x:assigned={a}*/ x = /*declared={a, b}*/ (int a, int b) {
+    a = 0;
+  };
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart
new file mode 100644
index 0000000..35a845a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart
@@ -0,0 +1,31 @@
+// 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.
+
+/*member: cStyle:declared={a, b, c, d}, assigned={a, b, c, d}*/
+cStyle(int a, int b, int c, int d) {
+  /*assigned={b, c, d}*/ for (a = 0; (b = 0) != 0; c = 0) {
+    d = 0;
+  }
+}
+
+/*member: cStyleWithDeclaration:declared={a, b, c, d, e}, assigned={a, b, c, d}*/
+cStyleWithDeclaration(int a, int b, int c, int d) {
+  /*assigned={b, c, d}*/ for (int e = (a = 0); (b = 0) != 0; c = 0) {
+    d = 0;
+  }
+}
+
+/*member: forEach:declared={a, b, c}, assigned={a, b, c}*/
+forEach(int a, int b, int c) {
+  /*assigned={c}*/ for (a in [b = 0]) {
+    c = 0;
+  }
+}
+
+/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b, c}*/
+forEachWithDeclaration(int a, int b) {
+  /*assigned={b}*/ for (var c in [a = 0]) {
+    b = 0;
+  }
+}
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
new file mode 100644
index 0000000..86b2e15
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
@@ -0,0 +1,27 @@
+// 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.
+
+/*member: cStyle:declared={a, b, c, d}, assigned={a, b, c, d}*/
+cStyle(int a, int b, int c, int d) {
+  [/*assigned={b, c, d}*/ for (a = 0; (b = 0) != 0; c = 0) (d = 0)];
+}
+
+/*member: cStyleWithDeclaration:declared={a, b, c, d, e}, assigned={a, b, c, d}*/
+cStyleWithDeclaration(int a, int b, int c, int d) {
+  [/*assigned={b, c, d}*/ for (int e = (a = 0); (b = 0) != 0; c = 0) (d = 0)];
+}
+
+/*member: forEach:declared={a, b, c}, assigned={a, b, c}*/
+forEach(int a, int b, int c) {
+  [
+    /*assigned={c}*/ for (a in [b = 0]) (c = 0)
+  ];
+}
+
+/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b, c}*/
+forEachWithDeclaration(int a, int b) {
+  [
+    /*assigned={b}*/ for (var c in [a = 0]) (b = 0)
+  ];
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/localFunction.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/localFunction.dart
new file mode 100644
index 0000000..e6be1bd
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/localFunction.dart
@@ -0,0 +1,35 @@
+// 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.
+
+/*member: singleNesting:declared={a, b, c}, assigned={a, b, c, d}, captured={b}*/
+singleNesting(int a, int b, int c) {
+  a = 0;
+  // Note: for a local function, "assigned" and "captured" are
+  // restricted to variables declared in enclosing contexts, so d is
+  // not included.
+  /*declared={d, e}, assigned={b}*/ fn(int d, int e) {
+    b = 0;
+    d = 0;
+  }
+
+  c = 0;
+}
+
+/*member: doubleNesting:declared={a, b, c}, assigned={a, b, c, d, e, f}, captured={b, c, e}*/
+doubleNesting(int a, int b, int c) {
+  a = 0;
+  // Note: for a local function, "assigned" and "captured" are
+  // restricted to variables declared in enclosing contexts, so d, e,
+  // and f are not included.
+  /*declared={d, e}, assigned={b, c}, captured={c}*/ fn1(int d, int e) {
+    b = 0;
+    d = 0;
+    // Similarly, f is not included in "assigned" here.
+    /*declared={f}, assigned={c, e}*/ fn2(int f) {
+      c = 0;
+      e = 0;
+      f = 0;
+    }
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/method.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/method.dart
new file mode 100644
index 0000000..39ba409
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/method.dart
@@ -0,0 +1,10 @@
+// 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.
+
+class C {
+  /*member: C.method:declared={a, b}, assigned={a}*/
+  C.method(int a, int b) {
+    a = 0;
+  }
+}
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
new file mode 100644
index 0000000..8f91e74
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/postfix.dart
@@ -0,0 +1,18 @@
+// 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.
+
+/*member: increment:declared={x}, assigned={x}*/
+increment(int x) {
+  x++;
+}
+
+/*member: decrement:declared={x}, assigned={x}*/
+decrement(int x) {
+  x--;
+}
+
+/*member: nonNullAssert:declared={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
new file mode 100644
index 0000000..445015c
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/prefix.dart
@@ -0,0 +1,28 @@
+// 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.
+
+/*member: increment:declared={x}, assigned={x}*/
+increment(int x) {
+  ++x;
+}
+
+/*member: decrement:declared={x}, assigned={x}*/
+decrement(int x) {
+  --x;
+}
+
+/*member: not:declared={b}*/
+not(bool b) {
+  !b;
+}
+
+/*member: binaryNot:declared={x}*/
+binaryNot(int x) {
+  ~x;
+}
+
+/*member: unaryMinus:declared={x}*/
+unaryMinus(int x) {
+  -x;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/switch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/switch.dart
new file mode 100644
index 0000000..6516d0f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/switch.dart
@@ -0,0 +1,15 @@
+// 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.
+
+/*member: switchStatement:declared={a, b, c}, assigned={a, b, c}*/
+switchStatement(int a, int b, int c) {
+  /*assigned={b, c}*/ switch (a = 0) {
+    case 1:
+      b = 0;
+      break;
+    default:
+      c = 0;
+      break;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelFunction.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelFunction.dart
new file mode 100644
index 0000000..2155ec3
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelFunction.dart
@@ -0,0 +1,8 @@
+// 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.
+
+/*member: f:declared={a, b}, assigned={a}*/
+f(int a, int b) {
+  a = 0;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart
new file mode 100644
index 0000000..b2b8e7d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/topLevelVariable.dart
@@ -0,0 +1,7 @@
+// 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.
+
+dynamic /*member: x:assigned={a}*/ x = /*declared={a, b}*/ (int a, int b) {
+  a = 0;
+};
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryCatch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryCatch.dart
new file mode 100644
index 0000000..89872d4
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryCatch.dart
@@ -0,0 +1,63 @@
+// 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.
+
+/*member: tryCatch:declared={a, b, d}, assigned={a, b}*/
+tryCatch(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } on String {
+    // Note: flow analysis doesn't need to track variables assigned, captured,
+    // or declared inside of catch blocks.  So we don't create an
+    // AssignedVariables node for this catch block, and consequently the
+    // assignment to `b` and declaration of `d` are considered to belong to the
+    // enclosing function.
+    b = 0;
+    var d;
+  }
+}
+
+/*member: catchClause:declared={a, b, d, e}, assigned={a, b}*/
+catchClause(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } catch (e) {
+    b = 0;
+    var d;
+  }
+}
+
+/*member: onCatch:declared={a, b, d, e}, assigned={a, b}*/
+onCatch(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } on String catch (e) {
+    b = 0;
+    var d;
+  }
+}
+
+/*member: catchStackTrace:declared={a, b, d, e, st}, assigned={a, b}*/
+catchStackTrace(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } catch (e, st) {
+    b = 0;
+    var d;
+  }
+}
+
+/*member: onCatchStackTrace:declared={a, b, d, e, st}, assigned={a, b}*/
+onCatchStackTrace(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } on String catch (e, st) {
+    b = 0;
+    var d;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryFinally.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryFinally.dart
new file mode 100644
index 0000000..43f49dc
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/tryFinally.dart
@@ -0,0 +1,33 @@
+// 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.
+
+/*member: tryFinally:declared={a, b}, assigned={a, b}*/
+tryFinally(int a, int b) {
+  try /*declared={c}, assigned={a}*/ {
+    a = 0;
+    var c;
+  } finally /*declared={d}, assigned={b}*/ {
+    b = 0;
+    var d;
+  }
+}
+
+/*analyzer.member: tryCatchFinally:declared={a, b, c}, assigned={a, b, c}*/
+/*cfe.member: tryCatchFinally:declared={a, b, c, e}, assigned={a, b, c}*/
+tryCatchFinally(int a, int b, int c) {
+  // Note: try/catch/finally is desugared into try/catch nested inside
+  // try/finally.  The comment preceding the "try" refers to the outer
+  // "try" block of the desugaring, and the comment after the "try"
+  // refers to the inner "try" block of the desugaring.
+  /*analyzer.declared={e}, assigned={a, b}*/ try /*declared={d}, assigned={a}*/ {
+    a = 0;
+    var d;
+  } on String {
+    b = 0;
+    var e;
+  } finally /*declared={f}, assigned={c}*/ {
+    c = 0;
+    var f;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/while.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/while.dart
new file mode 100644
index 0000000..88fd90b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/while.dart
@@ -0,0 +1,10 @@
+// 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.
+
+/*member: whileLoop:declared={a, b}, assigned={a, b}*/
+whileLoop(int a, int b) {
+  /*assigned={a, b}*/ while ((a = 0) != 0) {
+    b = 0;
+  }
+}
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
new file mode 100644
index 0000000..f17b730
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
@@ -0,0 +1,280 @@
+// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:test/test.dart';
+
+main() {
+  test('capturedAnywhere records assignments 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.write(v1);
+    assignedVariables.beginNode();
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.write(v3);
+    assignedVariables.finish();
+    expect(assignedVariables.capturedAnywhere, {v2});
+  });
+
+  test('capturedAnywhere 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.write(v1);
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.finish();
+    expect(assignedVariables.capturedAnywhere, {v1});
+  });
+
+  test('writtenAnywhere records all assignments', () {
+    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.write(v1);
+    assignedVariables.beginNode();
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.write(v3);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenAnywhere, {v1, v2, v3});
+  });
+
+  test('writtenInNode ignores assignments outside the node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.write(v1);
+    assignedVariables.beginNode();
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.write(v2);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenInNode(node), isEmpty);
+  });
+
+  test('writtenInNode records assignments inside the node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.write(v1);
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenInNode(node), {v1});
+  });
+
+  test('writtenInNode records assignments in a nested node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.write(v1);
+    assignedVariables.endNode(_Node());
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenInNode(node), {v1});
+  });
+
+  test('writtenInNode records assignments in a closure', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.write(v1);
+    var node = _Node();
+    assignedVariables.endNode(node, isClosure: true);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenInNode(node), {v1});
+  });
+
+  test('capturedInNode ignores assignments 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.write(v1);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.beginNode();
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.beginNode();
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.finish();
+    expect(assignedVariables.capturedInNode(node), isEmpty);
+  });
+
+  test('capturedInNode records assignments in nested closures', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    assignedVariables.declare(v1);
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.write(v1);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    var node = _Node();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.capturedInNode(node), {v1});
+  });
+
+  group('Variables do not percolate beyond the scope they were declared in',
+      () {
+    test('Non-closure scope', () {
+      var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+      var v1 = _Variable('v1');
+      var v2 = _Variable('v2');
+      assignedVariables.beginNode();
+      assignedVariables.beginNode();
+      assignedVariables.declare(v1);
+      assignedVariables.declare(v2);
+      assignedVariables.write(v1);
+      assignedVariables.beginNode();
+      assignedVariables.write(v2);
+      assignedVariables.endNode(_Node(), isClosure: true);
+      var innerNode = _Node();
+      assignedVariables.endNode(innerNode, isClosure: false);
+      var outerNode = _Node();
+      assignedVariables.endNode(outerNode);
+      assignedVariables.finish();
+      expect(assignedVariables.writtenInNode(innerNode), isEmpty);
+      expect(assignedVariables.capturedInNode(innerNode), isEmpty);
+      expect(assignedVariables.writtenInNode(outerNode), isEmpty);
+      expect(assignedVariables.capturedInNode(outerNode), isEmpty);
+    });
+
+    test('Closure scope', () {
+      var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+      var v1 = _Variable('v1');
+      var v2 = _Variable('v2');
+      assignedVariables.beginNode();
+      assignedVariables.beginNode();
+      assignedVariables.declare(v1);
+      assignedVariables.declare(v2);
+      assignedVariables.write(v1);
+      assignedVariables.beginNode();
+      assignedVariables.write(v2);
+      assignedVariables.endNode(_Node(), isClosure: true);
+      var innerNode = _Node();
+      assignedVariables.endNode(innerNode, isClosure: true);
+      var outerNode = _Node();
+      assignedVariables.endNode(outerNode);
+      assignedVariables.finish();
+      expect(assignedVariables.writtenInNode(innerNode), isEmpty);
+      expect(assignedVariables.capturedInNode(innerNode), isEmpty);
+      expect(assignedVariables.writtenInNode(outerNode), isEmpty);
+      expect(assignedVariables.capturedInNode(outerNode), isEmpty);
+    });
+  });
+
+  test('discardNode percolates declarations to enclosing node', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var node = _Node();
+    assignedVariables.beginNode();
+    assignedVariables.beginNode();
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.discardNode();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.declaredInNode(node), unorderedEquals([v1, v2]));
+  });
+
+  test('discardNode percolates writes 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.write(v1);
+    assignedVariables.write(v2);
+    assignedVariables.discardNode();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.writtenInNode(node), unorderedEquals([v1, v2]));
+  });
+
+  test('discardNode percolates 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.write(v1);
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.discardNode();
+    assignedVariables.endNode(node);
+    assignedVariables.finish();
+    expect(assignedVariables.capturedInNode(node), unorderedEquals([v1, v2]));
+  });
+
+  test('deferNode allows deferring of node info', () {
+    var assignedVariables = AssignedVariablesForTesting<_Node, _Variable>();
+    var v1 = _Variable('v1');
+    var v2 = _Variable('v2');
+    var v3 = _Variable('v3');
+    var v4 = _Variable('v4');
+    assignedVariables.declare(v1);
+    assignedVariables.declare(v2);
+    assignedVariables.declare(v4);
+    assignedVariables.beginNode();
+    assignedVariables.write(v1);
+    assignedVariables.declare(v3);
+    assignedVariables.beginNode();
+    assignedVariables.write(v2);
+    assignedVariables.endNode(_Node(), isClosure: true);
+    var info = assignedVariables.deferNode();
+    assignedVariables.beginNode();
+    assignedVariables.write(v4);
+    assignedVariables.endNode(_Node());
+    var node = _Node();
+    assignedVariables.storeInfo(node, info);
+    assignedVariables.finish();
+    expect(assignedVariables.declaredInNode(node), [v3]);
+    expect(assignedVariables.writtenInNode(node), unorderedEquals([v1, v2]));
+    expect(assignedVariables.capturedInNode(node), [v2]);
+  });
+}
+
+class _Node {}
+
+class _Variable {
+  final String name;
+
+  _Variable(this.name);
+
+  @override
+  String toString() => name;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assert.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assert.dart
new file mode 100644
index 0000000..45ebd89
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assert.dart
@@ -0,0 +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.
+
+assertStatement() {
+  late int v;
+  assert((v = 0) >= 0, v);
+  /*unassigned*/ v;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
new file mode 100644
index 0000000..39006b3
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/assignment.dart
@@ -0,0 +1,46 @@
+// 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.
+
+leftExpression() {
+  late List<int> v;
+  /*unassigned*/ v[0] = (v = [1, 2])[1];
+  v;
+}
+
+leftLocal_compound() {
+  late int v;
+  /*unassigned*/ v += 1;
+}
+
+leftLocal_compound_assignInRight() {
+  late int v;
+  /*unassigned*/ v += (v = /*unassigned*/ v);
+}
+
+leftLocal_pure_eq() {
+  late int v;
+  v = 0;
+}
+
+leftLocal_pure_eq_self() {
+  late int v;
+  v = /*unassigned*/ v;
+}
+
+leftLocal_pure_questionEq() {
+  late int v;
+  /*unassigned*/ v ??= 0;
+}
+
+leftLocal_pure_questionEq_self() {
+  late int v;
+  /*unassigned*/ v ??= /*unassigned*/ v;
+}
+
+questionEq_rhs_not_guaranteed_to_execute() {
+  late int v;
+  int? i;
+  i ??= (v = 0);
+  /*unassigned*/ v;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/binary_expression.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/binary_expression.dart
new file mode 100644
index 0000000..8ec202a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/binary_expression.dart
@@ -0,0 +1,51 @@
+// 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.
+
+ifNull_left() {
+  late int v;
+  (v = 0) ?? 0;
+  v;
+}
+
+ifNull_right(int a) {
+  late int v;
+  a ?? (v = 0);
+  /*unassigned*/ v;
+}
+
+logicalAnd_left(bool c) {
+  late int v;
+  ((v = 0) >= 0) && c;
+  v;
+}
+
+logicalAnd_right(bool c) {
+  late int v;
+  c && ((v = 0) >= 0);
+  /*unassigned*/ v;
+}
+
+logicalOr_left(bool c) {
+  late int v;
+  ((v = 0) >= 0) || c;
+  v;
+}
+
+logicalOr_right(bool c) {
+  late int v;
+  c || ((v = 0) >= 0);
+  /*unassigned*/ v;
+}
+
+plus_left() {
+  late int v;
+  (v = 0) + 1;
+  v;
+}
+
+plus_right() {
+  late int v;
+  1 + (v = 0);
+  v;
+}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/conditional_expression.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/conditional_expression.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/definite_assignment/data/conditional_expression.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/conditional_expression.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/do.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/do.dart
new file mode 100644
index 0000000..25c11ca
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/do.dart
@@ -0,0 +1,95 @@
+// 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.
+
+break_afterAssignment(bool c) {
+  late int v;
+  do {
+    v = 0;
+    v;
+    if (c) break;
+  } while (c);
+  v;
+}
+
+break_beforeAssignment(bool c) {
+  late int v;
+  do {
+    if (c) break;
+    v = 0;
+  } while (c);
+  /*unassigned*/ v;
+}
+
+breakOuterFromInner(bool c) {
+  late int v1, v2, v3;
+  L1:
+  do {
+    do {
+      v1 = 0;
+      if (c) break L1;
+      v2 = 0;
+      v3 = 0;
+    } while (c);
+    v2;
+  } while (c);
+  v1;
+  /*unassigned*/ v3;
+}
+
+condition() {
+  late int v1, v2;
+  do {
+    /*unassigned*/ v1; // assigned in the condition, but not yet
+  } while ((v1 = 0) + (v2 = 0) >= 0);
+  v2;
+}
+
+condition_break(bool c) {
+  late int v;
+  do {
+    if (c) break;
+  } while ((v = 0) >= 0);
+  /*unassigned*/ v;
+}
+
+condition_break_continue(bool c1, bool c2) {
+  late int v1, v2, v3, v4, v5, v6;
+  do {
+    v1 = 0; // visible outside, visible to the condition
+    if (c1) break;
+    v2 = 0; // not visible outside, visible to the condition
+    v3 = 0; // not visible outside, visible to the condition
+    if (c2) continue;
+    v4 = 0; // not visible
+    v5 = 0; // not visible
+  } while ((v6 = v1 + v2 + /*unassigned*/ v4) ==
+      0); // has break => v6 is not visible outside
+  v1;
+  /*unassigned*/ v3;
+  /*unassigned*/ v5;
+  /*unassigned*/ v6;
+}
+
+condition_continue(bool c) {
+  late int v1, v2, v3, v4;
+  do {
+    v1 = 0; // visible outside, visible to the condition
+    if (c) continue;
+    v2 = 0; // not visible
+    v3 = 0; // not visible
+  } while (
+      (v4 = v1 + /*unassigned*/ v2) == 0); // no break => v4 visible outside
+  v1;
+  /*unassigned*/ v3;
+  v4;
+}
+
+continue_beforeAssignment(bool c) {
+  late int v;
+  do {
+    if (c) continue;
+    v = 0;
+  } while (c);
+  /*unassigned*/ v;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for.dart
new file mode 100644
index 0000000..be858b0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for.dart
@@ -0,0 +1,125 @@
+// 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.
+
+for_body(bool c) {
+  late int v;
+  for (; c;) {
+    v = 0;
+  }
+  /*unassigned*/ v;
+}
+
+for_break(bool c) {
+  late int v1, v2;
+  for (; c;) {
+    v1 = 0;
+    if (c) break;
+    v2 = 0;
+  }
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+}
+
+for_break_updaters(bool c) {
+  late int v1, v2;
+  for (; c; v1 + v2) {
+    v1 = 0;
+    if (c) break;
+    v2 = 0;
+  }
+}
+
+for_condition() {
+  late int v;
+  for (; (v = 0) >= 0;) {
+    v;
+  }
+  v;
+}
+
+for_continue(bool c) {
+  late int v1, v2;
+  for (; c;) {
+    v1 = 0;
+    if (c) continue;
+    v2 = 0;
+  }
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+}
+
+for_continue_updaters(bool c) {
+  late int v1, v2;
+  for (; c; v1 + /*unassigned*/ v2) {
+    v1 = 0;
+    if (c) continue;
+    v2 = 0;
+  }
+}
+
+for_initializer_expression() {
+  late int v;
+  for (v = 0;;) {
+    v;
+  }
+  v;
+}
+
+for_initializer_variable() {
+  late int v;
+  for (var t = (v = 0);;) {
+    v;
+  }
+  v;
+}
+
+for_updaters(bool c) {
+  late int v1, v2, v3, v4;
+  for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) {
+    /*unassigned*/ v1;
+  }
+  /*unassigned*/ v2;
+}
+
+for_updaters_afterBody(bool c) {
+  late int v;
+  for (; c; v) {
+    v = 0;
+  }
+}
+
+collection_for_body(bool c) {
+  late int v;
+  [for (; c;) (v = 0)];
+  /*unassigned*/ v;
+}
+
+collection_for_condition() {
+  late int v;
+  [for (; (v = 0) >= 0;) null];
+  v;
+}
+
+collection_for_initializer_expression() {
+  late int v;
+  [for (v = 0;;) v];
+  v;
+}
+
+collection_for_initializer_variable() {
+  late int v;
+  [for (var t = (v = 0);;) v];
+  v;
+}
+
+collection_for_updaters(bool c) {
+  late int v1, v2, v3, v4;
+  [for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) /*unassigned*/ v1 ];
+  /*unassigned*/ v2;
+}
+
+collection_for_updaters_afterBody(bool c) {
+  late int v;
+  [for (; c; v) (v = 0)];
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for_each.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for_each.dart
new file mode 100644
index 0000000..20ca569
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/for_each.dart
@@ -0,0 +1,71 @@
+// 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.
+
+forEach() {
+  late Object v1, v2;
+  for (var _ in (v1 = [0, 1, 2])) {
+    v2 = 0;
+  }
+  v1;
+  /*unassigned*/ v2;
+}
+
+forEach_break(bool c) {
+  late int v1, v2;
+  for (var _ in [0, 1, 2]) {
+    v1 = 0;
+    if (c) break;
+    v2 = 0;
+  }
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+}
+
+forEach_continue(bool c) {
+  late int v1, v2;
+  for (var _ in [0, 1, 2]) {
+    v1 = 0;
+    if (c) continue;
+    v2 = 0;
+  }
+  /*unassigned*/ v1;
+  /*unassigned*/ v2;
+}
+
+forEach_assigns_to_identifier() {
+  late int i;
+  for (i in [0, 1, 2]) {
+    i;
+  }
+  /*unassigned*/ i;
+}
+
+forEach_assigns_to_declared_var() {
+  for (int i in [0, 1, 2]) {
+    i;
+  }
+}
+
+collection_forEach() {
+  late Object v1, v2;
+  [
+    for (var _ in (v1 = [0, 1, 2])) (v2 = 0)
+  ];
+  v1;
+  /*unassigned*/ v2;
+}
+
+collection_forEach_assigns_to_identifier() {
+  late int i;
+  [
+    for (i in [0, 1, 2]) i
+  ];
+  /*unassigned*/ i;
+}
+
+collection_forEach_assigns_to_declared_var() {
+  [
+    for (int i in [0, 1, 2]) i
+  ];
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/function_expression.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/function_expression.dart
new file mode 100644
index 0000000..71617d3
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/function_expression.dart
@@ -0,0 +1,72 @@
+// 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.
+
+closure_read() {
+  late int v1, v2;
+
+  v1 = 0;
+
+  [0, 1, 2].forEach((t) {
+    v1;
+    /*unassigned*/ v2;
+  });
+}
+
+closure_write() {
+  late int v;
+
+  [0, 1, 2].forEach((t) {
+    v = t;
+  });
+
+  /*unassigned*/ v;
+}
+
+localFunction_local() {
+  late int v;
+
+  v = 0;
+
+  void f() {
+    late int v;
+    /*unassigned*/ v;
+  }
+}
+
+localFunction_local2() {
+  late int v1;
+
+  v1 = 0;
+
+  void f() {
+    late int v2, v3;
+    v2 = 0;
+    v1;
+    v2;
+    /*unassigned*/ v3;
+  }
+}
+
+localFunction_read() {
+  late int v1, v2, v3;
+
+  v1 = 0;
+
+  void f() {
+    v1;
+    /*unassigned*/ v2;
+  }
+
+  v2 = 0;
+}
+
+localFunction_write() {
+  late int v;
+
+  void f() {
+    v = 0;
+  }
+
+  /*unassigned*/ v;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/if.dart
new file mode 100644
index 0000000..60d945d
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/if.dart
@@ -0,0 +1,89 @@
+// 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.
+
+if_condition() {
+  late int v;
+  if ((v = 0) >= 0) {
+    v;
+  } else {
+    v;
+  }
+  v;
+}
+
+if_then(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  }
+  /*unassigned*/ v;
+}
+
+if_thenElse_all(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+    v;
+  } else {
+    v = 0;
+    v;
+  }
+  v;
+}
+
+if_thenElse_else(bool c) {
+  late int v;
+  if (c) {
+    // not assigned
+  } else {
+    v = 0;
+  }
+  /*unassigned*/ v;
+}
+
+if_thenElse_then(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  } else {
+    // not assigned
+  }
+  /*unassigned*/ v;
+}
+
+if_thenElse_then_exit_alwaysThrows(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  } else {
+    foo();
+  }
+  // flow analysis understands that foo never returns, so
+  // `v` is definitely assigned here.
+  v;
+}
+
+Never foo() {
+  throw Object();
+}
+
+if_thenElse_then_exit_return(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  } else {
+    return;
+  }
+  v;
+}
+
+if_thenElse_then_exit_throw(bool c) {
+  late int v;
+  if (c) {
+    v = 0;
+  } else {
+    throw 42;
+  }
+  v;
+}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/initialization.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/initialization.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/definite_assignment/data/initialization.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/initialization.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/switch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/switch.dart
new file mode 100644
index 0000000..cb32efb
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/switch.dart
@@ -0,0 +1,83 @@
+// 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.
+
+case1_default(int e) {
+  late int v;
+  switch (e) {
+    case 1:
+      v = 0;
+      break;
+    case 2:
+      // not assigned
+      break;
+    default:
+      v = 0;
+  }
+  /*unassigned*/ v;
+}
+
+case2_default(int e) {
+  late int v1, v2;
+  switch (e) {
+    case 1:
+      v1 = 0;
+      v2 = 0;
+      v1;
+      break;
+    default:
+      v1 = 0;
+      v1;
+  }
+  v1;
+  /*unassigned*/ v2;
+}
+
+case_default_break(int e, bool c) {
+  late int v1, v2;
+  switch (e) {
+    case 1:
+      v1 = 0;
+      if (c) break;
+      v2 = 0;
+      break;
+    default:
+      v1 = 0;
+      if (c) break;
+      v2 = 0;
+  }
+  v1;
+  /*unassigned*/ v2;
+}
+
+case_default_continue(int e) {
+  late int v;
+  switch (e) {
+    L:
+    case 1:
+      v = 0;
+      break;
+    case 2:
+      continue L;
+    default:
+      v = 0;
+  }
+  v;
+}
+
+case_noDefault(int e) {
+  late int v;
+  switch (e) {
+    case 1:
+      v = 0;
+      break;
+  }
+  /*unassigned*/ v;
+}
+
+condition() {
+  late int v;
+  switch (v = 0) {
+  }
+  v;
+}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/try.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/try.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/definite_assignment/data/try.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/try.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/while.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/while.dart
new file mode 100644
index 0000000..d8370a2
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/while.dart
@@ -0,0 +1,125 @@
+// 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.
+
+condition() {
+  late int v;
+  while ((v = 0) >= 0) {
+    v;
+  }
+  v;
+}
+
+condition_notTrue(bool c) {
+  late int v1, v2;
+  while (c) {
+    v1 = 0;
+    v2 = 0;
+    v1;
+  }
+  /*unassigned*/ v2;
+}
+
+true_break_afterAssignment(bool c) {
+  late int v1, v2;
+  while (true) {
+    v1 = 0;
+    v1;
+    if (c) break;
+    v1;
+    v2 = 0;
+    v2;
+  }
+  v1;
+}
+
+true_break_beforeAssignment(bool c) {
+  late int v1, v2;
+  while (true) {
+    if (c) break;
+    v1 = 0;
+    v2 = 0;
+    v2;
+  }
+  /*unassigned*/ v1;
+}
+
+true_break_if(bool c) {
+  late int v;
+  while (true) {
+    if (c) {
+      v = 0;
+      break;
+    } else {
+      v = 0;
+      break;
+    }
+    v;
+  }
+  v;
+}
+
+true_break_if2(bool c) {
+  late Object v;
+  while (true) {
+    if (c) {
+      break;
+    } else {
+      v = 0;
+    }
+    v;
+  }
+}
+
+true_break_if3(bool c) {
+  late int v1, v2;
+  while (true) {
+    if (c) {
+      v1 = 0;
+      v2 = 0;
+      if (c) break;
+    } else {
+      if (c) break;
+      v1 = 0;
+      v2 = 0;
+    }
+    v1;
+  }
+  /*unassigned*/ v2;
+}
+
+true_breakOuterFromInner(bool c) {
+  late int v1, v2, v3;
+  L1:
+  while (true) {
+    L2:
+    while (true) {
+      v1 = 0;
+      if (c) break L1;
+      v2 = 0;
+      v3 = 0;
+      if (c) break L2;
+    }
+    v2;
+  }
+  v1;
+  /*unassigned*/ v3;
+}
+
+true_continue(bool c) {
+  late int v;
+  while (true) {
+    if (c) continue;
+    v = 0;
+  }
+  /*unassigned*/ v;
+}
+
+true_noBreak(bool c) {
+  late int v;
+  while (true) {
+    // No assignment, but not break.
+    // So, we don't exit the loop.
+  }
+  /*unassigned*/ v;
+}
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
new file mode 100644
index 0000000..d10e75e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -0,0 +1,2975 @@
+// 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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+
+main() {
+  group('API', () {
+    test('asExpression_end promotes variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var expr = _Expression();
+        flow.variableRead(expr, x);
+        flow.asExpression_end(expr, _Type('int'));
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    test('asExpression_end handles other expressions', () {
+      var h = _Harness();
+      h.run((flow) {
+        var expr = _Expression();
+        flow.asExpression_end(expr, _Type('int'));
+      });
+    });
+
+    test('assert_afterCondition promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        flow.assert_begin();
+        var expr = h.eqNull(x)();
+        flow.assert_afterCondition(expr);
+        expect(flow.promotedType(x).type, 'int');
+        flow.assert_end();
+      });
+    });
+
+    test('assert_end joins previous and ifTrue states', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('x', 'int?');
+      var z = h.addVar('x', 'int?');
+      h.assignedVariables((vars) {
+        vars.write(x);
+        vars.write(z);
+      });
+      h.run((flow) {
+        h.promote(x, 'int');
+        h.promote(z, 'int');
+        flow.assert_begin();
+        flow.write(x, _Type('int?'));
+        flow.write(z, _Type('int?'));
+        var expr = h.and(h.notNull(x), h.notNull(y))();
+        flow.assert_afterCondition(expr);
+        flow.assert_end();
+        // x should be promoted because it was promoted before the assert, and
+        // it is re-promoted within the assert (if it passes)
+        expect(flow.promotedType(x).type, 'int');
+        // y should not be promoted because it was not promoted before the
+        // assert.
+        expect(flow.promotedType(y), null);
+        // z should not be promoted because it is demoted in the assert
+        // condition.
+        expect(flow.promotedType(z), null);
+      });
+    });
+
+    test('conditional_thenBegin promotes true branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.conditional_thenBegin(h.notNull(x)());
+        expect(flow.promotedType(x).type, 'int');
+        flow.conditional_elseBegin(_Expression());
+        expect(flow.promotedType(x), isNull);
+        flow.conditional_end(_Expression(), _Expression());
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('conditional_elseBegin promotes false branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.conditional_thenBegin(h.eqNull(x)());
+        expect(flow.promotedType(x), isNull);
+        flow.conditional_elseBegin(_Expression());
+        expect(flow.promotedType(x).type, 'int');
+        flow.conditional_end(_Expression(), _Expression());
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('conditional_end keeps promotions common to true and false branches',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.conditional_thenBegin(_Expression());
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        flow.conditional_elseBegin(_Expression());
+        h.promote(x, 'int');
+        h.promote(z, 'int');
+        flow.conditional_end(_Expression(), _Expression());
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+      });
+    });
+
+    test('conditional joins true states', () {
+      // if (... ? (x != null && y != null) : (x != null && z != null)) {
+      //   promotes x, but not y or z
+      // }
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        h.if_(
+            h.conditional(h.expr, h.and(h.notNull(x), h.notNull(y)),
+                h.and(h.notNull(x), h.notNull(z))), () {
+          expect(flow.promotedType(x).type, 'int');
+          expect(flow.promotedType(y), isNull);
+          expect(flow.promotedType(z), isNull);
+        });
+      });
+    });
+
+    test('conditional joins false states', () {
+      // if (... ? (x == null || y == null) : (x == null || z == null)) {
+      // } else {
+      //   promotes x, but not y or z
+      // }
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        h.ifElse(
+            h.conditional(h.expr, h.or(h.eqNull(x), h.eqNull(y)),
+                h.or(h.eqNull(x), h.eqNull(z))),
+            () {}, () {
+          expect(flow.promotedType(x).type, 'int');
+          expect(flow.promotedType(y), isNull);
+          expect(flow.promotedType(z), isNull);
+        });
+      });
+    });
+
+    test('equalityOp(x != null) promotes true branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.equalityOp_rightBegin(varExpr);
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        var expr = _Expression();
+        flow.equalityOp_end(expr, nullExpr, notEqual: true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('equalityOp(x == null) promotes false branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.equalityOp_rightBegin(varExpr);
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        var expr = _Expression();
+        flow.equalityOp_end(expr, nullExpr, notEqual: false);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('equalityOp(null != x) promotes true branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        flow.equalityOp_rightBegin(nullExpr);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        var expr = _Expression();
+        flow.equalityOp_end(expr, varExpr, notEqual: true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('equalityOp(null == x) promotes false branch', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        flow.equalityOp_rightBegin(nullExpr);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        var expr = _Expression();
+        flow.equalityOp_end(expr, varExpr, notEqual: false);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('conditionEqNull() does not promote write-captured vars', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.if_(h.notNull(x), () {
+          expect(flow.promotedType(x).type, 'int');
+        });
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        h.if_(h.notNull(x), () {
+          expect(flow.promotedType(x), isNull);
+        });
+      });
+    });
+
+    test('doStatement_bodyBegin() un-promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var doStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(doStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.doStatement_bodyBegin(doStatement);
+        expect(flow.promotedType(x), isNull);
+        flow.doStatement_conditionBegin();
+        flow.doStatement_end(_Expression());
+      });
+    });
+
+    test('doStatement_bodyBegin() handles write captures in the loop', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var doStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(
+          doStatement, () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.doStatement_bodyBegin(doStatement);
+        h.promote(x, 'int');
+        // The promotion should have no effect, because the second time through
+        // the loop, x has been write-captured.
+        expect(flow.promotedType(x), isNull);
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.doStatement_conditionBegin();
+        flow.doStatement_end(_Expression());
+      });
+    });
+
+    test('doStatement_conditionBegin() joins continue state', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.doStatement_bodyBegin(stmt);
+        h.if_(h.notNull(x), () {
+          flow.handleContinue(stmt);
+        });
+        flow.handleExit();
+        expect(flow.isReachable, false);
+        expect(flow.promotedType(x), isNull);
+        flow.doStatement_conditionBegin();
+        expect(flow.isReachable, true);
+        expect(flow.promotedType(x).type, 'int');
+        flow.doStatement_end(_Expression());
+      });
+    });
+
+    test('doStatement_end() promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.doStatement_bodyBegin(stmt);
+        flow.doStatement_conditionBegin();
+        expect(flow.promotedType(x), isNull);
+        flow.doStatement_end(h.eqNull(x)());
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    test('finish checks proper nesting', () {
+      var h = _Harness();
+      var expr = _Expression();
+      var flow = h.createFlow();
+      flow.ifStatement_thenBegin(expr);
+      expect(() => flow.finish(), _asserts);
+    });
+
+    test('for_conditionBegin() un-promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var forStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(forStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.for_conditionBegin(forStatement);
+        expect(flow.promotedType(x), isNull);
+        flow.for_bodyBegin(_Statement(), _Expression());
+        flow.write(x, _Type('int?'));
+        flow.for_updaterBegin();
+        flow.for_end();
+      });
+    });
+
+    test('for_conditionBegin() handles write captures in the loop', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var forStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(forStatement,
+          () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.for_conditionBegin(forStatement);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.for_bodyBegin(_Statement(), _Expression());
+        flow.for_updaterBegin();
+        flow.for_end();
+      });
+    });
+
+    test('for_conditionBegin() handles not-yet-seen variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var forStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(forStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.for_conditionBegin(forStatement);
+        flow.initialize(x);
+        flow.for_bodyBegin(_Statement(), _Expression());
+        flow.for_updaterBegin();
+        flow.for_end();
+      });
+    });
+
+    test('for_bodyBegin() handles empty condition', () {
+      var h = _Harness();
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        flow.for_conditionBegin(stmt);
+        flow.for_bodyBegin(stmt, null);
+        flow.for_updaterBegin();
+        expect(flow.isReachable, isTrue);
+        flow.for_end();
+        expect(flow.isReachable, isFalse);
+      });
+    });
+
+    test('for_bodyBegin() promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.for_conditionBegin(stmt);
+        flow.for_bodyBegin(stmt, h.notNull(x)());
+        expect(flow.promotedType(x).type, 'int');
+        flow.for_updaterBegin();
+        flow.for_end();
+      });
+    });
+
+    test('for_bodyBegin() can be used with a null statement', () {
+      // This is needed for collection elements that are for-loops.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var node = _Node();
+      h.assignedVariables((vars) => vars.nest(node, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.for_conditionBegin(node);
+        flow.for_bodyBegin(null, h.notNull(x)());
+        flow.for_updaterBegin();
+        flow.for_end();
+      });
+    });
+
+    test('for_updaterBegin() joins current and continue states', () {
+      // To test that the states are properly joined, we have three variables:
+      // x, y, and z.  We promote x and y in the continue path, and x and z in
+      // the current path.  Inside the updater, only x should be promoted.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.for_conditionBegin(stmt);
+        flow.for_bodyBegin(stmt, h.expr());
+        h.if_(h.expr, () {
+          h.promote(x, 'int');
+          h.promote(y, 'int');
+          flow.handleContinue(stmt);
+        });
+        h.promote(x, 'int');
+        h.promote(z, 'int');
+        flow.for_updaterBegin();
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+        flow.for_end();
+      });
+    });
+
+    test('for_end() joins break and condition-false states', () {
+      // To test that the states are properly joined, we have three variables:
+      // x, y, and z.  We promote x and y in the break path, and x and z in the
+      // condition-false path.  After the loop, only x should be promoted.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.for_conditionBegin(stmt);
+        flow.for_bodyBegin(stmt, h.or(h.eqNull(x), h.eqNull(z))());
+        h.if_(h.expr, () {
+          h.promote(x, 'int');
+          h.promote(y, 'int');
+          flow.handleBreak(stmt);
+        });
+        flow.for_updaterBegin();
+        flow.for_end();
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+      });
+    });
+
+    test('forEach_bodyBegin() un-promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var forStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(forStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.forEach_bodyBegin(forStatement, null, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.write(x, _Type('int?'));
+        flow.forEach_end();
+      });
+    });
+
+    test('forEach_bodyBegin() handles write captures in the loop', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var forStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(forStatement,
+          () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.forEach_bodyBegin(forStatement, null, _Type('int?'));
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.forEach_end();
+      });
+    });
+
+    test('forEach_bodyBegin() writes to loop variable', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var forStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(forStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: false);
+        expect(flow.isAssigned(x), false);
+        flow.forEach_bodyBegin(forStatement, x, _Type('int?'));
+        expect(flow.isAssigned(x), true);
+        flow.forEach_end();
+        expect(flow.isAssigned(x), false);
+      });
+    });
+
+    test('forEach_end() restores state before loop', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.forEach_bodyBegin(stmt, null, _Type('int?'));
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.forEach_end();
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('functionExpression_begin() cancels promotions of self-captured vars',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_begin(functionNode);
+        // x is unpromoted within the local function
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        flow.write(x, _Type('int?'));
+        h.promote(x, 'int');
+        flow.functionExpression_end();
+        // x is unpromoted after the local function too
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+      });
+    });
+
+    test('functionExpression_begin() cancels promotions of other-captured vars',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var functionNode1 = _Node();
+      var functionNode2 = _Node();
+      h.assignedVariables((vars) {
+        vars.function(functionNode1, () {});
+        vars.function(functionNode2, () => vars.write(x));
+      });
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_begin(functionNode1);
+        // x is unpromoted within the local function, because the write
+        // might have been captured by the time the local function executes.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        // And any effort to promote x fails, because there is no way of knowing
+        // when the captured write might occur.
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_end();
+        // x is still promoted after the local function, though, because the
+        // write hasn't been captured yet.
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_begin(functionNode2);
+        // x is unpromoted inside this local function too.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        flow.write(x, _Type('int?'));
+        flow.functionExpression_end();
+        // And since the second local function captured x, it remains
+        // unpromoted.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+      });
+    });
+
+    test('functionExpression_begin() cancels promotions of written vars', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var node = _Node();
+      h.assignedVariables((vars) {
+        vars.function(node, () {});
+        vars.write(x);
+      });
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_begin(node);
+        // x is unpromoted within the local function, because the write
+        // might have happened by the time the local function executes.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        // But it can be re-promoted because the write isn't captured.
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.functionExpression_end();
+        // x is still promoted after the local function, though, because the
+        // write hasn't occurred yet.
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.write(x, _Type('int?'));
+        // x is unpromoted now.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+      });
+    });
+
+    test('functionExpression_begin() handles not-yet-seen variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.functionExpression_begin(functionNode);
+        flow.functionExpression_end();
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('functionExpression_begin() handles not-yet-seen write-captured vars',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var functionNode1 = _Node();
+      var functionNode2 = _Node();
+      h.assignedVariables((vars) {
+        vars.function(functionNode1, () {});
+        vars.function(functionNode2, () => vars.write(x));
+      });
+      h.run((flow) {
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.functionExpression_begin(functionNode1);
+        h.promote(x, 'int');
+        // Promotion should not occur, because x might be write-captured by the
+        // time this code is reached.
+        expect(flow.promotedType(x), isNull);
+        flow.functionExpression_end();
+        flow.functionExpression_begin(functionNode2);
+        h.declare(x, initialized: true);
+        flow.functionExpression_end();
+      });
+    });
+
+    test('ifNullExpression allows ensure guarding', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.assignedVariables((vars) => vars.write(x));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.ifNullExpression_rightBegin(h.variableRead(x)());
+        flow.write(x, _Type('int'));
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifNullExpression_end();
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    test('ifNullExpression allows promotion of tested var', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.ifNullExpression_rightBegin(h.variableRead(x)());
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifNullExpression_end();
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    test('ifNullExpression discards promotions unrelated to tested expr', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.ifNullExpression_rightBegin(h.expr());
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifNullExpression_end();
+        expect(flow.promotedType(x), null);
+      });
+    });
+
+    test('ifStatement_end(false) keeps else branch if then branch exits', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.ifStatement_thenBegin(h.eqNull(x)());
+        flow.handleExit();
+        flow.ifStatement_end(false);
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    void _checkIs(String declaredType, String tryPromoteType,
+        String expectedPromotedType) {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var read = _Expression();
+        flow.variableRead(read, x);
+        var expr = _Expression();
+        flow.isExpression_end(expr, read, false, _Type(tryPromoteType));
+        flow.ifStatement_thenBegin(expr);
+        if (expectedPromotedType == null) {
+          expect(flow.promotedType(x), isNull);
+        } else {
+          expect(flow.promotedType(x).type, expectedPromotedType);
+        }
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_end(true);
+      });
+    }
+
+    test('isExpression_end promotes to a subtype', () {
+      _checkIs('int?', 'int', 'int');
+    });
+
+    test('isExpression_end does not promote to a supertype', () {
+      _checkIs('int', 'int?', null);
+    });
+
+    test('isExpression_end does not promote to an unrelated type', () {
+      _checkIs('int', 'String', null);
+    });
+
+    test('isExpression_end() does not promote write-captured vars', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.if_(h.isType(h.variableRead(x), 'int'), () {
+          expect(flow.promotedType(x).type, 'int');
+        });
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        h.if_(h.isType(h.variableRead(x), 'int'), () {
+          expect(flow.promotedType(x), isNull);
+        });
+      });
+    });
+
+    test('isExpression_end() handles not-yet-seen variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.assignedVariables(
+          (vars) => vars.function(_Node(), () => vars.write(x)));
+      h.run((flow) {
+        h.if_(h.isType(h.variableRead(x), 'int'), () {
+          expect(flow.promotedType(x).type, 'int');
+        });
+        h.declare(x, initialized: true);
+      });
+    });
+
+    test('logicalBinaryOp_rightBegin(isAnd: true) promotes in RHS', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.logicalBinaryOp_rightBegin(h.notNull(x)(), isAnd: true);
+        expect(flow.promotedType(x).type, 'int');
+        flow.logicalBinaryOp_end(_Expression(), _Expression(), isAnd: true);
+      });
+    });
+
+    test('logicalBinaryOp_rightEnd(isAnd: true) keeps promotions from RHS', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: true);
+        var wholeExpr = _Expression();
+        flow.logicalBinaryOp_end(wholeExpr, h.notNull(x)(), isAnd: true);
+        flow.ifStatement_thenBegin(wholeExpr);
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_end(false);
+      });
+    });
+
+    test('logicalBinaryOp_rightEnd(isAnd: false) keeps promotions from RHS',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: false);
+        var wholeExpr = _Expression();
+        flow.logicalBinaryOp_end(wholeExpr, h.eqNull(x)(), isAnd: false);
+        flow.ifStatement_thenBegin(wholeExpr);
+        flow.ifStatement_elseBegin();
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('logicalBinaryOp_rightBegin(isAnd: false) promotes in RHS', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.logicalBinaryOp_rightBegin(h.eqNull(x)(), isAnd: false);
+        expect(flow.promotedType(x).type, 'int');
+        flow.logicalBinaryOp_end(_Expression(), _Expression(), isAnd: false);
+      });
+    });
+
+    test('logicalBinaryOp(isAnd: true) joins promotions', () {
+      // if (x != null && y != null) {
+      //   promotes x and y
+      // }
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.if_(h.and(h.notNull(x), h.notNull(y)), () {
+          expect(flow.promotedType(x).type, 'int');
+          expect(flow.promotedType(y).type, 'int');
+        });
+      });
+    });
+
+    test('logicalBinaryOp(isAnd: false) joins promotions', () {
+      // if (x == null || y == null) {} else {
+      //   promotes x and y
+      // }
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.ifElse(h.or(h.eqNull(x), h.eqNull(y)), () {}, () {
+          expect(flow.promotedType(x).type, 'int');
+          expect(flow.promotedType(y).type, 'int');
+        });
+      });
+    });
+
+    test('nonNullAssert_end(x) promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.nonNullAssert_end(varExpr);
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
+    test('nullAwareAccess temporarily promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.nullAwareAccess_rightBegin(varExpr);
+        expect(flow.promotedType(x).type, 'int');
+        flow.nullAwareAccess_end();
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('nullAwareAccess does not promote the target of a cascade', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.nullAwareAccess_rightBegin(null);
+        expect(flow.promotedType(x), isNull);
+        flow.nullAwareAccess_end();
+      });
+    });
+
+    test('nullAwareAccess preserves demotions', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.assignedVariables((vars) => vars.write(x));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        var lhs = _Expression();
+        flow.nullAwareAccess_rightBegin(lhs);
+        expect(flow.promotedType(x).type, 'int');
+        flow.write(x, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.nullAwareAccess_end();
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('parenthesizedExpression preserves promotion behaviors', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.if_(
+            h.parenthesized(h.notEqual(h.parenthesized(h.variableRead(x)),
+                h.parenthesized(h.nullLiteral))), () {
+          expect(flow.promotedType(x).type, 'int');
+        });
+      });
+    });
+
+    test('promotedType handles not-yet-seen variables', () {
+      // Note: this is needed for error recovery in the analyzer.
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      h.run((flow) {
+        expect(flow.promotedType(x), isNull);
+        h.declare(x, initialized: true);
+      });
+    });
+
+    test('switchStatement_beginCase(false) restores previous promotions', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var switchStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(switchStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        flow.switchStatement_expressionEnd(_Statement());
+        flow.switchStatement_beginCase(false, switchStatement);
+        expect(flow.promotedType(x).type, 'int');
+        flow.write(x, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_beginCase(false, switchStatement);
+        expect(flow.promotedType(x).type, 'int');
+        flow.write(x, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_end(false);
+      });
+    });
+
+    test('switchStatement_beginCase(false) does not un-promote', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var switchStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(switchStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        flow.switchStatement_expressionEnd(_Statement());
+        flow.switchStatement_beginCase(false, switchStatement);
+        expect(flow.promotedType(x).type, 'int');
+        flow.write(x, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_end(false);
+      });
+    });
+
+    test('switchStatement_beginCase(false) handles write captures in cases',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var switchStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(switchStatement,
+          () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        flow.switchStatement_expressionEnd(_Statement());
+        flow.switchStatement_beginCase(false, switchStatement);
+        expect(flow.promotedType(x).type, 'int');
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_end(false);
+      });
+    });
+
+    test('switchStatement_beginCase(true) un-promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var switchStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(switchStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        flow.switchStatement_expressionEnd(_Statement());
+        flow.switchStatement_beginCase(true, switchStatement);
+        expect(flow.promotedType(x), isNull);
+        flow.write(x, _Type('int?'));
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_end(false);
+      });
+    });
+
+    test('switchStatement_beginCase(true) handles write captures in cases', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var switchStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(switchStatement,
+          () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        flow.switchStatement_expressionEnd(_Statement());
+        flow.switchStatement_beginCase(true, switchStatement);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        expect(flow.promotedType(x), isNull);
+        flow.switchStatement_end(false);
+      });
+    });
+
+    test('switchStatement_end(false) joins break and default', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var switchStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(switchStatement, () => vars.write(y)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        h.promote(y, 'int');
+        h.promote(z, 'int');
+        var stmt = _Statement();
+        flow.switchStatement_expressionEnd(stmt);
+        flow.switchStatement_beginCase(false, switchStatement);
+        h.promote(x, 'int');
+        flow.write(y, _Type('int?'));
+        flow.handleBreak(stmt);
+        flow.switchStatement_end(false);
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z).type, 'int');
+      });
+    });
+
+    test('switchStatement_end(true) joins breaks', () {
+      var h = _Harness();
+      var w = h.addVar('w', 'int?');
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var switchStatement = _Statement();
+      h.assignedVariables((vars) => vars.nest(switchStatement, () {
+            vars.write(x);
+            vars.write(y);
+          }));
+      h.run((flow) {
+        h.declare(w, initialized: true);
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        h.promote(z, 'int');
+        var stmt = _Statement();
+        flow.switchStatement_expressionEnd(stmt);
+        flow.switchStatement_beginCase(false, switchStatement);
+        h.promote(w, 'int');
+        h.promote(y, 'int');
+        flow.write(x, _Type('int?'));
+        flow.handleBreak(stmt);
+        flow.switchStatement_beginCase(false, switchStatement);
+        h.promote(w, 'int');
+        h.promote(x, 'int');
+        flow.write(y, _Type('int?'));
+        flow.handleBreak(stmt);
+        flow.switchStatement_end(true);
+        expect(flow.promotedType(w).type, 'int');
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z).type, 'int');
+      });
+    });
+
+    test('switchStatement_end(true) allows fall-through of last case', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.switchStatement_expressionEnd(stmt);
+        flow.switchStatement_beginCase(false, stmt);
+        h.promote(x, 'int');
+        flow.handleBreak(stmt);
+        flow.switchStatement_beginCase(false, stmt);
+        flow.switchStatement_end(true);
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('tryCatchStatement_bodyEnd() restores pre-try state', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.tryCatchStatement_bodyBegin();
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryCatchStatement_bodyEnd(stmt);
+        flow.tryCatchStatement_catchBegin(null, null);
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+      });
+    });
+
+    test('tryCatchStatement_bodyEnd() un-promotes variables assigned in body',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var body = _Statement();
+      h.assignedVariables((vars) => vars.nest(body, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryCatchStatement_bodyBegin();
+        flow.write(x, _Type('int?'));
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryCatchStatement_bodyEnd(body);
+        flow.tryCatchStatement_catchBegin(null, null);
+        expect(flow.promotedType(x), isNull);
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+      });
+    });
+
+    test('tryCatchStatement_bodyEnd() preserves write captures in body', () {
+      // Note: it's not necessary for the write capture to survive to the end of
+      // the try body, because an exception could occur at any time.  We check
+      // this by putting an exit in the try body.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var body = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(
+          body, () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryCatchStatement_bodyBegin();
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.handleExit();
+        flow.tryCatchStatement_bodyEnd(body);
+        flow.tryCatchStatement_catchBegin(null, null);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+      });
+    });
+
+    test('tryCatchStatement_catchBegin() restores previous post-body state',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.tryCatchStatement_bodyBegin();
+        flow.tryCatchStatement_bodyEnd(stmt);
+        flow.tryCatchStatement_catchBegin(null, null);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_catchBegin(null, null);
+        expect(flow.promotedType(x), isNull);
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+      });
+    });
+
+    test('tryCatchStatement_catchBegin() initializes vars', () {
+      var h = _Harness();
+      var e = h.addVar('e', 'int');
+      var st = h.addVar('st', 'StackTrace');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        flow.tryCatchStatement_bodyBegin();
+        flow.tryCatchStatement_bodyEnd(stmt);
+        flow.tryCatchStatement_catchBegin(e, st);
+        expect(flow.isAssigned(e), true);
+        expect(flow.isAssigned(st), true);
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+      });
+    });
+
+    test('tryCatchStatement_catchEnd() joins catch state with after-try state',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.tryCatchStatement_bodyBegin();
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        flow.tryCatchStatement_bodyEnd(stmt);
+        flow.tryCatchStatement_catchBegin(null, null);
+        h.promote(x, 'int');
+        h.promote(z, 'int');
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+        // Only x should be promoted, because it's the only variable
+        // promoted in both the try body and the catch handler.
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+      });
+    });
+
+    test('tryCatchStatement_catchEnd() joins catch states', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.tryCatchStatement_bodyBegin();
+        flow.handleExit();
+        flow.tryCatchStatement_bodyEnd(stmt);
+        flow.tryCatchStatement_catchBegin(null, null);
+        h.promote(x, 'int');
+        h.promote(y, 'int');
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_catchBegin(null, null);
+        h.promote(x, 'int');
+        h.promote(z, 'int');
+        flow.tryCatchStatement_catchEnd();
+        flow.tryCatchStatement_end();
+        // Only x should be promoted, because it's the only variable promoted
+        // in both catch handlers.
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+      });
+    });
+
+    test('tryFinallyStatement_finallyBegin() restores pre-try state', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var body = _Node();
+      var finallyBlock = _Node();
+      h.assignedVariables((vars) {
+        vars.nest(body, () {});
+        vars.nest(finallyBlock, () {});
+      });
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.tryFinallyStatement_bodyBegin();
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryFinallyStatement_finallyBegin(body);
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryFinallyStatement_end(finallyBlock);
+      });
+    });
+
+    test(
+        'tryFinallyStatement_finallyBegin() un-promotes variables assigned in '
+        'body', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var body = _Node();
+      var finallyBlock = _Node();
+      h.assignedVariables((vars) {
+        vars.nest(body, () => vars.write(x));
+        vars.nest(finallyBlock, () {});
+      });
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryFinallyStatement_bodyBegin();
+        flow.write(x, _Type('int?'));
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryFinallyStatement_finallyBegin(body);
+        expect(flow.promotedType(x), isNull);
+        flow.tryFinallyStatement_end(finallyBlock);
+      });
+    });
+
+    test('tryFinallyStatement_finallyBegin() preserves write captures in body',
+        () {
+      // Note: it's not necessary for the write capture to survive to the end of
+      // the try body, because an exception could occur at any time.  We check
+      // this by putting an exit in the try body.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var body = _Statement();
+      var functionNode = _Node();
+      var finallyBlock = _Node();
+      h.assignedVariables((vars) => vars.nest(body, () {
+            vars.function(functionNode, () => vars.write(x));
+            vars.nest(finallyBlock, () {});
+          }));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.tryFinallyStatement_bodyBegin();
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.handleExit();
+        flow.tryFinallyStatement_finallyBegin(body);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        flow.tryFinallyStatement_end(finallyBlock);
+      });
+    });
+
+    test('tryFinallyStatement_end() restores promotions from try body', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var body = _Statement();
+      var finallyBlock = _Node();
+      h.assignedVariables((vars) => vars.nest(body, () {
+            vars.nest(body, () {});
+            vars.nest(finallyBlock, () {});
+          }));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        flow.tryFinallyStatement_bodyBegin();
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryFinallyStatement_finallyBegin(body);
+        expect(flow.promotedType(x), isNull);
+        h.promote(y, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryFinallyStatement_end(finallyBlock);
+        // Both x and y should now be promoted.
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y).type, 'int');
+      });
+    });
+
+    test(
+        'tryFinallyStatement_end() does not restore try body promotions for '
+        'variables assigned in finally', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var body = _Node();
+      var finallyBlock = _Node();
+      h.assignedVariables((vars) {
+        vars.nest(body, () {});
+        vars.nest(finallyBlock, () {
+          vars.write(x);
+          vars.write(y);
+        });
+      });
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        flow.tryFinallyStatement_bodyBegin();
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.tryFinallyStatement_finallyBegin(body);
+        expect(flow.promotedType(x), isNull);
+        flow.write(x, _Type('int?'));
+        flow.write(y, _Type('int?'));
+        h.promote(y, 'int');
+        expect(flow.promotedType(y).type, 'int');
+        flow.tryFinallyStatement_end(finallyBlock);
+        // 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.
+        expect(flow.promotedType(x), isNull);
+        expect(flow.promotedType(y).type, 'int');
+      });
+    });
+
+    test('whileStatement_conditionBegin() un-promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var whileStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(whileStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.whileStatement_conditionBegin(whileStatement);
+        expect(flow.promotedType(x), isNull);
+        flow.whileStatement_bodyBegin(_Statement(), _Expression());
+        flow.whileStatement_end();
+      });
+    });
+
+    test('whileStatement_conditionBegin() handles write captures in the loop',
+        () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var whileStatement = _Statement();
+      var functionNode = _Node();
+      h.assignedVariables((vars) => vars.nest(whileStatement,
+          () => vars.function(functionNode, () => vars.write(x))));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.whileStatement_conditionBegin(whileStatement);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+        h.function(functionNode, () {
+          flow.write(x, _Type('int?'));
+        });
+        flow.whileStatement_bodyBegin(_Statement(), _Expression());
+        flow.whileStatement_end();
+      });
+    });
+
+    test('whileStatement_conditionBegin() handles not-yet-seen variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var whileStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(whileStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(y, initialized: true);
+        h.promote(y, 'int');
+        flow.whileStatement_conditionBegin(whileStatement);
+        flow.initialize(x);
+        flow.whileStatement_bodyBegin(_Statement(), _Expression());
+        flow.whileStatement_end();
+      });
+    });
+
+    test('whileStatement_bodyBegin() promotes', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.whileStatement_conditionBegin(stmt);
+        flow.whileStatement_bodyBegin(stmt, h.notNull(x)());
+        expect(flow.promotedType(x).type, 'int');
+        flow.whileStatement_end();
+      });
+    });
+
+    test('whileStatement_end() joins break and condition-false states', () {
+      // To test that the states are properly joined, we have three variables:
+      // x, y, and z.  We promote x and y in the break path, and x and z in the
+      // condition-false path.  After the loop, only x should be promoted.
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      var y = h.addVar('y', 'int?');
+      var z = h.addVar('z', 'int?');
+      var stmt = _Statement();
+      h.assignedVariables((vars) => vars.nest(stmt, () {}));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.declare(y, initialized: true);
+        h.declare(z, initialized: true);
+        flow.whileStatement_conditionBegin(stmt);
+        flow.whileStatement_bodyBegin(stmt, h.or(h.eqNull(x), h.eqNull(z))());
+        h.if_(h.expr, () {
+          h.promote(x, 'int');
+          h.promote(y, 'int');
+          flow.handleBreak(stmt);
+        });
+        flow.whileStatement_end();
+        expect(flow.promotedType(x).type, 'int');
+        expect(flow.promotedType(y), isNull);
+        expect(flow.promotedType(z), isNull);
+      });
+    });
+
+    test('Infinite loop does not implicitly assign variables', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      var whileStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(whileStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: false);
+        var trueCondition = _Expression();
+        flow.whileStatement_conditionBegin(whileStatement);
+        flow.booleanLiteral(trueCondition, true);
+        flow.whileStatement_bodyBegin(whileStatement, trueCondition);
+        flow.whileStatement_end();
+        expect(flow.isAssigned(x), false);
+      });
+    });
+
+    test('If(false) does not discard promotions', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'Object');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        // if (false) {
+        var falseExpression = _Expression();
+        flow.booleanLiteral(falseExpression, false);
+        flow.ifStatement_thenBegin(falseExpression);
+        expect(flow.promotedType(x).type, 'int');
+        flow.ifStatement_end(false);
+      });
+    });
+
+    test('Promotions do not occur when a variable is write-captured', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'Object');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.function(functionNode, () {});
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('Promotion cancellation of write-captured vars survives join', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'Object');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        h.ifElse(h.expr, () {
+          h.function(functionNode, () {});
+        }, () {
+          // Promotion should work here because the write capture is in the
+          // other branch.
+          h.promote(x, 'int');
+          expect(flow.promotedType(x).type, 'int');
+        });
+        // But the promotion should be cancelled now, after the join.
+        expect(flow.promotedType(x), isNull);
+        // And further attempts to promote should fail due to the write capture.
+        h.promote(x, 'int');
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+  });
+
+  group('State', () {
+    var intVar = _Var('x', _Type('int'));
+    var intQVar = _Var('x', _Type('int?'));
+    var objectQVar = _Var('x', _Type('Object?'));
+    group('setReachable', () {
+      var unreachable = FlowModel<_Var, _Type>(false);
+      var reachable = FlowModel<_Var, _Type>(true);
+      test('unchanged', () {
+        expect(unreachable.setReachable(false), same(unreachable));
+        expect(reachable.setReachable(true), same(reachable));
+      });
+
+      test('changed', () {
+        void _check(FlowModel<_Var, _Type> initial, bool newReachability) {
+          var s = initial.setReachable(newReachability);
+          expect(s, isNot(same(initial)));
+          expect(s.reachable, newReachability);
+          expect(s.variableInfo, same(initial.variableInfo));
+        }
+
+        _check(unreachable, true);
+        _check(reachable, false);
+      });
+    });
+
+    group('promote', () {
+      test('unpromoted -> unchanged (same)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryPromote(h, intVar, _Type('int')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('unpromoted -> unchanged (supertype)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryPromote(h, intVar, _Type('Object')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('unpromoted -> unchanged (unrelated)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryPromote(h, intVar, _Type('String')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('unpromoted -> subtype', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryPromote(h, intQVar, _Type('int')).ifTrue;
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
+        });
+      });
+
+      test('promoted -> unchanged (same)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.tryPromote(h, objectQVar, _Type('int')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('promoted -> unchanged (supertype)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.tryPromote(h, objectQVar, _Type('Object')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('promoted -> unchanged (unrelated)', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.tryPromote(h, objectQVar, _Type('String')).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('promoted -> subtype', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int?'))
+            .ifTrue;
+        var s2 = s1.tryPromote(h, objectQVar, _Type('int')).ifTrue;
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
+        });
+      });
+    });
+
+    group('write', () {
+      var objectQVar = _Var('x', _Type('Object?'));
+      test('unchanged', () {
+        var h = _Harness();
+        var s1 =
+            FlowModel<_Var, _Type>(true).write(objectQVar, _Type('Object?'), h);
+        var s2 = s1.write(objectQVar, _Type('Object?'), h);
+        expect(s2, same(s1));
+      });
+
+      test('marks as assigned', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.write(objectQVar, _Type('int?'), h);
+        expect(s2.reachable, true);
+        expect(
+            s2.infoFor(objectQVar),
+            _matchVariableModel(
+                chain: null, ofInterest: isEmpty, assigned: true));
+      });
+
+      test('un-promotes fully', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        expect(s1.variableInfo, contains(objectQVar));
+        var s2 = s1.write(objectQVar, _Type('int?'), h);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: null, ofInterest: isEmpty, assigned: true)
+        });
+      });
+
+      test('un-promotes partially, when no exact match', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        expect(s1.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'int'],
+              ofInterest: ['num?', 'int'],
+              assigned: true)
+        });
+        var s2 = s1.write(objectQVar, _Type('num'), h);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?'], ofInterest: ['num?', 'int'], assigned: true)
+        });
+      });
+
+      test('un-promotes partially, when exact match', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('num'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        expect(s1.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num', 'int'],
+              ofInterest: ['num?', 'num', 'int'],
+              assigned: true)
+        });
+        var s2 = s1.write(objectQVar, _Type('num'), h);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num'],
+              ofInterest: ['num?', 'num', 'int'],
+              assigned: true)
+        });
+      });
+
+      test('leaves promoted, when exact match', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('num'))
+            .ifTrue;
+        expect(s1.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num'],
+              ofInterest: ['num?', 'num'],
+              assigned: true)
+        });
+        var s2 = s1.write(objectQVar, _Type('num'), h);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, same(s1.variableInfo));
+      });
+
+      test('leaves promoted, when writing a subtype', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('num'))
+            .ifTrue;
+        expect(s1.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'num'],
+              ofInterest: ['num?', 'num'],
+              assigned: true)
+        });
+        var s2 = s1.write(objectQVar, _Type('int'), h);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, same(s1.variableInfo));
+      });
+
+      test('Promotes to type of interest when not previously promoted', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar: _matchVariableModel(chain: null, ofInterest: ['num?'])
+        });
+        var s2 = s1.write(objectQVar, _Type('num?'), h);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(chain: ['num?'], ofInterest: ['num?'])
+        });
+      });
+
+      test('Promotes to type of interest when previously promoted', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifTrue
+            .tryPromote(h, objectQVar, _Type('int?'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: ['num?'], ofInterest: ['num?', 'int?'])
+        });
+        var s2 = s1.write(objectQVar, _Type('int?'), h);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['num?', 'int?'], ofInterest: ['num?', 'int?'])
+        });
+      });
+
+      test('Multiple candidate types of interest; choose most specific (first)',
+          () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('int?'))
+            .ifFalse
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: null, ofInterest: ['num?', 'int?'])
+        });
+        var s2 = s1.write(objectQVar, _Type('int'), h);
+        expect(s2.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: ['int?'], ofInterest: ['num?', 'int?'])
+        });
+      });
+
+      test(
+          'Multiple candidate types of interest; choose most specific (second)',
+          () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifFalse
+            .tryPromote(h, objectQVar, _Type('int?'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: null, ofInterest: ['num?', 'int?'])
+        });
+        var s2 = s1.write(objectQVar, _Type('int'), h);
+        expect(s2.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: ['int?'], ofInterest: ['num?', 'int?'])
+        });
+      });
+
+      test('Multiple candidate types of interest; ambiguous', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifFalse
+            .tryPromote(h, objectQVar, _Type('num*'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: null, ofInterest: ['num?', 'num*'])
+        });
+        var s2 = s1.write(objectQVar, _Type('int'), h);
+        // It's ambiguous whether to promote to num? or num*, so we don't
+        // promote.
+        expect(s2, same(s1));
+      });
+
+      test('Multiple candidate types of interest; ambiguous but exact match',
+          () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .write(objectQVar, _Type('Object?'), h)
+            .tryPromote(h, objectQVar, _Type('num?'))
+            .ifFalse
+            .tryPromote(h, objectQVar, _Type('num*'))
+            .ifFalse;
+        expect(s1.variableInfo, {
+          objectQVar:
+              _matchVariableModel(chain: null, ofInterest: ['num?', 'num*'])
+        });
+        var s2 = s1.write(objectQVar, _Type('num?'), 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, {
+          objectQVar:
+              _matchVariableModel(chain: ['num?'], ofInterest: ['num?', 'num*'])
+        });
+      });
+    });
+
+    group('initialize', () {
+      var objectQVar = _Var('x', _Type('Object?'));
+      test('unchanged', () {
+        var s1 = FlowModel<_Var, _Type>(true).initialize(objectQVar);
+        var s2 = s1.initialize(objectQVar);
+        expect(s2, same(s1));
+      });
+
+      test('marks as assigned', () {
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.initialize(objectQVar);
+        expect(s2.reachable, true);
+        expect(
+            s2.infoFor(objectQVar),
+            _matchVariableModel(
+                chain: null, ofInterest: isEmpty, assigned: true));
+      });
+
+      test('un-promotes fully', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .initialize(objectQVar)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        expect(s1.variableInfo, contains(objectQVar));
+        var s2 = s1.initialize(objectQVar);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: null, ofInterest: isEmpty, assigned: true)
+        });
+      });
+    });
+
+    group('markNonNullable', () {
+      test('unpromoted -> unchanged', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryMarkNonNullable(h, intVar).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('unpromoted -> promoted', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true);
+        var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
+        expect(s2.reachable, true);
+        expect(s2.infoFor(intQVar),
+            _matchVariableModel(chain: ['int'], ofInterest: ['int']));
+      });
+
+      test('promoted -> unchanged', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
+        expect(s2, same(s1));
+      });
+
+      test('promoted -> re-promoted', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int?'))
+            .ifTrue;
+        var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(
+              chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
+        });
+      });
+    });
+
+    group('removePromotedAll', () {
+      test('unchanged', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.removePromotedAll([intQVar], []);
+        expect(s2, same(s1));
+      });
+
+      test('written', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue
+            .tryPromote(h, intQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.removePromotedAll([intQVar], []);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
+          intQVar: _matchVariableModel(chain: null, ofInterest: ['int'])
+        });
+      });
+
+      test('write captured', () {
+        var h = _Harness();
+        var s1 = FlowModel<_Var, _Type>(true)
+            .tryPromote(h, objectQVar, _Type('int'))
+            .ifTrue
+            .tryPromote(h, intQVar, _Type('int'))
+            .ifTrue;
+        var s2 = s1.removePromotedAll([], [intQVar]);
+        expect(s2.reachable, true);
+        expect(s2.variableInfo, {
+          objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
+          intQVar: _matchVariableModel(chain: null, ofInterest: isEmpty)
+        });
+      });
+    });
+
+    group('restrict', () {
+      test('reachability', () {
+        var h = _Harness();
+        var reachable = FlowModel<_Var, _Type>(true);
+        var unreachable = reachable.setReachable(false);
+        expect(reachable.restrict(h, reachable, Set()), same(reachable));
+        expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
+        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
+        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
+      });
+
+      test('assignments', () {
+        var h = _Harness();
+        var a = _Var('a', _Type('int'));
+        var b = _Var('b', _Type('int'));
+        var c = _Var('c', _Type('int'));
+        var d = _Var('d', _Type('int'));
+        var s0 = FlowModel<_Var, _Type>(true);
+        var s1 = s0.write(a, _Type('int'), h).write(b, _Type('int'), h);
+        var s2 = s0.write(a, _Type('int'), h).write(c, _Type('int'), h);
+        var result = s1.restrict(h, s2, Set());
+        expect(result.infoFor(a).assigned, true);
+        expect(result.infoFor(b).assigned, true);
+        expect(result.infoFor(c).assigned, true);
+        expect(result.infoFor(d).assigned, false);
+      });
+
+      test('write captured', () {
+        var h = _Harness();
+        var a = _Var('a', _Type('int'));
+        var b = _Var('b', _Type('int'));
+        var c = _Var('c', _Type('int'));
+        var d = _Var('d', _Type('int'));
+        var s0 = FlowModel<_Var, _Type>(true);
+        // In s1, a and b are write captured.  In s2, a and c are.
+        var s1 = s0.removePromotedAll([a, b], [a, b]);
+        var s2 = s0.removePromotedAll([a, c], [a, c]);
+        var result = s1.restrict(h, s2, Set());
+        expect(result.infoFor(a).writeCaptured, true);
+        expect(result.infoFor(b).writeCaptured, true);
+        expect(result.infoFor(c).writeCaptured, true);
+        expect(result.infoFor(d).writeCaptured, false);
+      });
+
+      test('promotion', () {
+        void _check(String thisType, String otherType, bool unsafe,
+            List<String> expectedChain) {
+          var h = _Harness();
+          var x = _Var('x', _Type('Object?'));
+          var s0 = FlowModel<_Var, _Type>(true).write(x, _Type('Object?'), h);
+          var s1 = thisType == null
+              ? s0
+              : s0.tryPromote(h, x, _Type(thisType)).ifTrue;
+          var s2 = otherType == null
+              ? s0
+              : s0.tryPromote(h, x, _Type(otherType)).ifTrue;
+          var result = s1.restrict(h, s2, unsafe ? [x].toSet() : Set());
+          if (expectedChain == null) {
+            expect(result.variableInfo, contains(x));
+            expect(result.infoFor(x).promotionChain, isNull);
+          } else {
+            expect(result.infoFor(x).promotionChain.map((t) => t.type).toList(),
+                expectedChain);
+          }
+        }
+
+        _check(null, null, false, null);
+        _check(null, null, true, null);
+        _check('int', null, false, ['int']);
+        _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', true, ['int?']);
+        _check('int', 'int?', true, ['int']);
+        _check('int', 'String', true, ['int']);
+      });
+
+      test('promotion chains', () {
+        // Verify that the given promotion chain matches the expected list of
+        // strings.
+        void _checkChain(List<_Type> chain, List<String> expected) {
+          var strings = (chain ?? <_Type>[]).map((t) => t.type).toList();
+          expect(strings, expected);
+        }
+
+        // Test the following scenario:
+        // - Prior to the try/finally block, the sequence of promotions in
+        //   [before] is done.
+        // - During the try block, the sequence of promotions in [inTry] is
+        //   done.
+        // - During the finally block, the sequence of promotions in
+        //   [inFinally] is done.
+        // - After calling `restrict` to refine the state from the finally
+        //   block, the expected promotion chain is [expectedResult].
+        void _check(List<String> before, List<String> inTry,
+            List<String> inFinally, List<String> expectedResult) {
+          var h = _Harness();
+          var x = _Var('x', _Type('Object?'));
+          var initialModel =
+              FlowModel<_Var, _Type>(true).write(x, _Type('Object?'), h);
+          for (var t in before) {
+            initialModel = initialModel.tryPromote(h, x, _Type(t)).ifTrue;
+          }
+          _checkChain(initialModel.infoFor(x).promotionChain, before);
+          var tryModel = initialModel;
+          for (var t in inTry) {
+            tryModel = tryModel.tryPromote(h, x, _Type(t)).ifTrue;
+          }
+          var expectedTryChain = before.toList()..addAll(inTry);
+          _checkChain(tryModel.infoFor(x).promotionChain, expectedTryChain);
+          var finallyModel = initialModel;
+          for (var t in inFinally) {
+            finallyModel = finallyModel.tryPromote(h, x, _Type(t)).ifTrue;
+          }
+          var expectedFinallyChain = before.toList()..addAll(inFinally);
+          _checkChain(
+              finallyModel.infoFor(x).promotionChain, expectedFinallyChain);
+          var result = finallyModel.restrict(h, tryModel, {});
+          _checkChain(result.infoFor(x).promotionChain, expectedResult);
+          // And verify that the inputs are unchanged.
+          _checkChain(initialModel.infoFor(x).promotionChain, before);
+          _checkChain(tryModel.infoFor(x).promotionChain, expectedTryChain);
+          _checkChain(
+              finallyModel.infoFor(x).promotionChain, expectedFinallyChain);
+        }
+
+        _check(['Object'], ['Iterable', 'List'], ['num', 'int'],
+            ['Object', 'Iterable', 'List']);
+        _check([], ['Iterable', 'List'], ['num', 'int'], ['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(['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']);
+      });
+
+      test('variable present in one state but not the other', () {
+        var h = _Harness();
+        var x = _Var('x', _Type('Object?'));
+        var s0 = FlowModel<_Var, _Type>(true);
+        var s1 = s0.write(x, _Type('Object?'), h);
+        expect(s0.restrict(h, s1, {}), same(s1));
+        expect(s0.restrict(h, s1, {x}), same(s1));
+        expect(s1.restrict(h, s0, {}), same(s1));
+        expect(s1.restrict(h, s0, {x}), same(s1));
+      });
+    });
+  });
+
+  group('joinPromotionChains', () {
+    var doubleType = _Type('double');
+    var intType = _Type('int');
+    var numType = _Type('num');
+    var objectType = _Type('Object');
+    var neverType = _Type('Never');
+
+    test('should handle nulls', () {
+      var h = _Harness();
+      expect(VariableModel.joinPromotionChains(null, null, h), null);
+      expect(VariableModel.joinPromotionChains(null, [intType], h), null);
+      expect(VariableModel.joinPromotionChains([intType], null, h), null);
+    });
+
+    test('should return null if there are no common types', () {
+      var h = _Harness();
+      expect(
+          VariableModel.joinPromotionChains([intType], [doubleType], h), null);
+    });
+
+    test('should return common prefix if there are common types', () {
+      var h = _Harness();
+      expect(
+          VariableModel.joinPromotionChains(
+              [objectType, intType], [objectType, doubleType], h),
+          _matchPromotionChain(['Object']));
+      expect(
+          VariableModel.joinPromotionChains([objectType, numType, intType],
+              [objectType, numType, doubleType], h),
+          _matchPromotionChain(['Object', 'num']));
+    });
+
+    test('should return an input if it is a prefix of the other', () {
+      var h = _Harness();
+      var prefix = [objectType, numType];
+      var largerChain = [objectType, numType, intType];
+      expect(VariableModel.joinPromotionChains(prefix, largerChain, h),
+          same(prefix));
+      expect(VariableModel.joinPromotionChains(largerChain, prefix, h),
+          same(prefix));
+      expect(
+          VariableModel.joinPromotionChains(prefix, prefix, h), same(prefix));
+    });
+
+    test('should not keep common types after the first difference', () {
+      var h = _Harness();
+      expect(
+          VariableModel.joinPromotionChains([objectType, intType, neverType],
+              [objectType, doubleType, neverType], h),
+          _matchPromotionChain(['Object']));
+    });
+  });
+
+  group('joinTypesOfInterest', () {
+    List<_Type> _makeTypes(List<String> typeNames) =>
+        typeNames.map((t) => _Type(t)).toList();
+
+    test('simple prefix', () {
+      var h = _Harness();
+      var s1 = _makeTypes(['double', 'int']);
+      var s2 = _makeTypes(['double', 'int', 'bool']);
+      var expected = _matchOfInterestSet(['double', 'int', 'bool']);
+      expect(VariableModel.joinTypesOfInterest(s1, s2, h), expected);
+      expect(VariableModel.joinTypesOfInterest(s2, s1, h), expected);
+    });
+
+    test('common prefix', () {
+      var h = _Harness();
+      var s1 = _makeTypes(['double', 'int', 'String']);
+      var s2 = _makeTypes(['double', 'int', 'bool']);
+      var expected = _matchOfInterestSet(['double', 'int', 'String', 'bool']);
+      expect(VariableModel.joinTypesOfInterest(s1, s2, h), expected);
+      expect(VariableModel.joinTypesOfInterest(s2, s1, h), expected);
+    });
+
+    test('order mismatch', () {
+      var h = _Harness();
+      var s1 = _makeTypes(['double', 'int']);
+      var s2 = _makeTypes(['int', 'double']);
+      var expected = _matchOfInterestSet(['double', 'int']);
+      expect(VariableModel.joinTypesOfInterest(s1, s2, h), expected);
+      expect(VariableModel.joinTypesOfInterest(s2, s1, h), expected);
+    });
+
+    test('small common prefix', () {
+      var h = _Harness();
+      var s1 = _makeTypes(['int', 'double', 'String', 'bool']);
+      var s2 = _makeTypes(['int', 'List', 'bool', 'Future']);
+      var expected = _matchOfInterestSet(
+          ['int', 'double', 'String', 'bool', 'List', 'Future']);
+      expect(VariableModel.joinTypesOfInterest(s1, s2, h), expected);
+      expect(VariableModel.joinTypesOfInterest(s2, s1, h), expected);
+    });
+  });
+
+  group('join', () {
+    var x = _Var('x', _Type('Object?'));
+    var y = _Var('y', _Type('Object?'));
+    var z = _Var('z', _Type('Object?'));
+    var w = _Var('w', _Type('Object?'));
+    var intType = _Type('int');
+    var intQType = _Type('int?');
+    var stringType = _Type('String');
+    const emptyMap = <Null, VariableModel<Null>>{};
+
+    VariableModel<_Type> model(List<_Type> promotionChain,
+            [List<_Type> typesOfInterest]) =>
+        VariableModel<_Type>(promotionChain,
+            typesOfInterest ?? promotionChain ?? [], false, false);
+
+    group('without input reuse', () {
+      test('promoted with unpromoted', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intType]),
+          y: model(null)
+        };
+        var p2 = {
+          x: model(null),
+          y: model([intType])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), {
+          x: _matchVariableModel(chain: null, ofInterest: ['int']),
+          y: _matchVariableModel(chain: null, ofInterest: ['int'])
+        });
+      });
+    });
+    group('should re-use an input if possible', () {
+      test('identical inputs', () {
+        var h = _Harness();
+        var p = {
+          x: model([intType]),
+          y: model([stringType])
+        };
+        expect(FlowModel.joinVariableInfo(h, p, p), same(p));
+      });
+
+      test('one input empty', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intType]),
+          y: model([stringType])
+        };
+        var p2 = <_Var, VariableModel<_Type>>{};
+        expect(FlowModel.joinVariableInfo(h, p1, p2), same(emptyMap));
+        expect(FlowModel.joinVariableInfo(h, p2, p1), same(emptyMap));
+      });
+
+      test('promoted with unpromoted', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intType])
+        };
+        var p2 = {x: model(null)};
+        var expected = {
+          x: _matchVariableModel(chain: null, ofInterest: ['int'])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), expected);
+        expect(FlowModel.joinVariableInfo(h, p2, p1), expected);
+      });
+
+      test('related type chains', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intQType, intType])
+        };
+        var p2 = {
+          x: model([intQType])
+        };
+        var expected = {
+          x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int'])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), expected);
+        expect(FlowModel.joinVariableInfo(h, p2, p1), expected);
+      });
+
+      test('unrelated type chains', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intType])
+        };
+        var p2 = {
+          x: model([stringType])
+        };
+        var expected = {
+          x: _matchVariableModel(chain: null, ofInterest: ['String', 'int'])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), expected);
+        expect(FlowModel.joinVariableInfo(h, p2, p1), expected);
+      });
+
+      test('sub-map', () {
+        var h = _Harness();
+        var xModel = model([intType]);
+        var p1 = {
+          x: xModel,
+          y: model([stringType])
+        };
+        var p2 = {x: xModel};
+        expect(FlowModel.joinVariableInfo(h, p1, p2), same(p2));
+        expect(FlowModel.joinVariableInfo(h, p2, p1), same(p2));
+      });
+
+      test('sub-map with matched subtype', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intQType, intType]),
+          y: model([stringType])
+        };
+        var p2 = {
+          x: model([intQType])
+        };
+        var expected = {
+          x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int'])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), expected);
+        expect(FlowModel.joinVariableInfo(h, p2, p1), expected);
+      });
+
+      test('sub-map with mismatched subtype', () {
+        var h = _Harness();
+        var p1 = {
+          x: model([intQType]),
+          y: model([stringType])
+        };
+        var p2 = {
+          x: model([intQType, intType])
+        };
+        var expected = {
+          x: _matchVariableModel(chain: ['int?'], ofInterest: ['int?', 'int'])
+        };
+        expect(FlowModel.joinVariableInfo(h, p1, p2), expected);
+        expect(FlowModel.joinVariableInfo(h, p2, p1), expected);
+      });
+
+      test('assigned', () {
+        var h = _Harness();
+        var intQModel = model([intQType]);
+        var writtenModel = intQModel.write(_Type('Object?'), h);
+        var p1 = {x: writtenModel, y: writtenModel, z: intQModel, w: intQModel};
+        var p2 = {x: writtenModel, y: intQModel, z: writtenModel, w: intQModel};
+        var joined = FlowModel.joinVariableInfo(h, p1, p2);
+        expect(joined, {
+          x: same(writtenModel),
+          y: _matchVariableModel(chain: null, assigned: false),
+          z: _matchVariableModel(chain: null, assigned: false),
+          w: same(intQModel)
+        });
+      });
+
+      test('write captured', () {
+        var h = _Harness();
+        var intQModel = model([intQType]);
+        var writeCapturedModel = intQModel.writeCapture();
+        var p1 = {
+          x: writeCapturedModel,
+          y: writeCapturedModel,
+          z: intQModel,
+          w: intQModel
+        };
+        var p2 = {
+          x: writeCapturedModel,
+          y: intQModel,
+          z: writeCapturedModel,
+          w: intQModel
+        };
+        var joined = FlowModel.joinVariableInfo(h, p1, p2);
+        expect(joined, {
+          x: same(writeCapturedModel),
+          y: same(writeCapturedModel),
+          z: same(writeCapturedModel),
+          w: same(intQModel)
+        });
+      });
+    });
+  });
+}
+
+/// Returns the appropriate matcher for expecting an assertion error to be
+/// thrown or not, based on whether assertions are enabled.
+Matcher get _asserts {
+  var matcher = throwsA(TypeMatcher<AssertionError>());
+  bool assertionsEnabled = false;
+  assert(assertionsEnabled = true);
+  if (!assertionsEnabled) {
+    matcher = isNot(matcher);
+  }
+  return matcher;
+}
+
+String _describeMatcher(Matcher matcher) {
+  var description = StringDescription();
+  matcher.describe(description);
+  return description.toString();
+}
+
+Matcher _matchOfInterestSet(List<String> expectedTypes) {
+  return predicate(
+      (List<_Type> x) => unorderedEquals(expectedTypes)
+          .matches(x.map((t) => t.type).toList(), {}),
+      'interest set $expectedTypes');
+}
+
+Matcher _matchPromotionChain(List<String> expectedTypes) {
+  if (expectedTypes == null) return isNull;
+  return predicate(
+      (List<_Type> x) =>
+          equals(expectedTypes).matches(x.map((t) => t.type).toList(), {}),
+      'promotion chain $expectedTypes');
+}
+
+Matcher _matchVariableModel(
+    {Object chain = anything,
+    Object ofInterest = anything,
+    Object assigned = anything,
+    Object writeCaptured = anything}) {
+  Matcher chainMatcher =
+      chain is List<String> ? _matchPromotionChain(chain) : wrapMatcher(chain);
+  Matcher ofInterestMatcher = ofInterest is List<String>
+      ? _matchOfInterestSet(ofInterest)
+      : wrapMatcher(ofInterest);
+  Matcher assignedMatcher = wrapMatcher(assigned);
+  Matcher writeCapturedMatcher = wrapMatcher(writeCaptured);
+  return predicate((VariableModel<_Type> model) {
+    if (!chainMatcher.matches(model.promotionChain, {})) return false;
+    if (!ofInterestMatcher.matches(model.typesOfInterest, {})) return false;
+    if (!assignedMatcher.matches(model.assigned, {})) return false;
+    if (!writeCapturedMatcher.matches(model.writeCaptured, {})) return false;
+    return true;
+  },
+      'VariableModel(chain: ${_describeMatcher(chainMatcher)}, '
+      'ofInterest: ${_describeMatcher(ofInterestMatcher)}, '
+      'assigned: ${_describeMatcher(assignedMatcher)}, writeCaptured: '
+      '${_describeMatcher(writeCapturedMatcher)})');
+}
+
+/// Representation of an expression to be visited by the test harness.  Calling
+/// the function causes the expression to be "visited" (in other words, the
+/// appropriate methods in [FlowAnalysis] are called in the appropriate order),
+/// and the [_Expression] object representing the whole expression is returned.
+///
+/// This is used by methods in [_Harness] as a lightweight way of building up
+/// complex sequences of calls to [FlowAnalysis] that represent large
+/// expressions.
+typedef _Expression LazyExpression();
+
+class _AssignedVariablesHarness {
+  final AssignedVariables<_Node, _Var> _assignedVariables;
+
+  _AssignedVariablesHarness(this._assignedVariables);
+
+  void function(_Node node, void Function() callback) {
+    _assignedVariables.beginNode();
+    callback();
+    _assignedVariables.endNode(node, isClosure: true);
+  }
+
+  void nest(_Node node, void Function() callback) {
+    _assignedVariables.beginNode();
+    callback();
+    _assignedVariables.endNode(node);
+  }
+
+  void write(_Var v) {
+    _assignedVariables.write(v);
+  }
+}
+
+class _Expression {
+  static int _idCounter = 0;
+
+  final int _id = _idCounter++;
+
+  @override
+  String toString() => 'E$_id';
+}
+
+class _Harness implements TypeOperations<_Var, _Type> {
+  FlowAnalysis<_Node, _Statement, _Expression, _Var, _Type> _flow;
+
+  final _assignedVariables = AssignedVariables<_Node, _Var>();
+
+  /// Returns a [LazyExpression] representing an expression with now special
+  /// flow analysis semantics.
+  LazyExpression get expr => () => _Expression();
+
+  LazyExpression get nullLiteral => () {
+        var expr = _Expression();
+        _flow.nullLiteral(expr);
+        return expr;
+      };
+
+  _Var addVar(String name, String type) {
+    assert(_flow == null);
+    return _Var(name, _Type(type));
+  }
+
+  /// Given two [LazyExpression]s, produces a new [LazyExpression] representing
+  /// the result of combining them with `&&`.
+  LazyExpression and(LazyExpression lhs, LazyExpression rhs) {
+    return () {
+      var expr = _Expression();
+      _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: true);
+      _flow.logicalBinaryOp_end(expr, rhs(), isAnd: true);
+      return expr;
+    };
+  }
+
+  void assignedVariables(void Function(_AssignedVariablesHarness) callback) {
+    callback(_AssignedVariablesHarness(_assignedVariables));
+  }
+
+  /// Given three [LazyExpression]s, produces a new [LazyExpression]
+  /// representing the result of combining them with `?` and `:`.
+  LazyExpression conditional(
+      LazyExpression cond, LazyExpression ifTrue, LazyExpression ifFalse) {
+    return () {
+      var expr = _Expression();
+      _flow.conditional_thenBegin(cond());
+      _flow.conditional_elseBegin(ifTrue());
+      _flow.conditional_end(expr, ifFalse());
+      return expr;
+    };
+  }
+
+  FlowAnalysis<_Node, _Statement, _Expression, _Var, _Type> createFlow() =>
+      FlowAnalysis<_Node, _Statement, _Expression, _Var, _Type>(
+          this, _assignedVariables);
+
+  void declare(_Var v, {@required bool initialized}) {
+    if (initialized) {
+      _flow.initialize(v);
+    }
+  }
+
+  /// Creates a [LazyExpression] representing an `== null` check performed on
+  /// [variable].
+  LazyExpression eqNull(_Var variable) {
+    return () {
+      var varExpr = _Expression();
+      _flow.variableRead(varExpr, variable);
+      _flow.equalityOp_rightBegin(varExpr);
+      var nullExpr = _Expression();
+      _flow.nullLiteral(nullExpr);
+      var expr = _Expression();
+      _flow.equalityOp_end(expr, nullExpr, notEqual: false);
+      return expr;
+    };
+  }
+
+  /// Invokes flow analysis of a nested function.
+  void function(_Node node, void body()) {
+    _flow.functionExpression_begin(node);
+    body();
+    _flow.functionExpression_end();
+  }
+
+  /// Invokes flow analysis of an `if` statement with no `else` part.
+  void if_(LazyExpression cond, void ifTrue()) {
+    _flow.ifStatement_thenBegin(cond());
+    ifTrue();
+    _flow.ifStatement_end(false);
+  }
+
+  /// Invokes flow analysis of an `if` statement with an `else` part.
+  void ifElse(LazyExpression cond, void ifTrue(), void ifFalse()) {
+    _flow.ifStatement_thenBegin(cond());
+    ifTrue();
+    _flow.ifStatement_elseBegin();
+    ifFalse();
+    _flow.ifStatement_end(true);
+  }
+
+  /// Creates a [LazyExpression] representing an `is!` check, checking whether
+  /// [subExpression] has the given [type].
+  LazyExpression isNotType(LazyExpression subExpression, String type) {
+    return () {
+      var expr = _Expression();
+      _flow.isExpression_end(expr, subExpression(), true, _Type(type));
+      return expr;
+    };
+  }
+
+  @override
+  bool isSameType(_Type type1, _Type type2) {
+    return type1.type == type2.type;
+  }
+
+  @override
+  bool isSubtypeOf(_Type leftType, _Type rightType) {
+    const Map<String, bool> _subtypes = const {
+      'int <: int?': true,
+      'int <: Iterable': false,
+      'int <: List': false,
+      'int <: num': true,
+      'int <: num?': true,
+      'int <: num*': true,
+      'int <: Object': true,
+      'int <: Object?': true,
+      'int <: String': false,
+      'int? <: int': false,
+      'int? <: num?': true,
+      'int? <: Object?': true,
+      'num <: int': false,
+      'num <: Iterable': false,
+      'num <: List': false,
+      'num <: num?': true,
+      'num <: Object': true,
+      'num <: Object?': true,
+      'num? <: int?': false,
+      'num? <: num': false,
+      'num? <: num*': true,
+      'num? <: Object?': true,
+      'num* <: num?': true,
+      'num* <: Object?': true,
+      'Iterable <: int': false,
+      'Iterable <: num': false,
+      'Iterable <: Object': true,
+      'Iterable <: Object?': true,
+      'List <: int': false,
+      'List <: Iterable': true,
+      'List <: Object': true,
+      'Object <: int': false,
+      'Object <: List': false,
+      'Object <: num': false,
+      'Object <: Object?': true,
+      'Object? <: int': false,
+      'Object? <: int?': false,
+      'String <: int': false,
+      'String <: int?': false,
+      'String <: Object?': true,
+    };
+
+    if (leftType.type == rightType.type) return true;
+    var query = '$leftType <: $rightType';
+    return _subtypes[query] ?? fail('Unknown subtype query: $query');
+  }
+
+  /// Creates a [LazyExpression] representing an `is` check, checking whether
+  /// [subExpression] has the given [type].
+  LazyExpression isType(LazyExpression subExpression, String type) {
+    return () {
+      var expr = _Expression();
+      _flow.isExpression_end(expr, subExpression(), false, _Type(type));
+      return expr;
+    };
+  }
+
+  /// Creates a [LazyExpression] representing an equality check between two
+  /// other expressions.
+  LazyExpression notEqual(LazyExpression lhs, LazyExpression rhs) {
+    return () {
+      var expr = _Expression();
+      _flow.equalityOp_rightBegin(lhs());
+      _flow.equalityOp_end(expr, rhs(), notEqual: true);
+      return expr;
+    };
+  }
+
+  /// Creates a [LazyExpression] representing a `!= null` check performed on
+  /// [variable].
+  LazyExpression notNull(_Var variable) {
+    return () {
+      var varExpr = _Expression();
+      _flow.variableRead(varExpr, variable);
+      _flow.equalityOp_rightBegin(varExpr);
+      var nullExpr = _Expression();
+      _flow.nullLiteral(nullExpr);
+      var expr = _Expression();
+      _flow.equalityOp_end(expr, nullExpr, notEqual: true);
+      return expr;
+    };
+  }
+
+  /// Given two [LazyExpression]s, produces a new [LazyExpression] representing
+  /// the result of combining them with `||`.
+  LazyExpression or(LazyExpression lhs, LazyExpression rhs) {
+    return () {
+      var expr = _Expression();
+      _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: false);
+      _flow.logicalBinaryOp_end(expr, rhs(), isAnd: false);
+      return expr;
+    };
+  }
+
+  /// Creates a [LazyExpression] representing a parenthesized subexpression.
+  LazyExpression parenthesized(LazyExpression inner) {
+    return () {
+      var expr = _Expression();
+      _flow.parenthesizedExpression(expr, inner());
+      return expr;
+    };
+  }
+
+  /// Causes [variable] to be promoted to [type].
+  void promote(_Var variable, String type) {
+    if_(isNotType(variableRead(variable), type), _flow.handleExit);
+  }
+
+  @override
+  _Type promoteToNonNull(_Type type) {
+    if (type.type.endsWith('?')) {
+      return _Type(type.type.substring(0, type.type.length - 1));
+    } else {
+      return type;
+    }
+  }
+
+  void run(
+      void callback(
+          FlowAnalysis<_Node, _Statement, _Expression, _Var, _Type> flow)) {
+    assert(_flow == null);
+    _flow = createFlow();
+    callback(_flow);
+    _flow.finish();
+  }
+
+  @override
+  _Type tryPromoteToType(_Type to, _Type from) {
+    if (isSubtypeOf(to, from)) {
+      return to;
+    } else {
+      return null;
+    }
+  }
+
+  LazyExpression variableRead(_Var variable) {
+    return () {
+      var expr = _Expression();
+      _flow.variableRead(expr, variable);
+      return expr;
+    };
+  }
+
+  @override
+  _Type variableType(_Var variable) {
+    return variable.type;
+  }
+}
+
+class _Node {}
+
+class _Statement extends _Node {}
+
+class _Type {
+  final String type;
+
+  _Type(this.type);
+
+  @override
+  bool operator ==(Object other) {
+    // The flow analysis engine should not compare types using operator==.  It
+    // should compare them using TypeOperations.
+    fail('Unexpected use of operator== on types');
+  }
+
+  @override
+  String toString() => type;
+}
+
+class _Var {
+  final String name;
+
+  final _Type type;
+
+  _Var(this.name, this.type);
+
+  @override
+  String toString() => '$type $name';
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assert.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assert.dart
new file mode 100644
index 0000000..23d6346
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assert.dart
@@ -0,0 +1,18 @@
+// 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.
+
+assertStatement(int? i) {
+  // Assert statements do not promote because they only are only
+  // checked in debug mode.
+  assert(i != null);
+  i;
+}
+
+class C {
+  C.assertInitializer(int? i) : assert(i != null) {
+    // Assert statements do not promote because they only are only
+    // checked in debug mode.
+    i;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assign.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assign.dart
new file mode 100644
index 0000000..008cc8f
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/assign.dart
@@ -0,0 +1,31 @@
+// 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.
+
+void toNonNull(int? x) {
+  if (x != null) return;
+  x;
+  x = 0;
+  /*nonNullable*/ x;
+}
+
+void toNull(int? x) {
+  if (x == null) return;
+  /*nonNullable*/ x;
+  x = null;
+  x;
+}
+
+void toUnknown_fromNotNull(int? a, int? b) {
+  if (a == null) return;
+  /*nonNullable*/ a;
+  a = b;
+  a;
+}
+
+void toUnknown_fromNull(int? a, int? b) {
+  if (a != null) return;
+  a;
+  a = b;
+  a;
+}
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/if.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/if.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/if.dart
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/is.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/is.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/is.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/is.dart
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/logical.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/logical.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/logical.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/logical.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart
new file mode 100644
index 0000000..3dd6da9
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart
@@ -0,0 +1,150 @@
+// 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.
+
+class C {
+  void set setter(value) {}
+  C operator [](index) => this;
+  void operator []=(index, value) {}
+  C get getterReturningC => this;
+  C? get getterReturningNullableC => this;
+  C get getterSetter => this;
+  void set getterSetter(value) {}
+  C operator +(other) => this;
+}
+
+class D {
+  void set setter(value) {}
+  D? operator [](index) => this;
+  void operator []=(index, value) {}
+  D get getterSetter => this;
+  void set getterSetter(value) {}
+  D operator +(other) => this;
+}
+
+void setterCall(C? c) {
+  c?.setter = /*nonNullable*/ c;
+}
+
+void compoundAssign(C? c) {
+  c?.getterSetter += /*nonNullable*/ c;
+}
+
+void nullAwareAssign(C? c) {
+  c?.getterSetter ??= /*nonNullable*/ c;
+}
+
+void indexGetterCall(C? c) {
+  c?.[/*nonNullable*/ c];
+}
+
+void indexSetterCall(C? c) {
+  c?.[/*nonNullable*/ c] = /*nonNullable*/ c;
+}
+
+void indexCompoundAssign(C? c) {
+  c?.[/*nonNullable*/ c] += /*nonNullable*/ c;
+}
+
+void indexNullAwareAssign(C? c) {
+  c?.[/*nonNullable*/ c] ??= /*nonNullable*/ c;
+}
+
+void setterCall_nullShorting(C? c, D? d) {
+  c?.getterReturningC.setter = /*nonNullable*/ c;
+  c?.getterReturningNullableC?.setter = /*nonNullable*/ c;
+  c?.[0].setter = /*nonNullable*/ c;
+  d?.[0]?.setter = /*nonNullable*/ d;
+}
+
+void compoundAssign_nullShorting(C? c, D? d) {
+  c?.getterReturningC.getterSetter += /*nonNullable*/ c;
+  c?.getterReturningNullableC?.getterSetter += /*nonNullable*/ c;
+  c?.[0].getterSetter += /*nonNullable*/ c;
+  d?.[0]?.getterSetter += /*nonNullable*/ d;
+}
+
+void nullAwareAssign_nullShorting(C? c, D? d) {
+  c?.getterReturningC.getterSetter ??= /*nonNullable*/ c;
+  c?.getterReturningNullableC?.getterSetter ??= /*nonNullable*/ c;
+  c?.[0].getterSetter ??= /*nonNullable*/ c;
+  d?.[0]?.getterSetter ??= /*nonNullable*/ d;
+}
+
+void indexGetterCall_nullShorting(C? c, D? d) {
+  c?.getterReturningC[/*nonNullable*/ c];
+  c?.getterReturningNullableC?.[/*nonNullable*/ c];
+  c?.[0][/*nonNullable*/ c];
+  d?.[0]?.[/*nonNullable*/ d];
+}
+
+void indexSetterCall_nullShorting(C? c, D? d) {
+  c?.getterReturningC[/*nonNullable*/ c] = /*nonNullable*/ c;
+  c?.getterReturningNullableC?.[/*nonNullable*/ c] = /*nonNullable*/ c;
+  c?.[0][/*nonNullable*/ c] = /*nonNullable*/ c;
+  d?.[0]?.[/*nonNullable*/ d] = /*nonNullable*/ d;
+}
+
+void indexCompoundAssign_nullShorting(C? c, D? d) {
+  c?.getterReturningC[/*nonNullable*/ c] += /*nonNullable*/ c;
+  c?.getterReturningNullableC?.[/*nonNullable*/ c] += /*nonNullable*/ c;
+  c?.[0][/*nonNullable*/ c] += /*nonNullable*/ c;
+  d?.[0]?.[/*nonNullable*/ d] += /*nonNullable*/ d;
+}
+
+void indexNullAwareAssign_nullShorting(C? c, D? d) {
+  c?.getterReturningC[/*nonNullable*/ c] ??= /*nonNullable*/ c;
+  c?.getterReturningNullableC?.[/*nonNullable*/ c] ??= /*nonNullable*/ c;
+  c?.[0][/*nonNullable*/ c] ??= /*nonNullable*/ c;
+  d?.[0]?.[/*nonNullable*/ d] ??= /*nonNullable*/ d;
+}
+
+void null_aware_cascades_do_not_promote_target(C? c) {
+  // Cascaded invocations act on an invisible temporary variable that
+  // holds the result of evaluating the cascade target.  So
+  // effectively, no promotion happens (because there is no way to
+  // observe a change to the type of that variable).
+  c?..setter = c;
+  c?..getterSetter += c;
+  c?..getterSetter ??= c;
+  c?..[c];
+  c?..[c] = c;
+  c?..[c] += c;
+  c?..[c] ??= c;
+}
+
+void null_aware_cascades_do_not_promote_others(C? c, int? i, int? j) {
+  // Promotions that happen inside null-aware cascade sections
+  // disappear after the cascade section, because they are not
+  // guaranteed to execute.
+  c?..setter = i!;
+  c?..getterSetter += i!;
+  c?..getterSetter ??= i!;
+  c?..[i!];
+  c?..[i!] = j!;
+  c?..[i!] += j!;
+  c?..[i!] ??= j!;
+  i;
+  j;
+}
+
+void normal_cascades_do_promote_others(C c, int? i, int? j, int? k, int? l,
+    int? m, int? n, int? o, int? p, int? q, int? r) {
+  // Promotions that happen inside non-null-aware cascade sections
+  // don't disappear after the cascade section.
+  c..setter = i!;
+  c..getterSetter += m!;
+  c..getterSetter ??= n!;
+  c..[j!];
+  c..[k!] = l!;
+  c..[o!] += p!;
+  c..[q!] ??= r!;
+  /*nonNullable*/ i;
+  /*nonNullable*/ j;
+  /*nonNullable*/ k;
+  /*nonNullable*/ l;
+  /*nonNullable*/ m;
+  n; // Not promoted because `n!` is on the RHS of `??=`
+  /*nonNullable*/ o;
+  /*nonNullable*/ p;
+}
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/null_check.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/null_check.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_check.dart
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/potentially_mutated_in_closure.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/potentially_mutated_in_closure.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/potentially_mutated_in_closure.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/potentially_mutated_in_closure.dart
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/try_finally.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/try_finally.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/try_finally.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/try_finally.dart
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/while.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/while.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/nullability/data/while.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/while.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/assert.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/assert.dart
new file mode 100644
index 0000000..85269d8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/assert.dart
@@ -0,0 +1,44 @@
+// 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.
+
+assertFalse() {
+  // Code following assert(false) is still reachable because
+  // assertions are only checked in debug mode.
+  assert(false);
+  0;
+}
+
+assertThrow() {
+  // Code following assert(throw ...) is still reachable because
+  // assertions are only checked in debug mode.
+  assert(throw 'foo');
+  0;
+}
+
+assertThrowInString(bool b) {
+  // Code following assert(..., throw ...) is still reachable because
+  // assertions are only checked in debug mode.
+  assert(b, throw 'foo');
+  0;
+}
+
+class C {
+  C.assertFalse() : assert(false) {
+    // Code following assert(false) is still reachable because
+    // assertions are only checked in debug mode.
+    0;
+  }
+
+  C.assertThrow() : assert(throw 'foo') {
+    // Code following assert(throw ...) is still reachable because
+    // assertions are only checked in debug mode.
+    0;
+  }
+
+  C.assertThrowInString(bool b) : assert(b, throw 'foo') {
+    // Code following assert(..., throw ...) is still reachable because
+    // assertions are only checked in debug mode.
+    0;
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/conditional.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/reachability/data/conditional.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/conditional.dart
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/do.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/do.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/reachability/data/do.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/do.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/early_exit.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/early_exit.dart
new file mode 100644
index 0000000..fd67128
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/early_exit.dart
@@ -0,0 +1,36 @@
+// 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.
+
+/*member: beforeSplitStatement:doesNotComplete*/
+void beforeSplitStatement(bool b, int i) {
+  return;
+  /*unreachable*/
+  do /*unreachable*/ {} while (/*unreachable*/ b);
+
+  /*unreachable*/
+  for (;;) /*unreachable*/ {}
+
+  /*unreachable*/
+  /*cfe.iterator: unreachable*/
+  /*cfe.current: unreachable*/
+  /*cfe.moveNext: unreachable*/
+  for (var _ in /*unreachable*/ [])
+  /*unreachable*/ {}
+
+  /*unreachable*/
+  if (/*unreachable*/ b)
+  /*unreachable*/ {}
+
+  /*unreachable*/
+  switch (/*unreachable*/ i) {
+  }
+
+  /*unreachable*/
+  try /*unreachable*/ {} finally
+  /*unreachable*/ {}
+
+  /*unreachable*/
+  while (/*unreachable*/ b)
+  /*unreachable*/ {}
+}
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/for.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/for.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/reachability/data/for.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/for.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/function_body.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/function_body.dart
new file mode 100644
index 0000000..0979162
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/function_body.dart
@@ -0,0 +1,17 @@
+// 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.
+
+/*member: hasReturn:doesNotComplete*/
+int hasReturn() {
+  return 42;
+}
+
+void noReturn() {
+  1;
+}
+
+/*member: hasThrow:doesNotComplete*/
+int hasThrow() {
+  throw 42;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/never_return_type.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/never_return_type.dart
new file mode 100644
index 0000000..36913c5
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/never_return_type.dart
@@ -0,0 +1,201 @@
+// 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.
+
+void top_level_function_call(bool b) {
+  if (b) {
+    topLevelFunction();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void method_call(bool b, C c) {
+  if (b) {
+    c.method();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void static_method_call(bool b) {
+  if (b) {
+    C.staticMethod();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void simple_getter_call(bool b, C c) {
+  if (b) {
+    c.getter;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void static_getter_call(bool b) {
+  if (b) {
+    C.staticGetter;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void complex_getter_call(bool b1, bool b2, C c) {
+  if (b1) {
+    (b2 ? c : c).getter;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void binary_operation(bool b, C c) {
+  if (b) {
+    c + 1;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void is_expression(bool b, dynamic d) {
+  if (b) {
+    topLevelFunction() is int;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void as_subexpression(bool b) {
+  if (b) {
+    topLevelFunction() as Never;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void as_expression(bool b, dynamic d) {
+  if (b) {
+    d as Never;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void assignment_rhs(bool b, Never n, Object x) {
+  if (b) {
+    x = n;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void initialization(bool b, Never n) {
+  if (b) {
+    var x = n;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void conditional_condition(bool b) {
+  if (b) {
+    topLevelFunction() ? /*unreachable*/ 0 : /*unreachable*/ 1;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void conditional_then_else(bool b1, bool b2) {
+  if (b1) {
+    b2 ? topLevelFunction() : topLevelFunction();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+Future await_expression(bool b) async {
+  if (b) {
+    await topLevelFunction();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void invocation(bool b, Never Function() f) {
+  if (b) {
+    f();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void invocation_argument(bool b, C c) {
+  if (b) {
+    c.methodTakingArgument(topLevelFunction());
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void invocation_named_argument(bool b, C c) {
+  if (b) {
+    c.methodTakingNamedArgument(arg: topLevelFunction());
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void index_expression(bool b, C c) {
+  if (b) {
+    c[0];
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void unary_expression(bool b, C c) {
+  if (b) {
+    -c;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void cascade_method_call(bool b, C c) {
+  if (b) {
+    c..method();
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+void cascade_getter_call(bool b, C c) {
+  if (b) {
+    c..getter;
+    /*stmt: unreachable*/ 0;
+  }
+}
+
+/*member: topLevelFunction:doesNotComplete*/
+Never topLevelFunction() => throw 'foo';
+
+class C {
+  final dynamic field1;
+  final dynamic field2;
+
+  /*member: C.method:doesNotComplete*/
+  Never method() => throw 'foo';
+
+  /*member: C.staticMethod:doesNotComplete*/
+  static Never staticMethod() => throw 'foo';
+
+  void methodTakingArgument(arg) {}
+  void methodTakingNamedArgument({arg}) {}
+
+  /*member: C.getter:doesNotComplete*/
+  Never get getter => throw 'foo';
+
+  /*member: C.staticGetter:doesNotComplete*/
+  static Never get staticGetter => throw 'foo';
+
+  /*member: C.+:doesNotComplete*/
+  Never operator +(other) => throw 'foo';
+
+  /*member: C.[]:doesNotComplete*/
+  Never operator [](other) => throw 'foo';
+
+  /*member: C.unary-:doesNotComplete*/
+  Never operator -() => throw 'foo';
+
+  /*member: C.constructor_initializer:doesNotComplete*/
+  C.constructor_initializer()
+      : field1 = topLevelFunction(),
+        field2 = /*unreachable*/ 0 /*unreachable*/ {}
+
+  void local_getter(bool b) {
+    if (b) {
+      getter;
+      /*stmt: unreachable*/ 0;
+    }
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/switch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/switch.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/reachability/data/switch.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/switch.dart
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/try_catch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/try_catch.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/reachability/data/try_catch.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/try_catch.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/as.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/as.dart
new file mode 100644
index 0000000..85a84db
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/as.dart
@@ -0,0 +1,31 @@
+// 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.
+
+class A {}
+
+class B {}
+
+class C implements A, B {}
+
+promotesIfSubtype(A a) {
+  a as C;
+  /*C*/ a;
+}
+
+doesNotPromoteIfNotSubtype(A a) {
+  a as B;
+  a;
+}
+
+doesNotPromoteIfSameType(A a) {
+  a as A;
+  a;
+}
+
+class D<T extends A> {
+  promotesTypeParameter(T t) {
+    t as C;
+    /*T & C*/ t;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assert.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assert.dart
new file mode 100644
index 0000000..f262975
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assert.dart
@@ -0,0 +1,28 @@
+// 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.
+
+void assertStatement(Object x) {
+  assert((x is int ? /*int*/ x : throw 'foo') == 0);
+  // x is not promoted because the assertion won't execute in release
+  // mode.
+  x;
+}
+
+void promotionInConditionCarriesToMessage(Object x) {
+  // Code in the message part of an assertion can assume that the
+  // condition evaluated to false.
+  assert(x is! int, /*int*/ x.toString());
+}
+
+class C {
+  C.assertInitializer(Object x)
+      : assert((x is int ? /*int*/ x : throw 'foo') == 0) {
+    // x is not promoted because the assertion won't execute in release
+    // mode.
+    x;
+  }
+
+  C.promotionInConditionCarriesToMessage(Object x)
+      : assert(x is! int, /*int*/ x.toString());
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/assigned_anywhere.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assigned_anywhere.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/assigned_anywhere.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assigned_anywhere.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment.dart
new file mode 100644
index 0000000..929536a
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment.dart
@@ -0,0 +1,117 @@
+// 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.
+
+assignmentDepromotes(Object x) {
+  if (x is String) {
+    x = 42;
+    x;
+  }
+}
+
+assignmentDepromotes_partial(Object x) {
+  if (x is num) {
+    if (/*num*/ x is int) {
+      x = 42.0;
+      /*num*/ x;
+    }
+  }
+}
+
+assignmentPreservesPromotion(Object x) {
+  if (x is num) {
+    x = 42;
+    /*num*/ x;
+  }
+}
+
+compoundAssignmentDepromotes(Object x) {
+  if (x is int) {
+    /*int*/ x += 0.5;
+    x;
+  }
+}
+
+compoundAssignmentDepromotes_partial(Object x) {
+  if (x is num) {
+    if (/*num*/ x is int) {
+      /*int*/ x += 0.5;
+      /*num*/ x;
+    }
+  }
+}
+
+compoundAssignmentPreservesPromotion(Object x) {
+  if (x is num) {
+    /*num*/ x += 0.5;
+    /*num*/ x;
+  }
+}
+
+nullAwareAssignmentDepromotes(Object x) {
+  if (x is int?) {
+    x ??= 'foo';
+    x;
+  }
+}
+
+preIncrementDepromotes(Object x) {
+  if (x is C) {
+    ++ /*C*/ x;
+    x;
+  }
+}
+
+postIncrementDepromotes(Object x) {
+  if (x is C) {
+    /*C*/ x++;
+    x;
+  }
+}
+
+preDecrementDepromotes(Object x) {
+  if (x is C) {
+    -- /*C*/ x;
+    x;
+  }
+}
+
+postDecrementDepromotes(Object x) {
+  if (x is C) {
+    /*C*/ x--;
+    x;
+  }
+}
+
+preIncrementPreservesPromotion(Object x) {
+  if (x is int) {
+    ++ /*int*/ x;
+    /*int*/ x;
+  }
+}
+
+postIncrementPreservesPromotion(Object x) {
+  if (x is int) {
+    /*int*/ x++;
+    /*int*/ x;
+  }
+}
+
+preDecrementPreservesPromotion(Object x) {
+  if (x is int) {
+    -- /*int*/ x;
+    /*int*/ x;
+  }
+}
+
+postDecrementPreservesPromotion(Object x) {
+  if (x is int) {
+    /*int*/ x--;
+    /*int*/ x;
+  }
+}
+
+class C {
+  Object operator +(int i) => 'foo';
+  Object operator -(int i) => 'foo';
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart
new file mode 100644
index 0000000..051be11
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/assignment_promoted.dart
@@ -0,0 +1,57 @@
+// 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.
+
+notATypeOfInterest(Object x) {
+  x = 1;
+  x;
+}
+
+typeOfInterest_is(Object x) {
+  if (x is int) {
+  } else {
+    x = 1;
+    /*int*/ x;
+  }
+  /*int*/ x;
+}
+
+typeOfInterest_isNot(Object x) {
+  if (x is! int) {
+    x = 1;
+    /*int*/ x;
+  }
+  /*int*/ x;
+}
+
+notATypeOfInterest_nullability(Object? x) {
+  x = 1;
+  x;
+}
+
+typeOfInterest_notEqualNull(Object? x) {
+  if (x != null) {
+  } else {
+    x = 1;
+    /*Object*/ x;
+  }
+  /*Object*/ x;
+}
+
+typeOfInterest_equalNull(Object? x) {
+  if (x == null) {
+    x = 1;
+    /*Object*/ x;
+  }
+  /*Object*/ x;
+}
+
+typeOfInterest_nullAwareAssignment(Object? x) {
+  x ??= 1;
+  /*Object*/ x;
+}
+
+typeOfInterest_ifNullExpression(Object? x) {
+  x ?? (x = 1);
+  /*Object*/ x;
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/binary.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/binary.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/binary.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/binary.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug39178.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug39178.dart
new file mode 100644
index 0000000..f5d7284
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug39178.dart
@@ -0,0 +1,28 @@
+// 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.
+
+f(Object x, bool b) {
+  if (x is num) {
+    if (/*num*/ x is int) {
+      try {
+        throw 'foo';
+      } catch (e) {
+        x = 1.5;
+        if (b) throw 'baz';
+        x = 0;
+      } finally {
+        // Note: on entry to the "finally", flow analysis
+        // conservatively de-promotes any variables that were assigned
+        // earlier in the statement, on the grounds that whatever type
+        // they are promoted to now, there's no guarantee that they
+        // had that type throughout execution of the try block.  In
+        // this particular case that's over-conservative--we could in
+        // principle keep the promotion to "num", since the value
+        // assigned is compatible with "num").  But it doesn't seem
+        // worth the extra analysis cost to do so.
+        x;
+      }
+    }
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
new file mode 100644
index 0000000..b71d9fb
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
@@ -0,0 +1,21 @@
+// 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.
+
+void conditional_both(bool b, Object x) {
+  b ? ((x is num) || (throw 1)) : ((x is int) || (throw 2));
+  x;
+}
+
+void conditional_else(bool b, Object x) {
+  b ? 0 : ((x is int) || (throw 2));
+  x;
+}
+
+void conditional_then(bool b, Object x) {
+  b ? ((x is num) || (throw 1)) : 0;
+  x;
+}
+
+int conditional_in_expression_function_body(Object o) =>
+    o is int ? /*int*/ o : 0;
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/constructor_initializer.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/constructor_initializer.dart
new file mode 100644
index 0000000..600ef92
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/constructor_initializer.dart
@@ -0,0 +1,10 @@
+// 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.
+
+class C {
+  int y;
+  C.normalInitializer(Object x) : y = x is int ? /*int*/ x : throw 'foo' {
+    /*int*/ x;
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/do.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/do.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/do.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/do.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/for.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/for.dart
new file mode 100644
index 0000000..ce22b16
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/for.dart
@@ -0,0 +1,185 @@
+// 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.
+
+Object g() => Null;
+
+void for_declaredVar() {
+  for (Object x = g(); x is int; x = g()) {
+    /*int*/ x;
+  }
+}
+
+void for_outerIsType(bool b, Object x) {
+  if (x is String) {
+    for (; b;) {
+      /*String*/ x;
+    }
+    /*String*/ x;
+  }
+}
+
+void for_outerIsType_loopAssigned_body(bool b, Object x) {
+  if (x is String) {
+    for (; b;) {
+      x;
+      x = 42;
+    }
+    x;
+  }
+}
+
+void for_outerIsType_loopAssigned_body_emptyCondition(bool b, Object x) {
+  if (x is String) {
+    for (;;) {
+      if (!b) break;
+      x;
+      x = 42;
+    }
+    x;
+  }
+}
+
+void for_outerIsType_loopAssigned_condition(Object x) {
+  if (x is String) {
+    for (; (x = 42) > 0;) {
+      x;
+    }
+    x;
+  }
+}
+
+void for_outerIsType_loopAssigned_updaters(bool b, Object x) {
+  if (x is String) {
+    for (; b; x = 42) {
+      x;
+    }
+    x;
+  }
+}
+
+void for_outerIsType_loopAssigned_updaters_emptyCondition(bool b, Object x) {
+  if (x is String) {
+    for (;; x = 42) {
+      if (!b) break;
+      x;
+    }
+    x;
+  }
+}
+
+void forEach_outerIsType_loopAssigned(Object x) {
+  if (x is String) {
+    for (var _ in [0, 1, 2]) {
+      x;
+      x = 42;
+    }
+    x;
+  }
+}
+
+void collection_for_declaredVar() {
+  [for (Object x = g(); x is int; x = g()) /*int*/ x ];
+}
+
+void collection_for_outerIsType(bool b, Object x) {
+  if (x is String) {
+    [for (; b;) /*String*/ x ];
+    /*String*/ x;
+  }
+}
+
+void collection_for_outerIsType_loopAssigned_body(bool b, Object x) {
+  if (x is String) {
+    [
+      for (; b;) [x, (x = 42)]
+    ];
+    x;
+  }
+}
+
+void collection_for_outerIsType_loopAssigned_body_emptyCondition(Object x) {
+  if (x is String) {
+    [
+      for (;;) [x, (x = 42)]
+    ];
+    x;
+  }
+}
+
+void collection_for_outerIsType_loopAssigned_condition(Object x) {
+  if (x is String) {
+    [for (; (x = 42) > 0;) x];
+    x;
+  }
+}
+
+void collection_for_outerIsType_loopAssigned_updaters(bool b, Object x) {
+  if (x is String) {
+    [for (; b; x = 42) x];
+    x;
+  }
+}
+
+void collection_for_outerIsType_loopAssigned_updaters_emptyCondition(Object x) {
+  if (x is String) {
+    [for (;; x = 42) x];
+    x;
+  }
+}
+
+void collection_forEach_outerIsType_loopAssigned(Object x) {
+  if (x is String) {
+    [
+      for (var _ in [0, 1, 2]) [x, (x = 42)]
+    ];
+    x;
+  }
+}
+
+void assign_var_declared_in_loop() {
+  for (int x = 0; x < 10; x++) {
+    bool b = true;
+    b = false;
+  }
+}
+
+void forEach_noDemotion(Object? x, List<int> y) {
+  if (x is int) {
+    /*int*/ x;
+    for (x in y) {
+      /*int*/ x;
+    }
+    /*int*/ x;
+  }
+}
+
+void forEach_partialDemotion(Object? x, List<num> y) {
+  if (x is num) {
+    if (/*num*/ x is int) {
+      /*int*/ x;
+      for (x in y) {
+        /*num*/ x;
+      }
+      /*num*/ x;
+    }
+  }
+}
+
+void collection_forEach_noDemotion(Object? x, List<int> y) {
+  if (x is int) {
+    /*int*/ x;
+    [for (x in y) /*int*/ x ];
+    /*int*/ x;
+  }
+}
+
+void collection_forEach_partialDemotion(Object? x, List<num> y) {
+  if (x is num) {
+    if (/*num*/ x is int) {
+      /*int*/ x;
+      [for (x in y) /*num*/ x ];
+      /*num*/ x;
+    }
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/function_expression.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/function_expression.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/function_expression.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/function_expression.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
new file mode 100644
index 0000000..5995cd1
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
@@ -0,0 +1,80 @@
+// 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.
+
+combine_empty(bool b, Object v) {
+  if (b) {
+    v is int || (throw 1);
+  } else {
+    v is String || (throw 2);
+  }
+  v;
+}
+
+conditional_isNotType(bool b, Object v) {
+  if (b ? (v is! int) : (v is! num)) {
+    v;
+  } else {
+    v;
+  }
+  v;
+}
+
+conditional_isType(bool b, Object v) {
+  if (b ? (v is int) : (v is num)) {
+    v;
+  } else {
+    v;
+  }
+  v;
+}
+
+isNotType(v) {
+  if (v is! String) {
+    v;
+  } else {
+    /*String*/ v;
+  }
+  v;
+}
+
+isNotType_return(v) {
+  if (v is! String) return;
+  /*String*/ v;
+}
+
+isNotType_throw(v) {
+  if (v is! String) throw 42;
+  /*String*/ v;
+}
+
+isType(v) {
+  if (v is String) {
+    /*String*/ v;
+  } else {
+    v;
+  }
+  v;
+}
+
+isType_thenNonBoolean(Object x) {
+  if ((x is String) != 3) {
+    x;
+  }
+}
+
+logicalNot_isType(v) {
+  if (!(v is String)) {
+    v;
+  } else {
+    /*String*/ v;
+  }
+  v;
+}
+
+void isNotType_return2(bool b, Object x) {
+  if (b) {
+    if (x is! String) return;
+  }
+  x;
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/initialization.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/initialization.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/inside_closure.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/inside_closure.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/inside_closure.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/inside_closure.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/not_promoted.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/not_promoted.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/not_promoted.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/not_promoted.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/null_aware_assignment.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/null_aware_assignment.dart
new file mode 100644
index 0000000..9b7f800
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/null_aware_assignment.dart
@@ -0,0 +1,88 @@
+// 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.
+
+unrelatedTypes(Object? x, String? y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    x;
+  }
+}
+
+unrelatedTypes_nonNull(Object? x, String y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    // TODO(paulberry): in principle we could promote x to Object.
+    // Should we?
+    x;
+  }
+}
+
+supertype_previouslyPromoted(Object? x, num? y) {
+  if (x is num?) {
+    if (/*num?*/ x is int?) {
+      /*int?*/ x ??= y;
+      /*num?*/ x;
+    }
+  }
+}
+
+supertype_previouslyPromoted_nonNull(Object? x, num y) {
+  if (x is num?) {
+    if (/*num?*/ x is int?) {
+      /*int?*/ x ??= y;
+      // TODO(paulberry): we don't promote to num because it's not a
+      // type of interest.  Should we consider it a type of interest
+      // so that x is known to be non-null here?
+      /*num?*/ x;
+    }
+  }
+}
+
+supertype_notPreviouslyPromoted(Object? x, num? y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    x;
+  }
+}
+
+supertype_notPreviouslyPromoted_nonNull(Object? x, num y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    // TODO(paulberry): we don't promote to Object because it's not a
+    // type of interest.  Should we consider it a type of interest
+    // so that x is known to be non-null here?
+  }
+}
+
+sameType(Object? x, int? y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    /*int?*/ x;
+  }
+}
+
+sameType_nonNull(Object? x, int y) {
+  if (x is int?) {
+    /*int?*/ x ??= y;
+    // The implicit null test in the `??=` makes `int` a type of
+    // interest for `x`, so it is promoted.
+    /*int*/ x;
+  }
+}
+
+subtype(Object? x, int? y) {
+  if (x is num?) {
+    /*num?*/ x ??= y;
+    /*num?*/ x;
+  }
+}
+
+subtype_nonNull(Object? x, int y) {
+  if (x is num?) {
+    /*num?*/ x ??= y;
+    // The implicit null test in the `??=` makes `num` a type of
+    // interest for `x`, so it is promoted.
+    /*num*/ x;
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/null_check.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/null_check.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/null_check.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/null_check.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/potentially_mutated.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/potentially_mutated.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/potentially_mutated.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/potentially_mutated.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/switch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/switch.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/switch.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/switch.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/try_catch.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_catch.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/try_catch.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_catch.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/try_catch_finally.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_catch_finally.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/try_catch_finally.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_catch_finally.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/try_finally.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_finally.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/try_finally.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/try_finally.dart
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
new file mode 100644
index 0000000..48fdaca
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
@@ -0,0 +1,41 @@
+// 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.
+
+class C<T extends num?> {
+  void promotes(T t) {
+    if (t is int) {
+      /*T & int*/ t;
+    }
+  }
+
+  void doesNotPromote(T t) {
+    if (t is String) {
+      t;
+    }
+  }
+
+  void nonNull(T t) {
+    if (t != null) {
+      /*T & num*/ t;
+    }
+  }
+}
+
+class D<T extends dynamic> {
+  void nonNull(T t) {
+    if (t != null) {
+      // Does not promote because the bound (`dynamic`) has no
+      // non-nullable counterpart
+      t;
+    }
+  }
+}
+
+class E<T> {
+  void nonNull(T t) {
+    if (t != null) {
+      /*T & Object*/ t;
+    }
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/while.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/while.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/while.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/while.dart
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/write_capture.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/write_capture.dart
similarity index 100%
rename from pkg/front_end/test/flow_analysis/type_promotion/data/write_capture.dart
rename to pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/write_capture.dart
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 5bf0c26..75207a9 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.27.3
+  1.27.4
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -432,7 +432,6 @@
   "params": {
     "<b>version</b>": String
     "<b>pid</b>": int
-    "<b>sessionId</b>": <span style="color:#999999">optional</span> String
   }
 }</pre></div>
     <p>
@@ -452,9 +451,6 @@
       </dd><dt class="field"><b>pid: int</b></dt><dd>
         
         <p>The process id of the analysis server process.</p>
-      </dd><dt class="field"><b>sessionId: String<span style="color:#999999"> (optional)</span></b></dt><dd>
-        
-        <p>The session id for this session.</p>
       </dd></dl></dd><dt class="notification"><a name="notification_server.error">server.error</a></dt><dd><div class="box"><pre>notification: {
   "event": "server.error"
   "params": {
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index 0054ab8..a4fccb5 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -151,7 +151,7 @@
     }
     parameters = element.parameters.toList();
   } else if (element is engine.FunctionTypeAliasElement) {
-    parameters = element.parameters.toList();
+    parameters = element.function.parameters.toList();
   } else {
     return null;
   }
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 55a6571..861f7a6 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.27.3';
+const String PROTOCOL_VERSION = '1.27.4';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -173,6 +173,7 @@
 const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
     'includeRequiredFixes';
 const String EDIT_REQUEST_DARTFIX_OUTPUT_DIR = 'outputDir';
+const String EDIT_REQUEST_DARTFIX_PORT = 'port';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
@@ -336,7 +337,6 @@
     'hierarchyItems';
 const String SERVER_NOTIFICATION_CONNECTED = 'server.connected';
 const String SERVER_NOTIFICATION_CONNECTED_PID = 'pid';
-const String SERVER_NOTIFICATION_CONNECTED_SESSION_ID = 'sessionId';
 const String SERVER_NOTIFICATION_CONNECTED_VERSION = 'version';
 const String SERVER_NOTIFICATION_ERROR = 'server.error';
 const String SERVER_NOTIFICATION_ERROR_IS_FATAL = 'isFatal';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 74a1344..9e8e335 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -7964,6 +7964,7 @@
  *   "includePedanticFixes": optional bool
  *   "includeRequiredFixes": optional bool
  *   "excludedFixes": optional List<String>
+ *   "port": optional int
  *   "outputDir": optional FilePath
  * }
  *
@@ -7980,6 +7981,8 @@
 
   List<String> _excludedFixes;
 
+  int _port;
+
   String _outputDir;
 
   /**
@@ -8070,6 +8073,20 @@
   }
 
   /**
+   * The port to be used to listen for and respond to http requests for preview
+   * pages.
+   */
+  int get port => _port;
+
+  /**
+   * The port to be used to listen for and respond to http requests for preview
+   * pages.
+   */
+  void set port(int value) {
+    this._port = value;
+  }
+
+  /**
    * The absolute and normalized path to a directory to which non-nullability
    * migration output will be written. The output is only produced if the
    * non-nullable fix is included. Files in the directory might be overwritten,
@@ -8092,12 +8109,14 @@
       bool includePedanticFixes,
       bool includeRequiredFixes,
       List<String> excludedFixes,
+      int port,
       String outputDir}) {
     this.included = included;
     this.includedFixes = includedFixes;
     this.includePedanticFixes = includePedanticFixes;
     this.includeRequiredFixes = includeRequiredFixes;
     this.excludedFixes = excludedFixes;
+    this.port = port;
     this.outputDir = outputDir;
   }
 
@@ -8134,6 +8153,10 @@
         excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
             json["excludedFixes"], jsonDecoder.decodeString);
       }
+      int port;
+      if (json.containsKey("port")) {
+        port = jsonDecoder.decodeInt(jsonPath + ".port", json["port"]);
+      }
       String outputDir;
       if (json.containsKey("outputDir")) {
         outputDir = jsonDecoder.decodeString(
@@ -8144,6 +8167,7 @@
           includePedanticFixes: includePedanticFixes,
           includeRequiredFixes: includeRequiredFixes,
           excludedFixes: excludedFixes,
+          port: port,
           outputDir: outputDir);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
@@ -8171,6 +8195,9 @@
     if (excludedFixes != null) {
       result["excludedFixes"] = excludedFixes;
     }
+    if (port != null) {
+      result["port"] = port;
+    }
     if (outputDir != null) {
       result["outputDir"] = outputDir;
     }
@@ -8196,6 +8223,7 @@
           includeRequiredFixes == other.includeRequiredFixes &&
           listEqual(excludedFixes, other.excludedFixes,
               (String a, String b) => a == b) &&
+          port == other.port &&
           outputDir == other.outputDir;
     }
     return false;
@@ -8209,6 +8237,7 @@
     hash = JenkinsSmiHash.combine(hash, includePedanticFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, port.hashCode);
     hash = JenkinsSmiHash.combine(hash, outputDir.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -22377,7 +22406,6 @@
  * {
  *   "version": String
  *   "pid": int
- *   "sessionId": optional String
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -22387,8 +22415,6 @@
 
   int _pid;
 
-  String _sessionId;
-
   /**
    * The version number of the analysis server.
    */
@@ -22415,22 +22441,9 @@
     this._pid = value;
   }
 
-  /**
-   * The session id for this session.
-   */
-  String get sessionId => _sessionId;
-
-  /**
-   * The session id for this session.
-   */
-  void set sessionId(String value) {
-    this._sessionId = value;
-  }
-
-  ServerConnectedParams(String version, int pid, {String sessionId}) {
+  ServerConnectedParams(String version, int pid) {
     this.version = version;
     this.pid = pid;
-    this.sessionId = sessionId;
   }
 
   factory ServerConnectedParams.fromJson(
@@ -22452,12 +22465,7 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "pid");
       }
-      String sessionId;
-      if (json.containsKey("sessionId")) {
-        sessionId = jsonDecoder.decodeString(
-            jsonPath + ".sessionId", json["sessionId"]);
-      }
-      return new ServerConnectedParams(version, pid, sessionId: sessionId);
+      return new ServerConnectedParams(version, pid);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "server.connected params", json);
     }
@@ -22473,9 +22481,6 @@
     Map<String, dynamic> result = {};
     result["version"] = version;
     result["pid"] = pid;
-    if (sessionId != null) {
-      result["sessionId"] = sessionId;
-    }
     return result;
   }
 
@@ -22489,9 +22494,7 @@
   @override
   bool operator ==(other) {
     if (other is ServerConnectedParams) {
-      return version == other.version &&
-          pid == other.pid &&
-          sessionId == other.sessionId;
+      return version == other.version && pid == other.pid;
     }
     return false;
   }
@@ -22501,7 +22504,6 @@
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, version.hashCode);
     hash = JenkinsSmiHash.combine(hash, pid.hashCode);
-    hash = JenkinsSmiHash.combine(hash, sessionId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server/lib/src/analysis_logger.dart b/pkg/analysis_server/lib/src/analysis_logger.dart
deleted file mode 100644
index 768ab01..0000000
--- a/pkg/analysis_server/lib/src/analysis_logger.dart
+++ /dev/null
@@ -1,55 +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:analysis_server/src/analysis_server.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:logging/logging.dart' as logging;
-
-/**
- * Instances of the class [AnalysisLogger] translate from the analysis engine's
- * API to the logging package's API.
- */
-class AnalysisLogger implements Logger {
-  /**
-   * The underlying logger that is being wrapped.
-   */
-  final logging.Logger baseLogger = new logging.Logger('analysis.server');
-
-  /**
-   * The analysis server that is using this logger.
-   */
-  final AnalysisServer server;
-
-  AnalysisLogger(this.server) {
-    assert(server != null);
-    logging.Logger.root.onRecord.listen((logging.LogRecord record) {
-      AnalysisEngine.instance.instrumentationService.logLogEntry(
-          record.level.name,
-          record.time,
-          record.message,
-          record.error,
-          record.stackTrace);
-    });
-  }
-
-  @override
-  void logError(String message, [CaughtException exception]) {
-    if (exception == null) {
-      baseLogger.severe(message);
-    } else {
-      baseLogger.severe(message, exception.exception, exception.stackTrace);
-    }
-    server.sendServerErrorNotification(message, exception, null);
-  }
-
-  @override
-  void logInformation(String message, [CaughtException exception]) {
-    if (exception == null) {
-      baseLogger.info(message);
-    } else {
-      baseLogger.info(message, exception.exception, exception.stackTrace);
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 799e3e7..f00140f 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -13,7 +13,6 @@
     show PROTOCOL_VERSION;
 import 'package:analysis_server/protocol/protocol_generated.dart'
     hide AnalysisOptions;
-import 'package:analysis_server/src/analysis_logger.dart';
 import 'package:analysis_server/src/analysis_server_abstract.dart';
 import 'package:analysis_server/src/channel/channel.dart';
 import 'package:analysis_server/src/computer/computer_highlights.dart';
@@ -193,6 +192,7 @@
     PluginWatcher pluginWatcher =
         new PluginWatcher(resourceProvider, pluginManager);
 
+    defaultContextOptions.enabledExperiments = options.enabledExperiments;
     defaultContextOptions.generateImplicitErrors = false;
     defaultContextOptions.useFastaParser = options.useFastaParser;
 
@@ -240,7 +240,6 @@
     ServerContextManagerCallbacks contextManagerCallbacks =
         new ServerContextManagerCallbacks(this, resourceProvider);
     contextManager.callbacks = contextManagerCallbacks;
-    AnalysisEngine.instance.logger = new AnalysisLogger(this);
     _onAnalysisStartedController = new StreamController.broadcast();
     onAnalysisStarted.first.then((_) {
       onAnalysisComplete.then((_) {
@@ -249,10 +248,8 @@
       });
     });
     searchEngine = new SearchEngineImpl(driverMap.values);
-    Notification notification = new ServerConnectedParams(
-            PROTOCOL_VERSION, io.pid,
-            sessionId: instrumentationService.sessionId)
-        .toNotification();
+    Notification notification =
+        new ServerConnectedParams(PROTOCOL_VERSION, io.pid).toNotification();
     channel.sendNotification(notification);
     channel.listen(handleRequest, onDone: done, onError: error);
     handlers = <server.RequestHandler>[
@@ -751,6 +748,10 @@
   /// should be accessed via a null-aware operator.
   CrashReportSender crashReportSender;
 
+  /// The list of the names of the experiments that should be enabled by
+  /// default, unless the analysis options file of a context overrides it.
+  List<String> enabledExperiments = const <String>[];
+
   /// Whether to use the Language Server Protocol.
   bool useLanguageServerProtocol = false;
 
@@ -894,7 +895,8 @@
       if (result.contextKey != null) {
         message += ' context: ${result.contextKey}';
       }
-      AnalysisEngine.instance.logger.logError(message, result.exception);
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.wrapInMessage(message, result.exception));
     });
     analysisServer.driverMap[folder] = analysisDriver;
     return analysisDriver;
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index f1a3a54..d631698 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -110,9 +110,9 @@
           _analyzedFilesGlobs
               .add(new Glob(resourceProvider.pathContext.separator, pattern));
         } catch (exception, stackTrace) {
-          AnalysisEngine.instance.logger.logError(
-              'Invalid glob pattern: "$pattern"',
-              new CaughtException(exception, stackTrace));
+          AnalysisEngine.instance.instrumentationService.logException(
+              new CaughtException.withMessage(
+                  'Invalid glob pattern: "$pattern"', exception, stackTrace));
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 0b0e009..8710ba5 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/uri_converter.dart';
@@ -19,7 +20,6 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
-import 'package:front_end/src/base/syntactic_entity.dart';
 import 'package:path/src/context.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 8b5d142..5d3c4f4 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -85,6 +85,7 @@
     CompletionRequestImpl request,
     CompletionGetSuggestionsParams params,
     Set<ElementKind> includedElementKinds,
+    Set<String> includedElementNames,
     List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
   ) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
@@ -112,6 +113,7 @@
 
       var manager = new DartCompletionManager(
         includedElementKinds: includedElementKinds,
+        includedElementNames: includedElementNames,
         includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
       );
 
@@ -346,9 +348,11 @@
     // If the client opted into using available suggestion sets,
     // create the kinds set, so signal the completion manager about opt-in.
     Set<ElementKind> includedElementKinds;
+    Set<String> includedElementNames;
     List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
     if (subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
       includedElementKinds = Set<ElementKind>();
+      includedElementNames = Set<String>();
       includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
     }
 
@@ -357,21 +361,22 @@
       completionRequest,
       params,
       includedElementKinds,
+      includedElementNames,
       includedSuggestionRelevanceTags,
     ).then((CompletionResult result) {
       String libraryFile;
-      List<IncludedSuggestionSet> includedSuggestionSets;
+      List<IncludedSuggestionSet> includedSuggestionSets = [];
       if (includedElementKinds != null && resolvedUnit != null) {
         libraryFile = resolvedUnit.libraryElement.source.fullName;
         server.sendNotification(
           createExistingImportsNotification(resolvedUnit),
         );
-        includedSuggestionSets = computeIncludedSetList(
+        computeIncludedSetList(
           server.declarationsTracker,
           resolvedUnit,
+          includedSuggestionSets,
+          includedElementNames,
         );
-      } else {
-        includedSuggestionSets = [];
       }
 
       const SEND_NOTIFICATION_TAG = 'send notification';
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index fd378e1..e059c7f 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -14,16 +14,17 @@
 /// include different sets, e.g. inside the `lib/` directory of a `Pub` package
 /// only regular dependencies can be referenced, but `test/` can reference
 /// both regular and "dev" dependencies.
-List<protocol.IncludedSuggestionSet> computeIncludedSetList(
+void computeIncludedSetList(
   DeclarationsTracker tracker,
   ResolvedUnitResult resolvedUnit,
+  List<protocol.IncludedSuggestionSet> includedSetList,
+  Set<String> includedElementNames,
 ) {
   var analysisContext = resolvedUnit.session.analysisContext;
   var context = tracker.getContext(analysisContext);
-  if (context == null) return const [];
+  if (context == null) return;
 
   var librariesObject = context.getLibraries(resolvedUnit.path);
-  var includedSetList = <protocol.IncludedSuggestionSet>[];
 
   var importedUriSet = resolvedUnit.libraryElement.importedLibraries
       .map((importedLibrary) => importedLibrary.source.uri)
@@ -51,6 +52,10 @@
         displayUri: _getRelativeFileUri(resolvedUnit, library.uri),
       ),
     );
+
+    for (var declaration in library.declarations) {
+      includedElementNames.add(declaration.name);
+    }
   }
 
   for (var library in librariesObject.context) {
@@ -64,8 +69,6 @@
   for (var library in librariesObject.sdk) {
     includeLibrary(library, 6, 0, 3);
   }
-
-  return includedSetList;
 }
 
 /// Convert the [LibraryChange] into the corresponding protocol notification.
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index e0c0b81..a13283c 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_information.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -76,9 +77,12 @@
     return units;
   }
 
-  /// Return details for a fix built from the given [edge], or `null` if the
-  /// edge does not have an origin.
-  String _baseDescriptionForOrigin(AstNode node) {
+  /// Return detail text for a fix built from an edge with [node] as a
+  /// destination.
+  String _baseDescriptionForOrigin(EdgeOriginInfo origin) {
+    AstNode node = origin.node;
+    AstNode parent = node.parent;
+
     if (node is DefaultFormalParameter) {
       Expression defaultValue = node.defaultValue;
       if (defaultValue == null) {
@@ -103,18 +107,18 @@
       }
       return "This field is initialized by a field formal parameter and a "
           "nullable value is passed as an argument";
+    } else if (parent is AsExpression) {
+      return "The value of the expression is nullable";
     }
-    AstNode parent = node.parent;
+    String nullableValue =
+        node is NullLiteral ? "an explicit 'null'" : "a nullable value";
     if (parent is ArgumentList) {
-      if (node is NullLiteral) {
-        return "An explicit 'null' is passed as an argument";
-      }
-      return "A nullable value is explicitly passed as an argument";
+      return capitalize("$nullableValue is passed as an argument");
     }
 
-    /// If the [node] is the return expression for a function body, return the
-    /// function body. Otherwise return `null`.
-    AstNode findFunctionBody() {
+    /// If the [node] is inside the return expression for a function body,
+    /// return the function body. Otherwise return `null`.
+    FunctionBody findFunctionBody() {
       if (parent is ExpressionFunctionBody) {
         return parent;
       } else {
@@ -126,39 +130,56 @@
       }
     }
 
-    AstNode functionBody = findFunctionBody();
+    /// If the [node] is inside a collection literal, return it. Otherwise
+    /// return `null`.
+    TypedLiteral findCollectionLiteral() {
+      AstNode ancestor = parent;
+      // Walk up collection elements, except for collection literals.
+      while (ancestor is CollectionElement && ancestor is! TypedLiteral) {
+        ancestor = ancestor.parent;
+      }
+      return (ancestor is TypedLiteral) ? ancestor : null;
+    }
+
+    CompilationUnit unit = node.thisOrAncestorOfType<CompilationUnit>();
+    int lineNumber = unit.lineInfo.getLocation(node.offset).lineNumber;
+    FunctionBody functionBody = findFunctionBody();
     if (functionBody != null) {
       AstNode function = functionBody.parent;
       if (function is MethodDeclaration) {
         if (function.isGetter) {
-          return "This getter returns a nullable value";
+          return "This getter returns $nullableValue on line $lineNumber";
         }
-        return "This method returns a nullable value";
+        return "This method returns $nullableValue on line $lineNumber";
       }
-      return "This function returns a nullable value";
+      return "This function returns $nullableValue on line $lineNumber";
+    }
+
+    TypedLiteral collectionLiteral = findCollectionLiteral();
+    if (collectionLiteral != null) {
+      if (collectionLiteral is ListLiteral) {
+        return "This list is initialized with $nullableValue on line "
+            "$lineNumber";
+      } else if (collectionLiteral is SetOrMapLiteral) {
+        var mapOrSet = collectionLiteral.isMap ? 'map' : 'set';
+        return "This $mapOrSet is initialized with $nullableValue on line "
+            "$lineNumber";
+      }
+    } else if (node is InvocationExpression &&
+        origin.kind == EdgeOriginKind.namedParameterNotSupplied) {
+      return "This named parameter was omitted in a call to this function";
     } else if (parent is VariableDeclaration) {
       AstNode grandparent = parent.parent?.parent;
       if (grandparent is FieldDeclaration) {
-        if (node is NullLiteral) {
-          return "This field is initialized to null";
-        }
-        return "This field is initialized to a nullable value";
+        return "This field is initialized to $nullableValue";
       }
-      if (node is NullLiteral) {
-        return "This variable is initialized to null";
-      }
-      return "This variable is initialized to a nullable value";
-    } else if (parent is AsExpression) {
-      return "The value of the expression is nullable";
+      return "This variable is initialized to $nullableValue";
     }
-    if (node is NullLiteral) {
-      return "An explicit 'null' is assigned";
-    }
-    return "A nullable value is assigned";
+    return capitalize("$nullableValue is assigned");
   }
 
-  /// Return details for a fix built from the given [edge], or `null` if the
-  /// edge does not have an origin.
+  /// Return detail text for a fix built from an edge with [node] as a
+  /// destination.
   String _buildDescriptionForDestination(AstNode node) {
     // Other found types:
     // - ConstructorDeclaration
@@ -170,9 +191,9 @@
   }
 
   /// Return a description of the given [origin].
-  String _buildDescriptionForOrigin(AstNode origin) {
+  String _buildDescriptionForOrigin(EdgeOriginInfo origin) {
     String description = _baseDescriptionForOrigin(origin);
-    if (_inTestCode(origin)) {
+    if (_inTestCode(origin.node)) {
       // TODO(brianwilkerson) Don't add this if the graph node with which the
       //  origin is associated is also in test code.
       description += " in test code";
@@ -198,7 +219,8 @@
           CompilationUnit unit = type.thisOrAncestorOfType<CompilationUnit>();
           target = _targetForNode(unit.declaredElement.source.fullName, type);
           return RegionDetail(
-              "The corresponding parameter in the overridden method is nullable",
+              "The corresponding parameter in the overridden method is "
+              "nullable",
               target);
           // TODO(srawlins): Also, this could be where a return type in an
           //  overridden method is made nullable because an overriding method
@@ -208,7 +230,7 @@
       }
       target = _targetForNode(origin.source.fullName, node);
     }
-    return RegionDetail(_buildDescriptionForOrigin(node), target);
+    return RegionDetail(_buildDescriptionForOrigin(origin), target);
   }
 
   /// Compute the details for the fix with the given [fixInfo].
@@ -272,6 +294,42 @@
     }).toList();
   }
 
+  /// Compute details about [edgeInfos] which are upstream triggered.
+  List<RegionDetail> _computeUpstreamTriggeredDetails(
+      Iterable<EdgeInfo> edgeInfos) {
+    List<RegionDetail> details = [];
+    for (var edge in edgeInfos) {
+      EdgeOriginInfo origin = info.edgeOrigin[edge];
+      if (origin == null) {
+        // TODO(https://github.com/dart-lang/sdk/issues/39203): I think this
+        //  shouldn't happen? But it does on the path package.
+        continue;
+      }
+      NavigationTarget target =
+          _targetForNode(origin.source.fullName, origin.node);
+      if (origin.kind == EdgeOriginKind.expressionChecks) {
+        details.add(RegionDetail(
+            'This value is unconditionally used in a non-nullable context',
+            target));
+      } else if (origin.kind == EdgeOriginKind.inheritance) {
+        // TODO(srawlins): Figure out why this EdgeOriginKind is used.
+        details.add(RegionDetail('Something about inheritance', target));
+      } else if (origin.kind == EdgeOriginKind.initializerInference) {
+        // TODO(srawlins): Figure out why this EdgeOriginKind is used.
+        details.add(
+            RegionDetail('Something about initializer inheritance', target));
+      } else if (origin.kind == EdgeOriginKind.nonNullAssertion) {
+        details
+            .add(RegionDetail('This value is asserted to be non-null', target));
+      } else if (origin.kind == EdgeOriginKind.nullabilityComment) {
+        details.add(RegionDetail(
+            'This type is annotated with a non-nullability comment ("/*!*/")',
+            target));
+      }
+    }
+    return details;
+  }
+
   /// Return the migration information for the unit associated with the
   /// [result].
   UnitInfo _explainUnit(SourceInformation sourceInfo, ResolvedUnitResult result,
@@ -281,35 +339,57 @@
       unitInfo.sources = _computeNavigationSources(result);
     }
     String content = result.content;
+    List<RegionInfo> regions = unitInfo.regions;
+
     // [fileEdit] is null when a file has no edits.
-    if (fileEdit != null) {
-      List<RegionInfo> regions = unitInfo.regions;
-      List<SourceEdit> edits = fileEdit.edits;
-      edits.sort((first, second) => first.offset.compareTo(second.offset));
-      OffsetMapper mapper = OffsetMapper.forEdits(edits);
-      // Apply edits in reverse order and build the regions.
-      for (SourceEdit edit in edits.reversed) {
-        int offset = edit.offset;
-        int length = edit.length;
-        String replacement = edit.replacement;
-        int end = offset + length;
-        // Insert the replacement text without deleting the replaced text.
-        content = content.replaceRange(end, end, replacement);
-        FixInfo fixInfo = _findFixInfo(sourceInfo, offset);
-        if (fixInfo != null) {
-          String explanation = '${fixInfo.fix.description.appliedMessage}.';
-          List<RegionDetail> details = _computeDetails(fixInfo);
-          if (length > 0) {
-            regions.add(
-                RegionInfo(mapper.map(offset), length, explanation, details));
-          }
-          regions.add(RegionInfo(
-              mapper.map(end), replacement.length, explanation, details));
+    List<SourceEdit> edits = fileEdit == null ? [] : List.of(fileEdit.edits);
+    edits.sort((first, second) => first.offset.compareTo(second.offset));
+    OffsetMapper mapper = OffsetMapper.forEdits(edits);
+
+    // Apply edits in reverse order and build the regions.
+    for (SourceEdit edit in edits.reversed) {
+      int offset = edit.offset;
+      int length = edit.length;
+      String replacement = edit.replacement;
+      int end = offset + length;
+      // Insert the replacement text without deleting the replaced text.
+      content = content.replaceRange(end, end, replacement);
+      FixInfo fixInfo = _findFixInfo(sourceInfo, offset);
+      if (fixInfo != null) {
+        String explanation = '${fixInfo.fix.description.appliedMessage}.';
+        List<RegionDetail> details = _computeDetails(fixInfo);
+        if (length > 0) {
+          regions.add(RegionInfo(mapper.map(offset), length, explanation,
+              details, RegionType.fix));
         }
+        regions.add(RegionInfo(mapper.map(end), replacement.length, explanation,
+            details, RegionType.fix));
       }
-      regions.sort((first, second) => first.offset.compareTo(second.offset));
-      unitInfo.offsetMapper = mapper;
     }
+    Iterable<MapEntry<TypeAnnotation, NullabilityNodeInfo>> nonNullableTypes =
+        sourceInfo.explicitTypeNullability.entries
+            .where((entry) => !entry.value.isNullable);
+    for (MapEntry<TypeAnnotation, NullabilityNodeInfo> nonNullableType
+        in nonNullableTypes) {
+      Iterable<EdgeInfo> upstreamTriggeredEdgeInfos = info.edgeOrigin.keys
+          .where((e) =>
+              e.sourceNode == nonNullableType.value &&
+              e.isUpstreamTriggered &&
+              !e.destinationNode.isNullable);
+      if (upstreamTriggeredEdgeInfos.isNotEmpty) {
+        List<RegionDetail> details =
+            _computeUpstreamTriggeredDetails(upstreamTriggeredEdgeInfos);
+        TypeAnnotation node = nonNullableType.key;
+        regions.add(RegionInfo(
+            mapper.map(node.offset),
+            node.length,
+            "This type is not changed; it is determined to be non-nullable",
+            details,
+            RegionType.nonNullableType));
+      }
+    }
+    regions.sort((first, second) => first.offset.compareTo(second.offset));
+    unitInfo.offsetMapper = mapper;
     unitInfo.content = content;
     return unitInfo;
   }
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index 8caa0b1..f539107 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -79,6 +79,10 @@
 
 .code {
   left: 0.5em;
+  /* Increase line height to make room for borders in non-nullable type
+   * regions.
+   */
+  line-height: 1.3;
   padding-left: 60px;
   position: absolute;
   top: 0.5em;
@@ -106,6 +110,7 @@
 
 .regions td {
   border: none;
+  line-height: 1.3;
   padding: 0;
   white-space: pre;
 }
@@ -116,6 +121,7 @@
 
 .regions td.line-no {
   color: #999999;
+  display: inline-block;
   padding-right: 4px;
   text-align: right;
   visibility: visible;
@@ -123,15 +129,27 @@
 }
 
 .region {
-  /* Green means this region was added. */
-  background-color: #ccffcc;
-  color: #003300;
   cursor: default;
   display: inline-block;
   position: relative;
   visibility: visible;
 }
 
+.region.fix-region {
+  /* Green means this region was added. */
+  background-color: #ccffcc;
+  color: #003300;
+}
+
+.region.non-nullable-type-region {
+  background-color: rgba(0, 0, 0, 0.3);
+  border-bottom: solid 2px #cccccc;
+  /* Invisible text; use underlying highlighting. */
+  color: rgba(0, 0, 0, 0);
+  /* Reduce line height to make room for border. */
+  line-height: 1;
+}
+
 .region .tooltip {
   background-color: #EEE;
   border: solid 2px #999;
@@ -334,7 +352,10 @@
         writeSplitLines(content.substring(previousOffset, offset));
         previousOffset = offset + length;
       }
-      regions.write('<span class="region">'
+      String regionClass = region.regionType == RegionType.fix
+          ? 'fix-region'
+          : 'non-nullable-type-region';
+      regions.write('<span class="region $regionClass">'
           '${content.substring(offset, offset + length)}'
           '<span class="tooltip">'
           '<p>${region.explanation}</p>');
@@ -403,14 +424,28 @@
   MigrationInfo(this.units, this.pathContext, this.includedRoot);
 
   /// The path to the highlight.js script, relative to [unitInfo].
-  String highlightJsPath(UnitInfo unitInfo) => pathContext.relative(
-      pathContext.join(includedRoot, '..', 'highlight.pack.js'),
-      from: pathContext.dirname(unitInfo.path));
+  String highlightJsPath(UnitInfo unitInfo) {
+    if (pathContext.isWithin(includedRoot, unitInfo.path)) {
+      return pathContext.relative(
+          pathContext.join(includedRoot, '..', 'highlight.pack.js'),
+          from: pathContext.dirname(unitInfo.path));
+    }
+    // Files that aren't within the [includedRoot] are written to the top-level
+    // of the output directory, next to the Javascript file.
+    return 'highlight.pack.js';
+  }
 
   /// The path to the highlight.js stylesheet, relative to [unitInfo].
-  String highlightStylePath(UnitInfo unitInfo) => pathContext.relative(
-      pathContext.join(includedRoot, '..', 'androidstudio.css'),
-      from: pathContext.dirname(unitInfo.path));
+  String highlightStylePath(UnitInfo unitInfo) {
+    if (pathContext.isWithin(includedRoot, unitInfo.path)) {
+      return pathContext.relative(
+          pathContext.join(includedRoot, '..', 'androidstudio.css'),
+          from: pathContext.dirname(unitInfo.path));
+    }
+    // Files that aren't within the [includedRoot] are written to the top-level
+    // of the output directory, next to the CSS file.
+    return 'androidstudio.css';
+  }
 
   /// Generate mustache context for unit links, for navigation in the
   /// instrumentation document for [thisUnit].
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
index e2ee753..3738015 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -88,8 +88,21 @@
   /// Details that further explain why a change was made.
   final List<RegionDetail> details;
 
+  /// Type type of region.
+  final RegionType regionType;
+
   /// Initialize a newly created region.
-  RegionInfo(this.offset, this.length, this.explanation, this.details);
+  RegionInfo(this.offset, this.length, this.explanation, this.details,
+      this.regionType);
+}
+
+/// Different types of regions that are called out.
+enum RegionType {
+  /// This is a region of code that was fixed (changed) in migration.
+  fix,
+
+  /// This is a type that was declared non-nullable in migration.
+  nonNullableType,
 }
 
 /// The migration information associated with a single compilation unit.
@@ -118,4 +131,13 @@
 
   /// Initialize a newly created unit.
   UnitInfo(this.path);
+
+  /// Returns the [regions] that represent a fixed (changed) region of code.
+  List<RegionInfo> get fixRegions =>
+      List.of(regions.where((region) => region.regionType == RegionType.fix));
+
+  /// Returns the [regions] that represent an unchanged type which was
+  /// determined to be non-null.
+  List<RegionInfo> get nonNullableTypeRegions => List.of(regions
+      .where((region) => region.regionType == RegionType.nonNullableType));
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index a41573e..f7af4f1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -166,13 +166,16 @@
           .toList();
 
       // Now compute items in suggestion sets.
-      List<IncludedSuggestionSet> includedSuggestionSets =
-          includedElementKinds == null || unit == null
-              ? const []
-              : computeIncludedSetList(
-                  server.declarationsTracker,
-                  unit,
-                );
+      List<IncludedSuggestionSet> includedSuggestionSets = [];
+      Set<String> includedElementNames = Set<String>();
+      if (includedElementKinds != null && unit != null) {
+        computeIncludedSetList(
+          server.declarationsTracker,
+          unit,
+          includedSuggestionSets,
+          includedElementNames,
+        );
+      }
 
       // Build a fast lookup for imported symbols so that we can filter out
       // duplicates.
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 0f6f7ab..535d6ae 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -625,7 +625,8 @@
       if (result.contextKey != null) {
         message += ' context: ${result.contextKey}';
       }
-      AnalysisEngine.instance.logger.logError(message, result.exception);
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.wrapInMessage(message, result.exception));
     });
     analysisServer.driverMap[folder] = analysisDriver;
     return analysisDriver;
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 431f959..dca523a 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -68,7 +68,7 @@
     engine.DartType type = element.type;
     return type != null ? type.displayName : 'dynamic';
   } else if (element is engine.FunctionTypeAliasElement) {
-    return element.returnType.toString();
+    return element.function.returnType.toString();
   } else {
     return null;
   }
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 02e74bc..b0baf27 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -75,6 +75,31 @@
         hide: hide);
   }
 
+  /// Defines an option that takes multiple values.
+  /// See [ArgParser.addMultiOption].
+  void addMultiOption(String name,
+      {String abbr,
+      String help,
+      String valueHelp,
+      Iterable<String> allowed,
+      Map<String, String> allowedHelp,
+      Iterable<String> defaultsTo,
+      void callback(List<String> values),
+      bool splitCommas = true,
+      bool hide = false}) {
+    _knownFlags.add(name);
+    _parser.addMultiOption(name,
+        abbr: abbr,
+        help: help,
+        valueHelp: valueHelp,
+        allowed: allowed,
+        allowedHelp: allowedHelp,
+        defaultsTo: defaultsTo,
+        callback: callback,
+        splitCommas: splitCommas,
+        hide: hide);
+  }
+
   /// Defines a value-taking option.
   /// See [ArgParser.addOption()].
   void addOption(String name,
@@ -213,6 +238,11 @@
       "disable-server-feature-search";
 
   /**
+   * The name of the option used to enable experiments.
+   */
+  static const String ENABLE_EXPERIMENT_OPTION = 'enable-experiment';
+
+  /**
    * The name of the option used to enable instrumentation.
    */
   static const String ENABLE_INSTRUMENTATION_OPTION = "enable-instrumentation";
@@ -346,6 +376,10 @@
     analysisServerOptions.clientId = results[CLIENT_ID];
     analysisServerOptions.clientVersion = results[CLIENT_VERSION];
     analysisServerOptions.cacheFolder = results[CACHE_FOLDER];
+    if (results.wasParsed(ENABLE_EXPERIMENT_OPTION)) {
+      analysisServerOptions.enabledExperiments =
+          (results[ENABLE_EXPERIMENT_OPTION] as List).cast<String>().toList();
+    }
     analysisServerOptions.useFastaParser = results[USE_FASTA_PARSER];
     analysisServerOptions.useLanguageServerProtocol = results[USE_LSP];
 
@@ -737,6 +771,11 @@
         help: 'disable all completion features', defaultsTo: false, hide: true);
     parser.addFlag(DISABLE_SERVER_FEATURE_SEARCH,
         help: 'disable all search features', defaultsTo: false, hide: true);
+    parser.addMultiOption(ENABLE_EXPERIMENT_OPTION,
+        help: 'Enable one or more experimental features. If multiple features '
+            'are being added, they should be comma separated.',
+        hide: true,
+        splitCommas: true);
     parser.addFlag(ENABLE_INSTRUMENTATION_OPTION,
         help: "enable sending instrumentation information to a server",
         defaultsTo: false,
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
index f3e4441..c601d7a 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_performance.dart
@@ -56,40 +56,12 @@
   }
 
   void setContentsAndOffset(String contents, int offset) {
-    snippet = _computeSnippet(contents, offset);
+    snippet = computeCompletionSnippet(contents, offset);
   }
 
   void _logDuration(String tag, Duration elapsed) {
     operations.add(new OperationPerformance(tag, elapsed));
   }
-
-  static String _computeSnippet(String contents, int offset) {
-    if (contents == null ||
-        offset == null ||
-        offset < 0 ||
-        contents.length < offset) {
-      return '???';
-    }
-    int start = offset;
-    while (start > 0) {
-      String ch = contents[start - 1];
-      if (ch == '\r' || ch == '\n') {
-        break;
-      }
-      --start;
-    }
-    int end = offset;
-    while (end < contents.length) {
-      String ch = contents[end];
-      if (ch == '\r' || ch == '\n') {
-        break;
-      }
-      ++end;
-    }
-    String prefix = contents.substring(start, offset);
-    String suffix = contents.substring(offset, end);
-    return '$prefix^$suffix';
-  }
 }
 
 /**
@@ -108,3 +80,37 @@
 
   OperationPerformance(this.name, this.elapsed);
 }
+
+/**
+ * Compute a string representing a code completion operation at the
+ * given source and location.
+ *
+ * This string is useful for displaying to users in a diagnostic context.
+ */
+String computeCompletionSnippet(String contents, int offset) {
+  if (contents == null ||
+      offset == null ||
+      offset < 0 ||
+      contents.length < offset) {
+    return '???';
+  }
+  int start = offset;
+  while (start > 0) {
+    String ch = contents[start - 1];
+    if (ch == '\r' || ch == '\n') {
+      break;
+    }
+    --start;
+  }
+  int end = offset;
+  while (end < contents.length) {
+    String ch = contents[end];
+    if (ch == '\r' || ch == '\n') {
+      break;
+    }
+    ++end;
+  }
+  String prefix = contents.substring(start, offset);
+  String suffix = contents.substring(offset, end);
+  return '$prefix^$suffix';
+}
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 1a90a96..626caf1 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
@@ -66,12 +66,18 @@
   final Set<protocol.ElementKind> includedElementKinds;
 
   /// If [includedElementKinds] is not null, must be also not `null`, and
+  /// will be filled with names of all top-level declarations from all
+  /// included suggestion sets.
+  final Set<String> includedElementNames;
+
+  /// If [includedElementKinds] is not null, must be also not `null`, and
   /// will be filled with tags for suggestions that should be given higher
   /// relevance than other included suggestions.
   final List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
 
   DartCompletionManager({
     this.includedElementKinds,
+    this.includedElementNames,
     this.includedSuggestionRelevanceTags,
   });
 
@@ -185,6 +191,7 @@
       suggestions = await ranking.rerank(
           probabilityFuture,
           suggestions,
+          includedElementNames,
           includedSuggestionRelevanceTags,
           dartRequest,
           request.result.unit.featureSet);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
index 5863601..8213781 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_ranking.dart
@@ -3,10 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:collection';
 import 'dart:isolate';
 
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_ranking_internal.dart';
 import 'package:analysis_server/src/services/completion/dart/language_model.dart';
 import 'package:analyzer/dart/analysis/features.dart';
@@ -17,8 +19,10 @@
 /// Minimum probability to prioritize model-only suggestion.
 const double _MODEL_RELEVANCE_CUTOFF = 0.5;
 
+// TODO(devoncarew): We need to explore the memory costs of running multiple ML
+// isolates.
 /// Number of code completion isolates.
-const int _ISOLATE_COUNT = 4;
+const int _ISOLATE_COUNT = 2;
 
 /// Prediction service run by the model isolate.
 void entrypoint(SendPort sendPort) {
@@ -53,6 +57,9 @@
   /// Pointer for round robin load balancing over isolates.
   int _index;
 
+  /// General performance metrics around ML completion.
+  final PerformanceMetrics performanceMetrics = PerformanceMetrics._();
+
   CompletionRanking(this._directory);
 
   /// Send an RPC to the isolate worker and wait for it to respond.
@@ -68,17 +75,32 @@
     return await port.first;
   }
 
-  /// Makes a next-token prediction starting at the completion request
-  /// cursor and walking back to find previous input tokens.
+  /// Makes a next-token prediction starting at the completion request cursor
+  /// and walking back to find previous input tokens.
   Future<Map<String, double>> predict(DartCompletionRequest request) async {
     final query = constructQuery(request, _LOOKBACK);
     if (query == null) {
-      return Future.value(null);
+      return Future.value();
     }
 
     request.checkAborted();
+
+    performanceMetrics._incrementPredictionRequestCount();
+
+    final Stopwatch timer = Stopwatch()..start();
     final response = await makeRequest('predict', query);
-    return response['data'];
+    timer.stop();
+
+    final Map<String, double> result = response['data'];
+
+    performanceMetrics._addPredictionResult(PredictionResult(
+      result,
+      timer.elapsed,
+      request.source.fullName,
+      computeCompletionSnippet(request.sourceContents, request.offset),
+    ));
+
+    return result;
   }
 
   /// Transforms [CompletionSuggestion] relevances and
@@ -87,6 +109,7 @@
   Future<List<CompletionSuggestion>> rerank(
       Future<Map<String, double>> probabilityFuture,
       List<CompletionSuggestion> suggestions,
+      Set<String> includedElementNames,
       List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
       DartCompletionRequest request,
       FeatureSet featureSet) async {
@@ -136,6 +159,7 @@
       final completionSuggestions = suggestions.where((suggestion) =>
           areCompletionsEquivalent(suggestion.completion, entry.key));
       List<IncludedSuggestionRelevanceTag> includedSuggestions;
+      final isIncludedElementName = includedElementNames.contains(entry.key);
       if (includedSuggestionRelevanceTags != null) {
         includedSuggestions = includedSuggestionRelevanceTags
             .where((tag) => areCompletionsEquivalent(
@@ -154,23 +178,30 @@
           includedSuggestions.forEach((includedSuggestion) {
             includedSuggestion.relevanceBoost = relevance;
           });
-        } else {
-          suggestions
-              .add(createCompletionSuggestion(entry.key, featureSet, high--));
+        } else if (isIncludedElementName) {
           if (includedSuggestionRelevanceTags != null) {
             includedSuggestionRelevanceTags
                 .add(IncludedSuggestionRelevanceTag(entry.key, relevance));
           }
+        } else {
+          suggestions
+              .add(createCompletionSuggestion(entry.key, featureSet, high--));
         }
       } else if (completionSuggestions.isNotEmpty ||
-          includedSuggestions.isNotEmpty) {
+          includedSuggestions.isNotEmpty ||
+          isIncludedElementName) {
         final relevance = middle--;
         completionSuggestions.forEach((completionSuggestion) {
           completionSuggestion.relevance = relevance;
         });
-        includedSuggestions.forEach((includedSuggestion) {
-          includedSuggestion.relevanceBoost = relevance;
-        });
+        if (includedSuggestions.isNotEmpty) {
+          includedSuggestions.forEach((includedSuggestion) {
+            includedSuggestion.relevanceBoost = relevance;
+          });
+        } else if (includedSuggestionRelevanceTags != null) {
+          includedSuggestionRelevanceTags
+              .add(IncludedSuggestionRelevanceTag(entry.key, relevance));
+        }
       } else if (allowModelOnlySuggestions) {
         final relevance = low--;
         suggestions
@@ -185,22 +216,70 @@
     return suggestions;
   }
 
-  /// Spins up the model isolate and tells it to load the tflite model.
+  /// Spin up the model isolates and load the tflite model.
   Future<void> start() async {
     this._writes = [];
     this._index = 0;
     final initializations = <Future<void>>[];
-    for (var i = 0; i < _ISOLATE_COUNT; i++) {
+
+    // Start the first isolate.
+    await _startIsolate();
+
+    // Start the 2nd and later isolates.
+    for (int i = 1; i < _ISOLATE_COUNT; i++) {
       initializations.add(_startIsolate());
     }
 
-    await Future.wait(initializations);
+    return Future.wait(initializations);
   }
 
   Future<void> _startIsolate() async {
+    final Stopwatch timer = Stopwatch()..start();
     final port = ReceivePort();
     await Isolate.spawn(entrypoint, port.sendPort);
     this._writes.add(await port.first);
-    await makeRequest('load', [_directory]);
+    return makeRequest('load', [_directory]).whenComplete(() {
+      timer.stop();
+      performanceMetrics._isolateInitTimes.add(timer.elapsed);
+    });
   }
 }
+
+class PerformanceMetrics {
+  static const int _maxResultBuffer = 50;
+
+  final Queue<PredictionResult> _predictionResults = Queue();
+  int _predictionRequestCount = 0;
+  final List<Duration> _isolateInitTimes = [];
+
+  PerformanceMetrics._();
+
+  List<Duration> get isolateInitTimes => _isolateInitTimes;
+
+  /// An iterable of the last `n` prediction results;
+  Iterable<PredictionResult> get predictionResults => _predictionResults;
+
+  /// The total prediction requests to ML Complete.
+  int get predictionRequestCount => _predictionRequestCount;
+
+  void _addPredictionResult(PredictionResult request) {
+    _predictionResults.addFirst(request);
+    if (_predictionResults.length > _maxResultBuffer) {
+      _predictionResults.removeLast();
+    }
+  }
+
+  void _incrementPredictionRequestCount() {
+    _predictionRequestCount++;
+  }
+}
+
+class PredictionResult {
+  final Map<String, double> results;
+  final Duration elapsedTime;
+  final String sourcePath;
+  final String snippet;
+
+  PredictionResult(
+      this.results, this.elapsedTime, this.sourcePath, this.snippet);
+}
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 8803712..4d38a9a 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
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
-import 'package:front_end/src/fasta/scanner.dart';
 
 /// Constructs a [CompletionSuggestion] object.
 CompletionSuggestion createCompletionSuggestion(
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/language_model.dart b/pkg/analysis_server/lib/src/services/completion/dart/language_model.dart
index 00308b0..8b90e92 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/language_model.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/language_model.dart
@@ -12,8 +12,10 @@
 
 /// Interface to TensorFlow-based Dart language model for next-token prediction.
 class LanguageModel {
-  static const _defaultCompletions = 100;
-  static final _numeric = RegExp(r'^\d+(.\d+)?$');
+  static const _probabilityThreshold = 0.0001;
+  static final _numeric = RegExp(r'^\d+(\.\d+)?$');
+  static final _alphanumeric = RegExp(r"^['\w]+$");
+  static final _doubleQuote = '"'.codeUnitAt(0);
 
   final tfl.Interpreter _interpreter;
   final Map<String, int> _word2idx;
@@ -26,9 +28,6 @@
   /// Number of previous tokens to look at during predictions.
   int get lookback => _lookback;
 
-  /// Number of completion results to return during predictions.
-  int get completions => _defaultCompletions;
-
   /// Load model from directory.
   factory LanguageModel.load(String directory) {
     // Load model.
@@ -85,7 +84,7 @@
       if (_word2idx.containsKey(token)) {
         return token;
       }
-      if (_numeric.hasMatch(token)) {
+      if (isNumber(token)) {
         return '<num>';
       }
       if (_isString(token)) {
@@ -110,6 +109,7 @@
     final probabilities = Float32List.view(bytes.buffer);
 
     final scores = Map<String, double>();
+    final scoresAboveThreshold = Map<String, double>();
     probabilities.asMap().forEach((k, v) {
       // x in 0, 1, ..., |V| - 1 correspond to specific members of the vocabulary.
       // x in |V|, |V| + 1, ..., |V| + 49 are pointers to reference positions along the
@@ -117,18 +117,39 @@
       if (k >= _idx2word.length + tokens.length) {
         return;
       }
+      // Find the name corresponding to this position along the network output.
       final lexeme =
           k < _idx2word.length ? _idx2word[k] : tokens[k - _idx2word.length];
-      final sanitized = lexeme.replaceAll('"', '\'');
-      scores[sanitized] = (scores[sanitized] ?? 0.0) + v;
+      // Normalize double to single quotes.
+      final sanitized = lexeme.codeUnitAt(0) != _doubleQuote
+          ? lexeme
+          : lexeme.replaceAll('"', '\'');
+      final score = (scores[sanitized] ?? 0.0) + v;
+      scores[sanitized] = score;
+      if (score < _probabilityThreshold ||
+          k >= _idx2word.length && !_isAlphanumeric(sanitized)) {
+        // Discard names below a fixed likelihood, and
+        // don't assign probability to punctuation by reference.
+        return;
+      }
+      scoresAboveThreshold[sanitized] = score;
     });
 
-    final entries = scores.entries.toList()
-      ..sort((a, b) => b.value.compareTo(a.value));
-    return Map.fromEntries(entries.sublist(0, completions));
+    return Map.fromEntries(scoresAboveThreshold.entries.toList()
+      ..sort((a, b) => b.value.compareTo(a.value)));
+  }
+
+  bool _isAlphanumeric(String token) {
+    // Note that _numeric covers integral and decimal values whereas
+    // _alphanumeric only matches integral values. Check both.
+    return _alphanumeric.hasMatch(token) || _numeric.hasMatch(token);
   }
 
   bool _isString(String token) {
     return token.indexOf('"') != -1 || token.indexOf("'") != -1;
   }
+
+  bool isNumber(String token) {
+    return _numeric.hasMatch(token) || token.startsWith('0x');
+  }
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 22ea7d3..c1b1a69 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -10,7 +10,7 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart'
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -609,7 +609,7 @@
         ? NullabilitySuffix.none
         : NullabilitySuffix.star;
 
-    return element.instantiate2(
+    return element.instantiate(
       typeArguments: typeArguments,
       nullabilitySuffix: nullabilitySuffix,
     );
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 e728015..0d36636 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -206,6 +206,8 @@
       return null;
     }
     type = element.returnType;
+  } else if (element is FunctionTypeAliasElement) {
+    type = element.function.returnType;
   } else if (element is VariableElement) {
     type = element.type;
   } else {
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index ace514e..51b65d6 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -125,6 +125,8 @@
       const AssistKind('dart.assist.encapsulateField', 30, "Encapsulate field");
   static const EXCHANGE_OPERANDS =
       const AssistKind('dart.assist.exchangeOperands', 30, "Exchange operands");
+
+  // Flutter assists
   static const FLUTTER_CONVERT_TO_CHILDREN = const AssistKind(
       'dart.assist.flutter.convert.childToChildren',
       30,
@@ -133,30 +135,38 @@
       'dart.assist.flutter.convert.toStatefulWidget',
       30,
       "Convert to StatefulWidget");
-  static const FLUTTER_MOVE_DOWN =
-      const AssistKind('dart.assist.flutter.move.down', 30, "Move widget down");
-  static const FLUTTER_MOVE_UP =
-      const AssistKind('dart.assist.flutter.move.up', 30, "Move widget up");
-  static const FLUTTER_REMOVE_WIDGET = const AssistKind(
-      'dart.assist.flutter.removeWidget', 30, "Remove this widget");
-  static const FLUTTER_SWAP_WITH_CHILD = const AssistKind(
-      'dart.assist.flutter.swap.withChild', 30, "Swap with child");
-  static const FLUTTER_SWAP_WITH_PARENT = const AssistKind(
-      'dart.assist.flutter.swap.withParent', 30, "Swap with parent");
-  static const FLUTTER_WRAP_CENTER =
-      const AssistKind('dart.assist.flutter.wrap.center', 30, "Center widget");
-  static const FLUTTER_WRAP_COLUMN = const AssistKind(
-      'dart.assist.flutter.wrap.column', 30, "Wrap with Column");
-  static const FLUTTER_WRAP_CONTAINER = const AssistKind(
-      'dart.assist.flutter.wrap.container', 30, "Wrap with Container");
+
+  // Flutter wrap specific assists
   static const FLUTTER_WRAP_GENERIC = const AssistKind(
-      'dart.assist.flutter.wrap.generic', 30, "Wrap with new widget");
-  static const FLUTTER_WRAP_PADDING =
-      const AssistKind('dart.assist.flutter.wrap.padding', 30, "Add padding");
+      'dart.assist.flutter.wrap.generic', 31, "Wrap with widget...");
+
+  static const FLUTTER_WRAP_CENTER = const AssistKind(
+      'dart.assist.flutter.wrap.center', 32, "Wrap with Center");
+  static const FLUTTER_WRAP_COLUMN = const AssistKind(
+      'dart.assist.flutter.wrap.column', 32, "Wrap with Column");
+  static const FLUTTER_WRAP_CONTAINER = const AssistKind(
+      'dart.assist.flutter.wrap.container', 32, "Wrap with Container");
+  static const FLUTTER_WRAP_PADDING = const AssistKind(
+      'dart.assist.flutter.wrap.padding', 32, "Wrap with Padding");
   static const FLUTTER_WRAP_ROW =
-      const AssistKind('dart.assist.flutter.wrap.row', 30, "Wrap with Row");
+      const AssistKind('dart.assist.flutter.wrap.row', 32, "Wrap with Row");
   static const FLUTTER_WRAP_STREAM_BUILDER = const AssistKind(
-      'dart.assist.flutter.wrap.streamBuilder', 30, "Wrap with StreamBuilder");
+      'dart.assist.flutter.wrap.streamBuilder', 32, "Wrap with StreamBuilder");
+
+  // Flutter re-order assists
+  static const FLUTTER_SWAP_WITH_CHILD = const AssistKind(
+      'dart.assist.flutter.swap.withChild', 33, "Swap with child");
+  static const FLUTTER_SWAP_WITH_PARENT = const AssistKind(
+      'dart.assist.flutter.swap.withParent', 33, "Swap with parent");
+  static const FLUTTER_MOVE_DOWN =
+      const AssistKind('dart.assist.flutter.move.down', 34, "Move widget down");
+  static const FLUTTER_MOVE_UP =
+      const AssistKind('dart.assist.flutter.move.up', 34, "Move widget up");
+
+  // Flutter remove assist
+  static const FLUTTER_REMOVE_WIDGET = const AssistKind(
+      'dart.assist.flutter.removeWidget', 35, "Remove this widget");
+
   static const IMPORT_ADD_SHOW = const AssistKind(
       'dart.assist.addShowCombinator', 30, "Add explicit 'show' combinator");
   static const INLINE_INVOCATION =
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 890f69a..415c89c 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -21,7 +21,6 @@
 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/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -231,6 +230,12 @@
     assists.add(new Assist(kind, change));
   }
 
+  Future<void> _addProposal_addDiagnosticPropertyReference() async {
+    final changeBuilder = await createBuilder_addDiagnosticPropertyReference();
+    _addAssistFromBuilder(
+        changeBuilder, DartAssistKind.ADD_DIAGNOSTIC_PROPERTY_REFERENCE);
+  }
+
   Future<void> _addProposal_addNotNullAssert() async {
     final identifier = this.node;
     if (identifier is SimpleIdentifier) {
@@ -1738,31 +1743,46 @@
 
       // Create the State subclass.
       builder.addInsertion(widgetClass.end, (builder) {
-        var stateType = stateClass.instantiate(
-          typeArguments: [
-            widgetClassElement.instantiate(
-              typeArguments: const [],
-              nullabilitySuffix: NullabilitySuffix.none,
-            ),
-          ],
-          nullabilitySuffix: NullabilitySuffix.none,
-        );
+        builder.writeln();
+        builder.writeln();
 
-        builder.writeln();
-        builder.writeln();
-        builder.writeClassDeclaration(stateName, superclass: stateType,
-            membersWriter: () {
-          bool writeEmptyLine = false;
-          for (var member in nodesToMove) {
-            if (writeEmptyLine) {
-              builder.writeln();
+        var typeParams = '';
+        if (widgetClass.typeParameters != null) {
+          typeParams = utils.getNodeText(widgetClass.typeParameters);
+        }
+
+        builder.write('class $stateName$typeParams extends ');
+        builder.writeReference(stateClass);
+
+        // Write just param names (and not bounds, metadata and docs).
+        builder.write('<${widgetClass.name}');
+        if (widgetClass.typeParameters != null) {
+          builder.write('<');
+          var first = true;
+          for (var param in widgetClass.typeParameters.typeParameters) {
+            if (!first) {
+              builder.write(', ');
+              first = false;
             }
-            String text = rewriteWidgetMemberReferences(member);
-            builder.write(text);
-            // Write empty lines between members, but not before the first.
-            writeEmptyLine = true;
+            builder.write(param.name.name);
           }
-        });
+          builder.write('>');
+        }
+
+        builder.writeln('> {');
+
+        bool writeEmptyLine = false;
+        for (var member in nodesToMove) {
+          if (writeEmptyLine) {
+            builder.writeln();
+          }
+          String text = rewriteWidgetMemberReferences(member);
+          builder.write(text);
+          // Write empty lines between members, but not before the first.
+          writeEmptyLine = true;
+        }
+
+        builder.write('}');
       });
     });
     _addAssistFromBuilder(
@@ -3168,12 +3188,6 @@
     _addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
   }
 
-  Future<void> _addProposal_addDiagnosticPropertyReference() async {
-    final changeBuilder = await createBuilder_addDiagnosticPropertyReference();
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.ADD_DIAGNOSTIC_PROPERTY_REFERENCE);
-  }
-
   Future<void> _addProposals_addTypeAnnotation() async {
     var changeBuilder =
         await createBuilder_addTypeAnnotation_DeclaredIdentifier();
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 78af2cc..845a405 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
@@ -6,7 +6,7 @@
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analysis_server/src/utilities/yaml_node_locator.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
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 cef444b..87a2d2e 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
@@ -5,7 +5,7 @@
 import 'dart:math' as math;
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
+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';
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 4b3d769..f2d2e4c 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
@@ -5,7 +5,7 @@
 import 'dart:math' as math;
 
 import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analysis_server/src/utilities/yaml_node_locator.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.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 389d63d..da04677 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -14,10 +14,10 @@
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/levenshtein.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
@@ -32,7 +32,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/error/inheritance_override.dart';
@@ -1896,7 +1895,6 @@
     String targetClassName = targetClassElement.name;
     // add proposals for all super constructors
     for (ConstructorElement superConstructor in superType.constructors) {
-      superConstructor = ConstructorMember.from(superConstructor, superType);
       String constructorName = superConstructor.name;
       // skip private
       if (Identifier.isPrivateName(constructorName)) {
@@ -2821,11 +2819,13 @@
   }
 
   Future<void> _addFix_importLibrary_withExtension() async {
-    String extensionName = (node as SimpleIdentifier).name;
-    await _addFix_importLibrary_withElement(
-        extensionName,
-        const [ElementKind.EXTENSION],
-        const [TopLevelDeclarationKind.extension]);
+    if (node is SimpleIdentifier) {
+      String extensionName = (node as SimpleIdentifier).name;
+      await _addFix_importLibrary_withElement(
+          extensionName,
+          const [ElementKind.EXTENSION],
+          const [TopLevelDeclarationKind.extension]);
+    }
   }
 
   Future<void> _addFix_importLibrary_withFunction() async {
diff --git a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
index 284acbb..ccd8182 100644
--- a/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
+++ b/pkg/analysis_server/lib/src/services/correction/name_suggestion.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
index 15f2a75..a4909a8 100644
--- a/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
+++ b/pkg/analysis_server/lib/src/services/correction/organize_directives.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/error/error.dart';
@@ -17,7 +17,6 @@
   final String initialCode;
   final CompilationUnit unit;
   final List<AnalysisError> errors;
-  final bool removeUnresolved;
   final bool removeUnused;
 
   String code;
@@ -25,7 +24,7 @@
   bool hasUnresolvedIdentifierError;
 
   DirectiveOrganizer(this.initialCode, this.unit, this.errors,
-      {this.removeUnresolved = true, this.removeUnused = true}) {
+      {this.removeUnused = true}) {
     this.code = initialCode;
     this.endOfLine = getEOL(code);
     this.hasUnresolvedIdentifierError = errors.any((error) {
@@ -49,18 +48,6 @@
     return edits;
   }
 
-  bool _isUnresolvedUri(UriBasedDirective directive) {
-    for (AnalysisError error in errors) {
-      ErrorCode errorCode = error.errorCode;
-      if ((errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST ||
-              errorCode == CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED) &&
-          directive.uri.offset == error.offset) {
-        return true;
-      }
-    }
-    return false;
-  }
-
   bool _isUnusedImport(UriBasedDirective directive) {
     for (AnalysisError error in errors) {
       if ((error.errorCode == HintCode.DUPLICATE_IMPORT ||
@@ -125,9 +112,6 @@
       for (_DirectiveInfo directiveInfo in directives) {
         if (!hasUnresolvedIdentifierError) {
           UriBasedDirective directive = directiveInfo.directive;
-          if (removeUnresolved && _isUnresolvedUri(directive)) {
-            continue;
-          }
           if (removeUnused && _isUnusedImport(directive)) {
             continue;
           }
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 51f43ab..dd2bc5c 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 
diff --git a/pkg/analysis_server/lib/src/services/correction/strings.dart b/pkg/analysis_server/lib/src/services/correction/strings.dart
deleted file mode 100644
index 87b6fe3..0000000
--- a/pkg/analysis_server/lib/src/services/correction/strings.dart
+++ /dev/null
@@ -1,200 +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 'dart:math';
-
-import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
-
-/**
- * "$"
- */
-const int CHAR_DOLLAR = 0x24;
-
-/**
- * "_"
- */
-const int CHAR_UNDERSCORE = 0x5F;
-
-String capitalize(String str) {
-  if (isEmpty(str)) {
-    return str;
-  }
-  return str.substring(0, 1).toUpperCase() + str.substring(1);
-}
-
-int compareStrings(String a, String b) {
-  if (a == b) {
-    return 0;
-  }
-  if (a == null) {
-    return 1;
-  }
-  if (b == null) {
-    return -1;
-  }
-  return a.compareTo(b);
-}
-
-/**
- * Return a simple difference between the given [oldStr] and [newStr].
- */
-SimpleDiff computeSimpleDiff(String oldStr, String newStr) {
-  int prefixLength = findCommonPrefix(oldStr, newStr);
-  int suffixLength = findCommonSuffix(oldStr, newStr);
-  while (prefixLength >= 0) {
-    int oldReplaceLength = oldStr.length - prefixLength - suffixLength;
-    int newReplaceLength = newStr.length - prefixLength - suffixLength;
-    if (oldReplaceLength >= 0 && newReplaceLength >= 0) {
-      return new SimpleDiff(prefixLength, oldReplaceLength,
-          newStr.substring(prefixLength, newStr.length - suffixLength));
-    }
-    prefixLength--;
-  }
-  return new SimpleDiff(0, oldStr.length, newStr);
-}
-
-int countLeadingWhitespaces(String str) {
-  int i = 0;
-  for (; i < str.length; i++) {
-    int c = str.codeUnitAt(i);
-    if (!isWhitespace(c)) {
-      break;
-    }
-  }
-  return i;
-}
-
-/**
- * Counts how many times [sub] appears in [str].
- */
-int countMatches(String str, String sub) {
-  if (isEmpty(str) || isEmpty(sub)) {
-    return 0;
-  }
-  int count = 0;
-  int idx = 0;
-  while ((idx = str.indexOf(sub, idx)) != -1) {
-    count++;
-    idx += sub.length;
-  }
-  return count;
-}
-
-int countTrailingWhitespaces(String str) {
-  int i = 0;
-  for (; i < str.length; i++) {
-    int c = str.codeUnitAt(str.length - 1 - i);
-    if (!isWhitespace(c)) {
-      break;
-    }
-  }
-  return i;
-}
-
-/**
- * Return the number of characters common to the start of [a] and [b].
- */
-int findCommonPrefix(String a, String b) {
-  int n = min(a.length, b.length);
-  for (int i = 0; i < n; i++) {
-    if (a.codeUnitAt(i) != b.codeUnitAt(i)) {
-      return i;
-    }
-  }
-  return n;
-}
-
-/**
- * Return the number of characters common to the end of [a] and [b].
- */
-int findCommonSuffix(String a, String b) {
-  int a_length = a.length;
-  int b_length = b.length;
-  int n = min(a_length, b_length);
-  for (int i = 1; i <= n; i++) {
-    if (a.codeUnitAt(a_length - i) != b.codeUnitAt(b_length - i)) {
-      return i - 1;
-    }
-  }
-  return n;
-}
-
-/**
- * Checks if [str] is `null`, empty or is whitespace.
- */
-bool isBlank(String str) {
-  if (str == null) {
-    return true;
-  }
-  if (str.isEmpty) {
-    return true;
-  }
-  return str.codeUnits.every(isSpace);
-}
-
-bool isDigit(int c) {
-  return c >= 0x30 && c <= 0x39;
-}
-
-bool isEOL(int c) {
-  return c == 0x0D || c == 0x0A;
-}
-
-bool isLetter(int c) {
-  return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
-}
-
-bool isLetterOrDigit(int c) {
-  return isLetter(c) || isDigit(c);
-}
-
-bool isSpace(int c) => c == 0x20 || c == 0x09;
-
-bool isWhitespace(int c) {
-  return isSpace(c) || isEOL(c);
-}
-
-String removeEnd(String str, String remove) {
-  if (isEmpty(str) || isEmpty(remove)) {
-    return str;
-  }
-  if (str.endsWith(remove)) {
-    return str.substring(0, str.length - remove.length);
-  }
-  return str;
-}
-
-String repeat(String s, int n) {
-  StringBuffer sb = new StringBuffer();
-  for (int i = 0; i < n; i++) {
-    sb.write(s);
-  }
-  return sb.toString();
-}
-
-/**
- * If the [text] length is above the [limit], replace the middle with `...`.
- */
-String shorten(String text, int limit) {
-  if (text.length > limit) {
-    int headLength = limit ~/ 2 - 1;
-    int tailLength = limit - headLength - 3;
-    return text.substring(0, headLength) +
-        '...' +
-        text.substring(text.length - tailLength);
-  }
-  return text;
-}
-
-/**
- * Information about a single replacement that should be made to convert the
- * "old" string to the "new" one.
- */
-class SimpleDiff {
-  final int offset;
-  final int length;
-  final String replacement;
-
-  SimpleDiff(this.offset, this.length, this.replacement);
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 4519397..723a3c4 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -6,7 +6,7 @@
 
 import 'package:analysis_server/src/protocol_server.dart'
     show doSourceChange_addElementEdit;
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
@@ -734,7 +734,7 @@
     // skip whitespace characters
     while (index < length) {
       int c = _buffer.codeUnitAt(index);
-      if (!isWhitespace(c) || c == 0x0D || c == 0x0A) {
+      if (!isWhitespace(c) || isEOL(c)) {
         break;
       }
       index++;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 6c0b9d4..64c7b28 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -8,12 +8,12 @@
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
 import 'package:analysis_server/src/services/correction/name_suggestion.dart';
 import 'package:analysis_server/src/services/correction/status.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 294ed47..de26a40 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -6,13 +6,13 @@
 
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
 import 'package:analysis_server/src/services/correction/status.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
 import 'package:analysis_server/src/services/refactoring/visible_ranges_computer.dart';
 import 'package:analysis_server/src/services/search/hierarchy.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/precedence.dart';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
index 8d99597..a4d2113 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/naming_conventions.dart
@@ -2,10 +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:_fe_analyzer_shared/src/scanner/token.dart' show Keyword;
 import 'package:analysis_server/src/services/correction/status.dart';
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
-import 'package:front_end/src/scanner/token.dart' show Keyword;
 
 /**
  * Returns the [RefactoringStatus] with severity:
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index ed8d65b..46ef35f 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -18,6 +18,7 @@
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/server/http_server.dart';
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_ranking.dart';
 import 'package:analysis_server/src/socket_server.dart';
 import 'package:analysis_server/src/status/ast_writer.dart';
 import 'package:analysis_server/src/status/element_writer.dart';
@@ -380,6 +381,100 @@
       completionDomain.performanceList.items.toList();
 }
 
+class MLCompletionPage extends DiagnosticPageWithNav {
+  final AbstractAnalysisServer server;
+
+  MLCompletionPage(DiagnosticsSite site, this.server)
+      : super(site, 'ml-completion', 'ML Completion',
+            description: 'Statistics for ML code completion.');
+
+  path.Context get pathContext => server.resourceProvider.pathContext;
+
+  @override
+  Future<void> generateContent(Map<String, String> params) async {
+    final bool hasMLComplete = CompletionRanking.instance != null;
+    if (!hasMLComplete) {
+      blankslate('''ML code completion is not enabled (see <a
+href="https://github.com/dart-lang/sdk/wiki/Previewing-Dart-code-completions-powered-by-machine-learning"
+>previewing Dart ML completion</a> for how to enable it).''');
+      return;
+    }
+
+    buf.writeln('ML completion enabled.<br>');
+
+    final String isolateTimes = CompletionRanking
+        .instance.performanceMetrics.isolateInitTimes
+        .map((Duration time) {
+      return '${time.inMilliseconds}ms';
+    }).join(', ');
+    p('ML isolate init times: $isolateTimes');
+
+    final List<PredictionResult> predictions = CompletionRanking
+        .instance.performanceMetrics.predictionResults
+        .toList();
+
+    if (predictions.isEmpty) {
+      blankslate('No completions recorded.');
+      return;
+    }
+
+    p('${CompletionRanking.instance.performanceMetrics.predictionRequestCount} '
+        'requests');
+
+    // draw a chart
+    buf.writeln(
+        '<div id="chart-div" style="width: 700px; height: 300px;"></div>');
+    StringBuffer rowData = new StringBuffer();
+    for (PredictionResult prediction in predictions.reversed) {
+      // [' ', 101.5]
+      if (rowData.isNotEmpty) {
+        rowData.write(',');
+      }
+      rowData.write("[' ', ${prediction.elapsedTime.inMilliseconds}]");
+    }
+    buf.writeln('''
+      <script type="text/javascript">
+      google.charts.load('current', {'packages':['bar']});
+      google.charts.setOnLoadCallback(drawChart);
+      function drawChart() {
+        var data = google.visualization.arrayToDataTable([
+          ['Completions', 'Time'],
+          $rowData
+        ]);
+        var options = { bars: 'vertical', vAxis: {format: 'decimal'}, height: 300 };
+        var chart = new google.charts.Bar(document.getElementById('chart-div'));
+        chart.draw(data, google.charts.Bar.convertOptions(options));
+      }
+      </script>
+''');
+
+    String summarize(PredictionResult prediction) {
+      List<MapEntry<String, double>> entries =
+          prediction.results.entries.toList();
+      entries.sort((a, b) => b.value.compareTo(a.value));
+      String summary = entries
+          .take(3)
+          .map((entry) => '"${entry.key}":${entry.value.toStringAsFixed(3)}')
+          .join('<br>');
+      return summary;
+    }
+
+    // emit the data as a table
+    buf.writeln('<table>');
+    buf.writeln(
+        '<tr><th>Time</th><th>Results</th><th>Snippet</th><th>Top suggestions</th></tr>');
+    for (PredictionResult prediction in predictions) {
+      buf.writeln('<tr>'
+          '<td class="pre right">${printMilliseconds(prediction.elapsedTime.inMilliseconds)}</td>'
+          '<td class="right">${prediction.results.length}</td>'
+          '<td><code>${escape(prediction.snippet)}</code></td>'
+          '<td class="right">${summarize(prediction)}</td>'
+          '</tr>');
+    }
+    buf.writeln('</table>');
+  }
+}
+
 class ContextsPage extends DiagnosticPageWithNav {
   ContextsPage(DiagnosticsSite site)
       : super(site, 'contexts', 'Contexts',
@@ -739,7 +834,9 @@
 
     // Add server-specific pages. Ordering doesn't matter as the items are
     // sorted later.
-    final server = this.socketServer.analysisServer;
+    final AbstractAnalysisServer server = this.socketServer.analysisServer;
+    pages.add(new MLCompletionPage(this, server));
+
     if (server is AnalysisServer) {
       pages.add(new CompletionPage(this, server));
       pages.add(new PluginsPage(this, server));
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index c91f46b..a7a8294 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -123,9 +123,6 @@
       properties['isDartCore'] = element.isDartCore;
       properties['isInSdk'] = element.isInSdk;
     }
-    if (element is LocalElement) {
-      properties['visibleRange'] = element.visibleRange;
-    }
     if (element is ParameterElement) {
       properties['defaultValueCode'] = element.defaultValueCode;
       properties['isInitializingFormal'] = element.isInitializingFormal;
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index 288d4fb..e014c44 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -333,6 +333,8 @@
         }
 
         if (parent is ArgumentList ||
+            parent is ConditionalExpression && parent.thenExpression == node ||
+            parent is ConditionalExpression && parent.elseExpression == node ||
             parent is ExpressionFunctionBody && parent.expression == node ||
             parent is ForElement && parent.body == node ||
             parent is IfElement && parent.thenElement == node ||
diff --git a/pkg/analysis_server/lib/src/utilities/strings.dart b/pkg/analysis_server/lib/src/utilities/strings.dart
new file mode 100644
index 0000000..70035be
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/strings.dart
@@ -0,0 +1,182 @@
+// 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 'dart:math';
+
+import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
+
+/// "$"
+const int CHAR_DOLLAR = 0x24;
+
+/// "_"
+const int CHAR_UNDERSCORE = 0x5F;
+
+String capitalize(String str) {
+  if (isEmpty(str)) {
+    return str;
+  }
+  return str.substring(0, 1).toUpperCase() + str.substring(1);
+}
+
+int compareStrings(String a, String b) {
+  if (a == b) {
+    return 0;
+  }
+  if (a == null) {
+    return 1;
+  }
+  if (b == null) {
+    return -1;
+  }
+  return a.compareTo(b);
+}
+
+/// Return a simple difference between the given [oldStr] and [newStr].
+SimpleDiff computeSimpleDiff(String oldStr, String newStr) {
+  int prefixLength = findCommonPrefix(oldStr, newStr);
+  int suffixLength = findCommonSuffix(oldStr, newStr);
+  while (prefixLength >= 0) {
+    int oldReplaceLength = oldStr.length - prefixLength - suffixLength;
+    int newReplaceLength = newStr.length - prefixLength - suffixLength;
+    if (oldReplaceLength >= 0 && newReplaceLength >= 0) {
+      return new SimpleDiff(prefixLength, oldReplaceLength,
+          newStr.substring(prefixLength, newStr.length - suffixLength));
+    }
+    prefixLength--;
+  }
+  return new SimpleDiff(0, oldStr.length, newStr);
+}
+
+int countLeadingWhitespaces(String str) {
+  int i = 0;
+  for (; i < str.length; i++) {
+    int c = str.codeUnitAt(i);
+    if (!isWhitespace(c)) {
+      break;
+    }
+  }
+  return i;
+}
+
+/// Counts how many times [sub] appears in [str].
+int countMatches(String str, String sub) {
+  if (isEmpty(str) || isEmpty(sub)) {
+    return 0;
+  }
+  int count = 0;
+  int idx = 0;
+  while ((idx = str.indexOf(sub, idx)) != -1) {
+    count++;
+    idx += sub.length;
+  }
+  return count;
+}
+
+int countTrailingWhitespaces(String str) {
+  int i = 0;
+  for (; i < str.length; i++) {
+    int c = str.codeUnitAt(str.length - 1 - i);
+    if (!isWhitespace(c)) {
+      break;
+    }
+  }
+  return i;
+}
+
+/// Returns the number of characters common to the start of [a] and [b].
+int findCommonPrefix(String a, String b) {
+  int n = min(a.length, b.length);
+  for (int i = 0; i < n; i++) {
+    if (a.codeUnitAt(i) != b.codeUnitAt(i)) {
+      return i;
+    }
+  }
+  return n;
+}
+
+/// Returns the number of characters common to the end of [a] and [b].
+int findCommonSuffix(String a, String b) {
+  int a_length = a.length;
+  int b_length = b.length;
+  int n = min(a_length, b_length);
+  for (int i = 1; i <= n; i++) {
+    if (a.codeUnitAt(a_length - i) != b.codeUnitAt(b_length - i)) {
+      return i - 1;
+    }
+  }
+  return n;
+}
+
+/// Checks if [str] is `null`, empty or is whitespace.
+bool isBlank(String str) {
+  if (str == null) {
+    return true;
+  }
+  if (str.isEmpty) {
+    return true;
+  }
+  return str.codeUnits.every(isSpace);
+}
+
+bool isDigit(int c) {
+  return c >= 0x30 && c <= 0x39;
+}
+
+bool isEOL(int c) {
+  return c == 0x0D || c == 0x0A;
+}
+
+bool isLetter(int c) {
+  return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A);
+}
+
+bool isLetterOrDigit(int c) {
+  return isLetter(c) || isDigit(c);
+}
+
+bool isSpace(int c) => c == 0x20 || c == 0x09;
+
+bool isWhitespace(int c) {
+  return isSpace(c) || isEOL(c);
+}
+
+String removeEnd(String str, String remove) {
+  if (isEmpty(str) || isEmpty(remove)) {
+    return str;
+  }
+  if (str.endsWith(remove)) {
+    return str.substring(0, str.length - remove.length);
+  }
+  return str;
+}
+
+String repeat(String s, int n) {
+  StringBuffer sb = new StringBuffer();
+  for (int i = 0; i < n; i++) {
+    sb.write(s);
+  }
+  return sb.toString();
+}
+
+/// If the [text] length is above the [limit], replace the middle with `...`.
+String shorten(String text, int limit) {
+  if (text.length > limit) {
+    int headLength = limit ~/ 2 - 1;
+    int tailLength = limit - headLength - 3;
+    return text.substring(0, headLength) +
+        '...' +
+        text.substring(text.length - tailLength);
+  }
+  return text;
+}
+
+/// Information about a single replacement that should be made to convert the
+/// "old" string to the "new" one.
+class SimpleDiff {
+  final int offset;
+  final int length;
+  final String replacement;
+
+  SimpleDiff(this.offset, this.length, this.replacement);
+}
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index b1e3156..33c00b4 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -202,7 +202,6 @@
 
   void tearDown() {
     AnalysisEngine.instance.clearCaches();
-    AnalysisEngine.instance.logger = null;
   }
 
   /// Update `/home/test/pubspec.yaml` and create the driver.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index 99d4666..ed5bec3 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/plugin/notification_manager.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/source/error_processor.dart';
@@ -2509,8 +2510,9 @@
 
     driverMap[path] = currentDriver;
     currentDriver.exceptions.listen((ExceptionResult result) {
-      AnalysisEngine.instance.logger
-          .logError('Analysis failed: ${result.path}', result.exception);
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.wrapInMessage(
+              'Analysis failed: ${result.path}', result.exception));
     });
     return currentDriver;
   }
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
index 87fed8c..b849d8b 100644
--- a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
@@ -39,11 +39,11 @@
   test_outputContainsEachPath() async {
     LibraryInfo info = LibraryInfo({
       unit('/package/lib/a.dart', 'int? a = null;',
-          regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+          regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
       unit('/package/lib/part1.dart', 'int? b = null;',
-          regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+          regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
       unit('/package/lib/part2.dart', 'int? c = null;',
-          regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+          regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
     });
     List<String> contents = renderLibrary(info);
     expect(contents[0], contains(resourceProvider.convertPath('lib/a.dart')));
@@ -55,13 +55,14 @@
 
   test_outputContainsEscapedHtml() async {
     LibraryInfo info = LibraryInfo({
-      unit('/package/lib/a.dart', 'List<String>? a = null;',
-          regions: [RegionInfo(12, 1, 'null was assigned', [])]),
+      unit('/package/lib/a.dart', 'List<String>? a = null;', regions: [
+        RegionInfo(12, 1, 'null was assigned', [], RegionType.fix)
+      ]),
     });
     String output = renderLibrary(info)[0];
     expect(
         output,
-        contains('List&lt;String&gt;<span class="region">?'
+        contains('List&lt;String&gt;<span class="region fix-region">?'
             '<span class="tooltip"><p>null was assigned</p>'
             '</span></span> a = null;'));
   }
@@ -77,12 +78,12 @@
   test_outputContainsModifiedAndUnmodifiedRegions() async {
     LibraryInfo info = LibraryInfo({
       unit('/package/lib/a.dart', 'int? a = null;',
-          regions: [RegionInfo(3, 1, 'null was assigned', [])]),
+          regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
     });
     String output = renderLibrary(info)[0];
     expect(
         output,
-        contains('int<span class="region">?'
+        contains('int<span class="region fix-region">?'
             '<span class="tooltip"><p>null was assigned</p>'
             '</span></span> a = null;'));
   }
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index 116427e..9c1373a 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -83,6 +83,22 @@
     );
   }
 
+  Future test_keep_unresolvedDirectives() {
+    var code = r'''
+import 'dart:noSuchImportSdkLibrary';
+
+import 'package:noSuchImportPackage/andLib.dart';
+
+export 'dart:noSuchExportSdkLibrary';
+
+export 'package:noSuchExportPackage/andLib.dart';
+
+part 'no_such_part.dart';
+''';
+    addTestFile(code);
+    return _assertOrganized(code);
+  }
+
   Future test_OK_remove_duplicateImports_withSamePrefix() {
     addTestFile('''
 library lib;
@@ -105,48 +121,6 @@
 ''');
   }
 
-  Future test_OK_remove_unresolvedDirectives() {
-    newFile(join(testFolder, 'existing_part1.dart'), content: 'part of lib;');
-    newFile(join(testFolder, 'existing_part2.dart'), content: 'part of lib;');
-    addTestFile('''
-library lib;
-
-export 'dart:noSuchExportSdkLibrary';
-export 'dart:async';
-export 'package:noSuchExportPackage/andLib.dart';
-export 'dart:math';
-
-import 'dart:async';
-import 'dart:noSuchImportSdkLibrary';
-import 'dart:math';
-import 'package:noSuchImportPackage/andLib.dart';
-
-part 'existing_part1.dart';
-part 'no_such_part.dart';
-part 'existing_part2.dart';
-
-main(Future f) {
-  print(PI);
-}
-''');
-    return _assertOrganized(r'''
-library lib;
-
-import 'dart:async';
-import 'dart:math';
-
-export 'dart:async';
-export 'dart:math';
-
-part 'existing_part1.dart';
-part 'existing_part2.dart';
-
-main(Future f) {
-  print(PI);
-}
-''');
-  }
-
   Future test_OK_remove_unusedImports() {
     addTestFile('''
 library lib;
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 1425c1d..7213f72 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -90,10 +90,6 @@
    * pid: int
    *
    *   The process id of the analysis server process.
-   *
-   * sessionId: String (optional)
-   *
-   *   The session id for this session.
    */
   Stream<ServerConnectedParams> onServerConnected;
 
@@ -1773,6 +1769,11 @@
    *   If a name is specified that does not match the name of a known fix, an
    *   error of type UNKNOWN_FIX will be generated.
    *
+   * port: int (optional)
+   *
+   *   The port to be used to listen for and respond to http requests for
+   *   preview pages.
+   *
    * outputDir: FilePath (optional)
    *
    *   The absolute and normalized path to a directory to which non-nullability
@@ -1814,12 +1815,14 @@
       bool includePedanticFixes,
       bool includeRequiredFixes,
       List<String> excludedFixes,
+      int port,
       String outputDir}) async {
     var params = new EditDartfixParams(included,
             includedFixes: includedFixes,
             includePedanticFixes: includePedanticFixes,
             includeRequiredFixes: includeRequiredFixes,
             excludedFixes: excludedFixes,
+            port: port,
             outputDir: outputDir)
         .toJson();
     var result = await server.send("edit.dartfix", params);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 4fd9c45..8b5bbf4 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -2561,6 +2561,7 @@
  *   "includePedanticFixes": optional bool
  *   "includeRequiredFixes": optional bool
  *   "excludedFixes": optional List<String>
+ *   "port": optional int
  *   "outputDir": optional FilePath
  * }
  */
@@ -2572,6 +2573,7 @@
           "includePedanticFixes": isBool,
           "includeRequiredFixes": isBool,
           "excludedFixes": isListOf(isString),
+          "port": isInt,
           "outputDir": isFilePath
         }));
 
@@ -3506,13 +3508,11 @@
  * {
  *   "version": String
  *   "pid": int
- *   "sessionId": optional String
  * }
  */
 final Matcher isServerConnectedParams = new LazyMatcher(() =>
     new MatchesJsonObject(
-        "server.connected params", {"version": isString, "pid": isInt},
-        optionalFields: {"sessionId": isString}));
+        "server.connected params", {"version": isString, "pid": isInt}));
 
 /**
  * server.error params
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 000ba70..4640b6d 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -57,8 +57,18 @@
     assertHas('f', ElementKind.FIELD, className: 'C');
     assertHas('named', ElementKind.CONSTRUCTOR, className: 'C');
     assertHas('g', ElementKind.GETTER, className: 'C');
-    assertHas('s', ElementKind.SETTER, className: 'C');
-    assertHas('m', ElementKind.METHOD, className: 'C');
+
+    {
+      var declaration = assertHas('s', ElementKind.SETTER, className: 'C');
+      expect(declaration.codeOffset, 59);
+      expect(declaration.codeLength, 16);
+    }
+
+    {
+      var declaration = assertHas('m', ElementKind.METHOD, className: 'C');
+      expect(declaration.codeOffset, 78);
+      expect(declaration.codeLength, 11);
+    }
   }
 
   test_enum() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/language_model_test.dart b/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
index d28165d..3fab0ee 100644
--- a/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/language_model_test.dart
@@ -37,7 +37,6 @@
     final tokens =
         tokenize('if (list == null) { return; } for (final i = 0; i < list.');
     final suggestions = model.predict(tokens);
-    expect(suggestions, hasLength(model.completions));
     expect(suggestions.first, 'length');
   });
 
@@ -48,7 +47,6 @@
     final best = suggestions.entries.first;
     expect(best.key, 'length');
     expect(best.value, greaterThan(0.85));
-    expect(suggestions, hasLength(model.completions));
   });
 
   test('predict when no previous tokens', () {
@@ -66,6 +64,15 @@
           e.toString(), equals('Invalid argument(s): Unable to create model.'));
     }
   });
+
+  test('isNumber', () {
+    expect(model.isNumber('0xCAb005E'), true);
+    expect(model.isNumber('foo'), false);
+    expect(model.isNumber('3.1415'), true);
+    expect(model.isNumber('1337'), true);
+    expect(model.isNumber('"four score and seven years ago"'), false);
+    expect(model.isNumber('0.0'), true);
+  });
 }
 
 /// Tokenizes the input string.
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index b2f4518..12db63d 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -61,7 +61,23 @@
 main() {
   async1.Future f;
   async2.Stream s;
-}''', removeUnresolved: true, removeUnused: true);
+}''', removeUnused: true);
+  }
+
+  test_keep_unresolvedDirectives() async {
+    var code = r'''
+import 'dart:noSuchImportSdkLibrary';
+
+import 'package:noSuchImportPackage/andLib.dart';
+
+export 'dart:noSuchExportSdkLibrary';
+
+export 'package:noSuchExportPackage/andLib.dart';
+
+part 'no_such_part.dart';
+''';
+    await _computeUnitAndErrors(code);
+    _assertOrganize(code);
   }
 
   test_remove_duplicateImports() async {
@@ -78,7 +94,7 @@
 
 main() {
   Future f;
-}''', removeUnresolved: true, removeUnused: true);
+}''', removeUnused: true);
   }
 
   test_remove_duplicateImports_differentText_uri() async {
@@ -95,7 +111,7 @@
 
 main() {
   async.Future f;
-}''', removeUnresolved: true, removeUnused: true);
+}''', removeUnused: true);
   }
 
   test_remove_duplicateImports_withSamePrefix() async {
@@ -112,48 +128,7 @@
 
 main() {
   async.Future f;
-}''', removeUnresolved: true, removeUnused: true);
-  }
-
-  test_remove_unresolvedDirectives() async {
-    addSource('/home/test/lib/existing_part1.dart', 'part of lib;');
-    addSource('/home/test/lib/existing_part2.dart', 'part of lib;');
-    await _computeUnitAndErrors(r'''
-library lib;
-
-import 'dart:async';
-import 'dart:noSuchImportSdkLibrary';
-import 'dart:math';
-import 'package:noSuchImportPackage/andLib.dart';
-
-export 'dart:noSuchExportSdkLibrary';
-export 'dart:async';
-export 'package:noSuchExportPackage/andLib.dart';
-export 'dart:math';
-
-part 'existing_part1.dart';
-part 'no_such_part.dart';
-part 'existing_part2.dart';
-
-main() {
-}
-''');
-    // validate change
-    _assertOrganize(r'''
-library lib;
-
-import 'dart:async';
-import 'dart:math';
-
-export 'dart:async';
-export 'dart:math';
-
-part 'existing_part1.dart';
-part 'existing_part2.dart';
-
-main() {
-}
-''', removeUnresolved: true);
+}''', removeUnused: true);
   }
 
   test_remove_unusedImports() async {
@@ -202,7 +177,7 @@
 
 main() {
   Future f;
-}''', removeUnresolved: true, removeUnused: true);
+}''', removeUnused: true);
   }
 
   test_remove_unusedImports_hasUnresolvedError() async {
@@ -340,11 +315,10 @@
 ''');
   }
 
-  void _assertOrganize(String expectedCode,
-      {bool removeUnresolved = false, bool removeUnused = false}) {
+  void _assertOrganize(String expectedCode, {bool removeUnused = false}) {
     DirectiveOrganizer organizer = new DirectiveOrganizer(
         testCode, testUnit, testErrors,
-        removeUnresolved: removeUnresolved, removeUnused: removeUnused);
+        removeUnused: removeUnused);
     List<SourceEdit> edits = organizer.organize();
     String result = SourceEdit.applySequence(testCode, edits);
     expect(result, expectedCode);
diff --git a/pkg/analysis_server/test/services/correction/strings_test.dart b/pkg/analysis_server/test/services/correction/strings_test.dart
deleted file mode 100644
index c55cb7b..0000000
--- a/pkg/analysis_server/test/services/correction/strings_test.dart
+++ /dev/null
@@ -1,161 +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:analysis_server/src/services/correction/strings.dart';
-import 'package:test/test.dart' hide isEmpty;
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(StringsTest);
-  });
-}
-
-@reflectiveTest
-class StringsTest {
-  void test_capitalize() {
-    expect(capitalize(''), '');
-    expect(capitalize('a'), 'A');
-    expect(capitalize('abc'), 'Abc');
-    expect(capitalize('abc def'), 'Abc def');
-    expect(capitalize('ABC'), 'ABC');
-  }
-
-  void test_compareStrings() {
-    expect(compareStrings(null, null), 0);
-    expect(compareStrings(null, 'b'), 1);
-    expect(compareStrings('a', null), -1);
-    expect(compareStrings('a', 'b'), -1);
-    expect(compareStrings('b', 'a'), 1);
-  }
-
-  void test_computeSimpleDiff() {
-    assertDiff(String oldStr, String newStr) {
-      SimpleDiff diff = computeSimpleDiff(oldStr, newStr);
-      expect(diff.offset, isNonNegative);
-      expect(diff.length, isNonNegative);
-      String applied = oldStr.substring(0, diff.offset) +
-          diff.replacement +
-          oldStr.substring(diff.offset + diff.length);
-      expect(applied, newStr);
-    }
-
-    assertDiff('', '');
-    assertDiff('', 'a');
-    assertDiff('abc', '');
-    assertDiff('abcd', 'acd');
-    assertDiff('a', 'b');
-    assertDiff('12345xyz', '12345abcxyz');
-    assertDiff('12345xyz', '12345xyzabc');
-    assertDiff('abbc', 'abbbc');
-    assertDiff('abbbbc', 'abbbbbbc');
-  }
-
-  void test_countMatches() {
-    expect(countMatches(null, null), 0);
-    expect(countMatches('abc', null), 0);
-    expect(countMatches(null, 'abc'), 0);
-    expect(countMatches('ababa', 'a'), 3);
-    expect(countMatches('ababa', 'ab'), 2);
-    expect(countMatches('aaabaa', 'aa'), 2);
-  }
-
-  void test_findCommonPrefix() {
-    expect(findCommonPrefix('abc', 'xyz'), 0);
-    expect(findCommonPrefix('1234abcdef', '1234xyz'), 4);
-    expect(findCommonPrefix('123', '123xyz'), 3);
-  }
-
-  void test_findCommonSuffix() {
-    expect(findCommonSuffix('abc', 'xyz'), 0);
-    expect(findCommonSuffix('abcdef1234', 'xyz1234'), 4);
-    expect(findCommonSuffix('123', 'xyz123'), 3);
-  }
-
-  void test_isBlank() {
-    expect(isBlank(null), isTrue);
-    expect(isBlank(''), isTrue);
-    expect(isBlank(' '), isTrue);
-    expect(isBlank('\t'), isTrue);
-    expect(isBlank('  '), isTrue);
-    expect(isBlank('X'), isFalse);
-  }
-
-  void test_isDigit() {
-    for (int c in '0123456789'.codeUnits) {
-      expect(isDigit(c), isTrue);
-    }
-    expect(isDigit(' '.codeUnitAt(0)), isFalse);
-    expect(isDigit('A'.codeUnitAt(0)), isFalse);
-  }
-
-  void test_isLetter() {
-    for (int c in 'abcdefghijklmnopqrstuvwxyz'.codeUnits) {
-      expect(isLetter(c), isTrue);
-    }
-    for (int c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.codeUnits) {
-      expect(isLetter(c), isTrue);
-    }
-    expect(isLetter(' '.codeUnitAt(0)), isFalse);
-    expect(isLetter('0'.codeUnitAt(0)), isFalse);
-  }
-
-  void test_isLetterOrDigit() {
-    for (int c in 'abcdefghijklmnopqrstuvwxyz'.codeUnits) {
-      expect(isLetterOrDigit(c), isTrue);
-    }
-    for (int c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.codeUnits) {
-      expect(isLetterOrDigit(c), isTrue);
-    }
-    for (int c in '0123456789'.codeUnits) {
-      expect(isLetterOrDigit(c), isTrue);
-    }
-    expect(isLetterOrDigit(' '.codeUnitAt(0)), isFalse);
-    expect(isLetterOrDigit('.'.codeUnitAt(0)), isFalse);
-  }
-
-  void test_isSpace() {
-    expect(isSpace(' '.codeUnitAt(0)), isTrue);
-    expect(isSpace('\t'.codeUnitAt(0)), isTrue);
-    expect(isSpace('\r'.codeUnitAt(0)), isFalse);
-    expect(isSpace('\n'.codeUnitAt(0)), isFalse);
-    expect(isSpace('0'.codeUnitAt(0)), isFalse);
-    expect(isSpace('A'.codeUnitAt(0)), isFalse);
-  }
-
-  void test_isWhitespace() {
-    expect(isWhitespace(' '.codeUnitAt(0)), isTrue);
-    expect(isWhitespace('\t'.codeUnitAt(0)), isTrue);
-    expect(isWhitespace('\r'.codeUnitAt(0)), isTrue);
-    expect(isWhitespace('\n'.codeUnitAt(0)), isTrue);
-    expect(isWhitespace('0'.codeUnitAt(0)), isFalse);
-    expect(isWhitespace('A'.codeUnitAt(0)), isFalse);
-  }
-
-  void test_removeEnd() {
-    expect(removeEnd(null, 'x'), null);
-    expect(removeEnd('abc', null), 'abc');
-    expect(removeEnd('www.domain.com', '.com.'), 'www.domain.com');
-    expect(removeEnd('www.domain.com', 'domain'), 'www.domain.com');
-    expect(removeEnd('www.domain.com', '.com'), 'www.domain');
-  }
-
-  void test_repeat() {
-    expect(repeat('x', 0), '');
-    expect(repeat('x', 5), 'xxxxx');
-    expect(repeat('abc', 3), 'abcabcabc');
-  }
-
-  void test_shorten() {
-    expect(shorten('', 10), '');
-    expect(shorten('0', 10), '0');
-    expect(shorten('012', 10), '012');
-    expect(shorten('0123456789', 10), '0123456789');
-    expect(shorten('0123456789abcd', 10), '0123...bcd');
-    expect(shorten('0123456789abcde', 10), '0123...cde');
-    expect(shorten('0123456789abcdef', 10), '0123...def');
-    expect(shorten('0123456789abcdef', 11), '0123...cdef');
-    expect(shorten('0123456789abcdef', 12), '01234...cdef');
-  }
-}
diff --git a/pkg/analysis_server/test/services/correction/test_all.dart b/pkg/analysis_server/test/services/correction/test_all.dart
index e098648..022ae48 100644
--- a/pkg/analysis_server/test/services/correction/test_all.dart
+++ b/pkg/analysis_server/test/services/correction/test_all.dart
@@ -10,7 +10,6 @@
 import 'organize_directives_test.dart' as organize_directives_test;
 import 'sort_members_test.dart' as sort_members_test;
 import 'status_test.dart' as status_test;
-import 'strings_test.dart' as strings_test;
 import 'util_test.dart' as util_test;
 
 /// Utility for manually running all tests.
@@ -22,7 +21,6 @@
     organize_directives_test.main();
     sort_members_test.main();
     status_test.main();
-    strings_test.main();
     util_test.main();
   }, name: 'correction');
 }
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index bc9a5e5..3be8718 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -95,22 +95,34 @@
     infos = (await builder.explainMigration()).toList();
   }
 
+  /// Uses the InfoBuilder to build information for a single test file.
+  ///
+  /// Asserts that [originalContent] is migrated to [migratedContent]. Returns
+  /// the singular UnitInfo which was built.
+  Future<UnitInfo> buildInfoForSingleTestFile(String originalContent,
+      {@required String migratedContent}) async {
+    addTestFile(originalContent);
+    await buildInfo();
+    expect(infos, hasLength(1));
+    UnitInfo unit = infos[0];
+    expect(unit.path, testFile);
+    expect(unit.content, migratedContent);
+    return unit;
+  }
+
   test_asExpression() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f([num a]) {
   int b = a as int;
 }
-''');
-    await buildInfo();
-    UnitInfo unit = infos[0];
-    expect(unit.content, '''
+''', migratedContent: '''
 void f([num? a]) {
   int? b = a as int?;
 }
 ''');
     List<RegionInfo> regions = unit.regions;
     expect(regions, hasLength(3));
-    assertRegion(region: regions[0], offset: 11);
+    // regions[0] is `num? a`.
     assertRegion(
         region: regions[1],
         offset: 24,
@@ -121,13 +133,30 @@
         details: ["The value of the expression is nullable"]);
   }
 
-  test_expressionFunctionReturnTarget() async {
-    addTestFile('''
-String g() => 1 == 2 ? "Hello" : null;
+  test_asExpression_insideReturn() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+int f([num a]) {
+  return a as int;
+}
+''', migratedContent: '''
+int? f([num? a]) {
+  return a as int?;
+}
 ''');
-    await buildInfo();
-    UnitInfo unit = infos[0];
-    expect(unit.content, '''
+    List<RegionInfo> regions = unit.regions;
+    expect(regions, hasLength(3));
+    // regions[0] is `inf? f`.
+    // regions[1] is `num? a`.
+    assertRegion(
+        region: regions[2],
+        offset: 36,
+        details: ["The value of the expression is nullable"]);
+  }
+
+  test_expressionFunctionReturnTarget() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+String g() => 1 == 2 ? "Hello" : null;
+''', migratedContent: '''
 String? g() => 1 == 2 ? "Hello" : null;
 ''');
     assertInTargets(targets: unit.targets, offset: 7, length: 1); // "g"
@@ -137,22 +166,17 @@
     assertRegion(
         region: regions[0],
         offset: 6,
-        details: ["This function returns a nullable value"]);
+        details: ["This function returns a nullable value on line 1"]);
     assertDetail(detail: regions[0].details[0], offset: 11, length: 2);
   }
 
   test_field_fieldFormalInitializer_optional() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   int _f;
   A([this._f]);
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   int? _f;
   A([this._f]);
@@ -167,7 +191,7 @@
   }
 
   test_field_fieldFormalInitializer_required() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   int _f;
   A(this._f);
@@ -175,12 +199,7 @@
 void g() {
   A(null);
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   int? _f;
   A(this._f);
@@ -189,7 +208,7 @@
   A(null);
 }
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     // TODO(brianwilkerson) It would be nice if the target for the region could
     //  be the argument rather than the field formal parameter.
@@ -200,17 +219,12 @@
   }
 
   test_field_initializer() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   int _f = null;
   int _f2 = _f;
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   int? _f = null;
   int? _f2 = _f;
@@ -221,25 +235,82 @@
     assertRegion(
         region: regions[0],
         offset: 15,
-        details: ["This field is initialized to null"]);
+        details: ["This field is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 33,
         details: ["This field is initialized to a nullable value"]);
   }
 
+  test_listAndSetLiteralTypeArgument() async {
+    // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+  String s = null;
+  List<String> x = <String>["hello", s];
+  Set<String> y = <String>{"hello", s};
+}
+''', migratedContent: '''
+void f() {
+  String? s = null;
+  List<String?> x = <String?>["hello", s];
+  Set<String?> y = <String?>{"hello", s};
+}
+''');
+    List<RegionInfo> regions = unit.fixRegions;
+    expect(regions, hasLength(5));
+    // regions[0] is the `String? s` fix.
+    // regions[1] is the `List<String?> x` fix.
+    assertRegion(
+        region: regions[2],
+        offset: 58,
+        details: ["This list is initialized with a nullable value on line 3"]);
+    assertDetail(detail: regions[2].details[0], offset: 67, length: 1);
+    // regions[3] is the `Set<String?> y` fix.
+    assertRegion(
+        region: regions[4],
+        offset: 100,
+        details: ["This set is initialized with a nullable value on line 4"]);
+    assertDetail(detail: regions[4].details[0], offset: 107, length: 1);
+  }
+
+  test_listLiteralTypeArgument_collectionIf() async {
+    // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+  String s = null;
+  List<String> x = <String>[
+    "hello",
+    if (1 == 2) s
+  ];
+}
+''', migratedContent: '''
+void f() {
+  String? s = null;
+  List<String?> x = <String?>[
+    "hello",
+    if (1 == 2) s
+  ];
+}
+''');
+    List<RegionInfo> regions = unit.fixRegions;
+    expect(regions, hasLength(3));
+    // regions[0] is the `String? s` fix.
+    // regions[1] is the `List<String?> x` fix.
+    assertRegion(
+        region: regions[2],
+        offset: 58,
+        details: ["This list is initialized with a nullable value on line 5"]);
+    assertDetail(detail: regions[2].details[0], offset: 88, length: 1);
+  }
+
   test_localVariable() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f() {
   int _v1 = null;
   int _v2 = _v1;
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f() {
   int? _v1 = null;
   int? _v2 = _v1;
@@ -250,25 +321,101 @@
     assertRegion(
         region: regions[0],
         offset: 16,
-        details: ["This variable is initialized to null"]);
+        details: ["This variable is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 35,
         details: ["This variable is initialized to a nullable value"]);
   }
 
+  test_mapLiteralTypeArgument() async {
+    // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+  String s = null;
+  Map<String, bool> x = <String, bool>{"hello": false, s: true};
+  Map<bool, String> y = <bool, String>{false: "hello", true: s};
+}
+''', migratedContent: '''
+void f() {
+  String? s = null;
+  Map<String?, bool> x = <String?, bool>{"hello": false, s: true};
+  Map<bool, String?> y = <bool, String?>{false: "hello", true: s};
+}
+''');
+    List<RegionInfo> regions = unit.fixRegions;
+    expect(regions, hasLength(5));
+    // regions[0] is the `String? s` fix.
+    // regions[1] is the `Map<String?, bool> x` fix.
+    assertRegion(
+        region: regions[2],
+        offset: 63,
+        details: ["This map is initialized with a nullable value on line 3"]);
+    assertDetail(detail: regions[2].details[0], offset: 85, length: 1);
+    // regions[3] is the `Map<bool, String?> y` fix.
+    assertRegion(
+        region: regions[4],
+        offset: 136,
+        details: ["This map is initialized with a nullable value on line 4"]);
+    assertDetail(detail: regions[4].details[0], offset: 156, length: 1);
+  }
+
+  test_nonNullableType_assert() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f(String s) {
+  assert(s != null);
+}
+''', migratedContent: '''
+void f(String s) {
+  assert(s != null);
+}
+''');
+    List<RegionInfo> regions = unit.nonNullableTypeRegions;
+    expect(regions, hasLength(1));
+    assertRegion(
+        region: regions[0],
+        offset: 7,
+        length: 6,
+        details: ["This value is asserted to be non-null"]);
+  }
+
+  test_nonNullableType_exclamationComment() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f(String /*!*/ s) {}
+''', migratedContent: '''
+void f(String /*!*/ s) {}
+''');
+    List<RegionInfo> regions = unit.nonNullableTypeRegions;
+    expect(regions, hasLength(1));
+    assertRegion(region: regions[0], offset: 7, length: 6, details: [
+      'This type is annotated with a non-nullability comment ("/*!*/")'
+    ]);
+  }
+
+  test_nonNullableType_unconditionalFieldAccess() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f(String s) {
+  print(s.length);
+}
+''', migratedContent: '''
+void f(String s) {
+  print(s.length);
+}
+''');
+    List<RegionInfo> regions = unit.nonNullableTypeRegions;
+    expect(regions, hasLength(1));
+    assertRegion(region: regions[0], offset: 7, length: 6, details: [
+      "This value is unconditionally used in a non-nullable context"
+    ]);
+  }
+
   test_parameter_fromInvocation_explicit() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f(String s) {}
 void g() {
   f(null);
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f(String? s) {}
 void g() {
   f(null);
@@ -287,17 +434,12 @@
     // Failing because the upstream edge ("always -(hard)-> type(13)")
     // associated with the reason (a _NullabilityNodeSimple) had a `null` origin
     // when the listener's `graphEdge` method was called.
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f(String s) {}
 void g(p) {
   f(p);
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f(String? s) {}
 void g(p) {
   f(p);
@@ -312,7 +454,7 @@
   }
 
   test_parameter_fromOverriden_explicit() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   void m(int p) {}
 }
@@ -322,12 +464,7 @@
 void f(A a) {
   a.m(null);
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   void m(int? p) {}
 }
@@ -338,7 +475,7 @@
   a.m(null);
 }
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(2));
     assertRegion(
         region: regions[0],
@@ -350,19 +487,14 @@
   }
 
   test_parameter_fromOverriden_implicit() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   void m(p) {}
 }
 class B extends A {
   void m(Object p) {}
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   void m(p) {}
 }
@@ -370,7 +502,7 @@
   void m(Object? p) {}
 }
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     // TODO(brianwilkerson) The detail should read something like
     //  "The overridden method accepts a nullable type"
@@ -380,21 +512,35 @@
         details: ["A nullable value is assigned"]);
   }
 
+  test_parameter_named_omittedInCall() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() { g(); }
+
+void g({int i}) {}
+''', migratedContent: '''
+void f() { g(); }
+
+void g({int? i}) {}
+''');
+    List<RegionInfo> regions = unit.fixRegions;
+    expect(regions, hasLength(1));
+    assertRegion(region: regions[0], offset: 30, details: [
+      "This named parameter was omitted in a call to this function",
+      "This parameter has an implicit default value of 'null'",
+    ]);
+    assertDetail(detail: regions[0].details[0], offset: 11, length: 3);
+  }
+
   @failingTest
   test_parameter_optional_explicitDefault_null() async {
     // Failing because we appear to never get an origin when the upstream node
     // for an edge is 'always'.
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f({String s = null}) {}
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f({String? s = null}) {}
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
@@ -406,19 +552,14 @@
   test_parameter_optional_explicitDefault_nullable() async {
     // Failing because we appear to never get an origin when the upstream node
     // for an edge is 'always'.
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 const sd = null;
 void f({String s = sd}) {}
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 const sd = null;
 void f({String? s = sd}) {}
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
@@ -427,17 +568,12 @@
   }
 
   test_parameter_optional_implicitDefault_named() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f({String s}) {}
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f({String? s}) {}
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
@@ -446,17 +582,12 @@
   }
 
   test_parameter_optional_implicitDefault_positional() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 void f([String s]) {}
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 void f([String? s]) {}
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
@@ -466,19 +597,14 @@
 
   @failingTest
   test_return_fromOverriden() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 abstract class A {
   String m();
 }
 class B implements A {
   String m() => 1 == 2 ? "Hello" : null;
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 abstract class A {
   String? m();
 }
@@ -486,7 +612,7 @@
   String? m() => 1 == 2 ? "Hello" : null;
 }
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(2));
     assertRegion(
         region: regions[0],
@@ -495,40 +621,34 @@
   }
 
   test_return_multipleReturns() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 String g() {
   int x = 1;
   if (x == 2) return x == 3 ? "Hello" : null;
   return "Hello";
 }
-''');
-    await buildInfo();
-    UnitInfo unit = infos[0];
-    expect(unit.content, '''
+''', migratedContent: '''
 String? g() {
   int x = 1;
   if (x == 2) return x == 3 ? "Hello" : null;
   return "Hello";
 }
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(1));
     assertRegion(
         region: regions[0],
         offset: 6,
-        details: ["This function returns a nullable value"]);
+        details: ["This function returns a nullable value on line 3"]);
     assertInTargets(targets: unit.targets, offset: 40, length: 6); // "return"
   }
 
   test_returnDetailTarget() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 String g() {
   return 1 == 2 ? "Hello" : null;
 }
-''');
-    await buildInfo();
-    UnitInfo unit = infos[0];
-    expect(unit.content, '''
+''', migratedContent: '''
 String? g() {
   return 1 == 2 ? "Hello" : null;
 }
@@ -540,20 +660,15 @@
     assertRegion(
         region: regions[0],
         offset: 6,
-        details: ["This function returns a nullable value"]);
+        details: ["This function returns a nullable value on line 2"]);
     assertDetail(detail: regions[0].details[0], offset: 15, length: 6);
   }
 
   test_returnType_function_expression() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 int _f = null;
 int f() => _f;
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 int? _f = null;
 int? f() => _f;
 ''');
@@ -562,27 +677,22 @@
     assertRegion(
         region: regions[0],
         offset: 3,
-        details: ["This variable is initialized to null"]);
+        details: ["This variable is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 19,
-        details: ["This function returns a nullable value"]);
+        details: ["This function returns a nullable value on line 2"]);
   }
 
   test_returnType_getter_block() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   int _f = null;
   int get f {
     return _f;
   }
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   int? _f = null;
   int? get f {
@@ -595,25 +705,20 @@
     assertRegion(
         region: regions[0],
         offset: 15,
-        details: ["This field is initialized to null"]);
+        details: ["This field is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 33,
-        details: ["This getter returns a nullable value"]);
+        details: ["This getter returns a nullable value on line 4"]);
   }
 
   test_returnType_getter_expression() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 class A {
   int _f = null;
   int get f => _f;
 }
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 class A {
   int? _f = null;
   int? get f => _f;
@@ -624,32 +729,59 @@
     assertRegion(
         region: regions[0],
         offset: 15,
-        details: ["This field is initialized to null"]);
+        details: ["This field is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 33,
-        details: ["This getter returns a nullable value"]);
+        details: ["This getter returns a nullable value on line 3"]);
+  }
+
+  test_setLiteralTypeArgument_nestedList() async {
+    // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+  String s = null;
+  Set<List<String>> x = <List<String>>{
+    ["hello"],
+    if (1 == 2) [s]
+  };
+}
+''', migratedContent: '''
+void f() {
+  String? s = null;
+  Set<List<String?>> x = <List<String?>>{
+    ["hello"],
+    if (1 == 2) [s]
+  };
+}
+''');
+    List<RegionInfo> regions = unit.fixRegions;
+    expect(regions, hasLength(3));
+    // regions[0] is the `String? s` fix.
+    // regions[1] is the `Set<List<String?>> x` fix.
+    assertRegion(
+        region: regions[2],
+        offset: 68,
+        details: ["This set is initialized with a nullable value on line 5"]);
+    // TODO(srawlins): Actually, this is marking the `[s]`, but I think only
+    //  `s` should be marked. Minor bug for now.
+    assertDetail(detail: regions[2].details[0], offset: 101, length: 3);
   }
 
   test_topLevelVariable() async {
-    addTestFile('''
+    UnitInfo unit = await buildInfoForSingleTestFile('''
 int _f = null;
 int _f2 = _f;
-''');
-    await buildInfo();
-    expect(infos, hasLength(1));
-    UnitInfo unit = infos[0];
-    expect(unit.path, testFile);
-    expect(unit.content, '''
+''', migratedContent: '''
 int? _f = null;
 int? _f2 = _f;
 ''');
-    List<RegionInfo> regions = unit.regions;
+    List<RegionInfo> regions = unit.fixRegions;
     expect(regions, hasLength(2));
     assertRegion(
         region: regions[0],
         offset: 3,
-        details: ["This variable is initialized to null"]);
+        details: ["This variable is initialized to an explicit 'null'"]);
     assertRegion(
         region: regions[1],
         offset: 19,
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index da0dd43..8d38b88 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -48,6 +48,35 @@
 ''');
   }
 
+  test_empty_typeParam() async {
+    addFlutterPackage();
+    await resolveTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget<T> extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+    await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget<T> extends StatefulWidget {
+  @override
+  _MyWidgetState createState() => _MyWidgetState();
+}
+
+class _MyWidgetState<T> extends State<MyWidget<T>> {
+  @override
+  Widget build(BuildContext context) {
+    return Container();
+  }
+}
+''');
+  }
+
   test_fields() async {
     addFlutterPackage();
     await resolveTestUnit(r'''
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 76ce8fe..af92890 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -309,6 +309,21 @@
     }
   }
 
+  test_identifyWidgetExpression_parent_conditionalExpression() async {
+    await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main(bool condition, Widget w1, Widget w2) {
+  condition ? w1 : w2;
+}
+''');
+    Expression thenWidget = findNodeAtString('w1 :');
+    expect(flutter.identifyWidgetExpression(thenWidget), thenWidget);
+
+    Expression elseWidget = findNodeAtString('w2;');
+    expect(flutter.identifyWidgetExpression(elseWidget), elseWidget);
+  }
+
   test_identifyWidgetExpression_parent_expressionFunctionBody() async {
     await resolveTestUnit('''
 import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/src/utilities/strings_test.dart b/pkg/analysis_server/test/src/utilities/strings_test.dart
new file mode 100644
index 0000000..d1c51f4
--- /dev/null
+++ b/pkg/analysis_server/test/src/utilities/strings_test.dart
@@ -0,0 +1,161 @@
+// 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:analysis_server/src/utilities/strings.dart';
+import 'package:test/test.dart' hide isEmpty;
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(StringsTest);
+  });
+}
+
+@reflectiveTest
+class StringsTest {
+  void test_capitalize() {
+    expect(capitalize(''), '');
+    expect(capitalize('a'), 'A');
+    expect(capitalize('abc'), 'Abc');
+    expect(capitalize('abc def'), 'Abc def');
+    expect(capitalize('ABC'), 'ABC');
+  }
+
+  void test_compareStrings() {
+    expect(compareStrings(null, null), 0);
+    expect(compareStrings(null, 'b'), 1);
+    expect(compareStrings('a', null), -1);
+    expect(compareStrings('a', 'b'), -1);
+    expect(compareStrings('b', 'a'), 1);
+  }
+
+  void test_computeSimpleDiff() {
+    assertDiff(String oldStr, String newStr) {
+      SimpleDiff diff = computeSimpleDiff(oldStr, newStr);
+      expect(diff.offset, isNonNegative);
+      expect(diff.length, isNonNegative);
+      String applied = oldStr.substring(0, diff.offset) +
+          diff.replacement +
+          oldStr.substring(diff.offset + diff.length);
+      expect(applied, newStr);
+    }
+
+    assertDiff('', '');
+    assertDiff('', 'a');
+    assertDiff('abc', '');
+    assertDiff('abcd', 'acd');
+    assertDiff('a', 'b');
+    assertDiff('12345xyz', '12345abcxyz');
+    assertDiff('12345xyz', '12345xyzabc');
+    assertDiff('abbc', 'abbbc');
+    assertDiff('abbbbc', 'abbbbbbc');
+  }
+
+  void test_countMatches() {
+    expect(countMatches(null, null), 0);
+    expect(countMatches('abc', null), 0);
+    expect(countMatches(null, 'abc'), 0);
+    expect(countMatches('ababa', 'a'), 3);
+    expect(countMatches('ababa', 'ab'), 2);
+    expect(countMatches('aaabaa', 'aa'), 2);
+  }
+
+  void test_findCommonPrefix() {
+    expect(findCommonPrefix('abc', 'xyz'), 0);
+    expect(findCommonPrefix('1234abcdef', '1234xyz'), 4);
+    expect(findCommonPrefix('123', '123xyz'), 3);
+  }
+
+  void test_findCommonSuffix() {
+    expect(findCommonSuffix('abc', 'xyz'), 0);
+    expect(findCommonSuffix('abcdef1234', 'xyz1234'), 4);
+    expect(findCommonSuffix('123', 'xyz123'), 3);
+  }
+
+  void test_isBlank() {
+    expect(isBlank(null), isTrue);
+    expect(isBlank(''), isTrue);
+    expect(isBlank(' '), isTrue);
+    expect(isBlank('\t'), isTrue);
+    expect(isBlank('  '), isTrue);
+    expect(isBlank('X'), isFalse);
+  }
+
+  void test_isDigit() {
+    for (int c in '0123456789'.codeUnits) {
+      expect(isDigit(c), isTrue);
+    }
+    expect(isDigit(' '.codeUnitAt(0)), isFalse);
+    expect(isDigit('A'.codeUnitAt(0)), isFalse);
+  }
+
+  void test_isLetter() {
+    for (int c in 'abcdefghijklmnopqrstuvwxyz'.codeUnits) {
+      expect(isLetter(c), isTrue);
+    }
+    for (int c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.codeUnits) {
+      expect(isLetter(c), isTrue);
+    }
+    expect(isLetter(' '.codeUnitAt(0)), isFalse);
+    expect(isLetter('0'.codeUnitAt(0)), isFalse);
+  }
+
+  void test_isLetterOrDigit() {
+    for (int c in 'abcdefghijklmnopqrstuvwxyz'.codeUnits) {
+      expect(isLetterOrDigit(c), isTrue);
+    }
+    for (int c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.codeUnits) {
+      expect(isLetterOrDigit(c), isTrue);
+    }
+    for (int c in '0123456789'.codeUnits) {
+      expect(isLetterOrDigit(c), isTrue);
+    }
+    expect(isLetterOrDigit(' '.codeUnitAt(0)), isFalse);
+    expect(isLetterOrDigit('.'.codeUnitAt(0)), isFalse);
+  }
+
+  void test_isSpace() {
+    expect(isSpace(' '.codeUnitAt(0)), isTrue);
+    expect(isSpace('\t'.codeUnitAt(0)), isTrue);
+    expect(isSpace('\r'.codeUnitAt(0)), isFalse);
+    expect(isSpace('\n'.codeUnitAt(0)), isFalse);
+    expect(isSpace('0'.codeUnitAt(0)), isFalse);
+    expect(isSpace('A'.codeUnitAt(0)), isFalse);
+  }
+
+  void test_isWhitespace() {
+    expect(isWhitespace(' '.codeUnitAt(0)), isTrue);
+    expect(isWhitespace('\t'.codeUnitAt(0)), isTrue);
+    expect(isWhitespace('\r'.codeUnitAt(0)), isTrue);
+    expect(isWhitespace('\n'.codeUnitAt(0)), isTrue);
+    expect(isWhitespace('0'.codeUnitAt(0)), isFalse);
+    expect(isWhitespace('A'.codeUnitAt(0)), isFalse);
+  }
+
+  void test_removeEnd() {
+    expect(removeEnd(null, 'x'), null);
+    expect(removeEnd('abc', null), 'abc');
+    expect(removeEnd('www.domain.com', '.com.'), 'www.domain.com');
+    expect(removeEnd('www.domain.com', 'domain'), 'www.domain.com');
+    expect(removeEnd('www.domain.com', '.com'), 'www.domain');
+  }
+
+  void test_repeat() {
+    expect(repeat('x', 0), '');
+    expect(repeat('x', 5), 'xxxxx');
+    expect(repeat('abc', 3), 'abcabcabc');
+  }
+
+  void test_shorten() {
+    expect(shorten('', 10), '');
+    expect(shorten('0', 10), '0');
+    expect(shorten('012', 10), '012');
+    expect(shorten('0123456789', 10), '0123456789');
+    expect(shorten('0123456789abcd', 10), '0123...bcd');
+    expect(shorten('0123456789abcde', 10), '0123...cde');
+    expect(shorten('0123456789abcdef', 10), '0123...def');
+    expect(shorten('0123456789abcdef', 11), '0123...cdef');
+    expect(shorten('0123456789abcdef', 12), '01234...cdef');
+  }
+}
diff --git a/pkg/analysis_server/test/src/utilities/test_all.dart b/pkg/analysis_server/test/src/utilities/test_all.dart
index 580e29b..1bfac03 100644
--- a/pkg/analysis_server/test/src/utilities/test_all.dart
+++ b/pkg/analysis_server/test/src/utilities/test_all.dart
@@ -6,10 +6,12 @@
 
 import 'flutter_test.dart' as flutter_test;
 import 'profiling_test.dart' as profiling_test;
+import 'strings_test.dart' as strings_test;
 
 main() {
   defineReflectiveSuite(() {
     flutter_test.main();
     profiling_test.main();
+    strings_test.main();
   });
 }
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 45a4e35..7257145 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:analysis_server/src/services/correction/strings.dart';
+import 'package:analysis_server/src/utilities/strings.dart';
 import 'package:args/args.dart';
 import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as path;
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 3c7e5ed..5cf10d9 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -4,8 +4,7 @@
 
 import 'dart:math';
 
-import 'package:analysis_server/src/services/correction/strings.dart'
-    show capitalize;
+import 'package:analysis_server/src/utilities/strings.dart' show capitalize;
 
 import 'codegen_dart.dart';
 import 'typescript.dart';
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index f4e3170..e2df2d3 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -498,12 +498,13 @@
    * @param excludedFixes A list of names indicating which fixes should not be applied. If a name is
    *         specified that does not match the name of a known fix, an error of type UNKNOWN_FIX will
    *         be generated.
+   * @param port The port to be used to listen for and respond to http requests for preview pages.
    * @param outputDir The absolute and normalized path to a directory to which non-nullability
    *         migration output will be written. The output is only produced if the non-nullable fix is
    *         included. Files in the directory might be overwritten, but no previously existing files
    *         will be deleted.
    */
-  public void edit_dartfix(List<String> included, List<String> includedFixes, boolean includePedanticFixes, boolean includeRequiredFixes, List<String> excludedFixes, String outputDir, DartfixConsumer consumer);
+  public void edit_dartfix(List<String> included, List<String> includedFixes, boolean includePedanticFixes, boolean includeRequiredFixes, List<String> excludedFixes, int port, String outputDir, DartfixConsumer consumer);
 
   /**
    * {@code edit.format}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index f74c90d..5c210a87 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.27.3</version>
+  <version>1.27.4</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -267,10 +267,6 @@
         <ref>int</ref>
         <p>The process id of the analysis server process.</p>
       </field>
-      <field name="sessionId" optional="true">
-        <ref>String</ref>
-        <p>The session id for this session.</p>
-      </field>
     </params>
   </notification>
   <notification event="error">
@@ -2235,6 +2231,13 @@
           an error of type <tt>UNKNOWN_FIX</tt> will be generated.
         </p>
       </field>
+      <field name="port" optional="true">
+        <ref>int</ref>
+        <p>
+          The port to be used to listen for and respond to http requests for
+          preview pages.
+        </p>
+      </field>
       <field name="outputDir" optional="true">
         <ref>FilePath</ref>
         <p>
diff --git a/pkg/analysis_server_client/CHANGELOG.md b/pkg/analysis_server_client/CHANGELOG.md
index 968b0df..144b255 100644
--- a/pkg/analysis_server_client/CHANGELOG.md
+++ b/pkg/analysis_server_client/CHANGELOG.md
@@ -1,5 +1,6 @@
-# 1.1.3
- * update dartfix protocol to include --pedantic
+# 1.1.2
+ * Update the dartfix protocol to include `--pedantic`
+ * Supports changes made to Analysis Server protocol through Dart 2.6.0
 
 # 1.1.1
  * Update ConnectionHandler to call checkServerProtocolVersion
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 55a6571..861f7a6 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.27.3';
+const String PROTOCOL_VERSION = '1.27.4';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -173,6 +173,7 @@
 const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
     'includeRequiredFixes';
 const String EDIT_REQUEST_DARTFIX_OUTPUT_DIR = 'outputDir';
+const String EDIT_REQUEST_DARTFIX_PORT = 'port';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
@@ -336,7 +337,6 @@
     'hierarchyItems';
 const String SERVER_NOTIFICATION_CONNECTED = 'server.connected';
 const String SERVER_NOTIFICATION_CONNECTED_PID = 'pid';
-const String SERVER_NOTIFICATION_CONNECTED_SESSION_ID = 'sessionId';
 const String SERVER_NOTIFICATION_CONNECTED_VERSION = 'version';
 const String SERVER_NOTIFICATION_ERROR = 'server.error';
 const String SERVER_NOTIFICATION_ERROR_IS_FATAL = 'isFatal';
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 e0495b8..6431008 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -7964,6 +7964,7 @@
  *   "includePedanticFixes": optional bool
  *   "includeRequiredFixes": optional bool
  *   "excludedFixes": optional List<String>
+ *   "port": optional int
  *   "outputDir": optional FilePath
  * }
  *
@@ -7980,6 +7981,8 @@
 
   List<String> _excludedFixes;
 
+  int _port;
+
   String _outputDir;
 
   /**
@@ -8070,6 +8073,20 @@
   }
 
   /**
+   * The port to be used to listen for and respond to http requests for preview
+   * pages.
+   */
+  int get port => _port;
+
+  /**
+   * The port to be used to listen for and respond to http requests for preview
+   * pages.
+   */
+  void set port(int value) {
+    this._port = value;
+  }
+
+  /**
    * The absolute and normalized path to a directory to which non-nullability
    * migration output will be written. The output is only produced if the
    * non-nullable fix is included. Files in the directory might be overwritten,
@@ -8092,12 +8109,14 @@
       bool includePedanticFixes,
       bool includeRequiredFixes,
       List<String> excludedFixes,
+      int port,
       String outputDir}) {
     this.included = included;
     this.includedFixes = includedFixes;
     this.includePedanticFixes = includePedanticFixes;
     this.includeRequiredFixes = includeRequiredFixes;
     this.excludedFixes = excludedFixes;
+    this.port = port;
     this.outputDir = outputDir;
   }
 
@@ -8134,6 +8153,10 @@
         excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
             json["excludedFixes"], jsonDecoder.decodeString);
       }
+      int port;
+      if (json.containsKey("port")) {
+        port = jsonDecoder.decodeInt(jsonPath + ".port", json["port"]);
+      }
       String outputDir;
       if (json.containsKey("outputDir")) {
         outputDir = jsonDecoder.decodeString(
@@ -8144,6 +8167,7 @@
           includePedanticFixes: includePedanticFixes,
           includeRequiredFixes: includeRequiredFixes,
           excludedFixes: excludedFixes,
+          port: port,
           outputDir: outputDir);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
@@ -8171,6 +8195,9 @@
     if (excludedFixes != null) {
       result["excludedFixes"] = excludedFixes;
     }
+    if (port != null) {
+      result["port"] = port;
+    }
     if (outputDir != null) {
       result["outputDir"] = outputDir;
     }
@@ -8196,6 +8223,7 @@
           includeRequiredFixes == other.includeRequiredFixes &&
           listEqual(excludedFixes, other.excludedFixes,
               (String a, String b) => a == b) &&
+          port == other.port &&
           outputDir == other.outputDir;
     }
     return false;
@@ -8209,6 +8237,7 @@
     hash = JenkinsSmiHash.combine(hash, includePedanticFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
     hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, port.hashCode);
     hash = JenkinsSmiHash.combine(hash, outputDir.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
@@ -22377,7 +22406,6 @@
  * {
  *   "version": String
  *   "pid": int
- *   "sessionId": optional String
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -22387,8 +22415,6 @@
 
   int _pid;
 
-  String _sessionId;
-
   /**
    * The version number of the analysis server.
    */
@@ -22415,22 +22441,9 @@
     this._pid = value;
   }
 
-  /**
-   * The session id for this session.
-   */
-  String get sessionId => _sessionId;
-
-  /**
-   * The session id for this session.
-   */
-  void set sessionId(String value) {
-    this._sessionId = value;
-  }
-
-  ServerConnectedParams(String version, int pid, {String sessionId}) {
+  ServerConnectedParams(String version, int pid) {
     this.version = version;
     this.pid = pid;
-    this.sessionId = sessionId;
   }
 
   factory ServerConnectedParams.fromJson(
@@ -22452,12 +22465,7 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "pid");
       }
-      String sessionId;
-      if (json.containsKey("sessionId")) {
-        sessionId = jsonDecoder.decodeString(
-            jsonPath + ".sessionId", json["sessionId"]);
-      }
-      return new ServerConnectedParams(version, pid, sessionId: sessionId);
+      return new ServerConnectedParams(version, pid);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "server.connected params", json);
     }
@@ -22473,9 +22481,6 @@
     Map<String, dynamic> result = {};
     result["version"] = version;
     result["pid"] = pid;
-    if (sessionId != null) {
-      result["sessionId"] = sessionId;
-    }
     return result;
   }
 
@@ -22489,9 +22494,7 @@
   @override
   bool operator ==(other) {
     if (other is ServerConnectedParams) {
-      return version == other.version &&
-          pid == other.pid &&
-          sessionId == other.sessionId;
+      return version == other.version && pid == other.pid;
     }
     return false;
   }
@@ -22501,7 +22504,6 @@
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, version.hashCode);
     hash = JenkinsSmiHash.combine(hash, pid.hashCode);
-    hash = JenkinsSmiHash.combine(hash, sessionId.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
diff --git a/pkg/analysis_server_client/pubspec.yaml b/pkg/analysis_server_client/pubspec.yaml
index a09fc5f..fc2de5b 100644
--- a/pkg/analysis_server_client/pubspec.yaml
+++ b/pkg/analysis_server_client/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analysis_server_client
-version: 1.1.3
+version: 1.1.2
 author: Dart Team <misc@dartlang.org>
 description:
   A client wrapper over analysis_server.
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4fffa1a..16d19e6 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,68 @@
+## 0.39.1
+* Deprecated `DartType.substitute2()`. Use `ClassElement.instantiate()`
+  or `FunctionTypeAliasElement.instantiate()` instead.
+* Deprecated `ParameterizedType.instantiate()` and
+  `InterfaceType.instantiate()`. Use `ClassElement.instantiate()` instead.
+  Using `FunctionType.instantiate()` is still valid.
+* Deprecated `FunctionTypeAliasElement.instantiate2`, use `instantiate2`.
+  In the next version `instantiate2` will be removed.
+* Deprecated `ParameterizedType.typeParameters`.  Please use
+  `ClassElement.typeParameters or FunctionType.typeFormals` instead.
+* Bug fixes: 27617, 34378, 35607, 38494, 38582, 38583, 38643, 38761, 38991,
+  39089, 39111, 39156, 39158, 39170, 39171, 39178.
+
+## 0.39.0
+* Removed deprecated `DartType.isEquivalentTo`.
+* Removed `useDart2jsPaths` argument in `FolderBasedDartSdk` constructor.
+  Dartium does not exist anymore, so there is just one `dart:html`.
+* Removed several unused members of `SourceFactory`: `context`,
+  `localSourcePredicate`, `clone`, `fromEncoding`, `isLocalSource`.
+* Removed deprecated method `Element.computeNode`.
+* Removed deprecated getter `CompilationUnitElement.unit`.
+* Removed deprecated method `Element.computeDocumentationComment`.
+* Removed unused `wrapped.dart` with `WrappedLibraryElement`, etc.
+* Removed deprecated 'bestElement', 'bestType', 'propagatedElement',
+  'propagatedType', etc. Use 'staticElement' and 'staticType' instead.
+* Removed deprecated 'Declaration.element'.
+  Use 'Declaration.declaredElement' instead.
+* Removed deprecated 'Expression.precedence2'. Use 'precedence' instead.
+* Removed `ResolutionMap resolutionMap`. Use corresponding accessors
+  on AstNode(s) directly to get elements and types.
+* Removed 'InheritanceManager2'. Use 'InheritanceManager3' instead.
+* Removed 'InheritanceManager'. Use 'InheritanceManager3' instead.
+* Removed deprecated methods in `DartType`: `flattenFutures`,
+  `isAssignableTo`, `isEquivalentTo`, `isMoreSpecificThan`,
+  `isSubtypeOf`, `isSupertypeOf`, `isDirectSupertypeOf`.
+  Use corresponding methods of `TypeSystem` instead.
+* Removed deprecated getters for checking a specific annotations on
+  'Element': `isAlwaysThrows`, `isDeprecated`, `isFactory`, `isJS`,
+  `isOverride`, `isProtected`, `isRequired`, `isVisibleForTesting`.
+  Use corresponding `hasXyz` getters.
+* Removed 'LocalElement.visibleRange'.
+  Visible ranges of local variables and functions can be computed when
+  AST is available.
+* Removed unused `LibraryElement.libraryCycle`.
+* Removed `ElementHandle` and `ElementResynthesizer`.
+* Remove `ElementBuilder`, `DeclarationResolver`, `DirectiveResolver`,
+  `TypeParameterBoundsResolver`, `TypeResolverVisitor`, etc.
+  Use `ResolutionVisitor` instead, it combines all these operations.
+* Removed `FunctionTypeAliasElement.instantiate`, use `instantiate2` for now.
+  In the next version `instantiate` will be re-introduced with the same
+  signature and semantics as `instantiate2`, and `instantiate2` will be
+  deprecated and removed in the next breaking change version.
+* Stop setting types for identifiers where they are not expressions.
+  Specifically, where a SimpleIdentifier is the name of a declaration,
+  or Identifier is the name of the class in a TypeName.
+* Removed transitional `InheritanceManagerBase`.
+* Removed deprecated method `ArgumentList.correspondingPropagatedParameters`.
+  Use `ArgumentList.correspondingStaticParameters` instead.
+* Removed deprecated getter `PrefixElement.importedLibraries`.  It was never
+  implemented.
+* Removed deprecated getter `VariableElement.isPotentiallyMutatedInClosure` and
+  `VariableElement.isPotentiallyMutatedInScope`.  Please use the corresponding
+  methods in `FunctionBody` instead.
+* Bug fixes: 33441, 35777, 35993, 37898, 38560, 38803, 38811, 38900, 38911.
+
 ## 0.38.5
 * Added the interface `PromotableElement`, which representing
   variables that can be type promoted (local variables and parameters,
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_context.dart b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
index 3a77423..f4258ca 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_context.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_context.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/analysis/context_root.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 
 /// A representation of a body of code and the context in which the code is to
 /// be analyzed.
@@ -44,6 +45,9 @@
   @deprecated
   List<String> get includedPaths;
 
+  /// Return the workspace for containing the context root.
+  Workspace get workspace;
+
   /// Return the absolute, normalized paths of all of the files that are
   /// contained in this context. These are all of the files that are included
   /// directly or indirectly by one or more of the [includedPaths] and that are
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 5e4ff56..435477a 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -159,20 +159,11 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class ArgumentList implements AstNode {
-  /// Return the expressions producing the values of the arguments. Although the
-  /// language requires that positional arguments appear before named arguments,
-  /// this class allows them to be intermixed.
-  NodeList<Expression> get arguments;
-
-  /// Set the parameter elements corresponding to each of the arguments in this
-  /// list to the given list of [parameters]. The list of parameters must be the
-  /// same length as the number of arguments, but can contain `null` entries if
-  /// a given argument does not correspond to a formal parameter.
+  /// Return the expressions producing the values of the arguments.
   ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [correspondingStaticParameters] instead.
-  @deprecated
-  void set correspondingPropagatedParameters(List<ParameterElement> parameters);
+  /// Although the language requires that positional arguments appear before
+  /// named arguments, this class allows them to be intermixed.
+  NodeList<Expression> get arguments;
 
   /// Set the parameter elements corresponding to each of the arguments in this
   /// list to the given list of [parameters]. The list of parameters must be the
@@ -320,11 +311,12 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class AstNode implements SyntacticEntity {
-  /// A comparator that can be used to sort AST nodes in lexical order. In other
-  /// words, `compare` will return a negative value if the offset of the first
-  /// node is less than the offset of the second node, zero (0) if the nodes
-  /// have the same offset, and a positive value if the offset of the first node
-  /// is greater than the offset of the second node.
+  /// A comparator that can be used to sort AST nodes in lexical order.
+  ///
+  /// In other words, `compare` will return a negative value if the offset of
+  /// the first node is less than the offset of the second node, zero (0) if
+  /// the nodes have the same offset, and a positive value if the offset of the
+  /// first node is greater than the offset of the second node.
   static Comparator<AstNode> LEXICAL_ORDER =
       (AstNode first, AstNode second) => first.offset - second.offset;
 
@@ -337,20 +329,23 @@
   Iterable<SyntacticEntity> get childEntities;
 
   /// Return the offset of the character immediately following the last
-  /// character of this node's source range. This is equivalent to
-  /// `node.getOffset() + node.getLength()`. For a compilation unit this will be
-  /// equal to the length of the unit's source. For synthetic nodes this will be
-  /// equivalent to the node's offset (because the length is zero (0) by
-  /// definition).
+  /// character of this node's source range.
+  ///
+  /// This is equivalent to `node.getOffset() + node.getLength()`. For a
+  /// compilation unit this will be equal to the length of the unit's source.
+  /// For synthetic nodes this will be equivalent to the node's offset (because
+  /// the length is zero (0) by definition).
   @override
   int get end;
 
   /// Return the last token included in this node's source range.
   Token get endToken;
 
-  /// Return `true` if this node is a synthetic node. A synthetic node is a node
-  /// that was introduced by the parser in order to recover from an error in the
-  /// code. Synthetic nodes always have a length of zero (`0`).
+  /// Return `true` if this node is a synthetic node.
+  ///
+  /// A synthetic node is a node that was introduced by the parser in order to
+  /// recover from an error in the code. Synthetic nodes always have a length
+  /// of zero (`0`).
   bool get isSynthetic;
 
   @override
@@ -366,13 +361,16 @@
   /// change over the lifetime of a node.
   AstNode get parent;
 
-  /// Return the node at the root of this node's AST structure. Note that this
-  /// method's performance is linear with respect to the depth of the node in
-  /// the AST structure (O(depth)).
+  /// Return the node at the root of this node's AST structure.
+  ///
+  /// Note that this method's performance is linear with respect to the depth
+  /// of the node in the AST structure (O(depth)).
   AstNode get root;
 
-  /// Use the given [visitor] to visit this node. Return the value returned by
-  /// the visitor as a result of visiting this node.
+  /// Use the given [visitor] to visit this node.
+  ///
+  /// Return the value returned by the visitor as a result of visiting this
+  /// node.
   E accept<E>(AstVisitor<E> visitor);
 
   /// Return the token before [target] or `null` if it cannot be found.
@@ -395,12 +393,15 @@
   T thisOrAncestorOfType<T extends AstNode>();
 
   /// Return a textual description of this node in a form approximating valid
-  /// source. The returned string will not be valid source primarily in the case
-  /// where the node itself is not well-formed.
+  /// source.
+  ///
+  /// The returned string will not be valid source primarily in the case where
+  /// the node itself is not well-formed.
   String toSource();
 
-  /// Use the given [visitor] to visit all of the children of this node. The
-  /// children will be visited in lexical order.
+  /// Use the given [visitor] to visit all of the children of this node.
+  ///
+  /// The children will be visited in lexical order.
   void visitChildren(AstVisitor visitor);
 }
 
@@ -803,12 +804,13 @@
   /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /// Return the node from which this break statement is breaking. This will be
-  /// either a [Statement] (in the case of breaking out of a loop), a
-  /// [SwitchMember] (in the case of a labeled break statement whose label
-  /// matches a label on a switch case in an enclosing switch statement), or
-  /// `null` if the AST has not yet been resolved or if the target could not be
-  /// resolved. Note that if the source code has errors, the target might be
+  /// Return the node from which this break statement is breaking.
+  ///
+  /// This will be either a [Statement] (in the case of breaking out of a
+  /// loop), a [SwitchMember] (in the case of a labeled break statement whose
+  /// label matches a label on a switch case in an enclosing switch statement),
+  /// or `null` if the AST has not yet been resolved or if the target could not
+  /// be resolved. Note that if the source code has errors, the target might be
   /// invalid (e.g. trying to break to a switch case).
   AstNode get target;
 
@@ -818,6 +820,7 @@
 }
 
 /// A sequence of cascaded expressions: expressions that share a common target.
+///
 /// There are three kinds of expressions that can be used in a cascade
 /// expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
 ///
@@ -943,10 +946,6 @@
   /// Set the token representing the 'class' keyword.
   void set classKeyword(Token token);
 
-  @deprecated
-  @override
-  ClassElement get element;
-
   /// Return the extends clause for this class, or `null` if the class does not
   /// extend any other class.
   ExtendsClause get extendsClause;
@@ -985,8 +984,10 @@
   void set withClause(WithClause withClause);
 
   /// Return the constructor declared in the class with the given [name], or
-  /// `null` if there is no such constructor. If the [name] is `null` then the
-  /// default constructor will be searched for.
+  /// `null` if there is no such constructor.
+  ///
+  /// If the [name] is `null` then the default constructor will be searched
+  /// for.
   ConstructorDeclaration getConstructor(String name);
 }
 
@@ -1213,11 +1214,6 @@
   /// Return the directives contained in this compilation unit.
   NodeList<Directive> get directives;
 
-  /// Return the element associated with this compilation unit, or `null` if the
-  /// AST structure has not been resolved.
-  @deprecated
-  CompilationUnitElement get element;
-
   /// Set the element associated with this compilation unit to the given
   /// [element].
   void set element(CompilationUnitElement element);
@@ -1436,10 +1432,6 @@
   @override
   ConstructorElement get declaredElement;
 
-  @override
-  @deprecated
-  ConstructorElement get element;
-
   /// Set the element associated with this constructor to the given [element].
   void set element(ConstructorElement element);
 
@@ -1490,9 +1482,11 @@
   /// redirected to the given [redirectedConstructor] name.
   void set redirectedConstructor(ConstructorName redirectedConstructor);
 
-  /// Return the type of object being created. This can be different than the
-  /// type in which the constructor is being declared if the constructor is the
-  /// implementation of a factory constructor.
+  /// Return the type of object being created.
+  ///
+  /// This can be different than the type in which the constructor is being
+  /// declared if the constructor is the implementation of a factory
+  /// constructor.
   Identifier get returnType;
 
   /// Set the type of object being created to the given [typeName].
@@ -1632,12 +1626,14 @@
   /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /// Return the node to which this continue statement is continuing. This will
-  /// be either a [Statement] (in the case of continuing a loop), a
+  /// Return the node to which this continue statement is continuing.
+  ///
+  /// This will be either a [Statement] (in the case of continuing a loop), a
   /// [SwitchMember] (in the case of continuing from one switch case to
   /// another), or `null` if the AST has not yet been resolved or if the target
-  /// could not be resolved. Note that if the source code has errors, the target
-  /// might be invalid (e.g. the target may be in an enclosing function).
+  /// could not be resolved. Note that if the source code has errors, the
+  /// target might be invalid (e.g. the target may be in an enclosing
+  /// function).
   AstNode get target;
 
   /// Set the node to which this continue statement is continuing to the given
@@ -1645,8 +1641,9 @@
   void set target(AstNode node);
 }
 
-/// A node that represents the declaration of one or more names. Each declared
-/// name is visible within a name scope.
+/// A node that represents the declaration of one or more names.
+///
+/// Each declared name is visible within a name scope.
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class Declaration implements AnnotatedNode {
@@ -1654,12 +1651,6 @@
   /// this node corresponds to a list of declarations or if the AST structure
   /// has not been resolved.
   Element get declaredElement;
-
-  /// Return the element associated with this declaration, or `null` if either
-  /// this node corresponds to a list of declarations or if the AST structure
-  /// has not been resolved.
-  @deprecated
-  Element get element;
 }
 
 /// The declaration of a single identifier.
@@ -1672,10 +1663,6 @@
   @override
   LocalVariableElement get declaredElement;
 
-  @deprecated
-  @override
-  LocalVariableElement get element;
-
   /// Return the name of the variable being declared.
   SimpleIdentifier get identifier;
 
@@ -1706,9 +1693,10 @@
   void set type(TypeAnnotation type);
 }
 
-/// A formal parameter with a default value. There are two kinds of parameters
-/// that are both represented by this class: named formal parameters and
-/// positional formal parameters.
+/// A formal parameter with a default value.
+///
+/// There are two kinds of parameters that are both represented by this class:
+/// named formal parameters and positional formal parameters.
 ///
 ///    defaultFormalParameter ::=
 ///        [NormalFormalParameter] ('=' [Expression])?
@@ -1910,10 +1898,6 @@
   @override
   ClassElement get declaredElement;
 
-  @deprecated
-  @override
-  ClassElement get element;
-
   /// Return the 'enum' keyword.
   Token get enumKeyword;
 
@@ -1950,72 +1934,17 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class Expression implements CollectionElement {
-  /// Return the best parameter element information available for this
-  /// expression. If type propagation was able to find a better parameter
-  /// element than static analysis, that type will be returned. Otherwise, the
-  /// result of static analysis will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticParameterElement] instead.
-  @deprecated
-  ParameterElement get bestParameterElement;
-
-  /// Return the best type information available for this expression. If type
-  /// propagation was able to find a better type than static analysis, that type
-  /// will be returned. Otherwise, the result of static analysis will be
-  /// returned. If no type analysis has been performed, then the type 'dynamic'
-  /// will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticType] instead, but be aware that [staticType] will return
-  /// `null` under some circumstances, while [bestType] did not.
-  @deprecated
-  DartType get bestType;
-
   /// Return `true` if this expression is syntactically valid for the LHS of an
   /// [AssignmentExpression].
   bool get isAssignable;
 
-  /// Return the precedence of this expression. The precedence is a positive
-  /// integer value that defines how the source code is parsed into an AST. For
-  /// example `a * b + c` is parsed as `(a * b) + c` because the precedence of
-  /// `*` is greater than the precedence of `+`.
+  /// Return the precedence of this expression.
+  ///
+  /// The precedence is a positive integer value that defines how the source
+  /// code is parsed into an AST. For example `a * b + c` is parsed as `(a * b)
+  /// + c` because the precedence of `*` is greater than the precedence of `+`.
   Precedence get precedence;
 
-  /// Return the precedence of this expression. The precedence is a positive
-  /// integer value that defines how the source code is parsed into an AST. For
-  /// example `a * b + c` is parsed as `(a * b) + c` because the precedence of
-  /// `*` is greater than the precedence of `+`.
-  @Deprecated('Use precedence')
-  Precedence get precedence2;
-
-  /// If this expression is an argument to an invocation, and the AST structure
-  /// has been resolved, and the function being invoked is known based on
-  /// propagated type information, and this expression corresponds to one of the
-  /// parameters of the function being invoked, then return the parameter
-  /// element representing the parameter to which the value of this expression
-  /// will be bound. Otherwise, return `null`.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticParameterElement] instead.
-  @deprecated
-  ParameterElement get propagatedParameterElement;
-
-  /// Return the propagated type of this expression, or `null` if type
-  /// propagation has not been performed on the AST structure.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticType] instead.
-  @deprecated
-  DartType get propagatedType;
-
-  /// Set the propagated type of this expression to the given [type].
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticType] instead.
-  @deprecated
-  void set propagatedType(DartType type);
-
   /// If this expression is an argument to an invocation, and the AST structure
   /// has been resolved, and the function being invoked is known based on static
   /// type information, and this expression corresponds to one of the parameters
@@ -2249,6 +2178,11 @@
   /// is not a function-typed field formal parameter.
   FormalParameterList get parameters;
 
+  /// If the parameter is function-typed, and has the question mark, then its
+  /// function type is nullable. Having a nullable function type means that the
+  /// parameter can be null.
+  Token get question;
+
   /// Set the parameters of the function-typed parameter to the given
   /// [parameters].
   void set parameters(FormalParameterList parameters);
@@ -2266,8 +2200,10 @@
   void set thisKeyword(Token token);
 
   /// Return the declared type of the parameter, or `null` if the parameter does
-  /// not have a declared type. Note that if this is a function-typed field
-  /// formal parameter this is the return type of the function.
+  /// not have a declared type.
+  ///
+  /// Note that if this is a function-typed field formal parameter this is the
+  /// return type of the function.
   TypeAnnotation get type;
 
   /// Set the declared type of the parameter to the given [type].
@@ -2370,11 +2306,6 @@
   /// parameter has not been resolved.
   ParameterElement get declaredElement;
 
-  /// Return the element representing this parameter, or `null` if this
-  /// parameter has not been resolved.
-  @deprecated
-  ParameterElement get element;
-
   /// Return the name of the parameter being declared.
   SimpleIdentifier get identifier;
 
@@ -2382,16 +2313,19 @@
   bool get isConst;
 
   /// Return `true` if this parameter was declared with the 'final' modifier.
-  /// Parameters that are declared with the 'const' modifier will return `false`
-  /// even though they are implicitly final.
+  ///
+  /// Parameters that are declared with the 'const' modifier will return
+  /// `false` even though they are implicitly final.
   bool get isFinal;
 
-  /// Return `true` if this parameter is a named parameter. Named parameters can
-  /// either be required or optional.
+  /// Return `true` if this parameter is a named parameter.
+  ///
+  /// Named parameters can either be required or optional.
   bool get isNamed;
 
-  /// Return `true` if this parameter is an optional parameter. Optional
-  /// parameters can either be positional or named.
+  /// Return `true` if this parameter is an optional parameter.
+  ///
+  /// Optional parameters can either be positional or named.
   bool get isOptional;
 
   /// Return `true` if this parameter is both an optional and named parameter.
@@ -2401,12 +2335,14 @@
   /// parameter.
   bool get isOptionalPositional;
 
-  /// Return `true` if this parameter is a positional parameter. Positional
-  /// parameters can either be required or optional.
+  /// Return `true` if this parameter is a positional parameter.
+  ///
+  /// Positional parameters can either be required or optional.
   bool get isPositional;
 
-  /// Return `true` if this parameter is a required parameter. Required
-  /// parameters can either be positional or named.
+  /// Return `true` if this parameter is a required parameter.
+  ///
+  /// Required parameters can either be positional or named.
   ///
   /// Note: this will return `false` for a named parameter that is annotated
   /// with the `@required` annotation.
@@ -2477,8 +2413,10 @@
   void set leftParenthesis(Token token);
 
   /// Return a list containing the elements representing the parameters in this
-  /// list. The list will contain `null`s if the parameters in this list have
-  /// not been resolved.
+  /// list.
+  ///
+  /// The list will contain `null`s if the parameters in this list have not
+  /// been resolved.
   List<ParameterElement> get parameterElements;
 
   /// Return the parameters associated with the method.
@@ -2648,10 +2586,6 @@
   @override
   ExecutableElement get declaredElement;
 
-  @deprecated
-  @override
-  ExecutableElement get element;
-
   /// Return the token representing the 'external' keyword, or `null` if this is
   /// not an external function.
   Token get externalKeyword;
@@ -2718,11 +2652,6 @@
   /// structure has not been resolved.
   ExecutableElement get declaredElement;
 
-  /// Return the element associated with the function, or `null` if the AST
-  /// structure has not been resolved.
-  @deprecated
-  ExecutableElement get element;
-
   /// Set the element associated with the function to the given [element].
   void set element(ExecutableElement element);
 
@@ -2744,6 +2673,7 @@
 }
 
 /// The invocation of a function resulting from evaluating an expression.
+///
 /// Invocations of methods and other forms of functions are represented by
 /// [MethodInvocation] nodes. Invocations of getters and setters are represented
 /// by either [PrefixedIdentifier] or [PropertyAccess] nodes.
@@ -2756,17 +2686,6 @@
   /// Set the list of arguments to the method to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /// Return the best element available for the function being invoked. If
-  /// resolution was able to find a better element based on type propagation,
-  /// that element will be returned. Otherwise, the element found using the
-  /// result of static analysis will be returned. If resolution has not been
-  /// performed, then `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  ExecutableElement get bestElement;
-
   /// Return the expression producing the function being invoked.
   @override
   Expression get function;
@@ -2776,23 +2695,6 @@
   void set function(Expression expression);
 
   /// Return the element associated with the function being invoked based on
-  /// propagated type information, or `null` if the AST structure has not been
-  /// resolved or the function could not be resolved.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  ExecutableElement get propagatedElement;
-
-  /// Set the element associated with the function being invoked based on
-  /// propagated type information to the given [element].
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  void set propagatedElement(ExecutableElement element);
-
-  /// Return the element associated with the function being invoked based on
   /// static type information, or `null` if the AST structure has not been
   /// resolved or the function could not be resolved.
   ExecutableElement get staticElement;
@@ -2995,34 +2897,15 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class Identifier implements Expression {
-  /// Return the best element available for this operator. If resolution was
-  /// able to find a better element based on type propagation, that element will
-  /// be returned. Otherwise, the element found using the result of static
-  /// analysis will be returned. If resolution has not been performed, then
-  /// `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  Element get bestElement;
-
   /// Return the lexical representation of the identifier.
   String get name;
 
-  /// Return the element associated with this identifier based on propagated
-  /// type information, or `null` if the AST structure has not been resolved or
-  /// if this identifier could not be resolved. One example of the latter case
-  /// is an identifier that is not defined within the scope in which it appears.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  Element get propagatedElement;
-
   /// Return the element associated with this identifier based on static type
   /// information, or `null` if the AST structure has not been resolved or if
-  /// this identifier could not be resolved. One example of the latter case is
-  /// an identifier that is not defined within the scope in which it appears.
+  /// this identifier could not be resolved.
+  ///
+  /// One example of the latter case is an identifier that is not defined
+  /// within the scope in which it appears.
   Element get staticElement;
 
   /// Return `true` if the given [name] is visible only within the library in
@@ -3281,9 +3164,10 @@
 abstract class IndexExpression
     implements Expression, MethodReferenceExpression {
   /// Return the auxiliary elements associated with this identifier, or `null`
-  /// if this identifier is not in both a getter and setter context. The
-  /// auxiliary elements hold the static and propagated elements associated with
-  /// the getter context.
+  /// if this identifier is not in both a getter and setter context.
+  ///
+  /// The auxiliary elements hold the static and propagated elements associated
+  /// with the getter context.
   // TODO(brianwilkerson) Replace this API.
   AuxiliaryElements get auxiliaryElements;
 
@@ -3298,9 +3182,10 @@
   /// Set the expression used to compute the index to the given [expression].
   void set index(Expression expression);
 
-  /// Return `true` if this expression is cascaded. If it is, then the target of
-  /// this expression is not stored locally but is stored in the nearest
-  /// ancestor that is a [CascadeExpression].
+  /// Return `true` if this expression is cascaded.
+  ///
+  /// If it is, then the target of this expression is not stored locally but is
+  /// stored in the nearest ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
   /// Whether this index expression is null aware (as opposed to non-null).
@@ -3320,9 +3205,10 @@
   /// [token].
   void set period(Token token);
 
-  /// Return the expression used to compute the object being indexed. If this
-  /// index expression is not part of a cascade expression, then this is the
-  /// same as [target]. If this index expression is part of a cascade
+  /// Return the expression used to compute the object being indexed.
+  ///
+  /// If this index expression is not part of a cascade expression, then this
+  /// is the same as [target]. If this index expression is part of a cascade
   /// expression, then the target expression stored with the cascade expression
   /// is returned.
   Expression get realTarget;
@@ -3512,27 +3398,6 @@
   /// [staticInvokeType] before applying type arguments `TArgs`.
   Expression get function;
 
-  /// Return the function type of the invocation based on the propagated type
-  /// information, or `null` if the AST structure has not been resolved, or if
-  /// the invoke could not be resolved.
-  ///
-  /// This will usually be a [FunctionType], but it can also be an
-  /// [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
-  /// interface type that implements `Function`.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticInvokeType] instead.
-  @deprecated
-  DartType get propagatedInvokeType;
-
-  /// Sets the function type of the invocation based on the propagated type
-  /// information.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticInvokeType] instead.
-  @deprecated
-  void set propagatedInvokeType(DartType value);
-
   /// Return the function type of the invocation based on the static type
   /// information, or `null` if the AST structure has not been resolved, or if
   /// the invoke could not be resolved.
@@ -3769,10 +3634,6 @@
   @override
   ExecutableElement get declaredElement;
 
-  @deprecated
-  @override
-  ExecutableElement get element;
-
   /// Return the token for the 'external' keyword, or `null` if the constructor
   /// is not external.
   Token get externalKeyword;
@@ -3848,10 +3709,12 @@
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/// The invocation of either a function or a method. Invocations of functions
-/// resulting from evaluating an expression are represented by
-/// [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
-/// represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+/// The invocation of either a function or a method.
+///
+/// Invocations of functions resulting from evaluating an expression are
+/// represented by [FunctionExpressionInvocation] nodes. Invocations of getters
+/// and setters are represented by either [PrefixedIdentifier] or
+/// [PropertyAccess] nodes.
 ///
 ///    methodInvocation ::=
 ///        ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
@@ -3861,9 +3724,10 @@
   /// Set the list of arguments to the method to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /// Return `true` if this expression is cascaded. If it is, then the target of
-  /// this expression is not stored locally but is stored in the nearest
-  /// ancestor that is a [CascadeExpression].
+  /// Return `true` if this expression is cascaded.
+  ///
+  /// If it is, then the target of this expression is not stored locally but is
+  /// stored in the nearest ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
   /// Whether this method invocation is null aware (as opposed to non-null).
@@ -3876,19 +3740,21 @@
   void set methodName(SimpleIdentifier identifier);
 
   /// Return the operator that separates the target from the method name, or
-  /// `null` if there is no target. In an ordinary method invocation this will
-  /// be period ('.'). In a cascade section this will be the cascade operator
-  /// ('..').
+  /// `null` if there is no target.
+  ///
+  /// In an ordinary method invocation this will be period ('.'). In a cascade
+  /// section this will be the cascade operator ('..').
   Token get operator;
 
   /// Set the operator that separates the target from the method name to the
   /// given [token].
   void set operator(Token token);
 
-  /// Return the expression used to compute the receiver of the invocation. If
-  /// this invocation is not part of a cascade expression, then this is the same
-  /// as [target]. If this invocation is part of a cascade expression, then the
-  /// target stored with the cascade expression is returned.
+  /// Return the expression used to compute the receiver of the invocation.
+  ///
+  /// If this invocation is not part of a cascade expression, then this is the
+  /// same as [target]. If this invocation is part of a cascade expression,
+  /// then the target stored with the cascade expression is returned.
   Expression get realTarget;
 
   /// Return the expression producing the object on which the method is defined,
@@ -3912,36 +3778,6 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class MethodReferenceExpression implements AstNode {
-  /// Return the best element available for this expression. If resolution was
-  /// able to find a better element based on type propagation, that element will
-  /// be returned. Otherwise, the element found using the result of static
-  /// analysis will be returned. If resolution has not been performed, then
-  /// `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  MethodElement get bestElement;
-
-  /// Return the element associated with the expression based on propagated
-  /// types, or `null` if the AST structure has not been resolved, or there is
-  /// no meaningful propagated element to return (e.g. because this is a
-  /// non-compound assignment expression, or because the method referred to
-  /// could not be resolved).
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  MethodElement get propagatedElement;
-
-  /// Set the element associated with the expression based on propagated types
-  /// to the given [element].
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  void set propagatedElement(MethodElement element);
-
   /// Return the element associated with the expression based on the static
   /// types, or `null` if the AST structure has not been resolved, or there is
   /// no meaningful static element to return (e.g. because this is a
@@ -4062,16 +3898,19 @@
   /// ('import', 'export', 'library' or 'part') to the given [token].
   void set keyword(Token token);
 
-  /// Return the source that was selected based on the declared variables. This
-  /// will be the source from the first configuration whose condition is true,
-  /// or the [uriSource] if either there are no configurations or if there are
-  /// no configurations whose condition is true.
+  /// Return the source that was selected based on the declared variables.
+  ///
+  /// This will be the source from the first configuration whose condition is
+  /// true, or the [uriSource] if either there are no configurations or if
+  /// there are no configurations whose condition is true.
   Source get selectedSource;
 
   /// Return the content of the URI that was selected based on the declared
-  /// variables. This will be the URI from the first configuration whose
-  /// condition is true, or the [uriContent] if either there are no
-  /// configurations or if there are no configurations whose condition is true.
+  /// variables.
+  ///
+  /// This will be the URI from the first configuration whose condition is
+  /// true, or the [uriContent] if either there are no configurations or if
+  /// there are no configurations whose condition is true.
   String get selectedUriContent;
 
   /// Return the semicolon terminating the directive.
@@ -4412,9 +4251,10 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class PropertyAccess implements Expression {
-  /// Return `true` if this expression is cascaded. If it is, then the target of
-  /// this expression is not stored locally but is stored in the nearest
-  /// ancestor that is a [CascadeExpression].
+  /// Return `true` if this expression is cascaded.
+  ///
+  /// If it is, then the target of this expression is not stored locally but is
+  /// stored in the nearest ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
   /// Whether this property access is null aware (as opposed to non-null).
@@ -4432,10 +4272,11 @@
   /// Set the name of the property being accessed to the given [identifier].
   void set propertyName(SimpleIdentifier identifier);
 
-  /// Return the expression used to compute the receiver of the invocation. If
-  /// this invocation is not part of a cascade expression, then this is the same
-  /// as [target]. If this invocation is part of a cascade expression, then the
-  /// target stored with the cascade expression is returned.
+  /// Return the expression used to compute the receiver of the invocation.
+  ///
+  /// If this invocation is not part of a cascade expression, then this is the
+  /// same as [target]. If this invocation is part of a cascade expression,
+  /// then the target stored with the cascade expression is returned.
   Expression get realTarget;
 
   /// Return the expression computing the object defining the property being
@@ -4656,9 +4497,10 @@
 /// Clients may not extend, implement or mix-in this class.
 abstract class SimpleIdentifier implements Identifier {
   /// Return the auxiliary elements associated with this identifier, or `null`
-  /// if this identifier is not in both a getter and setter context. The
-  /// auxiliary elements hold the static and propagated elements associated with
-  /// the getter context.
+  /// if this identifier is not in both a getter and setter context.
+  ///
+  /// The auxiliary elements hold the static and propagated elements associated
+  /// with the getter context.
   // TODO(brianwilkerson) Replace this API.
   AuxiliaryElements get auxiliaryElements;
 
@@ -4671,14 +4513,6 @@
   /// identifier or a method invocation.
   bool get isQualified;
 
-  /// Set the element associated with this identifier based on propagated type
-  /// information to the given [element].
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElement] instead.
-  @deprecated
-  void set propagatedElement(Element element);
-
   /// Set the element associated with this identifier based on static type
   /// information to the given [element].
   void set staticElement(Element element);
@@ -4770,8 +4604,9 @@
   /// Return the offset of the after-last contents character.
   int get contentsEnd;
 
-  /// Return the offset of the first contents character. If the string is
-  /// multiline, then leading whitespaces are skipped.
+  /// Return the offset of the first contents character.
+  ///
+  /// If the string is multiline, then leading whitespaces are skipped.
   int get contentsOffset;
 
   /// Return `true` if this string literal is a multi-line string.
@@ -5302,8 +5137,10 @@
 
   /// Return the element associated with the [uri] of this directive, or `null`
   /// if the AST structure has not been resolved or if the URI could not be
-  /// resolved. Examples of the latter case include a directive that contains an
-  /// invalid URL or a URL that does not exist.
+  /// resolved.
+  ///
+  /// Examples of the latter case include a directive that contains an invalid
+  /// URL or a URL that does not exist.
   Element get uriElement;
 
   /// Return the source to which the [uri] was resolved.
@@ -5313,26 +5150,23 @@
   void set uriSource(Source source);
 }
 
-/// An identifier that has an initial value associated with it. Instances of
-/// this class are always children of the class [VariableDeclarationList].
+/// An identifier that has an initial value associated with it.
+///
+/// Instances of this class are always children of the class
+/// [VariableDeclarationList].
 ///
 ///    variableDeclaration ::=
 ///        [SimpleIdentifier] ('=' [Expression])?
 ///
-/// TODO(paulberry): the grammar does not allow metadata to be associated with
-/// a VariableDeclaration, and currently we don't record comments for it either.
-/// Consider changing the class hierarchy so that [VariableDeclaration] does not
-/// extend [Declaration].
-///
 /// Clients may not extend, implement or mix-in this class.
+// TODO(paulberry): the grammar does not allow metadata to be associated with a
+// VariableDeclaration, and currently we don't record comments for it either.
+// Consider changing the class hierarchy so that [VariableDeclaration] does not
+// extend [Declaration].
 abstract class VariableDeclaration implements Declaration {
   @override
   VariableElement get declaredElement;
 
-  @deprecated
-  @override
-  VariableElement get element;
-
   /// Return the equal sign separating the variable name from the initial value,
   /// or `null` if the initial value was not specified.
   Token get equals;
@@ -5353,6 +5187,7 @@
   bool get isConst;
 
   /// Return `true` if this variable was declared with the 'final' modifier.
+  ///
   /// Variables that are declared with the 'const' modifier will return `false`
   /// even though they are implicitly final.
   bool get isFinal;
@@ -5385,9 +5220,11 @@
   bool get isConst;
 
   /// Return `true` if the variables in this list were declared with the 'final'
-  /// modifier. Variables that are declared with the 'const' modifier will
-  /// return `false` even though they are implicitly final. (In other words,
-  /// this is a syntactic check rather than a semantic check.)
+  /// modifier.
+  ///
+  /// Variables that are declared with the 'const' modifier will return `false`
+  /// even though they are implicitly final. (In other words, this is a
+  /// syntactic check rather than a semantic check.)
   bool get isFinal;
 
   /// Return `true` if the variables in this list were declared with the 'late'
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 911b6b5..c26c895 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -2,10 +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:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:meta/meta.dart';
 
 /// A collection of factory methods which may be used to create concrete
@@ -407,7 +407,8 @@
       @required Token period,
       @required SimpleIdentifier identifier,
       TypeParameterList typeParameters,
-      FormalParameterList parameters});
+      FormalParameterList parameters,
+      Token question});
 
   /// Returns a newly created for each part that includes a declaration.
   ForEachPartsWithDeclaration forEachPartsWithDeclaration(
diff --git a/pkg/analyzer/lib/dart/ast/precedence.dart b/pkg/analyzer/lib/dart/ast/precedence.dart
index aaed019..f8e1494 100644
--- a/pkg/analyzer/lib/dart/ast/precedence.dart
+++ b/pkg/analyzer/lib/dart/ast/precedence.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 
 /// Opaque representation of Dart expression precedence.
 ///
diff --git a/pkg/analyzer/lib/dart/ast/resolution_map.dart b/pkg/analyzer/lib/dart/ast/resolution_map.dart
deleted file mode 100644
index a0cc7e4..0000000
--- a/pkg/analyzer/lib/dart/ast/resolution_map.dart
+++ /dev/null
@@ -1,266 +0,0 @@
-// 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.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-
-/// A collection of methods which may be used to map from nodes in a resolved
-/// AST to elements and types in the element model.
-///
-/// Clients should not extend, implement or mix-in this class.
-// TODO(brianwilkerson) This was added for unifying with the front_end, and is
-//  no longer needed. It should be removed.
-abstract class ResolutionMap {
-  /// Return the best element available for the function being invoked at
-  /// [node]. If resolution was able to find a better element based on type
-  /// propagation, that element will be returned. Otherwise, the element found
-  /// using the result of static analysis will be returned. If resolution has
-  /// not been performed, then `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForFunctionExpressionInvocation] instead.
-  @deprecated
-  ExecutableElement bestElementForFunctionExpressionInvocation(
-      FunctionExpressionInvocation node);
-
-  /// Return the best element available for the identifier [node]. If resolution
-  /// was able to find a better element based on type propagation, that element
-  /// will be returned. Otherwise, the element found using the result of static
-  /// analysis will be returned. If resolution has not been performed, then
-  /// `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForIdentifier] instead.
-  @deprecated
-  Element bestElementForIdentifier(Identifier node);
-
-  /// Return the best element available for the expression [node]. If resolution
-  /// was able to find a better element based on type propagation, that element
-  /// will be returned. Otherwise, the element found using the result of static
-  /// analysis will be returned. If resolution has not been performed, then
-  /// `null` will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForMethodReference] instead.
-  @deprecated
-  MethodElement bestElementForMethodReference(MethodReferenceExpression node);
-
-  /// Return the best parameter element information available for the expression
-  /// [node]. If type propagation was able to find a better parameter element
-  /// than static analysis, that type will be returned. Otherwise, the result of
-  /// static analysis will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticParameterElementForExpression] instead.
-  @deprecated
-  ParameterElement bestParameterElementForExpression(Expression node);
-
-  /// Return the best type information available for the expression [node]. If
-  /// type propagation was able to find a better type than static analysis, that
-  /// type will be returned. Otherwise, the result of static analysis will be
-  /// returned. If no type analysis has been performed, then the type 'dynamic'
-  /// will be returned.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticTypeForExpression] instead.
-  @deprecated
-  DartType bestTypeForExpression(Expression node);
-
-  /// Return the element annotation representing the annotation [node] in the
-  /// element model.
-  ElementAnnotation elementAnnotationForAnnotation(Annotation node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ClassElement elementDeclaredByClassDeclaration(ClassDeclaration node);
-
-  /// Return the element associated with the compilation unit [node], or `null`
-  /// if the AST structure has not been resolved.
-  CompilationUnitElement elementDeclaredByCompilationUnit(CompilationUnit node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ConstructorElement elementDeclaredByConstructorDeclaration(
-      ConstructorDeclaration node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  Element elementDeclaredByDeclaration(Declaration node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  LocalVariableElement elementDeclaredByDeclaredIdentifier(
-      DeclaredIdentifier node);
-
-  /// Return the element associated with the directive [node], or `null` if the
-  /// AST structure has not been resolved or if this directive could not be
-  /// resolved.
-  Element elementDeclaredByDirective(Directive node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ClassElement elementDeclaredByEnumDeclaration(EnumDeclaration node);
-
-  /// Return the element representing the parameter [node], or `null` if this
-  /// parameter has not been resolved.
-  ParameterElement elementDeclaredByFormalParameter(FormalParameter node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ExecutableElement elementDeclaredByFunctionDeclaration(
-      FunctionDeclaration node);
-
-  /// Return the element associated with the function expression [node], or
-  /// `null` if the AST structure has not been resolved.
-  ExecutableElement elementDeclaredByFunctionExpression(
-      FunctionExpression node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ExecutableElement elementDeclaredByMethodDeclaration(MethodDeclaration node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  ClassElement elementDeclaredByMixinDeclaration(MixinDeclaration node);
-
-  /// Return the element associated with the declaration [node], or `null` if
-  /// either this node corresponds to a list of declarations or if the AST
-  /// structure has not been resolved.
-  VariableElement elementDeclaredByVariableDeclaration(
-      VariableDeclaration node);
-
-  /// Return the element associated with the annotation [node], or `null` if the
-  /// AST structure has not been resolved or if this annotation could not be
-  /// resolved.
-  Element elementForAnnotation(Annotation node);
-
-  /// Return the element representing the parameter being named by the
-  /// expression [node], or `null` if the AST structure has not been resolved or
-  /// if there is no parameter with the same name as this expression.
-  ParameterElement elementForNamedExpression(NamedExpression node);
-
-  /// Return a list containing the elements representing the parameters in the
-  /// list [node]. The list will contain `null`s if the parameters in this list
-  /// have not been resolved.
-  List<ParameterElement> parameterElementsForFormalParameterList(
-      FormalParameterList node);
-
-  /// Return the element associated with the function being invoked at [node]
-  /// based on propagated type information, or `null` if the AST structure has
-  /// not been resolved or the function could not be resolved.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForFunctionExpressionInvocation] instead.
-  @deprecated
-  ExecutableElement propagatedElementForFunctionExpressionInvocation(
-      FunctionExpressionInvocation node);
-
-  /// Return the element associated with the identifier [node] based on
-  /// propagated type information, or `null` if the AST structure has not been
-  /// resolved or if this identifier could not be resolved. One example of the
-  /// latter case is an identifier that is not defined within the scope in which
-  /// it appears.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForIdentifier] instead.
-  @deprecated
-  Element propagatedElementForIdentifier(Identifier node);
-
-  /// Return the element associated with the expression [node] based on
-  /// propagated types, or `null` if the AST structure has not been resolved, or
-  /// there is no meaningful propagated element to return (e.g. because this is
-  /// a non-compound assignment expression, or because the method referred to
-  /// could not be resolved).
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticElementForMethodReference] instead.
-  @deprecated
-  MethodElement propagatedElementForMethodReference(
-      MethodReferenceExpression node);
-
-  /// If the expression [node] is an argument to an invocation, and the AST
-  /// structure has been resolved, and the function being invoked is known based
-  /// on propagated type information, and [node] corresponds to one of the
-  /// parameters of the function being invoked, then return the parameter
-  /// element representing the parameter to which the value of [node] will be
-  /// bound. Otherwise, return `null`.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticParameterElementForExpression] instead.
-  @deprecated
-  ParameterElement propagatedParameterElementForExpression(Expression node);
-
-  /// Return the propagated type of the expression [node], or `null` if type
-  /// propagation has not been performed on the AST structure.
-  ///
-  /// Deprecated: The analyzer no longer computes propagated type information.
-  /// Use [staticTypeForExpression] instead.
-  @deprecated
-  DartType propagatedTypeForExpression(Expression node);
-
-  /// Return the element associated with the constructor referenced by [node]
-  /// based on static type information, or `null` if the AST structure has not
-  /// been resolved or if the constructor could not be resolved.
-  ConstructorElement staticElementForConstructorReference(
-      ConstructorReferenceNode node);
-
-  /// Return the element associated with the function being invoked at [node]
-  /// based on static type information, or `null` if the AST structure has not
-  /// been resolved or the function could not be resolved.
-  ExecutableElement staticElementForFunctionExpressionInvocation(
-      FunctionExpressionInvocation node);
-
-  /// Return the element associated with the identifier [node] based on static
-  /// type information, or `null` if the AST structure has not been resolved or
-  /// if this identifier could not be resolved. One example of the latter case
-  /// is an identifier that is not defined within the scope in which it appears.
-  Element staticElementForIdentifier(Identifier node);
-
-  /// Return the element associated with the expression [node] based on the
-  /// static types, or `null` if the AST structure has not been resolved, or
-  /// there is no meaningful static element to return (e.g. because this is a
-  /// non-compound assignment expression, or because the method referred to
-  /// could not be resolved).
-  MethodElement staticElementForMethodReference(MethodReferenceExpression node);
-
-  /// Return the function type of the invocation [node] based on the static type
-  /// information, or `null` if the AST structure has not been resolved, or if
-  /// the invoke could not be resolved.
-  ///
-  /// This will usually be a [FunctionType], but it can also be an
-  /// [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
-  /// interface type that implements `Function`.
-  DartType staticInvokeTypeForInvocationExpression(InvocationExpression node);
-
-  /// If the expression [node] is an argument to an invocation, and the AST
-  /// structure has been resolved, and the function being invoked is known based
-  /// on static type information, and [node] corresponds to one of the
-  /// parameters of the function being invoked, then return the parameter
-  /// element representing the parameter to which the value of [node] will be
-  /// bound. Otherwise, return `null`.
-  ParameterElement staticParameterElementForExpression(Expression node);
-
-  /// Return the static type of the expression [node], or `null` if the AST
-  /// structure has not been resolved.
-  DartType staticTypeForExpression(Expression node);
-
-  /// Return the type being named by [node], or `null` if the AST structure has
-  /// not been resolved.
-  DartType typeForTypeName(TypeAnnotation node);
-
-  /// Return the element associated with the uri of the directive [node], or
-  /// `null` if the AST structure has not been resolved or if the URI could not
-  /// be resolved. Examples of the latter case include a directive that contains
-  /// an invalid URL or a URL that does not exist.
-  Element uriElementForDirective(UriBasedDirective node);
-}
diff --git a/pkg/analyzer/lib/dart/ast/standard_resolution_map.dart b/pkg/analyzer/lib/dart/ast/standard_resolution_map.dart
deleted file mode 100644
index 3353e19..0000000
--- a/pkg/analyzer/lib/dart/ast/standard_resolution_map.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// 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.
-
-import 'package:analyzer/dart/ast/resolution_map.dart';
-import 'package:analyzer/src/dart/ast/resolution_map.dart';
-
-/// Gets an instance of [ResolutionMap] based on the standard AST
-/// implementation.
-final ResolutionMap resolutionMap = new ResolutionMapImpl();
diff --git a/pkg/analyzer/lib/dart/ast/syntactic_entity.dart b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
index f32390f..946fb12 100644
--- a/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
+++ b/pkg/analyzer/lib/dart/ast/syntactic_entity.dart
@@ -2,4 +2,5 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-export 'package:front_end/src/base/syntactic_entity.dart' show SyntacticEntity;
+export 'package:_fe_analyzer_shared/src/base/syntactic_entity.dart'
+    show SyntacticEntity;
diff --git a/pkg/analyzer/lib/dart/ast/token.dart b/pkg/analyzer/lib/dart/ast/token.dart
index 4262a60..8cb6ef9 100644
--- a/pkg/analyzer/lib/dart/ast/token.dart
+++ b/pkg/analyzer/lib/dart/ast/token.dart
@@ -4,5 +4,5 @@
 
 /// Defines the tokens that are produced by the scanner, used by the parser, and
 /// referenced from the [AST structure](ast.dart).
-export 'package:front_end/src/scanner/token.dart'
+export 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show Keyword, Token, TokenType;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index b396c31..951dfe4 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -35,7 +35,6 @@
 /// statements declares a local variable then the local variable will be
 /// represented by an element.
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -185,6 +184,7 @@
   InterfaceType get thisType;
 
   @override
+  @deprecated
   InterfaceType get type;
 
   /// Return the unnamed constructor declared in this class, or `null` if either
@@ -195,10 +195,6 @@
   /// the class.
   ConstructorElement get unnamedConstructor;
 
-  @deprecated
-  @override
-  NamedCompilationUnitMember computeNode();
-
   /// Return the field (synthetic or explicit) defined in this class that has
   /// the given [name], or `null` if this class does not define a field with the
   /// given name.
@@ -428,10 +424,6 @@
   /// unit.
   List<ClassElement> get types;
 
-  @deprecated
-  @override
-  CompilationUnit computeNode();
-
   /// Return the enum defined in this compilation unit that has the given
   /// [name], or `null` if this compilation unit does not define an enum with
   /// the given name.
@@ -474,10 +466,6 @@
   /// if this constructor does not redirect to another constructor or if the
   /// library containing this constructor has not yet been resolved.
   ConstructorElement get redirectedConstructor;
-
-  @deprecated
-  @override
-  ConstructorDeclaration computeNode();
 }
 
 /// The base class for all of the elements in the element model. Generally
@@ -558,6 +546,9 @@
   /// Return  `true` if this element has an annotation of the form `@mustCallSuper`.
   bool get hasMustCallSuper;
 
+  /// Return  `true` if this element has an annotation of the form `@nonVirtual`.
+  bool get hasNonVirtual;
+
   /// Return `true` if this element has an annotation of the form
   /// `@optionalTypeArgs`.
   bool get hasOptionalTypeArgs;
@@ -585,55 +576,20 @@
   /// The unique integer identifier of this element.
   int get id;
 
-  /// Return `true` if this element has an annotation of the form
-  /// '@alwaysThrows'.
-  @deprecated
-  bool get isAlwaysThrows;
-
-  /// Return `true` if this element has an annotation of the form '@deprecated'
-  /// or '@Deprecated('..')'.
-  @deprecated
-  bool get isDeprecated;
-
-  /// Return `true` if this element has an annotation of the form '@factory'.
-  @deprecated
-  bool get isFactory;
-
-  /// Return `true` if this element has an annotation of the form '@JS(..)'.
-  @deprecated
-  bool get isJS;
-
-  /// Return `true` if this element has an annotation of the form '@override'.
-  @deprecated
-  bool get isOverride;
-
   /// Return `true` if this element is private. Private elements are visible
   /// only within the library in which they are declared.
   bool get isPrivate;
 
-  /// Return `true` if this element has an annotation of the form '@protected'.
-  @deprecated
-  bool get isProtected;
-
   /// Return `true` if this element is public. Public elements are visible
   /// within any library that imports the library in which they are declared.
   bool get isPublic;
 
-  /// Return `true` if this element has an annotation of the form '@required'.
-  @deprecated
-  bool get isRequired;
-
   /// Return `true` if this element is synthetic. A synthetic element is an
   /// element that is not represented in the source code explicitly, but is
   /// implied by the source code, such as the default constructor for a class
   /// that does not explicitly define any constructors.
   bool get isSynthetic;
 
-  /// Return `true` if this element has an annotation of the form
-  /// '@visibleForTesting'.
-  @deprecated
-  bool get isVisibleForTesting;
-
   /// Return the kind of element that this is.
   ElementKind get kind;
 
@@ -671,42 +627,10 @@
   @override
   Source get source;
 
-  /// Return the resolved [CompilationUnit] that declares this element, or
-  /// `null` if this element is synthetic.
-  ///
-  /// This method is expensive, because resolved AST might have been already
-  /// evicted from cache, so parsing and resolving will be performed.
-  @deprecated
-  CompilationUnit get unit;
-
   /// Use the given [visitor] to visit this element. Return the value returned
   /// by the visitor as a result of visiting this element.
   T accept<T>(ElementVisitor<T> visitor);
 
-  /// Return the documentation comment for this element as it appears in the
-  /// original source (complete with the beginning and ending delimiters), or
-  /// `null` if this element does not have a documentation comment associated
-  /// with it. This can be a long-running operation if the information needed to
-  /// access the comment is not cached.
-  ///
-  /// Throws [AnalysisException] if the documentation comment could not be
-  /// determined because the analysis could not be performed
-  ///
-  /// Deprecated.  Use [documentationComment] instead.
-  @deprecated
-  String computeDocumentationComment();
-
-  /// Return the resolved [AstNode] node that declares this element, or `null`
-  /// if this element is synthetic or isn't contained in a compilation unit,
-  /// such as a [LibraryElement].
-  ///
-  /// This method is expensive, because resolved AST might be evicted from
-  /// cache, so parsing and resolving will be performed.
-  ///
-  /// <b>Note:</b> This method cannot be used in an async environment.
-  @deprecated
-  AstNode computeNode();
-
   /// Return the most immediate ancestor of this element for which the
   /// [predicate] returns `true`, or `null` if there is no such ancestor. Note
   /// that this element will never be returned.
@@ -786,6 +710,10 @@
   /// overriding methods to call super.
   bool get isMustCallSuper;
 
+  /// Return `true` if this annotation marks the associated member as being
+  /// non-virtual.
+  bool get isNonVirtual;
+
   /// Return `true` if this annotation marks the associated type as
   /// having "optional" type arguments.
   bool get isOptionalTypeArgs;
@@ -1133,14 +1061,6 @@
   /// element that is not associated with a particular instance, but rather with
   /// an entire library or class.
   bool get isStatic;
-
-  /// Returns `true` if this field can be overridden in strong mode.
-  @deprecated
-  bool get isVirtual;
-
-  @deprecated
-  @override
-  AstNode computeNode();
 }
 
 /// A field formal parameter defined within a constructor element.
@@ -1176,10 +1096,6 @@
   /// Return `true` if the function is an entry point, i.e. a top-level function
   /// and has the name `main`.
   bool get isEntryPoint;
-
-  @deprecated
-  @override
-  FunctionDeclaration computeNode();
 }
 
 /// A function type alias (`typedef`).
@@ -1194,21 +1110,18 @@
   /// type on the right side of the equals.
   GenericFunctionTypeElement get function;
 
-  @deprecated
-  @override
-  TypeAlias computeNode();
-
   /// Produces the function type resulting from instantiating this typedef with
-  /// the given type arguments.
+  /// the given [typeArguments] and [nullabilitySuffix].
   ///
-  /// Note that for a generic typedef, this instantiates the typedef, not the
-  /// generic function type associated with it.  So, for example, if the typedef
-  /// is:
+  /// Note that this always instantiates the typedef itself, so for a
+  /// [GenericTypeAliasElement] the returned [FunctionType] might still be a
+  /// generic function, with type formals. For example, if the typedef is:
   ///     typedef F<T> = void Function<U>(T, U);
-  /// then a single type argument should be provided, and it will be substituted
-  /// for T.
-  @deprecated
-  FunctionType instantiate(List<DartType> argumentTypes);
+  /// then `F<int>` will produce `void Function<U>(int, U)`.
+  FunctionType instantiate({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  });
 
   /// Produces the function type resulting from instantiating this typedef with
   /// the given [typeArguments] and [nullabilitySuffix].
@@ -1218,6 +1131,7 @@
   /// generic function, with type formals. For example, if the typedef is:
   ///     typedef F<T> = void Function<U>(T, U);
   /// then `F<int>` will produce `void Function<U>(int, U)`.
+  @Deprecated('Use instantiate() instead')
   FunctionType instantiate2({
     @required List<DartType> typeArguments,
     @required NullabilitySuffix nullabilitySuffix,
@@ -1248,8 +1162,7 @@
 /// Clients may not extend, implement, or mix-in this class.
 abstract class GenericFunctionTypeElement implements FunctionTypedElement {}
 
-/// A [FunctionTypeAliasElement] whose returned function type has a [type]
-/// parameter.
+/// A synonym for [FunctionTypeAliasElement].
 ///
 /// Clients may not extend, implement, or mix-in this class.
 abstract class GenericTypeAliasElement implements FunctionTypeAliasElement {}
@@ -1359,10 +1272,6 @@
 
   bool get isNonNullableByDefault;
 
-  /// Return a list containing the strongly connected component in the
-  /// import/export graph in which the current library resides.
-  List<LibraryElement> get libraryCycle;
-
   /// Return the element representing the synthetic function `loadLibrary` that
   /// is implicitly defined for this library if the library is imported using a
   /// deferred import.
@@ -1405,21 +1314,7 @@
 /// or function (an [ExecutableElement]).
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class LocalElement implements Element {
-  /// Return a source range that covers the approximate portion of the source in
-  /// which the name of this element is visible, or `null` if there is no single
-  /// range of characters within which the element name is visible.
-  ///
-  /// * For a local variable, this is the source range of the block that
-  ///   encloses the variable declaration.
-  /// * For a parameter, this includes the body of the method or function that
-  ///   declares the parameter.
-  /// * For a local function, this is the source range of the block that
-  ///   encloses the variable declaration.
-  /// * For top-level functions, `null` will be returned because they are
-  ///   potentially visible in multiple sources.
-  SourceRange get visibleRange;
-}
+abstract class LocalElement implements Element {}
 
 /// A local variable.
 ///
@@ -1432,11 +1327,7 @@
 /// be contained within an extension element.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class MethodElement implements ClassMemberElement, ExecutableElement {
-  @deprecated
-  @override
-  MethodDeclaration computeNode();
-}
+abstract class MethodElement implements ClassMemberElement, ExecutableElement {}
 
 /// A pseudo-element that represents multiple elements defined within a single
 /// scope that have the same name. This situation is not allowed by the
@@ -1451,6 +1342,7 @@
   List<Element> get conflictingElements;
 
   /// Return the type of this element as the dynamic type.
+  @deprecated
   DartType get type;
 }
 
@@ -1549,10 +1441,6 @@
   /// Append the type, name and possibly the default value of this parameter to
   /// the given [buffer].
   void appendToWithoutDelimiters(StringBuffer buffer);
-
-  @deprecated
-  @override
-  FormalParameter computeNode();
 }
 
 /// A prefix used to import one or more libraries into another library.
@@ -1561,14 +1449,6 @@
 abstract class PrefixElement implements Element {
   @override
   LibraryElement get enclosingElement;
-
-  /// Return the empty list.
-  ///
-  /// Deprecated: this getter was intended to return a list containing all of
-  /// the libraries that are imported using this prefix, but it was never
-  /// implemented.  Due to lack of demand, it is being removed.
-  @deprecated
-  List<LibraryElement> get importedLibraries;
 }
 
 /// A variable that might be subject to type promotion.  This might be a local
@@ -1636,11 +1516,6 @@
   /// will be synthetic.
   PropertyAccessorElement get getter;
 
-  /// Return the propagated type of this variable, or `null` if type propagation
-  /// has not been performed, for example because the variable is not final.
-  @deprecated
-  DartType get propagatedType;
-
   /// Return the setter associated with this variable, or `null` if the variable
   /// is effectively `final` and therefore does not have a setter associated
   /// with it. (This can happen either because the variable is explicitly
@@ -1671,17 +1546,14 @@
 /// A top-level variable.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class TopLevelVariableElement implements PropertyInducingElement {
-  @deprecated
-  @override
-  VariableDeclaration computeNode();
-}
+abstract class TopLevelVariableElement implements PropertyInducingElement {}
 
 /// An element that defines a type.
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class TypeDefiningElement implements Element {
   /// Return the type defined by this element.
+  @deprecated
   DartType get type;
 }
 
@@ -1696,6 +1568,7 @@
   DartType get bound;
 
   @override
+  @deprecated
   TypeParameterType get type;
 
   /// Create the [TypeParameterType] with the given [nullabilitySuffix] for
@@ -1785,28 +1658,6 @@
   @experimental
   bool get isLate;
 
-  /// Return `true` if this variable is potentially mutated somewhere in a
-  /// closure. This information is only available for local variables (including
-  /// parameters) and only after the compilation unit containing the variable
-  /// has been resolved.
-  ///
-  /// This getter is deprecated--it now returns `true` for all local variables
-  /// and parameters.  Please use [FunctionBody.isPotentiallyMutatedInClosure]
-  /// instead.
-  @deprecated
-  bool get isPotentiallyMutatedInClosure;
-
-  /// Return `true` if this variable is potentially mutated somewhere in its
-  /// scope. This information is only available for local variables (including
-  /// parameters) and only after the compilation unit containing the variable
-  /// has been resolved.
-  ///
-  /// This getter is deprecated--it now returns `true` for all local variables
-  /// and parameters.  Please use [FunctionBody.isPotentiallyMutatedInClosure]
-  /// instead.
-  @deprecated
-  bool get isPotentiallyMutatedInScope;
-
   /// Return `true` if this element is a static variable, as per section 8 of
   /// the Dart Language Specification:
   ///
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index f147121..6462cde 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -21,7 +21,6 @@
 /// the references to `String` and `int` are type arguments.
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart' show InterfaceTypeImpl;
-import 'package:analyzer/src/generated/type_system.dart' show TypeSystem;
 
 /// The type associated with elements in the element model.
 ///
@@ -112,48 +111,6 @@
   /// such as when the type represents the type of an unnamed function.
   String get name;
 
-  /// Implements the function "flatten" defined in the spec, where T is this
-  /// type:
-  ///
-  ///     If T = Future<S> then flatten(T) = flatten(S).
-  ///
-  ///     Otherwise if T <: Future then let S be a type such that T << Future<S>
-  ///     and for all R, if T << Future<R> then S << R.  Then flatten(T) = S.
-  ///
-  ///     In any other circumstance, flatten(T) = T.
-  @Deprecated('Use TypeSystem.flatten() instead.')
-  DartType flattenFutures(TypeSystem typeSystem);
-
-  /// Return `true` if this type is assignable to the given [type]. A type
-  /// <i>T</i> may be assigned to a type <i>S</i>, written <i>T</i> &hArr;
-  /// <i>S</i>, iff either <i>T</i> <: <i>S</i> or <i>S</i> <: <i>T</i>.
-  @Deprecated('Use TypeSystem.isAssignableTo() instead.')
-  bool isAssignableTo(DartType type);
-
-  /// Indicates whether `this` represents a type that is equivalent to `dest`.
-  ///
-  /// This is different from `operator==`.  Consider for example:
-  ///
-  ///     typedef void F<T>(); // T not used!
-  ///
-  /// `operator==` would consider F<int> and F<bool> to be different types;
-  /// `isEquivalentTo` considers them to be equivalent.
-  @Deprecated('operator== was fixed. Use it instead.')
-  bool isEquivalentTo(DartType dest);
-
-  /// Return `true` if this type is more specific than the given [type].
-  @Deprecated('Use TypeSystem.isSubtypeOf() instead.')
-  bool isMoreSpecificThan(DartType type);
-
-  /// Return `true` if this type is a subtype of the given [type].
-  bool isSubtypeOf(DartType type);
-
-  /// Return `true` if this type is a supertype of the given [type]. A type
-  /// <i>S</i> is a supertype of <i>T</i>, written <i>S</i> :> <i>T</i>, iff
-  /// <i>T</i> is a subtype of <i>S</i>.
-  @Deprecated('Use TypeSystem.isSubtypeOf() instead.')
-  bool isSupertypeOf(DartType type);
-
   /// If this type is a [TypeParameterType], returns its bound if it has one, or
   /// [objectType] otherwise.
   ///
@@ -176,6 +133,9 @@
   ///
   /// Note too that the current implementation of this method is only guaranteed
   /// to work when the parameter types are type variables.
+  @Deprecated("""
+Use ClassElement.instantiate() or FunctionTypeAliasElement.instantiate()
+""")
   DartType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
 }
@@ -236,7 +196,8 @@
   /// The formal type parameters of this generic function.
   /// For example `<T> T -> T`.
   ///
-  /// These are distinct from the [typeParameters] list, which contains type
+  /// TODO(scheglov) Remove the mention for "typeParameters".
+  /// These are distinct from the `typeParameters` list, which contains type
   /// parameters from surrounding contexts, and thus are free type variables
   /// from the perspective of this function type.
   List<TypeParameterElement> get typeFormals;
@@ -244,67 +205,7 @@
   @override
   FunctionType instantiate(List<DartType> argumentTypes);
 
-  /// Return `true` if this type is a subtype of the given [type].
-  ///
-  /// A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T</i>
-  /// is a subtype of the function type <i>(S<sub>1</sub>, &hellip;,
-  /// S<sub>n</sub>) &rarr; S</i>, if all of the following conditions are met:
-  ///
-  /// * Either
-  ///   * <i>S</i> is void, or
-  ///   * <i>T &hArr; S</i>.
-  ///
-  /// * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr;
-  ///   S<sub>i</sub></i>.
-  ///
-  /// A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>,
-  /// [T<sub>n+1</sub>, &hellip;, T<sub>n+k</sub>]) &rarr; T</i> is a subtype of
-  /// the function type <i>(S<sub>1</sub>, &hellip;, S<sub>n</sub>,
-  /// [S<sub>n+1</sub>, &hellip;, S<sub>n+m</sub>]) &rarr; S</i>, if all of the
-  /// following conditions are met:
-  ///
-  /// * Either
-  ///   * <i>S</i> is void, or
-  ///   * <i>T &hArr; S</i>.
-  ///
-  /// * <i>k</i> >= <i>m</i> and for all <i>i</i>, 1 <= <i>i</i> <= <i>n+m</i>,
-  ///   <i>T<sub>i</sub> &hArr; S<sub>i</sub></i>.
-  ///
-  /// A function type <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>,
-  /// {T<sub>x1</sub> x1, &hellip;, T<sub>xk</sub> xk}) &rarr; T</i> is a
-  /// subtype of the function type <i>(S<sub>1</sub>, &hellip;, S<sub>n</sub>,
-  /// {S<sub>y1</sub> y1, &hellip;, S<sub>ym</sub> ym}) &rarr; S</i>, if all of
-  /// the following conditions are met:
-  /// * Either
-  ///   * <i>S</i> is void,
-  ///   * or <i>T &hArr; S</i>.
-  ///
-  /// * For all <i>i</i>, 1 <= <i>i</i> <= <i>n</i>, <i>T<sub>i</sub> &hArr;
-  ///   S<sub>i</sub></i>.
-  /// * <i>k</i> >= <i>m</i> and <i>y<sub>i</sub></i> in <i>{x<sub>1</sub>,
-  ///   &hellip;, x<sub>k</sub>}</i>, 1 <= <i>i</i> <= <i>m</i>.
-  /// * For all <i>y<sub>i</sub></i> in <i>{y<sub>1</sub>, &hellip;,
-  ///   y<sub>m</sub>}</i>, <i>y<sub>i</sub> = x<sub>j</sub> => Tj &hArr;
-  ///   Si</i>.
-  ///
-  /// In addition, the following subtype rules apply:
-  ///
-  /// <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, []) &rarr; T <:
-  /// (T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T.</i><br>
-  /// <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>,
-  /// &hellip;, T<sub>n</sub>, {}) &rarr; T.</i><br>
-  /// <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>, {}) &rarr; T <:
-  /// (T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T.</i><br>
-  /// <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub>) &rarr; T <: (T<sub>1</sub>,
-  /// &hellip;, T<sub>n</sub>, []) &rarr; T.</i>
-  ///
-  /// All functions implement the class `Function`. However not all function
-  /// types are a subtype of `Function`. If an interface type <i>I</i> includes
-  /// a method named `call()`, and the type of `call()` is the function type
-  /// <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>.
-  @override
-  bool isSubtypeOf(DartType type);
-
+  @Deprecated("Use FunctionTypeAliasElement.instantiate()")
   @override
   FunctionType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
@@ -374,30 +275,10 @@
   /// with the given name.
   PropertyAccessorElement getSetter(String name);
 
+  @Deprecated("Use ClassElement.instantiate()")
   @override
   InterfaceType instantiate(List<DartType> argumentTypes);
 
-  /// Return `true` if this type is a direct supertype of the given [type]. The
-  /// implicit interface of class <i>I</i> is a direct supertype of the implicit
-  /// interface of class <i>J</i> iff:
-  ///
-  /// * <i>I</i> is Object, and <i>J</i> has no extends clause.
-  /// * <i>I</i> is listed in the extends clause of <i>J</i>.
-  /// * <i>I</i> is listed in the implements clause of <i>J</i>.
-  /// * <i>I</i> is listed in the with clause of <i>J</i>.
-  /// * <i>J</i> is a mixin application of the mixin of <i>I</i>.
-  @Deprecated('This method was used internally, and is not used anymore.')
-  bool isDirectSupertypeOf(InterfaceType type);
-
-  /// Return `true` if this type is a subtype of the given [type]. An interface
-  /// type <i>T</i> is a subtype of an interface type <i>S</i>, written <i>T</i>
-  /// <: <i>S</i>, iff <i>[bottom/dynamic]T</i> &laquo; <i>S</i> (<i>T</i> is
-  /// more specific than <i>S</i>). If an interface type <i>I</i> includes a
-  /// method named <i>call()</i>, and the type of <i>call()</i> is the function
-  /// type <i>F</i>, then <i>I</i> is considered to be a subtype of <i>F</i>.
-  @override
-  bool isSubtypeOf(DartType type);
-
   /// Return the element representing the constructor that results from looking
   /// up the constructor with the given [name] in this class with respect to the
   /// given [library], or `null` if the look up fails. The behavior of this
@@ -558,6 +439,7 @@
   PropertyAccessorElement lookUpSetterInSuperclass(
       String name, LibraryElement library);
 
+  @Deprecated("Use ClassElement.instantiate()")
   @override
   InterfaceType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
@@ -593,20 +475,22 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class ParameterizedType implements DartType {
-  /// Return a list containing the actual types of the type arguments. If this
-  /// type's element does not have type parameters, then the array should be
-  /// empty (although it is possible for type arguments to be erroneously
-  /// declared). If the element has type parameters and the actual type does not
-  /// explicitly include argument values, then the type "dynamic" will be
-  /// automatically provided.
+  /// Return the type arguments used to instantiate this type.
+  ///
+  /// An [InterfaceType] always has type arguments.
+  ///
+  /// A [FunctionType] has type arguments only if it is a result of a typedef
+  /// instantiation, otherwise the result is `null`.
   List<DartType> get typeArguments;
 
   /// Return a list containing all of the type parameters declared for this
   /// type.
+  @Deprecated("Use ClassElement.typeParameters or FunctionType.typeFormals")
   List<TypeParameterElement> get typeParameters;
 
   /// Return the type resulting from instantiating (replacing) the given
   /// [argumentTypes] for this type's bound type parameters.
+  @Deprecated("Use ClassElement.instantiate()")
   ParameterizedType instantiate(List<DartType> argumentTypes);
 }
 
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 821ed3e..75cf369 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -4,6 +4,8 @@
 
 import 'dart:collection';
 
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/error/ffi_code.dart';
@@ -15,10 +17,8 @@
 import 'package:analyzer/src/generated/resolver.dart' show ResolverErrorCode;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/manifest/manifest_warning_code.dart';
-import 'package:front_end/src/base/errors.dart';
-import 'package:front_end/src/scanner/errors.dart';
 
-export 'package:front_end/src/base/errors.dart'
+export 'package:_fe_analyzer_shared/src/base/errors.dart'
     show ErrorCode, ErrorSeverity, ErrorType;
 
 const List<ErrorCode> errorCodeValues = const [
@@ -72,6 +72,7 @@
   CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
   CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_EITHER,
   CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
+  // ignore: deprecated_member_use_from_same_package
   CompileTimeErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
   CompileTimeErrorCode.ASSERT_IN_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT,
@@ -156,7 +157,6 @@
   CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES,
   CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE,
-  CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED,
   CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND,
   CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT,
   CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
@@ -335,7 +335,6 @@
   FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
   FfiCode.MUST_BE_A_SUBTYPE,
   FfiCode.NON_CONSTANT_TYPE_ARGUMENT,
-  FfiCode.NON_CONSTANT_TYPE_ARGUMENT_TO_POINTER,
   FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER,
   FfiCode.SUBTYPE_OF_FFI_CLASS_IN_EXTENDS,
   FfiCode.SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS,
@@ -371,6 +370,8 @@
   HintCode.INVALID_FACTORY_METHOD_IMPL,
   HintCode.INVALID_IMMUTABLE_ANNOTATION,
   HintCode.INVALID_LITERAL_ANNOTATION,
+  HintCode.INVALID_NON_VIRTUAL_ANNOTATION,
+  HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER,
   HintCode.INVALID_REQUIRED_NAMED_PARAM,
   HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM,
   // ignore: deprecated_member_use_from_same_package
diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart
index 9cceca8..124d667 100644
--- a/pkg/analyzer/lib/error/listener.dart
+++ b/pkg/analyzer/lib/error/listener.dart
@@ -4,6 +4,7 @@
 
 import 'dart:collection';
 
+import 'package:_fe_analyzer_shared/src/messages/codes.dart' show Message;
 import 'package:analyzer/dart/ast/ast.dart' show AstNode;
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -11,7 +12,6 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/fasta_codes.dart' show Message;
 import 'package:source_span/source_span.dart';
 
 /**
diff --git a/pkg/analyzer/lib/exception/exception.dart b/pkg/analyzer/lib/exception/exception.dart
index 73b1a5d..5fd7348 100644
--- a/pkg/analyzer/lib/exception/exception.dart
+++ b/pkg/analyzer/lib/exception/exception.dart
@@ -45,6 +45,11 @@
   final Object exception;
 
   /**
+   * The message describing where/how/why this was caught.
+   */
+  final String message;
+
+  /**
    * The stack trace associated with the exception.
    */
   StackTrace stackTrace;
@@ -53,16 +58,21 @@
    * Initialize a newly created caught exception to have the given [exception]
    * and [stackTrace].
    */
-  CaughtException(this.exception, stackTrace) {
-    if (stackTrace == null) {
-      try {
-        throw this;
-      } catch (_, st) {
-        stackTrace = st;
-      }
-    }
-    this.stackTrace = stackTrace;
-  }
+  CaughtException(exception, stackTrace)
+      : this.withMessage(null, exception, stackTrace);
+
+  /**
+   * Initialize a newly created caught exception to have the given [exception],
+   * [stackTrace], and [message].
+   */
+  CaughtException.withMessage(this.message, this.exception, stackTrace)
+      : this.stackTrace = stackTrace ?? StackTrace.current;
+
+  /**
+   * Create a [CaughtException] to wrap a prior one, adding a [message].
+   */
+  CaughtException.wrapInMessage(String message, CaughtException exception)
+      : this.withMessage(message, exception, null);
 
   @override
   String toString() {
@@ -76,6 +86,9 @@
    * stack trace.
    */
   void _writeOn(StringBuffer buffer) {
+    if (message != null) {
+      buffer.writeln(message);
+    }
     if (exception is AnalysisException) {
       AnalysisException analysisException = exception;
       buffer.writeln(analysisException.message);
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index 63920eb..449fb2c 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -131,7 +131,7 @@
    * Log that the given non-priority [exception] was thrown, with the given
    * [stackTrace].
    */
-  void logException(dynamic exception, StackTrace stackTrace) {
+  void logException(dynamic exception, [StackTrace stackTrace]) {
     if (_instrumentationServer != null) {
       String message = _toString(exception);
       String trace = _toString(stackTrace);
@@ -154,7 +154,8 @@
   /**
    * Log unstructured text information for debugging purposes.
    */
-  void logInfo(String message) => _log(TAG_INFO, message);
+  void logInfo(String message, [dynamic exception]) =>
+      _log(TAG_INFO, message + (exception == null ? "" : _toString(exception)));
 
   /**
    * Log that a log entry that was written to the analysis engine's log. The log
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index a1840b0..eb36757 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -406,8 +406,10 @@
     SdkDescription description =
         new SdkDescription(<String>[sdkPath], analysisOptions);
     return sdkManager.getSdk(description, () {
-      FolderBasedDartSdk sdk = new FolderBasedDartSdk(
-          resourceProvider, resourceProvider.getFolder(sdkPath), true);
+      var sdk = FolderBasedDartSdk(
+        resourceProvider,
+        resourceProvider.getFolder(sdkPath),
+      );
       sdk.analysisOptions = analysisOptions;
       sdk.useSummary = sdkManager.canUseSummaries;
       return sdk;
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
deleted file mode 100644
index e0b4d6a..0000000
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-import 'package:analyzer/src/generated/engine.dart';
-
-class AnalysisCache {
-  AnalysisCache(List<CachePartition> partitions);
-}
-
-abstract class CachePartition {
-  final InternalAnalysisContext context;
-  CachePartition(this.context);
-}
-
-class SdkCachePartition extends CachePartition {
-  SdkCachePartition(InternalAnalysisContext context) : super(context);
-}
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index be54661..e1cdfc4 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -2,11 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
 import 'package:analyzer/src/generated/source.dart';
 
 /**
@@ -87,32 +85,6 @@
   TypeSystem get typeSystem {
     return _typeSystem ??= Dart2TypeSystem(typeProvider);
   }
-
-  /**
-   * Create an analysis cache based on the given source [factory].
-   */
-  AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    throw UnimplementedError();
-  }
-}
-
-/**
- * An object that manages the partitions that can be shared between analysis
- * contexts.
- */
-class PartitionManager {
-  /**
-   * Clear any cached data being maintained by this manager.
-   */
-  void clearCache() {}
-
-  /**
-   * Return the partition being used for the given [sdk], creating the partition
-   * if necessary.
-   */
-  SdkCachePartition forSdk(DartSdk sdk) {
-    throw UnimplementedError();
-  }
 }
 
 /**
@@ -134,9 +106,4 @@
   void set analysisOptions(AnalysisOptions options) {
     throw new StateError('AnalysisOptions of SDK context cannot be changed.');
   }
-
-  @override
-  AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    throw UnimplementedError();
-  }
 }
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 07a26ee..05cbe28 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -21,9 +21,6 @@
  * against an existing [Source].
  */
 class SourceFactoryImpl implements SourceFactory {
-  @override
-  AnalysisContext context;
-
   /**
    * URI processor used to find mappings for `package:` URIs found in a
    * `.packages` config file.
@@ -41,11 +38,6 @@
   final List<UriResolver> resolvers;
 
   /**
-   * The predicate to determine is [Source] is local.
-   */
-  LocalSourcePredicate _localSourcePredicate = LocalSourcePredicate.NOT_SDK;
-
-  /**
    * Cache of mapping of absolute [Uri]s to [Source]s.
    */
   final HashMap<Uri, Source> _absoluteUriToSourceCache =
@@ -75,11 +67,6 @@
   }
 
   @override
-  void set localSourcePredicate(LocalSourcePredicate localSourcePredicate) {
-    this._localSourcePredicate = localSourcePredicate;
-  }
-
-  @override
   Map<String, List<Folder>> get packageMap {
     // Start by looking in .packages.
     if (_packages != null) {
@@ -109,24 +96,23 @@
   }
 
   @override
-  SourceFactory clone() {
-    SourceFactory factory =
-        new SourceFactory(resolvers, _packages, _resourceProvider);
-    factory.localSourcePredicate = _localSourcePredicate;
-    return factory;
-  }
-
-  @override
   Source forUri(String absoluteUri) {
     try {
-      Uri uri = Uri.parse(absoluteUri);
+      Uri uri;
+      try {
+        uri = Uri.parse(absoluteUri);
+      } catch (exception, stackTrace) {
+        AnalysisEngine.instance.instrumentationService
+            .logInfo('Could not resolve URI: $absoluteUri $stackTrace');
+        return null;
+      }
       if (uri.isAbsolute) {
         return _internalResolveUri(null, uri);
       }
     } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logError(
-          "Could not resolve URI: $absoluteUri",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              "Could not resolve URI: $absoluteUri", exception, stackTrace));
     }
     return null;
   }
@@ -137,27 +123,15 @@
       try {
         return _internalResolveUri(null, absoluteUri);
       } on AnalysisException catch (exception, stackTrace) {
-        AnalysisEngine.instance.logger.logError(
-            "Could not resolve URI: $absoluteUri",
-            new CaughtException(exception, stackTrace));
+        AnalysisEngine.instance.instrumentationService.logException(
+            new CaughtException.withMessage(
+                "Could not resolve URI: $absoluteUri", exception, stackTrace));
       }
     }
     return null;
   }
 
   @override
-  Source fromEncoding(String encoding) {
-    Source source = forUri(encoding);
-    if (source == null) {
-      throw new ArgumentError("Invalid source encoding: '$encoding'");
-    }
-    return source;
-  }
-
-  @override
-  bool isLocalSource(Source source) => _localSourcePredicate.isLocal(source);
-
-  @override
   Source resolveUri(Source containingSource, String containedUri) {
     if (containedUri == null || containedUri.isEmpty) {
       return null;
@@ -170,10 +144,12 @@
     } catch (exception, stackTrace) {
       String containingFullName =
           containingSource != null ? containingSource.fullName : '<null>';
-      AnalysisEngine.instance.logger.logInformation(
-          "Could not resolve URI ($containedUri) "
-          "relative to source ($containingFullName)",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService
+          .logException(new CaughtException.withMessage(
+              "Could not resolve URI ($containedUri) "
+              "relative to source ($containingFullName)",
+              exception,
+              stackTrace));
       return null;
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index f5a7f9a..75e72e1a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -287,7 +287,7 @@
       SummaryDataStore externalSummaries,
       bool retainDataForTesting: false})
       : _logger = logger,
-        _sourceFactory = sourceFactory.clone(),
+        _sourceFactory = sourceFactory,
         _externalSummaries = externalSummaries,
         testingData = retainDataForTesting ? TestingData() : null {
     _createNewSession(null);
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 6d35e0e..1ca44d2 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
@@ -6,8 +6,10 @@
 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/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' show AnalysisDriver;
 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.
@@ -27,6 +29,11 @@
   final AnalysisDriver driver;
 
   /**
+   * The [Workspace] for this context, `null` if not yet created.
+   */
+  Workspace _workspace;
+
+  /**
    * Initialize a newly created context that uses the given [resourceProvider]
    * to access the file system and that is based on the given analysis [driver].
    */
@@ -49,6 +56,11 @@
   @override
   List<String> get includedPaths => contextRoot.includedPaths.toList();
 
+  @override
+  Workspace get workspace {
+    return _workspace ??= _buildWorkspace();
+  }
+
   @deprecated
   @override
   Iterable<String> analyzedFiles() {
@@ -60,4 +72,11 @@
   bool isAnalyzed(String path) {
     return contextRoot.isAnalyzed(path);
   }
+
+  Workspace _buildWorkspace() {
+    String path = contextRoot.root.path;
+    ContextBuilder builder = ContextBuilder(
+        resourceProvider, null /* sdkManager */, null /* contentCache */);
+    return ContextBuilder.createWorkspace(resourceProvider, path, builder);
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 23f3f02..4f2d73a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
@@ -32,7 +33,6 @@
 import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:convert/convert.dart';
 import 'package:crypto/crypto.dart';
-import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:meta/meta.dart';
 
 var counterFileStateRefresh = 0;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 8876844..527a5a2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -41,6 +42,7 @@
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:pub_semver/pub_semver.dart';
 
 var timerLibraryAnalyzer = Stopwatch();
@@ -321,8 +323,19 @@
 
     var nodeRegistry = new NodeLintRegistry(_analysisOptions.enableTiming);
     var visitors = <AstVisitor>[];
-    var context = LinterContextImpl(allUnits, currentUnit, _declaredVariables,
-        _typeProvider, _typeSystem, _inheritance, _analysisOptions);
+
+    final workspacePackage = _getPackage(currentUnit.unit);
+
+    var context = LinterContextImpl(
+      allUnits,
+      currentUnit,
+      _declaredVariables,
+      _typeProvider,
+      _typeSystem,
+      _inheritance,
+      _analysisOptions,
+      workspacePackage,
+    );
     for (Linter linter in _analysisOptions.lintRules) {
       linter.reporter = errorReporter;
       if (linter is NodeLintRule) {
@@ -446,6 +459,23 @@
     });
   }
 
+  WorkspacePackage _getPackage(CompilationUnit unit) {
+    final libraryPath = _library.source.fullName;
+    Workspace workspace =
+        unit.declaredElement.session?.analysisContext?.workspace;
+
+    // If there is no driver setup (as in test environments), we need to create
+    // a workspace ourselves.
+    // todo (pq): fix tests or otherwise de-dup this logic shared w/ resolver.
+    if (workspace == null) {
+      final builder = ContextBuilder(
+          _resourceProvider, null /* sdkManager */, null /* contentCache */);
+      workspace = ContextBuilder.createWorkspace(
+          _resourceProvider, libraryPath, builder);
+    }
+    return workspace?.findPackageFor(libraryPath);
+  }
+
   /**
    * Return the name of the library that the given part is declared to be a
    * part of, or `null` if the part does not contain a part-of directive.
@@ -672,8 +702,8 @@
     if (unit.featureSet.isEnabled(Feature.non_nullable)) {
       flowAnalysisHelper =
           FlowAnalysisHelper(_context.typeSystem, _testingData != null);
-      _testingData?.recordFlowAnalysisResult(
-          file.uri, flowAnalysisHelper.result);
+      _testingData?.recordFlowAnalysisDataForTesting(
+          file.uri, flowAnalysisHelper.dataForTesting);
     }
 
     unit.accept(new ResolverVisitor(
diff --git a/pkg/analyzer/lib/src/dart/analysis/testing_data.dart b/pkg/analyzer/lib/src/dart/analysis/testing_data.dart
index 8d27ede..5e6a288 100644
--- a/pkg/analyzer/lib/src/dart/analysis/testing_data.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/testing_data.dart
@@ -9,11 +9,12 @@
 /// created.
 class TestingData {
   /// Map containing the results of flow analysis.
-  final Map<Uri, FlowAnalysisResult> uriToFlowAnalysisResult = {};
+  final Map<Uri, FlowAnalysisDataForTesting> uriToFlowAnalysisData = {};
 
   /// Called by the analysis driver after performing flow analysis, to record
   /// flow analysis results.
-  void recordFlowAnalysisResult(Uri uri, FlowAnalysisResult result) {
-    uriToFlowAnalysisResult[uri] = result;
+  void recordFlowAnalysisDataForTesting(
+      Uri uri, FlowAnalysisDataForTesting result) {
+    uriToFlowAnalysisData[uri] = result;
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 4e5e5ac..de7f57f 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -15,10 +15,9 @@
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/fasta/token_utils.dart' as util show findPrevious;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
@@ -341,19 +340,6 @@
     ..addAll(_arguments)
     ..add(rightParenthesis);
 
-  @deprecated
-  List<ParameterElement> get correspondingPropagatedParameters => null;
-
-  @deprecated
-  @override
-  void set correspondingPropagatedParameters(
-      List<ParameterElement> parameters) {
-    if (parameters != null && parameters.length != _arguments.length) {
-      throw new ArgumentError(
-          "Expected ${_arguments.length} parameters, not ${parameters.length}");
-    }
-  }
-
   List<ParameterElement> get correspondingStaticParameters =>
       _correspondingStaticParameters;
 
@@ -661,8 +647,9 @@
       } else {
         message = "The right-hand size is null";
       }
-      AnalysisEngine.instance.logger.logError(
-          message, new CaughtException(new AnalysisException(message), null));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException(new AnalysisException(message), null),
+          StackTrace.current);
     }
     _leftHandSide = _becomeParentOf(leftHandSide);
     _rightHandSide = _becomeParentOf(rightHandSide);
@@ -672,10 +659,6 @@
   Token get beginToken => _leftHandSide.beginToken;
 
   @override
-  @deprecated
-  MethodElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_leftHandSide)
     ..add(operator)
@@ -695,14 +678,6 @@
   @override
   Precedence get precedence => Precedence.assignment;
 
-  @deprecated
-  @override
-  MethodElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(MethodElement element) {}
-
   @override
   Expression get rightHandSide => _rightHandSide;
 
@@ -852,7 +827,7 @@
   @override
   String toSource() {
     StringBuffer buffer = new StringBuffer();
-    accept(new ToSourceVisitor2(buffer));
+    accept(new ToSourceVisitor(buffer));
     return buffer.toString();
   }
 
@@ -956,10 +931,6 @@
   Token get beginToken => _leftOperand.beginToken;
 
   @override
-  @deprecated
-  MethodElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_leftOperand)..add(operator)..add(_rightOperand);
 
@@ -977,14 +948,6 @@
   @override
   Precedence get precedence => Precedence.forTokenType(operator.type);
 
-  @deprecated
-  @override
-  MethodElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(MethodElement element) {}
-
   @override
   Expression get rightOperand => _rightOperand;
 
@@ -1511,10 +1474,6 @@
   @override
   ClassElement get declaredElement => _name?.staticElement as ClassElement;
 
-  @deprecated
-  @override
-  ClassElement get element => declaredElement;
-
   @override
   ExtendsClause get extendsClause => _extendsClause;
 
@@ -1754,10 +1713,6 @@
   @override
   ClassElement get declaredElement => _name?.staticElement as ClassElement;
 
-  @deprecated
-  @override
-  ClassElement get element => declaredElement;
-
   @override
   Token get firstTokenAfterCommentAndMetadata {
     if (abstractKeyword != null) {
@@ -2042,15 +1997,6 @@
   @override
   LineInfo lineInfo;
 
-  /// ?
-  // TODO(brianwilkerson) Remove this field. It is never read, only written.
-  Map<int, AstNode> localDeclarations;
-
-  /// Additional information about local variables that are declared within this
-  /// compilation unit but outside any function body, or `null` if resolution
-  /// has not yet been performed.
-  LocalVariableInfo localVariableInfo = new LocalVariableInfo();
-
   @override
   final FeatureSet featureSet;
 
@@ -2088,10 +2034,6 @@
   @override
   NodeList<Directive> get directives => _directives;
 
-  @deprecated
-  @override
-  CompilationUnitElement get element => declaredElement;
-
   @override
   set element(CompilationUnitElement element) {
     declaredElement = element;
@@ -2139,20 +2081,6 @@
   @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitCompilationUnit(this);
 
-  bool isPotentiallyMutatedInClosure(VariableElement variable) {
-    if (localVariableInfo == null) {
-      throw new StateError('Resolution has not yet been performed');
-    }
-    return localVariableInfo.potentiallyMutatedInClosure.contains(variable);
-  }
-
-  bool isPotentiallyMutatedInScope(VariableElement variable) {
-    if (localVariableInfo == null) {
-      throw new StateError('Resolution has not yet been performed');
-    }
-    return localVariableInfo.potentiallyMutatedInScope.contains(variable);
-  }
-
   @override
   void visitChildren(AstVisitor visitor) {
     _scriptTag?.accept(visitor);
@@ -2557,10 +2485,6 @@
 
   @deprecated
   @override
-  ConstructorElement get element => declaredElement;
-
-  @deprecated
-  @override
   set element(ConstructorElement element) {
     declaredElement = element;
   }
@@ -2909,9 +2833,6 @@
   }
 
   @override
-  LocalVariableElement get element => declaredElement;
-
-  @override
   Token get endToken => _identifier.endToken;
 
   @override
@@ -3349,10 +3270,6 @@
   @override
   FieldElement get declaredElement => _name?.staticElement as FieldElement;
 
-  @deprecated
-  @override
-  FieldElement get element => declaredElement;
-
   @override
   Token get endToken => _name.endToken;
 
@@ -3431,10 +3348,6 @@
   @override
   ClassElement get declaredElement => _name?.staticElement as ClassElement;
 
-  @deprecated
-  @override
-  ClassElement get element => declaredElement;
-
   @override
   Token get endToken => rightBracket;
 
@@ -3601,18 +3514,6 @@
   @override
   DartType staticType;
 
-  /// Return the best parameter element information available for this
-  /// expression. If type propagation was able to find a better parameter
-  /// element than static analysis, that type will be returned. Otherwise, the
-  /// result of static analysis will be returned.
-  @override
-  @deprecated
-  ParameterElement get bestParameterElement => staticParameterElement;
-
-  @override
-  @deprecated
-  DartType get bestType => staticType ?? DynamicTypeImpl.instance;
-
   /// An expression _e_ is said to _occur in a constant context_,
   /// * if _e_ is an element of a constant list literal, or a key or value of an
   ///   entry of a constant map literal.
@@ -3670,22 +3571,6 @@
   @override
   bool get isAssignable => false;
 
-  @Deprecated('Use precedence')
-  @override
-  Precedence get precedence2 => precedence;
-
-  @deprecated
-  @override
-  ParameterElement get propagatedParameterElement => null;
-
-  @deprecated
-  @override
-  DartType get propagatedType => null;
-
-  @deprecated
-  @override
-  set propagatedType(DartType type) {}
-
   @override
   ParameterElement get staticParameterElement {
     AstNode parent = this.parent;
@@ -3892,9 +3777,6 @@
   }
 
   @override
-  ExtensionElement get element => declaredElement;
-
-  @override
   Token get endToken => rightBracket;
 
   @override
@@ -4063,10 +3945,6 @@
   @override
   Element get declaredElement => null;
 
-  @deprecated
-  @override
-  Element get element => null;
-
   @override
   Token get endToken => semicolon;
 
@@ -4134,6 +4012,9 @@
   /// function-typed field formal parameter.
   FormalParameterListImpl _parameters;
 
+  @override
+  Token question;
+
   /// Initialize a newly created formal parameter. Either or both of the
   /// [comment] and [metadata] can be `null` if the parameter does not have the
   /// corresponding attribute. The [keyword] can be `null` if there is a type.
@@ -4152,7 +4033,8 @@
       this.period,
       SimpleIdentifierImpl identifier,
       TypeParameterListImpl typeParameters,
-      FormalParameterListImpl parameters)
+      FormalParameterListImpl parameters,
+      this.question)
       : super(
             comment, metadata, covariantKeyword, requiredKeyword, identifier) {
     _type = _becomeParentOf(type);
@@ -4416,10 +4298,6 @@
     return identifier.staticElement as ParameterElement;
   }
 
-  @deprecated
-  @override
-  ParameterElement get element => declaredElement;
-
   @override
   bool get isNamed =>
       kind == ParameterKind.NAMED || kind == ParameterKind.NAMED_REQUIRED;
@@ -4707,6 +4585,7 @@
 
   @override
   Token get beginToken => initialization?.beginToken ?? super.beginToken;
+
   @override
   Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_initialization)
@@ -4886,10 +4765,6 @@
   ExecutableElement get declaredElement =>
       _name?.staticElement as ExecutableElement;
 
-  @deprecated
-  @override
-  ExecutableElement get element => declaredElement;
-
   @override
   Token get endToken => _functionExpression.endToken;
 
@@ -5039,10 +4914,6 @@
 
   @deprecated
   @override
-  ExecutableElement get element => declaredElement;
-
-  @deprecated
-  @override
   set element(ExecutableElement element) {
     declaredElement = element;
   }
@@ -5118,10 +4989,6 @@
   Token get beginToken => _function.beginToken;
 
   @override
-  @deprecated
-  ExecutableElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_function)..add(_argumentList);
 
@@ -5139,14 +5006,6 @@
   @override
   Precedence get precedence => Precedence.postfix;
 
-  @deprecated
-  @override
-  ExecutableElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(ExecutableElement element) {}
-
   @override
   E accept<E>(AstVisitor<E> visitor) =>
       visitor.visitFunctionExpressionInvocation(this);
@@ -5211,10 +5070,6 @@
   FunctionTypeAliasElement get declaredElement =>
       _name?.staticElement as FunctionTypeAliasElement;
 
-  @deprecated
-  @override
-  FunctionTypeAliasElement get element => declaredElement;
-
   @override
   FormalParameterList get parameters => _parameters;
 
@@ -5515,10 +5370,6 @@
   @override
   Element get declaredElement => name.staticElement;
 
-  @deprecated
-  @override
-  Element get element => declaredElement;
-
   @override
   GenericFunctionType get functionType => _functionType;
 
@@ -5590,15 +5441,6 @@
 ///        [SimpleIdentifier]
 ///      | [PrefixedIdentifier]
 abstract class IdentifierImpl extends ExpressionImpl implements Identifier {
-  /// Return the best element available for this operator. If resolution was
-  /// able to find a better element based on type propagation, that element will
-  /// be returned. Otherwise, the element found using the result of static
-  /// analysis will be returned. If resolution has not been performed, then `null` will
-  /// be returned.
-  @override
-  @deprecated
-  Element get bestElement;
-
   @override
   bool get isAssignable => true;
 }
@@ -5962,10 +5804,6 @@
   }
 
   @override
-  @deprecated
-  MethodElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities => new ChildEntities()
     ..add(_target)
     ..add(period)
@@ -5992,19 +5830,14 @@
 
   @override
   bool get isNullAware =>
-      leftBracket.type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET;
+      leftBracket.type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
+      (leftBracket.type == TokenType.OPEN_SQUARE_BRACKET &&
+          period != null &&
+          period.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
   Precedence get precedence => Precedence.postfix;
 
-  @deprecated
-  @override
-  MethodElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(MethodElement element) {}
-
   @override
   Expression get realTarget {
     if (isCascaded) {
@@ -6067,7 +5900,7 @@
     if (parent is PrefixExpression) {
       return parent.operator.type.isIncrementOperator;
     } else if (parent is PostfixExpression) {
-      return true;
+      return parent.operator.type.isIncrementOperator;
     } else if (parent is AssignmentExpression) {
       return identical(parent.leftHandSide, this);
     }
@@ -6451,14 +6284,6 @@
     _argumentList = _becomeParentOf(argumentList as ArgumentListImpl);
   }
 
-  @deprecated
-  @override
-  DartType get propagatedInvokeType => null;
-
-  @deprecated
-  @override
-  set propagatedInvokeType(DartType type) {}
-
   @override
   TypeArgumentList get typeArguments => _typeArguments;
 
@@ -6711,10 +6536,6 @@
   Token get beginToken => _components.beginToken;
 
   @override
-  @deprecated
-  Element get bestElement => staticElement;
-
-  @override
   // TODO(paulberry): add "." tokens.
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..addAll(_components);
@@ -6745,10 +6566,6 @@
   @override
   Precedence get precedence => Precedence.postfix;
 
-  @deprecated
-  @override
-  Element get propagatedElement => null;
-
   @override
   Element get staticElement => null;
 
@@ -7030,10 +6847,6 @@
   ExecutableElement get declaredElement =>
       _name?.staticElement as ExecutableElement;
 
-  @deprecated
-  @override
-  ExecutableElement get element => declaredElement;
-
   @override
   Token get endToken => _body.endToken;
 
@@ -7189,7 +7002,10 @@
           operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
-  bool get isNullAware => operator?.type == TokenType.QUESTION_PERIOD;
+  bool get isNullAware =>
+      operator != null &&
+      (operator.type == TokenType.QUESTION_PERIOD ||
+          operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
   SimpleIdentifier get methodName => _methodName;
@@ -7304,10 +7120,6 @@
   @override
   ClassElement get declaredElement => _name?.staticElement as ClassElement;
 
-  @deprecated
-  @override
-  Element get element => declaredElement;
-
   @override
   Token get firstTokenAfterCommentAndMetadata {
     return mixinKeyword;
@@ -8165,10 +7977,6 @@
   Token get beginToken => _operand.beginToken;
 
   @override
-  @deprecated
-  MethodElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_operand)..add(operator);
 
@@ -8186,14 +7994,6 @@
   @override
   Precedence get precedence => Precedence.postfix;
 
-  @deprecated
-  @override
-  MethodElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(MethodElement element) {}
-
   /// If the AST structure has been resolved, and the function being invoked is
   /// known based on static type information, then return the parameter element
   /// representing the parameter to which the value of the operand will be
@@ -8250,15 +8050,6 @@
   Token get beginToken => _prefix.beginToken;
 
   @override
-  @deprecated
-  Element get bestElement {
-    if (_identifier == null) {
-      return null;
-    }
-    return _identifier.staticElement;
-  }
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(_prefix)..add(period)..add(_identifier);
 
@@ -8301,10 +8092,6 @@
     _prefix = _becomeParentOf(identifier as SimpleIdentifierImpl);
   }
 
-  @deprecated
-  @override
-  Element get propagatedElement => null;
-
   @override
   Element get staticElement {
     if (_identifier == null) {
@@ -8348,10 +8135,6 @@
   Token get beginToken => operator;
 
   @override
-  @deprecated
-  MethodElement get bestElement => staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(operator)..add(_operand);
 
@@ -8369,14 +8152,6 @@
   @override
   Precedence get precedence => Precedence.prefix;
 
-  @deprecated
-  @override
-  MethodElement get propagatedElement => null;
-
-  @deprecated
-  @override
-  set propagatedElement(MethodElement element) {}
-
   /// If the AST structure has been resolved, and the function being invoked is
   /// known based on static type information, then return the parameter element
   /// representing the parameter to which the value of the operand will be
@@ -8452,7 +8227,9 @@
 
   @override
   bool get isNullAware =>
-      operator != null && operator.type == TokenType.QUESTION_PERIOD;
+      operator != null &&
+      (operator.type == TokenType.QUESTION_PERIOD ||
+          operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
   Precedence get precedence => Precedence.postfix;
@@ -8933,10 +8710,6 @@
   Token get beginToken => token;
 
   @override
-  @deprecated
-  Element get bestElement => _staticElement;
-
-  @override
   Iterable<SyntacticEntity> get childEntities =>
       new ChildEntities()..add(token);
 
@@ -8967,14 +8740,6 @@
   @override
   Precedence get precedence => Precedence.primary;
 
-  @deprecated
-  @override
-  Element get propagatedElement => null;
-
-  @deprecated
-  @override
-  void set propagatedElement(Element element) {}
-
   @override
   Element get staticElement => _staticElement;
 
@@ -9067,7 +8832,7 @@
     if (parent is PrefixExpression) {
       return parent.operator.type.isIncrementOperator;
     } else if (parent is PostfixExpression) {
-      return true;
+      return parent.operator.type.isIncrementOperator;
     } else if (parent is AssignmentExpression) {
       return identical(parent.leftHandSide, target);
     } else if (parent is ForEachPartsWithIdentifier) {
@@ -9883,10 +9648,6 @@
   @override
   Element get declaredElement => null;
 
-  @deprecated
-  @override
-  Element get element => null;
-
   @override
   Token get endToken => semicolon;
 
@@ -10248,10 +10009,6 @@
   TypeParameterElement get declaredElement =>
       _name?.staticElement as TypeParameterElement;
 
-  @deprecated
-  @override
-  TypeParameterElement get element => declaredElement;
-
   @override
   Token get endToken {
     if (_bound == null) {
@@ -10486,10 +10243,6 @@
     return comment;
   }
 
-  @deprecated
-  @override
-  VariableElement get element => declaredElement;
-
   @override
   Token get endToken {
     if (_initializer != null) {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 9091adc..9b2cc48 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -2,12 +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:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:meta/meta.dart';
 
 /**
@@ -421,7 +421,7 @@
           TypeParameterList typeParameters,
           FormalParameterList parameters) =>
       new FieldFormalParameterImpl(comment, metadata, null, null, keyword, type,
-          thisKeyword, period, identifier, typeParameters, parameters);
+          thisKeyword, period, identifier, typeParameters, parameters, null);
 
   @override
   FieldFormalParameter fieldFormalParameter2(
@@ -435,7 +435,8 @@
           @required Token period,
           @required SimpleIdentifier identifier,
           TypeParameterList typeParameters,
-          FormalParameterList parameters}) =>
+          FormalParameterList parameters,
+          Token question}) =>
       new FieldFormalParameterImpl(
           comment,
           metadata,
@@ -447,7 +448,8 @@
           period,
           identifier,
           typeParameters,
-          parameters);
+          parameters,
+          question);
 
   @override
   ForEachPartsWithDeclaration forEachPartsWithDeclaration(
diff --git a/pkg/analyzer/lib/src/dart/ast/resolution_map.dart b/pkg/analyzer/lib/src/dart/ast/resolution_map.dart
deleted file mode 100644
index 3fa4ea4..0000000
--- a/pkg/analyzer/lib/src/dart/ast/resolution_map.dart
+++ /dev/null
@@ -1,172 +0,0 @@
-// 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.
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/resolution_map.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-
-/**
- * Concrete implementation of [ResolutionMap] based on the standard AST
- * implementation.
- */
-class ResolutionMapImpl implements ResolutionMap {
-  @deprecated
-  @override
-  ExecutableElement bestElementForFunctionExpressionInvocation(
-          FunctionExpressionInvocation node) =>
-      node.staticElement;
-
-  @deprecated
-  @override
-  Element bestElementForIdentifier(Identifier node) => node.staticElement;
-
-  @deprecated
-  @override
-  MethodElement bestElementForMethodReference(MethodReferenceExpression node) =>
-      node.staticElement;
-
-  @deprecated
-  @override
-  ParameterElement bestParameterElementForExpression(Expression node) =>
-      node.staticParameterElement;
-
-  @deprecated
-  @override
-  DartType bestTypeForExpression(Expression node) => node.staticType;
-
-  @override
-  ElementAnnotation elementAnnotationForAnnotation(Annotation node) =>
-      node.elementAnnotation;
-
-  @override
-  ClassElement elementDeclaredByClassDeclaration(ClassDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  CompilationUnitElement elementDeclaredByCompilationUnit(
-          CompilationUnit node) =>
-      node.declaredElement;
-
-  @override
-  ConstructorElement elementDeclaredByConstructorDeclaration(
-          ConstructorDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  Element elementDeclaredByDeclaration(Declaration node) =>
-      node.declaredElement;
-
-  @override
-  LocalVariableElement elementDeclaredByDeclaredIdentifier(
-          DeclaredIdentifier node) =>
-      node.declaredElement;
-
-  @override
-  Element elementDeclaredByDirective(Directive node) => node.element;
-
-  @override
-  ClassElement elementDeclaredByEnumDeclaration(EnumDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  ParameterElement elementDeclaredByFormalParameter(FormalParameter node) =>
-      node.declaredElement;
-
-  @override
-  ExecutableElement elementDeclaredByFunctionDeclaration(
-          FunctionDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  ExecutableElement elementDeclaredByFunctionExpression(
-          FunctionExpression node) =>
-      node.declaredElement;
-
-  @override
-  ExecutableElement elementDeclaredByMethodDeclaration(
-          MethodDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  ClassElement elementDeclaredByMixinDeclaration(MixinDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  VariableElement elementDeclaredByVariableDeclaration(
-          VariableDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  Element elementForAnnotation(Annotation node) => node.element;
-
-  @override
-  ParameterElement elementForNamedExpression(NamedExpression node) =>
-      node.element;
-
-  @override
-  List<ParameterElement> parameterElementsForFormalParameterList(
-          FormalParameterList node) =>
-      node.parameterElements;
-
-  @deprecated
-  @override
-  ExecutableElement propagatedElementForFunctionExpressionInvocation(
-          FunctionExpressionInvocation node) =>
-      null;
-
-  @deprecated
-  @override
-  Element propagatedElementForIdentifier(Identifier node) => null;
-
-  @deprecated
-  @override
-  MethodElement propagatedElementForMethodReference(
-          MethodReferenceExpression node) =>
-      null;
-
-  @deprecated
-  @override
-  ParameterElement propagatedParameterElementForExpression(Expression node) =>
-      null;
-
-  @deprecated
-  @override
-  DartType propagatedTypeForExpression(Expression node) => null;
-
-  @override
-  ConstructorElement staticElementForConstructorReference(
-          ConstructorReferenceNode node) =>
-      node.staticElement;
-
-  @override
-  ExecutableElement staticElementForFunctionExpressionInvocation(
-          FunctionExpressionInvocation node) =>
-      node.staticElement;
-
-  @override
-  Element staticElementForIdentifier(Identifier node) => node.staticElement;
-
-  @override
-  MethodElement staticElementForMethodReference(
-          MethodReferenceExpression node) =>
-      node.staticElement;
-
-  @override
-  DartType staticInvokeTypeForInvocationExpression(InvocationExpression node) =>
-      node.staticInvokeType;
-
-  @override
-  ParameterElement staticParameterElementForExpression(Expression node) =>
-      node.staticParameterElement;
-
-  @override
-  DartType staticTypeForExpression(Expression node) => node.staticType;
-
-  @override
-  DartType typeForTypeName(TypeAnnotation node) => node.type;
-
-  @override
-  Element uriElementForDirective(UriBasedDirective node) => node.uriElement;
-}
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
new file mode 100644
index 0000000..7cd5a86
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -0,0 +1,1200 @@
+// 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:meta/meta.dart';
+
+/**
+ * A visitor used to write a source representation of a visited AST node (and
+ * all of it's children) to a sink.
+ */
+class ToSourceVisitor implements AstVisitor<void> {
+  /**
+   * The sink to which the source is to be written.
+   */
+  @protected
+  final StringSink sink;
+
+  /**
+   * Initialize a newly created visitor to write source code representing the
+   * visited nodes to the given [sink].
+   */
+  ToSourceVisitor(this.sink);
+
+  /**
+   * Visit the given function [body], printing the [prefix] before if the body
+   * is not empty.
+   */
+  @protected
+  void safelyVisitFunctionWithPrefix(String prefix, FunctionBody body) {
+    if (body is! EmptyFunctionBody) {
+      sink.write(prefix);
+    }
+    safelyVisitNode(body);
+  }
+
+  /**
+   * Safely visit the given [node].
+   */
+  @protected
+  void safelyVisitNode(AstNode node) {
+    if (node != null) {
+      node.accept(this);
+    }
+  }
+
+  /**
+   * Print a list of [nodes] without any separation.
+   */
+  @protected
+  void safelyVisitNodeList(NodeList<AstNode> nodes) {
+    safelyVisitNodeListWithSeparator(nodes, "");
+  }
+
+  /**
+   * Print a list of [nodes], separated by the given [separator].
+   */
+  @protected
+  void safelyVisitNodeListWithSeparator(
+      NodeList<AstNode> nodes, String separator) {
+    if (nodes != null) {
+      int size = nodes.length;
+      for (int i = 0; i < size; i++) {
+        if (i > 0) {
+          sink.write(separator);
+        }
+        var node = nodes[i];
+        if (node != null) {
+          node.accept(this);
+        } else {
+          sink.write('<null>');
+        }
+      }
+    }
+  }
+
+  /**
+   * Print a list of [nodes], prefixed by the given [prefix] if the list is not
+   * empty, and separated by the given [separator].
+   */
+  @protected
+  void safelyVisitNodeListWithSeparatorAndPrefix(
+      String prefix, NodeList<AstNode> nodes, String separator) {
+    if (nodes != null) {
+      int size = nodes.length;
+      if (size > 0) {
+        sink.write(prefix);
+        for (int i = 0; i < size; i++) {
+          if (i > 0) {
+            sink.write(separator);
+          }
+          nodes[i].accept(this);
+        }
+      }
+    }
+  }
+
+  /**
+   * Print a list of [nodes], separated by the given [separator], followed by
+   * the given [suffix] if the list is not empty.
+   */
+  @protected
+  void safelyVisitNodeListWithSeparatorAndSuffix(
+      NodeList<AstNode> nodes, String separator, String suffix) {
+    if (nodes != null) {
+      int size = nodes.length;
+      if (size > 0) {
+        for (int i = 0; i < size; i++) {
+          if (i > 0) {
+            sink.write(separator);
+          }
+          nodes[i].accept(this);
+        }
+        sink.write(suffix);
+      }
+    }
+  }
+
+  /**
+   * Safely visit the given [node], printing the [prefix] before the node if it
+   * is non-`null`.
+   */
+  @protected
+  void safelyVisitNodeWithPrefix(String prefix, AstNode node) {
+    if (node != null) {
+      sink.write(prefix);
+      node.accept(this);
+    }
+  }
+
+  /**
+   * Safely visit the given [node], printing the [suffix] after the node if it
+   * is non-`null`.
+   */
+  @protected
+  void safelyVisitNodeWithSuffix(AstNode node, String suffix) {
+    if (node != null) {
+      node.accept(this);
+      sink.write(suffix);
+    }
+  }
+
+  /**
+   * Safely visit the given [token].
+   */
+  @protected
+  void safelyVisitToken(Token token) {
+    if (token != null) {
+      sink.write(token.lexeme);
+    }
+  }
+
+  /**
+   * Safely visit the given [token], printing the [suffix] after the token if it
+   * is non-`null`.
+   */
+  @protected
+  void safelyVisitTokenWithSuffix(Token token, String suffix) {
+    if (token != null) {
+      sink.write(token.lexeme);
+      sink.write(suffix);
+    }
+  }
+
+  @override
+  void visitAdjacentStrings(AdjacentStrings node) {
+    safelyVisitNodeListWithSeparator(node.strings, " ");
+  }
+
+  @override
+  void visitAnnotation(Annotation node) {
+    sink.write('@');
+    safelyVisitNode(node.name);
+    safelyVisitNodeWithPrefix(".", node.constructorName);
+    safelyVisitNode(node.arguments);
+  }
+
+  @override
+  void visitArgumentList(ArgumentList node) {
+    sink.write('(');
+    safelyVisitNodeListWithSeparator(node.arguments, ", ");
+    sink.write(')');
+  }
+
+  @override
+  void visitAsExpression(AsExpression node) {
+    safelyVisitNode(node.expression);
+    sink.write(" as ");
+    safelyVisitNode(node.type);
+  }
+
+  @override
+  void visitAssertInitializer(AssertInitializer node) {
+    sink.write("assert (");
+    safelyVisitNode(node.condition);
+    if (node.message != null) {
+      sink.write(', ');
+      safelyVisitNode(node.message);
+    }
+    sink.write(");");
+  }
+
+  @override
+  void visitAssertStatement(AssertStatement node) {
+    sink.write("assert (");
+    safelyVisitNode(node.condition);
+    if (node.message != null) {
+      sink.write(', ');
+      safelyVisitNode(node.message);
+    }
+    sink.write(");");
+  }
+
+  @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    safelyVisitNode(node.leftHandSide);
+    sink.write(' ');
+    sink.write(node.operator.lexeme);
+    sink.write(' ');
+    safelyVisitNode(node.rightHandSide);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    sink.write("await ");
+    safelyVisitNode(node.expression);
+  }
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    _writeOperand(node, node.leftOperand);
+    sink.write(' ');
+    sink.write(node.operator.lexeme);
+    sink.write(' ');
+    _writeOperand(node, node.rightOperand);
+  }
+
+  @override
+  void visitBlock(Block node) {
+    sink.write('{');
+    safelyVisitNodeListWithSeparator(node.statements, " ");
+    sink.write('}');
+  }
+
+  @override
+  void visitBlockFunctionBody(BlockFunctionBody node) {
+    Token keyword = node.keyword;
+    if (keyword != null) {
+      sink.write(keyword.lexeme);
+      if (node.star != null) {
+        sink.write('*');
+      }
+      sink.write(' ');
+    }
+    safelyVisitNode(node.block);
+  }
+
+  @override
+  void visitBooleanLiteral(BooleanLiteral node) {
+    sink.write(node.literal.lexeme);
+  }
+
+  @override
+  void visitBreakStatement(BreakStatement node) {
+    sink.write("break");
+    safelyVisitNodeWithPrefix(" ", node.label);
+    sink.write(";");
+  }
+
+  @override
+  void visitCascadeExpression(CascadeExpression node) {
+    safelyVisitNode(node.target);
+    safelyVisitNodeList(node.cascadeSections);
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    safelyVisitNodeWithPrefix("on ", node.exceptionType);
+    if (node.catchKeyword != null) {
+      if (node.exceptionType != null) {
+        sink.write(' ');
+      }
+      sink.write("catch (");
+      safelyVisitNode(node.exceptionParameter);
+      safelyVisitNodeWithPrefix(", ", node.stackTraceParameter);
+      sink.write(") ");
+    } else {
+      sink.write(" ");
+    }
+    safelyVisitNode(node.body);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.abstractKeyword, " ");
+    sink.write("class ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNodeWithPrefix(" ", node.extendsClause);
+    safelyVisitNodeWithPrefix(" ", node.withClause);
+    safelyVisitNodeWithPrefix(" ", node.implementsClause);
+    sink.write(" {");
+    safelyVisitNodeListWithSeparator(node.members, " ");
+    sink.write("}");
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    if (node.abstractKeyword != null) {
+      sink.write("abstract ");
+    }
+    sink.write("class ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    sink.write(" = ");
+    safelyVisitNode(node.superclass);
+    safelyVisitNodeWithPrefix(" ", node.withClause);
+    safelyVisitNodeWithPrefix(" ", node.implementsClause);
+    sink.write(";");
+  }
+
+  @override
+  void visitComment(Comment node) {}
+
+  @override
+  void visitCommentReference(CommentReference node) {}
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    ScriptTag scriptTag = node.scriptTag;
+    NodeList<Directive> directives = node.directives;
+    safelyVisitNode(scriptTag);
+    String prefix = scriptTag == null ? "" : " ";
+    safelyVisitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
+    prefix = scriptTag == null && directives.isEmpty ? "" : " ";
+    safelyVisitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
+  }
+
+  @override
+  void visitConditionalExpression(ConditionalExpression node) {
+    safelyVisitNode(node.condition);
+    sink.write(" ? ");
+    safelyVisitNode(node.thenExpression);
+    sink.write(" : ");
+    safelyVisitNode(node.elseExpression);
+  }
+
+  @override
+  void visitConfiguration(Configuration node) {
+    sink.write('if (');
+    safelyVisitNode(node.name);
+    safelyVisitNodeWithPrefix(" == ", node.value);
+    sink.write(') ');
+    safelyVisitNode(node.uri);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
+    safelyVisitTokenWithSuffix(node.constKeyword, " ");
+    safelyVisitTokenWithSuffix(node.factoryKeyword, " ");
+    safelyVisitNode(node.returnType);
+    safelyVisitNodeWithPrefix(".", node.name);
+    safelyVisitNode(node.parameters);
+    safelyVisitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
+    safelyVisitNodeWithPrefix(" = ", node.redirectedConstructor);
+    safelyVisitFunctionWithPrefix(" ", node.body);
+  }
+
+  @override
+  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    safelyVisitTokenWithSuffix(node.thisKeyword, ".");
+    safelyVisitNode(node.fieldName);
+    sink.write(" = ");
+    safelyVisitNode(node.expression);
+  }
+
+  @override
+  void visitConstructorName(ConstructorName node) {
+    safelyVisitNode(node.type);
+    safelyVisitNodeWithPrefix(".", node.name);
+  }
+
+  @override
+  void visitContinueStatement(ContinueStatement node) {
+    sink.write("continue");
+    safelyVisitNodeWithPrefix(" ", node.label);
+    sink.write(";");
+  }
+
+  @override
+  void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.keyword, " ");
+    safelyVisitNodeWithSuffix(node.type, " ");
+    safelyVisitNode(node.identifier);
+  }
+
+  @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (node.isRequiredNamed) {
+      sink.write('required ');
+    }
+    safelyVisitNode(node.parameter);
+    if (node.separator != null) {
+      if (node.separator.lexeme != ":") {
+        sink.write(" ");
+      }
+      sink.write(node.separator.lexeme);
+      safelyVisitNodeWithPrefix(" ", node.defaultValue);
+    }
+  }
+
+  @override
+  void visitDoStatement(DoStatement node) {
+    sink.write("do ");
+    safelyVisitNode(node.body);
+    sink.write(" while (");
+    safelyVisitNode(node.condition);
+    sink.write(");");
+  }
+
+  @override
+  void visitDottedName(DottedName node) {
+    safelyVisitNodeListWithSeparator(node.components, ".");
+  }
+
+  @override
+  void visitDoubleLiteral(DoubleLiteral node) {
+    sink.write(node.literal.lexeme);
+  }
+
+  @override
+  void visitEmptyFunctionBody(EmptyFunctionBody node) {
+    sink.write(';');
+  }
+
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
+    sink.write(';');
+  }
+
+  @override
+  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitNode(node.name);
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("enum ");
+    safelyVisitNode(node.name);
+    sink.write(" {");
+    safelyVisitNodeListWithSeparator(node.constants, ", ");
+    sink.write("}");
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("export ");
+    safelyVisitNode(node.uri);
+    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+    sink.write(';');
+  }
+
+  @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    Token keyword = node.keyword;
+    if (keyword != null) {
+      sink.write(keyword.lexeme);
+      sink.write(' ');
+    }
+    sink.write('${node.functionDefinition?.lexeme} ');
+    safelyVisitNode(node.expression);
+    if (node.semicolon != null) {
+      sink.write(';');
+    }
+  }
+
+  @override
+  void visitExpressionStatement(ExpressionStatement node) {
+    safelyVisitNode(node.expression);
+    sink.write(';');
+  }
+
+  @override
+  void visitExtendsClause(ExtendsClause node) {
+    sink.write("extends ");
+    safelyVisitNode(node.superclass);
+  }
+
+  @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.extensionKeyword, ' ');
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    sink.write(' ');
+    safelyVisitToken(node.onKeyword);
+    sink.write(' ');
+    safelyVisitNodeWithSuffix(node.extendedType, ' ');
+    safelyVisitToken(node.leftBracket);
+    safelyVisitNodeListWithSeparator(node.members, ' ');
+    safelyVisitToken(node.rightBracket);
+  }
+
+  @override
+  void visitExtensionOverride(ExtensionOverride node) {
+    safelyVisitNode(node.extensionName);
+    safelyVisitNode(node.typeArguments);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.staticKeyword, " ");
+    safelyVisitNode(node.fields);
+    sink.write(";");
+  }
+
+  @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
+    safelyVisitTokenWithSuffix(node.keyword, " ");
+    safelyVisitNodeWithSuffix(node.type, " ");
+    sink.write("this.");
+    safelyVisitNode(node.identifier);
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNode(node.parameters);
+  }
+
+  @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    safelyVisitNode(node.loopVariable);
+    sink.write(' in ');
+    safelyVisitNode(node.iterable);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    safelyVisitNode(node.identifier);
+    sink.write(' in ');
+    safelyVisitNode(node.iterable);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    safelyVisitTokenWithSuffix(node.awaitKeyword, ' ');
+    sink.write('for (');
+    safelyVisitNode(node.forLoopParts);
+    sink.write(') ');
+    safelyVisitNode(node.body);
+  }
+
+  @override
+  void visitFormalParameterList(FormalParameterList node) {
+    String groupEnd;
+    sink.write('(');
+    NodeList<FormalParameter> parameters = node.parameters;
+    int size = parameters.length;
+    for (int i = 0; i < size; i++) {
+      FormalParameter parameter = parameters[i];
+      if (i > 0) {
+        sink.write(", ");
+      }
+      if (groupEnd == null && parameter is DefaultFormalParameter) {
+        if (parameter.isNamed) {
+          groupEnd = "}";
+          sink.write('{');
+        } else {
+          groupEnd = "]";
+          sink.write('[');
+        }
+      }
+      parameter.accept(this);
+    }
+    if (groupEnd != null) {
+      sink.write(groupEnd);
+    }
+    sink.write(')');
+  }
+
+  @override
+  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    safelyVisitNode(node.variables);
+    sink.write(';');
+    safelyVisitNodeWithPrefix(' ', node.condition);
+    sink.write(';');
+    safelyVisitNodeListWithSeparatorAndPrefix(' ', node.updaters, ', ');
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    safelyVisitNode(node.initialization);
+    sink.write(';');
+    safelyVisitNodeWithPrefix(' ', node.condition);
+    sink.write(';');
+    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.updaters, ', ');
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    if (node.awaitKeyword != null) {
+      sink.write('await ');
+    }
+    sink.write('for (');
+    safelyVisitNode(node.forLoopParts);
+    sink.write(') ');
+    safelyVisitNode(node.body);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
+    safelyVisitNodeWithSuffix(node.returnType, " ");
+    safelyVisitTokenWithSuffix(node.propertyKeyword, " ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.functionExpression);
+  }
+
+  @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    safelyVisitNode(node.functionDeclaration);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNode(node.parameters);
+    if (node.body is! EmptyFunctionBody) {
+      sink.write(' ');
+    }
+    safelyVisitNode(node.body);
+  }
+
+  @override
+  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    safelyVisitNode(node.function);
+    safelyVisitNode(node.typeArguments);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("typedef ");
+    safelyVisitNodeWithSuffix(node.returnType, " ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNode(node.parameters);
+    sink.write(";");
+  }
+
+  @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
+    safelyVisitNodeWithSuffix(node.returnType, " ");
+    safelyVisitNode(node.identifier);
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNode(node.parameters);
+    if (node.question != null) {
+      sink.write('?');
+    }
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    safelyVisitNode(node.returnType);
+    sink.write(' Function');
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNode(node.parameters);
+    if (node.question != null) {
+      sink.write('?');
+    }
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("typedef ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    sink.write(" = ");
+    safelyVisitNode(node.functionType);
+  }
+
+  @override
+  void visitHideCombinator(HideCombinator node) {
+    sink.write("hide ");
+    safelyVisitNodeListWithSeparator(node.hiddenNames, ", ");
+  }
+
+  @override
+  void visitIfElement(IfElement node) {
+    sink.write('if (');
+    safelyVisitNode(node.condition);
+    sink.write(') ');
+    safelyVisitNode(node.thenElement);
+    safelyVisitNodeWithPrefix(' else ', node.elseElement);
+  }
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    sink.write("if (");
+    safelyVisitNode(node.condition);
+    sink.write(") ");
+    safelyVisitNode(node.thenStatement);
+    safelyVisitNodeWithPrefix(" else ", node.elseStatement);
+  }
+
+  @override
+  void visitImplementsClause(ImplementsClause node) {
+    sink.write("implements ");
+    safelyVisitNodeListWithSeparator(node.interfaces, ", ");
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("import ");
+    safelyVisitNode(node.uri);
+    if (node.deferredKeyword != null) {
+      sink.write(" deferred");
+    }
+    safelyVisitNodeWithPrefix(" as ", node.prefix);
+    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
+    sink.write(';');
+  }
+
+  @override
+  void visitIndexExpression(IndexExpression node) {
+    if (node.isCascaded) {
+      sink.write(node.period.lexeme);
+    } else {
+      safelyVisitNode(node.target);
+    }
+    sink.write('[');
+    safelyVisitNode(node.index);
+    sink.write(']');
+  }
+
+  @override
+  void visitInstanceCreationExpression(InstanceCreationExpression node) {
+    safelyVisitTokenWithSuffix(node.keyword, " ");
+    safelyVisitNode(node.constructorName);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitIntegerLiteral(IntegerLiteral node) {
+    sink.write(node.literal.lexeme);
+  }
+
+  @override
+  void visitInterpolationExpression(InterpolationExpression node) {
+    if (node.rightBracket != null) {
+      sink.write("\${");
+      safelyVisitNode(node.expression);
+      sink.write("}");
+    } else {
+      sink.write("\$");
+      safelyVisitNode(node.expression);
+    }
+  }
+
+  @override
+  void visitInterpolationString(InterpolationString node) {
+    sink.write(node.contents.lexeme);
+  }
+
+  @override
+  void visitIsExpression(IsExpression node) {
+    safelyVisitNode(node.expression);
+    if (node.notOperator == null) {
+      sink.write(" is ");
+    } else {
+      sink.write(" is! ");
+    }
+    safelyVisitNode(node.type);
+  }
+
+  @override
+  void visitLabel(Label node) {
+    safelyVisitNode(node.label);
+    sink.write(":");
+  }
+
+  @override
+  void visitLabeledStatement(LabeledStatement node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    safelyVisitNode(node.statement);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("library ");
+    safelyVisitNode(node.name);
+    sink.write(';');
+  }
+
+  @override
+  void visitLibraryIdentifier(LibraryIdentifier node) {
+    sink.write(node.name);
+  }
+
+  @override
+  void visitListLiteral(ListLiteral node) {
+    safelyVisitTokenWithSuffix(node.constKeyword, ' ');
+    safelyVisitNode(node.typeArguments);
+    sink.write('[');
+    safelyVisitNodeListWithSeparator(node.elements, ', ');
+    sink.write(']');
+  }
+
+  @override
+  void visitMapLiteralEntry(MapLiteralEntry node) {
+    safelyVisitNode(node.key);
+    sink.write(" : ");
+    safelyVisitNode(node.value);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
+    safelyVisitTokenWithSuffix(node.modifierKeyword, " ");
+    safelyVisitNodeWithSuffix(node.returnType, " ");
+    safelyVisitTokenWithSuffix(node.propertyKeyword, " ");
+    safelyVisitTokenWithSuffix(node.operatorKeyword, " ");
+    safelyVisitNode(node.name);
+    if (!node.isGetter) {
+      safelyVisitNode(node.typeParameters);
+      safelyVisitNode(node.parameters);
+    }
+    safelyVisitFunctionWithPrefix(" ", node.body);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    if (node.isCascaded) {
+      sink.write(node.operator.lexeme);
+    } else {
+      if (node.target != null) {
+        node.target.accept(this);
+        sink.write(node.operator.lexeme);
+      }
+    }
+    safelyVisitNode(node.methodName);
+    safelyVisitNode(node.typeArguments);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitMixinDeclaration(MixinDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("mixin ");
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeParameters);
+    safelyVisitNodeWithPrefix(" ", node.onClause);
+    safelyVisitNodeWithPrefix(" ", node.implementsClause);
+    sink.write(" {");
+    safelyVisitNodeListWithSeparator(node.members, " ");
+    sink.write("}");
+  }
+
+  @override
+  void visitNamedExpression(NamedExpression node) {
+    safelyVisitNode(node.name);
+    safelyVisitNodeWithPrefix(" ", node.expression);
+  }
+
+  @override
+  void visitNativeClause(NativeClause node) {
+    sink.write("native ");
+    safelyVisitNode(node.name);
+  }
+
+  @override
+  void visitNativeFunctionBody(NativeFunctionBody node) {
+    sink.write("native ");
+    safelyVisitNode(node.stringLiteral);
+    sink.write(';');
+  }
+
+  @override
+  void visitNullLiteral(NullLiteral node) {
+    sink.write("null");
+  }
+
+  @override
+  void visitOnClause(OnClause node) {
+    sink.write('on ');
+    safelyVisitNodeListWithSeparator(node.superclassConstraints, ", ");
+  }
+
+  @override
+  void visitParenthesizedExpression(ParenthesizedExpression node) {
+    sink.write('(');
+    safelyVisitNode(node.expression);
+    sink.write(')');
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("part ");
+    safelyVisitNode(node.uri);
+    sink.write(';');
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    sink.write("part of ");
+    safelyVisitNode(node.libraryName);
+    sink.write(';');
+  }
+
+  @override
+  void visitPostfixExpression(PostfixExpression node) {
+    _writeOperand(node, node.operand);
+    sink.write(node.operator.lexeme);
+  }
+
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    safelyVisitNode(node.prefix);
+    sink.write('.');
+    safelyVisitNode(node.identifier);
+  }
+
+  @override
+  void visitPrefixExpression(PrefixExpression node) {
+    sink.write(node.operator.lexeme);
+    _writeOperand(node, node.operand);
+  }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    if (node.isCascaded) {
+      sink.write(node.operator.lexeme);
+    } else {
+      safelyVisitNode(node.target);
+      sink.write(node.operator.lexeme);
+    }
+    safelyVisitNode(node.propertyName);
+  }
+
+  @override
+  void visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    sink.write("this");
+    safelyVisitNodeWithPrefix(".", node.constructorName);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitRethrowExpression(RethrowExpression node) {
+    sink.write("rethrow");
+  }
+
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    Expression expression = node.expression;
+    if (expression == null) {
+      sink.write("return;");
+    } else {
+      sink.write("return ");
+      expression.accept(this);
+      sink.write(";");
+    }
+  }
+
+  @override
+  void visitScriptTag(ScriptTag node) {
+    sink.write(node.scriptTag.lexeme);
+  }
+
+  @override
+  void visitSetOrMapLiteral(SetOrMapLiteral node) {
+    safelyVisitTokenWithSuffix(node.constKeyword, ' ');
+    safelyVisitNode(node.typeArguments);
+    sink.write('{');
+    safelyVisitNodeListWithSeparator(node.elements, ', ');
+    sink.write('}');
+  }
+
+  @override
+  void visitShowCombinator(ShowCombinator node) {
+    sink.write("show ");
+    safelyVisitNodeListWithSeparator(node.shownNames, ", ");
+  }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
+    safelyVisitTokenWithSuffix(node.keyword, " ");
+    safelyVisitNode(node.type);
+    if (node.type != null && node.identifier != null) {
+      sink.write(' ');
+    }
+    safelyVisitNode(node.identifier);
+  }
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    sink.write(node.token.lexeme);
+  }
+
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    sink.write(node.literal.lexeme);
+  }
+
+  @override
+  void visitSpreadElement(SpreadElement node) {
+    sink.write(node.spreadOperator.lexeme);
+    safelyVisitNode(node.expression);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    safelyVisitNodeList(node.elements);
+  }
+
+  @override
+  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    sink.write("super");
+    safelyVisitNodeWithPrefix(".", node.constructorName);
+    safelyVisitNode(node.argumentList);
+  }
+
+  @override
+  void visitSuperExpression(SuperExpression node) {
+    sink.write("super");
+  }
+
+  @override
+  void visitSwitchCase(SwitchCase node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    sink.write("case ");
+    safelyVisitNode(node.expression);
+    sink.write(": ");
+    safelyVisitNodeListWithSeparator(node.statements, " ");
+  }
+
+  @override
+  void visitSwitchDefault(SwitchDefault node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
+    sink.write("default: ");
+    safelyVisitNodeListWithSeparator(node.statements, " ");
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    sink.write("switch (");
+    safelyVisitNode(node.expression);
+    sink.write(") {");
+    safelyVisitNodeListWithSeparator(node.members, " ");
+    sink.write("}");
+  }
+
+  @override
+  void visitSymbolLiteral(SymbolLiteral node) {
+    sink.write("#");
+    List<Token> components = node.components;
+    for (int i = 0; i < components.length; i++) {
+      if (i > 0) {
+        sink.write(".");
+      }
+      sink.write(components[i].lexeme);
+    }
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    sink.write("this");
+  }
+
+  @override
+  void visitThrowExpression(ThrowExpression node) {
+    sink.write("throw ");
+    safelyVisitNode(node.expression);
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    safelyVisitNodeWithSuffix(node.variables, ";");
+  }
+
+  @override
+  void visitTryStatement(TryStatement node) {
+    sink.write("try ");
+    safelyVisitNode(node.body);
+    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
+    safelyVisitNodeWithPrefix(" finally ", node.finallyBlock);
+  }
+
+  @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    sink.write('<');
+    safelyVisitNodeListWithSeparator(node.arguments, ", ");
+    sink.write('>');
+  }
+
+  @override
+  void visitTypeName(TypeName node) {
+    safelyVisitNode(node.name);
+    safelyVisitNode(node.typeArguments);
+    if (node.question != null) {
+      sink.write('?');
+    }
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitNode(node.name);
+    safelyVisitNodeWithPrefix(" extends ", node.bound);
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    sink.write('<');
+    safelyVisitNodeListWithSeparator(node.typeParameters, ", ");
+    sink.write('>');
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitNode(node.name);
+    safelyVisitNodeWithPrefix(" = ", node.initializer);
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    safelyVisitTokenWithSuffix(node.lateKeyword, " ");
+    safelyVisitTokenWithSuffix(node.keyword, " ");
+    safelyVisitNodeWithSuffix(node.type, " ");
+    safelyVisitNodeListWithSeparator(node.variables, ", ");
+  }
+
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    safelyVisitNode(node.variables);
+    sink.write(";");
+  }
+
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    sink.write("while (");
+    safelyVisitNode(node.condition);
+    sink.write(") ");
+    safelyVisitNode(node.body);
+  }
+
+  @override
+  void visitWithClause(WithClause node) {
+    sink.write("with ");
+    safelyVisitNodeListWithSeparator(node.mixinTypes, ", ");
+  }
+
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    if (node.star != null) {
+      sink.write("yield* ");
+    } else {
+      sink.write("yield ");
+    }
+    safelyVisitNode(node.expression);
+    sink.write(";");
+  }
+
+  void _writeOperand(Expression node, Expression operand) {
+    if (operand != null) {
+      bool needsParenthesis = operand.precedence < node.precedence;
+      if (needsParenthesis) {
+        sink.write('(');
+      }
+      operand.accept(this);
+      if (needsParenthesis) {
+        sink.write(')');
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/token.dart b/pkg/analyzer/lib/src/dart/ast/token.dart
index 9939121..0833eb5 100644
--- a/pkg/analyzer/lib/src/dart/ast/token.dart
+++ b/pkg/analyzer/lib/src/dart/ast/token.dart
@@ -4,7 +4,7 @@
 
 import 'package:analyzer/dart/ast/token.dart';
 
-export 'package:front_end/src/scanner/token.dart'
+export 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show
         BeginToken,
         CommentToken,
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 67c908d..5d745b6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -10,10 +10,9 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
-import 'package:analyzer/src/generated/java_core.dart';
-import 'package:meta/meta.dart';
 
 export 'package:analyzer/src/dart/ast/constant_evaluator.dart';
 
@@ -489,7 +488,8 @@
           period: cloneToken(node.period),
           identifier: cloneNode(node.identifier),
           typeParameters: cloneNode(node.typeParameters),
-          parameters: cloneNode(node.parameters));
+          parameters: cloneNode(node.parameters),
+          question: cloneToken(node.question));
 
   @override
   ForEachPartsWithDeclaration visitForEachPartsWithDeclaration(
@@ -2475,8 +2475,9 @@
       buffer.write(currentNode.runtimeType);
       currentNode = currentNode.parent;
     }
-    AnalysisEngine.instance.logger.logError(
-        buffer.toString(), new CaughtException(exception, stackTrace));
+    AnalysisEngine.instance.instrumentationService.logException(
+        new CaughtException.withMessage(
+            buffer.toString(), exception, stackTrace));
   }
 }
 
@@ -2530,9 +2531,11 @@
     try {
       node.accept(this);
     } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
-          "Unable to locate element at offset ($_startOffset - $_endOffset)",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              "Unable to locate element at offset ($_startOffset - $_endOffset)",
+              exception,
+              stackTrace));
       return null;
     }
     return _foundNode;
@@ -2568,9 +2571,11 @@
     } catch (exception, stackTrace) {
       // Ignore the exception and proceed in order to visit the rest of the
       // structure.
-      AnalysisEngine.instance.logger.logInformation(
-          "Exception caught while traversing an AST structure.",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              "Exception caught while traversing an AST structure.",
+              exception,
+              stackTrace));
     }
     // Found a child.
     if (_foundNode != null) {
@@ -2626,9 +2631,11 @@
     try {
       node.accept(this);
     } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
-          "Unable to locate element at offset ($_startOffset - $_endOffset)",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              "Unable to locate element at offset ($_startOffset - $_endOffset)",
+              exception,
+              stackTrace));
       return null;
     }
     return _foundNode;
@@ -2664,9 +2671,11 @@
     } catch (exception, stackTrace) {
       // Ignore the exception and proceed in order to visit the rest of the
       // structure.
-      AnalysisEngine.instance.logger.logInformation(
-          "Exception caught while traversing an AST structure.",
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              "Exception caught while traversing an AST structure.",
+              exception,
+              stackTrace));
     }
     // Found a child.
     if (_foundNode != null) {
@@ -5773,2362 +5782,9 @@
 
 /**
  * A visitor used to write a source representation of a visited AST node (and
- * all of it's children) to a writer.
- *
- * This class has been deprecated. Use the class ToSourceVisitor2 instead.
- */
-@deprecated
-class ToSourceVisitor implements AstVisitor<void> {
-  /**
-   * The writer to which the source is to be written.
-   */
-  final PrintWriter _writer;
-
-  /**
-   * Initialize a newly created visitor to write source code representing the
-   * visited nodes to the given [writer].
-   */
-  ToSourceVisitor(this._writer);
-
-  @override
-  void visitAdjacentStrings(AdjacentStrings node) {
-    _visitNodeListWithSeparator(node.strings, " ");
-  }
-
-  @override
-  void visitAnnotation(Annotation node) {
-    _writer.print('@');
-    _visitNode(node.name);
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.arguments);
-  }
-
-  @override
-  void visitArgumentList(ArgumentList node) {
-    _writer.print('(');
-    _visitNodeListWithSeparator(node.arguments, ", ");
-    _writer.print(')');
-  }
-
-  @override
-  void visitAsExpression(AsExpression node) {
-    _visitNode(node.expression);
-    _writer.print(" as ");
-    _visitNode(node.type);
-  }
-
-  @override
-  void visitAssertInitializer(AssertInitializer node) {
-    _writer.print("assert (");
-    _visitNode(node.condition);
-    if (node.message != null) {
-      _writer.print(', ');
-      _visitNode(node.message);
-    }
-    _writer.print(")");
-  }
-
-  @override
-  void visitAssertStatement(AssertStatement node) {
-    _writer.print("assert (");
-    _visitNode(node.condition);
-    if (node.message != null) {
-      _writer.print(', ');
-      _visitNode(node.message);
-    }
-    _writer.print(");");
-  }
-
-  @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    _visitNode(node.leftHandSide);
-    _writer.print(' ');
-    _writer.print(node.operator.lexeme);
-    _writer.print(' ');
-    _visitNode(node.rightHandSide);
-  }
-
-  @override
-  void visitAwaitExpression(AwaitExpression node) {
-    _writer.print("await ");
-    _visitNode(node.expression);
-  }
-
-  @override
-  void visitBinaryExpression(BinaryExpression node) {
-    _visitNode(node.leftOperand);
-    _writer.print(' ');
-    _writer.print(node.operator.lexeme);
-    _writer.print(' ');
-    _visitNode(node.rightOperand);
-  }
-
-  @override
-  void visitBlock(Block node) {
-    _writer.print('{');
-    _visitNodeListWithSeparator(node.statements, " ");
-    _writer.print('}');
-  }
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      _writer.print(keyword.lexeme);
-      if (node.star != null) {
-        _writer.print('*');
-      }
-      _writer.print(' ');
-    }
-    _visitNode(node.block);
-  }
-
-  @override
-  void visitBooleanLiteral(BooleanLiteral node) {
-    _writer.print(node.literal.lexeme);
-  }
-
-  @override
-  void visitBreakStatement(BreakStatement node) {
-    _writer.print("break");
-    _visitNodeWithPrefix(" ", node.label);
-    _writer.print(";");
-  }
-
-  @override
-  void visitCascadeExpression(CascadeExpression node) {
-    _visitNode(node.target);
-    _visitNodeList(node.cascadeSections);
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    _visitNodeWithPrefix("on ", node.exceptionType);
-    if (node.catchKeyword != null) {
-      if (node.exceptionType != null) {
-        _writer.print(' ');
-      }
-      _writer.print("catch (");
-      _visitNode(node.exceptionParameter);
-      _visitNodeWithPrefix(", ", node.stackTraceParameter);
-      _writer.print(") ");
-    } else {
-      _writer.print(" ");
-    }
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.abstractKeyword, " ");
-    _writer.print("class ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _visitNodeWithPrefix(" ", node.extendsClause);
-    _visitNodeWithPrefix(" ", node.withClause);
-    _visitNodeWithPrefix(" ", node.implementsClause);
-    _writer.print(" {");
-    _visitNodeListWithSeparator(node.members, " ");
-    _writer.print("}");
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    if (node.abstractKeyword != null) {
-      _writer.print("abstract ");
-    }
-    _writer.print("class ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _writer.print(" = ");
-    _visitNode(node.superclass);
-    _visitNodeWithPrefix(" ", node.withClause);
-    _visitNodeWithPrefix(" ", node.implementsClause);
-    _writer.print(";");
-  }
-
-  @override
-  void visitComment(Comment node) {}
-
-  @override
-  void visitCommentReference(CommentReference node) {}
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    ScriptTag scriptTag = node.scriptTag;
-    NodeList<Directive> directives = node.directives;
-    _visitNode(scriptTag);
-    String prefix = scriptTag == null ? "" : " ";
-    _visitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
-    prefix = scriptTag == null && directives.isEmpty ? "" : " ";
-    _visitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
-  }
-
-  @override
-  void visitConditionalExpression(ConditionalExpression node) {
-    _visitNode(node.condition);
-    _writer.print(" ? ");
-    _visitNode(node.thenExpression);
-    _writer.print(" : ");
-    _visitNode(node.elseExpression);
-  }
-
-  @override
-  void visitConfiguration(Configuration node) {
-    _writer.print('if (');
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" == ", node.value);
-    _writer.print(') ');
-    _visitNode(node.uri);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitTokenWithSuffix(node.constKeyword, " ");
-    _visitTokenWithSuffix(node.factoryKeyword, " ");
-    _visitNode(node.returnType);
-    _visitNodeWithPrefix(".", node.name);
-    _visitNode(node.parameters);
-    _visitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
-    _visitNodeWithPrefix(" = ", node.redirectedConstructor);
-    _visitFunctionWithPrefix(" ", node.body);
-  }
-
-  @override
-  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    _visitTokenWithSuffix(node.thisKeyword, ".");
-    _visitNode(node.fieldName);
-    _writer.print(" = ");
-    _visitNode(node.expression);
-  }
-
-  @override
-  void visitConstructorName(ConstructorName node) {
-    _visitNode(node.type);
-    _visitNodeWithPrefix(".", node.name);
-  }
-
-  @override
-  void visitContinueStatement(ContinueStatement node) {
-    _writer.print("continue");
-    _visitNodeWithPrefix(" ", node.label);
-    _writer.print(";");
-  }
-
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _visitNode(node.identifier);
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    if (node.isRequiredNamed) {
-      _writer.print('required ');
-    }
-    _visitNode(node.parameter);
-    if (node.separator != null) {
-      if (node.separator.lexeme != ":") {
-        _writer.print(" ");
-      }
-      _writer.print(node.separator.lexeme);
-      _visitNodeWithPrefix(" ", node.defaultValue);
-    }
-  }
-
-  @override
-  void visitDoStatement(DoStatement node) {
-    _writer.print("do ");
-    _visitNode(node.body);
-    _writer.print(" while (");
-    _visitNode(node.condition);
-    _writer.print(");");
-  }
-
-  @override
-  void visitDottedName(DottedName node) {
-    _visitNodeListWithSeparator(node.components, ".");
-  }
-
-  @override
-  void visitDoubleLiteral(DoubleLiteral node) {
-    _writer.print(node.literal.lexeme);
-  }
-
-  @override
-  void visitEmptyFunctionBody(EmptyFunctionBody node) {
-    _writer.print(';');
-  }
-
-  @override
-  void visitEmptyStatement(EmptyStatement node) {
-    _writer.print(';');
-  }
-
-  @override
-  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-  }
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("enum ");
-    _visitNode(node.name);
-    _writer.print(" {");
-    _visitNodeListWithSeparator(node.constants, ", ");
-    _writer.print("}");
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("export ");
-    _visitNode(node.uri);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    _writer.print(';');
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      _writer.print(keyword.lexeme);
-      _writer.print(' ');
-    }
-    _writer.print('${node.functionDefinition?.lexeme} ');
-    _visitNode(node.expression);
-    if (node.semicolon != null) {
-      _writer.print(';');
-    }
-  }
-
-  @override
-  void visitExpressionStatement(ExpressionStatement node) {
-    _visitNode(node.expression);
-    _writer.print(';');
-  }
-
-  @override
-  void visitExtendsClause(ExtendsClause node) {
-    _writer.print("extends ");
-    _visitNode(node.superclass);
-  }
-
-  @override
-  void visitExtensionDeclaration(ExtensionDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.extensionKeyword, ' ');
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _writer.print(' ');
-    _visitToken(node.onKeyword);
-    _writer.print(' ');
-    _visitNodeWithSuffix(node.extendedType, ' ');
-    _visitToken(node.leftBracket);
-    _visitNodeListWithSeparator(node.members, ' ');
-    _visitToken(node.rightBracket);
-  }
-
-  @override
-  void visitExtensionOverride(ExtensionOverride node) {
-    _visitNode(node.extensionName);
-    _visitNode(node.typeArguments);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.staticKeyword, " ");
-    _visitNode(node.fields);
-    _writer.print(";");
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.covariantKeyword, ' ');
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _writer.print("this.");
-    _visitNode(node.identifier);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-  }
-
-  @override
-  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
-    _visitNode(node.loopVariable);
-    _writer.print(' in ');
-    _visitNode(node.iterable);
-  }
-
-  @override
-  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
-    _visitNode(node.identifier);
-    _writer.print(' in ');
-    _visitNode(node.iterable);
-  }
-
-  @override
-  void visitForElement(ForElement node) {
-    _visitTokenWithSuffix(node.awaitKeyword, ' ');
-    _writer.print('for (');
-    _visitNode(node.forLoopParts);
-    _writer.print(') ');
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitFormalParameterList(FormalParameterList node) {
-    String groupEnd;
-    _writer.print('(');
-    NodeList<FormalParameter> parameters = node.parameters;
-    int size = parameters.length;
-    for (int i = 0; i < size; i++) {
-      FormalParameter parameter = parameters[i];
-      if (i > 0) {
-        _writer.print(", ");
-      }
-      if (groupEnd == null && parameter is DefaultFormalParameter) {
-        if (parameter.isNamed) {
-          groupEnd = "}";
-          _writer.print('{');
-        } else {
-          groupEnd = "]";
-          _writer.print('[');
-        }
-      }
-      parameter.accept(this);
-    }
-    if (groupEnd != null) {
-      _writer.print(groupEnd);
-    }
-    _writer.print(')');
-  }
-
-  @override
-  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
-    _visitNode(node.variables);
-    _writer.print(';');
-    _visitNodeWithPrefix(' ', node.condition);
-    _writer.print(';');
-    _visitNodeListWithSeparatorAndPrefix(' ', node.updaters, ', ');
-  }
-
-  @override
-  void visitForPartsWithExpression(ForPartsWithExpression node) {
-    _visitNode(node.initialization);
-    _writer.print(';');
-    _visitNodeWithPrefix(' ', node.condition);
-    _writer.print(';');
-    _visitNodeListWithSeparatorAndPrefix(" ", node.updaters, ', ');
-  }
-
-  @override
-  void visitForStatement(ForStatement node) {
-    if (node.awaitKeyword != null) {
-      _writer.print('await ');
-    }
-    _writer.print('for (');
-    _visitNode(node.forLoopParts);
-    _writer.print(') ');
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitTokenWithSuffix(node.propertyKeyword, " ");
-    _visitNode(node.name);
-    _visitNode(node.functionExpression);
-  }
-
-  @override
-  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    _visitNode(node.functionDeclaration);
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    if (node.body is! EmptyFunctionBody) {
-      _writer.print(' ');
-    }
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    _visitNode(node.function);
-    _visitNode(node.typeArguments);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("typedef ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    _writer.print(";");
-  }
-
-  @override
-  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.covariantKeyword, ' ');
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitNode(node.identifier);
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    if (node.question != null) {
-      _writer.print('?');
-    }
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    _visitNode(node.returnType);
-    _writer.print(' Function');
-    _visitNode(node.typeParameters);
-    _visitNode(node.parameters);
-    if (node.question != null) {
-      _writer.print('?');
-    }
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("typedef ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _writer.print(" = ");
-    _visitNode(node.functionType);
-  }
-
-  @override
-  void visitHideCombinator(HideCombinator node) {
-    _writer.print("hide ");
-    _visitNodeListWithSeparator(node.hiddenNames, ", ");
-  }
-
-  @override
-  void visitIfElement(IfElement node) {
-    _writer.print('if (');
-    _visitNode(node.condition);
-    _writer.print(') ');
-    _visitNode(node.thenElement);
-    _visitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
-  void visitIfStatement(IfStatement node) {
-    _writer.print("if (");
-    _visitNode(node.condition);
-    _writer.print(") ");
-    _visitNode(node.thenStatement);
-    _visitNodeWithPrefix(" else ", node.elseStatement);
-  }
-
-  @override
-  void visitImplementsClause(ImplementsClause node) {
-    _writer.print("implements ");
-    _visitNodeListWithSeparator(node.interfaces, ", ");
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("import ");
-    _visitNode(node.uri);
-    if (node.deferredKeyword != null) {
-      _writer.print(" deferred");
-    }
-    _visitNodeWithPrefix(" as ", node.prefix);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    _writer.print(';');
-  }
-
-  @override
-  void visitIndexExpression(IndexExpression node) {
-    if (node.isCascaded) {
-      _writer.print(node.period.lexeme);
-    } else {
-      _visitNode(node.target);
-    }
-    _writer.print('[');
-    _visitNode(node.index);
-    _writer.print(']');
-  }
-
-  @override
-  void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNode(node.constructorName);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitIntegerLiteral(IntegerLiteral node) {
-    _writer.print(node.literal.lexeme);
-  }
-
-  @override
-  void visitInterpolationExpression(InterpolationExpression node) {
-    if (node.rightBracket != null) {
-      _writer.print("\${");
-      _visitNode(node.expression);
-      _writer.print("}");
-    } else {
-      _writer.print("\$");
-      _visitNode(node.expression);
-    }
-  }
-
-  @override
-  void visitInterpolationString(InterpolationString node) {
-    _writer.print(node.contents.lexeme);
-  }
-
-  @override
-  void visitIsExpression(IsExpression node) {
-    _visitNode(node.expression);
-    if (node.notOperator == null) {
-      _writer.print(" is ");
-    } else {
-      _writer.print(" is! ");
-    }
-    _visitNode(node.type);
-  }
-
-  @override
-  void visitLabel(Label node) {
-    _visitNode(node.label);
-    _writer.print(":");
-  }
-
-  @override
-  void visitLabeledStatement(LabeledStatement node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _visitNode(node.statement);
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("library ");
-    _visitNode(node.name);
-    _writer.print(';');
-  }
-
-  @override
-  void visitLibraryIdentifier(LibraryIdentifier node) {
-    _writer.print(node.name);
-  }
-
-  @override
-  void visitListLiteral(ListLiteral node) {
-    _visitTokenWithSuffix(node.constKeyword, ' ');
-    _visitNode(node.typeArguments);
-    _writer.print('[');
-    _visitNodeListWithSeparator(node.elements, ', ');
-    _writer.print(']');
-  }
-
-  @override
-  void visitMapLiteralEntry(MapLiteralEntry node) {
-    _visitNode(node.key);
-    _writer.print(" : ");
-    _visitNode(node.value);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.externalKeyword, " ");
-    _visitTokenWithSuffix(node.modifierKeyword, " ");
-    _visitNodeWithSuffix(node.returnType, " ");
-    _visitTokenWithSuffix(node.propertyKeyword, " ");
-    _visitTokenWithSuffix(node.operatorKeyword, " ");
-    _visitNode(node.name);
-    if (!node.isGetter) {
-      _visitNode(node.typeParameters);
-      _visitNode(node.parameters);
-    }
-    _visitFunctionWithPrefix(" ", node.body);
-  }
-
-  @override
-  void visitMethodInvocation(MethodInvocation node) {
-    if (node.isCascaded) {
-      _writer.print(node.operator.lexeme);
-    } else {
-      if (node.target != null) {
-        node.target.accept(this);
-        _writer.print(node.operator.lexeme);
-      }
-    }
-    _visitNode(node.methodName);
-    _visitNode(node.typeArguments);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("mixin ");
-    _visitNode(node.name);
-    _visitNode(node.typeParameters);
-    _visitNodeWithPrefix(" ", node.onClause);
-    _visitNodeWithPrefix(" ", node.implementsClause);
-    _writer.print(" {");
-    _visitNodeListWithSeparator(node.members, " ");
-    _writer.print("}");
-  }
-
-  @override
-  void visitNamedExpression(NamedExpression node) {
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" ", node.expression);
-  }
-
-  @override
-  void visitNativeClause(NativeClause node) {
-    _writer.print("native ");
-    _visitNode(node.name);
-  }
-
-  @override
-  void visitNativeFunctionBody(NativeFunctionBody node) {
-    _writer.print("native ");
-    _visitNode(node.stringLiteral);
-    _writer.print(';');
-  }
-
-  @override
-  void visitNullLiteral(NullLiteral node) {
-    _writer.print("null");
-  }
-
-  @override
-  void visitOnClause(OnClause node) {
-    _writer.print('on ');
-    _visitNodeListWithSeparator(node.superclassConstraints, ", ");
-  }
-
-  @override
-  void visitParenthesizedExpression(ParenthesizedExpression node) {
-    _writer.print('(');
-    _visitNode(node.expression);
-    _writer.print(')');
-  }
-
-  @override
-  void visitPartDirective(PartDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("part ");
-    _visitNode(node.uri);
-    _writer.print(';');
-  }
-
-  @override
-  void visitPartOfDirective(PartOfDirective node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _writer.print("part of ");
-    _visitNode(node.libraryName);
-    _writer.print(';');
-  }
-
-  @override
-  void visitPostfixExpression(PostfixExpression node) {
-    _visitNode(node.operand);
-    _writer.print(node.operator.lexeme);
-  }
-
-  @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    _visitNode(node.prefix);
-    _writer.print('.');
-    _visitNode(node.identifier);
-  }
-
-  @override
-  void visitPrefixExpression(PrefixExpression node) {
-    _writer.print(node.operator.lexeme);
-    _visitNode(node.operand);
-  }
-
-  @override
-  void visitPropertyAccess(PropertyAccess node) {
-    if (node.isCascaded) {
-      _writer.print(node.operator.lexeme);
-    } else {
-      _visitNode(node.target);
-      _writer.print(node.operator.lexeme);
-    }
-    _visitNode(node.propertyName);
-  }
-
-  @override
-  void visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    _writer.print("this");
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitRethrowExpression(RethrowExpression node) {
-    _writer.print("rethrow");
-  }
-
-  @override
-  void visitReturnStatement(ReturnStatement node) {
-    Expression expression = node.expression;
-    if (expression == null) {
-      _writer.print("return;");
-    } else {
-      _writer.print("return ");
-      expression.accept(this);
-      _writer.print(";");
-    }
-  }
-
-  @override
-  void visitScriptTag(ScriptTag node) {
-    _writer.print(node.scriptTag.lexeme);
-  }
-
-  @override
-  void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    if (node.constKeyword != null) {
-      _writer.print(node.constKeyword.lexeme);
-      _writer.print(' ');
-    }
-    _visitNode(node.typeArguments);
-    _writer.print('{');
-    _visitNodeListWithSeparator(node.elements, ', ');
-    _writer.print('}');
-  }
-
-  @override
-  void visitShowCombinator(ShowCombinator node) {
-    _writer.print("show ");
-    _visitNodeListWithSeparator(node.shownNames, ", ");
-  }
-
-  @override
-  void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    _visitTokenWithSuffix(node.covariantKeyword, ' ');
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNode(node.type);
-    if (node.type != null && node.identifier != null) {
-      _writer.print(' ');
-    }
-    _visitNode(node.identifier);
-  }
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    _writer.print(node.token.lexeme);
-  }
-
-  @override
-  void visitSimpleStringLiteral(SimpleStringLiteral node) {
-    _writer.print(node.literal.lexeme);
-  }
-
-  @override
-  void visitSpreadElement(SpreadElement node) {
-    _writer.print(node.spreadOperator.lexeme);
-    _visitNode(node.expression);
-  }
-
-  @override
-  void visitStringInterpolation(StringInterpolation node) {
-    _visitNodeList(node.elements);
-  }
-
-  @override
-  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    _writer.print("super");
-    _visitNodeWithPrefix(".", node.constructorName);
-    _visitNode(node.argumentList);
-  }
-
-  @override
-  void visitSuperExpression(SuperExpression node) {
-    _writer.print("super");
-  }
-
-  @override
-  void visitSwitchCase(SwitchCase node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _writer.print("case ");
-    _visitNode(node.expression);
-    _writer.print(": ");
-    _visitNodeListWithSeparator(node.statements, " ");
-  }
-
-  @override
-  void visitSwitchDefault(SwitchDefault node) {
-    _visitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    _writer.print("default: ");
-    _visitNodeListWithSeparator(node.statements, " ");
-  }
-
-  @override
-  void visitSwitchStatement(SwitchStatement node) {
-    _writer.print("switch (");
-    _visitNode(node.expression);
-    _writer.print(") {");
-    _visitNodeListWithSeparator(node.members, " ");
-    _writer.print("}");
-  }
-
-  @override
-  void visitSymbolLiteral(SymbolLiteral node) {
-    _writer.print("#");
-    List<Token> components = node.components;
-    for (int i = 0; i < components.length; i++) {
-      if (i > 0) {
-        _writer.print(".");
-      }
-      _writer.print(components[i].lexeme);
-    }
-  }
-
-  @override
-  void visitThisExpression(ThisExpression node) {
-    _writer.print("this");
-  }
-
-  @override
-  void visitThrowExpression(ThrowExpression node) {
-    _writer.print("throw ");
-    _visitNode(node.expression);
-  }
-
-  @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    _visitNodeWithSuffix(node.variables, ";");
-  }
-
-  @override
-  void visitTryStatement(TryStatement node) {
-    _writer.print("try ");
-    _visitNode(node.body);
-    _visitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
-    _visitNodeWithPrefix(" finally ", node.finallyBlock);
-  }
-
-  @override
-  void visitTypeArgumentList(TypeArgumentList node) {
-    _writer.print('<');
-    _visitNodeListWithSeparator(node.arguments, ", ");
-    _writer.print('>');
-  }
-
-  @override
-  void visitTypeName(TypeName node) {
-    _visitNode(node.name);
-    _visitNode(node.typeArguments);
-    if (node.question != null) {
-      _writer.print('?');
-    }
-  }
-
-  @override
-  void visitTypeParameter(TypeParameter node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" extends ", node.bound);
-  }
-
-  @override
-  void visitTypeParameterList(TypeParameterList node) {
-    _writer.print('<');
-    _visitNodeListWithSeparator(node.typeParameters, ", ");
-    _writer.print('>');
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitNode(node.name);
-    _visitNodeWithPrefix(" = ", node.initializer);
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    _visitTokenWithSuffix(node.lateKeyword, " ");
-    _visitTokenWithSuffix(node.keyword, " ");
-    _visitNodeWithSuffix(node.type, " ");
-    _visitNodeListWithSeparator(node.variables, ", ");
-  }
-
-  @override
-  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    _visitNode(node.variables);
-    _writer.print(";");
-  }
-
-  @override
-  void visitWhileStatement(WhileStatement node) {
-    _writer.print("while (");
-    _visitNode(node.condition);
-    _writer.print(") ");
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitWithClause(WithClause node) {
-    _writer.print("with ");
-    _visitNodeListWithSeparator(node.mixinTypes, ", ");
-  }
-
-  @override
-  void visitYieldStatement(YieldStatement node) {
-    if (node.star != null) {
-      _writer.print("yield* ");
-    } else {
-      _writer.print("yield ");
-    }
-    _visitNode(node.expression);
-    _writer.print(";");
-  }
-
-  /**
-   * Visit the given function [body], printing the [prefix] before if the body
-   * is not empty.
-   */
-  void _visitFunctionWithPrefix(String prefix, FunctionBody body) {
-    if (body is! EmptyFunctionBody) {
-      _writer.print(prefix);
-    }
-    _visitNode(body);
-  }
-
-  /**
-   * Safely visit the given [node].
-   */
-  void _visitNode(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Print a list of [nodes] without any separation.
-   */
-  void _visitNodeList(NodeList<AstNode> nodes) {
-    _visitNodeListWithSeparator(nodes, "");
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator].
-   */
-  void _visitNodeListWithSeparator(NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      for (int i = 0; i < size; i++) {
-        if (i > 0) {
-          _writer.print(separator);
-        }
-        nodes[i].accept(this);
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], prefixed by the given [prefix] if the list is not
-   * empty, and separated by the given [separator].
-   */
-  void _visitNodeListWithSeparatorAndPrefix(
-      String prefix, NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        _writer.print(prefix);
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            _writer.print(separator);
-          }
-          nodes[i].accept(this);
-        }
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator], followed by
-   * the given [suffix] if the list is not empty.
-   */
-  void _visitNodeListWithSeparatorAndSuffix(
-      NodeList<AstNode> nodes, String separator, String suffix) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            _writer.print(separator);
-          }
-          nodes[i].accept(this);
-        }
-        _writer.print(suffix);
-      }
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [prefix] before the node if it
-   * is non-`null`.
-   */
-  void _visitNodeWithPrefix(String prefix, AstNode node) {
-    if (node != null) {
-      _writer.print(prefix);
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [suffix] after the node if it
-   * is non-`null`.
-   */
-  void _visitNodeWithSuffix(AstNode node, String suffix) {
-    if (node != null) {
-      node.accept(this);
-      _writer.print(suffix);
-    }
-  }
-
-  /**
-   * Safely visit the given [token].
-   */
-  void _visitToken(Token token) {
-    if (token != null) {
-      _writer.print(token.lexeme);
-    }
-  }
-
-  /**
-   * Safely visit the given [token], printing the [suffix] after the token if it
-   * is non-`null`.
-   */
-  void _visitTokenWithSuffix(Token token, String suffix) {
-    if (token != null) {
-      _writer.print(token.lexeme);
-      _writer.print(suffix);
-    }
-  }
-}
-
-/**
- * A visitor used to write a source representation of a visited AST node (and
  * all of it's children) to a sink.
  */
-class ToSourceVisitor2 implements AstVisitor<void> {
-  /**
-   * The sink to which the source is to be written.
-   */
-  @protected
-  final StringSink sink;
-
-  /**
-   * Initialize a newly created visitor to write source code representing the
-   * visited nodes to the given [sink].
-   */
-  ToSourceVisitor2(this.sink);
-
-  /**
-   * Visit the given function [body], printing the [prefix] before if the body
-   * is not empty.
-   */
-  @protected
-  void safelyVisitFunctionWithPrefix(String prefix, FunctionBody body) {
-    if (body is! EmptyFunctionBody) {
-      sink.write(prefix);
-    }
-    safelyVisitNode(body);
-  }
-
-  /**
-   * Safely visit the given [node].
-   */
-  @protected
-  void safelyVisitNode(AstNode node) {
-    if (node != null) {
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Print a list of [nodes] without any separation.
-   */
-  @protected
-  void safelyVisitNodeList(NodeList<AstNode> nodes) {
-    safelyVisitNodeListWithSeparator(nodes, "");
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator].
-   */
-  @protected
-  void safelyVisitNodeListWithSeparator(
-      NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      for (int i = 0; i < size; i++) {
-        if (i > 0) {
-          sink.write(separator);
-        }
-        var node = nodes[i];
-        if (node != null) {
-          node.accept(this);
-        } else {
-          sink.write('<null>');
-        }
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], prefixed by the given [prefix] if the list is not
-   * empty, and separated by the given [separator].
-   */
-  @protected
-  void safelyVisitNodeListWithSeparatorAndPrefix(
-      String prefix, NodeList<AstNode> nodes, String separator) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        sink.write(prefix);
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            sink.write(separator);
-          }
-          nodes[i].accept(this);
-        }
-      }
-    }
-  }
-
-  /**
-   * Print a list of [nodes], separated by the given [separator], followed by
-   * the given [suffix] if the list is not empty.
-   */
-  @protected
-  void safelyVisitNodeListWithSeparatorAndSuffix(
-      NodeList<AstNode> nodes, String separator, String suffix) {
-    if (nodes != null) {
-      int size = nodes.length;
-      if (size > 0) {
-        for (int i = 0; i < size; i++) {
-          if (i > 0) {
-            sink.write(separator);
-          }
-          nodes[i].accept(this);
-        }
-        sink.write(suffix);
-      }
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [prefix] before the node if it
-   * is non-`null`.
-   */
-  @protected
-  void safelyVisitNodeWithPrefix(String prefix, AstNode node) {
-    if (node != null) {
-      sink.write(prefix);
-      node.accept(this);
-    }
-  }
-
-  /**
-   * Safely visit the given [node], printing the [suffix] after the node if it
-   * is non-`null`.
-   */
-  @protected
-  void safelyVisitNodeWithSuffix(AstNode node, String suffix) {
-    if (node != null) {
-      node.accept(this);
-      sink.write(suffix);
-    }
-  }
-
-  /**
-   * Safely visit the given [token].
-   */
-  @protected
-  void safelyVisitToken(Token token) {
-    if (token != null) {
-      sink.write(token.lexeme);
-    }
-  }
-
-  /**
-   * Safely visit the given [token], printing the [suffix] after the token if it
-   * is non-`null`.
-   */
-  @protected
-  void safelyVisitTokenWithSuffix(Token token, String suffix) {
-    if (token != null) {
-      sink.write(token.lexeme);
-      sink.write(suffix);
-    }
-  }
-
-  @override
-  void visitAdjacentStrings(AdjacentStrings node) {
-    safelyVisitNodeListWithSeparator(node.strings, " ");
-  }
-
-  @override
-  void visitAnnotation(Annotation node) {
-    sink.write('@');
-    safelyVisitNode(node.name);
-    safelyVisitNodeWithPrefix(".", node.constructorName);
-    safelyVisitNode(node.arguments);
-  }
-
-  @override
-  void visitArgumentList(ArgumentList node) {
-    sink.write('(');
-    safelyVisitNodeListWithSeparator(node.arguments, ", ");
-    sink.write(')');
-  }
-
-  @override
-  void visitAsExpression(AsExpression node) {
-    safelyVisitNode(node.expression);
-    sink.write(" as ");
-    safelyVisitNode(node.type);
-  }
-
-  @override
-  void visitAssertInitializer(AssertInitializer node) {
-    sink.write("assert (");
-    safelyVisitNode(node.condition);
-    if (node.message != null) {
-      sink.write(', ');
-      safelyVisitNode(node.message);
-    }
-    sink.write(");");
-  }
-
-  @override
-  void visitAssertStatement(AssertStatement node) {
-    sink.write("assert (");
-    safelyVisitNode(node.condition);
-    if (node.message != null) {
-      sink.write(', ');
-      safelyVisitNode(node.message);
-    }
-    sink.write(");");
-  }
-
-  @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    safelyVisitNode(node.leftHandSide);
-    sink.write(' ');
-    sink.write(node.operator.lexeme);
-    sink.write(' ');
-    safelyVisitNode(node.rightHandSide);
-  }
-
-  @override
-  void visitAwaitExpression(AwaitExpression node) {
-    sink.write("await ");
-    safelyVisitNode(node.expression);
-  }
-
-  @override
-  void visitBinaryExpression(BinaryExpression node) {
-    _writeOperand(node, node.leftOperand);
-    sink.write(' ');
-    sink.write(node.operator.lexeme);
-    sink.write(' ');
-    _writeOperand(node, node.rightOperand);
-  }
-
-  @override
-  void visitBlock(Block node) {
-    sink.write('{');
-    safelyVisitNodeListWithSeparator(node.statements, " ");
-    sink.write('}');
-  }
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      sink.write(keyword.lexeme);
-      if (node.star != null) {
-        sink.write('*');
-      }
-      sink.write(' ');
-    }
-    safelyVisitNode(node.block);
-  }
-
-  @override
-  void visitBooleanLiteral(BooleanLiteral node) {
-    sink.write(node.literal.lexeme);
-  }
-
-  @override
-  void visitBreakStatement(BreakStatement node) {
-    sink.write("break");
-    safelyVisitNodeWithPrefix(" ", node.label);
-    sink.write(";");
-  }
-
-  @override
-  void visitCascadeExpression(CascadeExpression node) {
-    safelyVisitNode(node.target);
-    safelyVisitNodeList(node.cascadeSections);
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    safelyVisitNodeWithPrefix("on ", node.exceptionType);
-    if (node.catchKeyword != null) {
-      if (node.exceptionType != null) {
-        sink.write(' ');
-      }
-      sink.write("catch (");
-      safelyVisitNode(node.exceptionParameter);
-      safelyVisitNodeWithPrefix(", ", node.stackTraceParameter);
-      sink.write(") ");
-    } else {
-      sink.write(" ");
-    }
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.abstractKeyword, " ");
-    sink.write("class ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNodeWithPrefix(" ", node.extendsClause);
-    safelyVisitNodeWithPrefix(" ", node.withClause);
-    safelyVisitNodeWithPrefix(" ", node.implementsClause);
-    sink.write(" {");
-    safelyVisitNodeListWithSeparator(node.members, " ");
-    sink.write("}");
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    if (node.abstractKeyword != null) {
-      sink.write("abstract ");
-    }
-    sink.write("class ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    sink.write(" = ");
-    safelyVisitNode(node.superclass);
-    safelyVisitNodeWithPrefix(" ", node.withClause);
-    safelyVisitNodeWithPrefix(" ", node.implementsClause);
-    sink.write(";");
-  }
-
-  @override
-  void visitComment(Comment node) {}
-
-  @override
-  void visitCommentReference(CommentReference node) {}
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    ScriptTag scriptTag = node.scriptTag;
-    NodeList<Directive> directives = node.directives;
-    safelyVisitNode(scriptTag);
-    String prefix = scriptTag == null ? "" : " ";
-    safelyVisitNodeListWithSeparatorAndPrefix(prefix, directives, " ");
-    prefix = scriptTag == null && directives.isEmpty ? "" : " ";
-    safelyVisitNodeListWithSeparatorAndPrefix(prefix, node.declarations, " ");
-  }
-
-  @override
-  void visitConditionalExpression(ConditionalExpression node) {
-    safelyVisitNode(node.condition);
-    sink.write(" ? ");
-    safelyVisitNode(node.thenExpression);
-    sink.write(" : ");
-    safelyVisitNode(node.elseExpression);
-  }
-
-  @override
-  void visitConfiguration(Configuration node) {
-    sink.write('if (');
-    safelyVisitNode(node.name);
-    safelyVisitNodeWithPrefix(" == ", node.value);
-    sink.write(') ');
-    safelyVisitNode(node.uri);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
-    safelyVisitTokenWithSuffix(node.constKeyword, " ");
-    safelyVisitTokenWithSuffix(node.factoryKeyword, " ");
-    safelyVisitNode(node.returnType);
-    safelyVisitNodeWithPrefix(".", node.name);
-    safelyVisitNode(node.parameters);
-    safelyVisitNodeListWithSeparatorAndPrefix(" : ", node.initializers, ", ");
-    safelyVisitNodeWithPrefix(" = ", node.redirectedConstructor);
-    safelyVisitFunctionWithPrefix(" ", node.body);
-  }
-
-  @override
-  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    safelyVisitTokenWithSuffix(node.thisKeyword, ".");
-    safelyVisitNode(node.fieldName);
-    sink.write(" = ");
-    safelyVisitNode(node.expression);
-  }
-
-  @override
-  void visitConstructorName(ConstructorName node) {
-    safelyVisitNode(node.type);
-    safelyVisitNodeWithPrefix(".", node.name);
-  }
-
-  @override
-  void visitContinueStatement(ContinueStatement node) {
-    sink.write("continue");
-    safelyVisitNodeWithPrefix(" ", node.label);
-    sink.write(";");
-  }
-
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.keyword, " ");
-    safelyVisitNodeWithSuffix(node.type, " ");
-    safelyVisitNode(node.identifier);
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    if (node.isRequiredNamed) {
-      sink.write('required ');
-    }
-    safelyVisitNode(node.parameter);
-    if (node.separator != null) {
-      if (node.separator.lexeme != ":") {
-        sink.write(" ");
-      }
-      sink.write(node.separator.lexeme);
-      safelyVisitNodeWithPrefix(" ", node.defaultValue);
-    }
-  }
-
-  @override
-  void visitDoStatement(DoStatement node) {
-    sink.write("do ");
-    safelyVisitNode(node.body);
-    sink.write(" while (");
-    safelyVisitNode(node.condition);
-    sink.write(");");
-  }
-
-  @override
-  void visitDottedName(DottedName node) {
-    safelyVisitNodeListWithSeparator(node.components, ".");
-  }
-
-  @override
-  void visitDoubleLiteral(DoubleLiteral node) {
-    sink.write(node.literal.lexeme);
-  }
-
-  @override
-  void visitEmptyFunctionBody(EmptyFunctionBody node) {
-    sink.write(';');
-  }
-
-  @override
-  void visitEmptyStatement(EmptyStatement node) {
-    sink.write(';');
-  }
-
-  @override
-  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitNode(node.name);
-  }
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("enum ");
-    safelyVisitNode(node.name);
-    sink.write(" {");
-    safelyVisitNodeListWithSeparator(node.constants, ", ");
-    sink.write("}");
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("export ");
-    safelyVisitNode(node.uri);
-    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    sink.write(';');
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    Token keyword = node.keyword;
-    if (keyword != null) {
-      sink.write(keyword.lexeme);
-      sink.write(' ');
-    }
-    sink.write('${node.functionDefinition?.lexeme} ');
-    safelyVisitNode(node.expression);
-    if (node.semicolon != null) {
-      sink.write(';');
-    }
-  }
-
-  @override
-  void visitExpressionStatement(ExpressionStatement node) {
-    safelyVisitNode(node.expression);
-    sink.write(';');
-  }
-
-  @override
-  void visitExtendsClause(ExtendsClause node) {
-    sink.write("extends ");
-    safelyVisitNode(node.superclass);
-  }
-
-  @override
-  void visitExtensionDeclaration(ExtensionDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    safelyVisitTokenWithSuffix(node.extensionKeyword, ' ');
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    sink.write(' ');
-    safelyVisitToken(node.onKeyword);
-    sink.write(' ');
-    safelyVisitNodeWithSuffix(node.extendedType, ' ');
-    safelyVisitToken(node.leftBracket);
-    safelyVisitNodeListWithSeparator(node.members, ' ');
-    safelyVisitToken(node.rightBracket);
-  }
-
-  @override
-  void visitExtensionOverride(ExtensionOverride node) {
-    safelyVisitNode(node.extensionName);
-    safelyVisitNode(node.typeArguments);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.staticKeyword, " ");
-    safelyVisitNode(node.fields);
-    sink.write(";");
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
-    safelyVisitTokenWithSuffix(node.keyword, " ");
-    safelyVisitNodeWithSuffix(node.type, " ");
-    sink.write("this.");
-    safelyVisitNode(node.identifier);
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNode(node.parameters);
-  }
-
-  @override
-  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
-    safelyVisitNode(node.loopVariable);
-    sink.write(' in ');
-    safelyVisitNode(node.iterable);
-  }
-
-  @override
-  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
-    safelyVisitNode(node.identifier);
-    sink.write(' in ');
-    safelyVisitNode(node.iterable);
-  }
-
-  @override
-  void visitForElement(ForElement node) {
-    safelyVisitTokenWithSuffix(node.awaitKeyword, ' ');
-    sink.write('for (');
-    safelyVisitNode(node.forLoopParts);
-    sink.write(') ');
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitFormalParameterList(FormalParameterList node) {
-    String groupEnd;
-    sink.write('(');
-    NodeList<FormalParameter> parameters = node.parameters;
-    int size = parameters.length;
-    for (int i = 0; i < size; i++) {
-      FormalParameter parameter = parameters[i];
-      if (i > 0) {
-        sink.write(", ");
-      }
-      if (groupEnd == null && parameter is DefaultFormalParameter) {
-        if (parameter.isNamed) {
-          groupEnd = "}";
-          sink.write('{');
-        } else {
-          groupEnd = "]";
-          sink.write('[');
-        }
-      }
-      parameter.accept(this);
-    }
-    if (groupEnd != null) {
-      sink.write(groupEnd);
-    }
-    sink.write(')');
-  }
-
-  @override
-  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
-    safelyVisitNode(node.variables);
-    sink.write(';');
-    safelyVisitNodeWithPrefix(' ', node.condition);
-    sink.write(';');
-    safelyVisitNodeListWithSeparatorAndPrefix(' ', node.updaters, ', ');
-  }
-
-  @override
-  void visitForPartsWithExpression(ForPartsWithExpression node) {
-    safelyVisitNode(node.initialization);
-    sink.write(';');
-    safelyVisitNodeWithPrefix(' ', node.condition);
-    sink.write(';');
-    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.updaters, ', ');
-  }
-
-  @override
-  void visitForStatement(ForStatement node) {
-    if (node.awaitKeyword != null) {
-      sink.write('await ');
-    }
-    sink.write('for (');
-    safelyVisitNode(node.forLoopParts);
-    sink.write(') ');
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
-    safelyVisitNodeWithSuffix(node.returnType, " ");
-    safelyVisitTokenWithSuffix(node.propertyKeyword, " ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.functionExpression);
-  }
-
-  @override
-  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    safelyVisitNode(node.functionDeclaration);
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNode(node.parameters);
-    if (node.body is! EmptyFunctionBody) {
-      sink.write(' ');
-    }
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    safelyVisitNode(node.function);
-    safelyVisitNode(node.typeArguments);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("typedef ");
-    safelyVisitNodeWithSuffix(node.returnType, " ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNode(node.parameters);
-    sink.write(";");
-  }
-
-  @override
-  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
-    safelyVisitNodeWithSuffix(node.returnType, " ");
-    safelyVisitNode(node.identifier);
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNode(node.parameters);
-    if (node.question != null) {
-      sink.write('?');
-    }
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    safelyVisitNode(node.returnType);
-    sink.write(' Function');
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNode(node.parameters);
-    if (node.question != null) {
-      sink.write('?');
-    }
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("typedef ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    sink.write(" = ");
-    safelyVisitNode(node.functionType);
-  }
-
-  @override
-  void visitHideCombinator(HideCombinator node) {
-    sink.write("hide ");
-    safelyVisitNodeListWithSeparator(node.hiddenNames, ", ");
-  }
-
-  @override
-  void visitIfElement(IfElement node) {
-    sink.write('if (');
-    safelyVisitNode(node.condition);
-    sink.write(') ');
-    safelyVisitNode(node.thenElement);
-    safelyVisitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
-  void visitIfStatement(IfStatement node) {
-    sink.write("if (");
-    safelyVisitNode(node.condition);
-    sink.write(") ");
-    safelyVisitNode(node.thenStatement);
-    safelyVisitNodeWithPrefix(" else ", node.elseStatement);
-  }
-
-  @override
-  void visitImplementsClause(ImplementsClause node) {
-    sink.write("implements ");
-    safelyVisitNodeListWithSeparator(node.interfaces, ", ");
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("import ");
-    safelyVisitNode(node.uri);
-    if (node.deferredKeyword != null) {
-      sink.write(" deferred");
-    }
-    safelyVisitNodeWithPrefix(" as ", node.prefix);
-    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.combinators, " ");
-    sink.write(';');
-  }
-
-  @override
-  void visitIndexExpression(IndexExpression node) {
-    if (node.isCascaded) {
-      sink.write(node.period.lexeme);
-    } else {
-      safelyVisitNode(node.target);
-    }
-    sink.write('[');
-    safelyVisitNode(node.index);
-    sink.write(']');
-  }
-
-  @override
-  void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    safelyVisitTokenWithSuffix(node.keyword, " ");
-    safelyVisitNode(node.constructorName);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitIntegerLiteral(IntegerLiteral node) {
-    sink.write(node.literal.lexeme);
-  }
-
-  @override
-  void visitInterpolationExpression(InterpolationExpression node) {
-    if (node.rightBracket != null) {
-      sink.write("\${");
-      safelyVisitNode(node.expression);
-      sink.write("}");
-    } else {
-      sink.write("\$");
-      safelyVisitNode(node.expression);
-    }
-  }
-
-  @override
-  void visitInterpolationString(InterpolationString node) {
-    sink.write(node.contents.lexeme);
-  }
-
-  @override
-  void visitIsExpression(IsExpression node) {
-    safelyVisitNode(node.expression);
-    if (node.notOperator == null) {
-      sink.write(" is ");
-    } else {
-      sink.write(" is! ");
-    }
-    safelyVisitNode(node.type);
-  }
-
-  @override
-  void visitLabel(Label node) {
-    safelyVisitNode(node.label);
-    sink.write(":");
-  }
-
-  @override
-  void visitLabeledStatement(LabeledStatement node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    safelyVisitNode(node.statement);
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("library ");
-    safelyVisitNode(node.name);
-    sink.write(';');
-  }
-
-  @override
-  void visitLibraryIdentifier(LibraryIdentifier node) {
-    sink.write(node.name);
-  }
-
-  @override
-  void visitListLiteral(ListLiteral node) {
-    safelyVisitTokenWithSuffix(node.constKeyword, ' ');
-    safelyVisitNode(node.typeArguments);
-    sink.write('[');
-    safelyVisitNodeListWithSeparator(node.elements, ', ');
-    sink.write(']');
-  }
-
-  @override
-  void visitMapLiteralEntry(MapLiteralEntry node) {
-    safelyVisitNode(node.key);
-    sink.write(" : ");
-    safelyVisitNode(node.value);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.externalKeyword, " ");
-    safelyVisitTokenWithSuffix(node.modifierKeyword, " ");
-    safelyVisitNodeWithSuffix(node.returnType, " ");
-    safelyVisitTokenWithSuffix(node.propertyKeyword, " ");
-    safelyVisitTokenWithSuffix(node.operatorKeyword, " ");
-    safelyVisitNode(node.name);
-    if (!node.isGetter) {
-      safelyVisitNode(node.typeParameters);
-      safelyVisitNode(node.parameters);
-    }
-    safelyVisitFunctionWithPrefix(" ", node.body);
-  }
-
-  @override
-  void visitMethodInvocation(MethodInvocation node) {
-    if (node.isCascaded) {
-      sink.write(node.operator.lexeme);
-    } else {
-      if (node.target != null) {
-        node.target.accept(this);
-        sink.write(node.operator.lexeme);
-      }
-    }
-    safelyVisitNode(node.methodName);
-    safelyVisitNode(node.typeArguments);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("mixin ");
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeParameters);
-    safelyVisitNodeWithPrefix(" ", node.onClause);
-    safelyVisitNodeWithPrefix(" ", node.implementsClause);
-    sink.write(" {");
-    safelyVisitNodeListWithSeparator(node.members, " ");
-    sink.write("}");
-  }
-
-  @override
-  void visitNamedExpression(NamedExpression node) {
-    safelyVisitNode(node.name);
-    safelyVisitNodeWithPrefix(" ", node.expression);
-  }
-
-  @override
-  void visitNativeClause(NativeClause node) {
-    sink.write("native ");
-    safelyVisitNode(node.name);
-  }
-
-  @override
-  void visitNativeFunctionBody(NativeFunctionBody node) {
-    sink.write("native ");
-    safelyVisitNode(node.stringLiteral);
-    sink.write(';');
-  }
-
-  @override
-  void visitNullLiteral(NullLiteral node) {
-    sink.write("null");
-  }
-
-  @override
-  void visitOnClause(OnClause node) {
-    sink.write('on ');
-    safelyVisitNodeListWithSeparator(node.superclassConstraints, ", ");
-  }
-
-  @override
-  void visitParenthesizedExpression(ParenthesizedExpression node) {
-    sink.write('(');
-    safelyVisitNode(node.expression);
-    sink.write(')');
-  }
-
-  @override
-  void visitPartDirective(PartDirective node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("part ");
-    safelyVisitNode(node.uri);
-    sink.write(';');
-  }
-
-  @override
-  void visitPartOfDirective(PartOfDirective node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    sink.write("part of ");
-    safelyVisitNode(node.libraryName);
-    sink.write(';');
-  }
-
-  @override
-  void visitPostfixExpression(PostfixExpression node) {
-    _writeOperand(node, node.operand);
-    sink.write(node.operator.lexeme);
-  }
-
-  @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    safelyVisitNode(node.prefix);
-    sink.write('.');
-    safelyVisitNode(node.identifier);
-  }
-
-  @override
-  void visitPrefixExpression(PrefixExpression node) {
-    sink.write(node.operator.lexeme);
-    _writeOperand(node, node.operand);
-  }
-
-  @override
-  void visitPropertyAccess(PropertyAccess node) {
-    if (node.isCascaded) {
-      sink.write(node.operator.lexeme);
-    } else {
-      safelyVisitNode(node.target);
-      sink.write(node.operator.lexeme);
-    }
-    safelyVisitNode(node.propertyName);
-  }
-
-  @override
-  void visitRedirectingConstructorInvocation(
-      RedirectingConstructorInvocation node) {
-    sink.write("this");
-    safelyVisitNodeWithPrefix(".", node.constructorName);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitRethrowExpression(RethrowExpression node) {
-    sink.write("rethrow");
-  }
-
-  @override
-  void visitReturnStatement(ReturnStatement node) {
-    Expression expression = node.expression;
-    if (expression == null) {
-      sink.write("return;");
-    } else {
-      sink.write("return ");
-      expression.accept(this);
-      sink.write(";");
-    }
-  }
-
-  @override
-  void visitScriptTag(ScriptTag node) {
-    sink.write(node.scriptTag.lexeme);
-  }
-
-  @override
-  void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    safelyVisitTokenWithSuffix(node.constKeyword, ' ');
-    safelyVisitNode(node.typeArguments);
-    sink.write('{');
-    safelyVisitNodeListWithSeparator(node.elements, ', ');
-    sink.write('}');
-  }
-
-  @override
-  void visitShowCombinator(ShowCombinator node) {
-    sink.write("show ");
-    safelyVisitNodeListWithSeparator(node.shownNames, ", ");
-  }
-
-  @override
-  void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
-    safelyVisitTokenWithSuffix(node.covariantKeyword, ' ');
-    safelyVisitTokenWithSuffix(node.keyword, " ");
-    safelyVisitNode(node.type);
-    if (node.type != null && node.identifier != null) {
-      sink.write(' ');
-    }
-    safelyVisitNode(node.identifier);
-  }
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    sink.write(node.token.lexeme);
-  }
-
-  @override
-  void visitSimpleStringLiteral(SimpleStringLiteral node) {
-    sink.write(node.literal.lexeme);
-  }
-
-  @override
-  void visitSpreadElement(SpreadElement node) {
-    sink.write(node.spreadOperator.lexeme);
-    safelyVisitNode(node.expression);
-  }
-
-  @override
-  void visitStringInterpolation(StringInterpolation node) {
-    safelyVisitNodeList(node.elements);
-  }
-
-  @override
-  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    sink.write("super");
-    safelyVisitNodeWithPrefix(".", node.constructorName);
-    safelyVisitNode(node.argumentList);
-  }
-
-  @override
-  void visitSuperExpression(SuperExpression node) {
-    sink.write("super");
-  }
-
-  @override
-  void visitSwitchCase(SwitchCase node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    sink.write("case ");
-    safelyVisitNode(node.expression);
-    sink.write(": ");
-    safelyVisitNodeListWithSeparator(node.statements, " ");
-  }
-
-  @override
-  void visitSwitchDefault(SwitchDefault node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.labels, " ", " ");
-    sink.write("default: ");
-    safelyVisitNodeListWithSeparator(node.statements, " ");
-  }
-
-  @override
-  void visitSwitchStatement(SwitchStatement node) {
-    sink.write("switch (");
-    safelyVisitNode(node.expression);
-    sink.write(") {");
-    safelyVisitNodeListWithSeparator(node.members, " ");
-    sink.write("}");
-  }
-
-  @override
-  void visitSymbolLiteral(SymbolLiteral node) {
-    sink.write("#");
-    List<Token> components = node.components;
-    for (int i = 0; i < components.length; i++) {
-      if (i > 0) {
-        sink.write(".");
-      }
-      sink.write(components[i].lexeme);
-    }
-  }
-
-  @override
-  void visitThisExpression(ThisExpression node) {
-    sink.write("this");
-  }
-
-  @override
-  void visitThrowExpression(ThrowExpression node) {
-    sink.write("throw ");
-    safelyVisitNode(node.expression);
-  }
-
-  @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    safelyVisitNodeWithSuffix(node.variables, ";");
-  }
-
-  @override
-  void visitTryStatement(TryStatement node) {
-    sink.write("try ");
-    safelyVisitNode(node.body);
-    safelyVisitNodeListWithSeparatorAndPrefix(" ", node.catchClauses, " ");
-    safelyVisitNodeWithPrefix(" finally ", node.finallyBlock);
-  }
-
-  @override
-  void visitTypeArgumentList(TypeArgumentList node) {
-    sink.write('<');
-    safelyVisitNodeListWithSeparator(node.arguments, ", ");
-    sink.write('>');
-  }
-
-  @override
-  void visitTypeName(TypeName node) {
-    safelyVisitNode(node.name);
-    safelyVisitNode(node.typeArguments);
-    if (node.question != null) {
-      sink.write('?');
-    }
-  }
-
-  @override
-  void visitTypeParameter(TypeParameter node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitNode(node.name);
-    safelyVisitNodeWithPrefix(" extends ", node.bound);
-  }
-
-  @override
-  void visitTypeParameterList(TypeParameterList node) {
-    sink.write('<');
-    safelyVisitNodeListWithSeparator(node.typeParameters, ", ");
-    sink.write('>');
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitNode(node.name);
-    safelyVisitNodeWithPrefix(" = ", node.initializer);
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
-    safelyVisitTokenWithSuffix(node.lateKeyword, " ");
-    safelyVisitTokenWithSuffix(node.keyword, " ");
-    safelyVisitNodeWithSuffix(node.type, " ");
-    safelyVisitNodeListWithSeparator(node.variables, ", ");
-  }
-
-  @override
-  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    safelyVisitNode(node.variables);
-    sink.write(";");
-  }
-
-  @override
-  void visitWhileStatement(WhileStatement node) {
-    sink.write("while (");
-    safelyVisitNode(node.condition);
-    sink.write(") ");
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitWithClause(WithClause node) {
-    sink.write("with ");
-    safelyVisitNodeListWithSeparator(node.mixinTypes, ", ");
-  }
-
-  @override
-  void visitYieldStatement(YieldStatement node) {
-    if (node.star != null) {
-      sink.write("yield* ");
-    } else {
-      sink.write("yield ");
-    }
-    safelyVisitNode(node.expression);
-    sink.write(";");
-  }
-
-  void _writeOperand(Expression node, Expression operand) {
-    if (operand != null) {
-      bool needsParenthesis = operand.precedence < node.precedence;
-      if (needsParenthesis) {
-        sink.write('(');
-      }
-      operand.accept(this);
-      if (needsParenthesis) {
-        sink.write(')');
-      }
-    }
-  }
+@Deprecated('Use ToSourceVisitor')
+class ToSourceVisitor2 extends ToSourceVisitor {
+  ToSourceVisitor2(StringSink sink) : super(sink);
 }
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 4e70221..4fa3e1f 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -254,7 +254,7 @@
     } else {
       // Should not happen.
       assert(false);
-      AnalysisEngine.instance.logger
+      AnalysisEngine.instance.instrumentationService
           .logError("Constant value computer trying to compute "
               "the value of a node of type ${constant.runtimeType}");
       return;
@@ -354,7 +354,7 @@
         // of the annotation, so there's not a lot of information in this
         // message, but it's better than getting an exception.
         // https://github.com/dart-lang/sdk/issues/26811
-        AnalysisEngine.instance.logger.logInformation(
+        AnalysisEngine.instance.instrumentationService.logInfo(
             'No annotationAst for $constant in ${constant.compilationUnit}');
       } else if (constNode.arguments != null) {
         constNode.arguments.accept(referenceFinder);
@@ -368,7 +368,7 @@
     } else {
       // Should not happen.
       assert(false);
-      AnalysisEngine.instance.logger
+      AnalysisEngine.instance.instrumentationService
           .logError("Constant value computer trying to compute "
               "the value of a node of type ${constant.runtimeType}");
     }
@@ -819,7 +819,7 @@
       // Should not happen.  Formal parameter defaults and annotations should
       // never appear as part of a cycle because they can't be referred to.
       assert(false);
-      AnalysisEngine.instance.logger
+      AnalysisEngine.instance.instrumentationService
           .logError("Constant value computer trying to report a cycle error "
               "for a node of type ${constant.runtimeType}");
     }
@@ -970,35 +970,6 @@
   /// provider.
   TypeProvider get _typeProvider => evaluationEngine.typeProvider;
 
-  /// Given a [type] that may contain free type variables, evaluate them against
-  /// the current lexical environment and return the substituted type.
-  DartType evaluateType(DartType type) {
-    if (type is TypeParameterType) {
-      return null;
-    }
-    if (type is ParameterizedType) {
-      List<DartType> typeArguments;
-      for (int i = 0; i < type.typeArguments.length; i++) {
-        DartType ta = type.typeArguments[i];
-        DartType t = evaluateType(ta);
-        if (!identical(t, ta)) {
-          if (typeArguments == null) {
-            typeArguments = type.typeArguments.toList(growable: false);
-          }
-          typeArguments[i] = t;
-        }
-      }
-      if (typeArguments == null) return type;
-      return type.substitute2(typeArguments, type.typeArguments);
-    }
-    return type;
-  }
-
-  /// Given a [type], returns the constant value that contains that type value.
-  DartObjectImpl typeConstant(DartType type) {
-    return new DartObjectImpl(_typeProvider.typeType, new TypeState(type));
-  }
-
   @override
   DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
     DartObjectImpl result;
@@ -1293,7 +1264,7 @@
     Element prefixElement = prefixNode.staticElement;
     // String.length
     if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
-      DartObjectImpl prefixResult = node.prefix.accept(this);
+      DartObjectImpl prefixResult = prefixNode.accept(this);
       if (_isStringLength(prefixResult, node.identifier)) {
         return prefixResult.stringLength(_typeProvider);
       }
@@ -1443,17 +1414,15 @@
         _typeProvider.symbolType, new SymbolState(buffer.toString()));
   }
 
-  DartObjectImpl visitTypeAnnotation(TypeAnnotation node) {
-    DartType type = evaluateType(node.type);
-    if (type == null) {
+  @override
+  DartObjectImpl visitTypeName(TypeName node) {
+    var type = node.type;
+    if (_hasTypeParameterReference(type)) {
       return super.visitTypeName(node);
     }
-    return typeConstant(type);
+    return DartObjectImpl(_typeProvider.typeType, TypeState(type));
   }
 
-  @override
-  DartObjectImpl visitTypeName(TypeName node) => visitTypeAnnotation(node);
-
   /// Add the entries produced by evaluating the given collection [element] to
   /// the given [list]. Return `true` if the evaluation of one or more of the
   /// elements failed.
@@ -1634,7 +1603,7 @@
         TypeState(_typeProvider.dynamicType),
       );
     } else if (variableElement is FunctionTypeAliasElement) {
-      var type = variableElement.instantiate2(
+      var type = variableElement.instantiate(
         typeArguments: variableElement.typeParameters
             .map((t) => _typeProvider.dynamicType)
             .toList(),
@@ -1662,7 +1631,8 @@
     if (targetResult == null || targetResult.type != _typeProvider.stringType) {
       return false;
     }
-    return identifier.name == 'length';
+    return identifier.name == 'length' &&
+        identifier.staticElement?.enclosingElement is! ExtensionElement;
   }
 
   void _reportNotPotentialConstants(AstNode node) {
@@ -1686,6 +1656,18 @@
     }
     return _typeProvider.nullObject;
   }
+
+  /// Return `true` if the [type] has a type parameter reference, so is not
+  /// valid in a constant context.
+  static bool _hasTypeParameterReference(DartType type) {
+    if (type is TypeParameterType) {
+      return true;
+    }
+    if (type is ParameterizedType) {
+      return type.typeArguments.any(_hasTypeParameterReference);
+    }
+    return false;
+  }
 }
 
 /// A utility class that contains methods for manipulating instances of a Dart
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
deleted file mode 100644
index 424d5dc..0000000
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ /dev/null
@@ -1,1734 +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 'dart:collection';
-
-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/error/error.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-
-/**
- * Instances of the class `ApiElementBuilder` traverse an AST structure and
- * build elements outside of function bodies and initializers.
- */
-class ApiElementBuilder extends _BaseElementBuilder {
-  /**
-   * A table mapping field names to field elements for the fields defined in the current class, or
-   * `null` if we are not in the scope of a class.
-   */
-  Map<String, FieldElement> _fieldMap;
-
-  /**
-   * Whether the class being built has a constant constructor.
-   */
-  bool _enclosingClassHasConstConstructor = false;
-
-  /**
-   * Initialize a newly created element builder to build the elements for a
-   * compilation unit. The [initialHolder] is the element holder to which the
-   * children of the visited compilation unit node will be added.
-   */
-  ApiElementBuilder(ElementHolder initialHolder,
-      CompilationUnitElementImpl compilationUnitElement)
-      : super(initialHolder, compilationUnitElement);
-
-  @override
-  void visitAnnotation(Annotation node) {
-    // Although it isn't valid to do so because closures are not constant
-    // expressions, it's possible for one of the arguments to the constructor to
-    // contain a closure. Wrapping the processing of the annotation this way
-    // prevents these closures from being added to the list of functions in the
-    // annotated declaration.
-    ElementHolder holder = new ElementHolder();
-    ElementHolder previousHolder = _currentHolder;
-    _currentHolder = holder;
-    try {
-      super.visitAnnotation(node);
-    } finally {
-      _currentHolder = previousHolder;
-    }
-  }
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {}
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    _enclosingClassHasConstConstructor = false;
-    for (var constructor in node.members) {
-      if (constructor is ConstructorDeclaration &&
-          constructor.constKeyword != null) {
-        _enclosingClassHasConstConstructor = true;
-        break;
-      }
-    }
-
-    ElementHolder holder = _buildClassMembers(node);
-
-    SimpleIdentifier className = node.name;
-    ClassElementImpl element = new ClassElementImpl.forNode(className);
-    className.staticElement = element;
-    element.isAbstract = node.isAbstract;
-    _fillClassElement(node, element, holder);
-
-    _currentHolder.addType(element);
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    SimpleIdentifier className = node.name;
-    ClassElementImpl element = new ClassElementImpl.forNode(className);
-    _setCodeRange(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-    element.isAbstract = node.abstractKeyword != null;
-    element.mixinApplication = true;
-    element.typeParameters = holder.typeParameters;
-    setElementDocumentationComment(element, node);
-    _currentHolder.addType(element);
-    className.staticElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    if (_unitElement is ElementImpl) {
-      _setCodeRange(_unitElement, node);
-    }
-    super.visitCompilationUnit(node);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    FunctionBody body = node.body;
-    SimpleIdentifier constructorName = node.name;
-    ConstructorElementImpl element =
-        new ConstructorElementImpl.forNode(constructorName);
-    _setCodeRange(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-    setElementDocumentationComment(element, node);
-    if (node.externalKeyword != null) {
-      element.external = true;
-    }
-    if (node.factoryKeyword != null) {
-      element.factory = true;
-    }
-    element.encloseElements(holder.functions);
-    element.encloseElements(holder.labels);
-    element.encloseElements(holder.localVariables);
-    element.parameters = holder.parameters;
-    element.isConst = node.constKeyword != null;
-    element.isCycleFree = element.isConst;
-    if (body.isAsynchronous) {
-      element.asynchronous = true;
-    }
-    if (body.isGenerator) {
-      element.generator = true;
-    }
-    _currentHolder.addConstructor(element);
-    (node as ConstructorDeclarationImpl).declaredElement = element;
-    if (constructorName == null) {
-      Identifier returnType = node.returnType;
-      if (returnType != null) {
-        element.nameOffset = returnType.offset;
-        element.nameEnd = returnType.end;
-      }
-    } else {
-      constructorName.staticElement = element;
-      element.periodOffset = node.period.offset;
-      element.nameEnd = constructorName.end;
-    }
-    holder.validate();
-  }
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    SimpleIdentifier enumName = node.name;
-    EnumElementImpl enumElement = new EnumElementImpl.forNode(enumName);
-    _setCodeRange(enumElement, node);
-    enumElement.metadata = _createElementAnnotations(node.metadata);
-    setElementDocumentationComment(enumElement, node);
-    InterfaceTypeImpl enumType = enumElement.thisType;
-    //
-    // Build the elements for the constants. These are minimal elements; the
-    // rest of the constant elements (and elements for other fields) must be
-    // built later after we can access the type provider.
-    //
-    List<FieldElement> fields = new List<FieldElement>();
-    NodeList<EnumConstantDeclaration> constants = node.constants;
-    for (EnumConstantDeclaration constant in constants) {
-      SimpleIdentifier constantName = constant.name;
-      FieldElementImpl constantField =
-          new ConstFieldElementImpl.forNode(constantName);
-      constantField.isStatic = true;
-      constantField.isConst = true;
-      constantField.type = enumType;
-      constantField.metadata = _createElementAnnotations(constant.metadata);
-      setElementDocumentationComment(constantField, constant);
-      fields.add(constantField);
-      new PropertyAccessorElementImpl_ImplicitGetter(constantField);
-      constantName.staticElement = constantField;
-    }
-    enumElement.fields = fields;
-    enumElement.createToStringMethodElement();
-
-    _currentHolder.addEnum(enumElement);
-    enumName.staticElement = enumElement;
-    super.visitEnumDeclaration(node);
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    List<ElementAnnotation> annotations =
-        _createElementAnnotations(node.metadata);
-    _unitElement.setAnnotations(node.offset, annotations);
-    super.visitExportDirective(node);
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {}
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    FunctionExpressionImpl expression = node.functionExpression;
-    if (expression != null) {
-      ElementHolder holder = new ElementHolder();
-      _visitChildren(holder, node);
-      FunctionBody body = expression.body;
-      Token property = node.propertyKeyword;
-      if (property == null) {
-        SimpleIdentifier functionName = node.name;
-        FunctionElementImpl element =
-            new FunctionElementImpl.forNode(functionName);
-        _setCodeRange(element, node);
-        element.metadata = _createElementAnnotations(node.metadata);
-        setElementDocumentationComment(element, node);
-        if (node.externalKeyword != null || body is NativeFunctionBody) {
-          element.external = true;
-        }
-        element.encloseElements(holder.functions);
-        element.encloseElements(holder.labels);
-        element.encloseElements(holder.localVariables);
-        element.parameters = holder.parameters;
-        element.typeParameters = holder.typeParameters;
-        if (body.isAsynchronous) {
-          element.asynchronous = true;
-        }
-        if (body.isGenerator) {
-          element.generator = true;
-        }
-        if (node.returnType == null) {
-          element.hasImplicitReturnType = true;
-        }
-        _currentHolder.addFunction(element);
-        expression.declaredElement = element;
-        functionName.staticElement = element;
-      } else {
-        SimpleIdentifier propertyNameNode = node.name;
-        if (propertyNameNode == null) {
-          // TODO(brianwilkerson) Report this internal error.
-          return;
-        }
-        String propertyName = propertyNameNode.name;
-        TopLevelVariableElementImpl variable = _currentHolder
-            .getTopLevelVariable(propertyName) as TopLevelVariableElementImpl;
-        if (variable == null) {
-          variable = new TopLevelVariableElementImpl(node.name.name, -1);
-          variable.isFinal = true;
-          variable.isSynthetic = true;
-          _currentHolder.addTopLevelVariable(variable);
-        }
-        if (node.isGetter) {
-          PropertyAccessorElementImpl getter =
-              new PropertyAccessorElementImpl.forNode(propertyNameNode);
-          _setCodeRange(getter, node);
-          getter.metadata = _createElementAnnotations(node.metadata);
-          setElementDocumentationComment(getter, node);
-          if (node.externalKeyword != null || body is NativeFunctionBody) {
-            getter.external = true;
-          }
-          getter.encloseElements(holder.functions);
-          getter.encloseElements(holder.labels);
-          getter.encloseElements(holder.localVariables);
-          if (body.isAsynchronous) {
-            getter.asynchronous = true;
-          }
-          if (body.isGenerator) {
-            getter.generator = true;
-          }
-          getter.variable = variable;
-          getter.getter = true;
-          getter.isStatic = true;
-          variable.getter = getter;
-          if (node.returnType == null) {
-            getter.hasImplicitReturnType = true;
-          }
-          _currentHolder.addAccessor(getter);
-          expression.declaredElement = getter;
-          propertyNameNode.staticElement = getter;
-        } else {
-          PropertyAccessorElementImpl setter =
-              new PropertyAccessorElementImpl.forNode(propertyNameNode);
-          _setCodeRange(setter, node);
-          setter.metadata = _createElementAnnotations(node.metadata);
-          setElementDocumentationComment(setter, node);
-          if (node.externalKeyword != null || body is NativeFunctionBody) {
-            setter.external = true;
-          }
-          setter.encloseElements(holder.functions);
-          setter.encloseElements(holder.labels);
-          setter.encloseElements(holder.localVariables);
-          setter.parameters = holder.parameters;
-          if (body.isAsynchronous) {
-            setter.asynchronous = true;
-          }
-          if (body.isGenerator) {
-            setter.generator = true;
-          }
-          setter.variable = variable;
-          setter.setter = true;
-          setter.isStatic = true;
-          if (node.returnType == null) {
-            setter.hasImplicitReturnType = true;
-          }
-          variable.setter = setter;
-          variable.isFinal = false;
-          _currentHolder.addAccessor(setter);
-          expression.declaredElement = setter;
-          propertyNameNode.staticElement = setter;
-        }
-      }
-      holder.validate();
-    }
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    if (node.parent is FunctionDeclaration) {
-      // visitFunctionDeclaration has already created the element for the
-      // declaration.  We just need to visit children.
-      super.visitFunctionExpression(node);
-      return;
-    }
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    FunctionBody body = node.body;
-    FunctionElementImpl element =
-        new FunctionElementImpl.forOffset(node.beginToken.offset);
-    _setCodeRange(element, node);
-    element.encloseElements(holder.functions);
-    element.encloseElements(holder.labels);
-    element.encloseElements(holder.localVariables);
-    element.parameters = holder.parameters;
-    element.typeParameters = holder.typeParameters;
-    if (body.isAsynchronous) {
-      element.asynchronous = true;
-    }
-    if (body.isGenerator) {
-      element.generator = true;
-    }
-    element.hasImplicitReturnType = true;
-    _currentHolder.addFunction(element);
-    (node as FunctionExpressionImpl).declaredElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    SimpleIdentifier aliasName = node.name;
-    List<ParameterElement> parameters = holder.parameters;
-    List<TypeParameterElement> typeParameters = holder.typeParameters;
-    GenericTypeAliasElementImpl element =
-        new GenericTypeAliasElementImpl.forNode(aliasName);
-    _setCodeRange(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-    setElementDocumentationComment(element, node);
-    element.function = new GenericFunctionTypeElementImpl.forOffset(-1)
-      ..parameters = parameters;
-    element.typeParameters = typeParameters;
-    _createTypeParameterTypes(typeParameters);
-    _currentHolder.addTypeAlias(element);
-    aliasName.staticElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    SimpleIdentifier aliasName = node.name;
-    List<TypeParameterElement> typeParameters = holder.typeParameters;
-    GenericTypeAliasElementImpl element =
-        new GenericTypeAliasElementImpl.forNode(aliasName);
-    _setCodeRange(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-    setElementDocumentationComment(element, node);
-    element.typeParameters = typeParameters;
-    _createTypeParameterTypes(typeParameters);
-    element.function = node.functionType?.type?.element;
-    _currentHolder.addTypeAlias(element);
-    aliasName.staticElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    List<ElementAnnotation> annotations =
-        _createElementAnnotations(node.metadata);
-    _unitElement.setAnnotations(node.offset, annotations);
-    super.visitImportDirective(node);
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    List<ElementAnnotation> annotations =
-        _createElementAnnotations(node.metadata);
-    _unitElement.setAnnotations(node.offset, annotations);
-    super.visitLibraryDirective(node);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    try {
-      ElementHolder holder = new ElementHolder();
-      _visitChildren(holder, node);
-      bool isStatic = node.isStatic;
-      Token property = node.propertyKeyword;
-      FunctionBody body = node.body;
-      if (property == null) {
-        SimpleIdentifier methodName = node.name;
-        String nameOfMethod = methodName.name;
-        if (nameOfMethod == TokenType.MINUS.lexeme &&
-            node.parameters.parameters.isEmpty) {
-          nameOfMethod = "unary-";
-        }
-        MethodElementImpl element =
-            new MethodElementImpl(nameOfMethod, methodName.offset);
-        _setCodeRange(element, node);
-        element.metadata = _createElementAnnotations(node.metadata);
-        setElementDocumentationComment(element, node);
-        element.isAbstract = node.isAbstract;
-        if (node.externalKeyword != null || body is NativeFunctionBody) {
-          element.external = true;
-        }
-        element.encloseElements(holder.functions);
-        element.encloseElements(holder.labels);
-        element.encloseElements(holder.localVariables);
-        element.parameters = holder.parameters;
-        element.isStatic = isStatic;
-        element.typeParameters = holder.typeParameters;
-        if (body.isAsynchronous) {
-          element.asynchronous = true;
-        }
-        if (body.isGenerator) {
-          element.generator = true;
-        }
-        if (node.returnType == null) {
-          element.hasImplicitReturnType = true;
-        }
-        _currentHolder.addMethod(element);
-        methodName.staticElement = element;
-      } else {
-        SimpleIdentifier propertyNameNode = node.name;
-        String propertyName = propertyNameNode.name;
-        FieldElementImpl field = _currentHolder.getField(propertyName,
-            synthetic: true) as FieldElementImpl;
-        if (field == null) {
-          field = new FieldElementImpl(node.name.name, -1);
-          field.isFinal = true;
-          field.isStatic = isStatic;
-          field.isSynthetic = true;
-          _currentHolder.addField(field);
-        }
-        if (node.isGetter) {
-          PropertyAccessorElementImpl getter =
-              new PropertyAccessorElementImpl.forNode(propertyNameNode);
-          _setCodeRange(getter, node);
-          getter.metadata = _createElementAnnotations(node.metadata);
-          setElementDocumentationComment(getter, node);
-          if (node.externalKeyword != null || body is NativeFunctionBody) {
-            getter.external = true;
-          }
-          getter.encloseElements(holder.functions);
-          getter.encloseElements(holder.labels);
-          getter.encloseElements(holder.localVariables);
-          if (body.isAsynchronous) {
-            getter.asynchronous = true;
-          }
-          if (body.isGenerator) {
-            getter.generator = true;
-          }
-          getter.variable = field;
-          getter.isAbstract = node.isAbstract;
-          getter.getter = true;
-          getter.isStatic = isStatic;
-          field.getter = getter;
-          if (node.returnType == null) {
-            getter.hasImplicitReturnType = true;
-          }
-          _currentHolder.addAccessor(getter);
-          propertyNameNode.staticElement = getter;
-        } else {
-          PropertyAccessorElementImpl setter =
-              new PropertyAccessorElementImpl.forNode(propertyNameNode);
-          _setCodeRange(setter, node);
-          setter.metadata = _createElementAnnotations(node.metadata);
-          setElementDocumentationComment(setter, node);
-          if (node.externalKeyword != null || body is NativeFunctionBody) {
-            setter.external = true;
-          }
-          setter.encloseElements(holder.functions);
-          setter.encloseElements(holder.labels);
-          setter.encloseElements(holder.localVariables);
-          setter.parameters = holder.parameters;
-          if (body.isAsynchronous) {
-            setter.asynchronous = true;
-          }
-          if (body.isGenerator) {
-            setter.generator = true;
-          }
-          setter.variable = field;
-          setter.isAbstract = node.isAbstract;
-          setter.setter = true;
-          setter.isStatic = isStatic;
-          if (node.returnType == null) {
-            setter.hasImplicitReturnType = true;
-          }
-          field.setter = setter;
-          field.isFinal = false;
-          _currentHolder.addAccessor(setter);
-          propertyNameNode.staticElement = setter;
-        }
-      }
-      holder.validate();
-    } catch (exception, stackTrace) {
-      if (node.name.staticElement == null) {
-        ClassDeclaration classNode =
-            node.thisOrAncestorOfType<ClassDeclaration>();
-        StringBuffer buffer = new StringBuffer();
-        buffer.write("The element for the method ");
-        buffer.write(node.name);
-        buffer.write(" in ");
-        buffer.write(classNode.name);
-        buffer.write(" was not set while trying to build the element model.");
-        AnalysisEngine.instance.logger.logError(
-            buffer.toString(), new CaughtException(exception, stackTrace));
-      } else {
-        String message =
-            "Exception caught in ElementBuilder.visitMethodDeclaration()";
-        AnalysisEngine.instance.logger
-            .logError(message, new CaughtException(exception, stackTrace));
-      }
-    } finally {
-      if (node.name.staticElement == null) {
-        ClassDeclaration classNode =
-            node.thisOrAncestorOfType<ClassDeclaration>();
-        StringBuffer buffer = new StringBuffer();
-        buffer.write("The element for the method ");
-        buffer.write(node.name);
-        buffer.write(" in ");
-        buffer.write(classNode.name);
-        buffer.write(" was not set while trying to resolve types.");
-        AnalysisEngine.instance.logger.logError(
-            buffer.toString(),
-            new CaughtException(
-                new AnalysisException(buffer.toString()), null));
-      }
-    }
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    ElementHolder holder = _buildClassMembers(node);
-
-    SimpleIdentifier nameNode = node.name;
-    MixinElementImpl element = new MixinElementImpl.forNode(nameNode);
-    nameNode.staticElement = element;
-    _fillClassElement(node, element, holder);
-
-    _currentHolder.addMixin(element);
-  }
-
-  @override
-  void visitPartDirective(PartDirective node) {
-    List<ElementAnnotation> annotations =
-        _createElementAnnotations(node.metadata);
-    _unitElement.setAnnotations(node.offset, annotations);
-    super.visitPartDirective(node);
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    bool isConst = node.isConst;
-    bool isFinal = node.isFinal;
-    Expression initializerNode = node.initializer;
-    bool hasInitializer = initializerNode != null;
-    VariableDeclarationList varList = node.parent;
-    FieldDeclaration fieldNode =
-        varList.parent is FieldDeclaration ? varList.parent : null;
-    VariableElementImpl element;
-    if (fieldNode != null) {
-      SimpleIdentifier fieldName = node.name;
-      FieldElementImpl field;
-      if ((isConst ||
-              isFinal &&
-                  !fieldNode.isStatic &&
-                  _enclosingClassHasConstConstructor) &&
-          hasInitializer) {
-        field = new ConstFieldElementImpl.forNode(fieldName);
-      } else {
-        field = new FieldElementImpl.forNode(fieldName);
-      }
-      element = field;
-      field.isCovariant = fieldNode.covariantKeyword != null;
-      field.isStatic = fieldNode.isStatic;
-      _setCodeRange(element, node);
-      setElementDocumentationComment(element, fieldNode);
-      field.hasImplicitType = varList.type == null;
-      _currentHolder.addField(field);
-      fieldName.staticElement = field;
-    } else {
-      SimpleIdentifier variableName = node.name;
-      TopLevelVariableElementImpl variable;
-      if (isConst && hasInitializer) {
-        variable = new ConstTopLevelVariableElementImpl.forNode(variableName);
-      } else {
-        variable = new TopLevelVariableElementImpl.forNode(variableName);
-      }
-      element = variable;
-      _setCodeRange(element, node);
-      if (varList.parent is TopLevelVariableDeclaration) {
-        setElementDocumentationComment(element, varList.parent);
-      }
-      variable.hasImplicitType = varList.type == null;
-      _currentHolder.addTopLevelVariable(variable);
-      variableName.staticElement = element;
-    }
-    element.isConst = isConst;
-    element.isFinal = isFinal;
-    if (element is PropertyInducingElementImpl) {
-      PropertyAccessorElementImpl_ImplicitGetter getter =
-          new PropertyAccessorElementImpl_ImplicitGetter(element);
-      _currentHolder.addAccessor(getter);
-      if (!isConst && !isFinal) {
-        PropertyAccessorElementImpl_ImplicitSetter setter =
-            new PropertyAccessorElementImpl_ImplicitSetter(element);
-        if (fieldNode != null) {
-          (setter.parameters[0] as ParameterElementImpl).isExplicitlyCovariant =
-              fieldNode.covariantKeyword != null;
-        }
-        _currentHolder.addAccessor(setter);
-      }
-    }
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    super.visitVariableDeclarationList(node);
-    AstNode parent = node.parent;
-    List<ElementAnnotation> elementAnnotations;
-    if (parent is FieldDeclaration) {
-      elementAnnotations = _createElementAnnotations(parent.metadata);
-    } else if (parent is TopLevelVariableDeclaration) {
-      elementAnnotations = _createElementAnnotations(parent.metadata);
-    } else {
-      // Local variable declaration
-      elementAnnotations = _createElementAnnotations(node.metadata);
-    }
-    _setVariableDeclarationListAnnotations(node, elementAnnotations);
-    _setVariableDeclarationListCodeRanges(node);
-  }
-
-  ElementHolder _buildClassMembers(AstNode classNode) {
-    ElementHolder holder = new ElementHolder();
-    //
-    // Process field declarations before constructors and methods so that field
-    // formal parameters can be correctly resolved to their fields.
-    //
-    ElementHolder previousHolder = _currentHolder;
-    _currentHolder = holder;
-    try {
-      List<ClassMember> nonFields = new List<ClassMember>();
-      classNode.visitChildren(
-          new _ClassNotExecutableElementsBuilder(this, nonFields));
-      _buildFieldMap(holder.fieldsWithoutFlushing);
-      int count = nonFields.length;
-      for (int i = 0; i < count; i++) {
-        nonFields[i].accept(this);
-      }
-    } finally {
-      _currentHolder = previousHolder;
-      _fieldMap = null;
-    }
-    return holder;
-  }
-
-  /**
-   * Build the table mapping field names to field elements for the [fields]
-   * defined in the current class.
-   */
-  void _buildFieldMap(List<FieldElement> fields) {
-    _fieldMap = new HashMap<String, FieldElement>();
-    int count = fields.length;
-    for (int i = 0; i < count; i++) {
-      FieldElement field = fields[i];
-      _fieldMap[field.name] ??= field;
-    }
-  }
-
-  /**
-   * Creates the [ConstructorElement]s array with the single default constructor element.
-   *
-   * @param interfaceType the interface type for which to create a default constructor
-   * @return the [ConstructorElement]s array with the single default constructor element
-   */
-  List<ConstructorElement> _createDefaultConstructors(
-      ClassElementImpl definingClass) {
-    ConstructorElementImpl constructor =
-        new ConstructorElementImpl.forNode(null);
-    constructor.isSynthetic = true;
-    constructor.enclosingElement = definingClass;
-    return <ConstructorElement>[constructor];
-  }
-
-  /**
-   * Create the types associated with the given type parameters, setting the type of each type
-   * parameter, and return an array of types corresponding to the given parameters.
-   *
-   * @param typeParameters the type parameters for which types are to be created
-   * @return an array of types corresponding to the given parameters
-   */
-  List<DartType> _createTypeParameterTypes(
-      List<TypeParameterElement> typeParameters) {
-    int typeParameterCount = typeParameters.length;
-    List<DartType> typeArguments = new List<DartType>(typeParameterCount);
-    for (int i = 0; i < typeParameterCount; i++) {
-      TypeParameterElementImpl typeParameter =
-          typeParameters[i] as TypeParameterElementImpl;
-      typeArguments[i] = TypeParameterTypeImpl(typeParameter);
-    }
-    return typeArguments;
-  }
-
-  void _fillClassElement(
-      AnnotatedNode node, ClassElementImpl element, ElementHolder holder) {
-    _setCodeRange(element, node);
-    setElementDocumentationComment(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-
-    element.accessors = holder.accessors;
-
-    List<ConstructorElement> constructors = holder.constructors;
-    if (constructors.isEmpty) {
-      constructors = _createDefaultConstructors(element);
-    }
-    element.constructors = constructors;
-
-    element.fields = holder.fields;
-    element.methods = holder.methods;
-    element.typeParameters = holder.typeParameters;
-
-    holder.validate();
-  }
-
-  @override
-  void _setFieldParameterField(
-      FormalParameter node, FieldFormalParameterElementImpl element) {
-    if (node.parent?.parent is ConstructorDeclaration) {
-      FieldElement field = _fieldMap == null ? null : _fieldMap[element.name];
-      if (field != null) {
-        element.field = field;
-      }
-    }
-  }
-}
-
-/**
- * A `CompilationUnitBuilder` builds an element model for a single compilation
- * unit.
- */
-class CompilationUnitBuilder {
-  /**
-   * Build the compilation unit element for the given [source] based on the
-   * compilation [unit] associated with the source. Throw an AnalysisException
-   * if the element could not be built.  [librarySource] is the source for the
-   * containing library.
-   */
-  CompilationUnitElementImpl buildCompilationUnit(
-      Source source, CompilationUnit unit, Source librarySource) {
-    return PerformanceStatistics.resolve.makeCurrentWhile(() {
-      if (unit == null) {
-        return null;
-      }
-      ElementHolder holder = new ElementHolder();
-      CompilationUnitElementImpl element = new CompilationUnitElementImpl();
-      ElementBuilder builder = new ElementBuilder(holder, element);
-      unit.accept(builder);
-      element.accessors = holder.accessors;
-      element.enums = holder.enums;
-      element.functions = holder.functions;
-      element.source = source;
-      element.librarySource = librarySource;
-      element.mixins = holder.mixins;
-      element.typeAliases = holder.typeAliases;
-      element.types = holder.types;
-      element.topLevelVariables = holder.topLevelVariables;
-      unit.element = element;
-      holder.validate();
-      return element;
-    });
-  }
-}
-
-/**
- * Instances of the class `DirectiveElementBuilder` build elements for top
- * level library directives.
- */
-class DirectiveElementBuilder extends SimpleAstVisitor<void> {
-  /**
-   * The analysis context within which directive elements are being built.
-   */
-  final AnalysisContext context;
-
-  /**
-   * The library element for which directive elements are being built.
-   */
-  final LibraryElementImpl libraryElement;
-
-  /**
-   * Map from sources referenced by this library to their modification times.
-   */
-  final Map<Source, int> sourceModificationTimeMap;
-
-  /**
-   * Map from sources imported by this library to their corresponding library
-   * elements.
-   */
-  final Map<Source, LibraryElement> importLibraryMap;
-
-  /**
-   * Map from sources imported by this library to their corresponding source
-   * kinds.
-   */
-  final Map<Source, SourceKind> importSourceKindMap;
-
-  /**
-   * Map from sources exported by this library to their corresponding library
-   * elements.
-   */
-  final Map<Source, LibraryElement> exportLibraryMap;
-
-  /**
-   * Map from sources exported by this library to their corresponding source
-   * kinds.
-   */
-  final Map<Source, SourceKind> exportSourceKindMap;
-
-  /**
-   * The [ImportElement]s created so far.
-   */
-  final List<ImportElement> imports = <ImportElement>[];
-
-  /**
-   * The [ExportElement]s created so far.
-   */
-  final List<ExportElement> exports = <ExportElement>[];
-
-  /**
-   * The errors found while building directive elements.
-   */
-  final List<AnalysisError> errors = <AnalysisError>[];
-
-  /**
-   * Map from prefix names to their corresponding elements.
-   */
-  final HashMap<String, PrefixElementImpl> nameToPrefixMap =
-      new HashMap<String, PrefixElementImpl>();
-
-  /**
-   * Indicates whether an explicit import of `dart:core` has been found.
-   */
-  bool explicitlyImportsCore = false;
-
-  DirectiveElementBuilder(
-      this.context,
-      this.libraryElement,
-      this.sourceModificationTimeMap,
-      this.importLibraryMap,
-      this.importSourceKindMap,
-      this.exportLibraryMap,
-      this.exportSourceKindMap);
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    //
-    // Resolve directives.
-    //
-    for (Directive directive in node.directives) {
-      directive.accept(this);
-    }
-    //
-    // Ensure "dart:core" import.
-    //
-    Source librarySource = libraryElement.source;
-    Source coreLibrarySource = context.sourceFactory.forUri(DartSdk.DART_CORE);
-    if (!explicitlyImportsCore && coreLibrarySource != librarySource) {
-      ImportElementImpl importElement = new ImportElementImpl(-1);
-      importElement.importedLibrary = importLibraryMap[coreLibrarySource];
-      importElement.isSynthetic = true;
-      imports.add(importElement);
-    }
-    //
-    // Populate the library element.
-    //
-    libraryElement.imports = imports;
-    libraryElement.exports = exports;
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    // Remove previous element. (It will remain null if the target is missing.)
-    node.element = null;
-    Source exportedSource = node.selectedSource;
-    int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
-    // The exported source will be null if the URI in the export
-    // directive was invalid.
-    LibraryElement exportedLibrary = exportLibraryMap[exportedSource];
-    ExportElementImpl exportElement = new ExportElementImpl(node.offset);
-    exportElement.metadata = _getElementAnnotations(node.metadata);
-    StringLiteral uriLiteral = node.uri;
-    if (uriLiteral != null) {
-      exportElement.uriOffset = uriLiteral.offset;
-      exportElement.uriEnd = uriLiteral.end;
-    }
-    exportElement.uri = node.selectedUriContent;
-    exportElement.combinators = _buildCombinators(node);
-    exportElement.exportedLibrary = exportedLibrary;
-    setElementDocumentationComment(exportElement, node);
-    node.element = exportElement;
-    exports.add(exportElement);
-    if (exportedTime >= 0 &&
-        exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
-      int offset = node.offset;
-      int length = node.length;
-      if (uriLiteral != null) {
-        offset = uriLiteral.offset;
-        length = uriLiteral.length;
-      }
-      errors.add(new AnalysisError(libraryElement.source, offset, length,
-          CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, [uriLiteral.toSource()]));
-    }
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    // Remove previous element. (It will remain null if the target is missing.)
-    node.element = null;
-    Source importedSource = node.selectedSource;
-    int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
-    // The imported source will be null if the URI in the import
-    // directive was invalid.
-    LibraryElement importedLibrary = importLibraryMap[importedSource];
-    if (importedLibrary != null && importedLibrary.isDartCore) {
-      explicitlyImportsCore = true;
-    }
-    ImportElementImpl importElement = new ImportElementImpl(node.offset);
-    importElement.metadata = _getElementAnnotations(node.metadata);
-    StringLiteral uriLiteral = node.uri;
-    if (uriLiteral != null) {
-      importElement.uriOffset = uriLiteral.offset;
-      importElement.uriEnd = uriLiteral.end;
-    }
-    importElement.uri = node.selectedUriContent;
-    importElement.deferred = node.deferredKeyword != null;
-    importElement.combinators = _buildCombinators(node);
-    importElement.importedLibrary = importedLibrary;
-    setElementDocumentationComment(importElement, node);
-    SimpleIdentifier prefixNode = node.prefix;
-    if (prefixNode != null) {
-      importElement.prefixOffset = prefixNode.offset;
-      String prefixName = prefixNode.name;
-      PrefixElementImpl prefix = nameToPrefixMap[prefixName];
-      if (prefix == null) {
-        prefix = new PrefixElementImpl.forNode(prefixNode);
-        nameToPrefixMap[prefixName] = prefix;
-      }
-      importElement.prefix = prefix;
-      prefixNode.staticElement = prefix;
-    }
-    node.element = importElement;
-    imports.add(importElement);
-    if (importedTime >= 0 &&
-        importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
-      int offset = node.offset;
-      int length = node.length;
-      if (uriLiteral != null) {
-        offset = uriLiteral.offset;
-        length = uriLiteral.length;
-      }
-      errors.add(new AnalysisError(libraryElement.source, offset, length,
-          CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, [uriLiteral.toSource()]));
-    }
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    (node.element as LibraryElementImpl)?.metadata =
-        _getElementAnnotations(node.metadata);
-  }
-
-  @override
-  void visitPartDirective(PartDirective node) {
-    (node.element as CompilationUnitElementImpl)?.metadata =
-        _getElementAnnotations(node.metadata);
-  }
-
-  /**
-   * Gather a list of the [ElementAnnotation]s referred to by the [Annotation]s
-   * in [metadata].
-   */
-  List<ElementAnnotation> _getElementAnnotations(
-      NodeList<Annotation> metadata) {
-    if (metadata.isEmpty) {
-      return const <ElementAnnotation>[];
-    }
-    return metadata.map((Annotation a) => a.elementAnnotation).toList();
-  }
-
-  /**
-   * Build the element model representing the combinators declared by
-   * the given [directive].
-   */
-  static List<NamespaceCombinator> _buildCombinators(
-      NamespaceDirective directive) {
-    _NamespaceCombinatorBuilder namespaceCombinatorBuilder =
-        new _NamespaceCombinatorBuilder();
-    for (Combinator combinator in directive.combinators) {
-      combinator.accept(namespaceCombinatorBuilder);
-    }
-    return namespaceCombinatorBuilder.combinators;
-  }
-}
-
-/**
- * Instances of the class `ElementBuilder` traverse an AST structure and build the element
- * model representing the AST structure.
- */
-class ElementBuilder extends ApiElementBuilder {
-  /// List of names of methods, getters, setters, and operators that are
-  /// super-invoked in the current mixin declaration.
-  Set<String> _mixinSuperInvokedNames;
-
-  /**
-   * Initialize a newly created element builder to build the elements for a
-   * compilation unit. The [initialHolder] is the element holder to which the
-   * children of the visited compilation unit node will be added.
-   */
-  ElementBuilder(ElementHolder initialHolder,
-      CompilationUnitElement compilationUnitElement)
-      : super(initialHolder, compilationUnitElement);
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {
-    _buildLocal(node);
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    super.visitDefaultFormalParameter(node);
-    buildParameterInitializer(
-        node.declaredElement as ParameterElementImpl, node.defaultValue);
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    _buildLocal(node);
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    _mixinSuperInvokedNames = new Set<String>();
-    try {
-      super.visitMixinDeclaration(node);
-    } finally {
-      MixinElementImpl element = node.declaredElement;
-      element.superInvokedNames = _mixinSuperInvokedNames.toList();
-      _mixinSuperInvokedNames = null;
-    }
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    super.visitVariableDeclaration(node);
-    VariableElementImpl element = node.declaredElement as VariableElementImpl;
-    buildVariableInitializer(element, node.initializer);
-  }
-
-  void _buildLocal(FunctionBody body) {
-    body.accept(new LocalElementBuilder(_currentHolder, _unitElement));
-    // This is not efficient - we visit AST second time.
-    if (_mixinSuperInvokedNames != null) {
-      body.accept(new MixinSuperInvokedNamesCollector(_mixinSuperInvokedNames));
-    }
-  }
-}
-
-/**
- * Traverse a [FunctionBody] and build elements for AST structures.
- */
-class LocalElementBuilder extends _BaseElementBuilder {
-  /**
-   * Initialize a newly created element builder to build the elements for a
-   * compilation unit. The [initialHolder] is the element holder to which the
-   * children of the visited compilation unit node will be added.
-   */
-  LocalElementBuilder(ElementHolder initialHolder,
-      CompilationUnitElementImpl compilationUnitElement)
-      : super(initialHolder, compilationUnitElement);
-
-  /**
-   * Initialize a newly created element builder as a first step to analyzing a
-   * dangling dart expression.
-   */
-  LocalElementBuilder.forDanglingExpression()
-      : super(new ElementHolder(), null);
-
-  /**
-   * Builds the variable elements associated with [node] and stores them in
-   * the element holder.
-   */
-  void buildCatchVariableElements(CatchClause node) {
-    SimpleIdentifier exceptionParameter = node.exceptionParameter;
-    if (exceptionParameter != null) {
-      // exception
-      LocalVariableElementImpl exception =
-          new LocalVariableElementImpl.forNode(exceptionParameter);
-      if (node.exceptionType == null) {
-        exception.hasImplicitType = true;
-      }
-      exception.setVisibleRange(node.offset, node.length);
-      _currentHolder.addLocalVariable(exception);
-      exceptionParameter.staticElement = exception;
-      // stack trace
-      SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
-      if (stackTraceParameter != null) {
-        LocalVariableElementImpl stackTrace =
-            new LocalVariableElementImpl.forNode(stackTraceParameter);
-        _setCodeRange(stackTrace, stackTraceParameter);
-        stackTrace.setVisibleRange(node.offset, node.length);
-        _currentHolder.addLocalVariable(stackTrace);
-        stackTraceParameter.staticElement = stackTrace;
-      }
-    }
-  }
-
-  /**
-   * Builds the label elements associated with [labels] and stores them in the
-   * element holder.
-   */
-  void buildLabelElements(
-      NodeList<Label> labels, bool onSwitchStatement, bool onSwitchMember) {
-    for (Label label in labels) {
-      SimpleIdentifier labelName = label.label;
-      LabelElementImpl element = new LabelElementImpl.forNode(
-          labelName, onSwitchStatement, onSwitchMember);
-      labelName.staticElement = element;
-      _currentHolder.addLabel(element);
-    }
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    buildCatchVariableElements(node);
-    super.visitCatchClause(node);
-  }
-
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    SimpleIdentifier variableName = node.identifier;
-    LocalVariableElementImpl element =
-        new LocalVariableElementImpl.forNode(variableName);
-    _setCodeRange(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-
-    var parent = node.parent;
-    if (parent is ForEachPartsWithDeclaration) {
-      var statement = parent.parent;
-      element.setVisibleRange(statement.offset, statement.length);
-    }
-
-    element.isConst = node.isConst;
-    element.isFinal = node.isFinal;
-    if (node.type == null) {
-      element.hasImplicitType = true;
-    } else {
-      // Note: this is a noop most of the time, however, not for
-      // [GenericFunctionType] and perhaps others in the future.
-      node.type.accept(this);
-    }
-    _currentHolder.addLocalVariable(element);
-    variableName.staticElement = element;
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    super.visitDefaultFormalParameter(node);
-    buildParameterInitializer(
-        node.declaredElement as ParameterElementImpl, node.defaultValue);
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    FunctionExpressionImpl expression = node.functionExpression;
-    if (expression == null) {
-      return;
-    }
-
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-
-    FunctionElementImpl element = new FunctionElementImpl.forNode(node.name);
-    element.type = new FunctionTypeImpl(element);
-    _setCodeRange(element, node);
-    setElementDocumentationComment(element, node);
-    element.metadata = _createElementAnnotations(node.metadata);
-    FunctionBody body = expression.body;
-    if (node.externalKeyword != null || body is NativeFunctionBody) {
-      element.external = true;
-    }
-    element.encloseElements(holder.functions);
-    element.encloseElements(holder.labels);
-    element.encloseElements(holder.localVariables);
-    element.parameters = holder.parameters;
-    element.typeParameters = holder.typeParameters;
-
-    if (body.isAsynchronous) {
-      element.asynchronous = body.isAsynchronous;
-    }
-    if (body.isGenerator) {
-      element.generator = true;
-    }
-
-    {
-      Block enclosingBlock = node.thisOrAncestorOfType<Block>();
-      if (enclosingBlock != null) {
-        element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
-      }
-    }
-
-    if (node.returnType == null) {
-      element.hasImplicitReturnType = true;
-    }
-
-    _currentHolder.addFunction(element);
-    expression.declaredElement = element;
-    node.name.staticElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    if (node.parent is FunctionDeclaration) {
-      // visitFunctionDeclaration has already created the element for the
-      // declaration.  We just need to visit children.
-      super.visitFunctionExpression(node);
-      return;
-    }
-
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    FunctionElementImpl element =
-        new FunctionElementImpl.forOffset(node.beginToken.offset);
-    _setCodeRange(element, node);
-    element.encloseElements(holder.functions);
-    element.encloseElements(holder.labels);
-    element.encloseElements(holder.localVariables);
-    element.parameters = holder.parameters;
-    element.typeParameters = holder.typeParameters;
-
-    FunctionBody body = node.body;
-    if (body.isAsynchronous) {
-      element.asynchronous = true;
-    }
-    if (body.isGenerator) {
-      element.generator = true;
-    }
-    Block enclosingBlock = node.thisOrAncestorOfType<Block>();
-    if (enclosingBlock != null) {
-      element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
-    }
-    element.hasImplicitReturnType = true;
-    _currentHolder.addFunction(element);
-    (node as FunctionExpressionImpl).declaredElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitLabeledStatement(LabeledStatement node) {
-    bool onSwitchStatement = node.statement is SwitchStatement;
-    buildLabelElements(node.labels, onSwitchStatement, false);
-    super.visitLabeledStatement(node);
-  }
-
-  @override
-  void visitSwitchCase(SwitchCase node) {
-    buildLabelElements(node.labels, false, true);
-    super.visitSwitchCase(node);
-  }
-
-  @override
-  void visitSwitchDefault(SwitchDefault node) {
-    buildLabelElements(node.labels, false, true);
-    super.visitSwitchDefault(node);
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    bool isConst = node.isConst;
-    bool isFinal = node.isFinal;
-    Expression initializerNode = node.initializer;
-    VariableDeclarationList varList = node.parent;
-    SimpleIdentifier variableName = node.name;
-    LocalVariableElementImpl element;
-    if (isConst && initializerNode != null) {
-      element = new ConstLocalVariableElementImpl.forNode(variableName);
-    } else {
-      element = new LocalVariableElementImpl.forNode(variableName);
-    }
-    _setCodeRange(element, node);
-    _setVariableVisibleRange(element, node);
-    element.hasImplicitType = varList.type == null;
-    _currentHolder.addLocalVariable(element);
-    variableName.staticElement = element;
-    element.isConst = isConst;
-    element.isFinal = isFinal;
-    element.isLate = node.isLate;
-    buildVariableInitializer(element, initializerNode);
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    super.visitVariableDeclarationList(node);
-    List<ElementAnnotation> elementAnnotations =
-        _createElementAnnotations(node.metadata);
-    _setVariableDeclarationListAnnotations(node, elementAnnotations);
-    _setVariableDeclarationListCodeRanges(node);
-  }
-
-  void _setVariableVisibleRange(
-      LocalVariableElementImpl element, VariableDeclaration node) {
-    AstNode scopeNode;
-    AstNode parent2 = node.parent.parent;
-    if (parent2 is ForPartsWithDeclarations) {
-      scopeNode = parent2.parent;
-    } else {
-      scopeNode = node.thisOrAncestorOfType<Block>();
-    }
-    element.setVisibleRange(scopeNode.offset, scopeNode.length);
-  }
-}
-
-/**
- * Base class for API and local element builders.
- */
-abstract class _BaseElementBuilder extends RecursiveAstVisitor<void> {
-  /**
-   * The compilation unit element into which the elements being built will be
-   * stored.
-   */
-  final CompilationUnitElementImpl _unitElement;
-
-  /**
-   * The element holder associated with the element that is currently being built.
-   */
-  ElementHolder _currentHolder;
-
-  _BaseElementBuilder(this._currentHolder, this._unitElement);
-
-  /**
-   * If the [defaultValue] is not `null`, build the [FunctionElementImpl]
-   * that corresponds it, and set it as the initializer for the [parameter].
-   */
-  void buildParameterInitializer(
-      ParameterElementImpl parameter, Expression defaultValue) {
-    if (defaultValue != null) {
-      ElementHolder holder = new ElementHolder();
-      _visit(holder, defaultValue);
-      FunctionElementImpl initializer =
-          new FunctionElementImpl.forOffset(defaultValue.beginToken.offset);
-      initializer.hasImplicitReturnType = true;
-      initializer.encloseElements(holder.functions);
-      initializer.encloseElements(holder.labels);
-      initializer.encloseElements(holder.localVariables);
-      initializer.parameters = holder.parameters;
-      initializer.isSynthetic = true;
-      parameter.initializer = initializer;
-      parameter.defaultValueCode = defaultValue.toSource();
-      holder.validate();
-    }
-  }
-
-  /**
-   * If the [initializer] is not `null`, build the [FunctionElementImpl] that
-   * corresponds it, and set it as the initializer for the [variable].
-   */
-  void buildVariableInitializer(
-      VariableElementImpl variable, Expression initializer) {
-    if (initializer != null) {
-      ElementHolder holder = new ElementHolder();
-      _visit(holder, initializer);
-      FunctionElementImpl initializerElement =
-          new FunctionElementImpl.forOffset(initializer.beginToken.offset);
-      initializerElement.hasImplicitReturnType = true;
-      initializerElement.encloseElements(holder.functions);
-      initializerElement.encloseElements(holder.labels);
-      initializerElement.encloseElements(holder.localVariables);
-      initializerElement.isSynthetic = true;
-      variable.initializer = initializerElement;
-      holder.validate();
-    }
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    NormalFormalParameter normalParameter = node.parameter;
-    SimpleIdentifier parameterName = normalParameter.identifier;
-    ParameterElementImpl parameter;
-    if (normalParameter is FieldFormalParameter) {
-      DefaultFieldFormalParameterElementImpl fieldParameter =
-          new DefaultFieldFormalParameterElementImpl.forNode(parameterName);
-      _setFieldParameterField(node, fieldParameter);
-      parameter = fieldParameter;
-    } else {
-      parameter = new DefaultParameterElementImpl.forNode(parameterName);
-    }
-    _setCodeRange(parameter, node);
-    parameter.isConst = node.isConst;
-    parameter.isExplicitlyCovariant = node.parameter.covariantKeyword != null;
-    parameter.isFinal = node.isFinal;
-    // ignore: deprecated_member_use_from_same_package
-    parameter.parameterKind = node.kind;
-    // visible range
-    _setParameterVisibleRange(node, parameter);
-    if (normalParameter is SimpleFormalParameter &&
-        normalParameter.type == null) {
-      parameter.hasImplicitType = true;
-    }
-    _currentHolder.addParameter(parameter);
-    if (normalParameter is SimpleFormalParameterImpl) {
-      normalParameter.declaredElement = parameter;
-    }
-    parameterName?.staticElement = parameter;
-    normalParameter.accept(this);
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    if (node.parent is! DefaultFormalParameter) {
-      SimpleIdentifier parameterName = node.identifier;
-      FieldFormalParameterElementImpl parameter =
-          new FieldFormalParameterElementImpl.forNode(parameterName);
-      _setCodeRange(parameter, node);
-      _setFieldParameterField(node, parameter);
-      parameter.isConst = node.isConst;
-      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
-      parameter.isFinal = node.isFinal;
-      // ignore: deprecated_member_use_from_same_package
-      parameter.parameterKind = node.kind;
-      _currentHolder.addParameter(parameter);
-      parameterName.staticElement = parameter;
-    }
-    //
-    // The children of this parameter include any parameters defined on the type
-    // of this parameter.
-    //
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    ParameterElementImpl element = node.declaredElement;
-    element.metadata = _createElementAnnotations(node.metadata);
-    if (node.parameters != null) {
-      _createGenericFunctionType(element, holder);
-    }
-    holder.validate();
-  }
-
-  @override
-  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    if (node.parent is! DefaultFormalParameter) {
-      SimpleIdentifier parameterName = node.identifier;
-      ParameterElementImpl parameter =
-          new ParameterElementImpl.forNode(parameterName);
-      _setCodeRange(parameter, node);
-      parameter.isConst = node.isConst;
-      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
-      parameter.isFinal = node.isFinal;
-      // ignore: deprecated_member_use_from_same_package
-      parameter.parameterKind = node.kind;
-      _setParameterVisibleRange(node, parameter);
-      _currentHolder.addParameter(parameter);
-      parameterName.staticElement = parameter;
-    }
-    //
-    // The children of this parameter include any parameters defined on the type
-    //of this parameter.
-    //
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    ParameterElementImpl element = node.declaredElement;
-    element.metadata = _createElementAnnotations(node.metadata);
-    _createGenericFunctionType(element, holder);
-    holder.validate();
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    ElementHolder holder = new ElementHolder();
-    _visitChildren(holder, node);
-    GenericFunctionTypeElementImpl element =
-        new GenericFunctionTypeElementImpl.forOffset(node.beginToken.offset);
-    _setCodeRange(element, node);
-    element.parameters = holder.parameters;
-    element.typeParameters = holder.typeParameters;
-    FunctionType type = new FunctionTypeImpl(element);
-    element.type = type;
-    (node as GenericFunctionTypeImpl).type = type;
-    (node as GenericFunctionTypeImpl).declaredElement = element;
-    holder.validate();
-  }
-
-  @override
-  void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    ParameterElementImpl parameter;
-    if (node.parent is! DefaultFormalParameter) {
-      SimpleIdentifier parameterName = node.identifier;
-      parameter = new ParameterElementImpl.forNode(parameterName);
-      _setCodeRange(parameter, node);
-      parameter.isConst = node.isConst;
-      parameter.isExplicitlyCovariant = node.covariantKeyword != null;
-      parameter.isFinal = node.isFinal;
-      // ignore: deprecated_member_use_from_same_package
-      parameter.parameterKind = node.kind;
-      _setParameterVisibleRange(node, parameter);
-      if (node.type == null) {
-        parameter.hasImplicitType = true;
-      }
-      _currentHolder.addParameter(parameter);
-      (node as SimpleFormalParameterImpl).declaredElement = parameter;
-      parameterName?.staticElement = parameter;
-    }
-    super.visitSimpleFormalParameter(node);
-    parameter ??= node.declaredElement;
-    parameter?.metadata = _createElementAnnotations(node.metadata);
-  }
-
-  @override
-  void visitTypeParameter(TypeParameter node) {
-    SimpleIdentifier parameterName = node.name;
-    TypeParameterElementImpl typeParameter =
-        new TypeParameterElementImpl.forNode(parameterName);
-    _setCodeRange(typeParameter, node);
-    typeParameter.metadata = _createElementAnnotations(node.metadata);
-    _currentHolder.addTypeParameter(typeParameter);
-    parameterName.staticElement = typeParameter;
-    super.visitTypeParameter(node);
-  }
-
-  /**
-   * For each [Annotation] found in [annotations], create a new
-   * [ElementAnnotation] object and set the [Annotation] to point to it.
-   */
-  List<ElementAnnotation> _createElementAnnotations(
-      NodeList<Annotation> annotations) {
-    if (annotations.isEmpty) {
-      return const <ElementAnnotation>[];
-    }
-    return annotations.map((Annotation a) {
-      ElementAnnotationImpl elementAnnotation =
-          new ElementAnnotationImpl(_unitElement);
-      a.elementAnnotation = elementAnnotation;
-      return elementAnnotation;
-    }).toList();
-  }
-
-  /**
-   * If the [holder] has type parameters or formal parameters for the
-   * given [parameter], wrap them into a new [GenericFunctionTypeElementImpl]
-   * and set [FunctionTypeImpl] for the [parameter].
-   */
-  void _createGenericFunctionType(
-      ParameterElementImpl parameter, ElementHolder holder) {
-    var typeElement = new GenericFunctionTypeElementImpl.forOffset(-1);
-    typeElement.enclosingElement = parameter;
-    typeElement.typeParameters = holder.typeParameters;
-    typeElement.parameters = holder.parameters;
-    var type = new FunctionTypeImpl(typeElement);
-    typeElement.type = type;
-    parameter.type = type;
-  }
-
-  /**
-   * Return the body of the function that contains the given [parameter], or
-   * `null` if no function body could be found.
-   */
-  FunctionBody _getFunctionBody(FormalParameter parameter) {
-    AstNode parent = parameter?.parent?.parent;
-    if (parent is ConstructorDeclaration) {
-      return parent.body;
-    } else if (parent is FunctionExpression) {
-      return parent.body;
-    } else if (parent is MethodDeclaration) {
-      return parent.body;
-    }
-    return null;
-  }
-
-  void _setCodeRange(ElementImpl element, AstNode node) {
-    element.setCodeRange(node.offset, node.length);
-  }
-
-  void _setFieldParameterField(
-      FormalParameter node, FieldFormalParameterElementImpl element) {}
-
-  /**
-   * Sets the visible source range for formal parameter.
-   */
-  void _setParameterVisibleRange(
-      FormalParameter node, ParameterElementImpl element) {
-    FunctionBody body = _getFunctionBody(node);
-    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
-      element.setVisibleRange(body.offset, body.length);
-    }
-  }
-
-  void _setVariableDeclarationListAnnotations(VariableDeclarationList node,
-      List<ElementAnnotation> elementAnnotations) {
-    for (VariableDeclaration variableDeclaration in node.variables) {
-      ElementImpl element = variableDeclaration.declaredElement as ElementImpl;
-      element.metadata = elementAnnotations;
-    }
-  }
-
-  void _setVariableDeclarationListCodeRanges(VariableDeclarationList node) {
-    List<VariableDeclaration> variables = node.variables;
-    for (var i = 0; i < variables.length; i++) {
-      var variable = variables[i];
-      var offset = (i == 0 ? node.parent : variable).offset;
-      var length = variable.end - offset;
-      var element = variable.declaredElement as ElementImpl;
-      element.setCodeRange(offset, length);
-    }
-  }
-
-  /**
-   * Make the given holder be the current holder while visiting the given node.
-   *
-   * @param holder the holder that will gather elements that are built while visiting the children
-   * @param node the node to be visited
-   */
-  void _visit(ElementHolder holder, AstNode node) {
-    if (node != null) {
-      ElementHolder previousHolder = _currentHolder;
-      _currentHolder = holder;
-      try {
-        node.accept(this);
-      } finally {
-        _currentHolder = previousHolder;
-      }
-    }
-  }
-
-  /**
-   * Make the given holder be the current holder while visiting the children of the given node.
-   *
-   * @param holder the holder that will gather elements that are built while visiting the children
-   * @param node the node whose children are to be visited
-   */
-  void _visitChildren(ElementHolder holder, AstNode node) {
-    if (node != null) {
-      ElementHolder previousHolder = _currentHolder;
-      _currentHolder = holder;
-      try {
-        node.visitChildren(this);
-      } finally {
-        _currentHolder = previousHolder;
-      }
-    }
-  }
-}
-
-/**
- * Builds elements for all node that are not constructors or methods.
- */
-class _ClassNotExecutableElementsBuilder extends UnifyingAstVisitor<void> {
-  final ApiElementBuilder builder;
-  final List<ClassMember> nonFields;
-
-  _ClassNotExecutableElementsBuilder(this.builder, this.nonFields);
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    nonFields.add(node);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    nonFields.add(node);
-  }
-
-  @override
-  void visitNode(AstNode node) => node.accept(builder);
-}
-
-/**
- * Instances of the class [_NamespaceCombinatorBuilder] can be used to visit
- * [Combinator] AST nodes and generate [NamespaceCombinator] elements.
- */
-class _NamespaceCombinatorBuilder extends SimpleAstVisitor<void> {
-  /**
-   * Elements generated so far.
-   */
-  final List<NamespaceCombinator> combinators = <NamespaceCombinator>[];
-
-  @override
-  void visitHideCombinator(HideCombinator node) {
-    HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
-    hide.hiddenNames = _getIdentifiers(node.hiddenNames);
-    combinators.add(hide);
-  }
-
-  @override
-  void visitShowCombinator(ShowCombinator node) {
-    ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
-    show.offset = node.offset;
-    show.end = node.end;
-    show.shownNames = _getIdentifiers(node.shownNames);
-    combinators.add(show);
-  }
-
-  /**
-   * Return the lexical identifiers associated with the given [identifiers].
-   */
-  static List<String> _getIdentifiers(NodeList<SimpleIdentifier> identifiers) {
-    return identifiers.map((identifier) => identifier.name).toList();
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index d405d8a..7b75052 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
-import 'dart:math' show min;
 
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -13,7 +12,6 @@
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/constant/compute.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
@@ -131,17 +129,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitClassElement(this);
 
-  @deprecated
-  @override
-  NamedCompilationUnitMember computeNode() {
-    if (isEnum) {
-      return getNodeMatching((node) => node is EnumDeclaration);
-    } else {
-      return getNodeMatching(
-          (node) => node is ClassDeclaration || node is ClassTypeAlias);
-    }
-  }
-
   @override
   ElementImpl getChild(String identifier) {
     //
@@ -418,22 +405,13 @@
 
 /// For AST nodes that could be in both the getter and setter contexts
 /// ([IndexExpression]s and [SimpleIdentifier]s), the additional resolved
-/// elements are stored in the AST node, in an [AuxiliaryElements]. Because
-/// resolved elements are either statically resolved or resolved using
-/// propagated type information, this class is a wrapper for a pair of
-/// [ExecutableElement]s, not just a single [ExecutableElement].
+/// element (getter) is stored in the AST node, in an [AuxiliaryElements].
 class AuxiliaryElements {
   /// The element based on static type information, or `null` if the AST
   /// structure has not been resolved or if the node could not be resolved.
   final ExecutableElement staticElement;
 
-  /// Initialize a newly created pair to have both the [staticElement] and
-  /// `null`.
-  AuxiliaryElements(this.staticElement, ExecutableElement propagatedElement);
-
-  /// The element based on propagated type information, or `null` if the AST
-  /// structure has not been resolved or if the node could not be resolved.
-  ExecutableElement get propagatedElement => null;
+  AuxiliaryElements(this.staticElement);
 }
 
 /// An [AbstractClassElementImpl] which is a class.
@@ -466,11 +444,6 @@
   /// of this class have been inferred.
   bool _hasBeenInferred = false;
 
-  /// The version of this element. The version is changed when the element is
-  /// incrementally updated, so that its lists of constructors, accessors and
-  /// methods might be different.
-  int version = 0;
-
   /// This callback is set during mixins inference to handle reentrant calls.
   List<InterfaceType> Function(ClassElementImpl) linkedMixinInferenceCallback;
 
@@ -593,9 +566,6 @@
   }
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
-  @override
   List<FieldElement> get fields {
     if (_fields != null) return _fields;
 
@@ -898,11 +868,13 @@
   }
 
   @override
+  @deprecated
   InterfaceType get type {
     if (_type == null) {
-      InterfaceTypeImpl type = new InterfaceTypeImpl(this);
-      type.typeArguments = typeParameterTypes;
-      _type = type;
+      var typeArguments = typeParameters
+          .map((e) => e.instantiate(nullabilitySuffix: _noneOrStarSuffix))
+          .toList();
+      _type = InterfaceTypeImpl.explicit(this, typeArguments);
     }
     return _type;
   }
@@ -1014,18 +986,22 @@
   /// one (this is used to detect circularities).
   List<ConstructorElement> _computeMixinAppConstructors(
       [List<ClassElementImpl> visitedClasses]) {
-    // First get the list of constructors of the superclass which need to be
-    // forwarded to this class.
-    Iterable<ConstructorElement> constructorsToForward;
     if (supertype == null) {
       // Shouldn't ever happen, since the only classes with no supertype are
       // Object and mixins, and they aren't a mixin application. But for
       // safety's sake just assume an empty list.
       assert(false);
-      constructorsToForward = <ConstructorElement>[];
-    } else if (!supertype.element.isMixinApplication) {
+      return <ConstructorElement>[];
+    }
+
+    ClassElementImpl superElement = supertype.element;
+
+    // First get the list of constructors of the superclass which need to be
+    // forwarded to this class.
+    Iterable<ConstructorElement> constructorsToForward;
+    if (!superElement.isMixinApplication) {
       var library = this.library;
-      constructorsToForward = supertype.element.constructors
+      constructorsToForward = superElement.constructors
           .where((constructor) => constructor.isAccessibleIn(library));
     } else {
       if (visitedClasses == null) {
@@ -1039,7 +1015,6 @@
         visitedClasses.add(this);
       }
       try {
-        ClassElementImpl superElement = supertype.element;
         constructorsToForward =
             superElement._computeMixinAppConstructors(visitedClasses);
       } finally {
@@ -1051,9 +1026,9 @@
     // to produce constructors for this class.  We want to be robust in the
     // face of errors, so drop any extra type arguments and fill in any missing
     // ones with `dynamic`.
-    var superTypeParameters = supertype.typeParameters;
+    var superClassParameters = superElement.typeParameters;
     List<DartType> argumentTypes = new List<DartType>.filled(
-        superTypeParameters.length, DynamicTypeImpl.instance);
+        superClassParameters.length, DynamicTypeImpl.instance);
     for (int i = 0; i < supertype.typeArguments.length; i++) {
       if (i >= argumentTypes.length) {
         break;
@@ -1061,7 +1036,7 @@
       argumentTypes[i] = supertype.typeArguments[i];
     }
     var substitution =
-        Substitution.fromPairs(superTypeParameters, argumentTypes);
+        Substitution.fromPairs(superClassParameters, argumentTypes);
 
     // Now create an implicit constructor for every constructor found above,
     // substituting type parameters as appropriate.
@@ -1275,11 +1250,6 @@
   /// computed.
   Source librarySource;
 
-  /// A table mapping the offset of a directive to the annotations associated
-  /// with that directive, or `null` if none of the annotations in the
-  /// compilation unit have annotations.
-  Map<int, List<ElementAnnotation>> annotationMap;
-
   /// A list containing all of the top-level accessors (getters and setters)
   /// contained in this compilation unit.
   List<PropertyAccessorElement> _accessors;
@@ -1308,12 +1278,6 @@
   /// A list containing all of the variables contained in this compilation unit.
   List<TopLevelVariableElement> _variables;
 
-  /// Resynthesized explicit top-level property accessors.
-  UnitExplicitTopLevelAccessors _explicitTopLevelAccessors;
-
-  /// Resynthesized explicit top-level variables.
-  UnitExplicitTopLevelVariables _explicitTopLevelVariables;
-
   /// Initialize a newly created compilation unit element to have the given
   /// [name].
   CompilationUnitElementImpl()
@@ -1336,12 +1300,6 @@
       return _accessors;
     }
 
-    if (_explicitTopLevelAccessors != null) {
-      _accessors = <PropertyAccessorElementImpl>[]
-        ..addAll(_explicitTopLevelAccessors.accessors)
-        ..addAll(_explicitTopLevelVariables.implicitAccessors);
-    }
-
     return _accessors ?? const <PropertyAccessorElement>[];
   }
 
@@ -1647,20 +1605,6 @@
     }
   }
 
-  @deprecated
-  @override
-  CompilationUnit computeNode() => unit;
-
-  /// Return the annotations associated with the directive at the given
-  /// [offset], or an empty list if the directive has no annotations or if
-  /// there is no directive at the given offset.
-  List<ElementAnnotation> getAnnotations(int offset) {
-    if (annotationMap == null) {
-      return const <ElementAnnotation>[];
-    }
-    return annotationMap[offset] ?? const <ElementAnnotation>[];
-  }
-
   @override
   ElementImpl getChild(String identifier) {
     //
@@ -1718,22 +1662,12 @@
 
   @override
   ClassElement getType(String className) {
-    return getTypeFromTypes(className, types);
-  }
-
-  /// Replace the given [from] top-level variable with [to] in this compilation
-  /// unit.
-  void replaceTopLevelVariable(
-      TopLevelVariableElement from, TopLevelVariableElement to) {
-    int index = _variables.indexOf(from);
-    _variables[index] = to;
-  }
-
-  /// Set the annotations associated with the directive at the given [offset] to
-  /// the given list of [annotations].
-  void setAnnotations(int offset, List<ElementAnnotation> annotations) {
-    annotationMap ??= new HashMap<int, List<ElementAnnotation>>();
-    annotationMap[offset] = annotations;
+    for (ClassElement type in types) {
+      if (type.name == className) {
+        return type;
+      }
+    }
+    return null;
   }
 
   @override
@@ -1749,16 +1683,6 @@
     safelyVisitChildren(topLevelVariables, visitor);
   }
 
-  static ClassElement getTypeFromTypes(
-      String className, List<ClassElement> types) {
-    for (ClassElement type in types) {
-      if (type.name == className) {
-        return type;
-      }
-    }
-    return null;
-  }
-
   static void _createPropertiesAndAccessors(CompilationUnitElementImpl unit) {
     if (unit._variables != null) return;
     assert(unit._accessors == null);
@@ -2085,10 +2009,6 @@
   ClassElementImpl get enclosingElement =>
       super.enclosingElement as ClassElementImpl;
 
-  @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
-      super.enclosingElement as ClassElementImpl;
-
   /// Set whether this constructor represents a factory method.
   void set factory(bool isFactory) {
     setModifier(Modifier.FACTORY, isFactory);
@@ -2265,7 +2185,7 @@
       } else {
         message = 'Found unnamed constructor element with no enclosing element';
       }
-      AnalysisEngine.instance.logger.logError(message);
+      AnalysisEngine.instance.instrumentationService.logError(message);
       name = '<unknown class>';
     } else {
       name = enclosingElement.displayName;
@@ -2285,11 +2205,6 @@
           context.declaredVariables, [this], analysisOptions.experimentStatus);
     }
   }
-
-  @deprecated
-  @override
-  ConstructorDeclaration computeNode() =>
-      getNodeMatching((node) => node is ConstructorDeclaration);
 }
 
 /// A [TopLevelVariableElement] for a top-level 'const' variable that has an
@@ -2401,11 +2316,6 @@
 
   /// Initialize a newly created parameter element to have the given [name].
   DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
-
-  @deprecated
-  @override
-  DefaultFormalParameter computeNode() =>
-      getNodeMatching((node) => node is DefaultFormalParameter);
 }
 
 /// The synthetic element representing the declaration of the type `dynamic`.
@@ -2486,6 +2396,9 @@
   /// annotations.
   static String _NG_META_LIB_NAME = "angular.meta";
 
+  /// The name of the top-level variable used to mark a member as being nonVirtual.
+  static String _NON_VIRTUAL_VARIABLE_NAME = "nonVirtual";
+
   /// The name of the top-level variable used to mark a method as being expected
   /// to override an inherited method.
   static String _OVERRIDE_VARIABLE_NAME = "override";
@@ -2610,6 +2523,12 @@
       element.library?.name == _META_LIB_NAME;
 
   @override
+  bool get isNonVirtual =>
+      element is PropertyAccessorElement &&
+      element.name == _NON_VIRTUAL_VARIABLE_NAME &&
+      element.library?.name == _META_LIB_NAME;
+
+  @override
   bool get isOptionalTypeArgs =>
       element is PropertyAccessorElement &&
       element.name == _OPTIONAL_TYPE_ARGS_VARIABLE_NAME &&
@@ -2899,6 +2818,18 @@
   }
 
   @override
+  bool get hasNonVirtual {
+    var metadata = this.metadata;
+    for (var i = 0; i < metadata.length; i++) {
+      var annotation = metadata[i];
+      if (annotation.isNonVirtual) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
   bool get hasOptionalTypeArgs {
     var metadata = this.metadata;
     for (var i = 0; i < metadata.length; i++) {
@@ -2987,21 +2918,6 @@
   String get identifier => name;
 
   @override
-  bool get isAlwaysThrows => hasAlwaysThrows;
-
-  @override
-  bool get isDeprecated => hasDeprecated;
-
-  @override
-  bool get isFactory => hasFactory;
-
-  @override
-  bool get isJS => hasJS;
-
-  @override
-  bool get isOverride => hasOverride;
-
-  @override
   bool get isPrivate {
     String name = displayName;
     if (name == null) {
@@ -3011,15 +2927,9 @@
   }
 
   @override
-  bool get isProtected => hasProtected;
-
-  @override
   bool get isPublic => !isPrivate;
 
   @override
-  bool get isRequired => hasRequired;
-
-  @override
   bool get isSynthetic {
     if (linkedNode != null) {
       return linkedNode.isSynthetic;
@@ -3033,9 +2943,6 @@
   }
 
   @override
-  bool get isVisibleForTesting => hasVisibleForTesting;
-
-  @override
   LibraryElement get library =>
       getAncestor((element) => element is LibraryElement);
 
@@ -3110,12 +3017,6 @@
     return _enclosingElement?.typeParameterContext;
   }
 
-  @deprecated
-  @override
-  CompilationUnit get unit {
-    throw UnimplementedError();
-  }
-
   NullabilitySuffix get _noneOrStarSuffix {
     return library?.isNonNullableByDefault == true
         ? NullabilitySuffix.none
@@ -3132,25 +3033,6 @@
         object.location == location;
   }
 
-  /// Append to the given [buffer] a comma-separated list of the names of the
-  /// types of this element and every enclosing element.
-  void appendPathTo(StringBuffer buffer) {
-    Element element = this;
-    while (element != null) {
-      if (element != this) {
-        buffer.write(', ');
-      }
-      buffer.write(element.runtimeType);
-      String name = element.name;
-      if (name != null) {
-        buffer.write(' (');
-        buffer.write(name);
-        buffer.write(')');
-      }
-      element = element.enclosingElement;
-    }
-  }
-
   /// Append a textual representation of this element to the given [buffer].
   void appendTo(StringBuffer buffer) {
     if (_name == null) {
@@ -3162,13 +3044,6 @@
     }
   }
 
-  @override
-  String computeDocumentationComment() => documentationComment;
-
-  @deprecated
-  @override
-  AstNode computeNode() => getNodeMatching((node) => node is AstNode);
-
   /// Set this element as the enclosing element for given [element].
   void encloseElement(ElementImpl element) {
     element.enclosingElement = this;
@@ -3183,7 +3058,11 @@
 
   @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) {
-    return getAncestorStatic<E>(_enclosingElement, predicate);
+    var ancestor = _enclosingElement;
+    while (ancestor != null && !predicate(ancestor)) {
+      ancestor = ancestor.enclosingElement;
+    }
+    return ancestor as E;
   }
 
   /// Return the child of this element that is uniquely identified by the given
@@ -3202,21 +3081,6 @@
     return shortName;
   }
 
-  /// Return the resolved [AstNode] of the given type enclosing [getNameOffset].
-  @deprecated
-  AstNode getNodeMatching(Predicate<AstNode> predicate) {
-    CompilationUnit unit = this.unit;
-    if (unit == null) {
-      return null;
-    }
-    int offset = nameOffset;
-    AstNode node = new NodeLocator(offset).searchWithin(unit);
-    if (node == null) {
-      return null;
-    }
-    return node.thisOrAncestorMatching(predicate);
-  }
-
   /// Return `true` if this element has the given [modifier] associated with it.
   bool hasModifier(Modifier modifier) =>
       BooleanArray.get(_modifiers, modifier.ordinal);
@@ -3302,25 +3166,6 @@
       element.accept(visitor);
     }
   }
-
-  static int findElementIndexUsingIdentical(List items, Object item) {
-    int length = items.length;
-    for (int i = 0; i < length; i++) {
-      if (identical(items[i], item)) {
-        return i;
-      }
-    }
-    throw new StateError('Unable to find $item in $items');
-  }
-
-  static E getAncestorStatic<E extends Element>(
-      Element startingPoint, Predicate<Element> predicate) {
-    Element ancestor = startingPoint;
-    while (ancestor != null && !predicate(ancestor)) {
-      ancestor = ancestor.enclosingElement;
-    }
-    return ancestor as E;
-  }
 }
 
 /// A concrete implementation of an [ElementLocation].
@@ -3603,10 +3448,11 @@
   InterfaceType get supertype => context.typeProvider.objectType;
 
   @override
+  @deprecated
   InterfaceType get type {
     if (_type == null) {
-      InterfaceTypeImpl type = new InterfaceTypeImpl(this);
-      type.typeArguments = const <DartType>[];
+      var typeArguments = const <DartType>[];
+      InterfaceTypeImpl type = InterfaceTypeImpl.explicit(this, typeArguments);
       _type = type;
     }
     return _type;
@@ -3698,9 +3544,6 @@
   /// element.
   List<ParameterElement> _parameters;
 
-  /// The declared return type of this executable element.
-  DartType _declaredReturnType;
-
   /// The inferred return type of this executable element.
   DartType _returnType;
 
@@ -3741,10 +3584,6 @@
     return super.codeOffset;
   }
 
-  void set declaredReturnType(DartType returnType) {
-    _declaredReturnType = _checkElementOfType(returnType);
-  }
-
   @override
   String get displayName {
     if (linkedNode != null) {
@@ -3871,12 +3710,13 @@
 
   @override
   DartType get returnType {
+    if (_returnType != null) return _returnType;
+
     if (linkedNode != null) {
-      if (_returnType != null) return _returnType;
       var context = enclosingUnit.linkedContext;
       return _returnType = context.getReturnType(linkedNode);
     }
-    return _returnType ?? _declaredReturnType;
+    return _returnType;
   }
 
   void set returnType(DartType returnType) {
@@ -4192,9 +4032,6 @@
   }
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
-  @override
   DartType get extendedType {
     if (_extendedType != null) return _extendedType;
 
@@ -4525,25 +4362,11 @@
     setModifier(Modifier.STATIC, isStatic);
   }
 
-  @deprecated
-  @override
-  bool get isVirtual => true;
-
   @override
   ElementKind get kind => ElementKind.FIELD;
 
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitFieldElement(this);
-
-  @deprecated
-  @override
-  AstNode computeNode() {
-    if (isEnumConstant) {
-      return getNodeMatching((node) => node is EnumConstantDeclaration);
-    } else {
-      return getNodeMatching((node) => node is VariableDeclaration);
-    }
-  }
 }
 
 /// A [ParameterElementImpl] that has the additional information of the
@@ -4609,13 +4432,6 @@
 /// A concrete implementation of a [FunctionElement].
 class FunctionElementImpl extends ExecutableElementImpl
     implements FunctionElement, FunctionTypedElementImpl {
-  /// The offset to the beginning of the visible range for this element.
-  int _visibleRangeOffset = 0;
-
-  /// The length of the visible range for this element, or `-1` if this element
-  /// does not have a visible range.
-  int _visibleRangeLength = -1;
-
   /// Initialize a newly created function element to have the given [name] and
   /// [offset].
   FunctionElementImpl(String name, int offset) : super(name, offset);
@@ -4650,11 +4466,6 @@
   }
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext {
-    return (enclosingElement as ElementImpl).typeParameterContext;
-  }
-
-  @override
   String get identifier {
     String identifier = super.identifier;
     Element enclosing = this.enclosingElement;
@@ -4684,63 +4495,7 @@
   }
 
   @override
-  SourceRange get visibleRange {
-    if (_visibleRangeLength < 0) {
-      return null;
-    }
-    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
-  }
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitFunctionElement(this);
-
-  @deprecated
-  @override
-  FunctionDeclaration computeNode() =>
-      getNodeMatching((node) => node is FunctionDeclaration);
-
-  /// Set the visible range for this element to the range starting at the given
-  /// [offset] with the given [length].
-  void setVisibleRange(int offset, int length) {
-    _visibleRangeOffset = offset;
-    _visibleRangeLength = length;
-  }
-
-  /// Set the parameters defined by this type alias to the given [parameters]
-  /// without becoming the parent of the parameters. This should only be used by
-  /// the [TypeResolverVisitor] when creating a synthetic type alias.
-  void shareParameters(List<ParameterElement> parameters) {
-    this._parameters = parameters;
-  }
-
-  /// Set the type parameters defined by this type alias to the given
-  /// [parameters] without becoming the parent of the parameters. This should
-  /// only be used by the [TypeResolverVisitor] when creating a synthetic type
-  /// alias.
-  void shareTypeParameters(List<TypeParameterElement> typeParameters) {
-    this._typeParameterElements = typeParameters;
-  }
-}
-
-/// Implementation of [FunctionElementImpl] for a function typed parameter.
-class FunctionElementImpl_forFunctionTypedParameter
-    extends FunctionElementImpl {
-  @override
-  final CompilationUnitElementImpl enclosingUnit;
-
-  /// The enclosing function typed [ParameterElementImpl].
-  final ParameterElementImpl _parameter;
-
-  FunctionElementImpl_forFunctionTypedParameter(
-      this.enclosingUnit, this._parameter)
-      : super('', -1);
-
-  @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
-      _parameter.typeParameterContext;
-
-  @override
-  bool get isSynthetic => true;
 }
 
 /// Common internal interface shared by elements whose type is a function type.
@@ -4776,11 +4531,6 @@
       : super("", nameOffset);
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext {
-    return _enclosingElement.typeParameterContext;
-  }
-
-  @override
   String get identifier => '-';
 
   @override
@@ -4972,9 +4722,6 @@
       super.enclosingElement as CompilationUnitElement;
 
   @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
-  @override
   CompilationUnitElementImpl get enclosingUnit =>
       _enclosingElement as CompilationUnitElementImpl;
 
@@ -4992,7 +4739,10 @@
           encloseElement(_function);
           return _function;
         } else {
-          return null;
+          return _function = GenericFunctionTypeElementImpl.forOffset(-1)
+            ..typeParameters = const <TypeParameterElement>[]
+            ..parameters = const <ParameterElement>[]
+            ..returnType = DynamicTypeImpl.instance;
         }
       } else {
         return _function = GenericFunctionTypeElementImpl.forLinkedNode(
@@ -5015,6 +4765,8 @@
     _function = function;
   }
 
+  /// Return `true` if the element has direct or indirect reference to itself
+  /// from anywhere except a class element or type parameter bounds.
   bool get hasSelfReference {
     if (linkedNode != null) {
       return linkedContext.getHasTypedefSelfReference(linkedNode);
@@ -5064,17 +4816,19 @@
   }
 
   @override
+  @deprecated
   FunctionType get type {
     _type ??= FunctionTypeImpl.synthetic(
-      returnType,
+      function.returnType,
       typeParameters,
-      parameters,
+      function.parameters,
       element: this,
       typeArguments: typeParameters.map((e) {
         return e.instantiate(
           nullabilitySuffix: NullabilitySuffix.star,
         );
       }).toList(),
+      nullabilitySuffix: NullabilitySuffix.star,
     );
     return _type;
   }
@@ -5118,11 +4872,6 @@
     }
   }
 
-  @deprecated
-  @override
-  GenericTypeAlias computeNode() =>
-      getNodeMatching((node) => node is GenericTypeAlias);
-
   @override
   ElementImpl getChild(String identifier) {
     for (TypeParameterElement typeParameter in typeParameters) {
@@ -5135,15 +4884,7 @@
   }
 
   @override
-  FunctionType instantiate(List<DartType> argumentTypes) {
-    return instantiate2(
-      typeArguments: argumentTypes,
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-  }
-
-  @override
-  FunctionType instantiate2({
+  FunctionType instantiate({
     @required List<DartType> typeArguments,
     @required NullabilitySuffix nullabilitySuffix,
   }) {
@@ -5170,6 +4911,18 @@
   }
 
   @override
+  @deprecated
+  FunctionType instantiate2({
+    @required List<DartType> typeArguments,
+    @required NullabilitySuffix nullabilitySuffix,
+  }) {
+    return instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: nullabilitySuffix,
+    );
+  }
+
+  @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
     safelyVisitChildren(typeParameters, visitor);
@@ -5489,13 +5242,6 @@
   /// library.
   List<ExportElement> _exports;
 
-  /// A list containing the strongly connected component in the import/export
-  /// graph in which the current library resides.  Computed on demand, null
-  /// if not present.  If _libraryCycle is set, then the _libraryCycle field
-  /// for all libraries reachable from this library in the import/export graph
-  /// is also set.
-  List<LibraryElement> _libraryCycle;
-
   /// A list containing all of the compilation units that are included in this
   /// library using a `part` directive.
   List<CompilationUnitElement> _parts = const <CompilationUnitElement>[];
@@ -5816,82 +5562,6 @@
   LibraryElement get library => this;
 
   @override
-  List<LibraryElement> get libraryCycle {
-    if (_libraryCycle != null) {
-      return _libraryCycle;
-    }
-
-    // Global counter for this run of the algorithm
-    int counter = 0;
-    // The discovery times of each library
-    Map<LibraryElementImpl, int> indices = {};
-    // The set of scc candidates
-    Set<LibraryElementImpl> active = new Set();
-    // The stack of discovered elements
-    List<LibraryElementImpl> stack = [];
-    // For a given library that has not yet been processed by this run of the
-    // algorithm, compute the strongly connected components.
-    int scc(LibraryElementImpl library) {
-      int index = counter++;
-      int root = index;
-      indices[library] = index;
-      active.add(library);
-      stack.add(library);
-      LibraryElementImpl getActualLibrary(LibraryElement lib) {
-        // TODO(paulberry): this means that computing a library cycle will be
-        // expensive for libraries resynthesized from summaries, since it will
-        // require fully resynthesizing all the libraries in the cycle as well
-        // as any libraries they import or export.  Try to find a better way.
-        return lib;
-      }
-
-      void recurse(LibraryElementImpl child) {
-        if (!indices.containsKey(child)) {
-          // We haven't visited this child yet, so recurse on the child,
-          // returning the lowest numbered node reachable from the child.  If
-          // the child can reach a root which is lower numbered than anything
-          // we've reached so far, update the root.
-          root = min(root, scc(child));
-        } else if (active.contains(child)) {
-          // The child has been visited, but has not yet been placed into a
-          // component.  If the child is higher than anything we've seen so far
-          // update the root appropriately.
-          root = min(root, indices[child]);
-        }
-      }
-
-      // Recurse on all of the children in the import/export graph, filtering
-      // out those for which library cycles have already been computed.
-      library.exportedLibraries
-          .map(getActualLibrary)
-          .where((l) => l._libraryCycle == null)
-          .forEach(recurse);
-      library.importedLibraries
-          .map(getActualLibrary)
-          .where((l) => l._libraryCycle == null)
-          .forEach(recurse);
-
-      if (root == index) {
-        // This is the root of a strongly connected component.
-        // Pop the elements, and share the component across all
-        // of the elements.
-        List<LibraryElement> component = <LibraryElement>[];
-        LibraryElementImpl cur;
-        do {
-          cur = stack.removeLast();
-          active.remove(cur);
-          component.add(cur);
-          cur._libraryCycle = component;
-        } while (cur != library);
-      }
-      return root;
-    }
-
-    scc(library);
-    return _libraryCycle;
-  }
-
-  @override
   FunctionElement get loadLibraryFunction {
     assert(_loadLibraryFunction != null);
     return _loadLibraryFunction;
@@ -5956,6 +5626,7 @@
     for (var unit in units) {
       yield* unit.accessors;
       yield* unit.enums;
+      yield* unit.extensions;
       yield* unit.functionTypeAliases;
       yield* unit.functions;
       yield* unit.mixins;
@@ -6119,43 +5790,9 @@
   constantExpressions,
 }
 
-/// The context in which the library is resynthesized.
-abstract class LibraryResynthesizerContext {
-  /// Return the [LinkedLibrary] that corresponds to the library being
-  /// resynthesized.
-  LinkedLibrary get linkedLibrary;
-
-  /// Return the exported [LibraryElement] for with the given [relativeUri].
-  LibraryElement buildExportedLibrary(String relativeUri);
-
-  /// Return the export namespace of the library.
-  Namespace buildExportNamespace();
-
-  /// Return the imported [LibraryElement] for the given dependency in the
-  /// linked library.
-  LibraryElement buildImportedLibrary(int dependency);
-
-  /// Return the public namespace of the library.
-  Namespace buildPublicNamespace();
-
-  /// Find the entry point of the library.
-  FunctionElement findEntryPoint();
-
-  /// Ensure that getters and setters in different units use the same
-  /// top-level variables.
-  void patchTopLevelAccessors();
-}
-
 /// A concrete implementation of a [LocalVariableElement].
 class LocalVariableElementImpl extends NonParameterVariableElementImpl
     implements LocalVariableElement {
-  /// The offset to the beginning of the visible range for this element.
-  int _visibleRangeOffset = 0;
-
-  /// The length of the visible range for this element, or `-1` if this element
-  /// does not have a visible range.
-  int _visibleRangeLength = -1;
-
   /// Initialize a newly created method element to have the given [name] and
   /// [offset].
   LocalVariableElementImpl(String name, int offset) : super(name, offset);
@@ -6180,23 +5817,9 @@
   }
 
   @override
-  bool get isPotentiallyMutatedInClosure => true;
-
-  @override
-  bool get isPotentiallyMutatedInScope => true;
-
-  @override
   ElementKind get kind => ElementKind.LOCAL_VARIABLE;
 
   @override
-  SourceRange get visibleRange {
-    if (_visibleRangeLength < 0) {
-      return null;
-    }
-    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
-  }
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitLocalVariableElement(this);
 
@@ -6206,18 +5829,6 @@
     buffer.write(" ");
     buffer.write(displayName);
   }
-
-  @deprecated
-  @override
-  Declaration computeNode() => getNodeMatching(
-      (node) => node is DeclaredIdentifier || node is VariableDeclaration);
-
-  /// Set the visible range for this element to the range starting at the given
-  /// [offset] with the given [length].
-  void setVisibleRange(int offset, int length) {
-    _visibleRangeOffset = offset;
-    _visibleRangeLength = length;
-  }
 }
 
 /// A concrete implementation of a [MethodElement].
@@ -6242,10 +5853,6 @@
     return displayName;
   }
 
-  @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext =>
-      super.enclosingElement as TypeParameterizedElementMixin;
-
   /// Set whether this class is abstract.
   void set isAbstract(bool isAbstract) {
     setModifier(Modifier.ABSTRACT, isAbstract);
@@ -6291,11 +5898,6 @@
 
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
-
-  @deprecated
-  @override
-  MethodDeclaration computeNode() =>
-      getNodeMatching((node) => node is MethodDeclaration);
 }
 
 /// A [ClassElementImpl] representing a mixin declaration.
@@ -6587,6 +6189,9 @@
   bool get hasMustCallSuper => false;
 
   @override
+  bool get hasNonVirtual => false;
+
+  @override
   bool get hasOptionalTypeArgs => false;
 
   @override
@@ -6608,21 +6213,6 @@
   bool get hasVisibleForTesting => false;
 
   @override
-  bool get isAlwaysThrows => false;
-
-  @override
-  bool get isDeprecated => false;
-
-  @override
-  bool get isFactory => false;
-
-  @override
-  bool get isJS => false;
-
-  @override
-  bool get isOverride => false;
-
-  @override
   bool get isPrivate {
     String name = displayName;
     if (name == null) {
@@ -6632,23 +6222,14 @@
   }
 
   @override
-  bool get isProtected => false;
-
-  @override
   bool get isPublic => !isPrivate;
 
   @override
-  bool get isRequired => false;
-
-  @override
   bool get isSynthetic => true;
 
   bool get isVisibleForTemplate => false;
 
   @override
-  bool get isVisibleForTesting => false;
-
-  @override
   ElementKind get kind => ElementKind.ERROR;
 
   @override
@@ -6676,20 +6257,10 @@
   DartType get type => DynamicTypeImpl.instance;
 
   @override
-  CompilationUnit get unit => null;
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitMultiplyDefinedElement(this);
 
   @override
-  String computeDocumentationComment() => null;
-
-  @deprecated
-  @override
-  AstNode computeNode() => null;
-
-  @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) => null;
 
   @override
@@ -6741,51 +6312,6 @@
   }
 }
 
-/// A [MethodElementImpl], with the additional information of a list of
-/// [ExecutableElement]s from which this element was composed.
-class MultiplyInheritedMethodElementImpl extends MethodElementImpl
-    implements MultiplyInheritedExecutableElement {
-  /// A list the array of executable elements that were used to compose this
-  /// element.
-  List<ExecutableElement> _elements = const <MethodElement>[];
-
-  MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
-    isSynthetic = true;
-  }
-
-  @override
-  List<ExecutableElement> get inheritedElements => _elements;
-
-  void set inheritedElements(List<ExecutableElement> elements) {
-    this._elements = elements;
-  }
-}
-
-/// A [PropertyAccessorElementImpl], with the additional information of a list
-///  of[ExecutableElement]s from which this element was composed.
-class MultiplyInheritedPropertyAccessorElementImpl
-    extends PropertyAccessorElementImpl
-    implements MultiplyInheritedExecutableElement {
-  /// A list the array of executable elements that were used to compose this
-  /// element.
-  List<ExecutableElement> _elements = const <PropertyAccessorElement>[];
-
-  MultiplyInheritedPropertyAccessorElementImpl(Identifier name)
-      : super.forNode(name) {
-    isSynthetic = true;
-  }
-
-  @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext => null;
-
-  @override
-  List<ExecutableElement> get inheritedElements => _elements;
-
-  void set inheritedElements(List<ExecutableElement> elements) {
-    this._elements = elements;
-  }
-}
-
 /// The synthetic element representing the declaration of the type `Never`.
 class NeverElementImpl extends ElementImpl implements TypeDefiningElement {
   /// Return the unique instance of this class.
@@ -6887,7 +6413,8 @@
         if (linkedContext.hasInitializer(linkedNode)) {
           _initializer = new FunctionElementImpl('', -1)
             ..isSynthetic = true
-            .._type = FunctionTypeImpl.synthetic(type, [], [])
+            .._type = FunctionTypeImpl.synthetic(type, [], [],
+                nullabilitySuffix: NullabilitySuffix.star)
             ..enclosingElement = this;
         }
       }
@@ -6951,13 +6478,6 @@
   /// The Dart code of the default value.
   String _defaultValueCode;
 
-  /// The offset to the beginning of the visible range for this element.
-  int _visibleRangeOffset = 0;
-
-  /// The length of the visible range for this element, or `-1` if this element
-  /// does not have a visible range.
-  int _visibleRangeLength = -1;
-
   bool _inheritsCovariant = false;
 
   /// Initialize a newly created parameter element to have the given [name] and
@@ -7118,12 +6638,6 @@
   bool get isLate => false;
 
   @override
-  bool get isPotentiallyMutatedInClosure => true;
-
-  @override
-  bool get isPotentiallyMutatedInScope => true;
-
-  @override
   ElementKind get kind => ElementKind.PARAMETER;
 
   @override
@@ -7244,14 +6758,6 @@
   }
 
   @override
-  SourceRange get visibleRange {
-    if (_visibleRangeLength < 0) {
-      return null;
-    }
-    return new SourceRange(_visibleRangeOffset, _visibleRangeLength);
-  }
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitParameterElement(this);
 
   @override
@@ -7272,18 +6778,6 @@
     }
   }
 
-  @deprecated
-  @override
-  FormalParameter computeNode() =>
-      getNodeMatching((node) => node is FormalParameter);
-
-  /// Set the visible range for this element to the range starting at the given
-  /// [offset] with the given [length].
-  void setVisibleRange(int offset, int length) {
-    _visibleRangeOffset = offset;
-    _visibleRangeLength = length;
-  }
-
   @override
   void visitChildren(ElementVisitor visitor) {
     super.visitChildren(visitor);
@@ -7476,9 +6970,6 @@
       super.enclosingElement as LibraryElement;
 
   @override
-  List<LibraryElement> get importedLibraries => const <LibraryElement>[];
-
-  @override
   ElementKind get kind => ElementKind.PREFIX;
 
   @override
@@ -7551,11 +7042,6 @@
     return variable.setter;
   }
 
-  @override
-  TypeParameterizedElementMixin get enclosingTypeParameterContext {
-    return (enclosingElement as ElementImpl).typeParameterContext;
-  }
-
   /// Set whether this accessor is a getter.
   void set getter(bool isGetter) {
     setModifier(Modifier.GETTER, isGetter);
@@ -7639,20 +7125,6 @@
     super.appendToWithName(
         buffer, (isGetter ? 'get ' : 'set ') + variable.displayName);
   }
-
-  @deprecated
-  @override
-  AstNode computeNode() {
-    if (isSynthetic) {
-      return null;
-    }
-    if (enclosingElement is ClassElement) {
-      return getNodeMatching((node) => node is MethodDeclaration);
-    } else if (enclosingElement is CompilationUnitElement) {
-      return getNodeMatching((node) => node is FunctionDeclaration);
-    }
-    return null;
-  }
 }
 
 /// Implicit getter for a [PropertyInducingElementImpl].
@@ -7802,13 +7274,6 @@
     return hasModifier(Modifier.LATE);
   }
 
-  @deprecated
-  @override
-  DartType get propagatedType => null;
-
-  @deprecated
-  void set propagatedType(DartType propagatedType) {}
-
   @override
   DartType get type {
     if (linkedNode != null) {
@@ -7963,11 +7428,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitTopLevelVariableElement(this);
-
-  @deprecated
-  @override
-  VariableDeclaration computeNode() =>
-      getNodeMatching((node) => node is VariableDeclaration);
 }
 
 /// A concrete implementation of a [TypeParameterElement].
@@ -8074,6 +7534,8 @@
     return super.nameOffset;
   }
 
+  @override
+  @deprecated
   TypeParameterType get type {
     // Note: TypeParameterElement.type has nullability suffix `star` regardless
     // of whether it appears in a migrated library.  This is because for type
@@ -8087,6 +7549,14 @@
   }
 
   @override
+  bool operator ==(Object object) {
+    if (identical(this, object)) {
+      return true;
+    }
+    return object is TypeParameterElementImpl && object.location == location;
+  }
+
+  @override
   T accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitTypeParameterElement(this);
 
@@ -8109,29 +7579,16 @@
 
 /// Mixin representing an element which can have type parameters.
 mixin TypeParameterizedElementMixin
-    implements
-        TypeParameterizedElement,
-        ElementImpl,
-        TypeParameterSerializationContext {
+    implements TypeParameterizedElement, ElementImpl {
   /// A cached list containing the type parameters declared by this element
   /// directly, or `null` if the elements have not been created yet. This does
   /// not include type parameters that are declared by any enclosing elements.
   List<TypeParameterElement> _typeParameterElements;
 
-  /// A cached list containing the type parameter types declared by this element
-  /// directly, or `null` if the list has not been computed yet.
-  List<TypeParameterType> _typeParameterTypes;
-
-  /// Get the type parameter context enclosing this one, if any.
-  TypeParameterizedElementMixin get enclosingTypeParameterContext;
-
   @override
   bool get isSimplyBounded => true;
 
   @override
-  TypeParameterizedElementMixin get typeParameterContext => this;
-
-  @override
   List<TypeParameterElement> get typeParameters {
     if (_typeParameterElements != null) return _typeParameterElements;
 
@@ -8153,77 +7610,6 @@
 
     return _typeParameterElements ?? const <TypeParameterElement>[];
   }
-
-  /// Get a list of [TypeParameterType] objects corresponding to the
-  /// element's type parameters.
-  List<TypeParameterType> get typeParameterTypes {
-    return _typeParameterTypes ??= typeParameters
-        .map((TypeParameterElement e) =>
-            e.instantiate(nullabilitySuffix: NullabilitySuffix.star))
-        .toList(growable: false);
-  }
-
-  @override
-  int computeDeBruijnIndex(TypeParameterElement typeParameter,
-      {int offset = 0}) {
-    if (typeParameter.enclosingElement == this) {
-      var index = typeParameters.indexOf(typeParameter);
-      assert(index >= 0);
-      return typeParameters.length - index + offset;
-    } else if (enclosingTypeParameterContext != null) {
-      return enclosingTypeParameterContext.computeDeBruijnIndex(typeParameter,
-          offset: offset + typeParameters.length);
-    } else {
-      return null;
-    }
-  }
-
-  /// Convert the given [index] into a type parameter type.
-  TypeParameterType getTypeParameterType(int index) {
-    List<TypeParameterType> types = typeParameterTypes;
-    if (index <= types.length) {
-      return types[types.length - index];
-    } else if (enclosingTypeParameterContext != null) {
-      return enclosingTypeParameterContext
-          .getTypeParameterType(index - types.length);
-    } else {
-      // If we get here, it means that a summary contained a type parameter
-      // index that was out of range.
-      throw new RangeError('Invalid type parameter index');
-    }
-  }
-}
-
-/// Interface used by linker serialization methods to convert type parameter
-/// references into De Bruijn indices.
-abstract class TypeParameterSerializationContext {
-  /// Return the given [typeParameter]'s de Bruijn index in this context, or
-  /// `null` if it's not in scope.
-  ///
-  /// If an [offset] is provided, then it is added to the computed index.
-  int computeDeBruijnIndex(TypeParameterElement typeParameter, {int offset: 0});
-}
-
-/// Container with information about explicit top-level property accessors and
-/// corresponding implicit top-level variables.
-class UnitExplicitTopLevelAccessors {
-  final List<PropertyAccessorElementImpl> accessors =
-      <PropertyAccessorElementImpl>[];
-  final List<TopLevelVariableElementImpl> implicitVariables =
-      <TopLevelVariableElementImpl>[];
-}
-
-/// Container with information about explicit top-level variables and
-/// corresponding implicit top-level property accessors.
-class UnitExplicitTopLevelVariables {
-  final List<TopLevelVariableElementImpl> variables;
-  final List<PropertyAccessorElementImpl> implicitAccessors =
-      <PropertyAccessorElementImpl>[];
-
-  UnitExplicitTopLevelVariables(int numberOfVariables)
-      : variables = numberOfVariables != 0
-            ? new List<TopLevelVariableElementImpl>(numberOfVariables)
-            : const <TopLevelVariableElementImpl>[];
 }
 
 /// A concrete implementation of a [UriReferencedElement].
@@ -8282,10 +7668,7 @@
 /// A concrete implementation of a [VariableElement].
 abstract class VariableElementImpl extends ElementImpl
     implements VariableElement {
-  /// The declared type of this variable.
-  DartType _declaredType;
-
-  /// The inferred type of this variable.
+  /// The type of this variable.
   DartType _type;
 
   /// A synthetic function representing this variable's initializer, or `null
@@ -8319,10 +7702,6 @@
   @override
   DartObject get constantValue => evaluationResult?.value;
 
-  void set declaredType(DartType type) {
-    _declaredType = _checkElementOfType(type);
-  }
-
   @override
   String get displayName => name;
 
@@ -8391,16 +7770,10 @@
   }
 
   @override
-  bool get isPotentiallyMutatedInClosure => false;
-
-  @override
-  bool get isPotentiallyMutatedInScope => false;
-
-  @override
   bool get isStatic => hasModifier(Modifier.STATIC);
 
   @override
-  DartType get type => _type ?? _declaredType;
+  DartType get type => _type;
 
   void set type(DartType type) {
     if (linkedNode != null) {
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
deleted file mode 100644
index 8b626ea..0000000
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ /dev/null
@@ -1,1345 +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:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/constant/value.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/element.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:meta/meta.dart';
-
-/**
- * A handle to a [ClassElement].
- */
-class ClassElementHandle extends ElementHandle implements ClassElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ClassElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  List<PropertyAccessorElement> get accessors => actualElement.accessors;
-
-  @override
-  ClassElement get actualElement => super.actualElement as ClassElement;
-
-  @override
-  List<InterfaceType> get allSupertypes => actualElement.allSupertypes;
-
-  @override
-  List<ConstructorElement> get constructors => actualElement.constructors;
-
-  @override
-  List<FieldElement> get fields => actualElement.fields;
-
-  @override
-  bool get hasJS => actualElement.hasJS;
-
-  @override
-  bool get hasLiteral => actualElement.hasLiteral;
-
-  @override
-  bool get hasNonFinalField => actualElement.hasNonFinalField;
-
-  @override
-  bool get hasReferenceToSuper => actualElement.hasReferenceToSuper;
-
-  @override
-  bool get hasRequired => actualElement.hasRequired;
-
-  @override
-  bool get hasSealed => actualElement.hasSealed;
-
-  @override
-  bool get hasStaticMember => actualElement.hasStaticMember;
-
-  @override
-  List<InterfaceType> get interfaces => actualElement.interfaces;
-
-  @override
-  bool get isAbstract => actualElement.isAbstract;
-
-  @override
-  bool get isDartCoreObject => actualElement.isDartCoreObject;
-
-  @override
-  bool get isEnum => actualElement.isEnum;
-
-  @override
-  bool get isJS => actualElement.hasJS;
-
-  @override
-  bool get isMixin => actualElement.isMixin;
-
-  @override
-  bool get isMixinApplication => actualElement.isMixinApplication;
-
-  @override
-  bool get isOrInheritsProxy => actualElement.isOrInheritsProxy;
-
-  @override
-  bool get isProxy => actualElement.isProxy;
-
-  @override
-  bool get isRequired => actualElement.hasRequired;
-
-  @override
-  bool get isSimplyBounded => actualElement.isSimplyBounded;
-
-  @override
-  bool get isValidMixin => actualElement.isValidMixin;
-
-  @override
-  ElementKind get kind => ElementKind.CLASS;
-
-  @override
-  List<MethodElement> get methods => actualElement.methods;
-
-  @override
-  List<InterfaceType> get mixins => actualElement.mixins;
-
-  @override
-  List<InterfaceType> get superclassConstraints =>
-      actualElement.superclassConstraints;
-
-  @override
-  InterfaceType get supertype => actualElement.supertype;
-
-  @override
-  InterfaceType get thisType => actualElement.thisType;
-
-  @override
-  InterfaceType get type => actualElement.type;
-
-  @override
-  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
-
-  @override
-  ConstructorElement get unnamedConstructor => actualElement.unnamedConstructor;
-
-  @deprecated
-  @override
-  NamedCompilationUnitMember computeNode() => super.computeNode();
-
-  @override
-  FieldElement getField(String fieldName) => actualElement.getField(fieldName);
-
-  @override
-  PropertyAccessorElement getGetter(String getterName) =>
-      actualElement.getGetter(getterName);
-
-  @override
-  MethodElement getMethod(String methodName) =>
-      actualElement.getMethod(methodName);
-
-  @override
-  ConstructorElement getNamedConstructor(String name) =>
-      actualElement.getNamedConstructor(name);
-
-  @override
-  PropertyAccessorElement getSetter(String setterName) =>
-      actualElement.getSetter(setterName);
-
-  @override
-  InterfaceType instantiate({
-    @required List<DartType> typeArguments,
-    @required NullabilitySuffix nullabilitySuffix,
-  }) {
-    return actualElement.instantiate(
-      typeArguments: typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-
-  @override
-  MethodElement lookUpConcreteMethod(
-          String methodName, LibraryElement library) =>
-      actualElement.lookUpConcreteMethod(methodName, library);
-
-  @override
-  PropertyAccessorElement lookUpGetter(
-          String getterName, LibraryElement library) =>
-      actualElement.lookUpGetter(getterName, library);
-
-  @override
-  PropertyAccessorElement lookUpInheritedConcreteGetter(
-          String methodName, LibraryElement library) =>
-      actualElement.lookUpInheritedConcreteGetter(methodName, library);
-
-  @override
-  MethodElement lookUpInheritedConcreteMethod(
-          String methodName, LibraryElement library) =>
-      actualElement.lookUpInheritedConcreteMethod(methodName, library);
-
-  @override
-  PropertyAccessorElement lookUpInheritedConcreteSetter(
-          String methodName, LibraryElement library) =>
-      actualElement.lookUpInheritedConcreteSetter(methodName, library);
-
-  @override
-  MethodElement lookUpInheritedMethod(
-      String methodName, LibraryElement library) {
-    return actualElement.lookUpInheritedMethod(methodName, library);
-  }
-
-  @override
-  MethodElement lookUpMethod(String methodName, LibraryElement library) =>
-      actualElement.lookUpMethod(methodName, library);
-
-  @override
-  PropertyAccessorElement lookUpSetter(
-          String setterName, LibraryElement library) =>
-      actualElement.lookUpSetter(setterName, library);
-}
-
-/**
- * A handle to a [CompilationUnitElement].
- */
-class CompilationUnitElementHandle extends ElementHandle
-    implements CompilationUnitElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  CompilationUnitElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  List<PropertyAccessorElement> get accessors => actualElement.accessors;
-
-  @override
-  CompilationUnitElement get actualElement =>
-      super.actualElement as CompilationUnitElement;
-
-  @override
-  LibraryElement get enclosingElement =>
-      super.enclosingElement as LibraryElement;
-
-  @override
-  List<ClassElement> get enums => actualElement.enums;
-
-  @override
-  List<ExtensionElement> get extensions => actualElement.extensions;
-
-  @override
-  List<FunctionElement> get functions => actualElement.functions;
-
-  @override
-  List<FunctionTypeAliasElement> get functionTypeAliases =>
-      actualElement.functionTypeAliases;
-
-  @override
-  bool get hasLoadLibraryFunction => actualElement.hasLoadLibraryFunction;
-
-  @override
-  ElementKind get kind => ElementKind.COMPILATION_UNIT;
-
-  @override
-  LineInfo get lineInfo => actualElement.lineInfo;
-
-  @override
-  List<ClassElement> get mixins => actualElement.mixins;
-
-  @override
-  Source get source => actualElement.source;
-
-  @override
-  List<TopLevelVariableElement> get topLevelVariables =>
-      actualElement.topLevelVariables;
-
-  @override
-  List<ClassElement> get types => actualElement.types;
-
-  @override
-  String get uri => actualElement.uri;
-
-  @override
-  int get uriEnd => actualElement.uriEnd;
-
-  @override
-  int get uriOffset => actualElement.uriOffset;
-
-  @deprecated
-  @override
-  CompilationUnit computeNode() => actualElement.computeNode();
-
-  @override
-  ClassElement getEnum(String enumName) => actualElement.getEnum(enumName);
-
-  @override
-  ClassElement getType(String className) => actualElement.getType(className);
-}
-
-/**
- * A handle to a [ConstructorElement].
- */
-class ConstructorElementHandle extends ExecutableElementHandle
-    implements ConstructorElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ConstructorElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ConstructorElement get actualElement =>
-      super.actualElement as ConstructorElement;
-
-  @override
-  ClassElement get enclosingElement => actualElement.enclosingElement;
-
-  @override
-  bool get isConst => actualElement.isConst;
-
-  @override
-  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
-
-  @override
-  bool get isDefaultConstructor => actualElement.isDefaultConstructor;
-
-  @override
-  bool get isFactory => actualElement.isFactory;
-
-  @override
-  ElementKind get kind => ElementKind.CONSTRUCTOR;
-
-  @override
-  int get nameEnd => actualElement.nameEnd;
-
-  @override
-  int get periodOffset => actualElement.periodOffset;
-
-  @override
-  ConstructorElement get redirectedConstructor =>
-      actualElement.redirectedConstructor;
-
-  @deprecated
-  @override
-  ConstructorDeclaration computeNode() => actualElement.computeNode();
-}
-
-/**
- * A handle to an [Element].
- */
-abstract class ElementHandle implements Element {
-  /**
-   * The unique integer identifier of this element.
-   */
-  final int id = 0;
-
-  /**
-   * The [ElementResynthesizer] which will be used to resynthesize elements on
-   * demand.
-   */
-  final ElementResynthesizer _resynthesizer;
-
-  /**
-   * The location of this element, used to reconstitute the element if it has
-   * not yet been resynthesized.
-   */
-  final ElementLocation _location;
-
-  /**
-   * A reference to the element being referenced by this handle, or `null` if
-   * the element has not yet been resynthesized.
-   */
-  Element _elementReference;
-
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ElementHandle(this._resynthesizer, this._location);
-
-  /**
-   * Return the element being represented by this handle, reconstituting the
-   * element if the reference has been set to `null`.
-   */
-  Element get actualElement {
-    if (_elementReference == null) {
-      _elementReference = _resynthesizer.getElement(_location);
-    }
-    return _elementReference;
-  }
-
-  @override
-  AnalysisContext get context => _resynthesizer.context;
-
-  @override
-  String get displayName => actualElement.displayName;
-
-  @override
-  String get documentationComment => actualElement.documentationComment;
-
-  @override
-  Element get enclosingElement => actualElement.enclosingElement;
-
-  @override
-  bool get hasAlwaysThrows => actualElement.hasAlwaysThrows;
-
-  @override
-  bool get hasDeprecated => actualElement.hasDeprecated;
-
-  @override
-  bool get hasFactory => actualElement.hasFactory;
-
-  @override
-  int get hashCode => _location.hashCode;
-
-  @override
-  bool get hasIsTest => actualElement.hasIsTest;
-
-  @override
-  bool get hasIsTestGroup => actualElement.hasIsTestGroup;
-
-  @override
-  bool get hasJS => actualElement.hasJS;
-
-  @override
-  bool get hasLiteral => actualElement.hasLiteral;
-
-  @override
-  bool get hasMustCallSuper => actualElement.hasMustCallSuper;
-
-  @override
-  bool get hasOptionalTypeArgs => actualElement.hasOptionalTypeArgs;
-
-  @override
-  bool get hasOverride => actualElement.hasOverride;
-
-  @override
-  bool get hasProtected => actualElement.hasProtected;
-
-  @override
-  bool get hasRequired => actualElement.hasRequired;
-
-  @override
-  bool get hasSealed => actualElement.hasSealed;
-
-  @override
-  bool get hasVisibleForTemplate => actualElement.hasVisibleForTemplate;
-
-  @override
-  bool get hasVisibleForTesting => actualElement.hasVisibleForTesting;
-
-  @override
-  bool get isAlwaysThrows => actualElement.hasAlwaysThrows;
-
-  @override
-  bool get isDeprecated => actualElement.hasDeprecated;
-
-  @override
-  bool get isFactory => actualElement.hasFactory;
-
-  @override
-  bool get isJS => actualElement.hasJS;
-
-  @override
-  bool get isOverride => actualElement.hasOverride;
-
-  @override
-  bool get isPrivate => actualElement.isPrivate;
-
-  @override
-  bool get isProtected => actualElement.hasProtected;
-
-  @override
-  bool get isPublic => actualElement.isPublic;
-
-  @override
-  bool get isRequired => actualElement.hasRequired;
-
-  @override
-  bool get isSynthetic => actualElement.isSynthetic;
-
-  @override
-  bool get isVisibleForTesting => actualElement.hasVisibleForTesting;
-
-  @override
-  LibraryElement get library =>
-      getAncestor((element) => element is LibraryElement);
-
-  @override
-  Source get librarySource => actualElement.librarySource;
-
-  @override
-  ElementLocation get location => _location;
-
-  @override
-  List<ElementAnnotation> get metadata => actualElement.metadata;
-
-  @override
-  String get name => actualElement.name;
-
-  @override
-  int get nameLength => actualElement.nameLength;
-
-  @override
-  int get nameOffset => actualElement.nameOffset;
-
-  @override
-  AnalysisSession get session => _resynthesizer.session;
-
-  @override
-  Source get source => actualElement.source;
-
-  @deprecated
-  @override
-  CompilationUnit get unit => actualElement.unit;
-
-  @override
-  bool operator ==(Object object) =>
-      object is Element && object.location == _location;
-
-  @override
-  T accept<T>(ElementVisitor<T> visitor) => actualElement.accept(visitor);
-
-  @override
-  String computeDocumentationComment() => documentationComment;
-
-  @deprecated
-  @override
-  AstNode computeNode() => actualElement.computeNode();
-
-  @override
-  E getAncestor<E extends Element>(Predicate<Element> predicate) =>
-      actualElement.getAncestor(predicate);
-
-  @override
-  String getExtendedDisplayName(String shortName) =>
-      actualElement.getExtendedDisplayName(shortName);
-
-  @override
-  bool isAccessibleIn(LibraryElement library) =>
-      actualElement.isAccessibleIn(library);
-
-  @override
-  String toString() => actualElement.toString();
-
-  @override
-  void visitChildren(ElementVisitor visitor) {
-    actualElement.visitChildren(visitor);
-  }
-}
-
-/**
- * Interface which allows an [Element] handle to be resynthesized based on an
- * [ElementLocation].  The concrete classes implementing element handles use
- * this interface to retrieve the underlying elements when queried.
- */
-abstract class ElementResynthesizer {
-  /**
-   * The context that owns the element to be resynthesized.
-   */
-  final AnalysisContext context;
-
-  /**
-   * The session that owns the element to be resynthesized.
-   * 
-   * Note that this will be `null` if the task model is being used.
-   */
-  final AnalysisSession session;
-
-  /**
-   * Initialize a newly created resynthesizer to resynthesize elements in the
-   * given [context].
-   */
-  ElementResynthesizer(this.context, this.session);
-
-  /**
-   * Return the element referenced by the given [location].
-   */
-  Element getElement(ElementLocation location);
-}
-
-/**
- * A handle to an [ExecutableElement].
- */
-abstract class ExecutableElementHandle extends ElementHandle
-    implements ExecutableElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ExecutableElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ExecutableElement get actualElement =>
-      super.actualElement as ExecutableElement;
-
-  @override
-  bool get hasImplicitReturnType => actualElement.hasImplicitReturnType;
-
-  @override
-  bool get isAbstract => actualElement.isAbstract;
-
-  @override
-  bool get isAsynchronous => actualElement.isAsynchronous;
-
-  @override
-  bool get isExternal => actualElement.isExternal;
-
-  @override
-  bool get isGenerator => actualElement.isGenerator;
-
-  @override
-  bool get isOperator => actualElement.isOperator;
-
-  @override
-  bool get isSimplyBounded => actualElement.isSimplyBounded;
-
-  @override
-  bool get isStatic => actualElement.isStatic;
-
-  @override
-  bool get isSynchronous => actualElement.isSynchronous;
-
-  @override
-  List<ParameterElement> get parameters => actualElement.parameters;
-
-  @override
-  DartType get returnType => actualElement.returnType;
-
-  @override
-  FunctionType get type => actualElement.type;
-
-  @override
-  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
-}
-
-/**
- * A handle to an [ExportElement].
- */
-class ExportElementHandle extends ElementHandle implements ExportElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ExportElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ExportElement get actualElement => super.actualElement as ExportElement;
-
-  @override
-  List<NamespaceCombinator> get combinators => actualElement.combinators;
-
-  @override
-  LibraryElement get exportedLibrary => actualElement.exportedLibrary;
-
-  @override
-  ElementKind get kind => ElementKind.EXPORT;
-
-  @override
-  String get uri => actualElement.uri;
-
-  @override
-  int get uriEnd => actualElement.uriEnd;
-
-  @override
-  int get uriOffset => actualElement.uriOffset;
-}
-
-/**
- * A handle to a [FieldElement].
- */
-class FieldElementHandle extends PropertyInducingElementHandle
-    implements FieldElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  FieldElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  FieldElement get actualElement => super.actualElement as FieldElement;
-
-  @override
-  ClassElement get enclosingElement => actualElement.enclosingElement;
-
-  @override
-  bool get isCovariant => actualElement.isCovariant;
-
-  @override
-  bool get isEnumConstant => actualElement.isEnumConstant;
-
-  @deprecated
-  @override
-  bool get isVirtual => actualElement.isVirtual;
-
-  @override
-  ElementKind get kind => ElementKind.FIELD;
-
-  @deprecated
-  @override
-  VariableDeclaration computeNode() => actualElement.computeNode();
-}
-
-/**
- * A handle to a [FunctionElement].
- */
-class FunctionElementHandle extends ExecutableElementHandle
-    implements FunctionElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  FunctionElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  FunctionElement get actualElement => super.actualElement as FunctionElement;
-
-  @override
-  bool get isEntryPoint => actualElement.isEntryPoint;
-
-  @override
-  ElementKind get kind => ElementKind.FUNCTION;
-
-  @override
-  SourceRange get visibleRange => actualElement.visibleRange;
-
-  @deprecated
-  @override
-  FunctionDeclaration computeNode() => actualElement.computeNode();
-}
-
-/**
- * A handle to a [FunctionTypeAliasElement].
- */
-class FunctionTypeAliasElementHandle extends ElementHandle
-    implements FunctionTypeAliasElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  FunctionTypeAliasElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  FunctionTypeAliasElement get actualElement =>
-      super.actualElement as FunctionTypeAliasElement;
-
-  @override
-  CompilationUnitElement get enclosingElement =>
-      super.enclosingElement as CompilationUnitElement;
-
-  @override
-  GenericFunctionTypeElement get function => actualElement.function;
-
-  @override
-  bool get isSimplyBounded => actualElement.isSimplyBounded;
-
-  @override
-  ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
-
-  @override
-  List<ParameterElement> get parameters => actualElement.parameters;
-
-  @override
-  DartType get returnType => actualElement.returnType;
-
-  @override
-  FunctionType get type => actualElement.type;
-
-  @override
-  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
-
-  @deprecated
-  @override
-  FunctionTypeAlias computeNode() => actualElement.computeNode();
-
-  @deprecated
-  @override
-  FunctionType instantiate(List<DartType> argumentTypes) =>
-      actualElement.instantiate(argumentTypes);
-
-  @override
-  FunctionType instantiate2({
-    @required List<DartType> typeArguments,
-    @required NullabilitySuffix nullabilitySuffix,
-  }) {
-    return actualElement.instantiate2(
-      typeArguments: typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-}
-
-/**
- * A handle to a [GenericTypeAliasElement].
- */
-class GenericTypeAliasElementHandle extends ElementHandle
-    implements GenericTypeAliasElement {
-  GenericTypeAliasElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  GenericTypeAliasElement get actualElement =>
-      super.actualElement as GenericTypeAliasElement;
-
-  @override
-  CompilationUnitElement get enclosingElement =>
-      super.enclosingElement as CompilationUnitElement;
-
-  @override
-  GenericFunctionTypeElement get function => actualElement.function;
-
-  @override
-  bool get isSimplyBounded => actualElement.isSimplyBounded;
-
-  @override
-  ElementKind get kind => ElementKind.FUNCTION_TYPE_ALIAS;
-
-  @override
-  List<ParameterElement> get parameters => actualElement.parameters;
-
-  @override
-  DartType get returnType => actualElement.returnType;
-
-  @override
-  FunctionType get type => actualElement.type;
-
-  @override
-  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
-
-  @deprecated
-  @override
-  FunctionTypeAlias computeNode() => actualElement.computeNode();
-
-  @deprecated
-  @override
-  FunctionType instantiate(List<DartType> argumentTypes) =>
-      actualElement.instantiate(argumentTypes);
-
-  @override
-  FunctionType instantiate2({
-    @required List<DartType> typeArguments,
-    @required NullabilitySuffix nullabilitySuffix,
-  }) {
-    return actualElement.instantiate2(
-      typeArguments: typeArguments,
-      nullabilitySuffix: nullabilitySuffix,
-    );
-  }
-}
-
-/**
- * A handle to an [ImportElement].
- */
-class ImportElementHandle extends ElementHandle implements ImportElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ImportElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ImportElement get actualElement => super.actualElement as ImportElement;
-
-  @override
-  List<NamespaceCombinator> get combinators => actualElement.combinators;
-
-  @override
-  LibraryElement get importedLibrary => actualElement.importedLibrary;
-
-  @override
-  bool get isDeferred => actualElement.isDeferred;
-
-  @override
-  ElementKind get kind => ElementKind.IMPORT;
-
-  @override
-  Namespace get namespace => actualElement.namespace;
-
-  @override
-  PrefixElement get prefix => actualElement.prefix;
-
-  @override
-  int get prefixOffset => actualElement.prefixOffset;
-
-  @override
-  String get uri => actualElement.uri;
-
-  @override
-  int get uriEnd => actualElement.uriEnd;
-
-  @override
-  int get uriOffset => actualElement.uriOffset;
-}
-
-/**
- * A handle to a [LabelElement].
- */
-class LabelElementHandle extends ElementHandle implements LabelElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  LabelElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ExecutableElement get enclosingElement =>
-      super.enclosingElement as ExecutableElement;
-
-  @override
-  ElementKind get kind => ElementKind.LABEL;
-}
-
-/**
- * A handle to a [LibraryElement].
- */
-class LibraryElementHandle extends ElementHandle implements LibraryElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  LibraryElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  LibraryElement get actualElement => super.actualElement as LibraryElement;
-
-  @override
-  CompilationUnitElement get definingCompilationUnit =>
-      actualElement.definingCompilationUnit;
-
-  @override
-  FunctionElement get entryPoint => actualElement.entryPoint;
-
-  @override
-  List<LibraryElement> get exportedLibraries => actualElement.exportedLibraries;
-
-  @override
-  Namespace get exportNamespace => actualElement.exportNamespace;
-
-  @override
-  List<ExportElement> get exports => actualElement.exports;
-
-  @override
-  bool get hasExtUri => actualElement.hasExtUri;
-
-  @override
-  bool get hasLoadLibraryFunction => actualElement.hasLoadLibraryFunction;
-
-  @override
-  String get identifier => location.components.last;
-
-  @override
-  List<LibraryElement> get importedLibraries => actualElement.importedLibraries;
-
-  @override
-  List<ImportElement> get imports => actualElement.imports;
-
-  @override
-  bool get isBrowserApplication => actualElement.isBrowserApplication;
-
-  @override
-  bool get isDartAsync => actualElement.isDartAsync;
-
-  @override
-  bool get isDartCore => actualElement.isDartCore;
-
-  @override
-  bool get isInSdk => actualElement.isInSdk;
-
-  @override
-  bool get isNonNullableByDefault => actualElement.isNonNullableByDefault;
-
-  @override
-  ElementKind get kind => ElementKind.LIBRARY;
-
-  @override
-  List<LibraryElement> get libraryCycle => actualElement.libraryCycle;
-
-  @override
-  FunctionElement get loadLibraryFunction => actualElement.loadLibraryFunction;
-
-  @override
-  List<CompilationUnitElement> get parts => actualElement.parts;
-
-  @override
-  List<PrefixElement> get prefixes => actualElement.prefixes;
-
-  @override
-  Namespace get publicNamespace => actualElement.publicNamespace;
-
-  @override
-  Iterable<Element> get topLevelElements => actualElement.topLevelElements;
-
-  @override
-  List<CompilationUnitElement> get units => actualElement.units;
-
-  @override
-  List<ImportElement> getImportsWithPrefix(PrefixElement prefixElement) =>
-      actualElement.getImportsWithPrefix(prefixElement);
-
-  @override
-  ClassElement getType(String className) => actualElement.getType(className);
-}
-
-/**
- * A handle to a [LocalVariableElement].
- */
-class LocalVariableElementHandle extends VariableElementHandle
-    implements LocalVariableElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  LocalVariableElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  LocalVariableElement get actualElement =>
-      super.actualElement as LocalVariableElement;
-
-  @override
-  ElementKind get kind => ElementKind.LOCAL_VARIABLE;
-
-  @override
-  SourceRange get visibleRange => actualElement.visibleRange;
-
-  @deprecated
-  @override
-  VariableDeclaration computeNode() => actualElement.computeNode();
-}
-
-/**
- * A handle to a [MethodElement].
- */
-class MethodElementHandle extends ExecutableElementHandle
-    implements MethodElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  MethodElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  MethodElement get actualElement => super.actualElement as MethodElement;
-
-  @override
-  ClassElement get enclosingElement => super.enclosingElement as ClassElement;
-
-  @override
-  bool get isStatic => actualElement.isStatic;
-
-  @override
-  ElementKind get kind => ElementKind.METHOD;
-
-  @deprecated
-  @override
-  MethodDeclaration computeNode() => actualElement.computeNode();
-}
-
-/**
- * A handle to a [ParameterElement].
- */
-class ParameterElementHandle extends VariableElementHandle
-    with ParameterElementMixin
-    implements ParameterElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  ParameterElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ParameterElement get actualElement => super.actualElement as ParameterElement;
-
-  @override
-  String get defaultValueCode => actualElement.defaultValueCode;
-
-  @override
-  bool get isCovariant => actualElement.isCovariant;
-
-  @override
-  bool get isInitializingFormal => actualElement.isInitializingFormal;
-
-  @override
-  ElementKind get kind => ElementKind.PARAMETER;
-
-  @deprecated
-  @override
-  ParameterKind get parameterKind => actualElement.parameterKind;
-
-  @override
-  List<ParameterElement> get parameters => actualElement.parameters;
-
-  @override
-  List<TypeParameterElement> get typeParameters => actualElement.typeParameters;
-
-  @override
-  SourceRange get visibleRange => actualElement.visibleRange;
-
-  @deprecated
-  @override
-  FormalParameter computeNode() => super.computeNode();
-}
-
-/**
- * A handle to a [PrefixElement].
- */
-class PrefixElementHandle extends ElementHandle implements PrefixElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  PrefixElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  PrefixElement get actualElement => super.actualElement as PrefixElement;
-
-  @override
-  LibraryElement get enclosingElement =>
-      super.enclosingElement as LibraryElement;
-
-  @override
-  List<LibraryElement> get importedLibraries => const <LibraryElement>[];
-
-  @override
-  ElementKind get kind => ElementKind.PREFIX;
-}
-
-/**
- * A handle to a [PropertyAccessorElement].
- */
-class PropertyAccessorElementHandle extends ExecutableElementHandle
-    implements PropertyAccessorElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  PropertyAccessorElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  PropertyAccessorElement get actualElement =>
-      super.actualElement as PropertyAccessorElement;
-
-  @override
-  PropertyAccessorElement get correspondingGetter =>
-      actualElement.correspondingGetter;
-
-  @override
-  PropertyAccessorElement get correspondingSetter =>
-      actualElement.correspondingSetter;
-
-  @override
-  bool get isGetter => !isSetter;
-
-  @override
-  bool get isSetter => location.components.last.endsWith('=');
-
-  @override
-  ElementKind get kind {
-    if (isGetter) {
-      return ElementKind.GETTER;
-    } else {
-      return ElementKind.SETTER;
-    }
-  }
-
-  @override
-  PropertyInducingElement get variable => actualElement.variable;
-}
-
-/**
- * A handle to an [PropertyInducingElement].
- */
-abstract class PropertyInducingElementHandle extends VariableElementHandle
-    implements PropertyInducingElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  PropertyInducingElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  PropertyInducingElement get actualElement =>
-      super.actualElement as PropertyInducingElement;
-
-  @override
-  PropertyAccessorElement get getter => actualElement.getter;
-
-  @override
-  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
-
-  @deprecated
-  @override
-  DartType get propagatedType => null;
-
-  @override
-  PropertyAccessorElement get setter => actualElement.setter;
-}
-
-/**
- * A handle to a [TopLevelVariableElement].
- */
-class TopLevelVariableElementHandle extends PropertyInducingElementHandle
-    implements TopLevelVariableElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  TopLevelVariableElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  ElementKind get kind => ElementKind.TOP_LEVEL_VARIABLE;
-
-  @deprecated
-  @override
-  VariableDeclaration computeNode() => super.computeNode();
-}
-
-/**
- * A handle to a [TypeParameterElement].
- */
-class TypeParameterElementHandle extends ElementHandle
-    implements TypeParameterElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  TypeParameterElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  TypeParameterElement get actualElement =>
-      super.actualElement as TypeParameterElement;
-
-  @override
-  DartType get bound => actualElement.bound;
-
-  @override
-  ElementKind get kind => ElementKind.TYPE_PARAMETER;
-
-  @override
-  TypeParameterType get type => actualElement.type;
-
-  @override
-  TypeParameterType instantiate({
-    @required NullabilitySuffix nullabilitySuffix,
-  }) {
-    return actualElement.instantiate(nullabilitySuffix: nullabilitySuffix);
-  }
-}
-
-/**
- * A handle to an [VariableElement].
- */
-abstract class VariableElementHandle extends ElementHandle
-    implements VariableElement {
-  /**
-   * Initialize a newly created element handle to represent the element at the
-   * given [_location]. The [_resynthesizer] will be used to resynthesize the
-   * element when needed.
-   */
-  VariableElementHandle(
-      ElementResynthesizer resynthesizer, ElementLocation location)
-      : super(resynthesizer, location);
-
-  @override
-  VariableElement get actualElement => super.actualElement as VariableElement;
-
-  @override
-  DartObject get constantValue => actualElement.constantValue;
-
-  @override
-  bool get hasImplicitType => actualElement.hasImplicitType;
-
-  @override
-  FunctionElement get initializer => actualElement.initializer;
-
-  @override
-  bool get isConst => actualElement.isConst;
-
-  @override
-  bool get isConstantEvaluated => actualElement.isConstantEvaluated;
-
-  @override
-  bool get isFinal => actualElement.isFinal;
-
-  @override
-  bool get isLate => actualElement.isLate;
-
-  @deprecated
-  @override
-  bool get isPotentiallyMutatedInClosure =>
-      actualElement.isPotentiallyMutatedInClosure;
-
-  @deprecated
-  @override
-  bool get isPotentiallyMutatedInScope =>
-      actualElement.isPotentiallyMutatedInScope;
-
-  @override
-  bool get isStatic => actualElement.isStatic;
-
-  @override
-  DartType get type => actualElement.type;
-
-  @override
-  DartObject computeConstantValue() => actualElement.computeConstantValue();
-}
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
deleted file mode 100644
index 63238fc..0000000
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
+++ /dev/null
@@ -1,539 +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:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart'
-    show InheritanceManagerBase, InheritanceManager3;
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-import 'package:analyzer/src/generated/utilities_general.dart';
-
-/// Description of a failure to find a valid override from superinterfaces.
-class Conflict {
-  /// The name of an instance member for which we failed to find a valid
-  /// override.
-  final Name name;
-
-  /// The list of candidates for a valid override for a member [name].  It has
-  /// at least two items, because otherwise the only candidate is always valid.
-  final List<FunctionType> candidates;
-
-  /// The getter that conflicts with the [method], or `null`, if the conflict
-  /// is inconsistent inheritance.
-  final FunctionType getter;
-
-  /// The method tha conflicts with the [getter], or `null`, if the conflict
-  /// is inconsistent inheritance.
-  final FunctionType method;
-
-  Conflict(this.name, this.candidates, [this.getter, this.method]);
-}
-
-/// Manages knowledge about interface types and their members.
-class InheritanceManager2 extends InheritanceManagerBase {
-  static final _noSuchMethodName = Name(null, 'noSuchMethod');
-
-  final TypeSystem _typeSystem;
-
-  /// Cached instance interfaces for [InterfaceType].
-  final Map<InterfaceType, Interface> _interfaces = {};
-
-  /// The set of classes that are currently being processed, used to detect
-  /// self-referencing cycles.
-  final Set<ClassElement> _processingClasses = new Set<ClassElement>();
-
-  InheritanceManager2(this._typeSystem);
-
-  @override
-  InheritanceManager3 get asInheritanceManager3 =>
-      InheritanceManager3(_typeSystem);
-
-  /// Return the most specific signature of the member with the given [name]
-  /// that the [type] inherits from the mixins, superclasses, or interfaces;
-  /// or `null` if no member is inherited because the member is not declared
-  /// at all, or because there is no the most specific signature.
-  ///
-  /// This is equivalent to `getInheritedMap(type)[name]`.
-  FunctionType getInherited(InterfaceType type, Name name) {
-    return getInheritedMap(type)[name];
-  }
-
-  /// Return signatures of all concrete members that the given [type] inherits
-  /// from the superclasses and mixins.
-  Map<Name, FunctionType> getInheritedConcreteMap(InterfaceType type) {
-    var interface = getInterface(type);
-    return interface._superImplemented.last;
-  }
-
-  /// Return the mapping from names to most specific signatures of members
-  /// inherited from the super-interfaces (superclasses, mixins, and
-  /// interfaces).  If there is no most specific signature for a name, the
-  /// corresponding name will not be included.
-  Map<Name, FunctionType> getInheritedMap(InterfaceType type) {
-    var interface = getInterface(type);
-    if (interface._inheritedMap == null) {
-      interface._inheritedMap = {};
-      _findMostSpecificFromNamedCandidates(
-        interface._inheritedMap,
-        interface._overridden,
-      );
-    }
-    return interface._inheritedMap;
-  }
-
-  /// Return the interface of the given [type].  It might include private
-  /// members, not necessary accessible in all libraries.
-  Interface getInterface(InterfaceType type) {
-    if (type == null) {
-      return Interface._empty;
-    }
-
-    var result = _interfaces[type];
-    if (result != null) {
-      return result;
-    }
-    _interfaces[type] = Interface._empty;
-
-    var classElement = type.element;
-    if (!_processingClasses.add(classElement)) {
-      return Interface._empty;
-    }
-
-    Map<Name, List<FunctionType>> namedCandidates = {};
-    List<Map<Name, FunctionType>> superImplemented = [];
-    Map<Name, FunctionType> declared;
-    Interface superInterface;
-    Map<Name, FunctionType> implemented;
-    Map<Name, FunctionType> implementedForMixing;
-    try {
-      // If a class declaration has a member declaration, the signature of that
-      // member declaration becomes the signature in the interface.
-      declared = _getTypeMembers(type);
-
-      for (var interface in type.interfaces) {
-        var interfaceObj = getInterface(interface);
-        _addCandidates(namedCandidates, interfaceObj);
-      }
-
-      if (classElement.isMixin) {
-        var superClassCandidates = <Name, List<FunctionType>>{};
-        for (var constraint in type.superclassConstraints) {
-          var interfaceObj = getInterface(constraint);
-          _addCandidates(superClassCandidates, interfaceObj);
-          _addCandidates(namedCandidates, interfaceObj);
-        }
-
-        implemented = {};
-
-        // `mixin M on S1, S2 {}` can call using `super` any instance member
-        // from its superclass constraints, whether it is abstract or concrete.
-        var superClass = <Name, FunctionType>{};
-        _findMostSpecificFromNamedCandidates(superClass, superClassCandidates);
-        superImplemented.add(superClass);
-      } else {
-        if (type.superclass != null) {
-          superInterface = getInterface(type.superclass);
-          _addCandidates(namedCandidates, superInterface);
-
-          implemented = superInterface.implemented;
-          superImplemented.add(implemented);
-        } else {
-          implemented = {};
-        }
-
-        implementedForMixing = {};
-        for (var mixin in type.mixins) {
-          var interfaceObj = getInterface(mixin);
-          _addCandidates(namedCandidates, interfaceObj);
-
-          implemented = <Name, FunctionType>{}
-            ..addAll(implemented)
-            ..addAll(interfaceObj._implementedForMixing);
-          superImplemented.add(implemented);
-          implementedForMixing.addAll(interfaceObj._implementedForMixing);
-        }
-      }
-    } finally {
-      _processingClasses.remove(classElement);
-    }
-
-    var thisImplemented = <Name, FunctionType>{};
-    _addImplemented(thisImplemented, type);
-
-    if (classElement.isMixin) {
-      implementedForMixing = thisImplemented;
-    } else {
-      implementedForMixing.addAll(thisImplemented);
-    }
-
-    implemented = <Name, FunctionType>{}..addAll(implemented);
-    _addImplemented(implemented, type);
-
-    // If a class declaration does not have a member declaration with a
-    // particular name, but some super-interfaces do have a member with that
-    // name, it's a compile-time error if there is no signature among the
-    // super-interfaces that is a valid override of all the other
-    // super-interface signatures with the same name. That "most specific"
-    // signature becomes the signature of the class's interface.
-    Map<Name, FunctionType> map = new Map.of(declared);
-    List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
-      map,
-      namedCandidates,
-    );
-
-    var noSuchMethodForwarders = Set<Name>();
-    if (classElement.isAbstract) {
-      if (superInterface != null) {
-        noSuchMethodForwarders = superInterface._noSuchMethodForwarders;
-      }
-    } else {
-      var noSuchMethod = implemented[_noSuchMethodName]?.element;
-      if (noSuchMethod != null && !_isDeclaredInObject(noSuchMethod)) {
-        var superForwarders = superInterface?._noSuchMethodForwarders;
-        for (var name in map.keys) {
-          if (!implemented.containsKey(name) ||
-              superForwarders != null && superForwarders.contains(name)) {
-            implemented[name] = map[name];
-            noSuchMethodForwarders.add(name);
-          }
-        }
-      }
-    }
-
-    var interface = new Interface._(
-      map,
-      declared,
-      implemented,
-      noSuchMethodForwarders,
-      implementedForMixing,
-      namedCandidates,
-      superImplemented,
-      conflicts ?? const [],
-    );
-    _interfaces[type] = interface;
-    return interface;
-  }
-
-  /// Return the member with the given [name].
-  ///
-  /// If [concrete] is `true`, the the concrete implementation is returned,
-  /// from the given [type], or its superclass.
-  ///
-  /// If [forSuper] is `true`, then [concrete] is implied, and only concrete
-  /// members from the superclass are considered.
-  ///
-  /// If [forMixinIndex] is specified, only the nominal superclass, and the
-  /// given number of mixins after it are considered.  For example for `1` in
-  /// `class C extends S with M1, M2, M3`, only `S` and `M1` are considered.
-  FunctionType getMember(
-    InterfaceType type,
-    Name name, {
-    bool concrete: false,
-    int forMixinIndex: -1,
-    bool forSuper: false,
-  }) {
-    var interface = getInterface(type);
-    if (forSuper) {
-      var superImplemented = interface._superImplemented;
-      if (forMixinIndex >= 0) {
-        return superImplemented[forMixinIndex][name];
-      }
-      return superImplemented.last[name];
-    }
-    if (concrete) {
-      return interface.implemented[name];
-    }
-    return interface.map[name];
-  }
-
-  /// Return all members of mixins, superclasses, and interfaces that a member
-  /// with the given [name], defined in the [type], would override; or `null`
-  /// if no members would be overridden.
-  List<FunctionType> getOverridden(InterfaceType type, Name name) {
-    var interface = getInterface(type);
-    return interface._overridden[name];
-  }
-
-  void _addCandidate(Map<Name, List<FunctionType>> namedCandidates, Name name,
-      FunctionType candidate) {
-    var candidates = namedCandidates[name];
-    if (candidates == null) {
-      candidates = <FunctionType>[];
-      namedCandidates[name] = candidates;
-    }
-
-    candidates.add(candidate);
-  }
-
-  void _addCandidates(
-      Map<Name, List<FunctionType>> namedCandidates, Interface interface) {
-    var map = interface.map;
-    for (var name in map.keys) {
-      var candidate = map[name];
-      _addCandidate(namedCandidates, name, candidate);
-    }
-  }
-
-  void _addImplemented(
-      Map<Name, FunctionType> implemented, InterfaceType type) {
-    var libraryUri = type.element.librarySource.uri;
-
-    void addMember(ExecutableElement member) {
-      if (!member.isAbstract && !member.isStatic) {
-        var name = new Name(libraryUri, member.name);
-        implemented[name] = member.type;
-      }
-    }
-
-    void addMembers(InterfaceType type) {
-      type.methods.forEach(addMember);
-      type.accessors.forEach(addMember);
-    }
-
-    addMembers(type);
-  }
-
-  /// Check that all [candidates] for the given [name] have the same kind, all
-  /// getters, all methods, or all setter.  If a conflict found, return the
-  /// new [Conflict] instance that describes it.
-  Conflict _checkForGetterMethodConflict(
-      Name name, List<FunctionType> candidates) {
-    assert(candidates.length > 1);
-
-    bool allGetters = true;
-    bool allMethods = true;
-    bool allSetters = true;
-    for (var candidate in candidates) {
-      var kind = candidate.element.kind;
-      if (kind != ElementKind.GETTER) {
-        allGetters = false;
-      }
-      if (kind != ElementKind.METHOD) {
-        allMethods = false;
-      }
-      if (kind != ElementKind.SETTER) {
-        allSetters = false;
-      }
-    }
-
-    if (allGetters || allMethods || allSetters) {
-      return null;
-    }
-
-    FunctionType getterType;
-    FunctionType methodType;
-    for (var candidate in candidates) {
-      var kind = candidate.element.kind;
-      if (kind == ElementKind.GETTER) {
-        getterType ??= candidate;
-      }
-      if (kind == ElementKind.METHOD) {
-        methodType ??= candidate;
-      }
-    }
-    return new Conflict(name, candidates, getterType, methodType);
-  }
-
-  /// The given [namedCandidates] maps names to candidates from direct
-  /// superinterfaces.  Find the most specific signature, and put it into the
-  /// [map], if there is no one yet (from the class itself).  If there is no
-  /// such single most specific signature (i.e. no valid override), then add a
-  /// new conflict description.
-  List<Conflict> _findMostSpecificFromNamedCandidates(
-      Map<Name, FunctionType> map,
-      Map<Name, List<FunctionType>> namedCandidates) {
-    List<Conflict> conflicts;
-
-    for (var name in namedCandidates.keys) {
-      if (map.containsKey(name)) {
-        continue;
-      }
-
-      var candidates = namedCandidates[name];
-
-      // If just one candidate, it is always valid.
-      if (candidates.length == 1) {
-        map[name] = candidates[0];
-        continue;
-      }
-
-      // Check for a getter/method conflict.
-      var conflict = _checkForGetterMethodConflict(name, candidates);
-      if (conflict != null) {
-        conflicts ??= <Conflict>[];
-        conflicts.add(conflict);
-      }
-
-      // Candidates are recorded in forward order, so
-      // `class X extends S with M1, M2 implements I1, I2 {}` will record
-      // candidates from [I1, I2, S, M1, M2]. But during method lookup
-      // candidates should be considered in backward order, i.e. from `M2`,
-      // then from `M1`, then from `S`.
-      FunctionType validOverride;
-      for (var i = candidates.length - 1; i >= 0; i--) {
-        validOverride = candidates[i];
-        for (var j = 0; j < candidates.length; j++) {
-          var candidate = candidates[j];
-          if (!_typeSystem.isOverrideSubtypeOf(validOverride, candidate)) {
-            validOverride = null;
-            break;
-          }
-        }
-        if (validOverride != null) {
-          break;
-        }
-      }
-
-      if (validOverride != null) {
-        map[name] = validOverride;
-      } else {
-        conflicts ??= <Conflict>[];
-        conflicts.add(new Conflict(name, candidates));
-      }
-    }
-
-    return conflicts;
-  }
-
-  Map<Name, FunctionType> _getTypeMembers(InterfaceType type) {
-    var declared = <Name, FunctionType>{};
-    var libraryUri = type.element.librarySource.uri;
-
-    var methods = type.methods;
-    for (var i = 0; i < methods.length; i++) {
-      var method = methods[i];
-      if (!method.isStatic) {
-        var name = new Name(libraryUri, method.name);
-        declared[name] = method.type;
-      }
-    }
-
-    var accessors = type.accessors;
-    for (var i = 0; i < accessors.length; i++) {
-      var accessor = accessors[i];
-      if (!accessor.isStatic) {
-        var name = new Name(libraryUri, accessor.name);
-        declared[name] = accessor.type;
-      }
-    }
-
-    return declared;
-  }
-
-  static bool _isDeclaredInObject(ExecutableElement element) {
-    var enclosing = element.enclosingElement;
-    return enclosing is ClassElement &&
-        enclosing.supertype == null &&
-        !enclosing.isMixin;
-  }
-}
-
-/// The instance interface of an [InterfaceType].
-class Interface {
-  static final _empty = Interface._(
-    const {},
-    const {},
-    const {},
-    Set<Name>(),
-    const {},
-    const {},
-    const [{}],
-    const [],
-  );
-
-  /// The map of names to their signature in the interface.
-  final Map<Name, FunctionType> map;
-
-  /// The map of declared names to their signatures.
-  final Map<Name, FunctionType> declared;
-
-  /// The map of names to their concrete implementations.
-  final Map<Name, FunctionType> implemented;
-
-  /// The set of names that are `noSuchMethod` forwarders in [implemented].
-  final Set<Name> _noSuchMethodForwarders;
-
-  /// The map of names to their concrete implementations that can be mixed
-  /// when this type is used as a mixin.
-  final Map<Name, FunctionType> _implementedForMixing;
-
-  /// The map of names to their signatures from the mixins, superclasses,
-  /// or interfaces.
-  final Map<Name, List<FunctionType>> _overridden;
-
-  /// Each item of this list maps names to their concrete implementations.
-  /// The first item of the list is the nominal superclass, next the nominal
-  /// superclass plus the first mixin, etc. So, for the class like
-  /// `class C extends S with M1, M2`, we get `[S, S&M1, S&M1&M2]`.
-  final List<Map<Name, FunctionType>> _superImplemented;
-
-  /// The list of conflicts between superinterfaces - the nominal superclass,
-  /// mixins, and interfaces.  Does not include conflicts with the declared
-  /// members of the class.
-  final List<Conflict> conflicts;
-
-  /// The map of names to the most specific signatures from the mixins,
-  /// superclasses, or interfaces.
-  Map<Name, FunctionType> _inheritedMap;
-
-  Interface._(
-    this.map,
-    this.declared,
-    this.implemented,
-    this._noSuchMethodForwarders,
-    this._implementedForMixing,
-    this._overridden,
-    this._superImplemented,
-    this.conflicts,
-  );
-
-  /// Return `true` if the [name] is implemented in the supertype.
-  bool isSuperImplemented(Name name) {
-    return _superImplemented.last.containsKey(name);
-  }
-}
-
-/// A public name, or a private name qualified by a library URI.
-class Name {
-  /// If the name is private, the URI of the defining library.
-  /// Otherwise, it is `null`.
-  final Uri libraryUri;
-
-  /// The name of this name object.
-  /// If the name starts with `_`, then the name is private.
-  /// Names of setters end with `=`.
-  final String name;
-
-  /// Precomputed
-  final bool isPublic;
-
-  /// The cached, pre-computed hash code.
-  final int hashCode;
-
-  factory Name(Uri libraryUri, String name) {
-    if (name.startsWith('_')) {
-      var hashCode = JenkinsSmiHash.hash2(libraryUri.hashCode, name.hashCode);
-      return new Name._internal(libraryUri, name, false, hashCode);
-    } else {
-      return new Name._internal(null, name, true, name.hashCode);
-    }
-  }
-
-  Name._internal(this.libraryUri, this.name, this.isPublic, this.hashCode);
-
-  @override
-  bool operator ==(other) {
-    return other is Name &&
-        name == other.name &&
-        libraryUri == other.libraryUri;
-  }
-
-  bool isAccessibleFor(Uri libraryUri) {
-    return isPublic || this.libraryUri == libraryUri;
-  }
-
-  @override
-  String toString() => libraryUri != null ? '$libraryUri::$name' : name;
-}
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index f457b8a..8f3af4e 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -29,7 +29,7 @@
 }
 
 /// Manages knowledge about interface types and their members.
-class InheritanceManager3 extends InheritanceManagerBase {
+class InheritanceManager3 {
   static final _noSuchMethodName = Name(null, 'noSuchMethod');
 
   final TypeSystem _typeSystem;
@@ -43,9 +43,6 @@
 
   InheritanceManager3(this._typeSystem);
 
-  @override
-  InheritanceManager3 get asInheritanceManager3 => this;
-
   /// Return the most specific signature of the member with the given [name]
   /// that the [type] inherits from the mixins, superclasses, or interfaces;
   /// or `null` if no member is inherited because the member is not declared
@@ -236,7 +233,12 @@
       if (forMixinIndex >= 0) {
         return superImplemented[forMixinIndex][name];
       }
-      return superImplemented.last[name];
+      if (superImplemented.isNotEmpty) {
+        return superImplemented.last[name];
+      } else {
+        assert(type.element.name == 'Object');
+        return null;
+      }
     }
     if (concrete) {
       return interface.implemented[name];
@@ -427,14 +429,6 @@
   }
 }
 
-/// A temporary bridge between the old and the new versions of inheritance
-/// managers. Clients may not reference, extend, implement, or mix-in this
-/// class. It will be removed in the next major version of analyser, together
-/// with "InheritanceManager2".
-abstract class InheritanceManagerBase {
-  InheritanceManager3 get asInheritanceManager3;
-}
-
 /// The instance interface of an [InterfaceType].
 class Interface {
   static final _empty = Interface._(
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 737047d..550b729 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -65,10 +64,6 @@
   T accept<T>(ElementVisitor<T> visitor) =>
       visitor.visitConstructorElement(this);
 
-  @deprecated
-  @override
-  ConstructorDeclaration computeNode() => baseElement.computeNode();
-
   @override
   String toString() {
     ConstructorElement baseElement = this.baseElement;
@@ -191,7 +186,7 @@
 
   @override
   List<TypeParameterElement> get typeParameters {
-    return TypeParameterMember.from2(
+    return TypeParameterMember.from(
       baseElement.typeParameters,
       _substitution,
     );
@@ -303,14 +298,6 @@
   @override
   bool get isEnumConstant => baseElement.isEnumConstant;
 
-  @deprecated
-  @override
-  bool get isVirtual => baseElement.isVirtual;
-
-  @deprecated
-  @override
-  DartType get propagatedType => null;
-
   @override
   PropertyAccessorElement get setter {
     var baseSetter = baseElement.setter;
@@ -323,10 +310,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitFieldElement(this);
 
-  @deprecated
-  @override
-  VariableDeclaration computeNode() => baseElement.computeNode();
-
   @override
   String toString() => '$type $displayName';
 
@@ -418,6 +401,9 @@
   bool get hasMustCallSuper => _baseElement.hasMustCallSuper;
 
   @override
+  bool get hasNonVirtual => _baseElement.hasNonVirtual;
+
+  @override
   bool get hasOptionalTypeArgs => _baseElement.hasOptionalTypeArgs;
 
   @override
@@ -442,39 +428,15 @@
   int get id => _baseElement.id;
 
   @override
-  bool get isAlwaysThrows => _baseElement.hasAlwaysThrows;
-
-  @override
-  bool get isDeprecated => _baseElement.hasDeprecated;
-
-  @override
-  bool get isFactory => _baseElement.hasFactory;
-
-  @override
-  bool get isJS => _baseElement.hasJS;
-
-  @override
-  bool get isOverride => _baseElement.hasOverride;
-
-  @override
   bool get isPrivate => _baseElement.isPrivate;
 
   @override
-  bool get isProtected => _baseElement.hasProtected;
-
-  @override
   bool get isPublic => _baseElement.isPublic;
 
   @override
-  bool get isRequired => _baseElement.hasRequired;
-
-  @override
   bool get isSynthetic => _baseElement.isSynthetic;
 
   @override
-  bool get isVisibleForTesting => _baseElement.hasVisibleForTesting;
-
-  @override
   ElementKind get kind => _baseElement.kind;
 
   @override
@@ -509,17 +471,6 @@
    */
   MapSubstitution get substitution => _substitution;
 
-  @deprecated
-  @override
-  CompilationUnit get unit => _baseElement.unit;
-
-  @override
-  String computeDocumentationComment() => documentationComment;
-
-  @deprecated
-  @override
-  AstNode computeNode() => _baseElement.computeNode();
-
   @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) =>
       baseElement.getAncestor(predicate);
@@ -573,10 +524,6 @@
   @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
 
-  @deprecated
-  @override
-  MethodDeclaration computeNode() => baseElement.computeNode();
-
   @override
   String toString() {
     MethodElement baseElement = this.baseElement;
@@ -722,22 +669,15 @@
 
   @override
   List<TypeParameterElement> get typeParameters {
-    return TypeParameterMember.from2(
+    return TypeParameterMember.from(
       baseElement.typeParameters,
       _substitution,
     );
   }
 
   @override
-  SourceRange get visibleRange => baseElement.visibleRange;
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitParameterElement(this);
 
-  @deprecated
-  @override
-  FormalParameter computeNode() => baseElement.computeNode();
-
   @override
   E getAncestor<E extends Element>(Predicate<Element> predicate) {
     Element element = baseElement.getAncestor(predicate);
@@ -923,7 +863,9 @@
 
   @override
   bool operator ==(Object other) =>
-      other is TypeParameterMember && baseElement == other.baseElement;
+      other is TypeParameterMember &&
+      other.baseElement == baseElement &&
+      other._bound == _bound;
 
   @override
   T accept<T>(ElementVisitor<T> visitor) =>
@@ -951,23 +893,7 @@
     return buffer.toString();
   }
 
-  /**
-   * If the given [parameter]'s type is different when any type parameters from
-   * the defining type's declaration are replaced with the actual type
-   * arguments from the [definingType], create a parameter member representing
-   * the given parameter. Return the member that was created, or the base
-   * parameter if no member was created.
-   */
   static List<TypeParameterElement> from(
-      List<TypeParameterElement> formals, FunctionType definingType) {
-    var substitution = Substitution.fromPairs(
-      definingType.typeParameters,
-      definingType.typeArguments,
-    );
-    return from2(formals, substitution);
-  }
-
-  static List<TypeParameterElement> from2(
     List<TypeParameterElement> elements,
     MapSubstitution substitution,
   ) {
@@ -981,7 +907,7 @@
     var newTypes = List<TypeParameterType>(elements.length);
     for (int i = 0; i < newElements.length; i++) {
       var element = elements[i];
-      var bound = element?.bound;
+      var bound = element.bound;
       if (bound != null) {
         bound = substitution.substituteType(bound);
         element = TypeParameterMember(element, substitution, bound);
@@ -992,14 +918,10 @@
       );
     }
 
-    // Recursive bounds are allowed too, so make sure these are updated
-    // to refer to any new TypeParameterMember we just made, rather than
-    // the original type parameter
+    // Update bounds to reference new TypeParameterMember(s).
     var substitution2 = Substitution.fromPairs(elements, newTypes);
     for (var newElement in newElements) {
       if (newElement is TypeParameterMember) {
-        // TODO(jmesserly): this is required so substituting for the
-        // type formal will work. Investigate if there's a better solution.
         newElement._bound = substitution2.substituteType(newElement.bound);
       }
     }
@@ -1063,16 +985,6 @@
   bool get isLate => baseElement.isLate;
 
   @override
-  @deprecated
-  bool get isPotentiallyMutatedInClosure =>
-      baseElement.isPotentiallyMutatedInClosure;
-
-  @override
-  @deprecated
-  bool get isPotentiallyMutatedInScope =>
-      baseElement.isPotentiallyMutatedInScope;
-
-  @override
   bool get isStatic => baseElement.isStatic;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 1f363f8..d518283 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -16,6 +16,7 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
 
 /// Transforms the given [list] by applying [transform] to all its elements.
 ///
@@ -97,20 +98,6 @@
   bool operator ==(Object object) => identical(object, this);
 
   @override
-  bool isMoreSpecificThan(DartType type,
-          [bool withDynamic = false, Set<Element> visitedElements]) =>
-      true;
-
-  @override
-  bool isSubtypeOf(DartType type) => true;
-
-  @override
-  bool isSupertypeOf(DartType type) => false;
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant = true}) {
     if (isCovariant) {
@@ -129,9 +116,9 @@
   }
 
   @override
+  @deprecated
   BottomTypeImpl substitute2(
-          List<DartType> argumentTypes, List<DartType> parameterTypes,
-          [List<FunctionTypeAliasElement> prune]) =>
+          List<DartType> argumentTypes, List<DartType> parameterTypes) =>
       this;
 
   @override
@@ -149,174 +136,6 @@
 }
 
 /**
- * The type created internally if a circular reference is ever detected in a
- * function type.
- */
-class CircularFunctionTypeImpl extends DynamicTypeImpl
-    implements _FunctionTypeImplLazy {
-  CircularFunctionTypeImpl() : super._circular();
-
-  @override
-  List<ParameterElement> get baseParameters => const <ParameterElement>[];
-
-  @override
-  DartType get baseReturnType => DynamicTypeImpl.instance;
-
-  @override
-  List<TypeParameterElement> get boundTypeParameters =>
-      const <TypeParameterElement>[];
-
-  @override
-  FunctionTypedElement get element => null;
-
-  @override
-  bool get isInstantiated => false;
-
-  @override
-  Map<String, DartType> get namedParameterTypes => <String, DartType>{};
-
-  @override
-  List<FunctionTypeAliasElement> get newPrune =>
-      const <FunctionTypeAliasElement>[];
-
-  @override
-  List<String> get normalParameterNames => <String>[];
-
-  @override
-  List<DartType> get normalParameterTypes => const <DartType>[];
-
-  @override
-  List<String> get optionalParameterNames => <String>[];
-
-  @override
-  List<DartType> get optionalParameterTypes => const <DartType>[];
-
-  @override
-  List<ParameterElement> get parameters => const <ParameterElement>[];
-
-  @override
-  List<FunctionTypeAliasElement> get prunedTypedefs =>
-      const <FunctionTypeAliasElement>[];
-
-  @override
-  DartType get returnType => DynamicTypeImpl.instance;
-
-  @override
-  List<DartType> get typeArguments => const <DartType>[];
-
-  @override
-  List<TypeParameterElement> get typeFormals => const <TypeParameterElement>[];
-
-  @override
-  List<TypeParameterElement> get typeParameters =>
-      const <TypeParameterElement>[];
-
-  @override
-  bool get _isInstantiated => false;
-
-  @override
-  List<ParameterElement> get _parameters => const <ParameterElement>[];
-
-  @override
-  DartType get _returnType => DynamicTypeImpl.instance;
-
-  @override
-  List<DartType> get _typeArguments => const <DartType>[];
-
-  @override
-  void set _typeArguments(List<DartType> arguments) {
-    throw new UnsupportedError('Cannot have type arguments');
-  }
-
-  @override
-  List<TypeParameterElement> get _typeParameters =>
-      const <TypeParameterElement>[];
-
-  @override
-  void set _typeParameters(List<TypeParameterElement> parameters) {
-    throw new UnsupportedError('Cannot have type parameters');
-  }
-
-  @override
-  bool operator ==(Object object) => object is CircularFunctionTypeImpl;
-
-  @override
-  void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
-      {bool withNullability = false}) {
-    buffer.write('...');
-  }
-
-  @override
-  FunctionTypeImpl instantiate(List<DartType> argumentTypes) => this;
-
-  @override
-  FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
-  FunctionType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    return this;
-  }
-
-  @override
-  FunctionTypeImpl substitute3(List<DartType> argumentTypes) => this;
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
-
-  @override
-  void _appendToWithTypeParameters(StringBuffer buffer,
-      Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
-    throw StateError('We should never get here.');
-  }
-
-  @override
-  void _forEachParameterType(
-      ParameterKind kind, callback(String name, DartType type)) {
-    // There are no parameters.
-  }
-
-  @override
-  void _freeVariablesInFunctionType(
-      FunctionType type, Set<TypeParameterType> free) {
-    // There are no free variables
-  }
-
-  @override
-  void _freeVariablesInInterfaceType(
-      InterfaceType type, Set<TypeParameterType> free) {
-    // There are no free variables
-  }
-
-  @override
-  void _freeVariablesInType(DartType type, Set<TypeParameterType> free) {
-    // There are no free variables
-  }
-}
-
-/**
- * Type created internally if a circular reference is ever detected.  Behaves
- * like `dynamic`, except that when converted to a string it is displayed as
- * `...`.
- */
-class CircularTypeImpl extends DynamicTypeImpl {
-  CircularTypeImpl() : super._circular();
-
-  @override
-  bool operator ==(Object object) => object is CircularTypeImpl;
-
-  @override
-  void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
-      {bool withNullability = false}) {
-    buffer.write('...');
-  }
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-}
-
-/**
  * The [Type] representing the type `dynamic`.
  */
 class DynamicTypeImpl extends TypeImpl {
@@ -330,11 +149,6 @@
    */
   DynamicTypeImpl._() : super(new DynamicElementImpl(), Keyword.DYNAMIC.lexeme);
 
-  /**
-   * Constructor used by [CircularTypeImpl].
-   */
-  DynamicTypeImpl._circular() : super(instance.element, Keyword.DYNAMIC.lexeme);
-
   @override
   int get hashCode => 1;
 
@@ -348,26 +162,6 @@
   bool operator ==(Object object) => identical(object, this);
 
   @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    // T is S
-    if (identical(this, type)) {
-      return true;
-    }
-    // else
-    return withDynamic;
-  }
-
-  @override
-  bool isSubtypeOf(DartType type) => true;
-
-  @override
-  bool isSupertypeOf(DartType type) => true;
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant = true}) {
     if (isCovariant) {
@@ -378,9 +172,9 @@
   }
 
   @override
+  @deprecated
   DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
       if (parameterTypes[i] == this) {
@@ -400,40 +194,31 @@
 /**
  * The type of a function, method, constructor, getter, or setter.
  */
-abstract class FunctionTypeImpl extends TypeImpl implements FunctionType {
+class FunctionTypeImpl extends TypeImpl implements FunctionType {
+  @override
+  final DartType returnType;
+
+  @override
+  final List<TypeParameterElement> typeFormals;
+
+  @override
+  final List<ParameterElement> parameters;
+
+  @override
+  final List<DartType> typeArguments;
+
   @override
   final NullabilitySuffix nullabilitySuffix;
 
-  /**
-   * Initialize a newly created function type to be declared by the given
-   * [element], and also initialize [typeArguments] to match the
-   * [typeParameters], which permits later substitution.
-   */
-  factory FunctionTypeImpl(FunctionTypedElement element,
-      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star}) {
-    if (element is FunctionTypeAliasElement) {
-      throw new StateError('Use FunctionTypeImpl.forTypedef for typedefs');
-    }
-    return new _FunctionTypeImplLazy._(
-        element, null, null, null, null, null, false,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
   /// Creates a function type that's not associated with any element in the
   /// element tree.
-  factory FunctionTypeImpl.synthetic(DartType returnType,
-      List<TypeParameterElement> typeFormals, List<ParameterElement> parameters,
+  FunctionTypeImpl.synthetic(this.returnType, this.typeFormals, this.parameters,
       {Element element,
-      List<DartType> typeArguments = const <DartType>[],
-      NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star}) {
-    return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
-        element: element,
-        typeArguments: typeArguments,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  FunctionTypeImpl._(Element element, String name, this.nullabilitySuffix)
-      : super(element, name);
+      List<DartType> typeArguments,
+      @required NullabilitySuffix nullabilitySuffix})
+      : typeArguments = typeArguments ?? const <DartType>[],
+        nullabilitySuffix = nullabilitySuffix,
+        super(element, null);
 
   @deprecated
   @override
@@ -484,7 +269,14 @@
   }
 
   @override
-  FunctionTypedElement get element => super.element;
+  FunctionTypedElement get element {
+    var element = super.element;
+    // TODO(scheglov) Can we just construct it with the right element?
+    if (element is GenericTypeAliasElement) {
+      return element.function;
+    }
+    return element;
+  }
 
   @override
   int get hashCode {
@@ -509,11 +301,6 @@
     return code;
   }
 
-  /**
-   * Return `true` if this type is the result of instantiating type parameters.
-   */
-  bool get isInstantiated;
-
   @override
   Map<String, DartType> get namedParameterTypes {
     // TODO(brianwilkerson) This implementation breaks the contract because the
@@ -529,11 +316,11 @@
     return types;
   }
 
-  /**
-   * Determine the new set of typedefs which should be pruned when expanding
-   * this function type.
-   */
-  List<FunctionTypeAliasElement> get newPrune;
+  @override
+  List<String> get normalParameterNames => parameters
+      .where((p) => p.isRequiredPositional)
+      .map((p) => p.name)
+      .toList();
 
   @override
   List<DartType> get normalParameterTypes {
@@ -545,6 +332,12 @@
   }
 
   @override
+  List<String> get optionalParameterNames => parameters
+      .where((p) => p.isOptionalPositional)
+      .map((p) => p.name)
+      .toList();
+
+  @override
   List<DartType> get optionalParameterTypes {
     List<DartType> types = <DartType>[];
     _forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
@@ -553,11 +346,8 @@
     return types;
   }
 
-  /**
-   * The set of typedefs which should not be expanded when exploring this type,
-   * to avoid creating infinite types in response to self-referential typedefs.
-   */
-  List<FunctionTypeAliasElement> get prunedTypedefs;
+  @override
+  List<TypeParameterElement> get typeParameters => const [] /*TODO(paulberry)*/;
 
   @override
   bool operator ==(Object object) {
@@ -639,7 +429,8 @@
             TypeImpl renamed =
                 Substitution.fromPairs(variables, instantiateTypeArgs)
                     .substituteType(e.bound);
-            renamed.appendTo(typeParametersBuffer, visitedTypes);
+            renamed.appendTo(typeParametersBuffer, visitedTypes,
+                withNullability: withNullability);
           }
         }
         typeParametersBuffer.write('>');
@@ -660,35 +451,33 @@
   }
 
   @override
-  FunctionTypeImpl instantiate(List<DartType> argumentTypes);
+  FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
+    if (argumentTypes.length != typeFormals.length) {
+      throw new ArgumentError(
+          "argumentTypes.length (${argumentTypes.length}) != "
+          "typeFormals.length (${typeFormals.length})");
+    }
+    if (argumentTypes.isEmpty) {
+      return this;
+    }
 
-  @override
-  bool isAssignableTo(DartType type) {
-    // A function type T may be assigned to a function type S, written T <=> S,
-    // iff T <: S.
-    return isSubtypeOf(type);
-  }
+    var substitution = Substitution.fromPairs(typeFormals, argumentTypes);
 
-  @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    // Note: visitedElements is only used for breaking recursion in the type
-    // hierarchy; we don't use it when recursing into the function type.
-    return FunctionTypeImpl.relate(
-        this,
-        type,
-        (DartType t, DartType s) =>
-            (t as TypeImpl).isMoreSpecificThan(s, withDynamic));
-  }
+    ParameterElement transformParameter(ParameterElement p) {
+      var type = p.type;
+      var newType = substitution.substituteType(type);
+      if (identical(newType, type)) return p;
+      return new ParameterElementImpl.synthetic(
+          p.name,
+          newType,
+          // ignore: deprecated_member_use_from_same_package
+          p.parameterKind)
+        ..isExplicitlyCovariant = p.isCovariant;
+    }
 
-  @override
-  bool isSubtypeOf(DartType type) {
-    var typeSystem = new Dart2TypeSystem(null);
-    return FunctionTypeImpl.relate(
-        typeSystem.instantiateToBounds(this),
-        typeSystem.instantiateToBounds(type),
-        // ignore: deprecated_member_use_from_same_package
-        (DartType t, DartType s) => t.isAssignableTo(s));
+    return FunctionTypeImpl.synthetic(substitution.substituteType(returnType),
+        const [], _transformOrShare(parameters, transformParameter),
+        nullabilitySuffix: nullabilitySuffix);
   }
 
   @override
@@ -713,19 +502,41 @@
         identical(parameters, this.parameters)) {
       return this;
     }
-    return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
+    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters,
         nullabilitySuffix: nullabilitySuffix);
   }
 
   @override
+  @deprecated
   FunctionType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]);
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
+    if (argumentTypes.length != parameterTypes.length) {
+      throw new ArgumentError(
+          "argumentTypes.length (${argumentTypes.length}) != "
+          "parameterTypes.length (${parameterTypes.length})");
+    }
+
+    var substitution = Substitution.fromPairs(
+      parameterTypes.map<TypeParameterElement>((t) => t.element).toList(),
+      argumentTypes,
+    );
+    return substitution.substituteType(this);
+  }
 
   @override
+  @deprecated
   FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
       substitute2(argumentTypes, typeArguments);
 
+  @override
+  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
+    if (this.nullabilitySuffix == nullabilitySuffix) return this;
+    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters,
+        element: element,
+        typeArguments: typeArguments,
+        nullabilitySuffix: nullabilitySuffix);
+  }
+
   void _appendToWithTypeParameters(StringBuffer buffer,
       Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
     List<DartType> normalParameterTypes = this.normalParameterTypes;
@@ -796,12 +607,15 @@
     }
   }
 
-  /**
-   * Invokes [callback] for each parameter of [kind] with the parameter's [name]
-   * and type after any type parameters have been applied.
-   */
   void _forEachParameterType(
-      ParameterKind kind, callback(String name, DartType type));
+      ParameterKind kind, Function(String name, DartType type) callback) {
+    for (var parameter in parameters) {
+      // ignore: deprecated_member_use_from_same_package
+      if (parameter.parameterKind == kind) {
+        callback(parameter.name, parameter.type);
+      }
+    }
+  }
 
   void _freeVariablesInFunctionType(
       FunctionType type, Set<TypeParameterType> free) {
@@ -1101,25 +915,12 @@
  */
 class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
   @override
+  final List<DartType> typeArguments;
+
+  @override
   final NullabilitySuffix nullabilitySuffix;
 
   /**
-   * A list containing the actual types of the type arguments.
-   */
-  List<DartType> _typeArguments = const <DartType>[];
-
-  /**
-   * The set of typedefs which should not be expanded when exploring this type,
-   * to avoid creating infinite types in response to self-referential typedefs.
-   */
-  final List<FunctionTypeAliasElement> prunedTypedefs;
-
-  /**
-   * The version of [element] for which members are cached.
-   */
-  int _versionOfCachedMembers;
-
-  /**
    * Cached [ConstructorElement]s - members or raw elements.
    */
   List<ConstructorElement> _constructors;
@@ -1138,31 +939,29 @@
    * Initialize a newly created type to be declared by the given [element].
    */
   InterfaceTypeImpl(ClassElement element,
-      {this.prunedTypedefs, this.nullabilitySuffix = NullabilitySuffix.star})
-      : super(element, element.displayName);
-
-  InterfaceTypeImpl.explicit(ClassElement element, List<DartType> typeArguments,
       {this.nullabilitySuffix = NullabilitySuffix.star})
-      : prunedTypedefs = null,
-        _typeArguments = typeArguments,
+      : typeArguments = const <DartType>[],
         super(element, element.displayName);
 
+  InterfaceTypeImpl.explicit(ClassElement element, this.typeArguments,
+      {this.nullabilitySuffix = NullabilitySuffix.star})
+      : super(element, element.displayName);
+
   /**
    * Private constructor.
    */
-  InterfaceTypeImpl._(Element element, String name, this.prunedTypedefs,
+  InterfaceTypeImpl._(Element element, String name,
       {this.nullabilitySuffix = NullabilitySuffix.star})
-      : super(element, name);
+      : typeArguments = const <DartType>[],
+        super(element, name);
 
   InterfaceTypeImpl._withNullability(InterfaceTypeImpl original,
       {this.nullabilitySuffix = NullabilitySuffix.star})
-      : _typeArguments = original._typeArguments,
-        prunedTypedefs = original.prunedTypedefs,
+      : typeArguments = original.typeArguments,
         super(original.element, original.name);
 
   @override
   List<PropertyAccessorElement> get accessors {
-    _flushCachedMembersIfStale();
     if (_accessors == null) {
       List<PropertyAccessorElement> accessors = element.accessors;
       List<PropertyAccessorElement> members =
@@ -1177,7 +976,6 @@
 
   @override
   List<ConstructorElement> get constructors {
-    _flushCachedMembersIfStale();
     if (_constructors == null) {
       List<ConstructorElement> constructors = element.constructors;
       List<ConstructorElement> members =
@@ -1371,7 +1169,6 @@
 
   @override
   List<MethodElement> get methods {
-    _flushCachedMembersIfStale();
     if (_methods == null) {
       List<MethodElement> methods = element.methods;
       List<MethodElement> members = new List<MethodElement>(methods.length);
@@ -1406,18 +1203,6 @@
   }
 
   @override
-  List<DartType> get typeArguments {
-    return _typeArguments;
-  }
-
-  /**
-   * Set [typeArguments].
-   */
-  void set typeArguments(List<DartType> typeArguments) {
-    _typeArguments = typeArguments;
-  }
-
-  @override
   List<TypeParameterElement> get typeParameters => element.typeParameters;
 
   @override
@@ -1480,39 +1265,6 @@
   }
 
   @override
-  DartType flattenFutures(TypeSystem typeSystem) {
-    // Implement the cases:
-    //  - "If T = FutureOr<S> then flatten(T) = S."
-    //  - "If T = Future<S> then flatten(T) = S."
-    if (isDartAsyncFutureOr || isDartAsyncFuture) {
-      return typeArguments.isNotEmpty
-          ? typeArguments[0]
-          : DynamicTypeImpl.instance;
-    }
-
-    // Implement the case: "Otherwise if T <: Future then let S be a type
-    // such that T << Future<S> and for all R, if T << Future<R> then S << R.
-    // Then flatten(T) = S."
-    //
-    // In other words, given the set of all types R such that T << Future<R>,
-    // let S be the most specific of those types, if any such S exists.
-    //
-    // Since we only care about the most specific type, it is sufficient to
-    // look at the types appearing as a parameter to Future in the type
-    // hierarchy of T.  We don't need to consider the supertypes of those
-    // types, since they are by definition less specific.
-    List<DartType> candidateTypes =
-        _searchTypeHierarchyForFutureTypeParameters();
-    DartType flattenResult = findMostSpecificType(candidateTypes, typeSystem);
-    if (flattenResult != null) {
-      return flattenResult;
-    }
-
-    // Implement the case: "In any other circumstance, flatten(T) = T."
-    return this;
-  }
-
-  @override
   PropertyAccessorElement getGetter(String getterName) =>
       PropertyAccessorMember.from(element.getGetter(getterName), this);
 
@@ -1525,182 +1277,11 @@
       PropertyAccessorMember.from(element.getSetter(setterName), this);
 
   @override
+  @deprecated
   InterfaceTypeImpl instantiate(List<DartType> argumentTypes) =>
       substitute2(argumentTypes, typeArguments);
 
   @override
-  bool isDirectSupertypeOf(InterfaceType type) {
-    InterfaceType i = this;
-    InterfaceType j = type;
-    var substitution = Substitution.fromInterfaceType(j);
-    ClassElement jElement = j.element;
-    //
-    // If J is Object, then it has no direct supertypes.
-    //
-    if (j.isObject) {
-      return false;
-    }
-    //
-    // I is listed in the extends clause of J.
-    //
-    InterfaceType supertype = jElement.supertype;
-    if (supertype != null) {
-      supertype = substitution.substituteType(supertype);
-      if (supertype == i) {
-        return true;
-      }
-    }
-    //
-    // I is listed in the on clause of J.
-    //
-    for (InterfaceType interfaceType in jElement.superclassConstraints) {
-      interfaceType = substitution.substituteType(interfaceType);
-      if (interfaceType == i) {
-        return true;
-      }
-    }
-    //
-    // I is listed in the implements clause of J.
-    //
-    for (InterfaceType interfaceType in jElement.interfaces) {
-      interfaceType = substitution.substituteType(interfaceType);
-      if (interfaceType == i) {
-        return true;
-      }
-    }
-    //
-    // I is listed in the with clause of J.
-    //
-    for (InterfaceType mixinType in jElement.mixins) {
-      mixinType = substitution.substituteType(mixinType);
-      if (mixinType == i) {
-        return true;
-      }
-    }
-    //
-    // J is a mixin application of the mixin of I.
-    //
-    // TODO(brianwilkerson) Determine whether this needs to be implemented or
-    // whether it is covered by the case above.
-    return false;
-  }
-
-  @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    //
-    // T is Null and S is not Bottom.
-    //
-    if (isDartCoreNull && !type.isBottom) {
-      return true;
-    }
-
-    // S is dynamic.
-    // The test to determine whether S is dynamic is done here because dynamic
-    // is not an instance of InterfaceType.
-    //
-    if (type.isDynamic) {
-      return true;
-    }
-    //
-    // A type T is more specific than a type S, written T << S,
-    // if one of the following conditions is met:
-    //
-    // Reflexivity: T is S.
-    //
-    if (this == type) {
-      return true;
-    }
-    if (type is InterfaceType) {
-      //
-      // T is bottom. (This case is handled by the class BottomTypeImpl.)
-      //
-      // Direct supertype: S is a direct supertype of T.
-      //
-      // ignore: deprecated_member_use_from_same_package
-      if (type.isDirectSupertypeOf(this)) {
-        return true;
-      }
-      //
-      // Covariance: T is of the form I<T1, ..., Tn> and S is of the form
-      // I<S1, ..., Sn> and Ti << Si, 1 <= i <= n.
-      //
-      ClassElement tElement = this.element;
-      ClassElement sElement = type.element;
-      if (tElement == sElement) {
-        List<DartType> tArguments = typeArguments;
-        List<DartType> sArguments = type.typeArguments;
-        if (tArguments.length != sArguments.length) {
-          return false;
-        }
-        for (int i = 0; i < tArguments.length; i++) {
-          if (!(tArguments[i] as TypeImpl)
-              .isMoreSpecificThan(sArguments[i], withDynamic)) {
-            return false;
-          }
-        }
-        return true;
-      }
-    }
-    //
-    // Transitivity: T << U and U << S.
-    //
-    // First check for infinite loops
-    if (element == null) {
-      return false;
-    }
-    if (visitedElements == null) {
-      visitedElements = new HashSet<ClassElement>();
-    } else if (visitedElements.contains(element)) {
-      return false;
-    }
-    visitedElements.add(element);
-    try {
-      // Iterate over all of the types U that are more specific than T because
-      // they are direct supertypes of T and return true if any of them are more
-      // specific than S.
-      InterfaceTypeImpl supertype = superclass;
-      if (supertype != null &&
-          supertype.isMoreSpecificThan(type, withDynamic, visitedElements)) {
-        return true;
-      }
-      for (InterfaceType interfaceType in interfaces) {
-        if ((interfaceType as InterfaceTypeImpl)
-            .isMoreSpecificThan(type, withDynamic, visitedElements)) {
-          return true;
-        }
-      }
-      for (InterfaceType mixinType in mixins) {
-        if ((mixinType as InterfaceTypeImpl)
-            .isMoreSpecificThan(type, withDynamic, visitedElements)) {
-          return true;
-        }
-      }
-      if (element.isMixin) {
-        for (InterfaceType constraint in superclassConstraints) {
-          if ((constraint as InterfaceTypeImpl)
-              .isMoreSpecificThan(type, withDynamic, visitedElements)) {
-            return true;
-          }
-        }
-      }
-      // If a type I includes an instance method named `call`, and the type of
-      // `call` is the function type F, then I is considered to be more specific
-      // than F.
-      MethodElement callMethod = getMethod('call');
-      if (callMethod != null && !callMethod.isStatic) {
-        FunctionTypeImpl callType = callMethod.type;
-        if (callType.isMoreSpecificThan(type, withDynamic, visitedElements)) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      visitedElements.remove(element);
-    }
-  }
-
-  @override
   ConstructorElement lookUpConstructor(
       String constructorName, LibraryElement library) {
     // prepare base ConstructorElement
@@ -2009,25 +1590,6 @@
   }
 
   @override
-  InterfaceTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
-    if (prune == null) {
-      return this;
-    } else {
-      // There should never be a reason to prune a type that has already been
-      // pruned, since pruning is only done when expanding a function type
-      // alias, and function type aliases are always expanded by starting with
-      // base types.
-      assert(this.prunedTypedefs == null);
-      InterfaceTypeImpl result = new InterfaceTypeImpl._(element, name, prune,
-          nullabilitySuffix: nullabilitySuffix);
-      result.typeArguments = typeArguments
-          .map((DartType t) => (t as TypeImpl).pruned(prune))
-          .toList();
-      return result;
-    }
-  }
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant: true}) {
     // First check if this is actually an instance of Bottom
@@ -2047,30 +1609,29 @@
     if (identical(typeArguments, this.typeArguments)) {
       return this;
     } else {
-      return new InterfaceTypeImpl._(element, name, prunedTypedefs,
-          nullabilitySuffix: nullabilitySuffix)
-        ..typeArguments = typeArguments;
+      return new InterfaceTypeImpl.explicit(element, typeArguments,
+          nullabilitySuffix: nullabilitySuffix);
     }
   }
 
   @override
+  @deprecated
   InterfaceTypeImpl substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
     if (argumentTypes.length != parameterTypes.length) {
       throw new ArgumentError(
           "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
     }
     if (argumentTypes.isEmpty || typeArguments.isEmpty) {
-      return this.pruned(prune);
+      return this;
     }
 
-    List<DartType> newTypeArguments = TypeImpl.substitute(
-        typeArguments, argumentTypes, parameterTypes, prune);
+    List<DartType> newTypeArguments =
+        TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
 
-    InterfaceTypeImpl newType = new InterfaceTypeImpl(element,
-        prunedTypedefs: prune, nullabilitySuffix: nullabilitySuffix);
-    newType.typeArguments = newTypeArguments;
+    InterfaceTypeImpl newType = new InterfaceTypeImpl.explicit(
+        element, newTypeArguments,
+        nullabilitySuffix: nullabilitySuffix);
     return newType;
   }
 
@@ -2123,23 +1684,6 @@
     return null;
   }
 
-  /**
-   * Flush cache members if the version of [element] for which members are
-   * cached and the current version of the [element].
-   */
-  void _flushCachedMembersIfStale() {
-    ClassElement element = this.element;
-    if (element is ClassElementImpl) {
-      int currentVersion = element.version;
-      if (_versionOfCachedMembers != currentVersion) {
-        _constructors = null;
-        _accessors = null;
-        _methods = null;
-      }
-      _versionOfCachedMembers = currentVersion;
-    }
-  }
-
   List<InterfaceType> _instantiateSuperTypes(List<InterfaceType> defined) {
     if (defined.isEmpty) return defined;
 
@@ -2155,32 +1699,6 @@
   }
 
   /**
-   * Starting from this type, search its class hierarchy for types of the form
-   * Future<R>, and return a list of the resulting R's.
-   */
-  List<DartType> _searchTypeHierarchyForFutureTypeParameters() {
-    List<DartType> result = <DartType>[];
-    HashSet<ClassElement> visitedClasses = new HashSet<ClassElement>();
-    void recurse(InterfaceTypeImpl type) {
-      if (type.isDartAsyncFuture && type.typeArguments.isNotEmpty) {
-        result.add(type.typeArguments[0]);
-      }
-      if (visitedClasses.add(type.element)) {
-        if (type.superclass != null) {
-          recurse(type.superclass);
-        }
-        for (InterfaceType interface in type.interfaces) {
-          recurse(interface);
-        }
-        visitedClasses.remove(type.element);
-      }
-    }
-
-    recurse(this);
-    return result;
-  }
-
-  /**
    * If there is a single type which is at least as specific as all of the
    * types in [types], return it.  Otherwise return `null`.
    */
@@ -2312,10 +1830,8 @@
       return NullabilitySuffix.none;
     }
 
-    InterfaceTypeImpl lub = new InterfaceTypeImpl(firstElement,
+    return new InterfaceTypeImpl.explicit(firstElement, lubArguments,
         nullabilitySuffix: computeNullability());
-    lub.typeArguments = lubArguments;
-    return lub;
   }
 
   /**
@@ -2486,81 +2002,6 @@
     }
   }
 
-  @override
-  DartType flattenFutures(TypeSystem typeSystem) => this;
-
-  /**
-   * Return `true` if this type is assignable to the given [type] (written in
-   * the spec as "T <=> S", where T=[this] and S=[type]).
-   *
-   * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
-   * function type aliases that have been expanded so far in the process of
-   * reaching [this] and [type], respectively.  These are used to avoid
-   * infinite regress when analyzing invalid code; since the language spec
-   * forbids a typedef from referring to itself directly or indirectly, we can
-   * use these as sets of function type aliases that don't need to be expanded.
-   */
-  @override
-  bool isAssignableTo(DartType type) {
-    // An interface type T may be assigned to a type S, written T <=> S, iff
-    // either T <: S or S <: T.
-    return isSubtypeOf(type) || type.isSubtypeOf(this);
-  }
-
-  @override
-  bool isEquivalentTo(DartType other) => this == other;
-
-  /**
-   * Return `true` if this type is more specific than the given [type] (written
-   * in the spec as "T << S", where T=[this] and S=[type]).
-   *
-   * If [withDynamic] is `true`, then "dynamic" should be considered as a
-   * subtype of any type (as though "dynamic" had been replaced with bottom).
-   *
-   * The set [visitedElements], if given, is the set of classes and type
-   * parameters that have been visited so far while examining the class
-   * hierarchy of [this].  This is used to avoid infinite regress when
-   * analyzing invalid code; since the language spec forbids loops in the class
-   * hierarchy, we can use this as a set of classes that don't need to be
-   * examined when walking the class hierarchy.
-   */
-  @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]);
-
-  /**
-   * Return `true` if this type is a subtype of the given [type] (written in
-   * the spec as "T <: S", where T=[this] and S=[type]).
-   *
-   * The sets [thisExpansions] and [typeExpansions], if given, are the sets of
-   * function type aliases that have been expanded so far in the process of
-   * reaching [this] and [type], respectively.  These are used to avoid
-   * infinite regress when analyzing invalid code; since the language spec
-   * forbids a typedef from referring to itself directly or indirectly, we can
-   * use these as sets of function type aliases that don't need to be expanded.
-   */
-  @override
-  bool isSubtypeOf(DartType type) {
-    // For non-function types, T <: S iff [_|_/dynamic]T << S.
-    return isMoreSpecificThan(type, true);
-  }
-
-  @override
-  bool isSupertypeOf(DartType type) => type.isSubtypeOf(this);
-
-  /**
-   * Create a new [TypeImpl] that is identical to [this] except that when
-   * visiting type parameters, function parameter types, and function return
-   * types, function types listed in [prune] will not be expanded.  This is
-   * used to avoid creating infinite types in the presence of circular
-   * typedefs.
-   *
-   * If [prune] is null, then [this] is returned unchanged.
-   *
-   * Only legal to call on a [TypeImpl] that is not already subject to pruning.
-   */
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune);
-
   /// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
   /// `Null` and all contravariant occurrences of `Null` with `Object`.
   ///
@@ -2575,16 +2016,11 @@
   /**
    * Return the type resulting from substituting the given [argumentTypes] for
    * the given [parameterTypes] in this type.
-   *
-   * In all classes derived from [TypeImpl], a new optional argument
-   * [prune] is added.  If specified, it is a list of function typdefs
-   * which should not be expanded.  This is used to avoid creating infinite
-   * types in response to self-referential typedefs.
    */
   @override
+  @deprecated
   DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]);
+      List<DartType> argumentTypes, List<DartType> parameterTypes);
 
   @override
   String toString({bool withNullability = false}) {
@@ -2635,12 +2071,12 @@
     }
     for (int i = 0; i < first.length; i++) {
       if (first[i] == null) {
-        AnalysisEngine.instance.logger
-            .logInformation('Found null type argument in TypeImpl.equalArrays');
+        AnalysisEngine.instance.instrumentationService
+            .logInfo('Found null type argument in TypeImpl.equalArrays');
         return second[i] == null;
       } else if (second[i] == null) {
-        AnalysisEngine.instance.logger
-            .logInformation('Found null type argument in TypeImpl.equalArrays');
+        AnalysisEngine.instance.instrumentationService
+            .logInfo('Found null type argument in TypeImpl.equalArrays');
         return false;
       }
       if (first[i] != second[i]) {
@@ -2653,22 +2089,18 @@
   /**
    * Return a list containing the results of using the given [argumentTypes] and
    * [parameterTypes] to perform a substitution on all of the given [types].
-   *
-   * If [prune] is specified, it is a list of function typdefs which should not
-   * be expanded.  This is used to avoid creating infinite types in response to
-   * self-referential typedefs.
    */
+  @deprecated
   static List<DartType> substitute(List<DartType> types,
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
     int length = types.length;
     if (length == 0) {
       return types;
     }
     List<DartType> newTypes = new List<DartType>(length);
     for (int i = 0; i < length; i++) {
-      newTypes[i] = (types[i] as TypeImpl)
-          .substitute2(argumentTypes, parameterTypes, prune);
+      newTypes[i] =
+          (types[i] as TypeImpl).substitute2(argumentTypes, parameterTypes);
     }
     return newTypes;
   }
@@ -2706,70 +2138,12 @@
     if (identical(other, this)) {
       return true;
     }
-    return other is TypeParameterTypeImpl && other.element == element;
+    return other is TypeParameterTypeImpl &&
+        other.element == element &&
+        other.nullabilitySuffix == nullabilitySuffix;
   }
 
   @override
-  bool isMoreSpecificThan(DartType s,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    //
-    // A type T is more specific than a type S, written T << S,
-    // if one of the following conditions is met:
-    //
-    // Reflexivity: T is S.
-    //
-    if (this == s) {
-      return true;
-    }
-    // S is dynamic.
-    //
-    if (s.isDynamic) {
-      return true;
-    }
-    //
-    // T is a type parameter and S is the upper bound of T.
-    //
-    TypeImpl bound = element.bound;
-    if (s == bound) {
-      return true;
-    }
-    //
-    // T is a type parameter and S is Object.
-    //
-    if (s.isObject) {
-      return true;
-    }
-    // We need upper bound to continue.
-    if (bound == null) {
-      return false;
-    }
-    //
-    // Transitivity: T << U and U << S.
-    //
-    // First check for infinite loops
-    if (element == null) {
-      return false;
-    }
-    if (visitedElements == null) {
-      visitedElements = new HashSet<Element>();
-    } else if (visitedElements.contains(element)) {
-      return false;
-    }
-    visitedElements.add(element);
-    try {
-      return bound.isMoreSpecificThan(s, withDynamic, visitedElements);
-    } finally {
-      visitedElements.remove(element);
-    }
-  }
-
-  @override
-  bool isSubtypeOf(DartType type) => isMoreSpecificThan(type, true);
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant = true}) {
     return this;
@@ -2799,9 +2173,9 @@
   }
 
   @override
+  @deprecated
   DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
       var parameterType = parameterTypes[i];
@@ -2876,6 +2250,7 @@
  */
 abstract class VoidType implements DartType {
   @override
+  @deprecated
   VoidType substitute2(
       List<DartType> argumentTypes, List<DartType> parameterTypes);
 }
@@ -2907,23 +2282,6 @@
   bool operator ==(Object object) => identical(object, this);
 
   @override
-  bool isMoreSpecificThan(DartType type,
-          [bool withDynamic = false, Set<Element> visitedElements]) =>
-      isSubtypeOf(type);
-
-  @override
-  bool isSubtypeOf(DartType type) {
-    // The only subtype relations that pertain to void are therefore:
-    // void <: void (by reflexivity)
-    // bottom <: void (as bottom is a subtype of all types).
-    // void <: dynamic (as dynamic is a supertype of all types)
-    return identical(type, this) || type.isDynamic;
-  }
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant = true}) {
     if (isCovariant) {
@@ -2934,9 +2292,9 @@
   }
 
   @override
+  @deprecated
   VoidTypeImpl substitute2(
-          List<DartType> argumentTypes, List<DartType> parameterTypes,
-          [List<FunctionTypeAliasElement> prune]) =>
+          List<DartType> argumentTypes, List<DartType> parameterTypes) =>
       this;
 
   @override
@@ -2945,489 +2303,3 @@
     return this;
   }
 }
-
-/**
- * A [FunctionTypeImpl] that is lazily built from a [FunctionTypedElement] in
- * the element model.
- */
-class _FunctionTypeImplLazy extends FunctionTypeImpl {
-  /**
-   * The list of [typeArguments].
-   */
-  List<DartType> _typeArguments;
-
-  /**
-   * The list of [typeParameters], if it has been computed already.  Otherwise
-   * `null`.
-   */
-  List<TypeParameterElement> _typeParameters;
-
-  /**
-   * The return type of the function, or `null` if the return type should be
-   * accessed through the element.
-   */
-  final DartType _returnType;
-
-  /**
-   * The parameters to the function, or `null` if the parameters should be
-   * accessed through the element.
-   */
-  final List<ParameterElement> _parameters;
-
-  /**
-   * True if this type is the result of instantiating type parameters (and thus
-   * any type parameters bound by the typedef should be considered part of
-   * [typeParameters] rather than [typeFormals]).
-   */
-  final bool _isInstantiated;
-
-  @override
-  final List<FunctionTypeAliasElement> prunedTypedefs;
-
-  /**
-   * Private constructor.
-   */
-  _FunctionTypeImplLazy._(
-      FunctionTypedElement element,
-      String name,
-      this.prunedTypedefs,
-      this._typeArguments,
-      this._returnType,
-      this._parameters,
-      this._isInstantiated,
-      {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star})
-      : _typeParameters = null,
-        super._(element, name, nullabilitySuffix);
-
-  /**
-   * Return the base parameter elements of this function element.
-   */
-  List<ParameterElement> get baseParameters =>
-      _parameters ?? element.parameters;
-
-  /**
-   * Return the return type defined by this function's element.
-   */
-  DartType get baseReturnType => _returnType ?? element.returnType;
-
-  @override
-  bool get isInstantiated => _isInstantiated;
-
-  @override
-  List<FunctionTypeAliasElement> get newPrune {
-    Element element = this.element;
-    if (element is GenericFunctionTypeElement) {
-      element = (element as GenericFunctionTypeElement).enclosingElement;
-    }
-    if (element is FunctionTypeAliasElement && !element.isSynthetic) {
-      // This typedef should be pruned, along with anything that was previously
-      // pruned.
-      if (prunedTypedefs == null) {
-        return <FunctionTypeAliasElement>[element];
-      } else {
-        return new List<FunctionTypeAliasElement>.from(prunedTypedefs)
-          ..add(element);
-      }
-    } else {
-      // This is not a typedef, so nothing additional needs to be pruned.
-      return prunedTypedefs;
-    }
-  }
-
-  @override
-  List<String> get normalParameterNames {
-    return baseParameters
-        .where((parameter) => parameter.isRequiredPositional)
-        .map((parameter) => parameter.name)
-        .toList();
-  }
-
-  @override
-  List<String> get optionalParameterNames {
-    return baseParameters
-        .where((parameter) => parameter.isOptionalPositional)
-        .map((parameter) => parameter.name)
-        .toList();
-  }
-
-  @override
-  List<ParameterElement> get parameters {
-    var substitution = Substitution.fromPairs(typeParameters, typeArguments);
-
-    List<ParameterElement> baseParameters = this.baseParameters;
-    // no parameters, quick return
-    int parameterCount = baseParameters.length;
-    if (parameterCount == 0) {
-      return baseParameters;
-    }
-
-    // create specialized parameters
-    var specializedParams = new List<ParameterElement>(parameterCount);
-
-    var parameterTypes = TypeParameterTypeImpl.getTypes(typeParameters);
-    for (int i = 0; i < parameterCount; i++) {
-      var parameter = baseParameters[i];
-      if (parameter?.type == null) {
-        specializedParams[i] = parameter;
-        continue;
-      }
-
-      // Check if parameter type depends on defining type type arguments, or
-      // if it needs to be pruned.
-
-      if (parameter is FieldFormalParameterElement) {
-        // TODO(jmesserly): this seems like it won't handle pruning correctly.
-        specializedParams[i] =
-            new FieldFormalParameterMember(parameter, substitution);
-        continue;
-      }
-      var baseType = parameter.type as TypeImpl;
-      TypeImpl type;
-      if (typeArguments.isEmpty ||
-          typeArguments.length != typeParameters.length) {
-        type = baseType.pruned(newPrune);
-      } else {
-        type = baseType.substitute2(typeArguments, parameterTypes, newPrune);
-      }
-
-      specializedParams[i] = identical(type, baseType)
-          ? parameter
-          : new ParameterMember(parameter, substitution, type);
-    }
-    return specializedParams;
-  }
-
-  @override
-  DartType get returnType {
-    DartType baseReturnType = this.baseReturnType;
-    if (baseReturnType == null) {
-      // TODO(brianwilkerson) This is a patch. The return type should never be
-      // null and we need to understand why it is and fix it.
-      return DynamicTypeImpl.instance;
-    }
-    // If there are no arguments to substitute, or if the arguments size doesn't
-    // match the parameter size, return the base return type.
-    if (typeArguments.isEmpty ||
-        typeArguments.length != typeParameters.length) {
-      return (baseReturnType as TypeImpl).pruned(newPrune);
-    }
-    return (baseReturnType as TypeImpl).substitute2(typeArguments,
-        TypeParameterTypeImpl.getTypes(typeParameters), newPrune);
-  }
-
-  /**
-   * A list containing the actual types of the type arguments.
-   */
-  List<DartType> get typeArguments {
-    if (_typeArguments == null) {
-      // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
-      // make it generic, which will allow it to return List<DartType> instead
-      // of List<TypeParameterType>.
-      if (typeParameters.isEmpty) {
-        _typeArguments = const <DartType>[];
-      } else {
-        _typeArguments = new List<DartType>.from(
-            typeParameters.map((t) => t.type),
-            growable: false);
-      }
-    }
-    return _typeArguments;
-  }
-
-  @override
-  List<TypeParameterElement> get typeFormals {
-    if (_isInstantiated || element == null) {
-      return const <TypeParameterElement>[];
-    }
-    List<TypeParameterElement> baseTypeFormals = element.typeParameters;
-    int formalCount = baseTypeFormals.length;
-    if (formalCount == 0) {
-      return const <TypeParameterElement>[];
-    }
-
-    // Create type formals with specialized bounds.
-    // For example `<U extends T>` where T comes from an outer scope.
-    return TypeParameterMember.from(baseTypeFormals, this);
-  }
-
-  @override
-  List<TypeParameterElement> get typeParameters {
-    if (_typeParameters == null) {
-      // Combine the generic type variables from all enclosing contexts, except
-      // for this generic function's type variables. Those variables are
-      // tracked in [boundTypeParameters].
-      _typeParameters = <TypeParameterElement>[];
-
-      Element e = element;
-      while (e != null) {
-        // If a static method, skip the enclosing class type parameters.
-        if (e is MethodElement && e.isStatic) {
-          e = e.enclosingElement;
-        }
-        e = e.enclosingElement;
-        if (e is TypeParameterizedElement) {
-          _typeParameters.addAll(e.typeParameters);
-        }
-      }
-
-      if (_isInstantiated) {
-        // Once the type has been instantiated, type parameters defined at the
-        // site of the declaration of the method are no longer considered part
-        // [boundTypeParameters]; they are part of [typeParameters].
-        List<TypeParameterElement> parametersToAdd = element?.typeParameters;
-        if (parametersToAdd != null) {
-          _typeParameters.addAll(parametersToAdd);
-        }
-      }
-    }
-    return _typeParameters;
-  }
-
-  @override
-  FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
-    if (argumentTypes.length != typeFormals.length) {
-      throw new ArgumentError(
-          "argumentTypes.length (${argumentTypes.length}) != "
-          "typeFormals.length (${typeFormals.length})");
-    }
-    if (argumentTypes.isEmpty) {
-      return this;
-    }
-
-    // Given:
-    //     {U/T} <S> T -> S
-    // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
-    // and <S> represents the typeFormals.
-    //
-    // Now instantiate([V]), and the result should be:
-    //     {U/T, V/S} T -> S.
-    List<DartType> newTypeArgs = <DartType>[];
-    newTypeArgs.addAll(typeArguments);
-    newTypeArgs.addAll(argumentTypes);
-
-    return new _FunctionTypeImplLazy._(element, name, prunedTypedefs,
-        newTypeArgs, _returnType, _parameters, true,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  @override
-  FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
-    if (prune == null) {
-      return this;
-    } else if (prune.contains(element) ||
-        prune.contains(element.enclosingElement)) {
-      // Circularity found.  Prune the type declaration.
-      return new CircularFunctionTypeImpl();
-    } else {
-      // There should never be a reason to prune a type that has already been
-      // pruned, since pruning is only done when expanding a function type
-      // alias, and function type aliases are always expanded by starting with
-      // base types.
-      assert(this.prunedTypedefs == null);
-      List<DartType> typeArgs = typeArguments
-          .map((DartType t) => (t as TypeImpl).pruned(prune))
-          .toList(growable: false);
-      return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
-          _returnType, _parameters, _isInstantiated,
-          nullabilitySuffix: nullabilitySuffix);
-    }
-  }
-
-  @override
-  FunctionType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    if (argumentTypes.length != parameterTypes.length) {
-      throw new ArgumentError(
-          "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
-    }
-    Element element = this.element;
-    Element forCircularity = this.element;
-    if (element is GenericFunctionTypeElement &&
-        element.enclosingElement is FunctionTypeAliasElement) {
-      forCircularity = element.enclosingElement;
-    }
-    if (prune != null && prune.contains(forCircularity)) {
-      // Circularity found.  Prune the type declaration.
-      return new CircularFunctionTypeImpl();
-    }
-    if (argumentTypes.isEmpty) {
-      return this.pruned(prune);
-    }
-    List<DartType> typeArgs =
-        TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
-    return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
-        _returnType, _parameters, _isInstantiated,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
-    if (this.nullabilitySuffix == nullabilitySuffix) return this;
-    return _FunctionTypeImplLazy._(element, name, prunedTypedefs,
-        _typeArguments, _returnType, _parameters, _isInstantiated,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  @override
-  void _forEachParameterType(
-      ParameterKind kind, callback(String name, DartType type)) {
-    List<ParameterElement> parameters = baseParameters;
-    if (parameters.isEmpty) {
-      return;
-    }
-
-    List<DartType> typeParameters =
-        TypeParameterTypeImpl.getTypes(this.typeParameters);
-    int length = parameters.length;
-    for (int i = 0; i < length; i++) {
-      ParameterElement parameter = parameters[i];
-      // ignore: deprecated_member_use_from_same_package
-      if (parameter.parameterKind == kind) {
-        TypeImpl type = parameter.type ?? DynamicTypeImpl.instance;
-        if (typeArguments.isNotEmpty &&
-            typeArguments.length == typeParameters.length) {
-          type = type.substitute2(typeArguments, typeParameters, newPrune);
-        } else {
-          type = type.pruned(newPrune);
-        }
-
-        callback(parameter.name, type);
-      }
-    }
-  }
-}
-
-/// A [FunctionTypeImpl] that is not associated with any element in the element
-/// model.
-///
-/// In contrast to [_FunctionTypeImplLazy], all of the properties of a
-/// [_FunctionTypeImplStrict] are known at construction time.
-class _FunctionTypeImplStrict extends FunctionTypeImpl {
-  @override
-  final DartType returnType;
-
-  @override
-  final List<TypeParameterElement> typeFormals;
-
-  @override
-  final List<ParameterElement> parameters;
-
-  @override
-  final List<DartType> typeArguments;
-
-  _FunctionTypeImplStrict._(this.returnType, this.typeFormals, this.parameters,
-      {Element element,
-      List<DartType> typeArguments,
-      NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star})
-      : typeArguments = typeArguments ?? const <DartType>[],
-        super._(element, null, nullabilitySuffix);
-
-  @override
-  List<TypeParameterElement> get boundTypeParameters => typeFormals;
-
-  @override
-  FunctionTypedElement get element {
-    var element = super.element;
-    if (element is GenericTypeAliasElement) {
-      return element.function;
-    }
-    return element;
-  }
-
-  @override
-  bool get isInstantiated => throw new UnimplementedError('TODO(paulberry)');
-
-  @override
-  List<FunctionTypeAliasElement> get newPrune => const [];
-
-  @override
-  List<String> get normalParameterNames => parameters
-      .where((p) => p.isRequiredPositional)
-      .map((p) => p.name)
-      .toList();
-
-  @override
-  List<String> get optionalParameterNames => parameters
-      .where((p) => p.isOptionalPositional)
-      .map((p) => p.name)
-      .toList();
-
-  @override
-  List<FunctionTypeAliasElement> get prunedTypedefs => const [];
-
-  @override
-  List<TypeParameterElement> get typeParameters => const [] /*TODO(paulberry)*/;
-
-  @override
-  FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
-    if (argumentTypes.length != typeFormals.length) {
-      throw new ArgumentError(
-          "argumentTypes.length (${argumentTypes.length}) != "
-          "typeFormals.length (${typeFormals.length})");
-    }
-    if (argumentTypes.isEmpty) {
-      return this;
-    }
-
-    var substitution = Substitution.fromPairs(typeFormals, argumentTypes);
-
-    ParameterElement transformParameter(ParameterElement p) {
-      var type = p.type;
-      var newType = substitution.substituteType(type);
-      if (identical(newType, type)) return p;
-      return new ParameterElementImpl.synthetic(
-          p.name,
-          newType,
-          // ignore: deprecated_member_use_from_same_package
-          p.parameterKind)
-        ..isExplicitlyCovariant = p.isCovariant;
-    }
-
-    return new _FunctionTypeImplStrict._(
-        substitution.substituteType(returnType),
-        const [],
-        _transformOrShare(parameters, transformParameter),
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
-  FunctionType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
-    if (argumentTypes.length != parameterTypes.length) {
-      throw new ArgumentError(
-          "argumentTypes.length (${argumentTypes.length}) != "
-          "parameterTypes.length (${parameterTypes.length})");
-    }
-
-    var substitution = Substitution.fromPairs(
-      parameterTypes.map<TypeParameterElement>((t) => t.element).toList(),
-      argumentTypes,
-    );
-    return substitution.substituteType(this);
-  }
-
-  @override
-  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
-    if (this.nullabilitySuffix == nullabilitySuffix) return this;
-    return _FunctionTypeImplStrict._(returnType, typeFormals, parameters,
-        element: element,
-        typeArguments: typeArguments,
-        nullabilitySuffix: nullabilitySuffix);
-  }
-
-  @override
-  void _forEachParameterType(
-      ParameterKind kind, Function(String name, DartType type) callback) {
-    for (var parameter in parameters) {
-      // ignore: deprecated_member_use_from_same_package
-      if (parameter.parameterKind == kind) {
-        callback(parameter.name, parameter.type);
-      }
-    }
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index 566d6bb..adeeb1e 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -26,7 +27,10 @@
 
   var map = <TypeParameterElement, DartType>{};
   for (int i = 0; i < typeParameters.length; ++i) {
-    map[typeParameters[i]] = new TypeParameterTypeImpl(freshParameters[i]);
+    map[typeParameters[i]] = new TypeParameterTypeImpl(
+      freshParameters[i],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
   }
 
   var substitution = Substitution.fromMap(map);
@@ -116,6 +120,7 @@
           parameter.parameterKind,
         );
       }).toList(),
+      nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
     );
   }
 
@@ -240,7 +245,9 @@
       var element = elements[i];
       var freshElement = TypeParameterElementImpl(element.name, -1);
       freshElements[i] = freshElement;
-      var freshType = TypeParameterTypeImpl(freshElement);
+      var freshType = freshElement.instantiate(
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
       freshElement.type = freshType;
       substitution[element] = freshType;
     }
@@ -411,8 +418,14 @@
 
     if (this.useCounter == before) return type;
 
-    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters,
-        element: type.element, typeArguments: typeArguments);
+    return FunctionTypeImpl.synthetic(
+      returnType,
+      typeFormals,
+      parameters,
+      element: type.element,
+      typeArguments: typeArguments,
+      nullabilitySuffix: (type as TypeImpl).nullabilitySuffix,
+    );
   }
 
   @override
@@ -488,6 +501,7 @@
     }
 
     return new NamedTypeBuilder(
+      type.isNNBD,
       type.element,
       arguments,
       type.nullabilitySuffix,
@@ -496,7 +510,15 @@
 
   @override
   DartType visitTypeParameterType(TypeParameterType type) {
-    return getSubstitute(type.element) ?? type;
+    var argument = getSubstitute(type.element);
+    if (argument == null) {
+      return type;
+    }
+
+    var parameterSuffix = (type as TypeImpl).nullabilitySuffix;
+    var argumentSuffix = (argument as TypeImpl).nullabilitySuffix;
+    var nullability = _computeNullability(parameterSuffix, argumentSuffix);
+    return (argument as TypeImpl).withNullability(nullability);
   }
 
   @override
@@ -505,6 +527,30 @@
   @override
   DartType visitVoidType(VoidType type) => 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?
+  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;
+  }
+
   static ParameterElementImpl _parameterElement(
     ParameterElement parameter,
     DartType type,
diff --git a/pkg/analyzer/lib/src/dart/element/wrapped.dart b/pkg/analyzer/lib/src/dart/element/wrapped.dart
deleted file mode 100644
index 4d7e6e6..0000000
--- a/pkg/analyzer/lib/src/dart/element/wrapped.dart
+++ /dev/null
@@ -1,658 +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:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart' hide Directive;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-
-/// Implementation of [CompilationUnitElement] that wraps a
-/// [CompilationUnitElement] and defers all method calls to it.
-///
-/// This is intended to be used by the rare clients that must reimplement
-/// [CompilationUnitElement], so that they won't be broken if new methods are
-/// added.
-class WrappedCompilationUnitElement implements CompilationUnitElement {
-  final CompilationUnitElement wrappedUnit;
-
-  WrappedCompilationUnitElement(this.wrappedUnit);
-
-  @override
-  List<PropertyAccessorElement> get accessors => wrappedUnit.accessors;
-
-  @override
-  AnalysisContext get context => wrappedUnit.context;
-
-  @override
-  String get displayName => wrappedUnit.displayName;
-
-  @override
-  String get documentationComment => wrappedUnit.documentationComment;
-
-  @override
-  LibraryElement get enclosingElement => wrappedUnit.enclosingElement;
-
-  @override
-  List<ClassElement> get enums => wrappedUnit.enums;
-
-  @override
-  List<ExtensionElement> get extensions => wrappedUnit.extensions;
-
-  @override
-  List<FunctionElement> get functions => wrappedUnit.functions;
-
-  @override
-  List<FunctionTypeAliasElement> get functionTypeAliases =>
-      wrappedUnit.functionTypeAliases;
-
-  @override
-  bool get hasAlwaysThrows => wrappedUnit.hasAlwaysThrows;
-
-  @override
-  bool get hasDeprecated => wrappedUnit.hasDeprecated;
-
-  @override
-  bool get hasFactory => wrappedUnit.hasFactory;
-
-  @override
-  bool get hasIsTest => wrappedUnit.hasIsTest;
-
-  @override
-  bool get hasIsTestGroup => wrappedUnit.hasIsTestGroup;
-
-  @override
-  bool get hasJS => wrappedUnit.hasJS;
-
-  @override
-  bool get hasLiteral => wrappedUnit.hasLiteral;
-
-  @override
-  bool get hasLoadLibraryFunction => wrappedUnit.hasLoadLibraryFunction;
-
-  @override
-  bool get hasMustCallSuper => wrappedUnit.hasMustCallSuper;
-
-  @override
-  bool get hasOptionalTypeArgs => wrappedUnit.hasOptionalTypeArgs;
-
-  @override
-  bool get hasOverride => wrappedUnit.hasOverride;
-
-  @override
-  bool get hasProtected => wrappedUnit.hasProtected;
-
-  @override
-  bool get hasRequired => wrappedUnit.hasRequired;
-
-  @override
-  bool get hasSealed => wrappedUnit.hasSealed;
-
-  @override
-  bool get hasVisibleForTemplate => wrappedUnit.hasVisibleForTemplate;
-
-  @override
-  bool get hasVisibleForTesting => wrappedUnit.hasVisibleForTesting;
-
-  @override
-  int get id => wrappedUnit.id;
-
-  @override
-  bool get isAlwaysThrows => hasAlwaysThrows;
-
-  @override
-  bool get isDeprecated => hasDeprecated;
-
-  @override
-  bool get isFactory => hasFactory;
-
-  @override
-  bool get isJS => hasJS;
-
-  @override
-  bool get isOverride => hasOverride;
-
-  @override
-  bool get isPrivate => wrappedUnit.isPrivate;
-
-  @override
-  bool get isProtected => hasProtected;
-
-  @override
-  bool get isPublic => wrappedUnit.isPublic;
-
-  @override
-  bool get isRequired => hasRequired;
-
-  @override
-  bool get isSynthetic => wrappedUnit.isSynthetic;
-
-  @override
-  bool get isVisibleForTesting => hasVisibleForTesting;
-
-  @override
-  ElementKind get kind => wrappedUnit.kind;
-
-  @override
-  LibraryElement get library => wrappedUnit.library;
-
-  @override
-  Source get librarySource => wrappedUnit.librarySource;
-
-  @override
-  LineInfo get lineInfo => wrappedUnit.lineInfo;
-
-  @override
-  ElementLocation get location => wrappedUnit.location;
-
-  @override
-  List<ElementAnnotation> get metadata => wrappedUnit.metadata;
-
-  @override
-  List<ClassElement> get mixins => wrappedUnit.mixins;
-
-  @override
-  String get name => wrappedUnit.name;
-
-  @override
-  int get nameLength => wrappedUnit.nameLength;
-
-  @override
-  int get nameOffset => wrappedUnit.nameOffset;
-
-  @override
-  AnalysisSession get session => wrappedUnit.session;
-
-  @override
-  Source get source => wrappedUnit.source;
-
-  @override
-  List<TopLevelVariableElement> get topLevelVariables =>
-      wrappedUnit.topLevelVariables;
-
-  @override
-  List<ClassElement> get types => wrappedUnit.types;
-
-  @deprecated
-  @override
-  CompilationUnit get unit => wrappedUnit.unit;
-
-  @override
-  String get uri => wrappedUnit.uri;
-
-  @override
-  int get uriEnd => wrappedUnit.uriEnd;
-
-  @override
-  int get uriOffset => wrappedUnit.uriOffset;
-
-  @override
-  T accept<T>(ElementVisitor<T> visitor) => wrappedUnit
-      .accept(visitor); // ignore: deprecated_member_use_from_same_package
-
-  @override
-  String computeDocumentationComment() {
-    // ignore: deprecated_member_use_from_same_package
-    return wrappedUnit.computeDocumentationComment();
-  }
-
-  @deprecated
-  @override
-  CompilationUnit computeNode() => wrappedUnit.computeNode();
-
-  @override
-  E getAncestor<E extends Element>(Predicate<Element> predicate) =>
-      wrappedUnit.getAncestor(predicate);
-
-  @override
-  ClassElement getEnum(String name) => wrappedUnit.getEnum(name);
-
-  @override
-  String getExtendedDisplayName(String shortName) =>
-      wrappedUnit.getExtendedDisplayName(shortName);
-
-  @override
-  ClassElement getType(String className) => wrappedUnit.getType(className);
-
-  @override
-  bool isAccessibleIn(LibraryElement library) =>
-      wrappedUnit.isAccessibleIn(library);
-
-  @override
-  void visitChildren(ElementVisitor visitor) =>
-      wrappedUnit.visitChildren(visitor);
-}
-
-/// Implementation of [ImportElement] that wraps an [ImportElement] and defers
-/// all method calls to it.
-///
-/// This is intended to be used by the rare clients that must reimplement
-/// [ImportElement], so that they won't be broken if new methods are added.
-class WrappedImportElement implements ImportElement {
-  final ImportElement wrappedImport;
-
-  WrappedImportElement(this.wrappedImport);
-
-  @override
-  List<NamespaceCombinator> get combinators => wrappedImport.combinators;
-
-  @override
-  AnalysisContext get context => wrappedImport.context;
-
-  @override
-  String get displayName => wrappedImport.displayName;
-
-  @override
-  String get documentationComment => wrappedImport.documentationComment;
-
-  @override
-  LibraryElement get enclosingElement => wrappedImport.enclosingElement;
-
-  @override
-  bool get hasAlwaysThrows => wrappedImport.hasAlwaysThrows;
-
-  @override
-  bool get hasDeprecated => wrappedImport.hasDeprecated;
-
-  @override
-  bool get hasFactory => wrappedImport.hasFactory;
-
-  @override
-  bool get hasIsTest => wrappedImport.hasIsTest;
-
-  @override
-  bool get hasIsTestGroup => wrappedImport.hasIsTestGroup;
-
-  @override
-  bool get hasJS => wrappedImport.hasJS;
-
-  @override
-  bool get hasLiteral => wrappedImport.hasLiteral;
-
-  @override
-  bool get hasMustCallSuper => wrappedImport.hasMustCallSuper;
-
-  @override
-  bool get hasOptionalTypeArgs => wrappedImport.hasOptionalTypeArgs;
-
-  @override
-  bool get hasOverride => wrappedImport.hasOverride;
-
-  @override
-  bool get hasProtected => wrappedImport.hasProtected;
-
-  @override
-  bool get hasRequired => wrappedImport.hasRequired;
-
-  @override
-  bool get hasSealed => wrappedImport.hasSealed;
-
-  @override
-  bool get hasVisibleForTemplate => wrappedImport.hasVisibleForTemplate;
-
-  @override
-  bool get hasVisibleForTesting => wrappedImport.hasVisibleForTesting;
-
-  @override
-  int get id => wrappedImport.id;
-
-  @override
-  LibraryElement get importedLibrary => wrappedImport.importedLibrary;
-
-  @override
-  bool get isAlwaysThrows => hasAlwaysThrows;
-
-  @override
-  bool get isDeferred => wrappedImport.isDeferred;
-
-  @override
-  bool get isDeprecated => hasDeprecated;
-
-  @override
-  bool get isFactory => hasFactory;
-
-  @override
-  bool get isJS => hasJS;
-
-  @override
-  bool get isOverride => hasOverride;
-
-  @override
-  bool get isPrivate => wrappedImport.isPrivate;
-
-  @override
-  bool get isProtected => hasProtected;
-
-  @override
-  bool get isPublic => wrappedImport.isPublic;
-
-  @override
-  bool get isRequired => hasRequired;
-
-  @override
-  bool get isSynthetic => wrappedImport.isSynthetic;
-
-  @override
-  bool get isVisibleForTesting => hasVisibleForTesting;
-
-  @override
-  ElementKind get kind => wrappedImport.kind;
-
-  @override
-  LibraryElement get library => wrappedImport.library;
-
-  @override
-  Source get librarySource => wrappedImport.librarySource;
-
-  @override
-  ElementLocation get location => wrappedImport.location;
-
-  @override
-  List<ElementAnnotation> get metadata => wrappedImport.metadata;
-
-  @override
-  String get name => wrappedImport.name;
-
-  @override
-  int get nameLength => wrappedImport.nameLength;
-
-  @override
-  int get nameOffset => wrappedImport.nameOffset;
-
-  @override
-  Namespace get namespace => wrappedImport.namespace;
-
-  @override
-  PrefixElement get prefix => wrappedImport.prefix;
-
-  @override
-  int get prefixOffset => wrappedImport.prefixOffset;
-
-  @override
-  AnalysisSession get session => wrappedImport.session;
-
-  @override
-  Source get source => wrappedImport.source;
-
-  @deprecated
-  @override
-  CompilationUnit get unit => wrappedImport.unit;
-
-  @override
-  String get uri => wrappedImport.uri;
-
-  @override
-  int get uriEnd => wrappedImport.uriEnd;
-
-  @override
-  int get uriOffset => wrappedImport.uriOffset;
-
-  @override
-  T accept<T>(ElementVisitor<T> visitor) => wrappedImport.accept(visitor);
-
-  @override
-  String computeDocumentationComment() => wrappedImport
-      .computeDocumentationComment(); // ignore: deprecated_member_use_from_same_package
-
-  @deprecated
-  @override
-  AstNode computeNode() => wrappedImport.computeNode();
-
-  @override
-  E getAncestor<E extends Element>(Predicate<Element> predicate) =>
-      wrappedImport.getAncestor(predicate);
-
-  @override
-  String getExtendedDisplayName(String shortName) =>
-      wrappedImport.getExtendedDisplayName(shortName);
-
-  @override
-  bool isAccessibleIn(LibraryElement library) =>
-      wrappedImport.isAccessibleIn(library);
-
-  @override
-  void visitChildren(ElementVisitor visitor) =>
-      wrappedImport.visitChildren(visitor);
-}
-
-/// Implementation of [LibraryElement] that wraps a [LibraryElement] and defers
-/// all method calls to it.
-///
-/// This is intended to be used by the rare clients that must reimplement
-/// [LibraryElement], so that they won't be broken if new methods are added.
-class WrappedLibraryElement implements LibraryElement {
-  final LibraryElement wrappedLib;
-
-  WrappedLibraryElement(this.wrappedLib);
-
-  @override
-  AnalysisContext get context => wrappedLib.context;
-
-  @override
-  CompilationUnitElement get definingCompilationUnit =>
-      wrappedLib.definingCompilationUnit;
-
-  @override
-  String get displayName => wrappedLib.displayName;
-
-  @override
-  String get documentationComment => wrappedLib.documentationComment;
-
-  @override
-  Element get enclosingElement => wrappedLib.enclosingElement;
-
-  @override
-  FunctionElement get entryPoint => wrappedLib.entryPoint;
-
-  @override
-  List<LibraryElement> get exportedLibraries => wrappedLib.exportedLibraries;
-
-  @override
-  Namespace get exportNamespace => wrappedLib.exportNamespace;
-
-  @override
-  List<ExportElement> get exports => wrappedLib.exports;
-
-  @override
-  bool get hasAlwaysThrows => wrappedLib.hasAlwaysThrows;
-
-  @override
-  bool get hasDeprecated => wrappedLib.hasDeprecated;
-
-  @override
-  bool get hasExtUri => wrappedLib.hasExtUri;
-
-  @override
-  bool get hasFactory => wrappedLib.hasFactory;
-
-  @override
-  bool get hasIsTest => wrappedLib.hasIsTest;
-
-  @override
-  bool get hasIsTestGroup => wrappedLib.hasIsTestGroup;
-
-  @override
-  bool get hasJS => wrappedLib.hasJS;
-
-  @override
-  bool get hasLiteral => wrappedLib.hasLiteral;
-
-  @override
-  bool get hasLoadLibraryFunction => wrappedLib.hasLoadLibraryFunction;
-
-  @override
-  bool get hasMustCallSuper => wrappedLib.hasMustCallSuper;
-
-  @override
-  bool get hasOptionalTypeArgs => wrappedLib.hasOptionalTypeArgs;
-
-  @override
-  bool get hasOverride => wrappedLib.hasOverride;
-
-  @override
-  bool get hasProtected => wrappedLib.hasProtected;
-
-  @override
-  bool get hasRequired => wrappedLib.hasRequired;
-
-  @override
-  bool get hasSealed => wrappedLib.hasSealed;
-
-  @override
-  bool get hasVisibleForTemplate => wrappedLib.hasVisibleForTemplate;
-
-  @override
-  bool get hasVisibleForTesting => wrappedLib.hasVisibleForTesting;
-
-  @override
-  int get id => wrappedLib.id;
-
-  @override
-  String get identifier => wrappedLib.identifier;
-
-  @override
-  List<LibraryElement> get importedLibraries => wrappedLib.importedLibraries;
-
-  @override
-  List<ImportElement> get imports => wrappedLib.imports;
-
-  @override
-  bool get isAlwaysThrows => hasAlwaysThrows;
-
-  @override
-  bool get isBrowserApplication => wrappedLib.isBrowserApplication;
-
-  @override
-  bool get isDartAsync => wrappedLib.isDartAsync;
-
-  @override
-  bool get isDartCore => wrappedLib.isDartCore;
-
-  @override
-  bool get isDeprecated => hasDeprecated;
-
-  @override
-  bool get isFactory => hasFactory;
-
-  @override
-  bool get isInSdk => wrappedLib.isInSdk;
-
-  @override
-  bool get isJS => hasJS;
-
-  @override
-  bool get isNonNullableByDefault => wrappedLib.isNonNullableByDefault;
-
-  @override
-  bool get isOverride => hasOverride;
-
-  @override
-  bool get isPrivate => wrappedLib.isPrivate;
-
-  @override
-  bool get isProtected => hasProtected;
-
-  @override
-  bool get isPublic => wrappedLib.isPublic;
-
-  @override
-  bool get isRequired => hasRequired;
-
-  @override
-  bool get isSynthetic => wrappedLib.isSynthetic;
-
-  @override
-  bool get isVisibleForTesting => hasVisibleForTesting;
-
-  @override
-  ElementKind get kind => wrappedLib.kind;
-
-  @override
-  LibraryElement get library => wrappedLib.library;
-
-  @override
-  List<LibraryElement> get libraryCycle => wrappedLib.libraryCycle;
-
-  @override
-  Source get librarySource => wrappedLib.librarySource;
-
-  @override
-  FunctionElement get loadLibraryFunction => wrappedLib.loadLibraryFunction;
-
-  @override
-  ElementLocation get location => wrappedLib.location;
-
-  @override
-  List<ElementAnnotation> get metadata => wrappedLib.metadata;
-
-  @override
-  String get name => wrappedLib.name;
-
-  @override
-  int get nameLength => wrappedLib.nameLength;
-
-  @override
-  int get nameOffset => wrappedLib.nameOffset;
-
-  @override
-  List<CompilationUnitElement> get parts => wrappedLib.parts;
-
-  @override
-  List<PrefixElement> get prefixes => wrappedLib.prefixes;
-
-  @override
-  Namespace get publicNamespace => wrappedLib.publicNamespace;
-
-  @override
-  AnalysisSession get session => wrappedLib.session;
-
-  @override
-  Source get source => wrappedLib.source;
-
-  @override
-  Iterable<Element> get topLevelElements => wrappedLib.topLevelElements;
-
-  @deprecated
-  @override
-  CompilationUnit get unit => wrappedLib.unit;
-
-  @override
-  List<CompilationUnitElement> get units => wrappedLib.units;
-
-  @override
-  T accept<T>(ElementVisitor<T> visitor) => wrappedLib.accept(visitor);
-
-  @override
-  String computeDocumentationComment() => wrappedLib
-      .computeDocumentationComment(); // ignore: deprecated_member_use_from_same_package
-
-  @deprecated
-  @override
-  AstNode computeNode() => wrappedLib.computeNode();
-
-  @override
-  E getAncestor<E extends Element>(Predicate<Element> predicate) =>
-      wrappedLib.getAncestor(predicate);
-
-  @override
-  String getExtendedDisplayName(String shortName) =>
-      wrappedLib.getExtendedDisplayName(shortName);
-
-  @override
-  List<ImportElement> getImportsWithPrefix(PrefixElement prefix) =>
-      wrappedLib.getImportsWithPrefix(prefix);
-
-  @override
-  ClassElement getType(String className) => wrappedLib.getType(className);
-
-  @override
-  bool isAccessibleIn(LibraryElement library) =>
-      wrappedLib.isAccessibleIn(library);
-
-  @override
-  void visitChildren(ElementVisitor visitor) =>
-      wrappedLib.visitChildren(visitor);
-}
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index 8cdcd7b..3687f54 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -124,8 +124,9 @@
   static const FfiCode MUST_BE_A_NATIVE_FUNCTION_TYPE = const FfiCode(
       name: 'MUST_BE_A_NATIVE_FUNCTION_TYPE',
       message:
-          "The type '{0}' given to {1} must be a valid `dart:ffi` native function type.",
-      correction: "Try changing the type to only use members for `dart:ffi`.");
+          "The type '{0}' given to '{1}' must be a valid 'dart:ffi' native "
+          "function type.",
+      correction: "Try changing the type to only use members for 'dart:ffi'.");
 
   /**
    * Parameters:
@@ -150,25 +151,14 @@
       correction: "Try changing the type argument to be a constant type.");
 
   /**
-   * No parameters.
-   */
-  static const FfiCode NON_CONSTANT_TYPE_ARGUMENT_TO_POINTER = const FfiCode(
-      name: 'NON_CONSTANT_TYPE_ARGUMENT_TO_POINTER',
-      message:
-          "The type argument for the pointer must be a compile time constant "
-          "but type parameters are not constants.",
-      correction: "Try changing the type argument to be a constant type.");
-
-  /**
    * Parameters:
    * 0: the type that should be a valid dart:ffi native type.
    */
   static const FfiCode NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER =
       const FfiCode(
           name: 'NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER',
-          message:
-              "The type argument for the pointer, '{0}' must be a 'NativeFunction' in "
-              "order to use 'asFunction'.",
+          message: "The type argument for the pointer '{0}' must be a "
+              "'NativeFunction' in order to use 'asFunction'.",
           correction:
               "Try changing the type argument to be a 'NativeFunction'.");
 
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 003cc29..291e8b08 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -242,10 +242,10 @@
    * When "strict-inference" is enabled, collection literal types must be
    * inferred via the context type, or have type arguments.
    */
-  static const HintCode INFERENCE_FAILURE_ON_COLLECTION_LITERAL = HintCode(
-      'INFERENCE_FAILURE_ON_COLLECTION_LITERAL',
-      "The type argument(s) of '{0}' can't be inferred.",
-      correction: "Use explicit type argument(s) for '{0}'.");
+  static const HintCode INFERENCE_FAILURE_ON_COLLECTION_LITERAL =
+      const HintCode('INFERENCE_FAILURE_ON_COLLECTION_LITERAL',
+          "The type argument(s) of '{0}' can't be inferred.",
+          correction: "Use explicit type argument(s) for '{0}'.");
 
   /**
    * When "strict-inference" is enabled, recursive local functions, top-level
@@ -254,17 +254,17 @@
    *
    * https://github.com/dart-lang/language/blob/master/resources/type-system/strict-inference.md
    */
-  static const HintCode INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE = HintCode(
-      'INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE',
-      "The return type of '{0}' cannot be inferred.",
-      correction: "Declare the return type of '{0}'.");
+  static const HintCode INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE =
+      const HintCode('INFERENCE_FAILURE_ON_FUNCTION_RETURN_TYPE',
+          "The return type of '{0}' cannot be inferred.",
+          correction: "Declare the return type of '{0}'.");
 
   /**
    * When "strict-inference" is enabled, types in instance creation
    * (constructor calls) must be inferred via the context type, or have type
    * arguments.
    */
-  static const HintCode INFERENCE_FAILURE_ON_INSTANCE_CREATION = HintCode(
+  static const HintCode INFERENCE_FAILURE_ON_INSTANCE_CREATION = const HintCode(
       'INFERENCE_FAILURE_ON_INSTANCE_CREATION',
       "The type argument(s) of '{0}' can't be inferred.",
       correction: "Use explicit type argument(s) for '{0}'.");
@@ -357,6 +357,32 @@
       hasPublishedDocs: true);
 
   /**
+   * This hint is generated anywhere where `@nonVirtual` annotates something
+   * other than a non-abstract instance member in a class or mixin.
+   *
+   * Parameters:
+   * 0: the name of the member
+   */
+  static const HintCode INVALID_NON_VIRTUAL_ANNOTATION = const HintCode(
+      'INVALID_NON_VIRTUAL_ANNOTATION',
+      "The member '{0}' can't be '@nonVirtual' because it isn't a concrete "
+          "instance member.",
+      correction: "Try removing @nonVirtual.");
+
+  /**
+   * This hint is generated anywhere where an instance member annotated with
+   * `@nonVirtual` is overridden in a subclass.
+   *
+   * Parameters:
+   * 0: the name of the member
+   * 1: the name of the defining class
+   */
+  static const HintCode INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER = const HintCode(
+      'INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER',
+      "The member '{0}' is declared non-virtual in '{1}' and can't be "
+          "overridden in subclasses.");
+
+  /**
    * This hint is generated anywhere where `@required` annotates a named
    * parameter with a default value.
    *
@@ -561,7 +587,7 @@
   // The following code produces this diagnostic:
   //
   // ```dart
-  // [!int!] f(int x) {
+  // int [!f!](int x) {
   //   if (x < 0) {
   //     return 0;
   //   }
@@ -1364,7 +1390,7 @@
    * When "strict-raw-types" is enabled, raw types must be inferred via the
    * context type, or have type arguments.
    */
-  static const HintCode STRICT_RAW_TYPE = HintCode('STRICT_RAW_TYPE',
+  static const HintCode STRICT_RAW_TYPE = const HintCode('STRICT_RAW_TYPE',
       "The generic type '{0}' should have explicit type arguments but doesn't.",
       correction: "Use explicit type arguments for '{0}'.");
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 85eaf09..5f1bace 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -7,7 +7,8 @@
  */
 import 'package:analyzer/error/error.dart';
 
-export 'package:front_end/src/scanner/errors.dart' show ScannerErrorCode;
+export 'package:_fe_analyzer_shared/src/scanner/errors.dart'
+    show ScannerErrorCode;
 
 part 'syntactic_errors.g.dart';
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index a41d8f6..4c3462b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -148,7 +148,10 @@
       substitution,
     );
 
-    if (!_typeSystem.isAssignableTo(receiverType, node.extendedType)) {
+    if (receiverType.isVoid) {
+      _errorReporter.reportErrorForNode(
+          StaticWarningCode.USE_OF_VOID_RESULT, receiverExpression);
+    } else if (!_typeSystem.isAssignableTo(receiverType, node.extendedType)) {
       _errorReporter.reportErrorForNode(
         CompileTimeErrorCode.EXTENSION_OVERRIDE_ARGUMENT_NOT_ASSIGNABLE,
         receiverExpression,
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 6cfd32a..15de2d3 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -2,14 +2,37 @@
 // for 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/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
 import 'package:analyzer/src/generated/variable_type_provider.dart';
-import 'package:front_end/src/fasta/flow_analysis/flow_analysis.dart';
+
+/// Data gathered by flow analysis, retained for testing purposes.
+class FlowAnalysisDataForTesting {
+  /// The list of nodes, [Expression]s or [Statement]s, that cannot be reached,
+  /// for example because a previous statement always exits.
+  final List<AstNode> unreachableNodes = [];
+
+  /// The list of [FunctionBody]s that don't complete, for example because
+  /// there is a `return` statement at the end of the function body block.
+  final List<FunctionBody> functionBodiesThatDontComplete = [];
+
+  /// The list of [Expression]s representing variable accesses that occur before
+  /// the corresponding variable has been definitely assigned.
+  final List<AstNode> unassignedNodes = [];
+
+  /// For each top level or class level declaration, the assigned variables
+  /// information that was computed for it.
+  final Map<Declaration,
+          AssignedVariablesForTesting<AstNode, PromotableElement>>
+      assignedVariables = {};
+}
 
 /// The helper for performing flow analysis during resolution.
 ///
@@ -23,26 +46,40 @@
   /// Precomputed sets of potentially assigned variables.
   AssignedVariables<AstNode, PromotableElement> assignedVariables;
 
-  /// The result for post-resolution stages of analysis.
-  final FlowAnalysisResult result;
+  /// The result for post-resolution stages of analysis, for testing only.
+  final FlowAnalysisDataForTesting dataForTesting;
 
   /// The current flow, when resolving a function body, or `null` otherwise.
-  FlowAnalysis<Statement, Expression, PromotableElement, DartType> flow;
+  FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>
+      flow;
 
   factory FlowAnalysisHelper(TypeSystem typeSystem, bool retainDataForTesting) {
     return FlowAnalysisHelper._(TypeSystemTypeOperations(typeSystem),
-        retainDataForTesting ? FlowAnalysisResult() : null);
+        retainDataForTesting ? FlowAnalysisDataForTesting() : null);
   }
 
-  FlowAnalysisHelper._(this._typeOperations, this.result);
+  FlowAnalysisHelper._(this._typeOperations, this.dataForTesting);
 
   LocalVariableTypeProvider get localVariableTypeProvider {
     return _LocalVariableTypeProvider(this);
   }
 
+  void asExpression(AsExpression node) {
+    if (flow == null) return;
+
+    var expression = node.expression;
+    var typeAnnotation = node.type;
+
+    flow.asExpression_end(expression, typeAnnotation.type);
+  }
+
   VariableElement assignmentExpression(AssignmentExpression node) {
     if (flow == null) return null;
 
+    if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
+      flow.ifNullExpression_rightBegin(node.leftHandSide);
+    }
+
     var left = node.leftHandSide;
 
     if (left is SimpleIdentifier) {
@@ -55,11 +92,15 @@
     return null;
   }
 
-  void assignmentExpression_afterRight(
-      VariableElement localElement, Expression right) {
-    if (localElement == null) return;
+  void assignmentExpression_afterRight(AssignmentExpression node,
+      VariableElement localElement, DartType writtenType) {
+    if (localElement != null) {
+      flow.write(localElement, writtenType);
+    }
 
-    flow.write(localElement);
+    if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
+      flow.ifNullExpression_end();
+    }
   }
 
   void breakStatement(BreakStatement node) {
@@ -73,14 +114,8 @@
     if (flow == null) return;
     if (flow.isReachable) return;
 
-    if (result != null) {
-      // Ignore the [node] if it is fully covered by the last unreachable.
-      if (result.unreachableNodes.isNotEmpty) {
-        var last = result.unreachableNodes.last;
-        if (node.offset >= last.offset && node.end <= last.end) return;
-      }
-
-      result.unreachableNodes.add(node);
+    if (dataForTesting != null) {
+      dataForTesting.unreachableNodes.add(node);
     }
   }
 
@@ -91,15 +126,15 @@
 
   void executableDeclaration_enter(
       Declaration node, FormalParameterList parameters, bool isClosure) {
+    if (isClosure) {
+      flow.functionExpression_begin(node);
+    }
+
     if (parameters != null) {
       for (var parameter in parameters.parameters) {
         flow.initialize(parameter.declaredElement);
       }
     }
-
-    if (isClosure) {
-      flow.functionExpression_begin(assignedVariables.writtenInNode(node));
-    }
   }
 
   void executableDeclaration_exit(FunctionBody body, bool isClosure) {
@@ -107,7 +142,7 @@
       flow.functionExpression_end();
     }
     if (!flow.isReachable) {
-      result?.functionBodiesThatDontComplete?.add(body);
+      dataForTesting?.functionBodiesThatDontComplete?.add(body);
     }
   }
 
@@ -116,8 +151,7 @@
   }
 
   void for_conditionBegin(AstNode node, Expression condition) {
-    flow.for_conditionBegin(assignedVariables.writtenInNode(node),
-        assignedVariables.capturedInNode(node));
+    flow.for_conditionBegin(node);
   }
 
   void isExpression(IsExpression node) {
@@ -126,17 +160,12 @@
     var expression = node.expression;
     var typeAnnotation = node.type;
 
-    if (expression is SimpleIdentifier) {
-      var element = expression.staticElement;
-      if (element is VariableElement) {
-        flow.isExpression_end(
-          node,
-          element,
-          node.notOperator != null,
-          typeAnnotation.type,
-        );
-      }
-    }
+    flow.isExpression_end(
+      node,
+      expression,
+      node.notOperator != null,
+      typeAnnotation.type,
+    );
   }
 
   bool isPotentiallyNonNullableLocalReadBeforeWrite(SimpleIdentifier node) {
@@ -151,7 +180,7 @@
       if (typeSystem.isPotentiallyNonNullable(element.type)) {
         var isUnassigned = !flow.isAssigned(element);
         if (isUnassigned) {
-          result?.unassignedNodes?.add(node);
+          dataForTesting?.unassignedNodes?.add(node);
         }
         // Note: in principle we could make this slightly more performant by
         // checking element.isLate earlier, but we would lose the ability to
@@ -170,11 +199,13 @@
       Declaration node, FormalParameterList parameters, FunctionBody body) {
     assert(node != null);
     assert(flow == null);
-    assignedVariables = computeAssignedVariables(node, parameters);
-    flow = FlowAnalysis<Statement, Expression, PromotableElement, DartType>(
-        _typeOperations,
-        assignedVariables.writtenAnywhere,
-        assignedVariables.capturedAnywhere);
+    assignedVariables = computeAssignedVariables(node, parameters,
+        retainDataForTesting: dataForTesting != null);
+    if (dataForTesting != null) {
+      dataForTesting.assignedVariables[node] = assignedVariables;
+    }
+    flow = FlowAnalysis<AstNode, Statement, Expression, PromotableElement,
+        DartType>(_typeOperations, assignedVariables);
   }
 
   void topLevelDeclaration_exit() {
@@ -202,8 +233,12 @@
 
   /// Computes the [AssignedVariables] map for the given [node].
   static AssignedVariables<AstNode, PromotableElement> computeAssignedVariables(
-      Declaration node, FormalParameterList parameters) {
-    var assignedVariables = AssignedVariables<AstNode, PromotableElement>();
+      Declaration node, FormalParameterList parameters,
+      {bool retainDataForTesting = false}) {
+    AssignedVariables<AstNode, PromotableElement> assignedVariables =
+        retainDataForTesting
+            ? AssignedVariablesForTesting()
+            : AssignedVariables();
     var assignedVariablesVisitor = _AssignedVariablesVisitor(assignedVariables);
     assignedVariablesVisitor._declareParameters(parameters);
     node.visitChildren(assignedVariablesVisitor);
@@ -246,24 +281,9 @@
   }
 }
 
-/// The result of performing flow analysis on a unit.
-class FlowAnalysisResult {
-  /// The list of nodes, [Expression]s or [Statement]s, that cannot be reached,
-  /// for example because a previous statement always exits.
-  final List<AstNode> unreachableNodes = [];
-
-  /// The list of [FunctionBody]s that don't complete, for example because
-  /// there is a `return` statement at the end of the function body block.
-  final List<FunctionBody> functionBodiesThatDontComplete = [];
-
-  /// The list of [Expression]s representing variable accesses that occur before
-  /// the corresponding variable has been definitely assigned.
-  final List<AstNode> unassignedNodes = [];
-}
-
 class TypeSystemTypeOperations
     implements TypeOperations<PromotableElement, DartType> {
-  final TypeSystem typeSystem;
+  final Dart2TypeSystem typeSystem;
 
   TypeSystemTypeOperations(this.typeSystem);
 
@@ -283,6 +303,11 @@
   }
 
   @override
+  DartType tryPromoteToType(DartType to, DartType from) {
+    return typeSystem.tryPromoteToType(to, from);
+  }
+
+  @override
   DartType variableType(PromotableElement variable) {
     return variable.type;
   }
@@ -352,14 +377,18 @@
     }
     assignedVariables.beginNode();
     _declareParameters(node.functionExpression.parameters);
-    // Note: we bypass this.visitFunctionExpression so that the function
-    // expression isn't mistaken for a closure.
-    super.visitFunctionExpression(node.functionExpression);
+    super.visitFunctionDeclaration(node);
     assignedVariables.endNode(node, isClosure: true);
   }
 
   @override
   void visitFunctionExpression(FunctionExpression node) {
+    if (node.parent is FunctionDeclaration) {
+      // A FunctionExpression just inside a FunctionDeclaration is an analyzer
+      // artifact--it doesn't correspond to a separate closure.  So skip our
+      // usual processing.
+      return super.visitFunctionExpression(node);
+    }
     assignedVariables.beginNode();
     _declareParameters(node.parameters);
     super.visitFunctionExpression(node);
@@ -372,6 +401,34 @@
   }
 
   @override
+  void visitPostfixExpression(PostfixExpression node) {
+    super.visitPostfixExpression(node);
+    if (node.operator.type.isIncrementOperator) {
+      var operand = node.operand;
+      if (operand is SimpleIdentifier) {
+        var element = operand.staticElement;
+        if (element is PromotableElement) {
+          assignedVariables.write(element);
+        }
+      }
+    }
+  }
+
+  @override
+  void visitPrefixExpression(PrefixExpression node) {
+    super.visitPrefixExpression(node);
+    if (node.operator.type.isIncrementOperator) {
+      var operand = node.operand;
+      if (operand is SimpleIdentifier) {
+        var element = operand.staticElement;
+        if (element is PromotableElement) {
+          assignedVariables.write(element);
+        }
+      }
+    }
+  }
+
+  @override
   void visitSwitchStatement(SwitchStatement node) {
     var expression = node.expression;
     var members = node.members;
@@ -385,13 +442,16 @@
 
   @override
   void visitTryStatement(TryStatement node) {
+    var finallyBlock = node.finallyBlock;
+    bool isDesugared = node.catchClauses.isNotEmpty && finallyBlock != null;
     assignedVariables.beginNode();
+    if (isDesugared) assignedVariables.beginNode();
     node.body.accept(this);
     assignedVariables.endNode(node.body);
 
     node.catchClauses.accept(this);
+    if (isDesugared) assignedVariables.endNode(node);
 
-    var finallyBlock = node.finallyBlock;
     if (finallyBlock != null) {
       assignedVariables.beginNode();
       finallyBlock.accept(this);
@@ -444,7 +504,6 @@
 
       iterable.accept(this);
 
-      assignedVariables.beginNode();
       if (forLoopParts is ForEachPartsWithIdentifier) {
         var element = forLoopParts.identifier.staticElement;
         if (element is VariableElement) {
@@ -457,6 +516,7 @@
       } else {
         throw new StateError('Unrecognized for loop parts');
       }
+      assignedVariables.beginNode();
       body.accept(this);
       assignedVariables.endNode(node);
     } else {
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
deleted file mode 100644
index 68b1179..0000000
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ /dev/null
@@ -1,1019 +0,0 @@
-// 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.
-
-import 'dart:collection';
-
-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/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-
-/**
- * Instances of the class `InheritanceManager` manage the knowledge of where class members
- * (methods, getters & setters) are inherited from.
- */
-@Deprecated('Use InheritanceManager3 instead.')
-class InheritanceManager {
-  /**
-   * The [LibraryElement] that is managed by this manager.
-   */
-  LibraryElement _library;
-
-  /**
-   * A flag indicating whether abstract methods should be included when looking
-   * up the superclass chain.
-   */
-  bool _includeAbstractFromSuperclasses;
-
-  /**
-   * This is a mapping between each [ClassElement] and a map between the [String] member
-   * names and the associated [ExecutableElement] in the mixin and superclass chain.
-   */
-  Map<ClassElement, Map<String, ExecutableElement>> _classLookup;
-
-  /**
-   * This is a mapping between each [ClassElement] and a map between the [String] member
-   * names and the associated [ExecutableElement] in the interface set.
-   */
-  Map<ClassElement, Map<String, ExecutableElement>> _interfaceLookup;
-
-  /**
-   * Initialize a newly created inheritance manager.
-   *
-   * @param library the library element context that the inheritance mappings are being generated
-   */
-  InheritanceManager(LibraryElement library,
-      {bool includeAbstractFromSuperclasses: false}) {
-    this._library = library;
-    _includeAbstractFromSuperclasses = includeAbstractFromSuperclasses;
-    _classLookup = new HashMap<ClassElement, Map<String, ExecutableElement>>();
-    _interfaceLookup =
-        new HashMap<ClassElement, Map<String, ExecutableElement>>();
-  }
-
-  /**
-   * Set the new library element context.
-   *
-   * @param library the new library element
-   */
-  void set libraryElement(LibraryElement library) {
-    this._library = library;
-  }
-
-  /**
-   * Get and return a mapping between the set of all string names of the members inherited from the
-   * passed [ClassElement] superclass hierarchy, and the associated [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @return a mapping between the set of all members inherited from the passed [ClassElement]
-   *         superclass hierarchy, and the associated [ExecutableElement]
-   */
-  @Deprecated('Use InheritanceManager3.getInheritedConcreteMap() instead.')
-  MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) =>
-      new MemberMap.fromMap(
-          _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()));
-
-  /**
-   * Get and return a mapping between the set of all string names of the members inherited from the
-   * passed [ClassElement] interface hierarchy, and the associated [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement].
-   */
-  @Deprecated('Use InheritanceManager3.getInheritedMap() instead.')
-  MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) =>
-      new MemberMap.fromMap(
-          _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()));
-
-  /**
-   * Return a table mapping the string names of the members inherited from the
-   * passed [ClassElement]'s superclass hierarchy, and the associated executable
-   * element.
-   */
-  @deprecated
-  Map<String, ExecutableElement> getMembersInheritedFromClasses(
-          ClassElement classElt) =>
-      _computeClassChainLookupMap(classElt, new HashSet<ClassElement>());
-
-  /**
-   * Return a table mapping the string names of the members inherited from the
-   * passed [ClassElement]'s interface hierarchy, and the associated executable
-   * element.
-   */
-  @deprecated
-  Map<String, ExecutableElement> getMembersInheritedFromInterfaces(
-          ClassElement classElt) =>
-      _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>());
-
-  /**
-   * Given some [ClassElement] and some member name, this returns the
-   * [ExecutableElement] that the class inherits from the mixins,
-   * superclasses or interfaces, that has the member name, if no member is inherited `null` is
-   * returned.
-   *
-   * @param classElt the class element to query
-   * @param memberName the name of the executable element to find and return
-   * @return the inherited executable element with the member name, or `null` if no such
-   *         member exists
-   */
-  @Deprecated('Use InheritanceManager3.getInherited() instead.')
-  ExecutableElement lookupInheritance(
-      ClassElement classElt, String memberName) {
-    if (memberName == null || memberName.isEmpty) {
-      return null;
-    }
-    ExecutableElement executable = _computeClassChainLookupMap(
-        classElt, new HashSet<ClassElement>())[memberName];
-    if (executable == null) {
-      return _computeInterfaceLookupMap(
-          classElt, new HashSet<ClassElement>())[memberName];
-    }
-    return executable;
-  }
-
-  /**
-   * Given some [ClassElement] and some member name, this returns the
-   * [ExecutableElement] that the class either declares itself, or
-   * inherits, that has the member name, if no member is inherited `null` is returned.
-   *
-   * @param classElt the class element to query
-   * @param memberName the name of the executable element to find and return
-   * @return the inherited executable element with the member name, or `null` if no such
-   *         member exists
-   */
-  @Deprecated('Use InheritanceManager3.getMember() instead.')
-  ExecutableElement lookupMember(ClassElement classElt, String memberName) {
-    ExecutableElement element = _lookupMemberInClass(classElt, memberName);
-    if (element != null) {
-      return element;
-    }
-    return lookupInheritance(classElt, memberName);
-  }
-
-  /**
-   * Determine the set of methods which is overridden by the given class member. If no member is
-   * inherited, an empty list is returned. If one of the inherited members is a
-   * [MultiplyInheritedExecutableElement], then it is expanded into its constituent inherited
-   * elements.
-   *
-   * @param classElt the class to query
-   * @param memberName the name of the class member to query
-   * @return a list of overridden methods
-   */
-  @Deprecated('Use InheritanceManager3.getOverridden() instead.')
-  List<ExecutableElement> lookupOverrides(
-      ClassElement classElt, String memberName) {
-    List<ExecutableElement> result = new List<ExecutableElement>();
-    if (memberName == null || memberName.isEmpty) {
-      return result;
-    }
-    List<Map<String, ExecutableElement>> interfaceMaps =
-        _gatherInterfaceLookupMaps(classElt, new HashSet<ClassElement>());
-    if (interfaceMaps != null) {
-      for (Map<String, ExecutableElement> interfaceMap in interfaceMaps) {
-        ExecutableElement overriddenElement = interfaceMap[memberName];
-        if (overriddenElement != null) {
-          if (overriddenElement is MultiplyInheritedExecutableElement) {
-            for (ExecutableElement element
-                in overriddenElement.inheritedElements) {
-              result.add(element);
-            }
-          } else {
-            result.add(overriddenElement);
-          }
-        }
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Compute and return a mapping between the set of all string names of the members inherited from
-   * the passed [ClassElement] superclass hierarchy, and the associated
-   * [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @param visitedClasses a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] superclass hierarchy, and the associated [ExecutableElement]
-   */
-  Map<String, ExecutableElement> _computeClassChainLookupMap(
-      ClassElement classElt, Set<ClassElement> visitedClasses) {
-    Map<String, ExecutableElement> resultMap = _classLookup[classElt];
-    if (resultMap != null) {
-      return resultMap;
-    } else {
-      resultMap = new Map<String, ExecutableElement>();
-    }
-    InterfaceType supertype = classElt.supertype;
-    if (supertype == null) {
-      // classElt is Object or a mixin
-      _classLookup[classElt] = resultMap;
-      return resultMap;
-    }
-    ClassElement superclassElt = supertype.element;
-    if (superclassElt != null) {
-      if (!visitedClasses.contains(superclassElt)) {
-        visitedClasses.add(superclassElt);
-        try {
-          resultMap = new Map<String, ExecutableElement>.from(
-              _computeClassChainLookupMap(superclassElt, visitedClasses));
-          //
-          // Substitute the super types down the hierarchy.
-          //
-          _substituteTypeParametersDownHierarchy(supertype, resultMap);
-          //
-          // Include the members from the superclass in the resultMap.
-          //
-          _recordMapWithClassMembers(
-              resultMap, supertype, _includeAbstractFromSuperclasses);
-        } finally {
-          visitedClasses.remove(superclassElt);
-        }
-      } else {
-        // This case happens only when the superclass was previously visited and
-        // not in the lookup, meaning this is meant to shorten the compute for
-        // recursive cases.
-        _classLookup[superclassElt] = resultMap;
-        return resultMap;
-      }
-    }
-    //
-    // Include the members from the mixins in the resultMap.  If there are
-    // multiple mixins, visit them in the order listed so that methods in later
-    // mixins will overwrite identically-named methods in earlier mixins.
-    //
-    List<InterfaceType> mixins = classElt.mixins;
-    for (InterfaceType mixin in mixins) {
-      ClassElement mixinElement = mixin.element;
-      if (mixinElement != null) {
-        if (!visitedClasses.contains(mixinElement)) {
-          visitedClasses.add(mixinElement);
-          try {
-            Map<String, ExecutableElement> map =
-                new Map<String, ExecutableElement>();
-            //
-            // Include the members from the mixin in the resultMap.
-            //
-            _recordMapWithClassMembers(
-                map, mixin, _includeAbstractFromSuperclasses);
-            //
-            // Add the members from map into result map.
-            //
-            for (String memberName in map.keys) {
-              ExecutableElement value = map[memberName];
-              ClassElement definingClass = value
-                  .getAncestor((Element element) => element is ClassElement);
-              if (!definingClass.isDartCoreObject) {
-                ExecutableElement existingValue = resultMap[memberName];
-                if (existingValue == null ||
-                    (existingValue != null && !_isAbstract(value))) {
-                  resultMap[memberName] = value;
-                }
-              }
-            }
-          } finally {
-            visitedClasses.remove(mixinElement);
-          }
-        } else {
-          // This case happens only when the superclass was previously visited
-          // and not in the lookup, meaning this is meant to shorten the compute
-          // for recursive cases.
-          _classLookup[mixinElement] = resultMap;
-          return resultMap;
-        }
-      }
-    }
-    _classLookup[classElt] = resultMap;
-    return resultMap;
-  }
-
-  /**
-   * Compute and return a mapping between the set of all string names of the members inherited from
-   * the passed [ClassElement] interface hierarchy, and the associated
-   * [ExecutableElement].
-   *
-   * @param classElt the class element to query
-   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return a mapping between the set of all string names of the members inherited from the passed
-   *         [ClassElement] interface hierarchy, and the associated [ExecutableElement]
-   */
-  Map<String, ExecutableElement> _computeInterfaceLookupMap(
-      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
-    Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt];
-    if (resultMap != null) {
-      return resultMap;
-    }
-    List<Map<String, ExecutableElement>> lookupMaps =
-        _gatherInterfaceLookupMaps(classElt, visitedInterfaces);
-    if (lookupMaps == null) {
-      resultMap = new Map<String, ExecutableElement>();
-    } else {
-      Map<String, List<ExecutableElement>> unionMap =
-          _unionInterfaceLookupMaps(lookupMaps);
-      resultMap = _resolveInheritanceLookup(classElt, unionMap);
-    }
-    _interfaceLookup[classElt] = resultMap;
-    return resultMap;
-  }
-
-  /**
-   * Given some array of [ExecutableElement]s, this method creates a synthetic element as
-   * described in 8.1.1:
-   *
-   * Let <i>numberOfPositionals</i>(<i>f</i>) denote the number of positional parameters of a
-   * function <i>f</i>, and let <i>numberOfRequiredParams</i>(<i>f</i>) denote the number of
-   * required parameters of a function <i>f</i>. Furthermore, let <i>s</i> denote the set of all
-   * named parameters of the <i>m<sub>1</sub>, &hellip;, m<sub>k</sub></i>. Then let
-   * * <i>h = max(numberOfPositionals(m<sub>i</sub>)),</i>
-   * * <i>r = min(numberOfRequiredParams(m<sub>i</sub>)), for all <i>i</i>, 1 <= i <= k.</i>
-   * Then <i>I</i> has a method named <i>n</i>, with <i>r</i> required parameters of type
-   * <b>dynamic</b>, <i>h</i> positional parameters of type <b>dynamic</b>, named parameters
-   * <i>s</i> of type <b>dynamic</b> and return type <b>dynamic</b>.
-   *
-   */
-  ExecutableElement _computeMergedExecutableElement(
-      List<ExecutableElement> elementArrayToMerge) {
-    int h = _getNumOfPositionalParameters(elementArrayToMerge[0]);
-    int r = _getNumOfRequiredParameters(elementArrayToMerge[0]);
-    Set<String> namedParametersList = new HashSet<String>();
-    for (int i = 1; i < elementArrayToMerge.length; i++) {
-      ExecutableElement element = elementArrayToMerge[i];
-      int numOfPositionalParams = _getNumOfPositionalParameters(element);
-      if (h < numOfPositionalParams) {
-        h = numOfPositionalParams;
-      }
-      int numOfRequiredParams = _getNumOfRequiredParameters(element);
-      if (r > numOfRequiredParams) {
-        r = numOfRequiredParams;
-      }
-      // TODO(brianwilkerson) Handle the fact that named parameters can now be
-      //  required.
-      namedParametersList.addAll(_getNamedParameterNames(element));
-    }
-    return _createSyntheticExecutableElement(
-        elementArrayToMerge,
-        elementArrayToMerge[0].displayName,
-        r,
-        h - r,
-        new List.from(namedParametersList));
-  }
-
-  /**
-   * Used by [computeMergedExecutableElement] to actually create the
-   * synthetic element.
-   *
-   * @param elementArrayToMerge the array used to create the synthetic element
-   * @param name the name of the method, getter or setter
-   * @param numOfRequiredParameters the number of required parameters
-   * @param numOfPositionalParameters the number of positional parameters
-   * @param namedParameters the list of [String]s that are the named parameters
-   * @return the created synthetic element
-   */
-  ExecutableElement _createSyntheticExecutableElement(
-      List<ExecutableElement> elementArrayToMerge,
-      String name,
-      int numOfRequiredParameters,
-      int numOfPositionalParameters,
-      List<String> namedParameters) {
-    DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
-    DartType bottomType = BottomTypeImpl.instance;
-    SimpleIdentifier nameIdentifier = astFactory
-        .simpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, 0));
-    ExecutableElementImpl executable;
-    ExecutableElement elementToMerge = elementArrayToMerge[0];
-    if (elementToMerge is MethodElement) {
-      MultiplyInheritedMethodElementImpl unionedMethod =
-          new MultiplyInheritedMethodElementImpl(nameIdentifier);
-      unionedMethod.inheritedElements = elementArrayToMerge;
-      executable = unionedMethod;
-    } else if (elementToMerge is PropertyAccessorElement) {
-      MultiplyInheritedPropertyAccessorElementImpl unionedPropertyAccessor =
-          new MultiplyInheritedPropertyAccessorElementImpl(nameIdentifier);
-      unionedPropertyAccessor.getter = elementToMerge.isGetter;
-      unionedPropertyAccessor.setter = elementToMerge.isSetter;
-      unionedPropertyAccessor.inheritedElements = elementArrayToMerge;
-      executable = unionedPropertyAccessor;
-    } else {
-      throw new AnalysisException(
-          'Invalid class of element in merge: ${elementToMerge.runtimeType}');
-    }
-    int numOfParameters = numOfRequiredParameters +
-        numOfPositionalParameters +
-        namedParameters.length;
-    List<ParameterElement> parameters =
-        new List<ParameterElement>(numOfParameters);
-    int i = 0;
-    for (int j = 0; j < numOfRequiredParameters; j++, i++) {
-      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
-      parameter.type = bottomType;
-      parameter.parameterKind = ParameterKind.REQUIRED;
-      parameters[i] = parameter;
-    }
-    for (int k = 0; k < numOfPositionalParameters; k++, i++) {
-      ParameterElementImpl parameter = new ParameterElementImpl("", 0);
-      parameter.type = bottomType;
-      parameter.parameterKind = ParameterKind.POSITIONAL;
-      parameters[i] = parameter;
-    }
-    // TODO(brianwilkerson) Handle the fact that named parameters can now be
-    //  required.
-    for (int m = 0; m < namedParameters.length; m++, i++) {
-      ParameterElementImpl parameter =
-          new ParameterElementImpl(namedParameters[m], 0);
-      parameter.type = bottomType;
-      parameter.parameterKind = ParameterKind.NAMED;
-      parameters[i] = parameter;
-    }
-    executable.returnType = dynamicType;
-    executable.parameters = parameters;
-    return executable;
-  }
-
-  /**
-   * Collect a list of interface lookup maps whose elements correspond to all of the classes
-   * directly above [classElt] in the class hierarchy (the direct superclass if any, all
-   * mixins, and all direct superinterfaces). Each item in the list is the interface lookup map
-   * returned by [computeInterfaceLookupMap] for the corresponding super, except with type
-   * parameters appropriately substituted.
-   *
-   * @param classElt the class element to query
-   * @param visitedInterfaces a set of visited classes passed back into this method when it calls
-   *          itself recursively
-   * @return `null` if there was a problem (such as a loop in the class hierarchy) or if there
-   *         are no classes above this one in the class hierarchy. Otherwise, a list of interface
-   *         lookup maps.
-   */
-  List<Map<String, ExecutableElement>> _gatherInterfaceLookupMaps(
-      ClassElement classElt, HashSet<ClassElement> visitedInterfaces) {
-    List<Map<String, ExecutableElement>> lookupMaps =
-        new List<Map<String, ExecutableElement>>();
-    bool hasProblem = false;
-
-    void recordInterface(InterfaceType type) {
-      ClassElement element = type.element;
-      if (!visitedInterfaces.add(element)) {
-        hasProblem = true;
-        return;
-      }
-      try {
-        //
-        // Recursively compute the map for the interfaces.
-        //
-        Map<String, ExecutableElement> map =
-            _computeInterfaceLookupMap(element, visitedInterfaces);
-        map = new Map<String, ExecutableElement>.from(map);
-        //
-        // Substitute the supertypes down the hierarchy.
-        //
-        _substituteTypeParametersDownHierarchy(type, map);
-        //
-        // And any members from the interface into the map as well.
-        //
-        _recordMapWithClassMembers(map, type, true);
-        lookupMaps.add(map);
-      } finally {
-        visitedInterfaces.remove(element);
-      }
-    }
-
-    void recordInterfaces(List<InterfaceType> types) {
-      for (int i = types.length - 1; i >= 0; i--) {
-        InterfaceType type = types[i];
-        recordInterface(type);
-      }
-    }
-
-    InterfaceType superType = classElt.supertype;
-    if (superType != null) {
-      recordInterface(superType);
-    }
-
-    recordInterfaces(classElt.mixins);
-    recordInterfaces(classElt.superclassConstraints);
-    recordInterfaces(classElt.interfaces);
-
-    if (hasProblem || lookupMaps.isEmpty) {
-      return null;
-    }
-    return lookupMaps;
-  }
-
-  /**
-   * Given some [classElement], this method finds and returns the executable
-   * element with the given [memberName] in the class element. Static members,
-   * members in super types and members not accessible from the current library
-   * are not considered.
-   */
-  ExecutableElement _lookupMemberInClass(
-      ClassElement classElement, String memberName) {
-    List<MethodElement> methods = classElement.methods;
-    int methodLength = methods.length;
-    for (int i = 0; i < methodLength; i++) {
-      MethodElement method = methods[i];
-      if (memberName == method.name &&
-          method.isAccessibleIn(_library) &&
-          !method.isStatic) {
-        return method;
-      }
-    }
-    List<PropertyAccessorElement> accessors = classElement.accessors;
-    int accessorLength = accessors.length;
-    for (int i = 0; i < accessorLength; i++) {
-      PropertyAccessorElement accessor = accessors[i];
-      if (memberName == accessor.name &&
-          accessor.isAccessibleIn(_library) &&
-          !accessor.isStatic) {
-        return accessor;
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Record the passed map with the set of all members (methods, getters and setters) in the type
-   * into the passed map.
-   *
-   * @param map some non-`null` map to put the methods and accessors from the passed
-   *          [ClassElement] into
-   * @param type the type that will be recorded into the passed map
-   * @param doIncludeAbstract `true` if abstract members will be put into the map
-   */
-  void _recordMapWithClassMembers(Map<String, ExecutableElement> map,
-      InterfaceType type, bool doIncludeAbstract) {
-    Set<InterfaceType> seenTypes = new HashSet<InterfaceType>();
-    while (type.element.isMixinApplication) {
-      List<InterfaceType> mixins = type.mixins;
-      if (!seenTypes.add(type) || mixins.isEmpty) {
-        // In the case of a circularity in the type hierarchy, just don't add
-        // any members to the map.
-        return;
-      }
-      type = mixins.last;
-    }
-    List<MethodElement> methods = type.methods;
-    for (MethodElement method in methods) {
-      if (method.isAccessibleIn(_library) &&
-          !method.isStatic &&
-          (doIncludeAbstract || !method.isAbstract)) {
-        map[method.name] = method;
-      }
-    }
-    List<PropertyAccessorElement> accessors = type.accessors;
-    for (PropertyAccessorElement accessor in accessors) {
-      if (accessor.isAccessibleIn(_library) &&
-          !accessor.isStatic &&
-          (doIncludeAbstract || !accessor.isAbstract)) {
-        map[accessor.name] = accessor;
-      }
-    }
-  }
-
-  /**
-   * Given the set of methods defined by classes above [classElt] in the class hierarchy,
-   * apply the appropriate inheritance rules to determine those methods inherited by or overridden
-   * by [classElt].
-   *
-   * @param classElt the class element to query.
-   * @param unionMap a mapping from method name to the set of unique (in terms of signature) methods
-   *          defined in superclasses of [classElt].
-   * @return the inheritance lookup map for [classElt].
-   */
-  Map<String, ExecutableElement> _resolveInheritanceLookup(
-      ClassElement classElt, Map<String, List<ExecutableElement>> unionMap) {
-    Map<String, ExecutableElement> resultMap =
-        new Map<String, ExecutableElement>();
-    unionMap.forEach((String key, List<ExecutableElement> list) {
-      int numOfEltsWithMatchingNames = list.length;
-      if (numOfEltsWithMatchingNames == 1) {
-        //
-        // Example: class A inherits only 1 method named 'm'.
-        // Since it is the only such method, it is inherited.
-        // Another example: class A inherits 2 methods named 'm' from 2
-        // different interfaces, but they both have the same signature, so it is
-        // the method inherited.
-        //
-        resultMap[key] = list[0];
-      } else {
-        //
-        // Then numOfEltsWithMatchingNames > 1, check for the warning cases.
-        //
-        bool allMethods = true;
-        bool allSetters = true;
-        bool allGetters = true;
-        for (ExecutableElement executableElement in list) {
-          if (executableElement is PropertyAccessorElement) {
-            allMethods = false;
-            if (executableElement.isSetter) {
-              allGetters = false;
-            } else {
-              allSetters = false;
-            }
-          } else {
-            allGetters = false;
-            allSetters = false;
-          }
-        }
-        //
-        // If there isn't a mixture of methods with getters, then continue,
-        // otherwise create a warning.
-        //
-        if (allMethods || allGetters || allSetters) {
-          //
-          // Compute the element whose type is the subtype of all of the other
-          // types.
-          //
-          List<ExecutableElement> elements = new List.from(list);
-          List<FunctionType> executableElementTypes =
-              new List<FunctionType>(numOfEltsWithMatchingNames);
-          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
-            executableElementTypes[i] = elements[i].type;
-          }
-          List<int> subtypesOfAllOtherTypesIndexes = new List<int>();
-          for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
-            FunctionType subtype = executableElementTypes[i];
-            if (subtype == null) {
-              continue;
-            }
-            bool subtypeOfAllTypes = true;
-            TypeSystem typeSystem = _library.context.typeSystem;
-            for (int j = 0;
-                j < numOfEltsWithMatchingNames && subtypeOfAllTypes;
-                j++) {
-              if (i != j) {
-                if (!typeSystem.isSubtypeOf(
-                    subtype, executableElementTypes[j])) {
-                  subtypeOfAllTypes = false;
-                  break;
-                }
-              }
-            }
-            if (subtypeOfAllTypes) {
-              subtypesOfAllOtherTypesIndexes.add(i);
-            }
-          }
-          //
-          // The following is split into three cases determined by the number of
-          // elements in subtypesOfAllOtherTypes
-          //
-          if (subtypesOfAllOtherTypesIndexes.length == 1) {
-            //
-            // Example: class A inherited only 2 method named 'm'.
-            // One has the function type '() -> dynamic' and one has the
-            // function type '([int]) -> dynamic'. Since the second method is a
-            // subtype of all the others, it is the inherited method.
-            // Tests: InheritanceManagerTest.
-            // test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_*
-            //
-            resultMap[key] = elements[subtypesOfAllOtherTypesIndexes[0]];
-          } else {
-            if (subtypesOfAllOtherTypesIndexes.isNotEmpty) {
-              //
-              // Example: class A inherits 2 methods named 'm'.
-              // One has the function type '(int) -> dynamic' and one has the
-              // function type '(num) -> dynamic'. Since they are both a subtype
-              // of the other, a synthetic function '(dynamic) -> dynamic' is
-              // inherited.
-              // Tests: test_getMapOfMembersInheritedFromInterfaces_
-              // union_multipleSubtypes_*
-              //
-              // TODO(leafp): this produces (dynamic) -> dynamic even if
-              // the types are equal which gives bad error messages. If
-              // types are equal, we should consider using them.  Even
-              // better, consider using the GLB of the parameter types
-              // and the LUB of the return types
-              List<ExecutableElement> elementArrayToMerge =
-                  new List<ExecutableElement>(
-                      subtypesOfAllOtherTypesIndexes.length);
-              for (int i = 0; i < elementArrayToMerge.length; i++) {
-                elementArrayToMerge[i] =
-                    elements[subtypesOfAllOtherTypesIndexes[i]];
-              }
-              ExecutableElement mergedExecutableElement =
-                  _computeMergedExecutableElement(elementArrayToMerge);
-              resultMap[key] = mergedExecutableElement;
-            }
-          }
-        }
-      }
-    });
-    return resultMap;
-  }
-
-  /**
-   * Loop through all of the members in the given [map], performing type
-   * parameter  substitutions using a passed [supertype].
-   */
-  void _substituteTypeParametersDownHierarchy(
-      InterfaceType superType, Map<String, ExecutableElement> map) {
-    for (String memberName in map.keys) {
-      ExecutableElement executableElement = map[memberName];
-      if (executableElement is MethodMember) {
-        map[memberName] = MethodMember.from(executableElement, superType);
-      } else if (executableElement is PropertyAccessorMember) {
-        map[memberName] =
-            PropertyAccessorMember.from(executableElement, superType);
-      }
-    }
-  }
-
-  /**
-   * Union all of the [lookupMaps] together into a single map, grouping the ExecutableElements
-   * into a list where none of the elements are equal where equality is determined by having equal
-   * function types. (We also take note too of the kind of the element: ()->int and () -> int may
-   * not be equal if one is a getter and the other is a method.)
-   *
-   * @param lookupMaps the maps to be unioned together.
-   * @return the resulting union map.
-   */
-  Map<String, List<ExecutableElement>> _unionInterfaceLookupMaps(
-      List<Map<String, ExecutableElement>> lookupMaps) {
-    Map<String, List<ExecutableElement>> unionMap =
-        new HashMap<String, List<ExecutableElement>>();
-    for (Map<String, ExecutableElement> lookupMap in lookupMaps) {
-      for (String memberName in lookupMap.keys) {
-        // Get the list value out of the unionMap
-        List<ExecutableElement> list = unionMap.putIfAbsent(
-            memberName, () => new List<ExecutableElement>());
-        // Fetch the entry out of this lookupMap
-        ExecutableElement newExecutableElementEntry = lookupMap[memberName];
-        if (list.isEmpty) {
-          // If the list is empty, just the new value
-          list.add(newExecutableElementEntry);
-        } else {
-          // Otherwise, only add the newExecutableElementEntry if it isn't
-          // already in the list, this covers situation where a class inherits
-          // two methods (or two getters) that are identical.
-          bool alreadyInList = false;
-          bool isMethod1 = newExecutableElementEntry is MethodElement;
-          for (ExecutableElement executableElementInList in list) {
-            bool isMethod2 = executableElementInList is MethodElement;
-            if (isMethod1 == isMethod2 &&
-                executableElementInList.type ==
-                    newExecutableElementEntry.type) {
-              alreadyInList = true;
-              break;
-            }
-          }
-          if (!alreadyInList) {
-            list.add(newExecutableElementEntry);
-          }
-        }
-      }
-    }
-    return unionMap;
-  }
-
-  /**
-   * Given some [ExecutableElement], return the list of named parameters.
-   */
-  static List<String> _getNamedParameterNames(
-      ExecutableElement executableElement) {
-    List<String> namedParameterNames = new List<String>();
-    List<ParameterElement> parameters = executableElement.parameters;
-    for (int i = 0; i < parameters.length; i++) {
-      ParameterElement parameterElement = parameters[i];
-      if (parameterElement.isNamed) {
-        namedParameterNames.add(parameterElement.name);
-      }
-    }
-    return namedParameterNames;
-  }
-
-  /**
-   * Given some [ExecutableElement] return the number of parameters of the specified kind.
-   */
-  static int _getNumOfParameters(
-      ExecutableElement executableElement, ParameterKind parameterKind) {
-    int parameterCount = 0;
-    List<ParameterElement> parameters = executableElement.parameters;
-    for (int i = 0; i < parameters.length; i++) {
-      ParameterElement parameterElement = parameters[i];
-      // ignore: deprecated_member_use_from_same_package
-      if (parameterElement.parameterKind == parameterKind) {
-        parameterCount++;
-      }
-    }
-    return parameterCount;
-  }
-
-  /**
-   * Given some [ExecutableElement] return the number of positional parameters.
-   *
-   * Note: by positional we mean [ParameterKind.REQUIRED] or [ParameterKind.POSITIONAL].
-   */
-  static int _getNumOfPositionalParameters(
-          ExecutableElement executableElement) =>
-      _getNumOfParameters(executableElement, ParameterKind.REQUIRED) +
-      _getNumOfParameters(executableElement, ParameterKind.POSITIONAL);
-
-  /**
-   * Given some [ExecutableElement] return the number of required parameters.
-   */
-  static int _getNumOfRequiredParameters(ExecutableElement executableElement) =>
-      _getNumOfParameters(executableElement, ParameterKind.REQUIRED);
-
-  /**
-   * Given some [ExecutableElement] returns `true` if it is an abstract member of a
-   * class.
-   *
-   * @param executableElement some [ExecutableElement] to evaluate
-   * @return `true` if the given element is an abstract member of a class
-   */
-  static bool _isAbstract(ExecutableElement executableElement) {
-    if (executableElement is MethodElement) {
-      return executableElement.isAbstract;
-    } else if (executableElement is PropertyAccessorElement) {
-      return executableElement.isAbstract;
-    }
-    return false;
-  }
-}
-
-/**
- * This class is used to replace uses of `HashMap<String, ExecutableElement>`
- * which are not as performant as this class.
- */
-@deprecated
-class MemberMap {
-  /**
-   * The current size of this map.
-   */
-  int _size = 0;
-
-  /**
-   * The array of keys.
-   */
-  List<String> _keys;
-
-  /**
-   * The array of ExecutableElement values.
-   */
-  List<ExecutableElement> _values;
-
-  /**
-   * Initialize a newly created member map to have the given [initialCapacity].
-   * The map will grow if needed.
-   */
-  MemberMap([int initialCapacity = 10]) {
-    _initArrays(initialCapacity);
-  }
-
-  /**
-   * Initialize a newly created member map to contain the same members as the
-   * given [memberMap].
-   */
-  MemberMap.from(MemberMap memberMap) {
-    _initArrays(memberMap._size + 5);
-    for (int i = 0; i < memberMap._size; i++) {
-      _keys[i] = memberMap._keys[i];
-      _values[i] = memberMap._values[i];
-    }
-    _size = memberMap._size;
-  }
-
-  /**
-   * Initialize a newly created member map to contain the same members as the
-   * given [map].
-   */
-  MemberMap.fromMap(Map<String, ExecutableElement> map) {
-    _size = map.length;
-    _initArrays(_size + 5);
-    int index = 0;
-    map.forEach((String memberName, ExecutableElement element) {
-      _keys[index] = memberName;
-      _values[index] = element;
-      index++;
-    });
-  }
-
-  /**
-   * The size of the map.
-   *
-   * @return the size of the map.
-   */
-  int get size => _size;
-
-  /**
-   * Given some key, return the ExecutableElement value from the map, if the key does not exist in
-   * the map, `null` is returned.
-   *
-   * @param key some key to look up in the map
-   * @return the associated ExecutableElement value from the map, if the key does not exist in the
-   *         map, `null` is returned
-   */
-  ExecutableElement get(String key) {
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] != null && _keys[i] == key) {
-        return _values[i];
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Get and return the key at the specified location. If the key/value pair has been removed from
-   * the set, then `null` is returned.
-   *
-   * @param i some non-zero value less than size
-   * @return the key at the passed index
-   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
-   *        zero or greater than or equal to the capacity of the arrays
-   */
-  String getKey(int i) => _keys[i];
-
-  /**
-   * Get and return the ExecutableElement at the specified location. If the key/value pair has been
-   * removed from the set, then then `null` is returned.
-   *
-   * @param i some non-zero value less than size
-   * @return the key at the passed index
-   * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passed index is less than
-   *        zero or greater than or equal to the capacity of the arrays
-   */
-  ExecutableElement getValue(int i) => _values[i];
-
-  /**
-   * Given some key/value pair, store the pair in the map. If the key exists already, then the new
-   * value overrides the old value.
-   *
-   * @param key the key to store in the map
-   * @param value the ExecutableElement value to store in the map
-   */
-  void put(String key, ExecutableElement value) {
-    // If we already have a value with this key, override the value
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] != null && _keys[i] == key) {
-        _values[i] = value;
-        return;
-      }
-    }
-    // If needed, double the size of our arrays and copy values over in both
-    // arrays
-    if (_size == _keys.length) {
-      int newArrayLength = _size * 2;
-      List<String> keys_new_array = new List<String>(newArrayLength);
-      List<ExecutableElement> values_new_array =
-          new List<ExecutableElement>(newArrayLength);
-      for (int i = 0; i < _size; i++) {
-        keys_new_array[i] = _keys[i];
-      }
-      for (int i = 0; i < _size; i++) {
-        values_new_array[i] = _values[i];
-      }
-      _keys = keys_new_array;
-      _values = values_new_array;
-    }
-    // Put new value at end of array
-    _keys[_size] = key;
-    _values[_size] = value;
-    _size++;
-  }
-
-  /**
-   * Given some [String] key, this method replaces the associated key and value pair with
-   * `null`. The size is not decremented with this call, instead it is expected that the users
-   * check for `null`.
-   *
-   * @param key the key of the key/value pair to remove from the map
-   */
-  void remove(String key) {
-    for (int i = 0; i < _size; i++) {
-      if (_keys[i] == key) {
-        _keys[i] = null;
-        _values[i] = null;
-        return;
-      }
-    }
-  }
-
-  /**
-   * Sets the ExecutableElement at the specified location.
-   *
-   * @param i some non-zero value less than size
-   * @param value the ExecutableElement value to store in the map
-   */
-  void setValue(int i, ExecutableElement value) {
-    _values[i] = value;
-  }
-
-  /**
-   * Initializes [keys] and [values].
-   */
-  void _initArrays(int initialCapacity) {
-    _keys = new List<String>(initialCapacity);
-    _values = new List<ExecutableElement>(initialCapacity);
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index f7286de..27e447b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -135,16 +135,11 @@
       _assertLegacyType(type.bound);
     } else if (type is InterfaceType) {
       type.typeArguments.forEach(_assertLegacyType);
-      type.typeParameters
-          .map((param) => param.bound)
-          .forEach(_assertLegacyType);
     } else if (type is FunctionType) {
       _assertLegacyType(type.returnType);
       type.parameters.map((param) => param.type).forEach(_assertLegacyType);
       type.typeArguments.forEach(_assertLegacyType);
-      type.typeParameters
-          .map((param) => param.bound)
-          .forEach(_assertLegacyType);
+      type.typeFormals.map((param) => param.bound).forEach(_assertLegacyType);
     }
 
     if ((type as TypeImpl).nullabilitySuffix == NullabilitySuffix.star) {
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 6d999b9..e119faf 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -121,10 +121,18 @@
       return;
     }
 
-    ClassElement typeReference = getTypeReference(receiver);
-    if (typeReference != null) {
-      _resolveReceiverTypeLiteral(node, typeReference, nameNode, name);
-      return;
+    if (receiver is Identifier) {
+      var element = receiver.staticElement;
+      if (element is ClassElement) {
+        _resolveReceiverTypeLiteral(node, element, nameNode, name);
+        return;
+      } else if (element is FunctionTypeAliasElement) {
+        _reportUndefinedMethod(
+          node,
+          name,
+          _resolver.typeProvider.typeType.element,
+        );
+      }
     }
 
     DartType receiverType = receiver.staticType;
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index c71d6f2..c3489dd 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -168,15 +168,14 @@
 
         if (exceptionTypeNode == null) {
           element.hasImplicitType = true;
-          element.declaredType = _dynamicType;
+          element.type = _dynamicType;
           exceptionNode.staticType = _dynamicType;
         } else {
-          element.declaredType = exceptionTypeNode.type;
+          element.type = exceptionTypeNode.type;
           exceptionNode.staticType = exceptionTypeNode.type;
         }
 
         _setCodeRange(element, exceptionNode);
-        element.setVisibleRange(node.offset, node.length);
       }
 
       var stackTraceNode = node.stackTraceParameter;
@@ -187,11 +186,10 @@
 
         stackTraceNode.staticElement = element;
 
-        element.declaredType = _typeProvider.stackTraceType;
+        element.type = _typeProvider.stackTraceType;
         stackTraceNode.staticType = _typeProvider.stackTraceType;
 
         _setCodeRange(element, stackTraceNode);
-        element.setVisibleRange(node.offset, node.length);
       }
 
       node.body.accept(this);
@@ -312,12 +310,6 @@
     }
 
     _setCodeRange(element, node);
-
-    var parent = node.parent;
-    if (parent is ForEachPartsWithDeclaration) {
-      var statement = parent.parent;
-      element.setVisibleRange(statement.offset, statement.length);
-    }
   }
 
   @override
@@ -338,7 +330,6 @@
       element.isFinal = node.isFinal;
       // ignore: deprecated_member_use_from_same_package
       element.parameterKind = node.kind;
-      _setParameterVisibleRange(node, element);
 
       if (normalParameter is SimpleFormalParameter &&
           normalParameter.type == null) {
@@ -485,8 +476,6 @@
           : _elementWalker.getFunction();
       node.name.staticElement = element;
     } else {
-      // Elements for local variables and functions are built before we
-      // start visiting a Block.
       element = node.declaredElement;
 
       _setCodeRange(element, node);
@@ -503,12 +492,6 @@
       if (node.returnType == null) {
         element.hasImplicitReturnType = true;
       }
-
-      var enclosingBlock = node.thisOrAncestorOfType<Block>();
-      if (enclosingBlock != null) {
-        (element as FunctionElementImpl)
-            .setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
-      }
     }
 
     FunctionExpressionImpl expression = node.functionExpression;
@@ -552,6 +535,15 @@
   }
 
   @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    if (!_hasLocalElementsBuilt(node)) {
+      _buildLocalFunctionElement(node);
+    }
+
+    node.functionDeclaration.accept(this);
+  }
+
+  @override
   void visitFunctionExpression(FunctionExpression node) {
     var element = FunctionElementImpl.forOffset(node.offset);
     _elementHolder.enclose(element);
@@ -579,11 +571,6 @@
     });
 
     _setCodeRange(element, node);
-
-    var enclosingBlock = node.thisOrAncestorOfType<Block>();
-    if (enclosingBlock != null) {
-      element.setVisibleRange(enclosingBlock.offset, enclosingBlock.length);
-    }
   }
 
   @override
@@ -622,7 +609,6 @@
         // ignore: deprecated_member_use_from_same_package
         element.parameterKind = node.kind;
         _setCodeRange(element, node);
-        _setParameterVisibleRange(node, element);
       }
       nameNode.staticElement = element;
     }
@@ -841,7 +827,6 @@
         element.isFinal = node.isFinal;
         // ignore: deprecated_member_use_from_same_package
         element.parameterKind = node.kind;
-        _setParameterVisibleRange(node, element);
         if (node.type == null) {
           element.hasImplicitType = true;
         }
@@ -931,29 +916,12 @@
       element = _elementWalker.getVariable();
       node.name.staticElement = element;
     } else {
-      bool isConst = node.isConst;
-      bool isFinal = node.isFinal;
-      SimpleIdentifier variableName = node.name;
-
-      LocalVariableElementImpl localElement;
-      if (isConst && initializerNode != null) {
-        localElement = ConstLocalVariableElementImpl.forNode(variableName);
-      } else {
-        localElement = LocalVariableElementImpl.forNode(variableName);
-      }
-      _elementHolder.enclose(localElement);
-      variableName.staticElement = localElement;
+      LocalVariableElementImpl localElement = node.declaredElement;
       element = localElement;
 
-      localElement.isConst = isConst;
-      localElement.isFinal = isFinal;
-      localElement.isLate = node.isLate;
-
       VariableDeclarationList varList = node.parent;
       localElement.hasImplicitType = varList.type == null;
       localElement.type = varList.type?.type ?? _dynamicType;
-
-      _setVariableVisibleRange(localElement, node);
     }
 
     if (initializerNode != null) {
@@ -974,10 +942,16 @@
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
-    super.visitVariableDeclarationList(node);
+    var parent = node.parent;
+    if (parent is ForPartsWithDeclarations ||
+        parent is VariableDeclarationStatement &&
+            !_hasLocalElementsBuilt(parent)) {
+      _buildLocalVariableElements(node);
+    }
+
+    node.visitChildren(this);
 
     List<ElementAnnotation> elementAnnotations;
-    AstNode parent = node.parent;
     if (parent is FieldDeclaration) {
       elementAnnotations = _createElementAnnotations(parent.metadata);
     } else if (parent is TopLevelVariableDeclaration) {
@@ -1015,25 +989,44 @@
   void _buildLocalElements(List<Statement> statements) {
     for (var statement in statements) {
       if (statement is FunctionDeclarationStatement) {
-        var declaration = statement.functionDeclaration;
-        var element = FunctionElementImpl.forNode(declaration.name);
-        declaration.name.staticElement = element;
-        _nameScope.define(element);
-        _elementHolder.enclose(element);
+        _buildLocalFunctionElement(statement);
       } else if (statement is VariableDeclarationStatement) {
-        for (var variable in statement.variables.variables) {
-          var element = LocalVariableElementImpl(
-            variable.name.name,
-            variable.name.offset,
-          );
-          variable.name.staticElement = element;
-          _nameScope.define(element);
-          _elementHolder.enclose(element);
-        }
+        _buildLocalVariableElements(statement.variables);
       }
     }
   }
 
+  void _buildLocalFunctionElement(FunctionDeclarationStatement statement) {
+    var node = statement.functionDeclaration;
+    var element = FunctionElementImpl.forNode(node.name);
+    node.name.staticElement = element;
+    _nameScope.define(element);
+    _elementHolder.enclose(element);
+  }
+
+  void _buildLocalVariableElements(VariableDeclarationList variableList) {
+    var isConst = variableList.isConst;
+    var isFinal = variableList.isFinal;
+    var isLate = variableList.isLate;
+    for (var variable in variableList.variables) {
+      var variableName = variable.name;
+
+      LocalVariableElementImpl element;
+      if (isConst && variable.initializer != null) {
+        element = ConstLocalVariableElementImpl.forNode(variableName);
+      } else {
+        element = LocalVariableElementImpl.forNode(variableName);
+      }
+      variableName.staticElement = element;
+      _elementHolder.enclose(element);
+      _nameScope.define(element);
+
+      element.isConst = isConst;
+      element.isFinal = isFinal;
+      element.isLate = isLate;
+    }
+  }
+
   /// Ensure that each type parameters from the [typeParameterList] has its
   /// element set, either from the [_elementWalker] or new, and define these
   /// elements in the [_nameScope].
@@ -1091,20 +1084,6 @@
     }
   }
 
-  /// Return the body of the function that contains the given [parameter], or
-  /// `null` if no function body could be found.
-  FunctionBody _getFunctionBody(FormalParameter parameter) {
-    AstNode parent = parameter?.parent?.parent;
-    if (parent is ConstructorDeclaration) {
-      return parent.body;
-    } else if (parent is FunctionExpression) {
-      return parent.body;
-    } else if (parent is MethodDeclaration) {
-      return parent.body;
-    }
-    return null;
-  }
-
   NullabilitySuffix _getNullability(bool hasQuestion) {
     NullabilitySuffix nullability;
     if (_nonNullableEnabled) {
@@ -1194,27 +1173,6 @@
     element.setCodeRange(node.offset, node.length);
   }
 
-  /// Sets the visible source range for formal parameter.
-  void _setParameterVisibleRange(
-      FormalParameter node, ParameterElementImpl element) {
-    FunctionBody body = _getFunctionBody(node);
-    if (body is BlockFunctionBody || body is ExpressionFunctionBody) {
-      element.setVisibleRange(body.offset, body.length);
-    }
-  }
-
-  void _setVariableVisibleRange(
-      LocalVariableElementImpl element, VariableDeclaration node) {
-    AstNode scopeNode;
-    AstNode parent2 = node.parent.parent;
-    if (parent2 is ForPartsWithDeclarations) {
-      scopeNode = parent2.parent;
-    } else {
-      scopeNode = node.thisOrAncestorOfType<Block>();
-    }
-    element.setVisibleRange(scopeNode.offset, scopeNode.length);
-  }
-
   /// Make the given [holder] be the current one while running [f].
   void _withElementHolder(ElementHolder holder, void Function() f) {
     var previousHolder = _elementHolder;
@@ -1248,6 +1206,14 @@
     }
   }
 
+  /// We always build local elements for [VariableDeclarationStatement]s and
+  /// [FunctionDeclarationStatement]s in blocks, because invalid code might try
+  /// to use forward references.
+  static bool _hasLocalElementsBuilt(Statement node) {
+    var parent = node.parent;
+    return parent is Block || parent is SwitchMember;
+  }
+
   /// Associate each of the annotation [nodes] with the corresponding
   /// [ElementAnnotation] in [annotations].
   static void _setElementAnnotations(
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 9304c38..40ca63b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -258,7 +258,7 @@
       return;
     }
     _parametersDefined = true;
-    for (ParameterElement parameter in _typeElement.parameters) {
+    for (ParameterElement parameter in _typeElement.function.parameters) {
       define(parameter);
     }
   }
@@ -858,7 +858,7 @@
         definedNames = _show(definedNames, combinator.shownNames);
       } else {
         // Internal error.
-        AnalysisEngine.instance.logger
+        AnalysisEngine.instance.instrumentationService
             .logError("Unknown type of combinator: ${combinator.runtimeType}");
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/scanner/reader.dart b/pkg/analyzer/lib/src/dart/scanner/reader.dart
index 041f1c6..0a21e3b 100644
--- a/pkg/analyzer/lib/src/dart/scanner/reader.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/reader.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/scanner/reader.dart';
+import 'package:_fe_analyzer_shared/src/scanner/reader.dart';
 
-export 'package:front_end/src/scanner/reader.dart'
+export 'package:_fe_analyzer_shared/src/scanner/reader.dart'
     show CharacterReader, CharSequenceReader, SubSequenceReader;
 
 /**
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index b446a32..4943680 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -2,15 +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 'package:_fe_analyzer_shared/src/scanner/errors.dart'
+    show translateErrorToken;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart'
+    show Token, TokenType;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/scanner.dart' as fasta;
-import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
-import 'package:front_end/src/scanner/token.dart' show Token, TokenType;
 import 'package:pub_semver/pub_semver.dart';
 
 export 'package:analyzer/src/dart/error/syntactic_errors.dart';
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 4f9c23e..7657ed0 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -151,7 +151,7 @@
     try {
       return file.createSource(Uri.parse(path));
     } on FormatException catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
+      AnalysisEngine.instance.instrumentationService.logInfo(
           "Failed to create URI: $path",
           new CaughtException(exception, stackTrace));
     }
@@ -305,9 +305,11 @@
         return new PackageBundle.fromBuffer(bytes);
       }
     } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logError(
-          'Failed to load SDK analysis summary from $file',
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              'Failed to load SDK analysis summary from $file',
+              exception,
+              stackTrace));
     }
     return null;
   }
@@ -484,13 +486,12 @@
 
   /**
    * Initialize a newly created SDK to represent the Dart SDK installed in the
-   * [sdkDirectory]. The flag [useDart2jsPaths] is `true` if the dart2js path
-   * should be used when it is available
+   * [sdkDirectory].
    */
-  FolderBasedDartSdk(ResourceProvider resourceProvider, this._sdkDirectory,
-      [bool useDart2jsPaths = false]) {
+  FolderBasedDartSdk(ResourceProvider resourceProvider, Folder sdkDirectory)
+      : _sdkDirectory = sdkDirectory {
     this.resourceProvider = resourceProvider;
-    libraryMap = initialLibraryMap(useDart2jsPaths);
+    libraryMap = initialLibraryMap();
   }
 
   /**
@@ -602,26 +603,27 @@
         return new PackageBundle.fromBuffer(bytes);
       }
     } catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logError(
-          'Failed to load SDK analysis summary from $path',
-          new CaughtException(exception, stackTrace));
+      AnalysisEngine.instance.instrumentationService.logException(
+          new CaughtException.withMessage(
+              'Failed to load SDK analysis summary from $path',
+              exception,
+              stackTrace));
     }
     return null;
   }
 
   /**
-   * Read all of the configuration files to initialize the library maps. The
-   * flag [useDart2jsPaths] is `true` if the dart2js path should be used when it
-   * is available. Return the initialized library map.
+   * Read all of the configuration files to initialize the library maps.
+   * Return the initialized library map.
    */
-  LibraryMap initialLibraryMap(bool useDart2jsPaths) {
+  LibraryMap initialLibraryMap() {
     List<String> searchedPaths = <String>[];
     StackTrace lastStackTrace;
     Object lastException;
     for (File librariesFile in _libraryMapLocations) {
       try {
         String contents = librariesFile.readAsStringSync();
-        return new SdkLibrariesReader().readFromFile(librariesFile, contents);
+        return SdkLibrariesReader().readFromFile(librariesFile, contents);
       } catch (exception, stackTrace) {
         searchedPaths.add(librariesFile.path);
         lastException = exception;
@@ -633,8 +635,9 @@
     if (resourceProvider is MemoryResourceProvider) {
       (resourceProvider as MemoryResourceProvider).writeOn(buffer);
     }
-    AnalysisEngine.instance.logger.logError(
-        buffer.toString(), new CaughtException(lastException, lastStackTrace));
+    AnalysisEngine.instance.instrumentationService.logException(
+        new CaughtException.withMessage(
+            buffer.toString(), lastException, lastStackTrace));
     return new LibraryMap();
   }
 
@@ -872,8 +875,6 @@
  *     };
  */
 class SdkLibrariesReader {
-  SdkLibrariesReader([@deprecated bool useDart2jsPaths]);
-
   /**
    * Return the library map read from the given [file], given that the content
    * of the file is already known to be [libraryFileContents].
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 5d68cd4..159c539 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -407,6 +407,7 @@
               "correcting the name to match a defined class, or "
               "defining a class with the given name.");
 
+  @Deprecated('Use ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS')
   static const ParserErrorCode ANNOTATION_WITH_TYPE_ARGUMENTS =
       ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS;
 
@@ -2008,22 +2009,6 @@
           correction: "Try removing type parameters from the generic function "
               "type, or using 'dynamic' as the type argument here.");
 
-  /**
-   * Temporary error to work around dartbug.com/28515.
-   *
-   * We cannot yet properly summarize function-typed parameters with generic
-   * arguments, so to prevent confusion, we produce an error for any such
-   * constructs (regardless of whether summaries are in use).
-   *
-   * TODO(paulberry): remove this once dartbug.com/28515 is fixed.
-   */
-  static const CompileTimeErrorCode GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED =
-      const CompileTimeErrorCode('GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED',
-          "Analysis of generic function typed parameters isn't yet supported.",
-          correction:
-              "Try using an explicit typedef, or changing type parameters to "
-              "`dynamic`.");
-
   static const CompileTimeErrorCode IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY =
       const CompileTimeErrorCode(
           'IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY',
@@ -3515,7 +3500,7 @@
           correction: "Try adding the missing arguments.",
           hasPublishedDocs: true);
 
-  @Deprecated('Use CompileTimeErrorCode NOT_ENOUGH_POSITIONAL_ARGUMENTS')
+  @Deprecated('Use CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS')
   static const CompileTimeErrorCode NOT_ENOUGH_REQUIRED_ARGUMENTS =
       NOT_ENOUGH_POSITIONAL_ARGUMENTS;
 
@@ -3994,7 +3979,7 @@
   static const CompileTimeErrorCode REDIRECT_TO_NON_CONST_CONSTRUCTOR =
       const CompileTimeErrorCode(
           'REDIRECT_TO_NON_CONST_CONSTRUCTOR',
-          "Constant factory constructor can't delegate to a non-constant "
+          "Constant redirecting constructor can't redirect to a non-constant "
               "constructor.",
           correction: "Try redirecting to a different constructor.");
 
@@ -6407,8 +6392,8 @@
    * abstract class and <i>q</i> is not a factory constructor.
    */
   static const StaticWarningCode NEW_WITH_ABSTRACT_CLASS =
-      const StaticWarningCode('NEW_WITH_ABSTRACT_CLASS',
-          "Abstract classes can't be instantiated.",
+      const StaticWarningCode(
+          'NEW_WITH_ABSTRACT_CLASS', "Abstract classes can't be instantiated.",
           correction: "Try creating an instance of a subtype.");
 
   /**
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index 3e17c27..c5ef35c 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -187,76 +187,60 @@
    * their bounds.
    */
   void _checkForTypeArgumentNotMatchingBounds(TypeName typeName) {
-    // prepare Type
-    DartType type = typeName.type;
-    if (type == null) {
+    var element = typeName.name.staticElement;
+    var type = typeName.type;
+
+    List<TypeParameterElement> typeParameters;
+    List<DartType> typeArguments;
+    if (type is InterfaceType) {
+      typeParameters = type.element.typeParameters;
+      typeArguments = type.typeArguments;
+    } else if (element is GenericTypeAliasElement && type is FunctionType) {
+      typeParameters = element.typeParameters;
+      typeArguments = type.typeArguments;
+    } else {
       return;
     }
-    if (type is ParameterizedType) {
-      var element = typeName.name.staticElement;
-      // prepare type parameters
-      List<TypeParameterElement> parameterElements;
-      if (element is ClassElement) {
-        parameterElements = element.typeParameters;
-      } else if (element is GenericTypeAliasElement) {
-        parameterElements = element.typeParameters;
-      } else if (element is GenericFunctionTypeElement) {
-        // TODO(paulberry): it seems like either this case or the one above
-        // should be unnecessary.
-        FunctionTypeAliasElement typedefElement = element.enclosingElement;
-        parameterElements = typedefElement.typeParameters;
-      } else if (type is FunctionType) {
-        parameterElements = type.typeFormals;
-      } else {
-        // There are no other kinds of parameterized types.
-        throw new UnimplementedError(
-            'Unexpected element associated with parameterized type: '
-            '${element.runtimeType}');
-      }
-      List<DartType> arguments = type.typeArguments;
-      // iterate over each bounded type parameter and corresponding argument
-      NodeList<TypeAnnotation> argumentNodes =
-          typeName.typeArguments?.arguments;
-      var typeArguments = type.typeArguments;
-      int loopThroughIndex =
-          math.min(typeArguments.length, parameterElements.length);
-      bool shouldSubstitute =
-          arguments.isNotEmpty && arguments.length == parameterElements.length;
-      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) {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT,
-            argumentNode,
-          );
-          continue;
-        }
-        DartType boundType = parameterElements[i].bound;
-        if (argType != null && boundType != null) {
-          if (shouldSubstitute) {
-            boundType = Substitution.fromPairs(parameterElements, arguments)
-                .substituteType(boundType);
-          }
 
-          if (!_typeSystem.isSubtypeOf(argType, boundType)) {
-            if (_shouldAllowSuperBoundedTypes(typeName)) {
-              var replacedType =
-                  (argType as TypeImpl).replaceTopAndBottom(_typeProvider);
-              if (!identical(replacedType, argType) &&
-                  _typeSystem.isSubtypeOf(replacedType, boundType)) {
-                // Bound is satisfied under super-bounded rules, so we're ok.
-                continue;
-              }
+    // 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) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_TYPE_ARGUMENT,
+          argumentNode,
+        );
+        continue;
+      }
+      DartType boundType = typeParameters[i].bound;
+      if (argType != null && boundType != null) {
+        if (shouldSubstitute) {
+          boundType = Substitution.fromPairs(typeParameters, typeArguments)
+              .substituteType(boundType);
+        }
+
+        if (!_typeSystem.isSubtypeOf(argType, boundType)) {
+          if (_shouldAllowSuperBoundedTypes(typeName)) {
+            var replacedType =
+                (argType as TypeImpl).replaceTopAndBottom(_typeProvider);
+            if (!identical(replacedType, argType) &&
+                _typeSystem.isSubtypeOf(replacedType, boundType)) {
+              // Bound is satisfied under super-bounded rules, so we're ok.
+              continue;
             }
-            _errorReporter.reportTypeErrorForNode(
-                CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
-                argumentNode,
-                [argType, boundType]);
           }
+          _errorReporter.reportTypeErrorForNode(
+              CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+              argumentNode,
+              [argType, boundType]);
         }
       }
     }
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 20ab282..94fcd92 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2,22 +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/analysis/features.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
-import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
-import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/dart/ast/ast.dart'
-    show
-        ClassDeclarationImpl,
-        CompilationUnitImpl,
-        ExtensionDeclarationImpl,
-        MixinDeclarationImpl;
-import 'package:analyzer/src/fasta/error_converter.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:front_end/src/fasta/messages.dart'
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
     show
         LocatedMessage,
         Message,
@@ -41,24 +26,41 @@
         templateExpectedIdentifier,
         templateExperimentNotEnabled,
         templateUnexpectedToken;
-import 'package:front_end/src/fasta/parser.dart'
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show
         Assert,
+        BlockKind,
         DeclarationKind,
         FormalParameterKind,
         IdentifierContext,
         MemberKind,
         optional,
         Parser;
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
+    show translateErrorToken;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' hide StringToken;
+import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart'
+    show SyntheticStringToken, SyntheticToken;
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/ast_factory.dart' show AstFactory;
+import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
+import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/dart/ast/ast.dart'
+    show
+        ClassDeclarationImpl,
+        CompilationUnitImpl,
+        ExtensionDeclarationImpl,
+        MixinDeclarationImpl;
+import 'package:analyzer/src/fasta/error_converter.dart';
+import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:front_end/src/fasta/problems.dart' show unhandled;
 import 'package:front_end/src/fasta/quote.dart';
-import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
-import 'package:front_end/src/fasta/scanner/token_constants.dart';
 import 'package:front_end/src/fasta/source/stack_listener.dart'
     show NullValue, StackListener;
-import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
-import 'package:front_end/src/scanner/token.dart'
-    show SyntheticStringToken, SyntheticToken;
 import 'package:kernel/ast.dart' show AsyncMarker;
 
 const _invalidCollectionElement = const _InvalidCollectionElement._();
@@ -72,7 +74,6 @@
   ScriptTag scriptTag;
   final List<Directive> directives = <Directive>[];
   final List<CompilationUnitMember> declarations = <CompilationUnitMember>[];
-  final localDeclarations = <int, AstNode>{};
 
   @override
   final Uri uri;
@@ -318,7 +319,6 @@
 
     Comment comment = _findComment(metadata, name.beginToken);
     var typeParameter = ast.typeParameter(comment, metadata, name, null, null);
-    localDeclarations[name.offset] = typeParameter;
     push(typeParameter);
   }
 
@@ -604,7 +604,8 @@
     }
   }
 
-  void endBlock(int count, Token leftBracket, Token rightBracket) {
+  void endBlock(
+      int count, Token leftBracket, Token rightBracket, BlockKind blockKind) {
     assert(optional('{', leftBracket));
     assert(optional('}', rightBracket));
     debugEvent("Block");
@@ -1295,7 +1296,8 @@
             thisKeyword: thisKeyword,
             period: periodAfterThis,
             typeParameters: typeOrFunctionTypedParameter.typeParameters,
-            parameters: typeOrFunctionTypedParameter.parameters);
+            parameters: typeOrFunctionTypedParameter.parameters,
+            question: typeOrFunctionTypedParameter.question);
       }
     } else {
       TypeAnnotation type = typeOrFunctionTypedParameter;
@@ -1334,7 +1336,6 @@
       parameter = ast.defaultFormalParameter(node, ParameterKind.NAMED,
           defaultValue.separator, defaultValue.value);
     }
-    localDeclarations[nameToken.offset] = parameter;
     push(parameter);
   }
 
@@ -1696,7 +1697,6 @@
         ast.functionExpression(typeParameters, parameters, body);
     var functionDeclaration = ast.functionDeclaration(
         null, metadata, null, returnType, null, name, functionExpression);
-    localDeclarations[name.offset] = functionDeclaration;
     push(ast.functionDeclarationStatement(functionDeclaration));
   }
 
@@ -2309,11 +2309,9 @@
       List<FormalParameter> catchParameters = catchParameterList.parameters;
       if (catchParameters.isNotEmpty) {
         exception = catchParameters[0].identifier;
-        localDeclarations[exception.offset] = exception;
       }
       if (catchParameters.length > 1) {
         stackTrace = catchParameters[1].identifier;
-        localDeclarations[stackTrace.offset] = stackTrace;
       }
     }
     push(ast.catchClause(
@@ -2527,12 +2525,12 @@
   }
 
   @override
-  void handleForInitializerExpressionStatement(Token token) {
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
     debugEvent("ForInitializerExpressionStatement");
   }
 
   @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
     debugEvent("ForInitializerLocalVariableDeclaration");
   }
 
@@ -3554,10 +3552,7 @@
 
   VariableDeclaration _makeVariableDeclaration(
       SimpleIdentifier name, Token equals, Expression initializer) {
-    var variableDeclaration =
-        ast.variableDeclaration(name, equals, initializer);
-    localDeclarations[name.offset] = variableDeclaration;
-    return variableDeclaration;
+    return ast.variableDeclaration(name, equals, initializer);
   }
 
   ParameterKind _toAnalyzerParameterKind(
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index c7bd01a..385b75f 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -2,12 +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:_fe_analyzer_shared/src/messages/codes.dart' show Code, Message;
 import 'package:analyzer/dart/ast/token.dart' show Token;
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:front_end/src/fasta/messages.dart' show Code, Message;
 
 /// An error reporter that knows how to convert a Fasta error into an analyzer
 /// error.
diff --git a/pkg/analyzer/lib/src/fasta/token_utils.dart b/pkg/analyzer/lib/src/fasta/token_utils.dart
index c5ad5c2..f7a5b56 100644
--- a/pkg/analyzer/lib/src/fasta/token_utils.dart
+++ b/pkg/analyzer/lib/src/fasta/token_utils.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/scanner/token.dart' show CommentToken, Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart'
+    show CommentToken, Token;
 
 /// Search for the token before [target] starting the search with [start].
 /// Return `null` if [target] is a comment token
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 2813216..8b07563 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -2,572 +2,8 @@
 // for 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/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/exception/exception.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-
-/// A visitor that resolves declarations in an AST structure to already built
-/// elements.
-///
-/// The resulting AST must have everything resolved that would have been
-/// resolved by a [CompilationUnitBuilder] (that is, must be a valid
-/// [RESOLVED_UNIT1]). This class must not assume that the
-/// [CompilationUnitElement] passed to it is any more complete than a
-/// [COMPILATION_UNIT_ELEMENT].
-class DeclarationResolver extends RecursiveAstVisitor<void> {
-  /// The compilation unit containing the AST nodes being visited.
-  CompilationUnitElementImpl _enclosingUnit;
-
-  /// The [ElementWalker] we are using to keep track of progress through the
-  /// element model.
-  ElementWalker _walker;
-
-  DeclarationResolver();
-
-  /// Resolve the declarations within the given compilation [unit] to the
-  /// elements rooted at the given [element]. Throw an
-  /// [ElementMismatchException] if the element model and compilation unit do
-  /// not match each other.
-  void resolve(CompilationUnit unit, CompilationUnitElement element) {
-    _enclosingUnit = element;
-    _walker = new ElementWalker.forCompilationUnit(element);
-    unit.element = element;
-    try {
-      unit.accept(this);
-      _walker.validate();
-    } on Error catch (e, st) {
-      throw new _ElementMismatchException(
-          element, _walker.element, new CaughtException(e, st));
-    }
-  }
-
-  @override
-  void visitAnnotation(Annotation node) {
-    // Annotations can only contain elements in certain erroneous situations,
-    // in which case the elements are disconnected from the rest of the element
-    // model, thus we can't reconnect to them.  To avoid crashes, just create
-    // fresh elements.
-    ElementHolder elementHolder = new ElementHolder();
-    new ElementBuilder(elementHolder, _enclosingUnit).visitAnnotation(node);
-  }
-
-  @override
-  void visitBlockFunctionBody(BlockFunctionBody node) {
-    if (_isBodyToCreateElementsFor(node)) {
-      _walker.consumeLocalElements();
-      node.accept(_walker.elementBuilder);
-    } else {
-      super.visitBlockFunctionBody(node);
-    }
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    _walker.elementBuilder.buildCatchVariableElements(node);
-    super.visitCatchClause(node);
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    ClassElement element = _match(node.name, _walker.getClass());
-    _walk(new ElementWalker.forClass(element), () {
-      super.visitClassDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    ClassElement element = _match(node.name, _walker.getClass());
-    _walk(new ElementWalker.forClass(element), () {
-      super.visitClassTypeAlias(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    ConstructorElement element = _match(node.name, _walker.getConstructor(),
-        offset: node.name?.offset ?? node.returnType.offset);
-    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
-      (node as ConstructorDeclarationImpl).declaredElement = element;
-      super.visitConstructorDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    // Declared identifiers can only occur inside executable elements.
-    _walker.elementBuilder.visitDeclaredIdentifier(node);
-  }
-
-  @override
-  void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    NormalFormalParameter normalParameter = node.parameter;
-    ParameterElement element =
-        _match(normalParameter.identifier, _walker.getParameter());
-    if (normalParameter is SimpleFormalParameterImpl) {
-      normalParameter.declaredElement = element;
-      _setGenericFunctionType(normalParameter.type, element.type);
-    }
-    if (normalParameter is FieldFormalParameterImpl) {
-      _setGenericFunctionType(normalParameter.type, element.type);
-    }
-
-    Expression defaultValue = node.defaultValue;
-    if (defaultValue != null) {
-      _walk(
-          new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
-          () {
-        defaultValue.accept(this);
-      });
-    }
-
-    _walk(new ElementWalker.forParameter(element), () {
-      normalParameter.accept(this);
-    });
-
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitEnumDeclaration(EnumDeclaration node) {
-    ClassElement element = _match(node.name, _walker.getEnum());
-    resolveMetadata(node, node.metadata, element);
-    _walk(new ElementWalker.forClass(element), () {
-      for (EnumConstantDeclaration constant in node.constants) {
-        VariableElement field = _match(constant.name, _walker.getVariable());
-        resolveMetadata(node, constant.metadata, field);
-        constant.name.staticElement = field;
-        constant.name.staticType = field.type;
-      }
-      _walker.getFunction(); // toString()
-      super.visitEnumDeclaration(node);
-    });
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    super.visitExportDirective(node);
-    List<ElementAnnotation> annotations =
-        _enclosingUnit.getAnnotations(node.offset);
-    if (annotations.isEmpty && node.metadata.isNotEmpty) {
-      int index = (node.parent as CompilationUnit)
-          .directives
-          .where((directive) => directive is ExportDirective)
-          .toList()
-          .indexOf(node);
-      annotations = _walker.element.library.exports[index].metadata;
-    }
-    resolveAnnotations(node, node.metadata, annotations);
-  }
-
-  @override
-  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    if (_isBodyToCreateElementsFor(node)) {
-      _walker.consumeLocalElements();
-      node.accept(_walker.elementBuilder);
-    } else {
-      super.visitExpressionFunctionBody(node);
-    }
-  }
-
-  @override
-  void visitExtensionDeclaration(ExtensionDeclaration node) {
-    ExtensionElement element = _match(node.name, _walker.getExtension());
-    (node as ExtensionDeclarationImpl).declaredElement = element;
-    _walk(new ElementWalker.forExtension(element), () {
-      super.visitExtensionDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    super.visitFieldDeclaration(node);
-    FieldElement firstFieldElement = node.fields.variables[0].declaredElement;
-    resolveMetadata(node, node.metadata, firstFieldElement);
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    if (node.parent is! DefaultFormalParameter) {
-      ParameterElement element =
-          _match(node.identifier, _walker.getParameter());
-      _walk(new ElementWalker.forParameter(element), () {
-        super.visitFieldFormalParameter(node);
-      });
-      resolveMetadata(node, node.metadata, element);
-      _setGenericFunctionType(node.type, element.type);
-    } else {
-      super.visitFieldFormalParameter(node);
-    }
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    SimpleIdentifier functionName = node.name;
-    Token property = node.propertyKeyword;
-    ExecutableElement element;
-    if (property == null) {
-      element = _match(functionName, _walker.getFunction());
-    } else {
-      if (_walker.element is ExecutableElement) {
-        element = _match(functionName, _walker.getFunction());
-      } else if (property.keyword == Keyword.GET) {
-        element = _match(functionName, _walker.getAccessor());
-      } else {
-        assert(property.keyword == Keyword.SET);
-        element = _match(functionName, _walker.getAccessor(),
-            elementName: functionName.name + '=');
-      }
-    }
-    _setGenericFunctionType(node.returnType, element.returnType);
-    (node.functionExpression as FunctionExpressionImpl).declaredElement =
-        element;
-    node.returnType?.accept(this);
-    _walker._elementHolder?.addFunction(element);
-    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
-      super.visitFunctionDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitFunctionExpression(FunctionExpression node) {
-    if (node.parent is! FunctionDeclaration) {
-      node.accept(_walker.elementBuilder);
-    } else {
-      super.visitFunctionExpression(node);
-    }
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    FunctionTypeAliasElement element = _match(node.name, _walker.getTypedef());
-    _walk(new ElementWalker.forTypedef(element), () {
-      super.visitFunctionTypeAlias(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    if (node.parent is! DefaultFormalParameter) {
-      ParameterElement element =
-          _match(node.identifier, _walker.getParameter());
-      _walk(new ElementWalker.forParameter(element), () {
-        super.visitFunctionTypedFormalParameter(node);
-      });
-      resolveMetadata(node, node.metadata, element);
-    } else {
-      super.visitFunctionTypedFormalParameter(node);
-    }
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    var builder = new LocalElementBuilder(ElementHolder(), _enclosingUnit);
-    node.accept(builder);
-
-    var nodeImpl = node as GenericFunctionTypeImpl;
-    _enclosingUnit.encloseElement(
-      nodeImpl.declaredElement as GenericFunctionTypeElementImpl,
-    );
-  }
-
-  @override
-  void visitGenericTypeAlias(GenericTypeAlias node) {
-    GenericTypeAliasElementImpl element =
-        _match(node.name, _walker.getTypedef());
-    _setGenericFunctionType(node.functionType, element.function?.type);
-    _walk(new ElementWalker.forGenericTypeAlias(element), () {
-      super.visitGenericTypeAlias(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    super.visitImportDirective(node);
-    List<ElementAnnotation> annotations =
-        _enclosingUnit.getAnnotations(node.offset);
-    if (annotations.isEmpty && node.metadata.isNotEmpty) {
-      int index = (node.parent as CompilationUnit)
-          .directives
-          .where((directive) => directive is ImportDirective)
-          .toList()
-          .indexOf(node);
-      annotations = _walker.element.library.imports[index].metadata;
-    }
-    resolveAnnotations(node, node.metadata, annotations);
-  }
-
-  @override
-  void visitLabeledStatement(LabeledStatement node) {
-    bool onSwitchStatement = node.statement is SwitchStatement;
-    _walker.elementBuilder
-        .buildLabelElements(node.labels, onSwitchStatement, false);
-    super.visitLabeledStatement(node);
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    super.visitLibraryDirective(node);
-    List<ElementAnnotation> annotations =
-        _enclosingUnit.getAnnotations(node.offset);
-    if (annotations.isEmpty && node.metadata.isNotEmpty) {
-      annotations = _walker.element.library.metadata;
-    }
-    resolveAnnotations(node, node.metadata, annotations);
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    Token property = node.propertyKeyword;
-    SimpleIdentifier methodName = node.name;
-    String nameOfMethod = methodName.name;
-    ExecutableElement element;
-    if (property == null) {
-      String elementName = nameOfMethod == '-' &&
-              node.parameters != null &&
-              node.parameters.parameters.isEmpty
-          ? 'unary-'
-          : nameOfMethod;
-      element =
-          _match(methodName, _walker.getFunction(), elementName: elementName);
-    } else {
-      if (property.keyword == Keyword.GET) {
-        element = _match(methodName, _walker.getAccessor());
-      } else {
-        assert(property.keyword == Keyword.SET);
-        element = _match(methodName, _walker.getAccessor(),
-            elementName: nameOfMethod + '=');
-      }
-    }
-    _setGenericFunctionType(node.returnType, element.returnType);
-    node.returnType?.accept(this);
-    _walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
-      super.visitMethodDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitMixinDeclaration(MixinDeclaration node) {
-    ClassElement element = _match(node.name, _walker.getMixin());
-    _walk(new ElementWalker.forClass(element), () {
-      super.visitMixinDeclaration(node);
-    });
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitPartDirective(PartDirective node) {
-    super.visitPartDirective(node);
-    List<ElementAnnotation> annotations =
-        _enclosingUnit.getAnnotations(node.offset);
-    if (annotations.isEmpty && node.metadata.isNotEmpty) {
-      int index = (node.parent as CompilationUnit)
-          .directives
-          .where((directive) => directive is PartDirective)
-          .toList()
-          .indexOf(node);
-      annotations = _walker.element.library.parts[index].metadata;
-    }
-    resolveAnnotations(node, node.metadata, annotations);
-  }
-
-  @override
-  void visitPartOfDirective(PartOfDirective node) {
-    node.element = _enclosingUnit.library;
-    super.visitPartOfDirective(node);
-  }
-
-  @override
-  void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    if (node.parent is! DefaultFormalParameter) {
-      ParameterElement element =
-          _match(node.identifier, _walker.getParameter());
-      (node as SimpleFormalParameterImpl).declaredElement = element;
-      _setGenericFunctionType(node.type, element.type);
-      _walk(new ElementWalker.forParameter(element), () {
-        super.visitSimpleFormalParameter(node);
-      });
-      resolveMetadata(node, node.metadata, element);
-    } else {
-      super.visitSimpleFormalParameter(node);
-    }
-  }
-
-  @override
-  void visitSwitchCase(SwitchCase node) {
-    _walker.elementBuilder.buildLabelElements(node.labels, false, true);
-    super.visitSwitchCase(node);
-  }
-
-  @override
-  void visitSwitchDefault(SwitchDefault node) {
-    _walker.elementBuilder.buildLabelElements(node.labels, false, true);
-    super.visitSwitchDefault(node);
-  }
-
-  @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    super.visitTopLevelVariableDeclaration(node);
-    VariableElement firstElement = node.variables.variables[0].declaredElement;
-    resolveMetadata(node, node.metadata, firstElement);
-  }
-
-  @override
-  void visitTypeParameter(TypeParameter node) {
-    TypeParameterElement element =
-        _match(node.name, _walker.getTypeParameter());
-    _setGenericFunctionType(node.bound, element.bound);
-    super.visitTypeParameter(node);
-    resolveMetadata(node, node.metadata, element);
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    VariableElement element = _match(node.name, _walker.getVariable());
-    Expression initializer = node.initializer;
-    if (initializer != null) {
-      _walk(
-          new ElementWalker.forExecutable(element.initializer, _enclosingUnit),
-          () {
-        super.visitVariableDeclaration(node);
-      });
-    } else {
-      super.visitVariableDeclaration(node);
-    }
-  }
-
-  @override
-  void visitVariableDeclarationList(VariableDeclarationList node) {
-    if (_walker.elementBuilder != null) {
-      _walker.elementBuilder.visitVariableDeclarationList(node);
-    } else {
-      node.variables.accept(this);
-      VariableElement firstVariable = node.variables[0].declaredElement;
-      _setGenericFunctionType(node.type, firstVariable.type);
-      node.type?.accept(this);
-      if (node.parent is! FieldDeclaration &&
-          node.parent is! TopLevelVariableDeclaration) {
-        resolveMetadata(node, node.metadata, firstVariable);
-      }
-    }
-  }
-
-  /// Updates [identifier] to point to [element], after ensuring that the
-  /// element has the expected name.
-  ///
-  /// If no [elementName] is given, it defaults to the name of the [identifier]
-  /// (or the empty string if [identifier] is `null`).
-  ///
-  /// If [identifier] is `null`, nothing is updated, but the element name is
-  /// still checked.
-  E _match<E extends Element>(SimpleIdentifier identifier, E element,
-      {String elementName, int offset}) {
-    elementName ??= identifier?.name ?? '';
-    offset ??= identifier?.offset ?? -1;
-    if (element.name != elementName) {
-      throw new StateError(
-          'Expected an element matching `$elementName`, got `${element.name}`');
-    }
-    identifier?.staticElement = element;
-    _matchOffset(element, offset);
-    return element;
-  }
-
-  void _matchOffset(Element element, int offset) {
-    if (element.nameOffset > 0 && element.nameOffset != offset) {
-      throw new StateError('Element offset mismatch');
-    } else {
-      (element as ElementImpl).nameOffset = offset;
-    }
-  }
-
-  /// If the given [typeNode] is a [GenericFunctionType], set its [type].
-  void _setGenericFunctionType(TypeAnnotation typeNode, DartType type) {
-    if (typeNode is GenericFunctionTypeImpl) {
-      typeNode.type = type;
-      typeNode.declaredElement = type.element;
-    } else if (typeNode is NamedType) {
-      typeNode.type = type;
-      if (type is ParameterizedType) {
-        List<TypeAnnotation> nodes =
-            typeNode.typeArguments?.arguments ?? const [];
-        List<DartType> types = type.typeArguments;
-        if (nodes.length == types.length) {
-          for (int i = 0; i < nodes.length; i++) {
-            _setGenericFunctionType(nodes[i], types[i]);
-          }
-        }
-      }
-    }
-  }
-
-  /// Recurses through the element model and AST, verifying that all elements
-  /// are matched.
-  ///
-  /// Executes [callback] with [_walker] pointing to the given [walker] (which
-  /// should be a new instance of [ElementWalker]).  Once [callback] returns,
-  /// uses [ElementWalker.validate] to verify that all expected elements have
-  /// been matched.
-  void _walk(ElementWalker walker, void callback()) {
-    ElementWalker outerWalker = _walker;
-    _walker = walker;
-    callback();
-    walker.validate();
-    _walker = outerWalker;
-  }
-
-  /// Associate each of the annotation [nodes] with the corresponding
-  /// [ElementAnnotation] in [annotations]. If there is a problem, report it
-  /// against the given [parent] node.
-  static void resolveAnnotations(AstNode parent, NodeList<Annotation> nodes,
-      List<ElementAnnotation> annotations) {
-    int nodeCount = nodes.length;
-    if (nodeCount != annotations.length) {
-      throw new StateError('Found $nodeCount annotation nodes and '
-          '${annotations.length} element annotations');
-    }
-    for (int i = 0; i < nodeCount; i++) {
-      nodes[i].elementAnnotation = annotations[i];
-    }
-  }
-
-  /// If [element] is not `null`, associate each of the annotation [nodes] with
-  /// the corresponding [ElementAnnotation] in [element.metadata]. If there is a
-  /// problem, report it against the given [parent] node.
-  ///
-  /// If [element] is `null`, do nothing--this allows us to be robust in the
-  /// case where we are operating on an element model that hasn't been fully
-  /// built.
-  static void resolveMetadata(
-      AstNode parent, NodeList<Annotation> nodes, Element element) {
-    if (element != null) {
-      resolveAnnotations(parent, nodes, element.metadata);
-    }
-  }
-
-  static bool _isBodyToCreateElementsFor(FunctionBody node) {
-    AstNode parent = node.parent;
-    return parent is ConstructorDeclaration ||
-        parent is MethodDeclaration ||
-        parent.parent is FunctionDeclaration &&
-            parent.parent.parent is CompilationUnit;
-  }
-}
 
 /// Keeps track of the set of non-synthetic child elements of an element,
 /// yielding them one at a time in response to "get" method calls.
@@ -575,15 +11,6 @@
   /// The element whose child elements are being walked.
   final Element element;
 
-  /// If [element] is an executable element, an element builder which is
-  /// accumulating the executable element's local variables and labels.
-  /// Otherwise `null`.
-  LocalElementBuilder elementBuilder;
-
-  /// If [element] is an executable element, the element holder associated with
-  /// [elementBuilder].  Otherwise `null`.
-  ElementHolder _elementHolder;
-
   List<PropertyAccessorElement> _accessors;
   int _accessorIndex = 0;
   List<ClassElement> _classes;
@@ -637,7 +64,7 @@
   /// unit element.
   ElementWalker.forExecutable(
       ExecutableElement element, CompilationUnitElement compilationUnit)
-      : this._forExecutable(element, compilationUnit, new ElementHolder());
+      : this._forExecutable(element, compilationUnit);
 
   /// Creates an [ElementWalker] which walks the child elements of an extension
   /// element.
@@ -672,15 +99,12 @@
   /// element.
   ElementWalker.forTypedef(GenericTypeAliasElementImpl element)
       : element = element,
-        _parameters = element.parameters,
+        _parameters = element.function.parameters,
         _typeParameters = element.typeParameters;
 
-  ElementWalker._forExecutable(ExecutableElement element,
-      CompilationUnitElement compilationUnit, ElementHolder elementHolder)
+  ElementWalker._forExecutable(
+      ExecutableElement element, CompilationUnitElement compilationUnit)
       : element = element,
-        elementBuilder =
-            new LocalElementBuilder(elementHolder, compilationUnit),
-        _elementHolder = elementHolder,
         _functions = const <ExecutableElement>[],
         _parameters = element.parameters,
         _typeParameters = element.typeParameters;
@@ -758,22 +182,7 @@
     check(_typedefs, _typedefIndex);
     check(_typeParameters, _typeParameterIndex);
     check(_variables, _variableIndex);
-    Element element = this.element;
-    if (element is ExecutableElementImpl) {
-      element.encloseElements(_elementHolder.functions);
-      element.encloseElements(_elementHolder.labels);
-      element.encloseElements(_elementHolder.localVariables);
-    }
   }
 
   static bool _isNotSynthetic(Element e) => !e.isSynthetic;
 }
-
-class _ElementMismatchException extends AnalysisException {
-  /// Creates an exception to refer to the given [compilationUnit], [element],
-  /// and [cause].
-  _ElementMismatchException(
-      CompilationUnitElement compilationUnit, Element element,
-      [CaughtException cause])
-      : super('Element mismatch in $compilationUnit at $element', cause);
-}
diff --git a/pkg/analyzer/lib/src/generated/element_handle.dart b/pkg/analyzer/lib/src/generated/element_handle.dart
deleted file mode 100644
index 4c798bd..0000000
--- a/pkg/analyzer/lib/src/generated/element_handle.dart
+++ /dev/null
@@ -1,17 +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.
-
-@deprecated
-library analyzer.src.generated.element_handle;
-
-export 'package:analyzer/src/dart/element/handle.dart';
-
-/**
- * TODO(scheglov) invalid implementation
- */
-class WeakReference<T> {
-  final T value;
-  WeakReference(this.value);
-  T get() => value;
-}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 16190aa..cb5fd6a 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -259,7 +259,7 @@
         if (library == null) {
           // TODO(brianwilkerson) We need to understand how the library could
           // ever be null.
-          AnalysisEngine.instance.logger
+          AnalysisEngine.instance.instrumentationService
               .logError("Found element with null library: ${element.name}");
         } else if (library != _definingLibrary) {
           // TODO(brianwilkerson) Report this error.
@@ -490,7 +490,7 @@
     bool isInSetterContext = node.inSetterContext();
     if (isInGetterContext && isInSetterContext) {
       node.staticElement = result.setter;
-      node.auxiliaryElements = AuxiliaryElements(result.getter, null);
+      node.auxiliaryElements = AuxiliaryElements(result.getter);
     } else if (isInGetterContext) {
       node.staticElement = result.getter;
     } else if (isInSetterContext) {
@@ -656,10 +656,21 @@
     Token operator = node.operator;
     TokenType operatorType = operator.type;
     if (operatorType.isUserDefinableOperator ||
-        operatorType == TokenType.PLUS_PLUS ||
-        operatorType == TokenType.MINUS_MINUS) {
+        operatorType.isIncrementOperator) {
       Expression operand = node.operand;
       String methodName = _getPrefixOperator(node);
+      if (operand is ExtensionOverride) {
+        ExtensionElement element = operand.extensionName.staticElement;
+        MethodElement member = element.getMethod(methodName);
+        if (member == null) {
+          _resolver.errorReporter.reportErrorForToken(
+              CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
+              node.operator,
+              [methodName, element.name]);
+        }
+        node.staticElement = member;
+        return;
+      }
       DartType staticType = _getStaticType(operand, read: true);
       var result = _newPropertyResolver()
           .resolve(operand, staticType, methodName, operand);
@@ -716,7 +727,7 @@
                 propertyName,
                 [memberName, element.name]);
           }
-          propertyName.auxiliaryElements = AuxiliaryElements(getter, null);
+          propertyName.auxiliaryElements = AuxiliaryElements(getter);
         }
       } else if (propertyName.inGetterContext()) {
         member = result.getter;
@@ -861,7 +872,6 @@
       propertyResolver.resolve(null, enclosingType, node.name, node);
       node.auxiliaryElements = AuxiliaryElements(
         propertyResolver.result.getter,
-        null,
       );
     }
     //
@@ -1128,7 +1138,7 @@
       parameters = (parameterizableType as FunctionType)?.typeFormals;
     }
 
-    if (parameterizableType is ParameterizedType) {
+    if (parameterizableType is FunctionType) {
       NodeList<TypeAnnotation> arguments = typeArguments?.arguments;
       if (arguments != null && arguments.length != parameters.length) {
         _resolver.errorReporter.reportErrorForNode(
@@ -1766,8 +1776,7 @@
         var setter = result.setter;
         if (setter != null) {
           propertyName.staticElement = setter;
-          propertyName.auxiliaryElements =
-              AuxiliaryElements(result.getter, null);
+          propertyName.auxiliaryElements = AuxiliaryElements(result.getter);
         } else {
           var getter = result.getter;
           propertyName.staticElement = getter;
@@ -1966,9 +1975,6 @@
   Token get beginToken => null;
 
   @override
-  Element get bestElement => null;
-
-  @override
   Iterable<SyntacticEntity> get childEntities {
     // Should never be called, since a SyntheticIdentifier never appears in the
     // AST--it is just used for lookup.
@@ -1988,10 +1994,6 @@
   @override
   Precedence get precedence => Precedence.primary;
 
-  @deprecated
-  @override
-  Element get propagatedElement => null;
-
   @override
   Element get staticElement => null;
 
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 8fe0222..f2af195 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -4,6 +4,7 @@
 
 import 'dart:typed_data';
 
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/exception/exception.dart';
@@ -18,7 +19,6 @@
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
-import 'package:front_end/src/fasta/scanner/token.dart';
 import 'package:path/path.dart' as pathos;
 import 'package:pub_semver/pub_semver.dart';
 
@@ -124,17 +124,10 @@
   /// The unique instance of this class.
   static final AnalysisEngine instance = new AnalysisEngine._();
 
-  /// The logger that should receive information about errors within the analysis
-  /// engine.
-  Logger _logger = Logger.NULL;
-
   /// The instrumentation service that is to be used by this analysis engine.
   InstrumentationService _instrumentationService =
       InstrumentationService.NULL_SERVICE;
 
-  /// The partition manager being used to manage the shared partitions.
-  final PartitionManager partitionManager = new PartitionManager();
-
   AnalysisEngine._();
 
   /// Return the instrumentation service that is to be used by this analysis
@@ -151,20 +144,9 @@
     }
   }
 
-  /// Return the logger that should receive information about errors within the
-  /// analysis engine.
-  Logger get logger => _logger;
-
-  /// Set the logger that should receive information about errors within the
-  /// analysis engine to the given [logger].
-  void set logger(Logger logger) {
-    this._logger = logger ?? Logger.NULL;
-  }
-
   /// Clear any caches holding on to analysis results so that a full re-analysis
   /// will be performed the next time an analysis context is created.
   void clearCaches() {
-    partitionManager.clearCache();
     // See https://github.com/dart-lang/sdk/issues/30314.
     StringToken.canonicalizer.clear();
   }
@@ -875,35 +857,6 @@
   void set typeProvider(TypeProvider typeProvider);
 }
 
-/// An object that can be used to receive information about errors within the
-/// analysis engine. Implementations usually write this information to a file,
-/// but can also record the information for later use (such as during testing) or
-/// even ignore the information.
-abstract class Logger {
-  /// A logger that ignores all logging.
-  static final Logger NULL = new NullLogger();
-
-  /// Log the given message as an error. The [message] is expected to be an
-  /// explanation of why the error occurred or what it means. The [exception] is
-  /// expected to be the reason for the error. At least one argument must be
-  /// provided.
-  void logError(String message, [CaughtException exception]);
-
-  /// Log the given informational message. The [message] is expected to be an
-  /// explanation of why the error occurred or what it means. The [exception] is
-  /// expected to be the reason for the error.
-  void logInformation(String message, [CaughtException exception]);
-}
-
-/// An implementation of [Logger] that does nothing.
-class NullLogger implements Logger {
-  @override
-  void logError(String message, [CaughtException exception]) {}
-
-  @override
-  void logInformation(String message, [CaughtException exception]) {}
-}
-
 /// Container with global [AnalysisContext] performance statistics.
 class PerformanceStatistics {
   /// The [PerformanceTag] for `package:analyzer`.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 4bef170..1132017 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -11,7 +11,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/visitor.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -141,15 +140,9 @@
 
   /**
    * A flag indicating whether the visitor is currently within an instance
-   * variable declaration.
+   * variable declaration, which is not `late`.
    */
-  bool _isInInstanceVariableDeclaration = false;
-
-  /**
-   * A flag indicating whether the visitor is currently within an instance
-   * variable initializer.
-   */
-  bool _isInInstanceVariableInitializer = false;
+  bool _isInInstanceNotLateVariableDeclaration = false;
 
   /**
    * A flag indicating whether the visitor is currently within a constructor
@@ -306,23 +299,11 @@
 
   /**
    * Initialize a newly created error verifier.
-   *
-   * [inheritanceManager] should be an instance of either [InheritanceManager2]
-   * or [InheritanceManager3].  If an [InheritanceManager2] is supplied, it
-   * will be converted into an [InheritanceManager3] internally.  The ability
-   * to pass in [InheritanceManager2] exists for backward compatibility; in a
-   * future major version of the analyzer, an [InheritanceManager3] will
-   * be required.
    */
-  ErrorVerifier(
-      ErrorReporter errorReporter,
-      this._currentLibrary,
-      this._typeProvider,
-      InheritanceManagerBase inheritanceManager,
-      bool enableSuperMixins,
+  ErrorVerifier(ErrorReporter errorReporter, this._currentLibrary,
+      this._typeProvider, this._inheritanceManager, bool enableSuperMixins,
       {this.disableConflictingGenericsCheck: false})
       : _errorReporter = errorReporter,
-        _inheritanceManager = inheritanceManager.asInheritanceManager3,
         _uninstantiatedBoundChecker =
             new _UninstantiatedBoundChecker(errorReporter),
         _requiredParametersVerifier = RequiredParametersVerifier(errorReporter),
@@ -333,8 +314,6 @@
     _isEnclosingConstructorConst = false;
     _isInCatchClause = false;
     _isInStaticVariableDeclaration = false;
-    _isInInstanceVariableDeclaration = false;
-    _isInInstanceVariableInitializer = false;
     _isInConstructorInitializer = false;
     _isInStaticMethod = false;
     _boolType = _typeProvider.boolType;
@@ -507,11 +486,6 @@
     }
   }
 
-  void visitCascadeExpression(CascadeExpression node) {
-    _checkForNullableDereference(node.target);
-    super.visitCascadeExpression(node);
-  }
-
   @override
   void visitCatchClause(CatchClause node) {
     _duplicateDefinitionVerifier.checkCatchClause(node);
@@ -624,7 +598,6 @@
         _checkForAllRedirectConstructorErrorCodes(node);
       }
       _checkForUndefinedConstructorInInitializerImplicit(node);
-      _checkForRedirectToNonConstConstructor(node, constructorElement);
       _checkForReturnInGenerativeConstructor(node);
       super.visitConstructorDeclaration(node);
     } finally {
@@ -743,13 +716,14 @@
 
   @override
   void visitFieldDeclaration(FieldDeclaration node) {
+    var fields = node.fields;
     _isInStaticVariableDeclaration = node.isStatic;
-    _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration;
-    if (_isInInstanceVariableDeclaration) {
-      VariableDeclarationList variables = node.fields;
-      if (variables.isConst) {
+    _isInInstanceNotLateVariableDeclaration =
+        !node.isStatic && !node.fields.isLate;
+    if (!_isInStaticVariableDeclaration) {
+      if (fields.isConst) {
         _errorReporter.reportErrorForToken(
-            CompileTimeErrorCode.CONST_INSTANCE_FIELD, variables.keyword);
+            CompileTimeErrorCode.CONST_INSTANCE_FIELD, fields.keyword);
       }
     }
     try {
@@ -757,7 +731,7 @@
       super.visitFieldDeclaration(node);
     } finally {
       _isInStaticVariableDeclaration = false;
-      _isInInstanceVariableDeclaration = false;
+      _isInInstanceNotLateVariableDeclaration = false;
     }
   }
 
@@ -914,7 +888,7 @@
     _checkForBuiltInIdentifierAsName(
         node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
     _checkForDefaultValueInFunctionTypeAlias(node);
-    _checkForTypeAliasCannotReferenceItself_function(node);
+    _checkForTypeAliasCannotReferenceItself(node, node.declaredElement);
     super.visitFunctionTypeAlias(node);
   }
 
@@ -947,10 +921,7 @@
 
   @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
-    if (_hasTypedefSelfReference(node.declaredElement)) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, node);
-    }
+    _checkForTypeAliasCannotReferenceItself(node, node.declaredElement);
     super.visitGenericTypeAlias(node);
   }
 
@@ -990,7 +961,7 @@
   void visitIndexExpression(IndexExpression node) {
     _checkForArgumentTypeNotAssignableForArgument(node.index);
     if (!node.isNullAware) {
-      _checkForNullableDereference(node.target);
+      _checkForNullableDereference(node.realTarget);
     }
     super.visitIndexExpression(node);
   }
@@ -1213,7 +1184,7 @@
         typeReference, node.target, propertyName);
     if (!node.isNullAware &&
         !_objectPropertyNames.contains(propertyName.name)) {
-      _checkForNullableDereference(node.target);
+      _checkForNullableDereference(node.realTarget);
     }
     _checkForUnnecessaryNullAware(node.target, node.operator);
     super.visitPropertyAccess(node);
@@ -1397,14 +1368,11 @@
     // visit initializer
     String name = nameNode.name;
     _namesForReferenceToDeclaredVariableInInitializer.add(name);
-    bool wasInInstanceVariableInitializer = _isInInstanceVariableInitializer;
-    _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration;
     try {
       if (initializerNode != null) {
         initializerNode.accept(this);
       }
     } finally {
-      _isInInstanceVariableInitializer = wasInInstanceVariableInitializer;
       _namesForReferenceToDeclaredVariableInInitializer.remove(name);
     }
     // declare the variable
@@ -3255,10 +3223,13 @@
    */
   void _checkForImplicitThisReferenceInInitializer(
       SimpleIdentifier identifier) {
+    if (_isInComment) {
+      return;
+    }
     if (!_isInConstructorInitializer &&
         !_isInStaticMethod &&
         !_isInFactory &&
-        !_isInInstanceVariableInitializer &&
+        !_isInInstanceNotLateVariableDeclaration &&
         !_isInStaticVariableDeclaration) {
       return;
     }
@@ -3277,12 +3248,8 @@
     if (enclosingElement is! ClassElement) {
       return;
     }
-    // comment
-    AstNode parent = identifier.parent;
-    if (parent is CommentReference) {
-      return;
-    }
     // qualified method invocation
+    AstNode parent = identifier.parent;
     if (parent is MethodInvocation) {
       if (identical(parent.methodName, identifier) &&
           parent.realTarget != null) {
@@ -3539,8 +3506,9 @@
       InstanceCreationExpression node, InterfaceType type) {
     if (!_isNonNullable) return;
 
-    if (node.argumentList.arguments.length == 1 &&
-        _isDartCoreList(type) &&
+    if (node.constructorName.name == null &&
+        node.argumentList.arguments.length == 1 &&
+        type.isDartCoreList &&
         _typeSystem.isPotentiallyNonNullable(type.typeArguments[0])) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH,
@@ -4564,6 +4532,8 @@
               parameter.identifier);
         }
       }
+      _checkForRedirectToNonConstConstructor(declaration.declaredElement,
+          redirectedConstructor.staticElement, redirectedConstructor);
     }
     // check if there are redirected invocations
     int numRedirections = 0;
@@ -4596,6 +4566,10 @@
             }
           }
         }
+        // [declaration] is a redirecting constructor via a redirecting
+        // initializer.
+        _checkForRedirectToNonConstConstructor(declaration.declaredElement,
+            initializer.staticElement, initializer.constructorName);
         numRedirections++;
       }
     }
@@ -4622,41 +4596,21 @@
   }
 
   /**
-   * Check whether the given constructor [declaration] has redirected
-   * constructor and references itself directly or indirectly. The
-   * constructor [element] is the element introduced by the declaration.
+   * Check whether the redirecting constructor, [element], is const, and
+   * [redirectedElement], its redirectee, is not const.
    *
    * See [CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR].
    */
-  void _checkForRedirectToNonConstConstructor(
-      ConstructorDeclaration declaration, ConstructorElement element) {
-    // prepare redirected constructor
-    ConstructorName redirectedConstructorNode =
-        declaration.redirectedConstructor;
-    if (redirectedConstructorNode == null) {
-      return;
+  void _checkForRedirectToNonConstConstructor(ConstructorElement element,
+      ConstructorElement redirectedElement, AstNode reportingNode) {
+    // This constructor is const, but it redirects to a non-const constructor.
+    if (redirectedElement != null &&
+        element.isConst &&
+        !redirectedElement.isConst) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
+          reportingNode);
     }
-    // prepare element
-    if (element == null) {
-      return;
-    }
-    // OK, it is not 'const'
-    if (!element.isConst) {
-      return;
-    }
-    // prepare redirected constructor
-    ConstructorElement redirectedConstructor = element.redirectedConstructor;
-    if (redirectedConstructor == null) {
-      return;
-    }
-    // OK, it is also 'const'
-    if (redirectedConstructor.isConst) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR,
-        redirectedConstructorNode);
   }
 
   void _checkForReferenceBeforeDeclaration(SimpleIdentifier node) {
@@ -4915,16 +4869,20 @@
   }
 
   /**
-   * Verify that the given function type [alias] does not reference itself
-   * directly.
+   * Verify that the given [element] does not reference itself directly.
+   * If it does, report the error on the [node].
    *
    * See [CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF].
    */
-  void _checkForTypeAliasCannotReferenceItself_function(
-      FunctionTypeAlias alias) {
-    if (_hasTypedefSelfReference(alias.declaredElement)) {
+  void _checkForTypeAliasCannotReferenceItself(
+    AstNode node,
+    FunctionTypeAliasElement element,
+  ) {
+    if ((element as GenericTypeAliasElementImpl).hasSelfReference) {
       _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, alias);
+        CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
+        node,
+      );
     }
   }
 
@@ -5530,9 +5488,6 @@
       FormalParameter parameter = parameters[i];
       if (parameter.isOptional) {
         DartType type = parameter.declaredElement.type;
-        if (type.isDartAsyncFutureOr) {
-          type = (type as ParameterizedType).typeArguments[0];
-        }
         if ((parameter as DefaultFormalParameter).defaultValue == null) {
           if (_typeSystem.isPotentiallyNonNullable(type)) {
             SimpleIdentifier parameterName = _parameterName(parameter);
@@ -5807,22 +5762,6 @@
     return false;
   }
 
-  /**
-   * Return `true` if the given [element] has direct or indirect reference to
-   * itself from anywhere except a class element or type parameter bounds.
-   */
-  bool _hasTypedefSelfReference(GenericTypeAliasElement element) {
-    if (element == null) {
-      return false;
-    }
-    if (element is GenericTypeAliasElementImpl && element.linkedNode != null) {
-      return element.hasSelfReference;
-    }
-    var visitor = new _HasTypedefSelfReferenceVisitor(element.function);
-    element.accept(visitor);
-    return visitor.hasSelfReference;
-  }
-
   void _initializeInitialFieldElementsMap(List<FieldElement> fields) {
     _initialFieldElementsMap = new HashMap<FieldElement, INIT_STATE>();
     for (FieldElement fieldElement in fields) {
@@ -5835,14 +5774,6 @@
     }
   }
 
-  bool _isDartCoreList(InterfaceType type) {
-    ClassElement element = type.element;
-    if (element == null) {
-      return false;
-    }
-    return element.name == "List" && element.library.isDartCore;
-  }
-
   bool _isFunctionType(DartType type) {
     if (type.isDynamic || type.isDartCoreNull) {
       return true;
@@ -6048,73 +5979,6 @@
   }
 }
 
-class _HasTypedefSelfReferenceVisitor extends GeneralizingElementVisitor<void> {
-  final GenericFunctionTypeElement element;
-  bool hasSelfReference = false;
-
-  _HasTypedefSelfReferenceVisitor(this.element);
-
-  @override
-  void visitClassElement(ClassElement element) {
-    // Typedefs are allowed to reference themselves via classes.
-  }
-
-  @override
-  void visitFunctionElement(FunctionElement element) {
-    _addTypeToCheck(element.returnType);
-    super.visitFunctionElement(element);
-  }
-
-  @override
-  void visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
-    _addTypeToCheck(element.returnType);
-    super.visitFunctionTypeAliasElement(element);
-  }
-
-  @override
-  void visitGenericFunctionTypeElement(GenericFunctionTypeElement element) {
-    _addTypeToCheck(element.returnType);
-    super.visitGenericFunctionTypeElement(element);
-  }
-
-  @override
-  void visitParameterElement(ParameterElement element) {
-    _addTypeToCheck(element.type);
-    super.visitParameterElement(element);
-  }
-
-  @override
-  void visitTypeParameterElement(TypeParameterElement element) {
-    _addTypeToCheck(element.bound);
-    super.visitTypeParameterElement(element);
-  }
-
-  void _addTypeToCheck(DartType type) {
-    if (hasSelfReference) {
-      return;
-    }
-    if (type == null) {
-      return;
-    }
-    if (type.element == element) {
-      hasSelfReference = true;
-      return;
-    }
-    if (type is FunctionType) {
-      _addTypeToCheck(type.returnType);
-      for (ParameterElement parameter in type.parameters) {
-        _addTypeToCheck(parameter.type);
-      }
-    }
-    // type arguments
-    if (type is InterfaceType) {
-      for (DartType typeArgument in type.typeArguments) {
-        _addTypeToCheck(typeArgument);
-      }
-    }
-  }
-}
-
 /**
  * Recursively visits an AST, looking for method invocations.
  */
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 38a0dbe..3d30728 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -14,6 +14,23 @@
 /// used. See 'pkg/vm/lib/transformations/ffi_checks.md' for the specification
 /// of the desired hints.
 class FfiVerifier extends RecursiveAstVisitor<void> {
+  static const List<String> _primitiveIntegerNativeTypes = [
+    'Int8',
+    'Int16',
+    'Int32',
+    'Int64',
+    'Uint8',
+    'Uint16',
+    'Uint32',
+    'Uint64',
+    'IntPtr'
+  ];
+
+  static const List<String> _primitiveDoubleNativeTypes = [
+    'Float',
+    'Double',
+  ];
+
   /// The type system used to check types.
   final TypeSystem typeSystem;
 
@@ -140,10 +157,57 @@
   bool _isDynamicLibrary(ClassElement element) =>
       element.name == 'DynamicLibrary' && element.library.name == 'dart.ffi';
 
+  /// 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') {
+        return element.name == 'NativeFunction' &&
+            nativeType.typeArguments?.length == 1;
+      }
+    }
+    return false;
+  }
+
+  /// 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') {
+        return element.name == 'NativeType';
+      }
+    }
+    return false;
+  }
+
   /// Return `true` if the given [element] represents the class `Pointer`.
   bool _isPointer(Element element) =>
       element.name == 'Pointer' && element.library.name == 'dart.ffi';
 
+  /// 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') {
+        return element.name == 'Pointer' &&
+            nativeType.typeArguments?.length == 1;
+      }
+    }
+    return false;
+  }
+
+  /// Returns `true` iff [nativeType] is a struct type.
+  _isStructClass(DartType nativeType) {
+    if (nativeType is InterfaceType) {
+      final superClassElement = nativeType.element.supertype.element;
+      if (superClassElement.library.name == 'dart.ffi') {
+        return superClassElement.name == 'Struct' &&
+            nativeType.typeArguments?.isEmpty == true;
+      }
+    }
+    return false;
+  }
+
   /// Return `true` if the [typeName] represents a subtype of `Struct`.
   bool _isSubtypeOfStruct(TypeName typeName) {
     Element superType = typeName.name.staticElement;
@@ -161,6 +225,71 @@
     return false;
   }
 
+  /// Validates that the given type is a valid dart:ffi native function
+  /// signature.
+  bool _isValidFfiNativeFunctionType(DartType nativeType) {
+    if (nativeType is FunctionType && !nativeType.isDartCoreFunction) {
+      if (nativeType.namedParameterTypes.isNotEmpty ||
+          nativeType.optionalParameterTypes.isNotEmpty) {
+        return false;
+      }
+      if (!_isValidFfiNativeType(nativeType.returnType, true)) {
+        return false;
+      }
+
+      for (final DartType typeArg in nativeType.typeArguments) {
+        if (!_isValidFfiNativeType(typeArg, false)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  /// Validates that the given [nativeType] is a valid dart:ffi native type.
+  bool _isValidFfiNativeType(DartType nativeType, bool allowVoid) {
+    if (nativeType is InterfaceType) {
+      // Is it a primitive integer/double type (or ffi.Void if we allow it).
+      final primitiveType = _primitiveNativeType(nativeType);
+      if (primitiveType != _PrimitiveDartType.none &&
+          (primitiveType != _PrimitiveDartType.void_ || allowVoid)) {
+        return true;
+      }
+      if (_isNativeFunctionInterfaceType(nativeType)) {
+        return _isValidFfiNativeFunctionType(nativeType.typeArguments.single);
+      }
+      if (_isPointerInterfaceType(nativeType)) {
+        final nativeArgumentType = nativeType.typeArguments.single;
+        return _isValidFfiNativeType(nativeArgumentType, true) ||
+            _isStructClass(nativeArgumentType) ||
+            _isNativeTypeInterfaceType(nativeArgumentType);
+      }
+    } else if (nativeType is FunctionType) {
+      return _isValidFfiNativeFunctionType(nativeType);
+    }
+    return false;
+  }
+
+  _PrimitiveDartType _primitiveNativeType(DartType nativeType) {
+    if (nativeType is InterfaceType) {
+      final element = nativeType.element;
+      if (element.library.name == 'dart.ffi') {
+        final String name = element.name;
+        if (_primitiveIntegerNativeTypes.contains(name)) {
+          return _PrimitiveDartType.int;
+        }
+        if (_primitiveDoubleNativeTypes.contains(name)) {
+          return _PrimitiveDartType.double;
+        }
+        if (name == 'Void') {
+          return _PrimitiveDartType.void_;
+        }
+      }
+    }
+    return _PrimitiveDartType.none;
+  }
+
   /// Return an indication of the Dart type associated with the [annotation].
   _PrimitiveDartType _typeForAnnotation(Annotation annotation) {
     Element element = annotation.element;
@@ -248,6 +377,79 @@
     }
   }
 
+  /// Validates that the given [nativeType] is, when native types are converted
+  /// to their Dart equivalent, a subtype of [dartType].
+  bool _validateCompatibleFunctionTypes(
+      DartType dartType, DartType nativeType) {
+    // We require both to be valid function types.
+    if (dartType is! FunctionType ||
+        dartType.isDartCoreFunction ||
+        nativeType is! FunctionType ||
+        nativeType.isDartCoreFunction) {
+      return false;
+    }
+
+    final dartFType = dartType as FunctionType;
+    final nativeFType = nativeType as FunctionType;
+
+    // We disallow any optional parameters.
+    final int parameterCount = dartFType.normalParameterTypes.length;
+    if (parameterCount != nativeFType.normalParameterTypes.length) {
+      return false;
+    }
+    // We disallow generic function types.
+    if (dartFType.typeFormals.isNotEmpty ||
+        nativeFType.typeFormals.isNotEmpty) {
+      return false;
+    }
+    if (dartFType.namedParameterTypes.isNotEmpty ||
+        dartFType.optionalParameterTypes.isNotEmpty ||
+        nativeFType.namedParameterTypes.isNotEmpty ||
+        nativeFType.optionalParameterTypes.isNotEmpty) {
+      return false;
+    }
+
+    // Validate that the return types are compatible.
+    if (!_validateCompatibleNativeType(
+        dartFType.returnType, nativeFType.returnType, false)) {
+      return false;
+    }
+
+    // Validate that the parameter types are compatible.
+    for (int i = 0; i < parameterCount; ++i) {
+      if (!_validateCompatibleNativeType(dartFType.normalParameterTypes[i],
+          nativeFType.normalParameterTypes[i], true)) {
+        return false;
+      }
+    }
+
+    // Signatures have same number of parameters and the types match.
+    return true;
+  }
+
+  /// Validates that, if we convert [nativeType] to it's corresponding
+  /// [dartType] the latter is a subtype of the former if
+  /// [checkCovariance].
+  bool _validateCompatibleNativeType(
+      DartType dartType, DartType nativeType, bool checkCovariance) {
+    final nativeReturnType = _primitiveNativeType(nativeType);
+    if (nativeReturnType == _PrimitiveDartType.int) {
+      return dartType.isDartCoreInt;
+    } else if (nativeReturnType == _PrimitiveDartType.double) {
+      return dartType.isDartCoreDouble;
+    } else if (nativeReturnType == _PrimitiveDartType.void_) {
+      return dartType.isVoid;
+    } else if (dartType is InterfaceType && nativeType is InterfaceType) {
+      return checkCovariance
+          ? typeSystem.isSubtypeOf(dartType, nativeType)
+          : typeSystem.isSubtypeOf(nativeType, dartType);
+    } else {
+      // If the [nativeType] is not a primitive int/double type then it has to
+      // be a Pointer type atm.
+      return false;
+    }
+  }
+
   /// Validate that the fields declared by the given [node] meet the
   /// requirements for fields within a struct class.
   void _validateFieldsInStruct(FieldDeclaration node) {
@@ -377,208 +579,6 @@
     }
     return false;
   }
-
-  /// Validates that the given [nativeType] is, when native types are converted
-  /// to their Dart equivalent, a subtype of [dartType].
-  bool _validateCompatibleFunctionTypes(
-      DartType dartType, DartType nativeType) {
-    // We require both to be valid function types.
-    if (dartType is! FunctionType ||
-        dartType.isDartCoreFunction ||
-        nativeType is! FunctionType ||
-        nativeType.isDartCoreFunction) {
-      return false;
-    }
-
-    final dartFType = dartType as FunctionType;
-    final nativeFType = nativeType as FunctionType;
-
-    // We disallow any optional parameters.
-    final int parameterCount = dartFType.normalParameterTypes.length;
-    if (parameterCount != nativeFType.normalParameterTypes.length) {
-      return false;
-    }
-    // We disallow generic function types.
-    if (dartFType.typeFormals.isNotEmpty ||
-        nativeFType.typeFormals.isNotEmpty) {
-      return false;
-    }
-    if (dartFType.namedParameterTypes.isNotEmpty ||
-        dartFType.optionalParameterTypes.isNotEmpty ||
-        nativeFType.namedParameterTypes.isNotEmpty ||
-        nativeFType.optionalParameterTypes.isNotEmpty) {
-      return false;
-    }
-
-    // Validate that the return types are compatible.
-    if (!_validateCompatibleNativeType(
-        dartFType.returnType, nativeFType.returnType, false)) {
-      return false;
-    }
-
-    // Validate that the parameter types are compatible.
-    for (int i = 0; i < parameterCount; ++i) {
-      if (!_validateCompatibleNativeType(dartFType.normalParameterTypes[i],
-          nativeFType.normalParameterTypes[i], true)) {
-        return false;
-      }
-    }
-
-    // Signatures have same number of parameters and the types match.
-    return true;
-  }
-
-  // Validates that, if we convert [nativeType] to it's corresponding
-  // [dartType] the latter is a subtype of the former if
-  // [checkCovariance].
-  bool _validateCompatibleNativeType(
-      DartType dartType, DartType nativeType, bool checkCovariance) {
-    final nativeReturnType = _primitiveNativeType(nativeType);
-    if (nativeReturnType == _PrimitiveDartType.int) {
-      return dartType.isDartCoreInt;
-    } else if (nativeReturnType == _PrimitiveDartType.double) {
-      return dartType.isDartCoreDouble;
-    } else if (nativeReturnType == _PrimitiveDartType.void_) {
-      return dartType.isVoid;
-    } else if (dartType is InterfaceType && nativeType is InterfaceType) {
-      return checkCovariance
-          ? typeSystem.isSubtypeOf(dartType, nativeType)
-          : typeSystem.isSubtypeOf(nativeType, dartType);
-    } else {
-      // If the [nativeType] is not a primitive int/double type then it has to
-      // be a Pointer type atm.
-      return false;
-    }
-  }
-
-  // Validates that the given type is a valid dart:ffi native function
-  // signature.
-  bool _isValidFfiNativeFunctionType(DartType nativeType) {
-    if (nativeType is FunctionType && !nativeType.isDartCoreFunction) {
-      if (nativeType.namedParameterTypes.isNotEmpty ||
-          nativeType.optionalParameterTypes.isNotEmpty) {
-        return false;
-      }
-      if (!_isValidFfiNativeType(nativeType.returnType, true)) {
-        return false;
-      }
-
-      for (final DartType typeArg in nativeType.typeArguments) {
-        if (!_isValidFfiNativeType(typeArg, false)) {
-          return false;
-        }
-      }
-      return true;
-    }
-    return false;
-  }
-
-  // Validates that the given [nativeType] is a valid dart:ffi native type.
-  bool _isValidFfiNativeType(DartType nativeType, bool allowVoid) {
-    if (nativeType is InterfaceType) {
-      // Is it a primitive integer/double type (or ffi.Void if we allow it).
-      final primitiveType = _primitiveNativeType(nativeType);
-      if (primitiveType != _PrimitiveDartType.none &&
-          (primitiveType != _PrimitiveDartType.void_ || allowVoid)) {
-        return true;
-      }
-      if (_isNativeFunctionInterfaceType(nativeType)) {
-        return _isValidFfiNativeFunctionType(nativeType.typeArguments.single);
-      }
-      if (_isPointerInterfaceType(nativeType)) {
-        final nativeArgumentType = nativeType.typeArguments.single;
-        return _isValidFfiNativeType(nativeArgumentType, true) ||
-            _isStructClass(nativeArgumentType) ||
-            _isNativeTypeInterfaceType(nativeArgumentType);
-      }
-    } else if (nativeType is FunctionType) {
-      return _isValidFfiNativeFunctionType(nativeType);
-    }
-    return false;
-  }
-
-  _PrimitiveDartType _primitiveNativeType(DartType nativeType) {
-    if (nativeType is InterfaceType) {
-      final element = nativeType.element;
-      if (element.library.name == 'dart.ffi') {
-        final String name = element.name;
-        if (_primitiveIntegerNativeTypes.contains(name)) {
-          return _PrimitiveDartType.int;
-        }
-        if (_primitiveDoubleNativeTypes.contains(name)) {
-          return _PrimitiveDartType.double;
-        }
-        if (name == 'Void') {
-          return _PrimitiveDartType.void_;
-        }
-      }
-    }
-    return _PrimitiveDartType.none;
-  }
-
-  // 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') {
-        return element.name == 'NativeFunction' &&
-            nativeType.typeArguments?.length == 1;
-      }
-    }
-    return false;
-  }
-
-  // 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') {
-        return element.name == 'Pointer' &&
-            nativeType.typeArguments?.length == 1;
-      }
-    }
-    return false;
-  }
-
-  // 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') {
-        return element.name == 'NativeType';
-      }
-    }
-    return false;
-  }
-
-  // Returns `true` iff [nativeType] is a struct type.
-  _isStructClass(DartType nativeType) {
-    if (nativeType is InterfaceType) {
-      final superClassElement = nativeType.element.supertype.element;
-      if (superClassElement.library.name == 'dart.ffi') {
-        return superClassElement.name == 'Struct' &&
-            nativeType.typeArguments?.isEmpty == true;
-      }
-    }
-    return false;
-  }
-
-  static const List<String> _primitiveIntegerNativeTypes = [
-    'Int8',
-    'Int16',
-    'Int32',
-    'Int64',
-    'Uint8',
-    'Uint16',
-    'Uint32',
-    'Uint64',
-    'IntPtr'
-  ];
-
-  static const List<String> _primitiveDoubleNativeTypes = [
-    'Float',
-    'Double',
-  ];
 }
 
 enum _PrimitiveDartType {
diff --git a/pkg/analyzer/lib/src/generated/interner.dart b/pkg/analyzer/lib/src/generated/interner.dart
index 652537f..1f0ea1d 100644
--- a/pkg/analyzer/lib/src/generated/interner.dart
+++ b/pkg/analyzer/lib/src/generated/interner.dart
@@ -4,9 +4,9 @@
 
 import 'dart:collection';
 
-import 'package:front_end/src/scanner/interner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/interner.dart';
 
-export 'package:front_end/src/scanner/interner.dart'
+export 'package:_fe_analyzer_shared/src/scanner/interner.dart'
     show Interner, NullInterner;
 
 /**
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 58b6393..621d1ee 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -7,6 +7,12 @@
 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';
@@ -25,11 +31,6 @@
 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:front_end/src/fasta/parser/identifier_context.dart' as fasta;
-import 'package:front_end/src/fasta/parser/member_kind.dart' as fasta;
-import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
-import 'package:front_end/src/fasta/parser/type_info.dart' as fasta;
-import 'package:front_end/src/fasta/scanner.dart' as fasta;
 import 'package:meta/meta.dart';
 
 export 'package:analyzer/src/dart/ast/utilities.dart' show ResolutionCopier;
@@ -307,7 +308,7 @@
     bool stringEndsAfterStart = end >= start;
     assert(stringEndsAfterStart);
     if (!stringEndsAfterStart) {
-      AnalysisEngine.instance.logger.logError(
+      AnalysisEngine.instance.instrumentationService.logError(
           "Internal error: computeStringValue($lexeme, $isFirst, $isLast)");
       return "";
     }
diff --git a/pkg/analyzer/lib/src/generated/parser_fasta.dart b/pkg/analyzer/lib/src/generated/parser_fasta.dart
index e5b6f3d..40d68b3 100644
--- a/pkg/analyzer/lib/src/generated/parser_fasta.dart
+++ b/pkg/analyzer/lib/src/generated/parser_fasta.dart
@@ -157,9 +157,7 @@
   @override
   CompilationUnit parseCompilationUnit2() {
     currentToken = fastaParser.parseUnit(currentToken);
-    CompilationUnitImpl compilationUnit = astBuilder.pop();
-    compilationUnit.localDeclarations = astBuilder.localDeclarations;
-    return compilationUnit;
+    return astBuilder.pop();
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 4fbbf74..d0e1e5f 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -6,7 +6,7 @@
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/ast_factory.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/dart/element/element.dart';
@@ -18,7 +18,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@@ -46,7 +45,6 @@
 
 export 'package:analyzer/src/dart/constant/constant_verifier.dart';
 export 'package:analyzer/src/dart/resolver/exit_detector.dart';
-export 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 export 'package:analyzer/src/dart/resolver/scope.dart';
 export 'package:analyzer/src/generated/type_system.dart';
 
@@ -120,19 +118,18 @@
             new _InvalidAccessVerifier(_errorReporter, _currentLibrary) {
     _inDeprecatedMember = _currentLibrary.hasDeprecated;
     String libraryPath = _currentLibrary.source.fullName;
-    ContextBuilder builder = new ContextBuilder(
-        resourceProvider, null /* sdkManager */, null /* contentCache */);
-    Workspace workspace =
-        ContextBuilder.createWorkspace(resourceProvider, libraryPath, builder);
-    _workspacePackage = workspace.findPackageFor(libraryPath);
+    _workspacePackage = _getPackage(libraryPath, resourceProvider);
+
     _linterContext = LinterContextImpl(
-        null /* allUnits */,
-        new LinterContextUnit(content, unit),
-        declaredVariables,
-        typeProvider,
-        _typeSystem,
-        _inheritanceManager,
-        analysisOptions);
+      null /* allUnits */,
+      new LinterContextUnit(content, unit),
+      declaredVariables,
+      typeProvider,
+      _typeSystem,
+      _inheritanceManager,
+      analysisOptions,
+      _workspacePackage,
+    );
   }
 
   @override
@@ -157,6 +154,27 @@
         _errorReporter
             .reportErrorForNode(HintCode.INVALID_LITERAL_ANNOTATION, node, []);
       }
+    } else if (element?.isNonVirtual == true) {
+      if (parent is FieldDeclaration) {
+        if (parent.isStatic) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_NON_VIRTUAL_ANNOTATION,
+              node,
+              [node.element.name]);
+        }
+      } else if (parent is MethodDeclaration) {
+        if (parent.parent is ExtensionDeclaration ||
+            parent.isStatic ||
+            parent.isAbstract) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_NON_VIRTUAL_ANNOTATION,
+              node,
+              [node.element.name]);
+        }
+      } else {
+        _errorReporter.reportErrorForNode(
+            HintCode.INVALID_NON_VIRTUAL_ANNOTATION, node, [node.element.name]);
+      }
     } else if (element?.isSealed == true) {
       if (!(parent is ClassDeclaration || parent is ClassTypeAlias)) {
         _errorReporter.reportErrorForNode(
@@ -292,6 +310,37 @@
 
     try {
       super.visitFieldDeclaration(node);
+      for (var field in node.fields.variables) {
+        ExecutableElement getOverriddenPropertyAccessor() {
+          final element = field.declaredElement;
+          if (element is PropertyAccessorElement || element is FieldElement) {
+            Name name = new Name(_currentLibrary.source.uri, element.name);
+            Element enclosingElement = element.enclosingElement;
+            if (enclosingElement is ClassElement) {
+              InterfaceType classType = enclosingElement.thisType;
+              var overridden = _inheritanceManager.getMember(classType, name,
+                  forSuper: true);
+              // Check for a setter.
+              if (overridden == null) {
+                Name setterName =
+                    new Name(_currentLibrary.source.uri, '${element.name}=');
+                overridden = _inheritanceManager
+                    .getMember(classType, setterName, forSuper: true);
+              }
+              return overridden;
+            }
+          }
+          return null;
+        }
+
+        final overriddenElement = getOverriddenPropertyAccessor();
+        if (_hasNonVirtualAnnotation(overriddenElement)) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER,
+              field.name,
+              [field.name, overriddenElement.enclosingElement.name]);
+        }
+      }
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
     }
@@ -421,17 +470,24 @@
   void visitMethodDeclaration(MethodDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
     ExecutableElement element = node.declaredElement;
-    bool elementIsOverride() {
-      if (element is ClassMemberElement) {
-        Name name = new Name(_currentLibrary.source.uri, element.name);
-        Element enclosingElement = element.enclosingElement;
-        if (enclosingElement is ClassElement) {
-          InterfaceType classType = enclosingElement.thisType;
-          return _inheritanceManager.getOverridden(classType, name) != null;
-        }
-      }
-      return false;
-    }
+    Element enclosingElement = element?.enclosingElement;
+
+    InterfaceType classType =
+        enclosingElement is ClassElement ? enclosingElement.thisType : null;
+    Name name = Name(_currentLibrary.source.uri, element?.name ?? '');
+
+    bool elementIsOverride() =>
+        element is ClassMemberElement && enclosingElement != null
+            ? _inheritanceManager.getOverridden(classType, name) != null
+            : false;
+    ExecutableElement getConcreteOverriddenElement() =>
+        element is ClassMemberElement && enclosingElement != null
+            ? _inheritanceManager.getMember(classType, name, forSuper: true)
+            : null;
+    ExecutableElement getOverriddenPropertyAccessor() =>
+        element is PropertyAccessorElement && enclosingElement != null
+            ? _inheritanceManager.getMember(classType, name, forSuper: true)
+            : null;
 
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
@@ -441,10 +497,24 @@
       //checkForOverridingPrivateMember(node);
       _checkForMissingReturn(node.returnType, node.body, element, node);
       _checkForUnnecessaryNoSuchMethod(node);
+
       if (_strictInference && !node.isSetter && !elementIsOverride()) {
         _checkStrictInferenceReturnType(node.returnType, node, node.name.name);
       }
       _checkStrictInferenceInParameters(node.parameters);
+
+      ExecutableElement overriddenElement = getConcreteOverriddenElement();
+      if (overriddenElement == null && (node.isSetter || node.isGetter)) {
+        overriddenElement = getOverriddenPropertyAccessor();
+      }
+
+      if (_hasNonVirtualAnnotation(overriddenElement)) {
+        _errorReporter.reportErrorForNode(
+            HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER,
+            node.name,
+            [node.name, overriddenElement.enclosingElement.name]);
+      }
+
       super.visitMethodDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
@@ -541,8 +611,8 @@
   bool _checkAllTypeChecks(IsExpression node) {
     Expression expression = node.expression;
     TypeAnnotation typeName = node.type;
-    DartType lhsType = expression.staticType;
-    DartType rhsType = typeName.type;
+    TypeImpl lhsType = expression.staticType;
+    TypeImpl rhsType = typeName.type;
     if (lhsType == null || rhsType == null) {
       return false;
     }
@@ -563,29 +633,53 @@
     Element rhsElement = rhsType.element;
     LibraryElement libraryElement = rhsElement?.library;
     if (libraryElement != null && libraryElement.isDartCore) {
-      // if x is Object or null is Null
-      if (rhsType.isObject ||
-          (expression is NullLiteral && rhsNameStr == _NULL_TYPE_NAME)) {
-        if (node.notOperator == null) {
-          // the is case
-          _errorReporter.reportErrorForNode(
-              HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node);
+      // `is Null` or `is! Null`
+      if (rhsNameStr == _NULL_TYPE_NAME) {
+        if (expression is NullLiteral) {
+          if (node.notOperator == null) {
+            _errorReporter.reportErrorForNode(
+              HintCode.UNNECESSARY_TYPE_CHECK_TRUE,
+              node,
+            );
+          } else {
+            _errorReporter.reportErrorForNode(
+              HintCode.UNNECESSARY_TYPE_CHECK_FALSE,
+              node,
+            );
+          }
         } else {
-          // the is not case
-          _errorReporter.reportErrorForNode(
-              HintCode.UNNECESSARY_TYPE_CHECK_FALSE, node);
+          if (node.notOperator == null) {
+            _errorReporter.reportErrorForNode(
+              HintCode.TYPE_CHECK_IS_NULL,
+              node,
+            );
+          } else {
+            _errorReporter.reportErrorForNode(
+              HintCode.TYPE_CHECK_IS_NOT_NULL,
+              node,
+            );
+          }
         }
         return true;
-      } else if (rhsNameStr == _NULL_TYPE_NAME) {
-        if (node.notOperator == null) {
-          // the is case
-          _errorReporter.reportErrorForNode(HintCode.TYPE_CHECK_IS_NULL, node);
-        } else {
-          // the is not case
-          _errorReporter.reportErrorForNode(
-              HintCode.TYPE_CHECK_IS_NOT_NULL, node);
+      }
+      // `is Object` or `is! Object`
+      if (rhsType.isObject) {
+        var nullability = rhsType.nullabilitySuffix;
+        if (nullability == NullabilitySuffix.star ||
+            nullability == NullabilitySuffix.question) {
+          if (node.notOperator == null) {
+            _errorReporter.reportErrorForNode(
+              HintCode.UNNECESSARY_TYPE_CHECK_TRUE,
+              node,
+            );
+          } else {
+            _errorReporter.reportErrorForNode(
+              HintCode.UNNECESSARY_TYPE_CHECK_FALSE,
+              node,
+            );
+          }
+          return true;
         }
-        return true;
       }
     }
     return false;
@@ -939,22 +1033,18 @@
 
   /// Generate a hint for functions or methods that have a return type, but do
   /// not have a return statement on all branches. At the end of blocks with no
-  /// return, Dart implicitly returns `null`, avoiding these implicit returns is
-  /// considered a best practice.
+  /// return, Dart implicitly returns `null`. Avoiding these implicit returns
+  /// is considered a best practice.
   ///
   /// Note: for async functions/methods, this hint only applies when the
   /// function has a return type that Future<Null> is not assignable to.
   ///
-  /// @param node the binary expression to check
-  /// @param body the function body
-  /// @return `true` if and only if a hint code is generated on the passed node
   /// See [HintCode.MISSING_RETURN].
   void _checkForMissingReturn(TypeAnnotation returnNode, FunctionBody body,
       ExecutableElement element, AstNode functionNode) {
     if (body is BlockFunctionBody) {
       // Prefer the type from the element model, in case we've inferred one.
       DartType returnType = element?.returnType ?? returnNode?.type;
-      AstNode errorNode = returnNode ?? functionNode;
 
       // Skip the check if we're missing a return type (e.g. erroneous code).
       // Generators are never required to have a return statement.
@@ -993,6 +1083,11 @@
       }
       // Otherwise issue a warning if the block doesn't have a return.
       if (!ExitDetector.exits(body)) {
+        AstNode errorNode = functionNode is MethodDeclaration
+            ? functionNode.name
+            : functionNode is FunctionDeclaration
+                ? functionNode.name
+                : functionNode;
         _errorReporter.reportErrorForNode(
             HintCode.MISSING_RETURN, errorNode, [returnType.displayName]);
       }
@@ -1237,6 +1332,20 @@
     }
   }
 
+  WorkspacePackage _getPackage(String root, ResourceProvider resourceProvider) {
+    Workspace workspace = _currentLibrary.session?.analysisContext?.workspace;
+    // If there is no driver setup (as in test environments), we need to create
+    // a workspace ourselves.
+    // todo (pq): fix tests or otherwise de-dup this logic shared w/ library_analyzer.
+    if (workspace == null) {
+      final builder = ContextBuilder(
+          resourceProvider, null /* sdkManager */, null /* contentCache */);
+      workspace =
+          ContextBuilder.createWorkspace(resourceProvider, root, builder);
+    }
+    return workspace?.findPackageFor(root);
+  }
+
   bool _isLibraryInWorkspacePackage(LibraryElement library) {
     if (_workspacePackage == null || library == null) {
       // Better to not make a big claim that they _are_ in the same package,
@@ -1309,6 +1418,16 @@
     return false;
   }
 
+  static bool _hasNonVirtualAnnotation(ExecutableElement element) {
+    if (element == null) {
+      return false;
+    }
+    if (element is PropertyAccessorElement && element.isSynthetic) {
+      return element.variable.hasNonVirtual;
+    }
+    return element.hasNonVirtual;
+  }
+
   /// Given a parenthesized expression, this returns the parent (or recursively
   /// grand-parent) of the expression that is a parenthesized expression, but
   /// whose parent is not a parenthesized expression.
@@ -1329,66 +1448,6 @@
   }
 }
 
-/// Utilities for [LibraryElementImpl] building.
-class BuildLibraryElementUtils {
-  /// Look through all of the compilation units defined for the given [library],
-  /// looking for getters and setters that are defined in different compilation
-  /// units but that have the same names. If any are found, make sure that they
-  /// have the same variable element.
-  static void patchTopLevelAccessors(LibraryElementImpl library) {
-    // Without parts getters/setters already share the same variable element.
-    List<CompilationUnitElement> parts = library.parts;
-    if (parts.isEmpty) {
-      return;
-    }
-    // Collect getters and setters.
-    Map<String, PropertyAccessorElement> getters =
-        new HashMap<String, PropertyAccessorElement>();
-    List<PropertyAccessorElement> setters = <PropertyAccessorElement>[];
-    _collectAccessors(getters, setters, library.definingCompilationUnit);
-    int partLength = parts.length;
-    for (int i = 0; i < partLength; i++) {
-      CompilationUnitElement unit = parts[i];
-      _collectAccessors(getters, setters, unit);
-    }
-    // Move every setter to the corresponding getter's variable (if exists).
-    int setterLength = setters.length;
-    for (int j = 0; j < setterLength; j++) {
-      PropertyAccessorElement setter = setters[j];
-      PropertyAccessorElement getter = getters[setter.displayName];
-      if (getter != null) {
-        TopLevelVariableElementImpl variable = getter.variable;
-        TopLevelVariableElementImpl setterVariable = setter.variable;
-        CompilationUnitElementImpl setterUnit = setterVariable.enclosingElement;
-        setterUnit.replaceTopLevelVariable(setterVariable, variable);
-        variable.setter = setter;
-        (setter as PropertyAccessorElementImpl).variable = variable;
-      }
-    }
-  }
-
-  /// Add all of the non-synthetic [getters] and [setters] defined in the given
-  /// [unit] that have no corresponding accessor to one of the given
-  /// collections.
-  static void _collectAccessors(Map<String, PropertyAccessorElement> getters,
-      List<PropertyAccessorElement> setters, CompilationUnitElement unit) {
-    List<PropertyAccessorElement> accessors = unit.accessors;
-    int length = accessors.length;
-    for (int i = 0; i < length; i++) {
-      PropertyAccessorElement accessor = accessors[i];
-      if (accessor.isGetter) {
-        if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
-          getters[accessor.displayName] = accessor;
-        }
-      } else {
-        if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
-          setters.add(accessor);
-        }
-      }
-    }
-  }
-}
-
 /// Instances of the class `Dart2JSVerifier` traverse an AST structure looking
 /// for hints for code that will be compiled to JS, such as
 /// [HintCode.IS_DOUBLE].
@@ -1921,474 +1980,6 @@
   }
 }
 
-/// A visitor that resolves directives in an AST structure to already built
-/// elements.
-///
-/// The resulting AST must have everything resolved that would have been
-/// resolved by a [DirectiveElementBuilder].
-class DirectiveResolver extends SimpleAstVisitor {
-  final Map<Source, int> sourceModificationTimeMap;
-  final Map<Source, SourceKind> importSourceKindMap;
-  final Map<Source, SourceKind> exportSourceKindMap;
-  final List<AnalysisError> errors = <AnalysisError>[];
-
-  LibraryElement _enclosingLibrary;
-
-  DirectiveResolver(this.sourceModificationTimeMap, this.importSourceKindMap,
-      this.exportSourceKindMap);
-
-  @override
-  void visitCompilationUnit(CompilationUnit node) {
-    _enclosingLibrary = node.declaredElement.library;
-    for (Directive directive in node.directives) {
-      directive.accept(this);
-    }
-  }
-
-  @override
-  void visitExportDirective(ExportDirective node) {
-    int nodeOffset = node.offset;
-    node.element = null;
-    for (ExportElement element in _enclosingLibrary.exports) {
-      if (element.nameOffset == nodeOffset) {
-        node.element = element;
-        // Verify the exported source kind.
-        LibraryElement exportedLibrary = element.exportedLibrary;
-        if (exportedLibrary != null) {
-          Source exportedSource = exportedLibrary.source;
-          int exportedTime = sourceModificationTimeMap[exportedSource] ?? -1;
-          if (exportedTime >= 0 &&
-              exportSourceKindMap[exportedSource] != SourceKind.LIBRARY) {
-            StringLiteral uriLiteral = node.uri;
-            errors.add(new AnalysisError(
-                _enclosingLibrary.source,
-                uriLiteral.offset,
-                uriLiteral.length,
-                CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
-                [uriLiteral.toSource()]));
-          }
-        }
-        break;
-      }
-    }
-  }
-
-  @override
-  void visitImportDirective(ImportDirective node) {
-    int nodeOffset = node.offset;
-    node.element = null;
-    for (ImportElement element in _enclosingLibrary.imports) {
-      if (element.nameOffset == nodeOffset) {
-        node.element = element;
-        // Verify the imported source kind.
-        LibraryElement importedLibrary = element.importedLibrary;
-        if (importedLibrary != null) {
-          Source importedSource = importedLibrary.source;
-          int importedTime = sourceModificationTimeMap[importedSource] ?? -1;
-          if (importedTime >= 0 &&
-              importSourceKindMap[importedSource] != SourceKind.LIBRARY) {
-            StringLiteral uriLiteral = node.uri;
-            errors.add(new AnalysisError(
-                _enclosingLibrary.source,
-                uriLiteral.offset,
-                uriLiteral.length,
-                CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
-                [uriLiteral.toSource()]));
-          }
-        }
-        break;
-      }
-    }
-  }
-
-  @override
-  void visitLibraryDirective(LibraryDirective node) {
-    node.element = _enclosingLibrary;
-  }
-}
-
-/// Instances of the class `ElementHolder` hold on to elements created while
-/// traversing an AST structure so that they can be accessed when creating their
-/// enclosing element.
-class ElementHolder {
-  List<PropertyAccessorElement> _accessors;
-
-  List<ConstructorElement> _constructors;
-
-  List<ClassElement> _enums;
-
-  List<FieldElement> _fields;
-
-  List<FunctionElement> _functions;
-
-  List<LabelElement> _labels;
-
-  List<LocalVariableElement> _localVariables;
-
-  List<MethodElement> _methods;
-
-  List<ClassElement> _mixins;
-
-  List<ParameterElement> _parameters;
-
-  List<TopLevelVariableElement> _topLevelVariables;
-
-  List<ClassElement> _types;
-
-  List<FunctionTypeAliasElement> _typeAliases;
-
-  List<TypeParameterElement> _typeParameters;
-
-  List<PropertyAccessorElement> get accessors {
-    if (_accessors == null) {
-      return const <PropertyAccessorElement>[];
-    }
-    List<PropertyAccessorElement> result = _accessors;
-    _accessors = null;
-    return result;
-  }
-
-  List<ConstructorElement> get constructors {
-    if (_constructors == null) {
-      return const <ConstructorElement>[];
-    }
-    List<ConstructorElement> result = _constructors;
-    _constructors = null;
-    return result;
-  }
-
-  List<ClassElement> get enums {
-    if (_enums == null) {
-      return const <ClassElement>[];
-    }
-    List<ClassElement> result = _enums;
-    _enums = null;
-    return result;
-  }
-
-  List<FieldElement> get fields {
-    if (_fields == null) {
-      return const <FieldElement>[];
-    }
-    List<FieldElement> result = _fields;
-    _fields = null;
-    return result;
-  }
-
-  List<FieldElement> get fieldsWithoutFlushing {
-    if (_fields == null) {
-      return const <FieldElement>[];
-    }
-    List<FieldElement> result = _fields;
-    return result;
-  }
-
-  List<FunctionElement> get functions {
-    if (_functions == null) {
-      return const <FunctionElement>[];
-    }
-    List<FunctionElement> result = _functions;
-    _functions = null;
-    return result;
-  }
-
-  List<LabelElement> get labels {
-    if (_labels == null) {
-      return const <LabelElement>[];
-    }
-    List<LabelElement> result = _labels;
-    _labels = null;
-    return result;
-  }
-
-  List<LocalVariableElement> get localVariables {
-    if (_localVariables == null) {
-      return const <LocalVariableElement>[];
-    }
-    List<LocalVariableElement> result = _localVariables;
-    _localVariables = null;
-    return result;
-  }
-
-  List<MethodElement> get methods {
-    if (_methods == null) {
-      return const <MethodElement>[];
-    }
-    List<MethodElement> result = _methods;
-    _methods = null;
-    return result;
-  }
-
-  List<ClassElement> get mixins {
-    if (_mixins == null) {
-      return const <ClassElement>[];
-    }
-    List<ClassElement> result = _mixins;
-    _mixins = null;
-    return result;
-  }
-
-  List<ParameterElement> get parameters {
-    if (_parameters == null) {
-      return const <ParameterElement>[];
-    }
-    List<ParameterElement> result = _parameters;
-    _parameters = null;
-    return result;
-  }
-
-  List<TopLevelVariableElement> get topLevelVariables {
-    if (_topLevelVariables == null) {
-      return const <TopLevelVariableElement>[];
-    }
-    List<TopLevelVariableElement> result = _topLevelVariables;
-    _topLevelVariables = null;
-    return result;
-  }
-
-  List<FunctionTypeAliasElement> get typeAliases {
-    if (_typeAliases == null) {
-      return const <FunctionTypeAliasElement>[];
-    }
-    List<FunctionTypeAliasElement> result = _typeAliases;
-    _typeAliases = null;
-    return result;
-  }
-
-  List<TypeParameterElement> get typeParameters {
-    if (_typeParameters == null) {
-      return const <TypeParameterElement>[];
-    }
-    List<TypeParameterElement> result = _typeParameters;
-    _typeParameters = null;
-    return result;
-  }
-
-  List<ClassElement> get types {
-    if (_types == null) {
-      return const <ClassElement>[];
-    }
-    List<ClassElement> result = _types;
-    _types = null;
-    return result;
-  }
-
-  void addAccessor(PropertyAccessorElement element) {
-    if (_accessors == null) {
-      _accessors = new List<PropertyAccessorElement>();
-    }
-    _accessors.add(element);
-  }
-
-  void addConstructor(ConstructorElement element) {
-    if (_constructors == null) {
-      _constructors = new List<ConstructorElement>();
-    }
-    _constructors.add(element);
-  }
-
-  void addEnum(ClassElement element) {
-    if (_enums == null) {
-      _enums = new List<ClassElement>();
-    }
-    _enums.add(element);
-  }
-
-  void addField(FieldElement element) {
-    if (_fields == null) {
-      _fields = new List<FieldElement>();
-    }
-    _fields.add(element);
-  }
-
-  void addFunction(FunctionElement element) {
-    if (_functions == null) {
-      _functions = new List<FunctionElement>();
-    }
-    _functions.add(element);
-  }
-
-  void addLabel(LabelElement element) {
-    if (_labels == null) {
-      _labels = new List<LabelElement>();
-    }
-    _labels.add(element);
-  }
-
-  void addLocalVariable(LocalVariableElement element) {
-    if (_localVariables == null) {
-      _localVariables = new List<LocalVariableElement>();
-    }
-    _localVariables.add(element);
-  }
-
-  void addMethod(MethodElement element) {
-    if (_methods == null) {
-      _methods = new List<MethodElement>();
-    }
-    _methods.add(element);
-  }
-
-  void addMixin(ClassElement element) {
-    if (_mixins == null) {
-      _mixins = new List<ClassElement>();
-    }
-    _mixins.add(element);
-  }
-
-  void addParameter(ParameterElement element) {
-    if (_parameters == null) {
-      _parameters = new List<ParameterElement>();
-    }
-    _parameters.add(element);
-  }
-
-  void addTopLevelVariable(TopLevelVariableElement element) {
-    if (_topLevelVariables == null) {
-      _topLevelVariables = new List<TopLevelVariableElement>();
-    }
-    _topLevelVariables.add(element);
-  }
-
-  void addType(ClassElement element) {
-    if (_types == null) {
-      _types = new List<ClassElement>();
-    }
-    _types.add(element);
-  }
-
-  void addTypeAlias(FunctionTypeAliasElement element) {
-    if (_typeAliases == null) {
-      _typeAliases = new List<FunctionTypeAliasElement>();
-    }
-    _typeAliases.add(element);
-  }
-
-  void addTypeParameter(TypeParameterElement element) {
-    if (_typeParameters == null) {
-      _typeParameters = new List<TypeParameterElement>();
-    }
-    _typeParameters.add(element);
-  }
-
-  FieldElement getField(String fieldName, {bool synthetic: false}) {
-    if (_fields == null) {
-      return null;
-    }
-    int length = _fields.length;
-    for (int i = 0; i < length; i++) {
-      FieldElement field = _fields[i];
-      if (field.name == fieldName && field.isSynthetic == synthetic) {
-        return field;
-      }
-    }
-    return null;
-  }
-
-  TopLevelVariableElement getTopLevelVariable(String variableName) {
-    if (_topLevelVariables == null) {
-      return null;
-    }
-    int length = _topLevelVariables.length;
-    for (int i = 0; i < length; i++) {
-      TopLevelVariableElement variable = _topLevelVariables[i];
-      if (variable.name == variableName) {
-        return variable;
-      }
-    }
-    return null;
-  }
-
-  void validate() {
-    StringBuffer buffer = new StringBuffer();
-    if (_accessors != null) {
-      buffer.write(_accessors.length);
-      buffer.write(" accessors");
-    }
-    if (_constructors != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_constructors.length);
-      buffer.write(" constructors");
-    }
-    if (_fields != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_fields.length);
-      buffer.write(" fields");
-    }
-    if (_functions != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_functions.length);
-      buffer.write(" functions");
-    }
-    if (_labels != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_labels.length);
-      buffer.write(" labels");
-    }
-    if (_localVariables != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_localVariables.length);
-      buffer.write(" local variables");
-    }
-    if (_methods != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_methods.length);
-      buffer.write(" methods");
-    }
-    if (_parameters != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_parameters.length);
-      buffer.write(" parameters");
-    }
-    if (_topLevelVariables != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_topLevelVariables.length);
-      buffer.write(" top-level variables");
-    }
-    if (_types != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_types.length);
-      buffer.write(" types");
-    }
-    if (_typeAliases != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_typeAliases.length);
-      buffer.write(" type aliases");
-    }
-    if (_typeParameters != null) {
-      if (buffer.length > 0) {
-        buffer.write("; ");
-      }
-      buffer.write(_typeParameters.length);
-      buffer.write(" type parameters");
-    }
-    if (buffer.length > 0) {
-      AnalysisEngine.instance.logger
-          .logError("Failed to capture elements: $buffer");
-    }
-  }
-}
-
 /// An [AstVisitor] that fills [UsedLocalElements].
 class GatherUsedLocalElementsVisitor extends RecursiveAstVisitor {
   final UsedLocalElements usedElements = new UsedLocalElements();
@@ -2771,9 +2362,9 @@
       enclosingClass = node.declaredElement;
       typeAnalyzer.thisType = enclosingClass?.thisType;
       if (enclosingClass == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for class declaration ${node.name.name} in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService.logInfo(
+            "Missing element for class declaration ${node.name.name} in "
+            "${definingLibrary.source.fullName}");
         // Don't try to re-resolve the initializers if we cannot set up the
         // right name scope for resolution.
       } else {
@@ -3106,15 +2697,11 @@
   /// or `null` if not in a [SwitchStatement].
   DartType _enclosingSwitchStatementExpressionType;
 
+  InterfaceType _iterableForSetMapDisambiguationCached;
+  InterfaceType _mapForSetMapDisambiguationCached;
+
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
-  /// [inheritanceManager] should be an instance of either [InheritanceManager2]
-  /// or [InheritanceManager3].  If an [InheritanceManager2] is supplied, it
-  /// will be converted into an [InheritanceManager3] internally.  The ability
-  /// to pass in [InheritanceManager2] exists for backward compatibility; in a
-  /// future major version of the analyzer, an [InheritanceManager3] will
-  /// be required.
-  ///
   /// The [definingLibrary] is the element for the library containing the node
   /// being visited. The [source] is the source representing the compilation
   /// unit containing the node being visited. The [typeProvider] is the object
@@ -3128,7 +2715,7 @@
   /// TODO(paulberry): make [featureSet] a required parameter (this will be a
   /// breaking change).
   ResolverVisitor(
-      InheritanceManagerBase inheritanceManager,
+      InheritanceManager3 inheritanceManager,
       LibraryElement definingLibrary,
       Source source,
       TypeProvider typeProvider,
@@ -3139,7 +2726,7 @@
       reportConstEvaluationErrors: true,
       FlowAnalysisHelper flowAnalysisHelper})
       : this._(
-            inheritanceManager.asInheritanceManager3,
+            inheritanceManager,
             definingLibrary,
             source,
             typeProvider,
@@ -3181,7 +2768,7 @@
     }
     this.inferenceContext = new InferenceContext._(
         typeProvider, typeSystem, strongModeHints, errorReporter);
-    this.typeAnalyzer = new StaticTypeAnalyzer(this, featureSet);
+    this.typeAnalyzer = new StaticTypeAnalyzer(this, featureSet, _flowAnalysis);
   }
 
   /// Return the element representing the function containing the current node,
@@ -3205,6 +2792,31 @@
         : NullabilitySuffix.star;
   }
 
+  InterfaceType get _iterableForSetMapDisambiguation {
+    return _iterableForSetMapDisambiguationCached ??=
+        typeProvider.iterableElement.instantiate(
+      typeArguments: [
+        typeProvider.dynamicType,
+      ],
+      nullabilitySuffix: _nonNullableEnabled
+          ? NullabilitySuffix.question
+          : NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get _mapForSetMapDisambiguation {
+    return _mapForSetMapDisambiguationCached ??=
+        typeProvider.mapElement.instantiate(
+      typeArguments: [
+        typeProvider.dynamicType,
+        typeProvider.dynamicType,
+      ],
+      nullabilitySuffix: _nonNullableEnabled
+          ? NullabilitySuffix.question
+          : NullabilitySuffix.star,
+    );
+  }
+
   /**
    * Return `true` if NNBD is enabled for this compilation unit.
    */
@@ -3389,15 +3001,29 @@
   }
 
   @override
+  void visitAsExpression(AsExpression node) {
+    super.visitAsExpression(node);
+    _flowAnalysis?.asExpression(node);
+  }
+
+  @override
   void visitAssertInitializer(AssertInitializer node) {
     InferenceContext.setType(node.condition, typeProvider.boolType);
-    super.visitAssertInitializer(node);
+    _flowAnalysis?.flow?.assert_begin();
+    node.condition?.accept(this);
+    _flowAnalysis?.flow?.assert_afterCondition(node.condition);
+    node.message?.accept(this);
+    _flowAnalysis?.flow?.assert_end();
   }
 
   @override
   void visitAssertStatement(AssertStatement node) {
     InferenceContext.setType(node.condition, typeProvider.boolType);
-    super.visitAssertStatement(node);
+    _flowAnalysis?.flow?.assert_begin();
+    node.condition?.accept(this);
+    _flowAnalysis?.flow?.assert_afterCondition(node.condition);
+    node.message?.accept(this);
+    _flowAnalysis?.flow?.assert_end();
   }
 
   @override
@@ -3416,10 +3042,14 @@
     }
 
     right?.accept(this);
-    _flowAnalysis?.assignmentExpression_afterRight(leftLocalVariable, right);
-
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
+    _flowAnalysis?.assignmentExpression_afterRight(
+        node,
+        leftLocalVariable,
+        operator == TokenType.QUESTION_QUESTION_EQ
+            ? node.rightHandSide.staticType
+            : node.staticType);
   }
 
   @override
@@ -3511,7 +3141,7 @@
       }
 
       if (operator == TokenType.QUESTION_QUESTION) {
-        flow?.ifNullExpression_rightBegin();
+        flow?.ifNullExpression_rightBegin(node.leftOperand);
         right.accept(this);
         flow?.ifNullExpression_end();
       } else {
@@ -3757,10 +3387,7 @@
 
     InferenceContext.setType(node.condition, typeProvider.boolType);
 
-    _flowAnalysis?.flow?.doStatement_bodyBegin(
-        node,
-        _flowAnalysis.assignedVariables.writtenInNode(node),
-        _flowAnalysis.assignedVariables.capturedInNode(node));
+    _flowAnalysis?.flow?.doStatement_bodyBegin(node);
     visitStatementInScope(body);
 
     _flowAnalysis?.flow?.doStatement_conditionBegin();
@@ -3841,8 +3468,7 @@
     // Continue the extension resolution.
     //
     try {
-      DartType extendedType = node.declaredElement.extendedType;
-      typeAnalyzer.thisType = typeSystem.resolveToBound(extendedType);
+      typeAnalyzer.thisType = node.declaredElement.extendedType;
       super.visitExtensionDeclaration(node);
       node.accept(elementResolver);
       node.accept(typeAnalyzer);
@@ -3913,13 +3539,25 @@
       // variable cannot be in scope while visiting the iterator.
       //
       iterable?.accept(this);
+      // Note: the iterable could have been rewritten so grab it from
+      // forLoopParts again.
+      iterable = forLoopParts.iterable;
       loopVariable?.accept(this);
+      var elementType = typeAnalyzer.computeForEachElementType(
+          iterable, node.awaitKeyword != null);
+      if (loopVariable != null &&
+          elementType != null &&
+          loopVariable.type == null) {
+        var loopVariableElement =
+            loopVariable.declaredElement as LocalVariableElementImpl;
+        loopVariableElement.type = elementType;
+      }
       _flowAnalysis?.flow?.forEach_bodyBegin(
-          _flowAnalysis.assignedVariables.writtenInNode(node),
-          _flowAnalysis.assignedVariables.capturedInNode(node),
+          node,
           identifierElement is VariableElement
               ? identifierElement
-              : loopVariable.declaredElement);
+              : loopVariable.declaredElement,
+          elementType ?? typeProvider.dynamicType);
       node.body?.accept(this);
       _flowAnalysis?.flow?.forEach_end();
 
@@ -3993,14 +3631,26 @@
       // cannot be in scope while visiting the iterator.
       //
       iterable?.accept(this);
+      // Note: the iterable could have been rewritten so grab it from
+      // forLoopParts again.
+      iterable = forLoopParts.iterable;
       loopVariable?.accept(this);
+      var elementType = typeAnalyzer.computeForEachElementType(
+          iterable, node.awaitKeyword != null);
+      if (loopVariable != null &&
+          elementType != null &&
+          loopVariable.type == null) {
+        var loopVariableElement =
+            loopVariable.declaredElement as LocalVariableElementImpl;
+        loopVariableElement.type = elementType;
+      }
 
       _flowAnalysis?.flow?.forEach_bodyBegin(
-          _flowAnalysis.assignedVariables.writtenInNode(node),
-          _flowAnalysis.assignedVariables.capturedInNode(node),
+          node,
           identifierElement is VariableElement
               ? identifierElement
-              : loopVariable?.declaredElement);
+              : loopVariable?.declaredElement,
+          elementType ?? typeProvider.dynamicType);
 
       Statement body = node.body;
       if (body != null) {
@@ -4023,8 +3673,7 @@
       SimpleIdentifier functionName = node.name;
       if (_flowAnalysis != null) {
         if (isFunctionDeclarationStatement) {
-          _flowAnalysis.flow.functionExpression_begin(
-              _flowAnalysis.assignedVariables.writtenInNode(node));
+          _flowAnalysis.flow.functionExpression_begin(node);
         } else {
           _flowAnalysis.topLevelDeclaration_enter(node,
               node.functionExpression.parameters, node.functionExpression.body);
@@ -4065,8 +3714,7 @@
     try {
       if (_flowAnalysis != null) {
         if (!isFunctionDeclaration) {
-          _flowAnalysis.flow.functionExpression_begin(
-              _flowAnalysis.assignedVariables.writtenInNode(node));
+          _flowAnalysis.flow.functionExpression_begin(node);
         }
       } else {
         _promoteManager.enterFunctionBody(node.body);
@@ -4192,6 +3840,9 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     node.target?.accept(this);
+    if (node.isNullAware) {
+      _flowAnalysis?.flow?.nullAwareAccess_rightBegin(node.target);
+    }
     node.accept(elementResolver);
     var method = node.staticElement;
     if (method != null && method.parameters.isNotEmpty) {
@@ -4352,7 +4003,8 @@
   void visitPostfixExpression(PostfixExpression node) {
     super.visitPostfixExpression(node);
 
-    if (node.operator.type == TokenType.BANG) {
+    var operator = node.operator.type;
+    if (operator == TokenType.BANG) {
       _flowAnalysis?.flow?.nonNullAssert_end(node.operand);
     }
   }
@@ -4385,6 +4037,9 @@
     // to be visited in the context of the property access node.
     //
     node.target?.accept(this);
+    if (node.isNullAware) {
+      _flowAnalysis?.flow?.nullAwareAccess_rightBegin(node.target);
+    }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
   }
@@ -4483,6 +4138,10 @@
 
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.inDeclarationContext()) {
+      return;
+    }
+
     if (_flowAnalysis != null &&
         _flowAnalysis.isPotentiallyNonNullableLocalReadBeforeWrite(node)) {
       errorReporter.reportErrorForNode(
@@ -4530,18 +4189,13 @@
 
       if (_flowAnalysis != null) {
         var flow = _flowAnalysis.flow;
-        var assignedInCases =
-            _flowAnalysis.assignedVariables.writtenInNode(node);
-        var capturedInCases =
-            _flowAnalysis.assignedVariables.capturedInNode(node);
 
         flow.switchStatement_expressionEnd(node);
 
         var hasDefault = false;
         var members = node.members;
         for (var member in members) {
-          flow.switchStatement_beginCase(
-              member.labels.isNotEmpty, assignedInCases, capturedInCases);
+          flow.switchStatement_beginCase(member.labels.isNotEmpty, node);
           member.accept(this);
 
           if (member is SwitchDefault) {
@@ -4581,36 +4235,31 @@
       flow.tryFinallyStatement_bodyBegin();
     }
 
-    flow.tryCatchStatement_bodyBegin();
-    body.accept(this);
-    flow.tryCatchStatement_bodyEnd(
-        _flowAnalysis.assignedVariables.writtenInNode(body),
-        _flowAnalysis.assignedVariables.capturedInNode(body));
-
-    var catchLength = catchClauses.length;
-    for (var i = 0; i < catchLength; ++i) {
-      var catchClause = catchClauses[i];
-      flow.tryCatchStatement_catchBegin();
-      if (catchClause.exceptionParameter != null) {
-        flow.initialize(catchClause.exceptionParameter.staticElement);
-      }
-      if (catchClause.stackTraceParameter != null) {
-        flow.initialize(catchClause.stackTraceParameter.staticElement);
-      }
-      catchClause.accept(this);
-      flow.tryCatchStatement_catchEnd();
+    if (catchClauses.isNotEmpty) {
+      flow.tryCatchStatement_bodyBegin();
     }
+    body.accept(this);
+    if (catchClauses.isNotEmpty) {
+      flow.tryCatchStatement_bodyEnd(body);
 
-    flow.tryCatchStatement_end();
+      var catchLength = catchClauses.length;
+      for (var i = 0; i < catchLength; ++i) {
+        var catchClause = catchClauses[i];
+        flow.tryCatchStatement_catchBegin(
+            catchClause.exceptionParameter?.staticElement,
+            catchClause.stackTraceParameter?.staticElement);
+        catchClause.accept(this);
+        flow.tryCatchStatement_catchEnd();
+      }
+
+      flow.tryCatchStatement_end();
+    }
 
     if (finallyBlock != null) {
       flow.tryFinallyStatement_finallyBegin(
-          _flowAnalysis.assignedVariables.writtenInNode(body),
-          _flowAnalysis.assignedVariables.capturedInNode(body));
+          catchClauses.isNotEmpty ? node : body);
       finallyBlock.accept(this);
-      flow.tryFinallyStatement_end(
-        _flowAnalysis.assignedVariables.writtenInNode(finallyBlock),
-      );
+      flow.tryFinallyStatement_end(finallyBlock);
     }
   }
 
@@ -4668,9 +4317,7 @@
       Expression condition = node.condition;
       InferenceContext.setType(condition, typeProvider.boolType);
 
-      _flowAnalysis?.flow?.whileStatement_conditionBegin(
-          _flowAnalysis.assignedVariables.writtenInNode(node),
-          _flowAnalysis.assignedVariables.capturedInNode(node));
+      _flowAnalysis?.flow?.whileStatement_conditionBegin(node);
       condition?.accept(this);
 
       Statement body = node.body;
@@ -4862,9 +4509,9 @@
       // TODO(brianwilkerson) Find out what the "greatest closure" is and use that
       // where [unwrappedContextType] is used below.
       bool isIterable = typeSystem.isSubtypeOf(
-          unwrappedContextType, typeProvider.iterableObjectType);
+          unwrappedContextType, _iterableForSetMapDisambiguation);
       bool isMap = typeSystem.isSubtypeOf(
-          unwrappedContextType, typeProvider.mapObjectObjectType);
+          unwrappedContextType, _mapForSetMapDisambiguation);
       if (isIterable && !isMap) {
         return _LiteralResolution(
             _LiteralResolutionKind.set, unwrappedContextType);
@@ -5307,8 +4954,9 @@
     Scope outerScope = nameScope;
     try {
       if (classElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for class declaration ${node.name.name} in ${definingLibrary.source.fullName}",
+        AnalysisEngine.instance.instrumentationService.logInfo(
+            "Missing element for class declaration ${node.name.name} in "
+            "${definingLibrary.source.fullName}",
             new CaughtException(new AnalysisException(), null));
         super.visitClassDeclaration(node);
       } else {
@@ -5369,8 +5017,7 @@
       }
       buffer.write(" in ");
       buffer.write(definingLibrary.source.fullName);
-      AnalysisEngine.instance.logger.logInformation(buffer.toString(),
-          new CaughtException(new AnalysisException(), null));
+      AnalysisEngine.instance.instrumentationService.logInfo(buffer.toString());
     }
     Scope outerScope = nameScope;
     try {
@@ -5434,9 +5081,9 @@
     Scope outerScope = nameScope;
     try {
       if (classElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for enum declaration ${node.name.name} in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService.logInfo(
+            "Missing element for enum declaration ${node.name.name} in "
+            "${definingLibrary.source.fullName}");
         super.visitEnumDeclaration(node);
       } else {
         ClassElement outerClass = enclosingClass;
@@ -5465,10 +5112,9 @@
     Scope outerScope = nameScope;
     try {
       if (extensionElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
+        AnalysisEngine.instance.instrumentationService.logInfo(
             "Missing element for extension declaration ${node.name.name} "
-            "in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+            "in ${definingLibrary.source.fullName}");
         super.visitExtensionDeclaration(node);
       } else {
         ExtensionElement outerExtension = enclosingExtension;
@@ -5580,9 +5226,9 @@
     Scope outerScope = nameScope;
     try {
       if (functionElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for top-level function ${node.name.name} in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService.logInfo(
+            "Missing element for top-level function ${node.name.name} in "
+            "${definingLibrary.source.fullName}");
       } else {
         nameScope = new FunctionScope(nameScope, functionElement);
       }
@@ -5620,8 +5266,8 @@
           }
           buffer.write("in ");
           buffer.write(definingLibrary.source.fullName);
-          AnalysisEngine.instance.logger.logInformation(buffer.toString(),
-              new CaughtException(new AnalysisException(), null));
+          AnalysisEngine.instance.instrumentationService
+              .logInfo(buffer.toString());
         } else {
           nameScope = new FunctionScope(nameScope, functionElement);
         }
@@ -5653,9 +5299,9 @@
     try {
       ParameterElement parameterElement = node.declaredElement;
       if (parameterElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for function typed formal parameter ${node.identifier.name} in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService.logInfo(
+            "Missing element for function typed formal parameter "
+            "${node.identifier.name} in ${definingLibrary.source.fullName}");
       } else {
         nameScope = new EnclosedScope(nameScope);
         var typeParameters = parameterElement.typeParameters;
@@ -5684,9 +5330,9 @@
     Scope outerScope = nameScope;
     try {
       if (element == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for generic function type in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService
+            .logInfo("Missing element for generic function type in "
+                "${definingLibrary.source.fullName}");
         super.visitGenericFunctionType(node);
       } else {
         nameScope = new TypeParameterScope(nameScope, element);
@@ -5703,9 +5349,9 @@
     Scope outerScope = nameScope;
     try {
       if (element == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for generic function type in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService
+            .logInfo("Missing element for generic function type in "
+                "${definingLibrary.source.fullName}");
         super.visitGenericTypeAlias(node);
       } else {
         nameScope = new TypeParameterScope(nameScope, element);
@@ -5748,9 +5394,9 @@
     try {
       ExecutableElement methodElement = node.declaredElement;
       if (methodElement == null) {
-        AnalysisEngine.instance.logger.logInformation(
-            "Missing element for method ${node.name.name} in ${definingLibrary.source.fullName}",
-            new CaughtException(new AnalysisException(), null));
+        AnalysisEngine.instance.instrumentationService
+            .logInfo("Missing element for method ${node.name.name} in "
+                "${definingLibrary.source.fullName}");
       } else {
         nameScope = new FunctionScope(nameScope, methodElement);
       }
@@ -6038,12 +5684,10 @@
 //          // TODO(brianwilkerson) Report this error
 //          reporter.reportError(StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, node, voidType.getName(), 0, argumentList.getArguments().size());
 //        }
-        typeName.staticType = voidType;
         node.type = voidType;
         return;
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = dynamicType;
         node.type = dynamicType;
         return;
       }
@@ -6064,7 +5708,6 @@
           element = nameScope.lookup(prefix, definingLibrary);
           if (element is PrefixElement) {
             if (nameScope.shouldIgnoreUndefined(typeName)) {
-              typeName.staticType = dynamicType;
               node.type = dynamicType;
               return;
             }
@@ -6104,7 +5747,6 @@
         }
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = dynamicType;
         node.type = dynamicType;
         return;
       }
@@ -6178,25 +5820,23 @@
               argumentList,
               [prefix.name, identifier.name]);
           prefix.staticElement = prefixElement;
-          prefix.staticType = classElement.instantiate(
-            typeArguments: List.filled(
-              classElement.typeParameters.length,
-              dynamicType,
-            ),
-            nullabilitySuffix: _noneOrStarSuffix,
-          );
           identifier.staticElement = constructorElement;
-          identifier.staticType = constructorElement.type;
-          typeName.staticType = prefix.staticType;
           AstNode grandParent = node.parent.parent;
           if (grandParent is InstanceCreationExpressionImpl) {
+            var instanceType = classElement.instantiate(
+              typeArguments: List.filled(
+                classElement.typeParameters.length,
+                dynamicType,
+              ),
+              nullabilitySuffix: _noneOrStarSuffix,
+            );
             grandParent.staticElement = constructorElement;
-            grandParent.staticType = typeName.staticType;
+            grandParent.staticType = instanceType;
             //
             // Re-write the AST to reflect the resolution.
             //
-            AstFactory astFactory = new AstFactoryImpl();
             TypeName newTypeName = astFactory.typeName(prefix, null);
+            newTypeName.type = instanceType;
             ConstructorName newConstructorName = astFactory.constructorName(
                 newTypeName,
                 (typeName as PrefixedIdentifier).period,
@@ -6225,7 +5865,6 @@
       if (element is MultiplyDefinedElement) {
         _setElement(typeName, element);
       }
-      typeName.staticType = dynamicType;
       node.type = dynamicType;
       return;
     }
@@ -6291,7 +5930,6 @@
               StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
         }
       }
-      typeName.staticType = dynamicType;
       node.type = dynamicType;
       return;
     }
@@ -6319,7 +5957,7 @@
         }
       }
       if (element is GenericTypeAliasElementImpl) {
-        type = element.instantiate2(
+        type = element.instantiate(
           typeArguments: typeArguments,
           nullabilitySuffix: _getNullability(node.question != null),
         );
@@ -6335,7 +5973,7 @@
         var typeArguments = typeSystem.instantiateTypeFormalsToBounds(
           element.typeParameters,
         );
-        type = element.instantiate2(
+        type = element.instantiate(
           typeArguments: typeArguments,
           nullabilitySuffix: _getNullability(node.question != null),
         );
@@ -6345,7 +5983,6 @@
       }
     }
 
-    typeName.staticType = type;
     node.type = type;
   }
 
@@ -6613,7 +6250,6 @@
       }
     }
 
-    typeName.staticType = type;
     node.type = type;
   }
 
@@ -6653,131 +6289,6 @@
   }
 }
 
-/// This class resolves bounds of type parameters of classes, class and function
-/// type aliases.
-class TypeParameterBoundsResolver {
-  final TypeSystem typeSystem;
-  final LibraryElement library;
-  final Source source;
-  final AnalysisErrorListener errorListener;
-
-  Scope libraryScope;
-  TypeNameResolver typeNameResolver;
-
-  TypeParameterBoundsResolver(this.typeSystem, this.library, this.source,
-      this.errorListener, FeatureSet featureSet)
-      : libraryScope = new LibraryScope(library),
-        typeNameResolver = new TypeNameResolver(
-            typeSystem,
-            typeSystem.typeProvider,
-            featureSet.isEnabled(Feature.non_nullable),
-            library,
-            source,
-            errorListener);
-
-  /// Resolve bounds of type parameters of classes, class and function type
-  /// aliases.
-  void resolveTypeBounds(CompilationUnit unit) {
-    for (CompilationUnitMember unitMember in unit.declarations) {
-      if (unitMember is ClassDeclaration) {
-        _resolveTypeParameters(
-            unitMember.typeParameters,
-            () => new TypeParameterScope(
-                libraryScope, unitMember.declaredElement));
-      } else if (unitMember is ClassTypeAlias) {
-        _resolveTypeParameters(
-            unitMember.typeParameters,
-            () => new TypeParameterScope(
-                libraryScope, unitMember.declaredElement));
-      } else if (unitMember is FunctionTypeAlias) {
-        _resolveTypeParameters(
-            unitMember.typeParameters,
-            () => new FunctionTypeScope(
-                libraryScope, unitMember.declaredElement));
-      } else if (unitMember is GenericTypeAlias) {
-        _resolveTypeParameters(
-            unitMember.typeParameters,
-            () => new FunctionTypeScope(
-                libraryScope, unitMember.declaredElement));
-      }
-    }
-  }
-
-  void _resolveTypeName(TypeAnnotation type) {
-    if (type is TypeName) {
-      type.typeArguments?.arguments?.forEach(_resolveTypeName);
-      typeNameResolver.resolveTypeName(type);
-      // TODO(scheglov) report error when don't apply type bounds for type bounds
-    } else if (type is GenericFunctionType) {
-      // While GenericFunctionTypes with free types are not allowed as bounds,
-      // those free types *should* ideally be recognized as type parameter types
-      // rather than classnames. Create a scope to accomplish that.
-      Scope previousScope = typeNameResolver.nameScope;
-
-      try {
-        Scope typeParametersScope = new TypeParameterScope(
-            typeNameResolver.nameScope, type.type.element);
-        typeNameResolver.nameScope = typeParametersScope;
-
-        void resolveTypeParameter(TypeParameter t) {
-          _resolveTypeName(t.bound);
-        }
-
-        void resolveParameter(FormalParameter p) {
-          if (p is SimpleFormalParameter) {
-            _resolveTypeName(p.type);
-          } else if (p is DefaultFormalParameter) {
-            resolveParameter(p.parameter);
-          } else if (p is FieldFormalParameter) {
-            _resolveTypeName(p.type);
-          } else if (p is FunctionTypedFormalParameter) {
-            _resolveTypeName(p.returnType);
-            p.typeParameters?.typeParameters?.forEach(resolveTypeParameter);
-            p.parameters?.parameters?.forEach(resolveParameter);
-          }
-        }
-
-        _resolveTypeName(type.returnType);
-        type.typeParameters?.typeParameters?.forEach(resolveTypeParameter);
-        type.parameters?.parameters?.forEach(resolveParameter);
-      } finally {
-        typeNameResolver.nameScope = previousScope;
-      }
-    }
-  }
-
-  void _resolveTypeParameters(
-      TypeParameterList typeParameters, Scope createTypeParametersScope()) {
-    if (typeParameters != null) {
-      Scope typeParametersScope;
-      for (TypeParameter typeParameter in typeParameters.typeParameters) {
-        TypeAnnotation bound = typeParameter.bound;
-        if (bound != null) {
-          Element typeParameterElement = typeParameter.name.staticElement;
-          if (typeParameterElement is TypeParameterElementImpl) {
-            if (LibraryElementImpl.hasResolutionCapability(
-                library, LibraryResolutionCapability.resolvedTypeNames)) {
-              if (bound is TypeName) {
-                bound.type = typeParameterElement.bound;
-              } else if (bound is GenericFunctionTypeImpl) {
-                bound.type = typeParameterElement.bound;
-              }
-            } else {
-              typeParametersScope ??= createTypeParametersScope();
-              // _resolveTypeParameters is the entry point into each declaration
-              // with a separate scope. We can safely, and should, clobber the
-              // old scope here.
-              typeNameResolver.nameScope = typeParametersScope;
-              _resolveTypeName(bound);
-              typeParameterElement.bound = bound.type;
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
 /// The interface `TypeProvider` defines the behavior of objects that provide
 /// access to types defined by the language.
 abstract class TypeProvider {
@@ -6951,733 +6462,6 @@
   InterfaceType streamType2(DartType elementType);
 }
 
-/// Modes in which [TypeResolverVisitor] works.
-enum TypeResolverMode {
-  /// Resolve all names types of all nodes.
-  everything,
-
-  /// Resolve only type names outside of function bodies, variable initializers,
-  /// and parameter default values.
-  api,
-
-  /// Resolve only type names that would be skipped during [api].
-  ///
-  /// Resolution must start from a unit member or a class member. For example
-  /// it is not allowed to resolve types in a separate statement, or a function
-  /// body.
-  local
-}
-
-/// Instances of the class `TypeResolverVisitor` are used to resolve the types
-/// associated with the elements in the element model. This includes the types
-/// of superclasses, mixins, interfaces, fields, methods, parameters, and local
-/// variables. As a side-effect, this also finishes building the type hierarchy.
-class TypeResolverVisitor extends ScopedVisitor {
-  /// The type representing the type 'dynamic'.
-  DartType _dynamicType;
-
-  /// The flag specifying if currently visited class references 'super'
-  /// expression.
-  bool _hasReferenceToSuper = false;
-
-  /// True if we're analyzing in strong mode.
-  final bool _strongMode = true;
-
-  /// Type type system in use for this resolver pass.
-  TypeSystem _typeSystem;
-
-  /// Whether the compilation unit is non-nullable.
-  final bool isNonNullableUnit;
-
-  /// The helper to resolve types.
-  TypeNameResolver _typeNameResolver;
-
-  final TypeResolverMode mode;
-
-  /// Is `true` when we are visiting all nodes in [TypeResolverMode.local] mode.
-  bool _localModeVisitAll = false;
-
-  /// Is `true` if we are in [TypeResolverMode.local] mode, and the initial
-  /// [nameScope] was computed.
-  bool _localModeScopeReady = false;
-
-  /// Initialize a newly created visitor to resolve the nodes in an AST node.
-  ///
-  /// [definingLibrary] is the element for the library containing the node being
-  /// visited.
-  /// [source] is the source representing the compilation unit containing the
-  /// node being visited.
-  /// [typeProvider] is the object used to access the types from the core
-  /// library.
-  /// [errorListener] is the error listener that will be informed of any errors
-  /// that are found during resolution.
-  /// [nameScope] is the scope used to resolve identifiers in the node that will
-  /// first be visited.  If `null` or unspecified, a new [LibraryScope] will be
-  /// created based on [definingLibrary] and [typeProvider].
-  ///
-  /// Note: in a future release of the analyzer, the [featureSet] parameter will
-  /// be required.
-  TypeResolverVisitor(LibraryElement definingLibrary, Source source,
-      TypeProvider typeProvider, AnalysisErrorListener errorListener,
-      {Scope nameScope,
-      @Deprecated('Use featureSet instead') bool isNonNullableUnit: false,
-      FeatureSet featureSet,
-      this.mode: TypeResolverMode.everything,
-      bool shouldUseWithClauseInferredTypes: true})
-      : isNonNullableUnit = featureSet?.isEnabled(Feature.non_nullable) ??
-            // ignore: deprecated_member_use_from_same_package
-            isNonNullableUnit,
-        super(definingLibrary, source, typeProvider, errorListener,
-            nameScope: nameScope) {
-    _dynamicType = typeProvider.dynamicType;
-    _typeSystem = TypeSystem.create(definingLibrary.context);
-    _typeNameResolver = new TypeNameResolver(_typeSystem, typeProvider,
-        this.isNonNullableUnit, definingLibrary, source, errorListener,
-        shouldUseWithClauseInferredTypes: shouldUseWithClauseInferredTypes);
-  }
-
-  @override
-  void visitAnnotation(Annotation node) {
-    //
-    // Visit annotations, if the annotation is @proxy, on a class, and "proxy"
-    // resolves to the proxy annotation in dart.core, then resolve the
-    // ElementAnnotation.
-    //
-    // Element resolution is done in the ElementResolver, and this work will be
-    // done in the general case for all annotations in the ElementResolver.
-    // The reason we resolve this particular element early is so that
-    // ClassElement.isProxy() returns the correct information during all
-    // phases of the ElementResolver.
-    //
-    super.visitAnnotation(node);
-    Identifier identifier = node.name;
-    if (identifier.name.endsWith(ElementAnnotationImpl.PROXY_VARIABLE_NAME) &&
-        node.parent is ClassDeclaration) {
-      Element element = nameScope.lookup(identifier, definingLibrary);
-      if (element != null &&
-          element.library.isDartCore &&
-          element is PropertyAccessorElement) {
-        // This is the @proxy from dart.core
-        ElementAnnotationImpl elementAnnotation = node.elementAnnotation;
-        elementAnnotation.element = element;
-      }
-    }
-  }
-
-  @override
-  void visitCatchClause(CatchClause node) {
-    super.visitCatchClause(node);
-    SimpleIdentifier exception = node.exceptionParameter;
-    if (exception != null) {
-      // If an 'on' clause is provided the type of the exception parameter is
-      // the type in the 'on' clause. Otherwise, the type of the exception
-      // parameter is 'Object'.
-      TypeAnnotation exceptionTypeName = node.exceptionType;
-      DartType exceptionType;
-      if (exceptionTypeName == null) {
-        exceptionType = typeProvider.dynamicType;
-      } else {
-        exceptionType = _typeNameResolver._getType(exceptionTypeName);
-      }
-      _recordType(exception, exceptionType);
-      Element element = exception.staticElement;
-      if (element is VariableElementImpl) {
-        element.declaredType = exceptionType;
-      } else {
-        // TODO(brianwilkerson) Report the internal error
-      }
-    }
-    SimpleIdentifier stackTrace = node.stackTraceParameter;
-    if (stackTrace != null) {
-      _recordType(stackTrace, typeProvider.stackTraceType);
-      Element element = stackTrace.staticElement;
-      if (element is VariableElementImpl) {
-        element.declaredType = typeProvider.stackTraceType;
-      } else {
-        // TODO(brianwilkerson) Report the internal error
-      }
-    }
-  }
-
-  @override
-  void visitClassDeclaration(ClassDeclaration node) {
-    _hasReferenceToSuper = false;
-    super.visitClassDeclaration(node);
-    ClassElementImpl classElement = _getClassElement(node.name);
-    if (classElement != null) {
-      // Clear this flag, as we just invalidated any inferred member types.
-      classElement.hasBeenInferred = false;
-      classElement.hasReferenceToSuper = _hasReferenceToSuper;
-    }
-  }
-
-  @override
-  void visitClassDeclarationInScope(ClassDeclaration node) {
-    super.visitClassDeclarationInScope(node);
-    ExtendsClause extendsClause = node.extendsClause;
-    WithClause withClause = node.withClause;
-    ImplementsClause implementsClause = node.implementsClause;
-    ClassElementImpl classElement = _getClassElement(node.name);
-    if (extendsClause != null) {
-      ErrorCode errorCode = (withClause == null
-          ? CompileTimeErrorCode.EXTENDS_NON_CLASS
-          : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS);
-      _resolveType(extendsClause.superclass, errorCode, asClass: true);
-    }
-    _resolveWithClause(classElement, withClause);
-    _resolveImplementsClause(classElement, implementsClause);
-  }
-
-  @override
-  void visitClassMembersInScope(ClassDeclaration node) {
-    node.documentationComment?.accept(this);
-    node.metadata.accept(this);
-    //
-    // Process field declarations before constructors and methods so that the
-    // types of field formal parameters can be correctly resolved.
-    //
-    List<ClassMember> nonFields = new List<ClassMember>();
-    NodeList<ClassMember> members = node.members;
-    int length = members.length;
-    for (int i = 0; i < length; i++) {
-      ClassMember member = members[i];
-      if (member is ConstructorDeclaration) {
-        nonFields.add(member);
-      } else {
-        member.accept(this);
-      }
-    }
-    int count = nonFields.length;
-    for (int i = 0; i < count; i++) {
-      nonFields[i].accept(this);
-    }
-  }
-
-  @override
-  void visitClassTypeAlias(ClassTypeAlias node) {
-    super.visitClassTypeAlias(node);
-    _resolveType(
-      node.superclass,
-      CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS,
-      asClass: true,
-    );
-    ClassElementImpl classElement = _getClassElement(node.name);
-    _resolveWithClause(classElement, node.withClause);
-    _resolveImplementsClause(classElement, node.implementsClause);
-  }
-
-  @override
-  void visitConstructorDeclaration(ConstructorDeclaration node) {
-    super.visitConstructorDeclaration(node);
-    if (node.declaredElement == null) {
-      ClassDeclaration classNode =
-          node.thisOrAncestorOfType<ClassDeclaration>();
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("The element for the constructor ");
-      buffer.write(node.name == null ? "<unnamed>" : node.name.name);
-      buffer.write(" in ");
-      if (classNode == null) {
-        buffer.write("<unknown class>");
-      } else {
-        buffer.write(classNode.name.name);
-      }
-      buffer.write(" in ");
-      buffer.write(source.fullName);
-      buffer.write(" was not set while trying to resolve types.");
-      AnalysisEngine.instance.logger.logError(buffer.toString(),
-          new CaughtException(new AnalysisException(), null));
-    }
-  }
-
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    super.visitDeclaredIdentifier(node);
-    DartType declaredType;
-    TypeAnnotation typeName = node.type;
-    if (typeName == null) {
-      declaredType = _dynamicType;
-    } else {
-      declaredType = _typeNameResolver._getType(typeName);
-    }
-    LocalVariableElementImpl element =
-        node.declaredElement as LocalVariableElementImpl;
-    element.declaredType = declaredType;
-  }
-
-  @override
-  void visitFieldFormalParameter(FieldFormalParameter node) {
-    super.visitFieldFormalParameter(node);
-    Element element = node.identifier.staticElement;
-    if (element is ParameterElementImpl) {
-      FormalParameterList parameterList = node.parameters;
-      if (parameterList == null) {
-        DartType type;
-        TypeAnnotation typeName = node.type;
-        if (typeName == null) {
-          element.hasImplicitType = true;
-          if (element is FieldFormalParameterElement) {
-            FieldElement fieldElement =
-                (element as FieldFormalParameterElement).field;
-            type = fieldElement?.type;
-          }
-        } else {
-          type = _typeNameResolver._getType(typeName);
-        }
-        element.declaredType = type ?? _dynamicType;
-      } else {
-        _setFunctionTypedParameterType(element, node.type, node.parameters);
-      }
-    } else {
-      // TODO(brianwilkerson) Report this internal error
-    }
-  }
-
-  @override
-  void visitFunctionDeclaration(FunctionDeclaration node) {
-    super.visitFunctionDeclaration(node);
-    ExecutableElementImpl element =
-        node.declaredElement as ExecutableElementImpl;
-    if (element == null) {
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("The element for the top-level function ");
-      buffer.write(node.name);
-      buffer.write(" in ");
-      buffer.write(source.fullName);
-      buffer.write(" was not set while trying to resolve types.");
-      AnalysisEngine.instance.logger.logError(buffer.toString(),
-          new CaughtException(new AnalysisException(), null));
-    }
-    element.declaredReturnType = _computeReturnType(node.returnType);
-    _inferSetterReturnType(element);
-  }
-
-  @override
-  void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    var element = node.declaredElement as GenericTypeAliasElementImpl;
-    super.visitFunctionTypeAlias(node);
-    element.function.returnType = _computeReturnType(node.returnType);
-  }
-
-  @override
-  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    super.visitFunctionTypedFormalParameter(node);
-    Element element = node.identifier.staticElement;
-    if (element is ParameterElementImpl) {
-      _setFunctionTypedParameterType(element, node.returnType, node.parameters);
-    } else {
-      // TODO(brianwilkerson) Report this internal error
-    }
-  }
-
-  @override
-  void visitGenericFunctionType(GenericFunctionType node) {
-    GenericFunctionTypeElementImpl element =
-        (node as GenericFunctionTypeImpl).declaredElement;
-    if (node.type != null) {
-      var nullability =
-          _typeNameResolver._getNullability(node.question != null);
-      (node as GenericFunctionTypeImpl).type =
-          (node.type as TypeImpl).withNullability(nullability);
-    }
-    if (element != null) {
-      super.visitGenericFunctionType(node);
-      element.returnType =
-          _computeReturnType(node.returnType) ?? DynamicTypeImpl.instance;
-    }
-  }
-
-  @override
-  void visitMethodDeclaration(MethodDeclaration node) {
-    super.visitMethodDeclaration(node);
-    ExecutableElementImpl element =
-        node.declaredElement as ExecutableElementImpl;
-    if (element == null) {
-      ClassDeclaration classNode =
-          node.thisOrAncestorOfType<ClassDeclaration>();
-      StringBuffer buffer = new StringBuffer();
-      buffer.write("The element for the method ");
-      buffer.write(node.name.name);
-      buffer.write(" in ");
-      if (classNode == null) {
-        buffer.write("<unknown class>");
-      } else {
-        buffer.write(classNode.name.name);
-      }
-      buffer.write(" in ");
-      buffer.write(source.fullName);
-      buffer.write(" was not set while trying to resolve types.");
-      AnalysisEngine.instance.logger.logError(buffer.toString(),
-          new CaughtException(new AnalysisException(), null));
-    }
-
-    // When the library is resynthesized, types of all of its elements are
-    // already set - statically or inferred. We don't want to overwrite them.
-    if (LibraryElementImpl.hasResolutionCapability(
-        definingLibrary, LibraryResolutionCapability.resolvedTypeNames)) {
-      return;
-    }
-
-    element.declaredReturnType = _computeReturnType(node.returnType);
-    _inferSetterReturnType(element);
-    _inferOperatorReturnType(element);
-    if (element is PropertyAccessorElement) {
-      PropertyAccessorElement accessor = element as PropertyAccessorElement;
-      PropertyInducingElementImpl variable =
-          accessor.variable as PropertyInducingElementImpl;
-      if (accessor.isGetter) {
-        variable.declaredType = element.returnType;
-      } else if (variable.type == null) {
-        List<ParameterElement> parameters = element.parameters;
-        DartType type = parameters != null && parameters.isNotEmpty
-            ? parameters[0].type
-            : _dynamicType;
-        variable.declaredType = type;
-      }
-    }
-  }
-
-  @override
-  void visitMixinDeclarationInScope(MixinDeclaration node) {
-    super.visitMixinDeclarationInScope(node);
-    MixinElementImpl element = node.declaredElement;
-    _resolveOnClause(element, node.onClause);
-    _resolveImplementsClause(element, node.implementsClause);
-  }
-
-  @override
-  void visitNode(AstNode node) {
-    // In API mode we need to skip:
-    //   - function bodies;
-    //   - default values of parameters;
-    //   - initializers of top-level variables.
-    if (mode == TypeResolverMode.api) {
-      if (node is FunctionBody) {
-        return;
-      }
-      if (node is DefaultFormalParameter) {
-        node.parameter.accept(this);
-        return;
-      }
-      if (node is VariableDeclaration) {
-        return;
-      }
-    }
-
-    // In local mode we need to resolve only:
-    //   - function bodies;
-    //   - default values of parameters;
-    //   - initializers of top-level variables.
-    // So, we carefully visit only nodes that are, or contain, these nodes.
-    // The client may choose to start visiting any node, but we still want to
-    // resolve only type names that are local.
-    if (mode == TypeResolverMode.local) {
-      // We are in the state of visiting all nodes.
-      if (_localModeVisitAll) {
-        super.visitNode(node);
-        return;
-      }
-
-      // Ensure that the name scope is ready.
-      if (!_localModeScopeReady) {
-        void fillNameScope(AstNode node) {
-          if (node is FunctionBody ||
-              node is FormalParameterList ||
-              node is VariableDeclaration) {
-            throw new StateError(
-                'Local type resolution must start from a class or unit member.');
-          }
-          // Create enclosing name scopes.
-          AstNode parent = node.parent;
-          if (parent != null) {
-            fillNameScope(parent);
-          }
-          // Create the name scope for the node.
-          if (node is ClassDeclaration) {
-            ClassElement classElement = node.declaredElement;
-            nameScope = new TypeParameterScope(nameScope, classElement);
-            nameScope = new ClassScope(nameScope, classElement);
-          }
-        }
-
-        fillNameScope(node);
-        _localModeScopeReady = true;
-      }
-
-      /// Visit the given [node] and all its children.
-      void visitAllNodes(AstNode node) {
-        if (node != null) {
-          bool wasVisitAllInLocalMode = _localModeVisitAll;
-          try {
-            _localModeVisitAll = true;
-            node.accept(this);
-          } finally {
-            _localModeVisitAll = wasVisitAllInLocalMode;
-          }
-        }
-      }
-
-      // Visit only nodes that may contain type names to resolve.
-      if (node is CompilationUnit) {
-        node.declarations.forEach(visitNode);
-      } else if (node is ClassDeclaration) {
-        node.members.forEach(visitNode);
-      } else if (node is DefaultFormalParameter) {
-        visitAllNodes(node.defaultValue);
-      } else if (node is FieldDeclaration) {
-        visitNode(node.fields);
-      } else if (node is FunctionBody) {
-        visitAllNodes(node);
-      } else if (node is FunctionDeclaration) {
-        visitNode(node.functionExpression.parameters);
-        visitAllNodes(node.functionExpression.body);
-      } else if (node is FormalParameterList) {
-        node.parameters.accept(this);
-      } else if (node is MethodDeclaration) {
-        visitNode(node.parameters);
-        visitAllNodes(node.body);
-      } else if (node is TopLevelVariableDeclaration) {
-        visitNode(node.variables);
-      } else if (node is VariableDeclaration) {
-        visitAllNodes(node.initializer);
-      } else if (node is VariableDeclarationList) {
-        node.variables.forEach(visitNode);
-      }
-      return;
-    }
-    // The mode in which we visit all nodes.
-    super.visitNode(node);
-  }
-
-  @override
-  void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    super.visitSimpleFormalParameter(node);
-    DartType declaredType;
-    TypeAnnotation typeName = node.type;
-    if (typeName == null) {
-      declaredType = _dynamicType;
-    } else {
-      declaredType = _typeNameResolver._getType(typeName);
-    }
-    Element element = node.declaredElement;
-    if (element is ParameterElementImpl) {
-      element.declaredType = declaredType;
-    } else {
-      // TODO(brianwilkerson) Report the internal error.
-    }
-  }
-
-  @override
-  void visitSuperExpression(SuperExpression node) {
-    _hasReferenceToSuper = true;
-    super.visitSuperExpression(node);
-  }
-
-  @override
-  void visitTypeName(TypeName node) {
-    super.visitTypeName(node);
-    _typeNameResolver.nameScope = this.nameScope;
-    _typeNameResolver.resolveTypeName(node);
-  }
-
-  @override
-  void visitTypeParameter(TypeParameter node) {
-    super.visitTypeParameter(node);
-    AstNode parent2 = node.parent?.parent;
-    if (parent2 is ClassDeclaration ||
-        parent2 is ClassTypeAlias ||
-        parent2 is FunctionTypeAlias ||
-        parent2 is GenericTypeAlias) {
-      // Bounds of parameters of classes and function type aliases are
-      // already resolved.
-    } else {
-      TypeAnnotation bound = node.bound;
-      if (bound != null) {
-        TypeParameterElementImpl typeParameter =
-            node.name.staticElement as TypeParameterElementImpl;
-        if (typeParameter != null) {
-          typeParameter.bound = bound.type;
-        }
-      }
-    }
-  }
-
-  @override
-  void visitVariableDeclaration(VariableDeclaration node) {
-    super.visitVariableDeclaration(node);
-    var variableList = node.parent as VariableDeclarationList;
-    // When the library is resynthesized, the types of field elements are
-    // already set - statically or inferred. We don't want to overwrite them.
-    if (variableList.parent is FieldDeclaration &&
-        LibraryElementImpl.hasResolutionCapability(
-            definingLibrary, LibraryResolutionCapability.resolvedTypeNames)) {
-      return;
-    }
-    // Resolve the type.
-    DartType declaredType;
-    TypeAnnotation typeName = variableList.type;
-    if (typeName == null) {
-      declaredType = _dynamicType;
-    } else {
-      declaredType = _typeNameResolver._getType(typeName);
-    }
-    Element element = node.name.staticElement;
-    if (element is VariableElementImpl) {
-      element.declaredType = declaredType;
-    }
-  }
-
-  /// Given the [returnType] of a function, compute the return type of the
-  /// function.
-  DartType _computeReturnType(TypeAnnotation returnType) {
-    if (returnType == null) {
-      return _dynamicType;
-    } else {
-      return _typeNameResolver._getType(returnType);
-    }
-  }
-
-  /// Return the class element that represents the class whose name was
-  /// provided.
-  ///
-  /// @param identifier the name from the declaration of a class
-  /// @return the class element that represents the class
-  ClassElementImpl _getClassElement(SimpleIdentifier identifier) {
-    // TODO(brianwilkerson) Seems like we should be using
-    // ClassDeclaration.getElement().
-    if (identifier == null) {
-      // TODO(brianwilkerson) Report this
-      // Internal error: We should never build a class declaration without a
-      // name.
-      return null;
-    }
-    Element element = identifier.staticElement;
-    if (element is ClassElementImpl) {
-      return element;
-    }
-    // TODO(brianwilkerson) Report this
-    // Internal error: Failed to create an element for a class declaration.
-    return null;
-  }
-
-  /// In strong mode we infer "void" as the return type of operator []= (as void
-  /// is the only legal return type for []=). This allows us to give better
-  /// errors later if an invalid type is returned.
-  void _inferOperatorReturnType(ExecutableElementImpl element) {
-    if (_strongMode &&
-        element.isOperator &&
-        element.name == '[]=' &&
-        element.hasImplicitReturnType) {
-      element.declaredReturnType = VoidTypeImpl.instance;
-    }
-  }
-
-  /// In strong mode we infer "void" as the setter return type (as void is the
-  /// only legal return type for a setter). This allows us to give better
-  /// errors later if an invalid type is returned.
-  void _inferSetterReturnType(ExecutableElementImpl element) {
-    if (_strongMode &&
-        element is PropertyAccessorElementImpl &&
-        element.isSetter &&
-        element.hasImplicitReturnType) {
-      element.declaredReturnType = VoidTypeImpl.instance;
-    }
-  }
-
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  Object _recordType(Expression expression, DartType type) {
-    if (type == null) {
-      expression.staticType = _dynamicType;
-    } else {
-      expression.staticType = type;
-    }
-    return null;
-  }
-
-  void _resolveImplementsClause(
-      ClassElementImpl classElement, ImplementsClause clause) {
-    if (clause != null) {
-      _resolveTypes(
-          clause.interfaces, CompileTimeErrorCode.IMPLEMENTS_NON_CLASS);
-    }
-  }
-
-  void _resolveOnClause(MixinElementImpl classElement, OnClause clause) {
-    List<InterfaceType> types;
-    if (clause != null) {
-      _resolveTypes(clause.superclassConstraints,
-          CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE);
-    }
-    if (types == null || types.isEmpty) {
-      types = [typeProvider.objectType];
-    }
-  }
-
-  /// Return the [InterfaceType] of the given [typeName].
-  ///
-  /// If the resulting type is not a valid interface type, return `null`.
-  ///
-  /// The flag [asClass] specifies if the type will be used as a class, so mixin
-  /// declarations are not valid (they declare interfaces and mixins, but not
-  /// classes).
-  void _resolveType(TypeName typeName, ErrorCode errorCode,
-      {bool asClass: false}) {
-    DartType type = typeName.type;
-    if (type is InterfaceType) {
-      ClassElement element = type.element;
-      if (element != null) {
-        if (element.isEnum || element.isMixin && asClass) {
-          errorReporter.reportErrorForNode(errorCode, typeName);
-          return;
-        }
-      }
-      return;
-    }
-    // If the type is not an InterfaceType, then visitTypeName() sets the type
-    // to be a DynamicTypeImpl
-    Identifier name = typeName.name;
-    if (!nameScope.shouldIgnoreUndefined(name)) {
-      errorReporter.reportErrorForNode(errorCode, name, [name.name]);
-    }
-  }
-
-  /// Resolve the types in the given list of type names.
-  ///
-  /// @param typeNames the type names to be resolved
-  /// @param nonTypeError the error to produce if the type name is defined to be
-  ///        something other than a type
-  /// @param enumTypeError the error to produce if the type name is defined to
-  ///        be an enum
-  /// @param dynamicTypeError the error to produce if the type name is "dynamic"
-  /// @return an array containing all of the types that were resolved.
-  void _resolveTypes(NodeList<TypeName> typeNames, ErrorCode errorCode) {
-    for (TypeName typeName in typeNames) {
-      _resolveType(typeName, errorCode);
-    }
-  }
-
-  void _resolveWithClause(ClassElementImpl classElement, WithClause clause) {
-    if (clause != null) {
-      _resolveTypes(clause.mixinTypes, CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
-    }
-  }
-
-  /// Given a function typed [parameter] with [FunctionType] based on a
-  /// [GenericFunctionTypeElementImpl], compute and set the return type for the
-  /// function element.
-  void _setFunctionTypedParameterType(ParameterElementImpl parameter,
-      TypeAnnotation returnType, FormalParameterList parameterList) {
-    DartType type = parameter.type;
-    GenericFunctionTypeElementImpl typeElement = type.element;
-    // With summary2 we use synthetic FunctionType(s).
-    if (typeElement != null) {
-      typeElement.returnType = _computeReturnType(returnType);
-    }
-  }
-}
-
 /// Instances of the class [UnusedLocalElementsVerifier] traverse an AST
 /// looking for cases of [HintCode.UNUSED_ELEMENT], [HintCode.UNUSED_FIELD],
 /// [HintCode.UNUSED_LOCAL_VARIABLE], etc.
@@ -7911,8 +6695,8 @@
   /// not inside a method or function.
   ExecutableElement _enclosingFunction;
 
-  /// Information about local variables in the enclosing function or method.
-  LocalVariableInfo _localVariableInfo;
+  /// The container with information about local variables.
+  final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
 
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
@@ -7929,9 +6713,8 @@
   /// created based on [definingLibrary] and [typeProvider].
   VariableResolverVisitor(LibraryElement definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
-      {Scope nameScope, LocalVariableInfo localVariableInfo})
-      : _localVariableInfo = localVariableInfo,
-        super(definingLibrary, source, typeProvider, errorListener,
+      {Scope nameScope})
+      : super(definingLibrary, source, typeProvider, errorListener,
             nameScope: nameScope);
 
   @override
@@ -7941,22 +6724,13 @@
   }
 
   @override
-  void visitCompilationUnit(CompilationUnit node) {
-    _localVariableInfo = (node as CompilationUnitImpl).localVariableInfo;
-    super.visitCompilationUnit(node);
-  }
-
-  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
-    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
     try {
-      _localVariableInfo ??= new LocalVariableInfo();
       (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
       _enclosingFunction = node.declaredElement;
       super.visitConstructorDeclaration(node);
     } finally {
-      _localVariableInfo = outerLocalVariableInfo;
       _enclosingFunction = outerFunction;
     }
   }
@@ -7973,15 +6747,12 @@
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
-    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
     try {
-      _localVariableInfo ??= new LocalVariableInfo();
       (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
           _localVariableInfo;
       _enclosingFunction = node.declaredElement;
       super.visitFunctionDeclaration(node);
     } finally {
-      _localVariableInfo = outerLocalVariableInfo;
       _enclosingFunction = outerFunction;
     }
   }
@@ -7990,14 +6761,11 @@
   void visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
       ExecutableElement outerFunction = _enclosingFunction;
-      LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
       try {
-        _localVariableInfo ??= new LocalVariableInfo();
         (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
         _enclosingFunction = node.declaredElement;
         super.visitFunctionExpression(node);
       } finally {
-        _localVariableInfo = outerLocalVariableInfo;
         _enclosingFunction = outerFunction;
       }
     } else {
@@ -8011,14 +6779,11 @@
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement outerFunction = _enclosingFunction;
-    LocalVariableInfo outerLocalVariableInfo = _localVariableInfo;
     try {
-      _localVariableInfo ??= new LocalVariableInfo();
       (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
       _enclosingFunction = node.declaredElement;
       super.visitMethodDeclaration(node);
     } finally {
-      _localVariableInfo = outerLocalVariableInfo;
       _enclosingFunction = outerFunction;
     }
   }
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 1db0d80..81ad574 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -329,8 +329,6 @@
    */
   LibraryMap _librariesMap = new LibraryMap();
 
-  SdkLibrariesReader_LibraryBuilder([@deprecated bool useDart2jsPaths]);
-
   /**
    * Return the library map that was populated by visiting the AST structure
    * parsed from the contents of the libraries file.
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index b1ec9e0..48993a4 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -117,9 +117,9 @@
     try {
       return new FileBasedSource(file, Uri.parse(path));
     } on FormatException catch (exception, stackTrace) {
-      AnalysisEngine.instance.logger.logInformation(
+      AnalysisEngine.instance.instrumentationService.logInfo(
           "Failed to create URI: $path",
-          new CaughtException(exception, stackTrace));
+          CaughtException(exception, stackTrace));
     }
     return null;
   }
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index dd872c2..33af032 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -248,52 +248,6 @@
 }
 
 /**
- * Instances of interface `LocalSourcePredicate` are used to determine if the given
- * [Source] is "local" in some sense, so can be updated.
- */
-abstract class LocalSourcePredicate {
-  /**
-   * Instance of [LocalSourcePredicate] that always returns `false`.
-   */
-  static final LocalSourcePredicate FALSE = new LocalSourcePredicate_FALSE();
-
-  /**
-   * Instance of [LocalSourcePredicate] that always returns `true`.
-   */
-  static final LocalSourcePredicate TRUE = new LocalSourcePredicate_TRUE();
-
-  /**
-   * Instance of [LocalSourcePredicate] that returns `true` for all [Source]s
-   * except of SDK.
-   */
-  static final LocalSourcePredicate NOT_SDK =
-      new LocalSourcePredicate_NOT_SDK();
-
-  /**
-   * Determines if the given [Source] is local.
-   *
-   * @param source the [Source] to analyze
-   * @return `true` if the given [Source] is local
-   */
-  bool isLocal(Source source);
-}
-
-class LocalSourcePredicate_FALSE implements LocalSourcePredicate {
-  @override
-  bool isLocal(Source source) => false;
-}
-
-class LocalSourcePredicate_NOT_SDK implements LocalSourcePredicate {
-  @override
-  bool isLocal(Source source) => source.uriKind != UriKind.DART_URI;
-}
-
-class LocalSourcePredicate_TRUE implements LocalSourcePredicate {
-  @override
-  bool isLocal(Source source) => true;
-}
-
-/**
  * An implementation of an non-existing [Source].
  */
 class NonExistingSource extends Source {
@@ -492,48 +446,11 @@
 }
 
 /**
- * The interface `ContentReceiver` defines the behavior of objects that can receive the
- * content of a source.
- */
-abstract class Source_ContentReceiver {
-  /**
-   * Accept the contents of a source.
-   *
-   * @param contents the contents of the source
-   * @param modificationTime the time at which the contents were last set
-   */
-  void accept(String contents, int modificationTime);
-}
-
-/**
- * The interface `SourceContainer` is used by clients to define a collection of sources
- *
- * Source containers are not used within analysis engine, but can be used by clients to group
- * sources for the purposes of accessing composite dependency information. For example, the Eclipse
- * client uses source containers to represent Eclipse projects, which allows it to easily compute
- * project-level dependencies.
- */
-abstract class SourceContainer {
-  /**
-   * Determine if the specified source is part of the receiver's collection of sources.
-   *
-   * @param source the source in question
-   * @return `true` if the receiver contains the source, else `false`
-   */
-  bool contains(Source source);
-}
-
-/**
  * Instances of the class `SourceFactory` resolve possibly relative URI's against an existing
  * [Source].
  */
 abstract class SourceFactory {
   /**
-   * The analysis context that this source factory is associated with.
-   */
-  AnalysisContext context;
-
-  /**
    * Initialize a newly created source factory with the given absolute URI
    * [resolvers] and optional [packages] resolution helper.
    */
@@ -550,13 +467,6 @@
    */
   DartSdk get dartSdk;
 
-  /**
-   * Sets the [LocalSourcePredicate].
-   *
-   * @param localSourcePredicate the predicate to determine is [Source] is local
-   */
-  void set localSourcePredicate(LocalSourcePredicate localSourcePredicate);
-
   /// A table mapping package names to paths of directories containing
   /// the package (or [null] if there is no registered package URI resolver).
   Map<String, List<Folder>> get packageMap;
@@ -568,12 +478,6 @@
   void clearCache();
 
   /**
-   * Return a source factory that will resolve URI's in the same way that this
-   * source factory does.
-   */
-  SourceFactory clone();
-
-  /**
    * Return a source object representing the given absolute URI, or `null` if
    * the URI is not a valid URI or if it is not an absolute URI.
    *
@@ -592,24 +496,6 @@
   Source forUri2(Uri absoluteUri);
 
   /**
-   * Return a source object that is equal to the source object used to obtain
-   * the given encoding.
-   *
-   * @param encoding the encoding of a source object
-   * @return a source object that is described by the given encoding
-   * @throws IllegalArgumentException if the argument is not a valid encoding
-   */
-  Source fromEncoding(String encoding);
-
-  /**
-   * Determines if the given [Source] is local.
-   *
-   * @param source the [Source] to analyze
-   * @return `true` if the given [Source] is local
-   */
-  bool isLocalSource(Source source);
-
-  /**
    * Return a source representing the URI that results from resolving the given
    * (possibly relative) [containedUri] against the URI associated with the
    * [containingSource], whether or not the resulting source exists, or `null`
diff --git a/pkg/analyzer/lib/src/generated/source_io.dart b/pkg/analyzer/lib/src/generated/source_io.dart
index f6319d1..33f39c3 100644
--- a/pkg/analyzer/lib/src/generated/source_io.dart
+++ b/pkg/analyzer/lib/src/generated/source_io.dart
@@ -339,12 +339,14 @@
       pkgDir = pkgDir.getCanonicalFile();
     } catch (exception, stackTrace) {
       if (!exception.toString().contains("Required key not available")) {
-        AnalysisEngine.instance.logger.logError("Canonical failed: $pkgDir",
-            new CaughtException(exception, stackTrace));
+        AnalysisEngine.instance.instrumentationService.logException(
+            new CaughtException.withMessage(
+                "Canonical failed: $pkgDir", exception, stackTrace));
       } else if (_CanLogRequiredKeyIoException) {
         _CanLogRequiredKeyIoException = false;
-        AnalysisEngine.instance.logger.logError("Canonical failed: $pkgDir",
-            new CaughtException(exception, stackTrace));
+        AnalysisEngine.instance.instrumentationService.logException(
+            new CaughtException.withMessage(
+                "Canonical failed: $pkgDir", exception, stackTrace));
       }
     }
     return new JavaFile.relative(
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 974ae86..e4ba3a4 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -69,18 +70,23 @@
    */
   DartType thisType;
 
+  InterfaceType _iterableForSetMapDisambiguationCached;
+  InterfaceType _mapForSetMapDisambiguationCached;
+
   /**
    * The object providing promoted or declared types of variables.
    */
   LocalVariableTypeProvider _localVariableTypeProvider;
 
+  final FlowAnalysisHelper _flowAnalysis;
+
   /**
    * Initialize a newly created static type analyzer to analyze types for the
    * [_resolver] based on the
    *
    * @param resolver the resolver driving this participant
    */
-  StaticTypeAnalyzer(this._resolver, this._featureSet) {
+  StaticTypeAnalyzer(this._resolver, this._featureSet, this._flowAnalysis) {
     _typeProvider = _resolver.typeProvider;
     _typeSystem = _resolver.typeSystem;
     _dynamicType = _typeProvider.dynamicType;
@@ -90,6 +96,31 @@
     _strictInference = analysisOptions.strictInference;
   }
 
+  InterfaceType get _iterableForSetMapDisambiguation {
+    return _iterableForSetMapDisambiguationCached ??=
+        _typeProvider.iterableElement.instantiate(
+      typeArguments: [
+        _typeProvider.dynamicType,
+      ],
+      nullabilitySuffix: _nonNullableEnabled
+          ? NullabilitySuffix.question
+          : NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get _mapForSetMapDisambiguation {
+    return _mapForSetMapDisambiguationCached ??=
+        _typeProvider.mapElement.instantiate(
+      typeArguments: [
+        _typeProvider.dynamicType,
+        _typeProvider.dynamicType,
+      ],
+      nullabilitySuffix: _nonNullableEnabled
+          ? NullabilitySuffix.question
+          : NullabilitySuffix.star,
+    );
+  }
+
   NullabilitySuffix get _noneOrStarSuffix {
     return _nonNullableEnabled
         ? NullabilitySuffix.none
@@ -102,6 +133,31 @@
   bool get _nonNullableEnabled => _featureSet.isEnabled(Feature.non_nullable);
 
   /**
+   * Given an iterable expression from a foreach loop, attempt to infer
+   * a type for the elements being iterated over.  Inference is based
+   * on the type of the iterator or stream over which the foreach loop
+   * is defined.
+   */
+  DartType computeForEachElementType(Expression iterable, bool isAsync) {
+    DartType iterableType = iterable.staticType;
+    if (iterableType == null) return null;
+    iterableType = iterableType.resolveToBound(_typeProvider.objectType);
+
+    ClassElement iteratedElement =
+        isAsync ? _typeProvider.streamElement : _typeProvider.iterableElement;
+
+    InterfaceType iteratedType = iterableType is InterfaceTypeImpl
+        ? iterableType.asInstanceOf(iteratedElement)
+        : null;
+
+    if (iteratedType != null) {
+      return iteratedType.typeArguments.single;
+    } else {
+      return null;
+    }
+  }
+
+  /**
    * Given a constructor name [node] and a type [type], record an inferred type
    * for the constructor if in strong mode. This is used to fill in any
    * inferred type parameters found by the resolver.
@@ -228,7 +284,7 @@
     );
   }
 
-  ParameterizedType inferMapTypeDownwards(
+  InterfaceType inferMapTypeDownwards(
       SetOrMapLiteral node, DartType contextType) {
     if (contextType == null) {
       return null;
@@ -360,7 +416,6 @@
         _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide,
             read: true);
       }
-      return;
     } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
         operator == TokenType.BAR_BAR_EQ) {
       _recordStaticType(node, _nonNullable(_typeProvider.boolType));
@@ -515,12 +570,6 @@
     _analyzeLeastUpperBound(node, node.thenExpression, node.elseExpression);
   }
 
-  @override
-  void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    super.visitDeclaredIdentifier(node);
-    _inferForEachLoopVariableType(node);
-  }
-
   /**
    * The Dart Language Specification, 12.3: <blockquote>The static type of a literal double is
    * double.</blockquote>
@@ -545,14 +594,12 @@
       // we only need to handle local functions.
       if (node.returnType == null) {
         _inferLocalFunctionReturnType(node.functionExpression);
-        _recordStaticTypeWhereItShouldNotBe(node.name, functionElement.type);
         return;
       }
       functionElement.returnType =
           _computeStaticReturnTypeOfFunctionDeclaration(node);
     }
     _recordStaticType(function, functionElement.type);
-    _recordStaticTypeWhereItShouldNotBe(node.name, functionElement.type);
   }
 
   /**
@@ -851,12 +898,21 @@
     if (node.operator.type == TokenType.BANG) {
       staticType = _typeSystem.promoteToNonNull(staticType);
     } else {
-      // No need to check for `intVar++`, the result is `int`.
-      if (!staticType.isDartCoreInt) {
+      DartType operatorReturnType;
+      if (staticType.isDartCoreInt) {
+        // No need to check for `intVar++`, the result is `int`.
+        operatorReturnType = staticType;
+      } else {
         var operatorElement = node.staticElement;
-        var operatorReturnType = _computeStaticReturnType(operatorElement);
+        operatorReturnType = _computeStaticReturnType(operatorElement);
         _checkForInvalidAssignmentIncDec(node, operand, operatorReturnType);
       }
+      if (operand is SimpleIdentifier) {
+        var element = operand.staticElement;
+        if (element is PromotableElement) {
+          _flowAnalysis?.flow?.write(element, operatorReturnType);
+        }
+      }
     }
 
     _recordStaticType(node, staticType);
@@ -877,25 +933,27 @@
 
     DartType staticType = _dynamicType;
     if (staticElement is ClassElement) {
-      if (_isNotTypeLiteral(node)) {
-        staticType = staticElement.type;
-      } else {
-        staticType = _nonNullable(_typeProvider.typeType);
+      if (_isExpressionIdentifier(node)) {
+        var type = _nonNullable(_typeProvider.typeType);
+        node.staticType = type;
+        node.identifier.staticType = type;
       }
+      return;
     } else if (staticElement is FunctionTypeAliasElement) {
-      if (_isNotTypeLiteral(node)) {
-        staticType = staticElement.type;
+      if (node.parent is TypeName) {
+        // no type
       } else {
-        staticType = _nonNullable(_typeProvider.typeType);
+        var type = _nonNullable(_typeProvider.typeType);
+        node.staticType = type;
+        node.identifier.staticType = type;
       }
+      return;
     } else if (staticElement is MethodElement) {
       staticType = staticElement.type;
     } else if (staticElement is PropertyAccessorElement) {
       staticType = _getTypeOfProperty(staticElement);
     } else if (staticElement is ExecutableElement) {
       staticType = staticElement.type;
-    } else if (staticElement is TypeParameterElement) {
-      staticType = staticElement.type;
     } else if (staticElement is VariableElement) {
       staticType = staticElement.type;
     }
@@ -921,8 +979,7 @@
       // The other cases are equivalent to invoking a method.
       ExecutableElement staticMethodElement = node.staticElement;
       DartType staticType = _computeStaticReturnType(staticMethodElement);
-      if (operator == TokenType.MINUS_MINUS ||
-          operator == TokenType.PLUS_PLUS) {
+      if (operator.isIncrementOperator) {
         Expression operand = node.operand;
         var operandReadType = _getStaticType(operand, read: true);
         if (operandReadType.isDartCoreInt) {
@@ -930,6 +987,12 @@
         } else {
           _checkForInvalidAssignmentIncDec(node, operand, staticType);
         }
+        if (operand is SimpleIdentifier) {
+          var element = operand.staticElement;
+          if (element is PromotableElement) {
+            _flowAnalysis?.flow?.write(element, staticType);
+          }
+        }
       }
       _recordStaticType(node, staticType);
     }
@@ -1109,17 +1172,17 @@
 
     DartType staticType = _dynamicType;
     if (element is ClassElement) {
-      if (_isNotTypeLiteral(node)) {
-        staticType = element.type;
-      } else {
-        staticType = _nonNullable(_typeProvider.typeType);
+      if (_isExpressionIdentifier(node)) {
+        node.staticType = _nonNullable(_typeProvider.typeType);
       }
+      return;
     } else if (element is FunctionTypeAliasElement) {
-      if (_isNotTypeLiteral(node)) {
-        staticType = element.type;
+      if (node.inDeclarationContext() || node.parent is TypeName) {
+        // no type
       } else {
-        staticType = _nonNullable(_typeProvider.typeType);
+        node.staticType = _nonNullable(_typeProvider.typeType);
       }
+      return;
     } else if (element is MethodElement) {
       staticType = element.type;
     } else if (element is PropertyAccessorElement) {
@@ -1386,6 +1449,35 @@
     return returnType.type;
   }
 
+  /// If [node] is a null-shorting expression, updates flow analysis as
+  /// appropriate to finish the null shorting, and returns `true`.  Otherwise
+  /// returns `false`.
+  bool _finishNullShorting(Expression node) {
+    bool nullShortingFound = false;
+    while (true) {
+      Expression next;
+      if (node is AssignmentExpression) {
+        next = node.leftHandSide;
+      } else if (node is IndexExpression) {
+        if (node.isNullAware) {
+          nullShortingFound = true;
+          _flowAnalysis?.flow?.nullAwareAccess_end();
+        }
+        next = node.target;
+      } else if (node is PropertyAccess) {
+        if (node.isNullAware) {
+          nullShortingFound = true;
+          _flowAnalysis?.flow?.nullAwareAccess_end();
+        }
+        next = node.target;
+      } else {
+        break;
+      }
+      node = next;
+    }
+    return nullShortingFound;
+  }
+
   /**
    * If the given element name can be mapped to the name of a class defined within the given
    * library, return the type specified by the argument.
@@ -1452,7 +1544,17 @@
     if (read) {
       type = getReadType(expression);
     } else {
-      type = expression.staticType;
+      if (expression is SimpleIdentifier && expression.inSetterContext()) {
+        var element = expression.staticElement;
+        if (element is PromotableElement) {
+          // We're writing to the element so ignore promotions.
+          type = element.type;
+        } else {
+          type = expression.staticType;
+        }
+      } else {
+        type = expression.staticType;
+      }
     }
     if (type == null) {
       // TODO(brianwilkerson) Determine the conditions for which the static type
@@ -1570,53 +1672,6 @@
   }
 
   /**
-   * Given a declared identifier from a foreach loop, attempt to infer
-   * a type for it if one is not already present.  Inference is based
-   * on the type of the iterator or stream over which the foreach loop
-   * is defined.
-   */
-  void _inferForEachLoopVariableType(DeclaredIdentifier loopVariable) {
-    if (loopVariable != null && loopVariable.type == null) {
-      AstNode parent = loopVariable.parent;
-      Token awaitKeyword;
-      Expression iterable;
-      if (parent is ForEachPartsWithDeclaration) {
-        AstNode parentParent = parent.parent;
-        if (parentParent is ForStatementImpl) {
-          awaitKeyword = parentParent.awaitKeyword;
-        } else if (parentParent is ForElement) {
-          awaitKeyword = parentParent.awaitKeyword;
-        } else {
-          return;
-        }
-        iterable = parent.iterable;
-      } else {
-        return;
-      }
-      if (iterable != null) {
-        LocalVariableElementImpl element = loopVariable.declaredElement;
-
-        DartType iterableType = iterable.staticType;
-        iterableType = iterableType.resolveToBound(_typeProvider.objectType);
-
-        ClassElement iteratedElement = (awaitKeyword == null)
-            ? _typeProvider.iterableElement
-            : _typeProvider.streamElement;
-
-        InterfaceType iteratedType = iterableType is InterfaceTypeImpl
-            ? iterableType.asInstanceOf(iteratedElement)
-            : null;
-
-        if (element != null && iteratedType != null) {
-          DartType elementType = iteratedType.typeArguments.single;
-          element.type = elementType;
-          loopVariable.identifier.staticType = elementType;
-        }
-      }
-    }
-  }
-
-  /**
    * Given a possibly generic invocation like `o.m(args)` or `(f)(args)` try to
    * infer the instantiated generic function type.
    *
@@ -1788,7 +1843,6 @@
           VariableElement element = node.declaredElement;
           if (element is LocalVariableElementImpl) {
             element.type = initializer.staticType;
-            node.name.staticType = initializer.staticType;
           }
         }
       }
@@ -1941,9 +1995,9 @@
     bool contextProvidesAmbiguityResolutionClues =
         contextType != null && contextType is! UnknownInferredType;
     bool contextIsIterable = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(contextType, _typeProvider.iterableObjectType);
+        _typeSystem.isSubtypeOf(contextType, _iterableForSetMapDisambiguation);
     bool contextIsMap = contextProvidesAmbiguityResolutionClues &&
-        _typeSystem.isSubtypeOf(contextType, _typeProvider.mapObjectObjectType);
+        _typeSystem.isSubtypeOf(contextType, _mapForSetMapDisambiguation);
     if (contextIsIterable && !contextIsMap) {
       return _toSetType(literal, contextType, inferredTypes);
     } else if ((contextIsMap && !contextIsIterable) || elements.isEmpty) {
@@ -1994,17 +2048,24 @@
   /**
    * Return `true` if the given [node] is not a type literal.
    */
-  bool _isNotTypeLiteral(Identifier node) {
-    AstNode parent = node.parent;
-    return parent is TypeName ||
-        (parent is PrefixedIdentifier &&
-            (parent.parent is TypeName || identical(parent.prefix, node))) ||
-        (parent is PropertyAccess &&
-            identical(parent.target, node) &&
-            parent.operator.type == TokenType.PERIOD) ||
-        (parent is MethodInvocation &&
-            identical(node, parent.target) &&
-            parent.operator.type == TokenType.PERIOD);
+  bool _isExpressionIdentifier(Identifier node) {
+    var parent = node.parent;
+    if (node is SimpleIdentifier && node.inDeclarationContext()) {
+      return false;
+    }
+    if (parent is ConstructorDeclaration) {
+      if (parent.name == node || parent.returnType == node) {
+        return false;
+      }
+    }
+    if (parent is ConstructorName ||
+        parent is MethodInvocation ||
+        parent is PrefixedIdentifier && parent.prefix == node ||
+        parent is PropertyAccess ||
+        parent is TypeName) {
+      return false;
+    }
+    return true;
   }
 
   /**
@@ -2030,8 +2091,11 @@
     if (parent is PropertyAccess) {
       return;
     }
+    if (parent is IndexExpression && parent.target == node) {
+      return;
+    }
 
-    if (_hasNullShorting(node)) {
+    if (_finishNullShorting(node)) {
       var type = node.staticType;
       node.staticType = _typeSystem.makeNullable(type);
     }
@@ -2048,14 +2112,12 @@
       expression.staticType = _dynamicType;
     } else {
       expression.staticType = type;
+      if (identical(type, BottomTypeImpl.instance)) {
+        _flowAnalysis?.flow?.handleExit();
+      }
     }
   }
 
-  /// Remove when https://dart-review.googlesource.com/c/sdk/+/119761 lands.
-  void _recordStaticTypeWhereItShouldNotBe(Expression node, DartType type) {
-    node.staticType = type;
-  }
-
   void _setExtensionIdentifierType(Identifier node) {
     if (node is SimpleIdentifier && node.inDeclarationContext()) {
       return;
@@ -2178,6 +2240,7 @@
       constructor.returnType,
       typeParameters,
       constructor.parameters,
+      nullabilitySuffix: NullabilitySuffix.star,
     );
   }
 
@@ -2189,20 +2252,6 @@
       return type;
     }
   }
-
-  /// Return `true` if the [node] has null-aware shorting, e.g. `foo?.bar`.
-  static bool _hasNullShorting(Expression node) {
-    if (node is AssignmentExpression) {
-      return _hasNullShorting(node.leftHandSide);
-    }
-    if (node is IndexExpression) {
-      return node.isNullAware || _hasNullShorting(node.target);
-    }
-    if (node is PropertyAccess) {
-      return node.isNullAware || _hasNullShorting(node.target);
-    }
-    return false;
-  }
 }
 
 class _InferredCollectionElementTypeInformation {
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index e3d001e..a854d3f 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -787,6 +787,14 @@
           index,
           TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
 
+  static IndexExpression indexExpressionForCascade(Expression array,
+          Expression index, TokenType period, TokenType leftBracket) =>
+      astFactory.indexExpressionForCascade(
+          TokenFactory.tokenFromType(period),
+          TokenFactory.tokenFromType(leftBracket),
+          index,
+          TokenFactory.tokenFromType(TokenType.CLOSE_SQUARE_BRACKET));
+
   static InstanceCreationExpression instanceCreationExpression(
           Keyword keyword, ConstructorName name,
           [List<Expression> arguments]) =>
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index cf1a27a..cfebd50 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -93,11 +93,6 @@
  * A type system that implements the type semantics for Dart 2.0.
  */
 class Dart2TypeSystem extends TypeSystem {
-  /// Track types currently being compared via type parameter bounds so that we
-  /// can detect recursion.
-  static Set<TypeComparison> _typeParameterBoundsComparisons =
-      new HashSet<TypeComparison>();
-
   /**
    * False if implicit casts should always be disallowed, otherwise the
    * [FeatureSet] will be used.
@@ -113,9 +108,30 @@
 
   final TypeProvider typeProvider;
 
+  /// The cached instance of `Object?`.
+  InterfaceTypeImpl _objectQuestionCached;
+
+  /// The cached instance of `Object!`.
+  InterfaceTypeImpl _objectNoneCached;
+
+  /// The cached instance of `Null!`.
+  InterfaceTypeImpl _nullNoneCached;
+
   Dart2TypeSystem(this.typeProvider,
       {this.implicitCasts: true, this.strictInference: false});
 
+  InterfaceTypeImpl get _nullNone =>
+      _nullNoneCached ??= (typeProvider.nullType as TypeImpl)
+          .withNullability(NullabilitySuffix.none);
+
+  InterfaceTypeImpl get _objectNone =>
+      _objectNoneCached ??= (typeProvider.objectType as TypeImpl)
+          .withNullability(NullabilitySuffix.none);
+
+  InterfaceTypeImpl get _objectQuestion =>
+      _objectQuestionCached ??= (typeProvider.objectType as TypeImpl)
+          .withNullability(NullabilitySuffix.question);
+
   /// Returns true iff the type [t] accepts function types, and requires an
   /// implicit coercion if interface types with a `call` method are passed in.
   ///
@@ -579,146 +595,248 @@
         p1.isCovariant && isSubtypeOf(p1.type, p2.type);
   }
 
-  /// Check if [_t1] is a subtype of [_t2].
+  /// Check if [_T0] is a subtype of [_T1].
   ///
-  /// Partially updated to reflect
-  /// https://github.com/dart-lang/language/blob/da5adf7eb5f2d479069d8660ed7ca7b230098510/resources/type-system/subtyping.md
-  ///
-  /// However, it does not correlate 1:1 and does not specialize Null vs Never
-  /// cases. It also is not guaranteed to be exactly accurate vs the "spec"
-  /// because it has slightly different order of operations. These should be
-  /// brought in line or proven equivalent.
+  /// Implements:
+  /// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md#rules
   @override
-  bool isSubtypeOf(DartType _t1, DartType _t2) {
-    var t1 = _t1 as TypeImpl;
-    var t2 = _t2 as TypeImpl;
-
-    // Convert Null to Never? so that NullabilitySuffix can handle more cases.
-    if (t1.isDartCoreNull) {
-      t1 = BottomTypeImpl.instanceNullable;
-    }
-    if (t2.isDartCoreNull) {
-      t2 = BottomTypeImpl.instanceNullable;
-    }
-
-    if (identical(t1, t2)) {
+  bool isSubtypeOf(DartType _T0, DartType _T1) {
+    // Reflexivity: if `T0` and `T1` are the same type then `T0 <: T1`.
+    if (identical(_T0, _T1)) {
       return true;
     }
-    // The types are void, dynamic, bottom, interface types, function types,
-    // FutureOr<T> and type parameters.
-    //
-    // We proceed by eliminating these different classes from consideration.
 
     // `?` is treated as a top and a bottom type during inference.
-    if (identical(t1, UnknownInferredType.instance) ||
-        identical(t2, UnknownInferredType.instance)) {
+    if (identical(_T0, UnknownInferredType.instance) ||
+        identical(_T1, UnknownInferredType.instance)) {
       return true;
     }
 
-    // Trivial top case.
-    if (_isTop(t2)) {
+    var T0 = _T0 as TypeImpl;
+    var T1 = _T1 as TypeImpl;
+
+    // Right Top: if `T1` is a top type (i.e. `dynamic`, or `void`, or
+    // `Object?`) then `T0 <: T1`.
+    if (identical(T1, DynamicTypeImpl.instance) ||
+        identical(T1, VoidTypeImpl.instance) ||
+        T1.nullabilitySuffix == NullabilitySuffix.question &&
+            T1.isDartCoreObject) {
       return true;
     }
 
-    // Legacy top case. Must be done now to find Object* <: Object.
-    // TODO: handle false positives like FutureOr<Object?>* and T* extends int?.
-    if (t1.nullabilitySuffix == NullabilitySuffix.star &&
-        _isLegacyTop(t2, orTrueTop: false)) {
-      return true;
-    }
-
-    // Having excluded RHS top, this now must be false.
-    if (_isTop(t1)) {
-      return false;
-    }
-
-    // Handle T1? <: T2
-    if (t1.nullabilitySuffix == NullabilitySuffix.question) {
-      if (t2.nullabilitySuffix == NullabilitySuffix.none) {
-        // If T2 is not FutureOr<S2>, then subtype is false.
-        if (!t2.isDartAsyncFutureOr) {
-          return false;
-        }
-
-        // T1? <: FutureOr<S2> is true if S2 is nullable.
-        final s2 = (t2 as InterfaceType).typeArguments[0];
-        if (!isNullable(s2)) {
-          return false;
-        }
-      }
-    }
-
-    // Legacy bottom cases
-    if (_isLegacyBottom(t1, orTrueBottom: true)) {
-      return true;
-    }
-
-    if (_isLegacyBottom(t2, orTrueBottom: true)) {
-      return false;
-    }
-
-    // Handle FutureOr<T> union type.
-    if (t1 is InterfaceTypeImpl && t1.isDartAsyncFutureOr) {
-      var t1TypeArg = t1.typeArguments[0];
-      if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
-        var t2TypeArg = t2.typeArguments[0];
-        // FutureOr<A> <: FutureOr<B> iff A <: B
-        return isSubtypeOf(t1TypeArg, t2TypeArg);
-      }
-
-      // given t1 is Future<A> | A, then:
-      // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      var t1Future = typeProvider.futureType2(t1TypeArg);
-      return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
-    }
-
-    if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
-      // given t2 is Future<A> | A, then:
-      // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
-      var t2TypeArg = t2.typeArguments[0];
-      var t2Future = typeProvider.futureType2(t2TypeArg);
-      return isSubtypeOf(t1, t2Future) || isSubtypeOf(t1, t2TypeArg);
-    }
-
-    // S <: T where S is a type variable
-    //  T is not dynamic or object (handled above)
-    //  True if T == S
-    //  Or true if bound of S is S' and S' <: T
-    if (t1 is TypeParameterTypeImpl) {
-      if (t2 is TypeParameterTypeImpl &&
-          t1.definition == t2.definition &&
-          _typeParameterBoundsSubtype(t1.bound, t2.bound, true)) {
+    // Left Top: if `T0` is `dynamic` or `void`,
+    //   then `T0 <: T1` if `Object? <: T1`.
+    if (identical(T0, DynamicTypeImpl.instance) ||
+        identical(T0, VoidTypeImpl.instance)) {
+      if (isSubtypeOf(_objectQuestion, T1)) {
         return true;
       }
-
-      DartType bound = t1.element.bound;
-      return bound == null
-          ? false
-          : _typeParameterBoundsSubtype(bound, t2, false);
     }
 
-    if (t2 is TypeParameterType) {
+    // Left Bottom: if `T0` is `Never`, then `T0 <: T1`.
+    if (identical(T0, BottomTypeImpl.instance)) {
+      return true;
+    }
+
+    // Right Object: if `T1` is `Object` then:
+    var T1_nullability = T1.nullabilitySuffix;
+    if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreObject) {
+      var T0_nullability = T0.nullabilitySuffix;
+      // * if `T0` is an unpromoted type variable with bound `B`,
+      //   then `T0 <: T1` iff `B <: Object`.
+      // * if `T0` is a promoted type variable `X & S`,
+      //   then `T0 <: T1`iff `S <: Object`.
+      if (T0_nullability == NullabilitySuffix.none &&
+          T0 is TypeParameterTypeImpl) {
+        var bound = T0.element.bound ?? _objectQuestion;
+        return isSubtypeOf(bound, _objectNone);
+      }
+      // * if `T0` is `FutureOr<S>` for some `S`,
+      //   then `T0 <: T1` iff `S <: Object`
+      if (T0_nullability == NullabilitySuffix.none &&
+          T0 is InterfaceTypeImpl &&
+          T0.isDartAsyncFutureOr) {
+        return isSubtypeOf(T0.typeArguments[0], T1);
+      }
+      // * if `T0` is `S*` for any `S`, then `T0 <: T1` iff `S <: T1`
+      if (T0_nullability == NullabilitySuffix.star) {
+        return isSubtypeOf(
+          T0.withNullability(NullabilitySuffix.none),
+          T1,
+        );
+      }
+      // * if `T0` is `Null`, `dynamic`, `void`, or `S?` for any `S`,
+      //   then the subtyping does not hold, the result is false.
+      if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull ||
+          identical(T0, DynamicTypeImpl.instance) ||
+          identical(T0, VoidTypeImpl.instance) ||
+          T0_nullability == NullabilitySuffix.question) {
+        return false;
+      }
+      // Otherwise `T0 <: T1` is true.
+      return true;
+    }
+
+    // Left Null: if `T0` is `Null` then:
+    var T0_nullability = T0.nullabilitySuffix;
+    if (T0_nullability == NullabilitySuffix.none && T0.isDartCoreNull) {
+      // * If `T1` is `FutureOr<S>` for some `S`, then the query is true iff
+      // `Null <: S`.
+      if (T1_nullability == NullabilitySuffix.none &&
+          T1 is InterfaceTypeImpl &&
+          T1.isDartAsyncFutureOr) {
+        var S = T1.typeArguments[0];
+        return isSubtypeOf(_nullNone, S);
+      }
+      // If `T1` is `Null`, `S?` or `S*` for some `S`, then the query is true.
+      if (T1_nullability == NullabilitySuffix.none && T1.isDartCoreNull ||
+          T1_nullability == NullabilitySuffix.question ||
+          T1_nullability == NullabilitySuffix.star) {
+        return true;
+      }
+      // * if `T1` is a type variable (promoted or not) the query is false
+      if (T1 is TypeParameterTypeImpl) {
+        return false;
+      }
+      // Otherwise, the query is false.
       return false;
     }
 
-    // We've eliminated void, dynamic, bottom, type parameters, FutureOr,
-    // nullable, and legacy nullable types. The only cases are the combinations
-    // of interface type and function type.
-
-    // A function type can only subtype an interface type if
-    // the interface type is Function
-    if (t1 is FunctionType && t2 is InterfaceType) {
-      return t2.isDartCoreFunction;
+    // Left Legacy if `T0` is `S0*` then:
+    if (T0_nullability == NullabilitySuffix.star) {
+      // * `T0 <: T1` iff `S0 <: T1`.
+      var S0 = T0.withNullability(NullabilitySuffix.none);
+      return isSubtypeOf(S0, T1);
     }
 
-    if (t1 is InterfaceType && t2 is FunctionType) return false;
-
-    // Two interface types
-    if (t1 is InterfaceTypeImpl && t2 is InterfaceTypeImpl) {
-      return _isInterfaceSubtypeOf(t1, t2, null);
+    // Right Legacy `T1` is `S1*` then:
+    //   * `T0 <: T1` iff `T0 <: S1?`.
+    if (T1_nullability == NullabilitySuffix.star) {
+      var S1 = T1.withNullability(NullabilitySuffix.question);
+      return isSubtypeOf(T0, S1);
     }
 
-    return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
+    // Left FutureOr: if `T0` is `FutureOr<S0>` then:
+    if (T0_nullability == NullabilitySuffix.none &&
+        T0 is InterfaceTypeImpl &&
+        T0.isDartAsyncFutureOr) {
+      var S0 = T0.typeArguments[0];
+      // * `T0 <: T1` iff `Future<S0> <: T1` and `S0 <: T1`
+      if (isSubtypeOf(S0, T1)) {
+        var FutureS0 = typeProvider.futureElement.instantiate(
+          typeArguments: [S0],
+          nullabilitySuffix: NullabilitySuffix.none,
+        );
+        return isSubtypeOf(FutureS0, T1);
+      }
+      return false;
+    }
+
+    // Left Nullable: if `T0` is `S0?` then:
+    //   * `T0 <: T1` iff `S0 <: T1` and `Null <: T1`.
+    if (T0_nullability == NullabilitySuffix.question) {
+      var S0 = T0.withNullability(NullabilitySuffix.none);
+      return isSubtypeOf(S0, T1) && isSubtypeOf(_nullNone, T1);
+    }
+
+    // Right Promoted Variable: if `T1` is a promoted type variable `X1 & S1`:
+    //   * `T0 <: T1` iff `T0 <: X1` and `T0 <: S1`
+    if (T0 is TypeParameterTypeImpl) {
+      if (T1 is TypeParameterTypeImpl && T0.definition == T1.definition) {
+        var S0 = T0.element.bound ?? _objectQuestion;
+        var S1 = T1.element.bound ?? _objectQuestion;
+        if (isSubtypeOf(S0, S1)) {
+          return true;
+        }
+      }
+
+      var T0_element = T0.element;
+      if (T0_element is TypeParameterMember) {
+        return isSubtypeOf(T0_element.bound, T1);
+      }
+    }
+
+    // Right FutureOr: if `T1` is `FutureOr<S1>` then:
+    if (T1_nullability == NullabilitySuffix.none &&
+        T1 is InterfaceTypeImpl &&
+        T1.isDartAsyncFutureOr) {
+      var S1 = T1.typeArguments[0];
+      // `T0 <: T1` iff any of the following hold:
+      // * either `T0 <: Future<S1>`
+      var FutureS1 = typeProvider.futureElement.instantiate(
+        typeArguments: [S1],
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
+      if (isSubtypeOf(T0, FutureS1)) {
+        return true;
+      }
+      // * or `T0 <: S1`
+      if (isSubtypeOf(T0, S1)) {
+        return true;
+      }
+      // * or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
+      // * or `T0` is `X0 & S0` and `S0 <: T1`
+      if (T0 is TypeParameterTypeImpl) {
+        var S0 = T0.element.bound ?? _objectQuestion;
+        if (isSubtypeOf(S0, T1)) {
+          return true;
+        }
+      }
+      // iff
+      return false;
+    }
+
+    // Right Nullable: if `T1` is `S1?` then:
+    if (T1_nullability == NullabilitySuffix.question) {
+      var S1 = T1.withNullability(NullabilitySuffix.none);
+      // `T0 <: T1` iff any of the following hold:
+      // * either `T0 <: S1`
+      if (isSubtypeOf(T0, S1)) {
+        return true;
+      }
+      // * or `T0 <: Null`
+      if (isSubtypeOf(T0, _nullNone)) {
+        return true;
+      }
+      // or `T0` is `X0` and `X0` has bound `S0` and `S0 <: T1`
+      // or `T0` is `X0 & S0` and `S0 <: T1`
+      if (T0 is TypeParameterTypeImpl) {
+        var S0 = T0.element.bound ?? _objectQuestion;
+        return isSubtypeOf(S0, T1);
+      }
+      // iff
+      return false;
+    }
+
+    // Super-Interface: `T0` is an interface type with super-interfaces
+    // `S0,...Sn`:
+    //   * and `Si <: T1` for some `i`.
+    if (T0 is InterfaceTypeImpl && T1 is InterfaceTypeImpl) {
+      return _isInterfaceSubtypeOf(T0, T1, null);
+    }
+
+    // Left Promoted Variable: `T0` is a promoted type variable `X0 & S0`
+    //   * and `S0 <: T1`
+    // Left Type Variable Bound: `T0` is a type variable `X0` with bound `B0`
+    //   * and `B0 <: T1`
+    if (T0 is TypeParameterTypeImpl) {
+      var S0 = T0.element.bound ?? _objectQuestion;
+      if (isSubtypeOf(S0, T1)) {
+        return true;
+      }
+    }
+
+    if (T0 is FunctionTypeImpl) {
+      // Function Type/Function: `T0` is a function type and `T1` is `Function`.
+      if (T1.isDartCoreFunction) {
+        return true;
+      }
+      if (T1 is FunctionTypeImpl) {
+        return _isFunctionSubtypeOf(T0, T1);
+      }
+    }
+
+    return false;
   }
 
   /// Given a [type] T that may have an unknown type `?`, returns a type
@@ -1072,10 +1190,8 @@
       var newTypeArgs = _transformList(
           type.typeArguments, (t) => _substituteType(t, lowerBound, visitType));
       if (identical(type.typeArguments, newTypeArgs)) return type;
-      return new InterfaceTypeImpl(type.element,
-          prunedTypedefs: type.prunedTypedefs,
-          nullabilitySuffix: type.nullabilitySuffix)
-        ..typeArguments = newTypeArgs;
+      return new InterfaceTypeImpl.explicit(type.element, newTypeArgs,
+          nullabilitySuffix: type.nullabilitySuffix);
     }
     if (type is FunctionType) {
       var parameters = type.parameters;
@@ -1106,20 +1222,6 @@
     return type;
   }
 
-  bool _typeParameterBoundsSubtype(
-      DartType t1, DartType t2, bool recursionValue) {
-    TypeComparison comparison = TypeComparison(t1, t2);
-    if (_typeParameterBoundsComparisons.contains(comparison)) {
-      return recursionValue;
-    }
-    _typeParameterBoundsComparisons.add(comparison);
-    try {
-      return isSubtypeOf(t1, t2);
-    } finally {
-      _typeParameterBoundsComparisons.remove(comparison);
-    }
-  }
-
   /**
    * This currently just implements a simple least upper bound to
    * handle some common cases.  It also avoids some termination issues
@@ -1163,19 +1265,23 @@
       return type1;
     }
     if (type1 is TypeParameterType) {
-      type1 = type1
-          .resolveToBound(typeProvider.objectType)
-          .substitute2([typeProvider.objectType], [type1]);
+      type1 = _typeParameterResolveToObjectBounds(type1);
       return getLeastUpperBound(type1, type2);
     }
     // We should only be called when at least one of the types is a
     // TypeParameterType
-    type2 = type2
-        .resolveToBound(typeProvider.objectType)
-        .substitute2([typeProvider.objectType], [type2]);
+    type2 = _typeParameterResolveToObjectBounds(type2);
+
     return getLeastUpperBound(type1, type2);
   }
 
+  DartType _typeParameterResolveToObjectBounds(DartType type) {
+    var element = type.element;
+    type = type.resolveToBound(typeProvider.objectType);
+    return Substitution.fromMap({element: typeProvider.objectType})
+        .substituteType(type);
+  }
+
   static List<T> _transformList<T>(List<T> list, T f(T t)) {
     List<T> newList;
     for (var i = 0; i < list.length; i++) {
@@ -1253,6 +1359,7 @@
       fnType.returnType,
       const [],
       fnType.parameters,
+      nullabilitySuffix: (fnType as TypeImpl).nullabilitySuffix,
     );
     tryMatchSubtypeOf(inferFnType, contextType, origin, covariant: true);
   }
@@ -2409,8 +2516,14 @@
    * no instantiation is done.
    */
   DartType instantiateType(DartType type, List<DartType> typeArguments) {
-    if (type is ParameterizedType) {
+    if (type is FunctionType) {
       return type.instantiate(typeArguments);
+    } else if (type is InterfaceTypeImpl) {
+      // TODO(scheglov) Use `ClassElement.instantiate()`, don't use raw types.
+      return type.element.instantiate(
+        typeArguments: typeArguments,
+        nullabilitySuffix: type.nullabilitySuffix,
+      );
     } else {
       return type;
     }
@@ -2561,17 +2674,25 @@
     if (type.isDartCoreNull) return BottomTypeImpl.instance;
 
     if (type is TypeParameterTypeImpl) {
-      var promotedElement = TypeParameterElementImpl.synthetic(
-        type.element.name,
-      );
-
-      var bound = type.element.bound ?? typeProvider.objectType;
-      promotedElement.bound = promoteToNonNull(bound);
-
-      return TypeParameterTypeImpl(
-        promotedElement,
-        nullabilitySuffix: NullabilitySuffix.none,
-      );
+      var element = type.element;
+      var promotedBound =
+          promoteToNonNull(element.bound ?? typeProvider.objectType);
+      var identicalBound = identical(promotedBound, element.bound);
+      if (identicalBound) {
+        if (type.nullabilitySuffix == NullabilitySuffix.none) {
+          return type;
+        } else {
+          return TypeParameterTypeImpl(
+            element,
+            nullabilitySuffix: NullabilitySuffix.none,
+          );
+        }
+      } else {
+        return TypeParameterTypeImpl(
+          TypeParameterMember(element, null, promotedBound),
+          nullabilitySuffix: NullabilitySuffix.none,
+        );
+      }
     }
 
     return type.withNullability(NullabilitySuffix.none);
@@ -2684,7 +2805,7 @@
     if (type is FunctionType) {
       return type.typeFormals;
     } else if (type is InterfaceType) {
-      return type.typeParameters;
+      return type.element.typeParameters;
     } else {
       return const <TypeParameterElement>[];
     }
@@ -2781,7 +2902,12 @@
     // Calculate the LUB of the return type.
     DartType returnType = getLeastUpperBound(f.returnType, g.returnType);
 
-    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters);
+    return FunctionTypeImpl.synthetic(
+      returnType,
+      typeFormals,
+      parameters,
+      nullabilitySuffix: (f as TypeImpl).nullabilitySuffix,
+    );
   }
 
   /**
@@ -2875,26 +3001,6 @@
   }
 
   @override
-  bool isMoreSpecificThan(DartType type,
-      [bool withDynamic = false, Set<Element> visitedElements]) {
-    // T is S
-    if (identical(this, type)) {
-      return true;
-    }
-    // else
-    return withDynamic;
-  }
-
-  @override
-  bool isSubtypeOf(DartType type) => true;
-
-  @override
-  bool isSupertypeOf(DartType type) => true;
-
-  @override
-  TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
-
-  @override
   DartType replaceTopAndBottom(TypeProvider typeProvider,
       {bool isCovariant = true}) {
     // In theory this should never happen, since we only need to do this
@@ -2913,8 +3019,7 @@
 
   @override
   DartType substitute2(
-      List<DartType> argumentTypes, List<DartType> parameterTypes,
-      [List<FunctionTypeAliasElement> prune]) {
+      List<DartType> argumentTypes, List<DartType> parameterTypes) {
     int length = parameterTypes.length;
     for (int i = 0; i < length; i++) {
       if (parameterTypes[i] == this) {
diff --git a/pkg/analyzer/lib/src/generated/utilities_dart.dart b/pkg/analyzer/lib/src/generated/utilities_dart.dart
index 160c47a..105d46a 100644
--- a/pkg/analyzer/lib/src/generated/utilities_dart.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_dart.dart
@@ -6,7 +6,7 @@
 import 'package:analyzer/dart/ast/token.dart' show Token;
 import 'package:analyzer/src/dart/element/element.dart' show ElementImpl;
 
-export 'package:front_end/src/base/resolve_relative_uri.dart'
+export 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
     show resolveRelativeUri;
 
 /**
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 0ec27b9..6268493 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/file_system/file_system.dart'
     show File, Folder, ResourceProvider, ResourceUriResolver;
 import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -134,8 +135,8 @@
     ContextBuilder builder = new ContextBuilder(resourceProvider, null, null);
 
     DartSdk sdk = options.mockSdk ??
-        new FolderBasedDartSdk(resourceProvider,
-            resourceProvider.getFolder(sdkDir), options.strongMode);
+        new FolderBasedDartSdk(
+            resourceProvider, resourceProvider.getFolder(sdkDir));
 
     List<UriResolver> resolvers = [new DartUriResolver(sdk)];
 
@@ -171,7 +172,7 @@
   Future<List<AnalysisErrorInfo>> analyze(Iterable<io.File> files) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
-    AnalysisEngine.instance.logger = new StdLogger();
+    AnalysisEngine.instance.instrumentationService = new StdInstrumentation();
 
     SourceFactory sourceFactory =
         new SourceFactory(resolvers, _getPackageConfig());
@@ -252,7 +253,9 @@
 
 /// Prints logging information comments to the [outSink] and error messages to
 /// [errorSink].
-class StdLogger extends Logger {
+class StdInstrumentation extends InstrumentationService {
+  StdInstrumentation() : super(null);
+
   @override
   void logError(String message, [exception]) {
     errorSink.writeln(message);
@@ -262,7 +265,13 @@
   }
 
   @override
-  void logInformation(String message, [exception]) {
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    errorSink.writeln(exception);
+    errorSink.writeln(stackTrace);
+  }
+
+  @override
+  void logInfo(String message, [exception]) {
     outSink.writeln(message);
     if (exception != null) {
       outSink.writeln(exception);
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 2d1444a..0c48fea 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -20,8 +20,7 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions, Logger;
-import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
+    show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo;
 import 'package:analyzer/src/generated/source_io.dart';
@@ -33,6 +32,7 @@
 import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart' show Linter;
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:glob/glob.dart';
 import 'package:path/path.dart' as p;
 
@@ -215,6 +215,8 @@
 
   InheritanceManager3 get inheritanceManager;
 
+  WorkspacePackage get package;
+
   TypeProvider get typeProvider;
 
   TypeSystem get typeSystem;
@@ -255,6 +257,9 @@
   final DeclaredVariables declaredVariables;
 
   @override
+  final WorkspacePackage package;
+
+  @override
   final TypeProvider typeProvider;
 
   @override
@@ -271,6 +276,7 @@
     this.typeSystem,
     this.inheritanceManager,
     this.analysisOptions,
+    this.package,
   );
 
   @override
@@ -522,7 +528,7 @@
 @deprecated
 abstract class NodeLintRuleWithContext extends NodeLintRule {}
 
-class PrintingReporter implements Reporter, Logger {
+class PrintingReporter implements Reporter {
   final Printer _print;
 
   const PrintingReporter([this._print = print]);
@@ -533,16 +539,6 @@
   }
 
   @override
-  void logError(String message, [CaughtException exception]) {
-    _print('ERROR: $message');
-  }
-
-  @override
-  void logInformation(String message, [CaughtException exception]) {
-    _print('INFO: $message');
-  }
-
-  @override
   void warn(String message) {
     _print('WARN: $message');
   }
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 8217608..180e833 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -195,7 +195,7 @@
     }
 
     if (_pathPrefixToDependencyPathList.isEmpty) {
-      _addLibrariesWithPaths(dependencyLibraries, _knownPathList);
+      _addKnownLibraries(dependencyLibraries);
     }
 
     _Package package;
@@ -279,6 +279,26 @@
     }
   }
 
+  /// Add known libraries, other then in the context itself, or the SDK.
+  void _addKnownLibraries(List<Library> libraries) {
+    var contextPathSet = _contextPathList.toSet();
+    var sdkPathSet = _sdkLibraryPathList.toSet();
+
+    for (var path in _knownPathList) {
+      if (contextPathSet.contains(path) || sdkPathSet.contains(path)) {
+        continue;
+      }
+
+      var file = _tracker._pathToFile[path];
+      if (file != null && file.isLibrary) {
+        var library = _tracker._idToLibrary[file.id];
+        if (library != null) {
+          libraries.add(library);
+        }
+      }
+    }
+  }
+
   void _addLibrariesWithPaths(List<Library> libraries, List<String> pathList,
       {String excludingLibraryOfPath}) {
     var excludedFile = _tracker._pathToFile[excludingLibraryOfPath];
@@ -500,7 +520,7 @@
     var now = DateTime.now();
     if (now.difference(_whenKnownFilesPulled).inSeconds > 1) {
       _whenKnownFilesPulled = now;
-      _pullKnownFiles();
+      pullKnownFiles();
     }
     return _changedPaths.isNotEmpty || _scheduledFiles.isNotEmpty;
   }
@@ -610,6 +630,17 @@
     return _idToLibrary[id];
   }
 
+  /// Pull known files into [DeclarationsContext]s.
+  ///
+  /// This is a temporary support for Bazel repositories, because IDEA
+  /// does not yet give us dependencies for them.
+  @visibleForTesting
+  void pullKnownFiles() {
+    for (var context in _contexts.values) {
+      context._scheduleKnownFiles();
+    }
+  }
+
   void _addFile(DeclarationsContext context, String path) {
     if (path.endsWith('.dart')) {
       _scheduledFiles.add(_ScheduledFile(context, path));
@@ -752,16 +783,6 @@
       LibraryChange._(changedLibraries, removedLibraries),
     );
   }
-
-  /// Pull known files into [DeclarationsContext]s.
-  ///
-  /// This is a temporary support for Bazel repositories, because IDEA
-  /// does not yet give us dependencies for them.
-  void _pullKnownFiles() {
-    for (var context in _contexts.values) {
-      context._scheduleKnownFiles();
-    }
-  }
 }
 
 class Libraries {
@@ -1011,6 +1032,8 @@
       children: d.children.map(toIdl).toList(),
       defaultArgumentListString: d.defaultArgumentListString,
       defaultArgumentListTextRanges: d.defaultArgumentListTextRanges,
+      codeOffset: d.codeOffset,
+      codeLength: d.codeLength,
       docComplete: d.docComplete,
       docSummary: d.docSummary,
       fieldMask: fieldMask,
@@ -1074,7 +1097,7 @@
 
 class _File {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 13;
+  static const int DATA_VERSION = 14;
 
   /// The next value for [id].
   static int _nextId = 0;
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index b42a5a4..ed90c40 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -40,7 +40,7 @@
     //
     ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
     FolderBasedDartSdk sdk = new FolderBasedDartSdk(
-        resourceProvider, resourceProvider.getFolder(sdkPath), true);
+        resourceProvider, resourceProvider.getFolder(sdkPath));
     sdk.useSummary = false;
     sdk.analysisOptions = new AnalysisOptionsImpl();
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
index 6ac2782..42ffe5c 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_flags.dart
@@ -47,6 +47,7 @@
 
   static final _hasQuestion = _checkBit(
     1,
+    FieldFormalParameter,
     GenericFunctionType,
     TypeName,
   );
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 6509d9c..232ab13 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -672,6 +672,8 @@
       comment: _readDocumentationComment(data),
       type: _readNodeLazy(data.fieldFormalParameter_type),
       parameters: _readNodeLazy(data.fieldFormalParameter_formalParameters),
+      question:
+          AstBinaryFlags.hasQuestion(data.flags) ? _Tokens.QUESTION : null,
       requiredKeyword:
           AstBinaryFlags.isRequired(data.flags) ? _Tokens.REQUIRED : null,
     );
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 58fcfec..6bca136 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -557,6 +557,7 @@
       fieldFormalParameter_typeParameters: node.typeParameters?.accept(this),
     );
     _storeNormalFormalParameter(builder, node, node.keyword);
+    builder.flags |= AstBinaryFlags.encode(hasQuestion: node.question != null);
     return builder;
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index 3914139..fc4908c 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/resolver/resolution_visitor.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/summary2/link.dart';
@@ -44,7 +43,6 @@
       _linker.typeProvider,
       errorListener,
       nameScope: _nameScope,
-      localVariableInfo: LocalVariableInfo(),
     );
     node.accept(variableResolverVisitor);
 
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index 2a00807..d170f4a 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -89,7 +89,7 @@
   }
 
   @override
-  String toString() {
+  String toString({bool withNullability = false}) {
     var buffer = StringBuffer();
 
     if (typeFormals.isNotEmpty) {
@@ -108,6 +108,21 @@
     return buffer.toString();
   }
 
+  @override
+  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
+    if (this.nullabilitySuffix == nullabilitySuffix) {
+      return this;
+    }
+
+    return FunctionTypeBuilder(
+      typeFormals,
+      parameters,
+      returnType,
+      nullabilitySuffix,
+      node: node,
+    );
+  }
+
   /// If the [type] is a [TypeBuilder], build it; otherwise return as is.
   static DartType _buildType(DartType type) {
     if (type is TypeBuilder) {
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index ef725a0..47b48b1 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -936,8 +936,6 @@
         _typeParameters.remove(--_nextSyntheticTypeParameterId);
       }
 
-      var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
-
       GenericTypeAliasElement typedefElement;
       List<DartType> typedefTypeArguments = const <DartType>[];
       if (linkedType.functionTypedef != 0) {
@@ -947,10 +945,16 @@
             linkedType.functionTypedefTypeArguments.map(readType).toList();
       }
 
+      var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
+
       return FunctionTypeImpl.synthetic(
-              returnType, typeParameters, formalParameters,
-              element: typedefElement, typeArguments: typedefTypeArguments)
-          .withNullability(nullabilitySuffix);
+        returnType,
+        typeParameters,
+        formalParameters,
+        element: typedefElement,
+        typeArguments: typedefTypeArguments,
+        nullabilitySuffix: nullabilitySuffix,
+      );
     } else if (kind == LinkedNodeTypeKind.interface) {
       var element = bundleContext.elementOfIndex(linkedType.interfaceClass);
       var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
@@ -970,7 +974,10 @@
         element = bundleContext.elementOfIndex(index);
       }
       var nullabilitySuffix = _nullabilitySuffix(linkedType.nullabilitySuffix);
-      return TypeParameterTypeImpl(element).withNullability(nullabilitySuffix);
+      return TypeParameterTypeImpl(
+        element,
+        nullabilitySuffix: nullabilitySuffix,
+      );
     } else if (kind == LinkedNodeTypeKind.void_) {
       return VoidTypeImpl.instance;
     } else {
diff --git a/pkg/analyzer/lib/src/summary2/named_type_builder.dart b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
index e33f2ad..b44a12a 100644
--- a/pkg/analyzer/lib/src/summary2/named_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/named_type_builder.dart
@@ -11,11 +11,15 @@
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/type_builder.dart';
+import 'package:meta/meta.dart';
 
 /// The type builder for a [TypeName].
 class NamedTypeBuilder extends TypeBuilder {
   static DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
 
+  /// Indicates whether the library is opted into NNBD.
+  final bool isNNBD;
+
   final Element element;
   final List<DartType> arguments;
   final NullabilitySuffix nullabilitySuffix;
@@ -31,10 +35,12 @@
   /// and set for the [node].
   DartType _type;
 
-  NamedTypeBuilder(this.element, this.arguments, this.nullabilitySuffix,
+  NamedTypeBuilder(
+      this.isNNBD, this.element, this.arguments, this.nullabilitySuffix,
       {this.node});
 
   factory NamedTypeBuilder.of(
+    bool isNNBD,
     TypeName node,
     Element element,
     NullabilitySuffix nullabilitySuffix,
@@ -47,7 +53,8 @@
       arguments = <DartType>[];
     }
 
-    return NamedTypeBuilder(element, arguments, nullabilitySuffix, node: node);
+    return NamedTypeBuilder(isNNBD, element, arguments, nullabilitySuffix,
+        node: node);
   }
 
   @override
@@ -98,7 +105,7 @@
   }
 
   @override
-  String toString() {
+  String toString({bool withNullability = false}) {
     var buffer = StringBuffer();
     buffer.write(element.displayName);
     if (arguments.isNotEmpty) {
@@ -109,6 +116,16 @@
     return buffer.toString();
   }
 
+  @override
+  TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
+    if (this.nullabilitySuffix == nullabilitySuffix) {
+      return this;
+    }
+
+    return NamedTypeBuilder(isNNBD, element, arguments, nullabilitySuffix,
+        node: node);
+  }
+
   /// Build arguments that correspond to the type [parameters].
   List<DartType> _buildArguments(List<TypeParameterElement> parameters) {
     if (parameters.isEmpty) {
@@ -141,9 +158,10 @@
       return _buildFormalParameterType(node.parameter);
     } else if (node is FunctionTypedFormalParameter) {
       return _buildFunctionType(
-        node.typeParameters,
-        node.returnType,
-        node.parameters,
+        typeParameterList: node.typeParameters,
+        returnTypeNode: node.returnType,
+        parameterList: node.parameters,
+        hasQuestion: node.question != null,
       );
     } else if (node is SimpleFormalParameter) {
       return _buildNodeType(node.type);
@@ -152,11 +170,12 @@
     }
   }
 
-  FunctionType _buildFunctionType(
-    TypeParameterList typeParameterList,
-    TypeAnnotation returnTypeNode,
-    FormalParameterList parameterList,
-  ) {
+  FunctionType _buildFunctionType({
+    @required TypeParameterList typeParameterList,
+    @required TypeAnnotation returnTypeNode,
+    @required FormalParameterList parameterList,
+    @required bool hasQuestion,
+  }) {
     var returnType = _buildNodeType(returnTypeNode);
     var typeParameters = _typeParameters(typeParameterList);
 
@@ -173,9 +192,23 @@
       returnType,
       typeParameters,
       formalParameters,
+      nullabilitySuffix: _getNullabilitySuffix(hasQuestion),
     );
   }
 
+  DartType _buildGenericFunctionType(GenericFunctionType node) {
+    if (node != null) {
+      return _buildType(node?.type);
+    } else {
+      return FunctionTypeImpl.synthetic(
+        _dynamicType,
+        const <TypeParameterElement>[],
+        const <ParameterElement>[],
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
+    }
+  }
+
   DartType _buildNodeType(TypeAnnotation node) {
     if (node == null) {
       return _dynamicType;
@@ -184,17 +217,22 @@
     }
   }
 
+  NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
+    if (hasQuestion) {
+      return NullabilitySuffix.question;
+    } else if (isNNBD) {
+      return NullabilitySuffix.none;
+    } else {
+      return NullabilitySuffix.star;
+    }
+  }
+
   DartType _getRawFunctionType(GenericTypeAliasElementImpl element) {
     // If the element is not being linked, there is no reason (or a way,
     // because the linked node might be read only partially) to go through
     // its node - all its types have already been built.
     if (!element.linkedContext.isLinking) {
-      var function = element.function;
-      if (function != null) {
-        return function.type;
-      } else {
-        return _dynamicType;
-      }
+      return element.function.type;
     }
 
     var typedefNode = element.linkedNode;
@@ -209,15 +247,16 @@
 
     if (typedefNode is FunctionTypeAlias) {
       var result = _buildFunctionType(
-        null,
-        typedefNode.returnType,
-        typedefNode.parameters,
+        typeParameterList: null,
+        returnTypeNode: typedefNode.returnType,
+        parameterList: typedefNode.parameters,
+        hasQuestion: false,
       );
       LazyAst.setRawFunctionType(typedefNode, result);
       return result;
     } else if (typedefNode is GenericTypeAlias) {
       var functionNode = typedefNode.functionType;
-      var functionType = _buildType(functionNode?.type);
+      var functionType = _buildGenericFunctionType(functionNode);
       LazyAst.setRawFunctionType(typedefNode, functionType);
       return functionType;
     } else {
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index e55e10c..169a9f4 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -514,6 +514,7 @@
       );
     } else {
       var builder = NamedTypeBuilder.of(
+        isNNBD,
         node,
         element,
         nullabilitySuffix,
diff --git a/pkg/analyzer/lib/src/summary2/type_alias.dart b/pkg/analyzer/lib/src/summary2/type_alias.dart
index 37fae3b..617c152 100644
--- a/pkg/analyzer/lib/src/summary2/type_alias.dart
+++ b/pkg/analyzer/lib/src/summary2/type_alias.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -10,10 +12,16 @@
 import 'package:analyzer/src/summary2/link.dart';
 
 class TypeAliasSelfReferenceFinder {
+  NullabilitySuffix _unitNullability;
+
   /// Check typedefs and mark the ones having self references.
   void perform(Linker linker) {
     for (var builder in linker.builders.values) {
       for (var unitContext in builder.context.units) {
+        _unitNullability =
+            unitContext.unit.featureSet.isEnabled(Feature.non_nullable)
+                ? NullabilitySuffix.none
+                : NullabilitySuffix.star;
         for (var node in unitContext.unit.declarations) {
           if (node is FunctionTypeAlias) {
             var finder = _Finder(node);
@@ -48,7 +56,12 @@
     node.functionType.returnType = null;
     node.functionType.parameters.parameters.clear();
     (node.functionType as GenericFunctionTypeImpl).type =
-        FunctionTypeImpl.synthetic(DynamicTypeImpl.instance, [], []);
+        FunctionTypeImpl.synthetic(
+      DynamicTypeImpl.instance,
+      [],
+      [],
+      nullabilitySuffix: _unitNullability,
+    );
   }
 }
 
diff --git a/pkg/analyzer/lib/src/summary2/type_builder.dart b/pkg/analyzer/lib/src/summary2/type_builder.dart
index ffa1d14..4fe6f7d 100644
--- a/pkg/analyzer/lib/src/summary2/type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/type_builder.dart
@@ -3,9 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 
 /// The builder for a [DartType] represented by a node.
-abstract class TypeBuilder implements DartType {
+abstract class TypeBuilder implements TypeImpl {
   /// Build the type, and set it for the corresponding node.
   /// Does nothing if the type has been already built.
   ///
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index aa37167..dfda000 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -151,7 +151,7 @@
         node.typeParameters,
         node.type,
         parameterList,
-        _nullability(node, true), // TODO(scheglov) use 'question' token
+        _nullability(node, node.question != null),
       );
       LazyAst.setType(node, type);
     } else {
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 15c9568..6b90f74 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -23,6 +23,7 @@
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/error/codes.dart' show StrongModeCode;
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
@@ -901,24 +902,24 @@
       // The member may be from a superclass, so we need to ensure the type
       // parameters are properly substituted.
       var classElement = targetType.element;
-      var classLowerBound = classElement.instantiate(
-        typeArguments: List.filled(
-          classElement.typeParameters.length,
-          BottomTypeImpl.instance,
-        ),
-        nullabilitySuffix: NullabilitySuffix.none,
-      );
-      var memberLowerBound = inheritance.getMember(
-        classLowerBound,
-        Name(element.librarySource.uri, element.name),
-      );
-      if (memberLowerBound == null &&
-          element.enclosingElement is ExtensionElement) {
-        return;
-      }
-      var expectedType = invokeType.returnType;
 
-      if (!rules.isSubtypeOf(memberLowerBound.returnType, expectedType)) {
+      var rawElement =
+          (element is ExecutableMember) ? element.baseElement : element;
+      var rawReturnType = rawElement.returnType;
+
+      // Check if the return type uses a class type parameter contravariantly.
+      bool needsCheck = false;
+      for (var typeParameter in classElement.typeParameters) {
+        var variance = computeVariance(typeParameter, rawReturnType);
+        if (variance == Variance.contravariant ||
+            variance == Variance.invariant) {
+          needsCheck = true;
+          break;
+        }
+      }
+
+      if (needsCheck) {
+        var expectedType = invokeType.returnType;
         var isMethod = element is MethodElement;
         var isCall = node is MethodInvocation;
 
@@ -962,8 +963,7 @@
   }
 
   void _checkUnary(Expression operand, Token op, MethodElement element) {
-    bool isIncrementAssign =
-        op.type == TokenType.PLUS_PLUS || op.type == TokenType.MINUS_MINUS;
+    bool isIncrementAssign = op.type.isIncrementOperator;
     if (op.isUserDefinableOperator || isIncrementAssign) {
       if (element == null) {
         _recordDynamicInvoke(operand.parent, operand);
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index b2439c3..cd8c597 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -4,8 +4,6 @@
 
 import 'dart:collection';
 
-import 'package:analyzer/dart/ast/ast.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/src/dart/element/element.dart';
@@ -17,19 +15,6 @@
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 
 /**
- * Sets the type of the field. The types in implicit accessors are updated
- * implicitly, and the types of explicit accessors should be updated separately.
- */
-void setFieldType(VariableElement field, DartType newType) {
-  (field as VariableElementImpl).type = newType;
-}
-
-/**
- * A function that returns `true` if the given [element] passes the filter.
- */
-typedef bool VariableFilter(VariableElement element);
-
-/**
  * An object used to infer the type of instance fields and the return types of
  * instance methods within a single compilation unit.
  */
@@ -258,7 +243,7 @@
         parameter.inheritsCovariant = typeResult.isCovariant;
       }
     }
-    setFieldType(element.variable, typeResult.type);
+    (element.variable as FieldElementImpl).type = typeResult.type;
   }
 
   /**
@@ -396,7 +381,7 @@
    * If the given [field] represents a non-synthetic instance field for
    * which no type was provided, infer the type of the field.
    */
-  void _inferField(FieldElement field) {
+  void _inferField(FieldElementImpl field) {
     if (field.isSynthetic || field.isStatic) {
       return;
     }
@@ -404,7 +389,7 @@
     _FieldOverrideInferenceResult typeResult =
         _computeFieldOverrideType(field.getter);
     if (typeResult.isError) {
-      if (field is FieldElementImpl && field.linkedNode != null) {
+      if (field.linkedNode != null) {
         LazyAst.setTypeInferenceError(
           field.linkedNode,
           TopLevelInferenceErrorBuilder(
@@ -429,7 +414,7 @@
         newType = typeProvider.dynamicType;
       }
 
-      setFieldType(field, newType);
+      field.type = newType;
     }
 
     if (field.setter != null) {
@@ -538,47 +523,6 @@
 }
 
 /**
- * A visitor that will gather all of the variables referenced within a given
- * AST structure. The collection can be restricted to contain only those
- * variables that pass a specified filter.
- */
-class VariableGatherer extends RecursiveAstVisitor {
-  /**
-   * The filter used to limit which variables are gathered, or `null` if no
-   * filtering is to be performed.
-   */
-  final VariableFilter filter;
-
-  /**
-   * The variables that were found.
-   */
-  final Set<VariableElement> results = new HashSet<VariableElement>();
-
-  /**
-   * Initialize a newly created gatherer to gather all of the variables that
-   * pass the given [filter] (or all variables if no filter is provided).
-   */
-  VariableGatherer([this.filter]);
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (!node.inDeclarationContext()) {
-      Element nonAccessor(Element element) {
-        if (element is PropertyAccessorElement && element.isSynthetic) {
-          return element.variable;
-        }
-        return element;
-      }
-
-      Element element = nonAccessor(node.staticElement);
-      if (element is VariableElement && (filter == null || filter(element))) {
-        results.add(element);
-      }
-    }
-  }
-}
-
-/**
  * A class of exception that is not used anywhere else.
  */
 class _CycleException implements Exception {}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 4e5f626..de58249 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -358,7 +358,7 @@
     }
 
     for (var function in unitElement.functionTypeAliases) {
-      findIn(function.parameters);
+      findIn(function.function.parameters);
     }
 
     for (var extension_ in unitElement.extensions) {
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index ff822c1..5d6413f 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -4,9 +4,7 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/cache.dart';
 import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
@@ -336,7 +334,13 @@
 
 class List<E> implements Iterable<E> {
   List([int length]);
-  factory List.from(Iterable elements, {bool growable: true}) => null;
+  external factory List.from(Iterable elements, {bool growable: true});
+  external factory List.filled(int length, E fill, {bool growable = false});
+  external factory List.from(Iterable elements, {bool growable = true});
+  external factory List.of(Iterable<E> elements, {bool growable = true});
+  external factory List.generate(int length, E generator(int index),
+      {bool growable = true});
+  external factory List.unmodifiable(Iterable elements);
 
   E get last => null;
   E operator [](int index) => null;
@@ -720,172 +724,6 @@
   ],
 );
 
-final MockSdkLibrary _LIB_HTML_DARTIUM = MockSdkLibrary(
-  [
-    MockSdkLibraryUnit(
-      'dart:html',
-      '$sdkRoot/lib/html/dartium/html_dartium.dart',
-      '''
-library dart.dom.html;
-import 'dart:async';
-
-class Event {}
-class MouseEvent extends Event {}
-class FocusEvent extends Event {}
-class KeyEvent extends Event {}
-
-abstract class ElementStream<T extends Event> implements Stream<T> {}
-
-abstract class Element {
-  /// Stream of `cut` events handled by this [Element].
-  ElementStream<Event> get onCut => null;
-
-  String get id => null;
-
-  set id(String value) => null;
-}
-
-class HtmlElement extends Element {
-  int tabIndex;
-  ElementStream<Event> get onChange => null;
-  ElementStream<MouseEvent> get onClick => null;
-  ElementStream<KeyEvent> get onKeyUp => null;
-  ElementStream<KeyEvent> get onKeyDown => null;
-
-  bool get hidden => null;
-  set hidden(bool value) => null;
-
-  void set className(String s){}
-  void set readOnly(bool b){}
-  void set tabIndex(int i){}
-
-  String _innerHtml;
-  String get innerHtml {
-    throw 'not the real implementation';
-  }
-  set innerHtml(String value) {
-    // stuff
-  }
-}
-
-class AnchorElement extends HtmlElement {
-  factory AnchorElement({String href}) {
-    AnchorElement e = JS('returns:AnchorElement;creates:AnchorElement;new:true',
-        '#.createElement(#)', document, "a");
-    if (href != null) e.href = href;
-    return e;
-  }
-
-  String href;
-  String _privateField;
-}
-
-class BodyElement extends HtmlElement {
-  factory BodyElement() => document.createElement("body");
-
-  ElementStream<Event> get onUnload => null;
-}
-
-class ButtonElement extends HtmlElement {
-  factory ButtonElement._() { throw new UnsupportedError("Not supported"); }
-  factory ButtonElement() => document.createElement("button");
-
-  bool autofocus;
-}
-
-class EmbedElement extends HtmlEment {
-  String src;
-}
-
-class HeadingElement extends HtmlElement {
-  factory HeadingElement._() { throw new UnsupportedError("Not supported"); }
-  factory HeadingElement.h1() => document.createElement("h1");
-  factory HeadingElement.h2() => document.createElement("h2");
-  factory HeadingElement.h3() => document.createElement("h3");
-}
-
-class InputElement extends HtmlElement {
-  factory InputElement._() { throw new UnsupportedError("Not supported"); }
-  factory InputElement() => document.createElement("input");
-
-  String value;
-  String validationMessage;
-}
-
-class IFrameElement extends HtmlElement {
-  factory IFrameElement._() { throw new UnsupportedError("Not supported"); }
-  factory IFrameElement() => JS(
-      'returns:IFrameElement;creates:IFrameElement;new:true',
-      '#.createElement(#)',
-      document,
-      "iframe");
-
-  String src;
-}
-
-class ImageElement extends HtmlEment {
-  String src;
-}
-
-class OptionElement extends HtmlElement {
-  factory OptionElement({String data: '', String value : '', bool selected: false}) {
-  }
-
-  factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) {
-  }
-}
-
-class ScriptElement extends HtmlElement {
-  String src;
-  String type;
-}
-
-class TableSectionElement extends HtmlElement {
-
-  List<TableRowElement> get rows => null;
-
-  TableRowElement addRow() {
-  }
-
-  TableRowElement insertRow(int index) => null;
-
-  factory TableSectionElement._() { throw new UnsupportedError("Not supported"); }
-
-  @Deprecated("Internal Use Only")
-  external static Type get instanceRuntimeType;
-
-  @Deprecated("Internal Use Only")
-  TableSectionElement.internal_() : super.internal_();
-}
-
-class TemplateElement extends HtmlElement {
-  factory TemplateElement._() { throw new UnsupportedError("Not supported"); }
-  factory TemplateElement() => document.createElement("template");
-}
-
-class AudioElement extends MediaElement {
-  factory AudioElement._([String src]) {
-    if (src != null) {
-      return AudioElement._create_1(src);
-    }
-    return AudioElement._create_2();
-  }
-
-  static AudioElement _create_1(src) => JS('AudioElement', 'new Audio(#)', src);
-  static AudioElement _create_2() => JS('AudioElement', 'new Audio()');
-  AudioElement.created() : super.created();
-
-  factory AudioElement([String src]) => new AudioElement._(src);
-}
-
-class MediaElement extends Element {}
-
-dynamic JS(a, b, c, d) {}
-''',
-    )
-  ],
-);
-
 final MockSdkLibrary _LIB_INTERCEPTORS = MockSdkLibrary(
   [
     MockSdkLibraryUnit(
@@ -1009,7 +847,6 @@
   _LIB_IO,
   _LIB_MATH,
   _LIB_HTML_DART2JS,
-  _LIB_HTML_DARTIUM,
   _LIB_INTERCEPTORS,
   _LIB_INTERNAL,
 ];
@@ -1020,8 +857,7 @@
   'convert': 'const LibraryInfo("convert/convert.dart")',
   'core': 'const LibraryInfo("core/core.dart")',
   'ffi': 'const LibraryInfo("ffi/ffi.dart")',
-  'html': 'const LibraryInfo("html/dartium/html_dartium.dart", '
-      'dart2jsPath: "html/dart2js/html_dart2js.dart")',
+  'html': 'const LibraryInfo("html/dart2js/html_dart2js.dart")',
   'io': 'const LibraryInfo("io/io.dart")',
   'math': 'const LibraryInfo("math/math.dart")',
   '_foreign_helper':
@@ -1268,13 +1104,4 @@
   final DartSdk sdk;
 
   _SdkAnalysisContext(this.sdk);
-
-  @override
-  AnalysisCache createCacheFromSourceFactory(SourceFactory factory) {
-    if (factory == null) {
-      return super.createCacheFromSourceFactory(factory);
-    }
-    return new AnalysisCache(
-        <CachePartition>[AnalysisEngine.instance.partitionManager.forSdk(sdk)]);
-  }
 }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
index 85d5856..ccc3b5e 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk_elements.dart
@@ -34,6 +34,7 @@
   final NullabilitySuffix nullabilitySuffix;
 
   ClassElementImpl _boolElement;
+  ClassElementImpl _comparableElement;
   ClassElementImpl _completerElement;
   ClassElementImpl _deprecatedElement;
   ClassElementImpl _doubleElement;
@@ -93,6 +94,20 @@
     return _boolType ??= _interfaceType(boolElement);
   }
 
+  ClassElementImpl get comparableElement {
+    if (_comparableElement != null) return _comparableElement;
+
+    var tElement = _typeParameter('T');
+    _comparableElement = _class(
+      name: 'Comparable',
+      isAbstract: true,
+      typeParameters: [tElement],
+    );
+    _comparableElement.supertype = objectType;
+
+    return _comparableElement;
+  }
+
   ClassElementImpl get completerElement {
     if (_completerElement != null) return _completerElement;
 
@@ -460,6 +475,12 @@
 
     _numElement = _class(name: 'num', isAbstract: true);
     _numElement.supertype = objectType;
+    _numElement.interfaces = [
+      _interfaceType(
+        comparableElement,
+        typeArguments: [numType],
+      ),
+    ];
 
     _numElement.methods = [
       _method('+', numType, parameters: [
@@ -825,6 +846,7 @@
 
     coreUnit.types = <ClassElement>[
       boolElement,
+      comparableElement,
       deprecatedElement,
       doubleElement,
       functionElement,
@@ -939,12 +961,10 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    var element = FunctionElementImpl(name, 0)
+    return FunctionElementImpl(name, 0)
       ..parameters = parameters
       ..returnType = returnType
       ..typeParameters = typeFormals;
-    element.type = _typeOfExecutableElement(element);
-    return element;
   }
 
   FunctionType _functionType({
@@ -952,7 +972,12 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    return FunctionTypeImpl.synthetic(returnType, typeFormals, parameters);
+    return FunctionTypeImpl.synthetic(
+      returnType,
+      typeFormals,
+      parameters,
+      nullabilitySuffix: nullabilitySuffix,
+    );
   }
 
   PropertyAccessorElement _getter(
@@ -971,7 +996,6 @@
     getter.isStatic = isStatic;
     getter.isSynthetic = false;
     getter.returnType = type;
-    getter.type = _typeOfExecutableElement(getter);
     getter.variable = field;
 
     field.getter = getter;
@@ -995,12 +1019,10 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    var element = MethodElementImpl(name, 0)
+    return MethodElementImpl(name, 0)
       ..parameters = parameters
       ..returnType = returnType
       ..typeParameters = typeFormals;
-    element.type = _typeOfExecutableElement(element);
-    return element;
   }
 
   ParameterElement _namedParameter(String name, DartType type,
@@ -1048,16 +1070,6 @@
         name, isConst, isFinal, type);
   }
 
-  /// TODO(scheglov) We should do the opposite - build type in the element.
-  /// But build a similar synthetic / structured type.
-  FunctionType _typeOfExecutableElement(ExecutableElement element) {
-    return FunctionTypeImpl.synthetic(
-      element.returnType,
-      element.typeParameters,
-      element.parameters,
-    );
-  }
-
   TypeParameterElementImpl _typeParameter(String name) {
     return TypeParameterElementImpl(name, 0);
   }
diff --git a/pkg/analyzer/lib/src/test_utilities/package_mixin.dart b/pkg/analyzer/lib/src/test_utilities/package_mixin.dart
index d071a81..ffcf84c 100644
--- a/pkg/analyzer/lib/src/test_utilities/package_mixin.dart
+++ b/pkg/analyzer/lib/src/test_utilities/package_mixin.dart
@@ -33,6 +33,7 @@
 const Immutable immutable = const Immutable();
 const _Literal literal = const _Literal();
 const _MustCallSuper mustCallSuper = const _MustCallSuper();
+const _NonVirtual nonVirtual = const _NonVirtual();
 const _OptionalTypeArgs optionalTypeArgs = const _OptionalTypeArgs();
 const _Protected protected = const _Protected();
 const Required required = const Required();
@@ -55,6 +56,9 @@
 class _MustCallSuper {
   const _MustCallSuper();
 }
+class _NonVirtual {
+  const _NonVirtual();
+}
 class _OptionalTypeArgs {
   const _OptionalTypeArgs();
 }
diff --git a/pkg/analyzer/lib/src/util/ast_data_extractor.dart b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
index da98e77..6dc4524 100644
--- a/pkg/analyzer/lib/src/util/ast_data_extractor.dart
+++ b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart'
+    show ActualData, DataRegistry, Id, IdKind, MemberId, NodeId;
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:front_end/src/testing/id.dart'
-    show ActualData, DataRegistry, Id, IdKind, MemberId, NodeId;
 
 /// Abstract IR visitor for computing data corresponding to a node or element,
 /// and record it with a generic [Id]
@@ -24,7 +24,7 @@
   NodeId computeDefaultNodeId(AstNode node) =>
       NodeId(_nodeOffset(node), IdKind.node);
 
-  void computeForExpression(Expression node, NodeId id) {
+  void computeForCollectionElement(CollectionElement node, NodeId id) {
     if (id == null) return;
     T value = computeNodeValue(id, node);
     registerValue(uri, node.offset, id, value, node);
@@ -55,6 +55,10 @@
         memberName += '=';
       }
       return MemberId.internal(memberName);
+    } else if (element.enclosingElement is ClassElement) {
+      var memberName = element.name;
+      var className = element.enclosingElement.name;
+      return MemberId.internal(memberName, className: className);
     }
     throw UnimplementedError(
         'TODO(paulberry): $element (${element.runtimeType})');
@@ -79,9 +83,15 @@
   }
 
   @override
-  visitExpression(Expression node) {
-    computeForExpression(node, computeDefaultNodeId(node));
-    super.visitExpression(node);
+  visitCollectionElement(CollectionElement node) {
+    computeForCollectionElement(node, computeDefaultNodeId(node));
+    super.visitCollectionElement(node);
+  }
+
+  @override
+  visitConstructorDeclaration(ConstructorDeclaration node) {
+    computeForMember(node, createMemberId(node));
+    return super.visitConstructorDeclaration(node);
   }
 
   @override
@@ -93,11 +103,31 @@
   }
 
   @override
+  visitMethodDeclaration(MethodDeclaration node) {
+    computeForMember(node, createMemberId(node));
+    return super.visitMethodDeclaration(node);
+  }
+
+  @override
   visitStatement(Statement node) {
-    computeForStatement(node, createStatementId(node));
+    computeForStatement(
+        node,
+        node is ExpressionStatement
+            ? createStatementId(node)
+            : computeDefaultNodeId(node));
     super.visitStatement(node);
   }
 
+  @override
+  visitVariableDeclaration(VariableDeclaration node) {
+    if (node.parent.parent is TopLevelVariableDeclaration) {
+      computeForMember(node, createMemberId(node));
+    } else if (node.parent.parent is FieldDeclaration) {
+      computeForMember(node, createMemberId(node));
+    }
+    return super.visitVariableDeclaration(node);
+  }
+
   int _nodeOffset(AstNode node) {
     var offset = node.offset;
     assert(offset != null && offset >= 0,
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 5fcbbaf..5209ea3 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -277,8 +277,8 @@
         return null;
       }
 
-      if (folder.getChildAssumingFile(_buildFileName).exists) {
-        // Found the BUILD file, denoting a Dart package.
+      // 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) {
@@ -288,25 +288,53 @@
         }
       }
 
+      // In some distributed build environments, BUILD files are not preserved.
+      // We can still look for a ".packages" file in order to determine a
+      // package's root. A ".packages" file found in [folder]'s sister path
+      // under [bin] denotes a Dart package.
+      //
+      // For example, if this BazelWorkspace's [root] is
+      // "/build/work/abc123/workspace" with a [bin] folder of
+      // "/build/work/abc123/workspace/blaze-out/k8-opt/bin/", and [folder]
+      // is at "/build/work/abc123/workspace/foo/bar", then we  must look for a
+      // file ending in ".packages" in the folder
+      // "/build/work/abc123/workspace/blaze-out/k8-opt/bin/foo/bar".
+
+      // [folder]'s path, relative to [root]. For example, "foo/bar".
+      String relative = context.relative(folder.path, from: root);
+      if (bin != null) {
+        Folder binChild = provider.getFolder(context.join(bin, relative));
+        if (binChild.exists &&
+            binChild.getChildren().any((c) => c.path.endsWith('.packages'))) {
+          // [folder]'s sister folder within [bin] contains a ".packages" file.
+          return packageRootedHere();
+        }
+      }
+
+      if (folder.getChildAssumingFile(_buildFileName).exists) {
+        // Found the BUILD file, denoting a Dart package.
+        return packageRootedHere();
+      }
+
       // Go up a folder.
       folder = parent;
     }
   }
 
-  /**
-   * Find the Bazel workspace that contains the given [filePath].
-   *
-   * Return `null` if a workspace marker, such as the `WORKSPACE` file, or
-   * the sibling `READONLY` folder cannot be found.
-   *
-   * Return `null` if the workspace does not have `bazel-genfiles` or
-   * `blaze-genfiles` folders, since we don't know where to search generated
-   * files.
-   *
-   * Return `null` if there is a folder 'foo' with the sibling `READONLY`
-   * folder, but there is corresponding folder 'foo' in `READONLY`, i.e. the
-   * corresponding readonly workspace root.
-   */
+  /// Find the Bazel workspace that contains the given [filePath].
+  ///
+  /// This method walks up the file system from [filePath], looking for various
+  /// "marker" files which indicate a Bazel workspace.
+  ///
+  /// At each folder _f_ with parent _p_, starting with [filePath]:
+  ///
+  /// * If _f_ has a sibling folder named "READONLY", and that folder has a
+  ///   child folder with the same name as _f_, then a BazelWorkspace rooted at
+  ///   _f_ is returned.
+  /// * If _f_ has a child folder named "blaze-out" or "bazel-out", then a
+  ///   BazelWorkspace rooted at _f_ is returned.
+  /// * If _f_ has a child file named "WORKSPACE", then a BazelWorkspace rooted
+  ///   at _f_ is returned.
   static BazelWorkspace find(ResourceProvider provider, String filePath) {
     Resource resource = provider.getResource(filePath);
     if (resource is File && resource.parent != null) {
@@ -327,31 +355,35 @@
         String readonlyRoot =
             context.join(readonlyFolder.path, folder.shortName);
         if (provider.getFolder(readonlyRoot).exists) {
-          String symlinkPrefix = _findSymlinkPrefix(provider, root);
-          if (symlinkPrefix != null) {
-            return new BazelWorkspace._(
-                provider,
-                root,
-                readonlyRoot,
-                context.join(root, '$symlinkPrefix-bin'),
-                context.join(root, '$symlinkPrefix-genfiles'));
-          }
+          String binPath = _findBinFolderPath(folder);
+          String symlinkPrefix =
+              _findSymlinkPrefix(provider, root, binPath: binPath);
+          binPath ??= context.join(root, '$symlinkPrefix-bin');
+          return new BazelWorkspace._(provider, root, readonlyRoot, binPath,
+              context.join(root, '$symlinkPrefix-genfiles'));
         }
       }
 
+      if (_firstExistingFolder(parent, ['blaze-out', 'bazel-out']) != null) {
+        // Found the "out" folder; must be a bazel workspace.
+        String root = parent.path;
+        String binPath = _findBinFolderPath(parent);
+        String symlinkPrefix =
+            _findSymlinkPrefix(provider, root, binPath: binPath);
+        binPath ??= context.join(root, '$symlinkPrefix-bin');
+        return new BazelWorkspace._(provider, root, null /* readonly */,
+            binPath, context.join(root, '$symlinkPrefix-genfiles'));
+      }
+
       // Found the WORKSPACE file, must be a non-git workspace.
       if (folder.getChildAssumingFile(_WORKSPACE).exists) {
         String root = folder.path;
-        String symlinkPrefix = _findSymlinkPrefix(provider, root);
-        if (symlinkPrefix == null) {
-          return null;
-        }
-        return new BazelWorkspace._(
-            provider,
-            root,
-            null,
-            context.join(root, '$symlinkPrefix-bin'),
-            context.join(root, '$symlinkPrefix-genfiles'));
+        String binPath = _findBinFolderPath(folder);
+        String symlinkPrefix =
+            _findSymlinkPrefix(provider, root, binPath: binPath);
+        binPath ??= context.join(root, '$symlinkPrefix-bin');
+        return new BazelWorkspace._(provider, root, null /* readonly */,
+            binPath, context.join(root, '$symlinkPrefix-genfiles'));
       }
 
       // Go up the folder.
@@ -359,14 +391,57 @@
     }
   }
 
-  /**
-   * Return the symlink prefix for folders `X-bin` or `X-genfiles` by probing
-   * the internal `blaze-genfiles` and `bazel-genfiles`. Make a default
-   * assumption according to defaultSymlinkPrefix if neither of the folders
-   * exists.
-   */
-  static String _findSymlinkPrefix(ResourceProvider provider, String root) {
+  /// Return the first folder within [root], chosen from [names], which exists.
+  static Folder _firstExistingFolder(Folder root, List<String> names) => names
+      .map((name) => root.getChildAssumingFolder(name))
+      .firstWhere((folder) => folder.exists, orElse: () => null);
+
+  /// Find the "bin" folder path, by searching for it.
+  ///
+  /// Depending on the environment we're working in (source code tree, build
+  /// environment subtree of sources, local workspace, blaze, bazel), the "bin"
+  /// folder may be available at a symlink found at `$root/blaze-bin/` or
+  /// `$root/bazel-bin/`. If that symlink is not available, then we must search
+  /// the immediate folders found in `$root/blaze-out/` and `$root/bazel-out/`
+  /// for a folder named "bin".
+  ///
+  /// If no "bin" folder is found in any of those locations, `null` is returned.
+  static String _findBinFolderPath(Folder root) {
+    // This is a symlink to the real bin folder, but it is the easiest and
+    // cheapest to search for.
+    Folder symlink = _firstExistingFolder(root, ['blaze-bin', 'bazel-bin']);
+    if (symlink != null) {
+      return symlink.path;
+    }
+
+    Folder out = _firstExistingFolder(root, ['blaze-out', 'bazel-out']);
+    if (out == null) {
+      return null;
+    }
+
+    for (var child in out.getChildren().whereType<Folder>()) {
+      // Children are folders denoting architectures and build flags, like
+      // 'k8-opt', 'k8-fastbuild', perhaps 'host'.
+      Folder possibleBin = child.getChildAssumingFolder('bin');
+      if (possibleBin.exists) {
+        return possibleBin.path;
+      }
+    }
+    return null;
+  }
+
+  /// Return the symlink prefix, _X_, for folders `X-bin` or `X-genfiles`.
+  ///
+  /// If the workspace's "bin" folder was already found, the symlink prefix is
+  /// determined from [binPath]. Otherwise it is determined by probing the
+  /// internal `blaze-genfiles` and `bazel-genfiles`. Make a default assumption
+  /// according to [defaultSymlinkPrefix] if neither of the folders exists.
+  static String _findSymlinkPrefix(ResourceProvider provider, String root,
+      {String binPath}) {
     path.Context context = provider.pathContext;
+    if (binPath != null) {
+      return context.basename(binPath).startsWith('bazel') ? 'bazel' : 'blaze';
+    }
     if (provider.getFolder(context.join(root, 'blaze-genfiles')).exists) {
       return 'blaze';
     }
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 08c9157..5e16cc2 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.38.5
+version: 0.39.1
 author: Dart Team <misc@dartlang.org>
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -8,15 +8,16 @@
   sdk: '>=2.2.2 <3.0.0'
 
 dependencies:
+  _fe_analyzer_shared: 1.0.0
   args: '>=0.12.1 <2.0.0'
   charcode: ^1.1.0
   collection: ^1.10.1
   convert: ^2.0.0
   crypto: '>=1.1.1 <3.0.0'
-  front_end: 0.1.27
+  front_end: 0.1.29
   glob: ^1.0.3
   html: '>=0.13.4+1 <0.15.0'
-  kernel: 0.3.27
+  kernel: 0.3.29
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/dart/analysis/declared_variables_test.dart b/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
index 4563f45..129250a 100644
--- a/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
+++ b/pkg/analyzer/test/dart/analysis/declared_variables_test.dart
@@ -104,8 +104,7 @@
     expect(result.type, typeProvider.nullType);
   }
 
-  void _assertUnknownDartObject(
-      ParameterizedType expectedType, DartObject result) {
+  void _assertUnknownDartObject(DartType expectedType, DartObject result) {
     expect((result as DartObjectImpl).isUnknown, isTrue);
     expect(result.type, expectedType);
   }
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index 61d45e6..d764b46 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -293,7 +293,15 @@
     expect(expression.inSetterContext(), isFalse);
   }
 
-  void test_inSetterContext_postfix() {
+  void test_inSetterContext_postfix_bang() {
+    IndexExpression expression = AstTestFactory.indexExpression(
+        AstTestFactory.identifier3("a"), AstTestFactory.identifier3("b"));
+    // a[b]!
+    AstTestFactory.postfixExpression(expression, TokenType.BANG);
+    expect(expression.inSetterContext(), isFalse);
+  }
+
+  void test_inSetterContext_postfix_plusPlus() {
     IndexExpression expression = AstTestFactory.indexExpression(
         AstTestFactory.identifier3("a"), AstTestFactory.identifier3("b"));
     AstTestFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
@@ -325,6 +333,32 @@
     expect(expression.inSetterContext(), isTrue);
   }
 
+  void test_isNullAware_cascade_false() {
+    final expression = AstTestFactory.indexExpressionForCascade(
+        AstTestFactory.nullLiteral(),
+        AstTestFactory.nullLiteral(),
+        TokenType.PERIOD_PERIOD,
+        TokenType.OPEN_SQUARE_BRACKET);
+    expect(expression.isNullAware, isFalse);
+  }
+
+  void test_isNullAware_cascade_true() {
+    final expression = AstTestFactory.indexExpressionForCascade(
+        AstTestFactory.nullLiteral(),
+        AstTestFactory.nullLiteral(),
+        TokenType.QUESTION_PERIOD_PERIOD,
+        TokenType.OPEN_SQUARE_BRACKET);
+    expect(expression.isNullAware, isTrue);
+  }
+
+  void test_isNullAware_false() {
+    final expression = AstTestFactory.indexExpression(
+        AstTestFactory.nullLiteral(),
+        AstTestFactory.nullLiteral(),
+        TokenType.OPEN_SQUARE_BRACKET);
+    expect(expression.isNullAware, isFalse);
+  }
+
   void test_isNullAware_regularIndex() {
     final expression = AstTestFactory.indexExpression(
         AstTestFactory.nullLiteral(),
@@ -388,6 +422,16 @@
     expect(invocation.isNullAware, isFalse);
   }
 
+  void test_isNullAware_cascade_true() {
+    final invocation = AstTestFactory.methodInvocation3(
+        AstTestFactory.nullLiteral(),
+        'foo',
+        null,
+        [],
+        TokenType.QUESTION_PERIOD_PERIOD);
+    expect(invocation.isNullAware, isTrue);
+  }
+
   void test_isNullAware_regularInvocation() {
     final invocation = AstTestFactory.methodInvocation3(
         AstTestFactory.nullLiteral(), 'foo', null, [], TokenType.PERIOD);
@@ -762,6 +806,12 @@
     expect(invocation.isNullAware, isFalse);
   }
 
+  void test_isNullAware_cascade_true() {
+    final invocation = AstTestFactory.propertyAccess2(
+        AstTestFactory.nullLiteral(), 'foo', TokenType.QUESTION_PERIOD_PERIOD);
+    expect(invocation.isNullAware, isTrue);
+  }
+
   void test_isNullAware_regularPropertyAccess() {
     final invocation = AstTestFactory.propertyAccess2(
         AstTestFactory.nullLiteral(), 'foo', TokenType.PERIOD);
@@ -842,6 +892,7 @@
             wrapper == _WrapperKind.PROPERTY_LEFT ||
             assignment == _AssignmentKind.BINARY ||
             assignment == _AssignmentKind.COMPOUND_RIGHT ||
+            assignment == _AssignmentKind.POSTFIX_BANG ||
             assignment == _AssignmentKind.PREFIX_NOT ||
             assignment == _AssignmentKind.SIMPLE_RIGHT ||
             assignment == _AssignmentKind.NONE) {
@@ -943,6 +994,8 @@
       } else if (assignment == _AssignmentKind.COMPOUND_RIGHT) {
         AstTestFactory.assignmentExpression(
             AstTestFactory.identifier3("_"), TokenType.PLUS_EQ, expression);
+      } else if (assignment == _AssignmentKind.POSTFIX_BANG) {
+        AstTestFactory.postfixExpression(expression, TokenType.BANG);
       } else if (assignment == _AssignmentKind.POSTFIX_INC) {
         AstTestFactory.postfixExpression(expression, TokenType.PLUS_PLUS);
       } else if (assignment == _AssignmentKind.PREFIX_DEC) {
@@ -1430,30 +1483,34 @@
   static const _AssignmentKind COMPOUND_RIGHT =
       const _AssignmentKind('COMPOUND_RIGHT', 2);
 
-  static const _AssignmentKind POSTFIX_INC =
+  static const _AssignmentKind POSTFIX_BANG =
       const _AssignmentKind('POSTFIX_INC', 3);
 
+  static const _AssignmentKind POSTFIX_INC =
+      const _AssignmentKind('POSTFIX_INC', 4);
+
   static const _AssignmentKind PREFIX_DEC =
-      const _AssignmentKind('PREFIX_DEC', 4);
+      const _AssignmentKind('PREFIX_DEC', 5);
 
   static const _AssignmentKind PREFIX_INC =
-      const _AssignmentKind('PREFIX_INC', 5);
+      const _AssignmentKind('PREFIX_INC', 6);
 
   static const _AssignmentKind PREFIX_NOT =
-      const _AssignmentKind('PREFIX_NOT', 6);
+      const _AssignmentKind('PREFIX_NOT', 7);
 
   static const _AssignmentKind SIMPLE_LEFT =
-      const _AssignmentKind('SIMPLE_LEFT', 7);
+      const _AssignmentKind('SIMPLE_LEFT', 8);
 
   static const _AssignmentKind SIMPLE_RIGHT =
-      const _AssignmentKind('SIMPLE_RIGHT', 8);
+      const _AssignmentKind('SIMPLE_RIGHT', 9);
 
-  static const _AssignmentKind NONE = const _AssignmentKind('NONE', 9);
+  static const _AssignmentKind NONE = const _AssignmentKind('NONE', 10);
 
   static const List<_AssignmentKind> values = const [
     BINARY,
     COMPOUND_LEFT,
     COMPOUND_RIGHT,
+    POSTFIX_BANG,
     POSTFIX_INC,
     PREFIX_DEC,
     PREFIX_INC,
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
deleted file mode 100644
index fc77013..0000000
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ /dev/null
@@ -1,2711 +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: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/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/element_search.dart';
-import 'package:analyzer/src/generated/testing/node_search.dart';
-import 'package:analyzer/src/generated/testing/token_factory.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 '../../generated/parser_test.dart';
-import '../../generated/test_support.dart';
-import '../../util/element_type_matchers.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ApiElementBuilderTest);
-    defineReflectiveTests(ElementBuilderTest);
-    defineReflectiveTests(LocalElementBuilderTest);
-  });
-}
-
-@reflectiveTest
-class ApiElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin {
-  @override
-  AstVisitor createElementBuilder(ElementHolder holder) {
-    return new ApiElementBuilder(holder, compilationUnitElement);
-  }
-
-  void test_api_class_field() {
-    List<FieldElement> fields = buildElementsForText(r'''
-class C {
-  var a = 42;
-  var b = () {
-    int v = 0;
-    localFunction() {}
-  };
-}
-''').types[0].fields;
-    expect(fields, hasLength(2));
-    {
-      FieldElement a = fields[0];
-      expect(a.displayName, 'a');
-      expect(a.initializer, isNull);
-    }
-    {
-      FieldElement b = fields[1];
-      expect(b.displayName, 'b');
-      expect(b.initializer, isNull);
-    }
-  }
-
-  void test_api_class_method_blockBody() {
-    MethodElement method = buildElementsForText(r'''
-class C {
-  void m(int a, {int b: 42}) {
-    int v = 0;
-    localFunction() {}
-  }
-}
-''').types[0].methods[0];
-    {
-      expect(method.parameters, hasLength(2));
-      expect(method.parameters[0].displayName, 'a');
-      expect(method.parameters[0].initializer, isNull);
-      expect(method.parameters[1].displayName, 'b');
-      expect(method.parameters[1].initializer, isNull);
-    }
-    expect(
-        findDeclaredIdentifiersByName(compilationUnit, 'v')
-            .single
-            .staticElement,
-        isNull);
-    expect(
-        findDeclaredIdentifiersByName(compilationUnit, 'localFunction')
-            .single
-            .staticElement,
-        isNull);
-  }
-
-  void test_api_topLevelFunction_blockBody() {
-    FunctionElement topLevelFunction = buildElementsForText(r'''
-void topLevelFunction() {
-  int v = 0;
-  localFunction() {}
-}
-''').functions[0];
-    expect(topLevelFunction, isNotNull);
-    expect(topLevelFunction.name, 'topLevelFunction');
-    expect(
-        findDeclaredIdentifiersByName(compilationUnit, 'v')
-            .single
-            .staticElement,
-        isNull);
-    expect(
-        findDeclaredIdentifiersByName(compilationUnit, 'localFunction')
-            .single
-            .staticElement,
-        isNull);
-  }
-
-  void test_api_topLevelFunction_expressionBody() {
-    FunctionElement topLevelFunction = buildElementsForText(r'''
-topLevelFunction() => () {
-  int localVar = 0;
-};
-''').functions[0];
-    expect(topLevelFunction, isNotNull);
-    expect(topLevelFunction.name, 'topLevelFunction');
-    expect(
-        findDeclaredIdentifiersByName(compilationUnit, 'localVar')
-            .single
-            .staticElement,
-        isNull);
-  }
-
-  void test_api_topLevelFunction_parameters() {
-    FunctionElement function = buildElementsForText(r'''
-void topLevelFunction(int a, int b(double b2), {c: () {int c2; c3() {} }}) {
-}
-''').functions[0];
-    List<ParameterElement> parameters = function.parameters;
-    expect(parameters, hasLength(3));
-    {
-      ParameterElement a = parameters[0];
-      expect(a.displayName, 'a');
-      expect(a.initializer, isNull);
-    }
-    {
-      ParameterElement b = parameters[1];
-      expect(b.displayName, 'b');
-      expect(b.initializer, isNull);
-      var bTypeElement = b.type.element as GenericFunctionTypeElementImpl;
-      expect(bTypeElement.parameters, hasLength(1));
-      expect(bTypeElement.parameters[0].displayName, 'b2');
-    }
-    {
-      var c = parameters[2] as DefaultParameterElementImpl;
-      expect(c.displayName, 'c');
-      expect(c.initializer, isNull);
-    }
-  }
-
-  void test_api_topLevelVariable() {
-    List<TopLevelVariableElement> variables = buildElementsForText(r'''
-var A = 42;
-var B = () {
-  int v = 0;
-  localFunction(int _) {}
-};
-''').topLevelVariables;
-    expect(variables, hasLength(2));
-    {
-      TopLevelVariableElement a = variables[0];
-      expect(a.displayName, 'A');
-      expect(a.initializer, isNull);
-    }
-    {
-      TopLevelVariableElement b = variables[1];
-      expect(b.displayName, 'B');
-      expect(b.initializer, isNull);
-    }
-  }
-
-  @override
-  void _assertHasVariableInitializer(VariableElement element) {
-    expect(element.initializer, isNull);
-  }
-}
-
-@reflectiveTest
-class ElementBuilderTest extends _BaseTest with _ApiElementBuilderTestMixin {
-  /**
-   * Parse the given [code], pass it through [ElementBuilder], and return the
-   * resulting [ElementHolder].
-   */
-  ElementHolder buildElementsForText(String code) {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = new ElementBuilder(holder, compilationUnitElement);
-    _visitAstOfCode(code, builder);
-    return holder;
-  }
-
-  AstVisitor createElementBuilder(ElementHolder holder) {
-    return new ElementBuilder(holder, compilationUnitElement);
-  }
-
-  void fail_visitMethodDeclaration_setter_duplicate() {
-    // https://github.com/dart-lang/sdk/issues/25601
-    String code = r'''
-class C {
-  set zzz(x) {}
-  set zzz(y) {}
-}
-''';
-    ClassElement classElement = buildElementsForText(code).types[0];
-    for (PropertyAccessorElement accessor in classElement.accessors) {
-      expect(accessor.variable.setter, same(accessor));
-    }
-  }
-
-  @override
-  void setUp() {
-    super.setUp();
-    compilationUnitElement = new CompilationUnitElementImpl();
-  }
-
-  void test_metadata_localVariableDeclaration() {
-    var code = 'f() { @a int x, y; }';
-    buildElementsForText(code);
-    var x = findLocalVariable('x, ');
-    var y = findLocalVariable('x, ');
-    checkMetadata(x);
-    checkMetadata(y);
-    expect(x.metadata, same(y.metadata));
-  }
-
-  void test_metadata_visitDeclaredIdentifier() {
-    var code = 'f() { for (@a var x in y) {} }';
-    buildElementsForText(code);
-    var x = findLocalVariable('x in');
-    checkMetadata(x);
-  }
-
-  void test_visitCatchClause() {
-    var code = 'f() { try {} catch (e, s) {} }';
-    buildElementsForText(code);
-    var e = findLocalVariable('e, ');
-    var s = findLocalVariable('s) {}');
-
-    expect(e, isNotNull);
-    expect(e.name, 'e');
-    expect(e.hasImplicitType, isTrue);
-    expect(e.isSynthetic, isFalse);
-    expect(e.isConst, isFalse);
-    expect(e.isFinal, isFalse);
-    expect(e.initializer, isNull);
-    _assertVisibleRange(e, 13, 28);
-
-    expect(s, isNotNull);
-    expect(s.name, 's');
-    expect(s.isSynthetic, isFalse);
-    expect(s.isConst, isFalse);
-    expect(s.isFinal, isFalse);
-    expect(s.initializer, isNull);
-    _assertVisibleRange(s, 13, 28);
-  }
-
-  void test_visitCatchClause_withType() {
-    var code = 'f() { try {} on E catch (e) {} }';
-    buildElementsForText(code);
-    var e = findLocalVariable('e) {}');
-    expect(e, isNotNull);
-    expect(e.name, 'e');
-    expect(e.hasImplicitType, isFalse);
-  }
-
-  void test_visitCompilationUnit_codeRange() {
-    TopLevelVariableDeclaration topLevelVariableDeclaration =
-        AstTestFactory.topLevelVariableDeclaration(
-            null,
-            AstTestFactory.typeName4('int'),
-            [AstTestFactory.variableDeclaration('V')]);
-    CompilationUnit unit = astFactory.compilationUnit(
-        beginToken: topLevelVariableDeclaration.beginToken,
-        declarations: [topLevelVariableDeclaration],
-        endToken: topLevelVariableDeclaration.endToken,
-        featureSet: null);
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    unit.beginToken.offset = 10;
-    unit.endToken.offset = 40;
-    unit.accept(builder);
-
-    assertHasCodeRange(compilationUnitElement, 0, 41);
-  }
-
-  void test_visitDeclaredIdentifier_noType() {
-    var code = 'f() { for (var i in []) {} }';
-    buildElementsForText(code);
-    var variable = findLocalVariable('i in');
-    assertHasCodeRange(variable, 11, 5);
-    expect(variable, isNotNull);
-    expect(variable.hasImplicitType, isTrue);
-    expect(variable.isConst, isFalse);
-    expect(variable.hasDeprecated, isFalse);
-    expect(variable.isFinal, isFalse);
-    expect(variable.hasAlwaysThrows, isFalse);
-    expect(variable.isPrivate, isFalse);
-    expect(variable.isPublic, isTrue);
-    expect(variable.isSynthetic, isFalse);
-    expect(variable.name, 'i');
-  }
-
-  void test_visitDeclaredIdentifier_type() {
-    var code = 'f() { for (int i in []) {} }';
-    buildElementsForText(code);
-    var variable = findLocalVariable('i in');
-    assertHasCodeRange(variable, 11, 5);
-    expect(variable.hasImplicitType, isFalse);
-    expect(variable.isConst, isFalse);
-    expect(variable.hasDeprecated, isFalse);
-    expect(variable.isFinal, isFalse);
-    expect(variable.hasOverride, isFalse);
-    expect(variable.isPrivate, isFalse);
-    expect(variable.isPublic, isTrue);
-    expect(variable.isSynthetic, isFalse);
-    expect(variable.name, 'i');
-  }
-
-  void test_visitDefaultFormalParameter_noType() {
-    // p = 0
-    String parameterName = 'p';
-    DefaultFormalParameter formalParameter =
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter3(parameterName),
-            AstTestFactory.integer(0));
-    formalParameter.beginToken.offset = 50;
-    formalParameter.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(formalParameter);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    assertHasCodeRange(parameter, 50, 31);
-    expect(parameter.hasImplicitType, isTrue);
-    expect(parameter.initializer, isNotNull);
-    expect(parameter.initializer.type, isNotNull);
-    expect(parameter.initializer.hasImplicitReturnType, isTrue);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.hasDeprecated, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isInitializingFormal, isFalse);
-    expect(parameter.hasOverride, isFalse);
-    expect(parameter.isPrivate, isFalse);
-    expect(parameter.isPublic, isTrue);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-  }
-
-  void test_visitDefaultFormalParameter_type() {
-    // E p = 0
-    String parameterName = 'p';
-    DefaultFormalParameter formalParameter =
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter4(
-                AstTestFactory.typeName4('E'), parameterName),
-            AstTestFactory.integer(0));
-
-    ElementHolder holder = buildElementsForAst(formalParameter);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter.hasImplicitType, isFalse);
-    expect(parameter.initializer, isNotNull);
-    expect(parameter.initializer.type, isNotNull);
-    expect(parameter.initializer.hasImplicitReturnType, isTrue);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.hasDeprecated, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isInitializingFormal, isFalse);
-    expect(parameter.hasOverride, isFalse);
-    expect(parameter.isPrivate, isFalse);
-    expect(parameter.isPublic, isTrue);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-  }
-
-  void test_visitFunctionExpression() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    FunctionExpression expression = AstTestFactory.functionExpression2(
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    expression.accept(builder);
-    List<FunctionElement> functions = holder.functions;
-    expect(functions, hasLength(1));
-    FunctionElement function = functions[0];
-    expect(function, isNotNull);
-    expect(expression.declaredElement, same(function));
-    expect(function.hasImplicitReturnType, isTrue);
-    expect(function.isSynthetic, isFalse);
-    expect(function.typeParameters, hasLength(0));
-  }
-
-  void test_visitFunctionExpression_inBlockBody() {
-    buildElementsForText('f() { return () => 42; }');
-    FunctionDeclaration f = compilationUnit.declarations[0];
-    BlockFunctionBody fBody = f.functionExpression.body;
-    ReturnStatement returnStatement = fBody.block.statements[0];
-    FunctionExpression closure = returnStatement.expression;
-    FunctionElement function = closure.declaredElement;
-    expect(function, isNotNull);
-    expect(function.hasImplicitReturnType, isTrue);
-    expect(function.isSynthetic, isFalse);
-    expect(function.typeParameters, hasLength(0));
-  }
-
-  void test_visitFunctionExpression_inExpressionBody() {
-    buildElementsForText('f() => () => 42;');
-    FunctionDeclaration f = compilationUnit.declarations[0];
-    ExpressionFunctionBody fBody = f.functionExpression.body;
-    FunctionExpression closure = fBody.expression;
-    FunctionElement function = closure.declaredElement;
-    expect(function, isNotNull);
-    expect(function.hasImplicitReturnType, isTrue);
-    expect(function.isSynthetic, isFalse);
-    expect(function.typeParameters, hasLength(0));
-  }
-
-  void test_visitFunctionTypeAlias() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String aliasName = "F";
-    String parameterName = "E";
-    FunctionTypeAlias aliasNode = AstTestFactory.typeAlias(null, aliasName,
-        AstTestFactory.typeParameterList([parameterName]), null);
-    aliasNode.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    aliasNode.endToken.offset = 80;
-    aliasNode.accept(builder);
-
-    List<FunctionTypeAliasElement> aliases = holder.typeAliases;
-    expect(aliases, hasLength(1));
-    FunctionTypeAliasElement alias = aliases[0];
-    expect(alias, isNotNull);
-    assertHasCodeRange(alias, 50, 31);
-    expect(alias.documentationComment, '/// aaa');
-    expect(alias.name, aliasName);
-    expect(alias.parameters, hasLength(0));
-    List<TypeParameterElement> typeParameters = alias.typeParameters;
-    expect(typeParameters, hasLength(1));
-    TypeParameterElement typeParameter = typeParameters[0];
-    expect(typeParameter, isNotNull);
-    expect(typeParameter.name, parameterName);
-  }
-
-  void test_visitFunctionTypedFormalParameter() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    FunctionTypedFormalParameter formalParameter =
-        AstTestFactory.functionTypedFormalParameter(null, parameterName);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.name, parameterName);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitFunctionTypedFormalParameter_covariant() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    FunctionTypedFormalParameterImpl formalParameter =
-        AstTestFactory.functionTypedFormalParameter(null, parameterName);
-    formalParameter.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElementImpl parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.name, parameterName);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isExplicitlyCovariant, isTrue);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitFunctionTypedFormalParameter_withTypeParameters() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    FunctionTypedFormalParameter formalParameter =
-        AstTestFactory.functionTypedFormalParameter(null, parameterName);
-    formalParameter.typeParameters = AstTestFactory.typeParameterList(['F']);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-
-    ParameterElement parameter = parameters[0];
-    var typeElement = parameter.type.element as GenericFunctionTypeElementImpl;
-    expect(parameter, isNotNull);
-    expect(parameter.name, parameterName);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isRequiredPositional, isTrue);
-    expect(typeElement.typeParameters, hasLength(1));
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitLabeledStatement() {
-    String code = 'f() { l: print(42); }';
-    buildElementsForText(code);
-    LabelElement label = findLabel('l:');
-    expect(label, isNotNull);
-    expect(label.name, 'l');
-    expect(label.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_withMembers() {
-    var code = 'class C { m(p) { var v; try { l: return; } catch (e) {} } }';
-    MethodElement method = buildElementsForText(code).types[0].methods[0];
-    String methodName = "m";
-    String parameterName = "p";
-    String labelName = "l";
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-    List<VariableElement> parameters = method.parameters;
-    expect(parameters, hasLength(1));
-    VariableElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.name, parameterName);
-
-    var v = findLocalVariable('v;');
-    expect(v.name, 'v');
-
-    var e = findLocalVariable('e) {}');
-    expect(e.name, 'e');
-
-    LabelElement label = findLabel('l:');
-    expect(label, isNotNull);
-    expect(label.name, labelName);
-  }
-
-  void test_visitNamedFormalParameter() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    DefaultFormalParameter formalParameter =
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3(parameterName),
-            AstTestFactory.identifier3("42"));
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.beginToken.offset = 50;
-    formalParameter.endToken.offset = 80;
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    assertHasCodeRange(parameter, 50, 32);
-    expect(parameter.name, parameterName);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNamed, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-    expect(parameter.defaultValueCode, "42");
-    FunctionElement initializer = parameter.initializer;
-    expect(initializer, isNotNull);
-    expect(initializer.isSynthetic, isTrue);
-    expect(initializer.hasImplicitReturnType, isTrue);
-  }
-
-  void test_visitNamedFormalParameter_covariant() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    DefaultFormalParameter formalParameter =
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3(parameterName),
-            AstTestFactory.identifier3("42"));
-    (formalParameter.parameter as NormalFormalParameterImpl).covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.beginToken.offset = 50;
-    formalParameter.endToken.offset = 80;
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElementImpl parameter = parameters[0];
-    expect(parameter, isNotNull);
-    assertHasCodeRange(parameter, 50, 32);
-    expect(parameter.name, parameterName);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isExplicitlyCovariant, isTrue);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isNamed, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-    expect(parameter.defaultValueCode, "42");
-    FunctionElement initializer = parameter.initializer;
-    expect(initializer, isNotNull);
-    expect(initializer.isSynthetic, isTrue);
-    expect(initializer.hasImplicitReturnType, isTrue);
-  }
-
-  void test_visitSimpleFormalParameter_noType() {
-    // p
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    SimpleFormalParameter formalParameter =
-        AstTestFactory.simpleFormalParameter3(parameterName);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.hasImplicitType, isTrue);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitSimpleFormalParameter_noType_covariant() {
-    // p
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    SimpleFormalParameterImpl formalParameter =
-        AstTestFactory.simpleFormalParameter3(parameterName);
-    formalParameter.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElementImpl parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.hasImplicitType, isTrue);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isExplicitlyCovariant, isTrue);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitSimpleFormalParameter_type() {
-    // T p
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    SimpleFormalParameter formalParameter =
-        AstTestFactory.simpleFormalParameter4(
-            AstTestFactory.typeName4('T'), parameterName);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.hasImplicitType, isFalse);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitSimpleFormalParameter_type_covariant() {
-    // T p
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String parameterName = "p";
-    SimpleFormalParameterImpl formalParameter =
-        AstTestFactory.simpleFormalParameter4(
-            AstTestFactory.typeName4('T'), parameterName);
-    formalParameter.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _useParameterInMethod(formalParameter, 100, 110);
-    formalParameter.accept(builder);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElementImpl parameter = parameters[0];
-    expect(parameter, isNotNull);
-    expect(parameter.hasImplicitType, isFalse);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isExplicitlyCovariant, isTrue);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.name, parameterName);
-    expect(parameter.isRequiredPositional, isTrue);
-    _assertVisibleRange(parameter, 100, 110);
-  }
-
-  void test_visitVariableDeclaration_field_covariant() {
-    // covariant int f;
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String fieldName = "f";
-    VariableDeclarationImpl variableDeclaration =
-        AstTestFactory.variableDeclaration2(fieldName, null);
-    FieldDeclarationImpl fieldDeclaration = AstTestFactory.fieldDeclaration(
-        false,
-        null,
-        AstTestFactory.typeName4('int'),
-        <VariableDeclaration>[variableDeclaration]);
-    fieldDeclaration.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    variableDeclaration.accept(builder);
-
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElementImpl field = fields[0];
-    expect(field, isNotNull);
-    PropertyAccessorElementImpl setter = field.setter;
-    expect(setter, isNotNull);
-    expect(setter.parameters[0].isCovariant, isTrue);
-  }
-
-  void test_visitVariableDeclaration_inConstructor() {
-    var code = 'class C { C() { var v = 1; } }';
-    buildElementsForText(code);
-    var v = findLocalVariable('v =');
-    assertHasCodeRange(v, 16, 9);
-    expect(v.hasImplicitType, isTrue);
-    expect(v.name, 'v');
-    _assertVisibleRange(v, 14, 28);
-  }
-
-  void test_visitVariableDeclaration_inForEachStatement() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    //
-    // m() { for (var v in []) }
-    //
-    String variableName = "v";
-    DeclaredIdentifier variableIdentifier =
-        AstTestFactory.declaredIdentifier3('v');
-    Statement statement = AstTestFactory.forStatement(
-        AstTestFactory.forEachPartsWithDeclaration(
-            variableIdentifier, AstTestFactory.listLiteral()),
-        AstTestFactory.block());
-    _setNodeSourceRange(statement, 100, 110);
-    MethodDeclaration method = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2([statement]));
-    _setBlockBodySourceRange(method.body, 200, 220);
-    method.accept(builder);
-
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    LocalVariableElement variableElement = variableIdentifier.declaredElement;
-    expect(variableElement.name, variableName);
-    _assertVisibleRange(variableElement, 100, 110);
-  }
-
-  void test_visitVariableDeclaration_inForStatement() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    //
-    // m() { for (T v;;) }
-    //
-    String variableName = "v";
-    VariableDeclaration variableIdentifier =
-        AstTestFactory.variableDeclaration('v');
-    ForStatement statement = AstTestFactory.forStatement(
-        AstTestFactory.forPartsWithDeclarations(
-            AstTestFactory.variableDeclarationList(
-                null, AstTestFactory.typeName4('T'), [variableIdentifier]),
-            null,
-            null),
-        AstTestFactory.block());
-    _setNodeSourceRange(statement, 100, 110);
-    MethodDeclaration method = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2([statement]));
-    _setBlockBodySourceRange(method.body, 200, 220);
-    method.accept(builder);
-
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    LocalVariableElement variableElement = variableIdentifier.declaredElement;
-    expect(variableElement.name, variableName);
-    _assertVisibleRange(variableElement, 100, 110);
-  }
-
-  void test_visitVariableDeclaration_inMethod() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    //
-    // m() {T v;}
-    //
-    String variableName = "v";
-    VariableDeclaration variable =
-        AstTestFactory.variableDeclaration2(variableName, null);
-    Statement statement = AstTestFactory.variableDeclarationStatement(
-        null, AstTestFactory.typeName4('T'), [variable]);
-    MethodDeclaration method = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2([statement]));
-    _setBlockBodySourceRange(method.body, 100, 110);
-    method.accept(builder);
-
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    LocalVariableElement variableElement = variable.declaredElement;
-    expect(variableElement.hasImplicitType, isFalse);
-    expect(variableElement.name, variableName);
-    _assertVisibleRange(variableElement, 100, 110);
-  }
-
-  void test_visitVariableDeclaration_localNestedInFunction() {
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    //
-    // var f = () {var v;};
-    //
-    String variableName = "v";
-    VariableDeclaration variable =
-        AstTestFactory.variableDeclaration2(variableName, null);
-    Statement statement =
-        AstTestFactory.variableDeclarationStatement2(null, [variable]);
-    FunctionExpression initializer = AstTestFactory.functionExpression2(
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2([statement]));
-    String fieldName = "f";
-    VariableDeclaration field =
-        AstTestFactory.variableDeclaration2(fieldName, initializer);
-    FieldDeclaration fieldDeclaration =
-        AstTestFactory.fieldDeclaration2(false, null, [field]);
-    fieldDeclaration.accept(builder);
-
-    List<FieldElement> variables = holder.fields;
-    expect(variables, hasLength(1));
-    FieldElement fieldElement = variables[0];
-    expect(fieldElement, isNotNull);
-    FunctionElement initializerElement = fieldElement.initializer;
-    expect(initializerElement, isNotNull);
-    expect(initializerElement.hasImplicitReturnType, isTrue);
-    expect(initializer.declaredElement, isFunctionElement);
-    LocalVariableElement variableElement = variable.declaredElement;
-    expect(variableElement.hasImplicitType, isTrue);
-    expect(variableElement.isConst, isFalse);
-    expect(variableElement.isFinal, isFalse);
-    expect(variableElement.isSynthetic, isFalse);
-    expect(variableElement.name, variableName);
-  }
-
-  void test_visitVariableDeclaration_noInitializer() {
-    // var v;
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String variableName = "v";
-    VariableDeclaration variableDeclaration =
-        AstTestFactory.variableDeclaration2(variableName, null);
-    AstTestFactory.variableDeclarationList2(null, [variableDeclaration]);
-    variableDeclaration.accept(builder);
-
-    List<TopLevelVariableElement> variables = holder.topLevelVariables;
-    expect(variables, hasLength(1));
-    TopLevelVariableElement variable = variables[0];
-    expect(variable, isNotNull);
-    expect(variable.hasImplicitType, isTrue);
-    expect(variable.initializer, isNull);
-    expect(variable.name, variableName);
-    expect(variable.isConst, isFalse);
-    expect(variable.isFinal, isFalse);
-    expect(variable.isSynthetic, isFalse);
-    expect(variable.getter, isNotNull);
-    expect(variable.setter, isNotNull);
-  }
-
-  void test_visitVariableDeclaration_top() {
-    // final a, b;
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    VariableDeclaration variableDeclaration1 =
-        AstTestFactory.variableDeclaration('a');
-    VariableDeclaration variableDeclaration2 =
-        AstTestFactory.variableDeclaration('b');
-    TopLevelVariableDeclaration topLevelVariableDeclaration =
-        AstTestFactory.topLevelVariableDeclaration(
-            Keyword.FINAL, null, [variableDeclaration1, variableDeclaration2]);
-    topLevelVariableDeclaration.documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-
-    topLevelVariableDeclaration.accept(builder);
-    List<TopLevelVariableElement> variables = holder.topLevelVariables;
-    expect(variables, hasLength(2));
-
-    TopLevelVariableElement variable1 = variables[0];
-    expect(variable1, isNotNull);
-    expect(variable1.documentationComment, '/// aaa');
-
-    TopLevelVariableElement variable2 = variables[1];
-    expect(variable2, isNotNull);
-    expect(variable2.documentationComment, '/// aaa');
-  }
-
-  void test_visitVariableDeclaration_top_const_hasInitializer() {
-    // const v = 42;
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String variableName = "v";
-    VariableDeclaration variableDeclaration =
-        AstTestFactory.variableDeclaration2(
-            variableName, AstTestFactory.integer(42));
-    AstTestFactory.variableDeclarationList2(
-        Keyword.CONST, [variableDeclaration]);
-    variableDeclaration.accept(builder);
-
-    List<TopLevelVariableElement> variables = holder.topLevelVariables;
-    expect(variables, hasLength(1));
-    TopLevelVariableElement variable = variables[0];
-    expect(variable, new TypeMatcher<ConstTopLevelVariableElementImpl>());
-    expect(variable.initializer, isNotNull);
-    expect(variable.initializer.type, isNotNull);
-    expect(variable.initializer.hasImplicitReturnType, isTrue);
-    expect(variable.name, variableName);
-    expect(variable.hasImplicitType, isTrue);
-    expect(variable.isConst, isTrue);
-    expect(variable.isFinal, isFalse);
-    expect(variable.isSynthetic, isFalse);
-    expect(variable.getter, isNotNull);
-    expect(variable.setter, isNull);
-  }
-
-  void test_visitVariableDeclaration_top_final() {
-    // final v;
-    ElementHolder holder = new ElementHolder();
-    ElementBuilder builder = _makeBuilder(holder);
-    String variableName = "v";
-    VariableDeclaration variableDeclaration =
-        AstTestFactory.variableDeclaration2(variableName, null);
-    AstTestFactory.variableDeclarationList2(
-        Keyword.FINAL, [variableDeclaration]);
-    variableDeclaration.accept(builder);
-    List<TopLevelVariableElement> variables = holder.topLevelVariables;
-    expect(variables, hasLength(1));
-    TopLevelVariableElement variable = variables[0];
-    expect(variable, isNotNull);
-    expect(variable.hasImplicitType, isTrue);
-    expect(variable.initializer, isNull);
-    expect(variable.name, variableName);
-    expect(variable.isConst, isFalse);
-    expect(variable.isFinal, isTrue);
-    expect(variable.isSynthetic, isFalse);
-    expect(variable.getter, isNotNull);
-    expect(variable.setter, isNull);
-  }
-
-  ElementBuilder _makeBuilder(ElementHolder holder) =>
-      new ElementBuilder(holder, compilationUnitElement);
-
-  void _setBlockBodySourceRange(BlockFunctionBody body, int offset, int end) {
-    _setNodeSourceRange(body.block, offset, end);
-  }
-
-  void _setNodeSourceRange(AstNode node, int offset, int end) {
-    node.beginToken.offset = offset;
-    Token endToken = node.endToken;
-    endToken.offset = end - endToken.length;
-  }
-
-  void _useParameterInMethod(
-      FormalParameter formalParameter, int blockOffset, int blockEnd) {
-    Block block = AstTestFactory.block();
-    block.leftBracket.offset = blockOffset;
-    block.rightBracket.offset = blockEnd - 1;
-    BlockFunctionBody body = AstTestFactory.blockFunctionBody(block);
-    AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("main"),
-        AstTestFactory.formalParameterList([formalParameter]),
-        body);
-  }
-}
-
-@reflectiveTest
-class LocalElementBuilderTest extends _BaseTest {
-  @override
-  AstVisitor createElementBuilder(ElementHolder holder) {
-    return new LocalElementBuilder(holder, compilationUnitElement);
-  }
-
-  void test_buildLocalElements() {
-    var code = r'''
-main() {
-  int v1;
-  f1() {
-    int v2;
-    f2() {
-      int v3;
-    }
-  }
-}
-''';
-    _compilationUnit = parseCompilationUnit(code);
-    var mainAst = _compilationUnit.declarations.single as FunctionDeclaration;
-
-    // Build API elements.
-    FunctionElementImpl main;
-    {
-      ElementHolder holder = new ElementHolder();
-      _compilationUnit
-          .accept(new ApiElementBuilder(holder, compilationUnitElement));
-      main = holder.functions.single as FunctionElementImpl;
-    }
-
-    // Build local elements in body.
-    ElementHolder holder = new ElementHolder();
-    FunctionBody mainBody = mainAst.functionExpression.body;
-    mainBody.accept(new LocalElementBuilder(holder, compilationUnitElement));
-    main.encloseElements(holder.functions);
-    main.encloseElements(holder.localVariables);
-
-    findNode = FindNode(code, _compilationUnit);
-    var f1 = findLocalFunction('f1() {');
-    var f2 = findLocalFunction('f2() {');
-    var v1 = findLocalVariable('v1;');
-    var v2 = findLocalVariable('v2;');
-    var v3 = findLocalVariable('v3;');
-
-    expect(v1.enclosingElement, main);
-    {
-      expect(f1.name, 'f1');
-      expect(v2.enclosingElement, f1);
-      {
-        expect(f2.name, 'f2');
-        expect(v3.enclosingElement, f2);
-      }
-    }
-  }
-
-  void test_buildParameterInitializer() {
-    CompilationUnit unit = parseCompilationUnit('f({p: 42}) {}');
-    var function = unit.declarations.single as FunctionDeclaration;
-    var parameter = function.functionExpression.parameters.parameters.single
-        as DefaultFormalParameter;
-    // Build API elements.
-    {
-      ElementHolder holder = new ElementHolder();
-      unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
-    }
-    // Validate the parameter element.
-    var parameterElement = parameter.declaredElement as ParameterElementImpl;
-    expect(parameterElement, isNotNull);
-    expect(parameterElement.initializer, isNull);
-    // Build the initializer element.
-    new LocalElementBuilder(new ElementHolder(), compilationUnitElement)
-        .buildParameterInitializer(parameterElement, parameter.defaultValue);
-    expect(parameterElement.initializer, isNotNull);
-  }
-
-  void test_buildVariableInitializer() {
-    CompilationUnit unit = parseCompilationUnit('var V = 42;');
-    TopLevelVariableDeclaration topLevelDecl =
-        unit.declarations[0] as TopLevelVariableDeclaration;
-    VariableDeclaration variable = topLevelDecl.variables.variables.single;
-    // Build the variable element.
-    {
-      ElementHolder holder = new ElementHolder();
-      unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
-    }
-    // Validate the variable element.
-    var variableElement = variable.declaredElement as VariableElementImpl;
-    expect(variableElement, isNotNull);
-    expect(variableElement.initializer, isNull);
-    // Build the initializer element.
-    new LocalElementBuilder(new ElementHolder(), compilationUnitElement)
-        .buildVariableInitializer(variableElement, variable.initializer);
-    expect(variableElement.initializer, isNotNull);
-  }
-
-  void test_genericFunction_isExpression() {
-    buildElementsForText('main(p) { p is Function(int a, String); }');
-    var main = compilationUnit.declarations[0] as FunctionDeclaration;
-    var body = main.functionExpression.body as BlockFunctionBody;
-    var statement = body.block.statements[0] as ExpressionStatement;
-    var expression = statement.expression as IsExpression;
-    var typeNode = expression.type as GenericFunctionType;
-    var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
-    expect(typeElement.parameters, hasLength(2));
-    expect(typeElement.parameters[0].name, 'a');
-    expect(typeElement.parameters[1].name, '');
-  }
-
-  void test_visitDefaultFormalParameter_local() {
-    CompilationUnit unit = parseCompilationUnit('''
-main() {
-  f({bool b: false}) {}
-}
-''');
-    var mainAst = unit.declarations.single as FunctionDeclaration;
-    // Build API elements.
-    FunctionElementImpl main;
-    {
-      ElementHolder holder = new ElementHolder();
-      unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
-      main = holder.functions.single as FunctionElementImpl;
-    }
-    // Build local elements in body.
-    ElementHolder holder = new ElementHolder();
-    FunctionBody mainBody = mainAst.functionExpression.body;
-    mainBody.accept(new LocalElementBuilder(holder, compilationUnitElement));
-
-    List<FunctionElement> functions = holder.functions;
-    main.encloseElements(functions);
-
-    FunctionElement f = findElementsByName(unit, 'f').single;
-    expect(f.parameters, hasLength(1));
-    expect(f.parameters[0].initializer, isNotNull);
-  }
-
-  void test_visitFieldFormalParameter() {
-    CompilationUnit unit = parseCompilationUnit(r'''
-main() {
-  f(a, this.b) {}
-}
-''', codes: [ParserErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR]);
-    var main = unit.declarations[0] as FunctionDeclaration;
-    var mainBody = main.functionExpression.body as BlockFunctionBody;
-    var mainBlock = mainBody.block;
-    var statement = mainBlock.statements[0] as FunctionDeclarationStatement;
-    FunctionDeclaration f = statement.functionDeclaration;
-
-    // Build API elements.
-    {
-      ElementHolder holder = new ElementHolder();
-      unit.accept(new ApiElementBuilder(holder, compilationUnitElement));
-    }
-
-    // Build local elements.
-    ElementHolder holder = new ElementHolder();
-    var builder = new LocalElementBuilder(holder, compilationUnitElement);
-    f.accept(builder);
-
-    List<FormalParameter> parameters =
-        f.functionExpression.parameters.parameters;
-
-    ParameterElement a = parameters[0].declaredElement;
-    expect(a, isNotNull);
-    expect(a.name, 'a');
-
-    ParameterElement b = parameters[1].declaredElement;
-    expect(b, isNotNull);
-    expect(b.name, 'b');
-  }
-
-  void test_visitVariableDeclaration_local() {
-    var code = 'class C { m() { T v = null; } }';
-    buildElementsForText(code);
-    LocalVariableElement element = findNode.simple('v =').staticElement;
-    expect(element.hasImplicitType, isFalse);
-    expect(element.name, 'v');
-    expect(element.initializer, isNotNull);
-    _assertVisibleRange(element, 14, 29);
-  }
-}
-
-/**
- * Mixin with test methods for testing element building in [ApiElementBuilder].
- * It is used to test the [ApiElementBuilder] itself, and its usage by
- * [ElementBuilder].
- */
-mixin _ApiElementBuilderTestMixin {
-  CompilationUnit get compilationUnit;
-
-  void set isMixinSupportEnabled(bool value);
-
-  void assertHasCodeRange(Element element, int offset, int length);
-
-  /**
-   * Build elements using [ApiElementBuilder].
-   */
-  ElementHolder buildElementsForAst(AstNode node);
-
-  /**
-   * Parse the given [code], and build elements using [ApiElementBuilder].
-   */
-  ElementHolder buildElementsForText(String code);
-
-  /**
-   * Verify that the given [metadata] has exactly one annotation, and that its
-   * [ElementAnnotationImpl] is unresolved.
-   */
-  void checkAnnotation(NodeList<Annotation> metadata);
-
-  /**
-   * Verify that the given [element] has exactly one annotation, and that its
-   * [ElementAnnotationImpl] is unresolved.
-   */
-  void checkMetadata(Element element);
-
-  void test_genericFunction_asTopLevelVariableType() {
-    buildElementsForText('int Function(int a, String) v;');
-    var v = compilationUnit.declarations[0] as TopLevelVariableDeclaration;
-    var typeNode = v.variables.type as GenericFunctionType;
-    var typeElement = typeNode.type.element as GenericFunctionTypeElementImpl;
-    expect(typeElement.parameters, hasLength(2));
-    expect(typeElement.parameters[0].name, 'a');
-    expect(typeElement.parameters[1].name, '');
-  }
-
-  void test_metadata_fieldDeclaration() {
-    List<FieldElement> fields =
-        buildElementsForText('class C { @a int x, y; }').types[0].fields;
-    checkMetadata(fields[0]);
-    checkMetadata(fields[1]);
-    expect(fields[0].metadata, same(fields[1].metadata));
-  }
-
-  void test_metadata_topLevelVariableDeclaration() {
-    List<TopLevelVariableElement> topLevelVariables =
-        buildElementsForText('@a int x, y;').topLevelVariables;
-    checkMetadata(topLevelVariables[0]);
-    checkMetadata(topLevelVariables[1]);
-    expect(topLevelVariables[0].metadata, same(topLevelVariables[1].metadata));
-  }
-
-  void test_metadata_visitClassDeclaration() {
-    ClassElement classElement = buildElementsForText('@a class C {}').types[0];
-    checkMetadata(classElement);
-  }
-
-  void test_metadata_visitClassTypeAlias() {
-    ClassElement classElement =
-        buildElementsForText('@a class C = D with E;').types[0];
-    checkMetadata(classElement);
-  }
-
-  void test_metadata_visitConstructorDeclaration() {
-    ConstructorElement constructorElement =
-        buildElementsForText('class C { @a C(); }').types[0].constructors[0];
-    checkMetadata(constructorElement);
-  }
-
-  void test_metadata_visitDefaultFormalParameter_fieldFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('class C { var x; C([@a this.x = null]); }')
-            .types[0]
-            .constructors[0]
-            .parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void
-      test_metadata_visitDefaultFormalParameter_functionTypedFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('f([@a g() = null]) {}')
-            .functions[0]
-            .parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void test_metadata_visitDefaultFormalParameter_simpleFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('f([@a gx = null]) {}').functions[0].parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void test_metadata_visitEnumConstant() {
-    ElementHolder enumElement = buildElementsForText('enum E { @a v }');
-    FieldElement v = enumElement.enums[0].fields[0];
-    expect(v.name, 'v');
-    checkMetadata(v);
-  }
-
-  void test_metadata_visitEnumDeclaration() {
-    ClassElement classElement =
-        buildElementsForText('@a enum E { v }').enums[0];
-    checkMetadata(classElement);
-  }
-
-  void test_metadata_visitExportDirective() {
-    buildElementsForText('@a export "foo.dart";');
-    expect(compilationUnit.directives[0], new TypeMatcher<ExportDirective>());
-    ExportDirective exportDirective = compilationUnit.directives[0];
-    checkAnnotation(exportDirective.metadata);
-  }
-
-  void test_metadata_visitFieldFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('class C { var x; C(@a this.x); }')
-            .types[0]
-            .constructors[0]
-            .parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void test_metadata_visitFunctionDeclaration_function() {
-    FunctionElement functionElement =
-        buildElementsForText('@a f() {}').functions[0];
-    checkMetadata(functionElement);
-  }
-
-  void test_metadata_visitFunctionDeclaration_getter() {
-    PropertyAccessorElement propertyAccessorElement =
-        buildElementsForText('@a get f => null;').accessors[0];
-    checkMetadata(propertyAccessorElement);
-  }
-
-  void test_metadata_visitFunctionDeclaration_setter() {
-    PropertyAccessorElement propertyAccessorElement =
-        buildElementsForText('@a set f(value) {}').accessors[0];
-    checkMetadata(propertyAccessorElement);
-  }
-
-  void test_metadata_visitFunctionTypeAlias() {
-    FunctionTypeAliasElement functionTypeAliasElement =
-        buildElementsForText('@a typedef F();').typeAliases[0];
-    checkMetadata(functionTypeAliasElement);
-  }
-
-  void test_metadata_visitFunctionTypedFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('f(@a g()) {}').functions[0].parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void test_metadata_visitImportDirective() {
-    buildElementsForText('@a import "foo.dart";');
-    expect(compilationUnit.directives[0], new TypeMatcher<ImportDirective>());
-    ImportDirective importDirective = compilationUnit.directives[0];
-    checkAnnotation(importDirective.metadata);
-  }
-
-  void test_metadata_visitLibraryDirective() {
-    buildElementsForText('@a library L;');
-    expect(compilationUnit.directives[0], new TypeMatcher<LibraryDirective>());
-    LibraryDirective libraryDirective = compilationUnit.directives[0];
-    checkAnnotation(libraryDirective.metadata);
-  }
-
-  void test_metadata_visitMethodDeclaration_getter() {
-    PropertyAccessorElement propertyAccessorElement =
-        buildElementsForText('class C { @a get m => null; }')
-            .types[0]
-            .accessors[0];
-    checkMetadata(propertyAccessorElement);
-  }
-
-  void test_metadata_visitMethodDeclaration_method() {
-    MethodElement methodElement =
-        buildElementsForText('class C { @a m() {} }').types[0].methods[0];
-    checkMetadata(methodElement);
-  }
-
-  void test_metadata_visitMethodDeclaration_setter() {
-    PropertyAccessorElement propertyAccessorElement =
-        buildElementsForText('class C { @a set f(value) {} }')
-            .types[0]
-            .accessors[0];
-    checkMetadata(propertyAccessorElement);
-  }
-
-  void test_metadata_visitPartDirective() {
-    buildElementsForText('@a part "foo.dart";');
-    expect(compilationUnit.directives[0], new TypeMatcher<PartDirective>());
-    PartDirective partDirective = compilationUnit.directives[0];
-    checkAnnotation(partDirective.metadata);
-  }
-
-  void test_metadata_visitPartOfDirective() {
-    // We don't build ElementAnnotation objects for `part of` directives, since
-    // analyzer ignores them in favor of annotations on the library directive.
-    buildElementsForText('@a part of L;');
-    expect(compilationUnit.directives[0], new TypeMatcher<PartOfDirective>());
-    PartOfDirective partOfDirective = compilationUnit.directives[0];
-    expect(partOfDirective.metadata, hasLength(1));
-    expect(partOfDirective.metadata[0].elementAnnotation, isNull);
-  }
-
-  void test_metadata_visitSimpleFormalParameter() {
-    ParameterElement parameterElement =
-        buildElementsForText('f(@a x) {}').functions[0].parameters[0];
-    checkMetadata(parameterElement);
-  }
-
-  void test_metadata_visitTypeParameter() {
-    TypeParameterElement typeParameterElement =
-        buildElementsForText('class C<@a T> {}').types[0].typeParameters[0];
-    checkMetadata(typeParameterElement);
-  }
-
-  void test_visitClassDeclaration_abstract() {
-    List<ClassElement> types =
-        buildElementsForText('abstract class C {}').types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type, isNotNull);
-    expect(type.name, 'C');
-    List<TypeParameterElement> typeParameters = type.typeParameters;
-    expect(typeParameters, hasLength(0));
-    expect(type.isAbstract, isTrue);
-    expect(type.isMixinApplication, isFalse);
-    expect(type.isSynthetic, isFalse);
-  }
-
-  void test_visitClassDeclaration_invalidFunctionInAnnotation_class() {
-    // https://github.com/dart-lang/sdk/issues/25696
-    String code = r'''
-class A {
-  const A({f});
-}
-
-@A(f: () {})
-class C {}
-''';
-    buildElementsForText(code);
-  }
-
-  void test_visitClassDeclaration_invalidFunctionInAnnotation_method() {
-    String code = r'''
-class A {
-  const A({f});
-}
-
-class C {
-  @A(f: () {})
-  void m() {}
-}
-''';
-    ElementHolder holder = buildElementsForText(code);
-    ClassElement elementC = holder.types[1];
-    expect(elementC, isNotNull);
-    MethodElement methodM = elementC.methods[0];
-    expect(methodM, isNotNull);
-  }
-
-  void test_visitClassDeclaration_minimal() {
-    String className = "C";
-    ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
-        null, className, null, null, null, null);
-    classDeclaration.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    classDeclaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(classDeclaration);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type, isNotNull);
-    expect(type.name, className);
-    List<TypeParameterElement> typeParameters = type.typeParameters;
-    expect(typeParameters, hasLength(0));
-    expect(type.isAbstract, isFalse);
-    expect(type.isMixinApplication, isFalse);
-    expect(type.isSynthetic, isFalse);
-    expect(type.documentationComment, '/// aaa');
-    assertHasCodeRange(type, 50, 31);
-  }
-
-  void test_visitClassDeclaration_parameterized() {
-    String className = "C";
-    String firstVariableName = "E";
-    String secondVariableName = "F";
-    ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
-        null,
-        className,
-        AstTestFactory.typeParameterList(
-            [firstVariableName, secondVariableName]),
-        null,
-        null,
-        null);
-
-    ElementHolder holder = buildElementsForAst(classDeclaration);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type, isNotNull);
-    expect(type.name, className);
-    List<TypeParameterElement> typeParameters = type.typeParameters;
-    expect(typeParameters, hasLength(2));
-    expect(typeParameters[0].name, firstVariableName);
-    expect(typeParameters[1].name, secondVariableName);
-    expect(type.isAbstract, isFalse);
-    expect(type.isMixinApplication, isFalse);
-    expect(type.isSynthetic, isFalse);
-  }
-
-  void test_visitClassDeclaration_withMembers() {
-    String className = "C";
-    String typeParameterName = "E";
-    String fieldName = "f";
-    String methodName = "m";
-    ClassDeclaration classDeclaration = AstTestFactory.classDeclaration(
-        null,
-        className,
-        AstTestFactory.typeParameterList([typeParameterName]),
-        null,
-        null,
-        null, [
-      AstTestFactory.fieldDeclaration2(
-          false, null, [AstTestFactory.variableDeclaration(fieldName)]),
-      AstTestFactory.methodDeclaration2(
-          null,
-          null,
-          null,
-          null,
-          AstTestFactory.identifier3(methodName),
-          AstTestFactory.formalParameterList(),
-          AstTestFactory.blockFunctionBody2())
-    ]);
-
-    ElementHolder holder = buildElementsForAst(classDeclaration);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type, isNotNull);
-    expect(type.name, className);
-    expect(type.isAbstract, isFalse);
-    expect(type.isMixinApplication, isFalse);
-    expect(type.isSynthetic, isFalse);
-    List<TypeParameterElement> typeParameters = type.typeParameters;
-    expect(typeParameters, hasLength(1));
-    TypeParameterElement typeParameter = typeParameters[0];
-    expect(typeParameter, isNotNull);
-    expect(typeParameter.name, typeParameterName);
-    List<FieldElement> fields = type.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, fieldName);
-    List<MethodElement> methods = type.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.name, methodName);
-  }
-
-  void test_visitClassTypeAlias() {
-    // class B {}
-    // class M {}
-    // class C = B with M
-    ClassElementImpl classB = ElementFactory.classElement2('B', []);
-    ConstructorElementImpl constructorB =
-        ElementFactory.constructorElement2(classB, '', []);
-    constructorB.setModifier(Modifier.SYNTHETIC, true);
-    classB.constructors = [constructorB];
-    ClassElement classM = ElementFactory.classElement2('M', []);
-    WithClause withClause =
-        AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
-    ClassTypeAlias alias = AstTestFactory.classTypeAlias(
-        'C', null, null, AstTestFactory.typeName(classB, []), withClause, null);
-
-    ElementHolder holder = buildElementsForAst(alias);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(alias.declaredElement, same(type));
-    expect(type.name, equals('C'));
-    expect(type.isAbstract, isFalse);
-    expect(type.isMixinApplication, isTrue);
-    expect(type.isSynthetic, isFalse);
-    expect(type.typeParameters, isEmpty);
-    expect(type.fields, isEmpty);
-    expect(type.methods, isEmpty);
-  }
-
-  void test_visitClassTypeAlias_abstract() {
-    // class B {}
-    // class M {}
-    // abstract class C = B with M
-    ClassElementImpl classB = ElementFactory.classElement2('B', []);
-    ConstructorElementImpl constructorB =
-        ElementFactory.constructorElement2(classB, '', []);
-    constructorB.setModifier(Modifier.SYNTHETIC, true);
-    classB.constructors = [constructorB];
-    ClassElement classM = ElementFactory.classElement2('M', []);
-    WithClause withClause =
-        AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
-    ClassTypeAlias alias = AstTestFactory.classTypeAlias(
-        'C',
-        null,
-        Keyword.ABSTRACT,
-        AstTestFactory.typeName(classB, []),
-        withClause,
-        null);
-
-    ElementHolder holder = buildElementsForAst(alias);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type.isAbstract, isTrue);
-    expect(type.isMixinApplication, isTrue);
-  }
-
-  void test_visitClassTypeAlias_typeParams() {
-    // class B {}
-    // class M {}
-    // class C<T> = B with M
-    ClassElementImpl classB = ElementFactory.classElement2('B', []);
-    ConstructorElementImpl constructorB =
-        ElementFactory.constructorElement2(classB, '', []);
-    constructorB.setModifier(Modifier.SYNTHETIC, true);
-    classB.constructors = [constructorB];
-    ClassElementImpl classM = ElementFactory.classElement2('M', []);
-    WithClause withClause =
-        AstTestFactory.withClause([AstTestFactory.typeName(classM, [])]);
-    ClassTypeAlias alias = AstTestFactory.classTypeAlias(
-        'C',
-        AstTestFactory.typeParameterList(['T']),
-        null,
-        AstTestFactory.typeName(classB, []),
-        withClause,
-        null);
-
-    ElementHolder holder = buildElementsForAst(alias);
-    List<ClassElement> types = holder.types;
-    expect(types, hasLength(1));
-    ClassElement type = types[0];
-    expect(type.typeParameters, hasLength(1));
-    expect(type.typeParameters[0].name, equals('T'));
-  }
-
-  void test_visitConstructorDeclaration_external() {
-    String className = "A";
-    ConstructorDeclaration constructorDeclaration =
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3(className),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2());
-    constructorDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-
-    ElementHolder holder = buildElementsForAst(constructorDeclaration);
-    List<ConstructorElement> constructors = holder.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-    expect(constructor.isExternal, isTrue);
-    expect(constructor.isFactory, isFalse);
-    expect(constructor.name, "");
-    expect(constructor.parameters, hasLength(0));
-  }
-
-  void test_visitConstructorDeclaration_factory() {
-    String className = "A";
-    ConstructorDeclaration constructorDeclaration =
-        AstTestFactory.constructorDeclaration2(
-            null,
-            Keyword.FACTORY,
-            AstTestFactory.identifier3(className),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2());
-
-    ElementHolder holder = buildElementsForAst(constructorDeclaration);
-    List<ConstructorElement> constructors = holder.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-    expect(constructor.isExternal, isFalse);
-    expect(constructor.isFactory, isTrue);
-    expect(constructor.name, "");
-    expect(constructor.parameters, hasLength(0));
-  }
-
-  void test_visitConstructorDeclaration_minimal() {
-    String className = "A";
-    ConstructorDeclaration constructorDeclaration =
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3(className),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2());
-    constructorDeclaration.documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    constructorDeclaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(constructorDeclaration);
-    List<ConstructorElement> constructors = holder.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-    assertHasCodeRange(constructor, 50, 31);
-    expect(constructor.documentationComment, '/// aaa');
-    expect(constructor.isExternal, isFalse);
-    expect(constructor.isFactory, isFalse);
-    expect(constructor.name, "");
-    expect(constructor.parameters, hasLength(0));
-  }
-
-  void test_visitConstructorDeclaration_named() {
-    String className = "A";
-    String constructorName = "c";
-    ConstructorDeclaration constructorDeclaration =
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3(className),
-            constructorName,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2());
-
-    ElementHolder holder = buildElementsForAst(constructorDeclaration);
-    List<ConstructorElement> constructors = holder.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-    expect(constructor.isExternal, isFalse);
-    expect(constructor.isFactory, isFalse);
-    expect(constructor.name, constructorName);
-    expect(constructor.parameters, hasLength(0));
-    expect(constructorDeclaration.name.staticElement, same(constructor));
-    expect(constructorDeclaration.declaredElement, same(constructor));
-  }
-
-  void test_visitConstructorDeclaration_unnamed() {
-    String className = "A";
-    ConstructorDeclaration constructorDeclaration =
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3(className),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2());
-
-    ElementHolder holder = buildElementsForAst(constructorDeclaration);
-    List<ConstructorElement> constructors = holder.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-    expect(constructor.isExternal, isFalse);
-    expect(constructor.isFactory, isFalse);
-    expect(constructor.name, "");
-    expect(constructor.parameters, hasLength(0));
-    expect(constructorDeclaration.declaredElement, same(constructor));
-  }
-
-  void test_visitEnumDeclaration() {
-    String enumName = "E";
-    EnumDeclaration enumDeclaration =
-        AstTestFactory.enumDeclaration2(enumName, ["ONE"]);
-    enumDeclaration.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    enumDeclaration.endToken.offset = 80;
-    ElementHolder holder = buildElementsForAst(enumDeclaration);
-    List<ClassElement> enums = holder.enums;
-    expect(enums, hasLength(1));
-    ClassElement enumElement = enums[0];
-    expect(enumElement, isNotNull);
-    assertHasCodeRange(enumElement, 50, 31);
-    expect(enumElement.documentationComment, '/// aaa');
-    expect(enumElement.name, enumName);
-  }
-
-  void test_visitFieldDeclaration() {
-    var holder = buildElementsForText(r'''
-class C {
-  /// aaa
-  int x = 1, y;
-}
-''');
-    ClassElement c = holder.types.single;
-    List<FieldElement> fields = c.fields;
-    expect(fields, hasLength(2));
-
-    FieldElement x = fields[0];
-    expect(x, isNotNull);
-    assertHasCodeRange(x, 12, 19);
-    expect(x.documentationComment, '/// aaa');
-    expect(x.name, 'x');
-    _assertHasVariableInitializer(x);
-    expect(x.isConst, isFalse);
-    expect(x.isFinal, isFalse);
-    expect(x.isSynthetic, isFalse);
-
-    FieldElement y = fields[1];
-    expect(y, isNotNull);
-    assertHasCodeRange(y, 33, 1);
-    expect(y.documentationComment, '/// aaa');
-    expect(y.name, 'y');
-    expect(y.initializer, isNull);
-    expect(y.isConst, isFalse);
-    expect(y.isFinal, isFalse);
-    expect(y.isSynthetic, isFalse);
-  }
-
-  void test_visitFieldFormalParameter() {
-    String parameterName = "p";
-    FieldFormalParameter formalParameter =
-        AstTestFactory.fieldFormalParameter(null, null, parameterName);
-    formalParameter.beginToken.offset = 50;
-    formalParameter.endToken.offset = 80;
-    ElementHolder holder = buildElementsForAst(formalParameter);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-    ParameterElement parameter = parameters[0];
-    expect(parameter, isNotNull);
-    assertHasCodeRange(parameter, 50, 31);
-    expect(parameter.name, parameterName);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isRequiredPositional, isTrue);
-    expect(parameter.parameters, hasLength(0));
-  }
-
-  void test_visitFieldFormalParameter_functionTyped() {
-    String parameterName = "p";
-    FieldFormalParameter formalParameter = AstTestFactory.fieldFormalParameter(
-        null,
-        null,
-        parameterName,
-        AstTestFactory.formalParameterList(
-            [AstTestFactory.simpleFormalParameter3("a")]));
-    ElementHolder holder = buildElementsForAst(formalParameter);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(1));
-
-    ParameterElement parameter = parameters[0];
-    var typeElement = parameter.type.element as GenericFunctionTypeElementImpl;
-    expect(parameter, isNotNull);
-    expect(parameter.name, parameterName);
-    expect(parameter.initializer, isNull);
-    expect(parameter.isConst, isFalse);
-    expect(parameter.isFinal, isFalse);
-    expect(parameter.isSynthetic, isFalse);
-    expect(parameter.isRequiredPositional, isTrue);
-    expect(typeElement.parameters, hasLength(1));
-  }
-
-  void test_visitFormalParameterList() {
-    String firstParameterName = "a";
-    String secondParameterName = "b";
-    FormalParameterList parameterList = AstTestFactory.formalParameterList([
-      AstTestFactory.simpleFormalParameter3(firstParameterName),
-      AstTestFactory.simpleFormalParameter3(secondParameterName)
-    ]);
-    ElementHolder holder = buildElementsForAst(parameterList);
-    List<ParameterElement> parameters = holder.parameters;
-    expect(parameters, hasLength(2));
-    expect(parameters[0].name, firstParameterName);
-    expect(parameters[1].name, secondParameterName);
-  }
-
-  void test_visitFunctionDeclaration_external() {
-    // external f();
-    String functionName = "f";
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null,
-        null,
-        functionName,
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.emptyFunctionBody()));
-    declaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-
-    ElementHolder holder = buildElementsForAst(declaration);
-    List<FunctionElement> functions = holder.functions;
-    expect(functions, hasLength(1));
-    FunctionElement function = functions[0];
-    expect(function, isNotNull);
-    expect(function.name, functionName);
-    expect(declaration.declaredElement, same(function));
-    expect(declaration.functionExpression.declaredElement, same(function));
-    expect(function.hasImplicitReturnType, isTrue);
-    expect(function.isExternal, isTrue);
-    expect(function.isSynthetic, isFalse);
-    expect(function.typeParameters, hasLength(0));
-  }
-
-  void test_visitFunctionDeclaration_getter() {
-    // get f() {}
-    String functionName = "f";
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null,
-        Keyword.GET,
-        functionName,
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-    declaration.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    declaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(declaration);
-    List<PropertyAccessorElement> accessors = holder.accessors;
-    expect(accessors, hasLength(1));
-    PropertyAccessorElement accessor = accessors[0];
-    expect(accessor, isNotNull);
-    assertHasCodeRange(accessor, 50, 31);
-    expect(accessor.documentationComment, '/// aaa');
-    expect(accessor.name, functionName);
-    expect(declaration.declaredElement, same(accessor));
-    expect(declaration.functionExpression.declaredElement, same(accessor));
-    expect(accessor.hasImplicitReturnType, isTrue);
-    expect(accessor.isGetter, isTrue);
-    expect(accessor.isExternal, isFalse);
-    expect(accessor.isSetter, isFalse);
-    expect(accessor.isSynthetic, isFalse);
-    expect(accessor.typeParameters, hasLength(0));
-    TopLevelVariableElement variable = accessor.variable;
-    expect(variable.isSynthetic, isTrue);
-  }
-
-  void test_visitFunctionDeclaration_plain() {
-    // T f() {}
-    String functionName = "f";
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        AstTestFactory.typeName4('T'),
-        null,
-        functionName,
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-    declaration.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    declaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(declaration);
-    List<FunctionElement> functions = holder.functions;
-    expect(functions, hasLength(1));
-    FunctionElement function = functions[0];
-    expect(function, isNotNull);
-    assertHasCodeRange(function, 50, 31);
-    expect(function.documentationComment, '/// aaa');
-    expect(function.hasImplicitReturnType, isFalse);
-    expect(function.name, functionName);
-    expect(declaration.declaredElement, same(function));
-    expect(declaration.functionExpression.declaredElement, same(function));
-    expect(function.isExternal, isFalse);
-    expect(function.isSynthetic, isFalse);
-    expect(function.typeParameters, hasLength(0));
-  }
-
-  void test_visitFunctionDeclaration_setter() {
-    // set f() {}
-    String functionName = "f";
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null,
-        Keyword.SET,
-        functionName,
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-    declaration.documentationComment = AstTestFactory.documentationComment(
-        [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    declaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(declaration);
-    List<PropertyAccessorElement> accessors = holder.accessors;
-    expect(accessors, hasLength(1));
-    PropertyAccessorElement accessor = accessors[0];
-    expect(accessor, isNotNull);
-    assertHasCodeRange(accessor, 50, 31);
-    expect(accessor.documentationComment, '/// aaa');
-    expect(accessor.hasImplicitReturnType, isTrue);
-    expect(accessor.name, "$functionName=");
-    expect(declaration.declaredElement, same(accessor));
-    expect(declaration.functionExpression.declaredElement, same(accessor));
-    expect(accessor.isGetter, isFalse);
-    expect(accessor.isExternal, isFalse);
-    expect(accessor.isSetter, isTrue);
-    expect(accessor.isSynthetic, isFalse);
-    expect(accessor.typeParameters, hasLength(0));
-    TopLevelVariableElement variable = accessor.variable;
-    expect(variable.isSynthetic, isTrue);
-  }
-
-  void test_visitFunctionDeclaration_typeParameters() {
-    // f<E>() {}
-    String functionName = 'f';
-    String typeParameterName = 'E';
-    FunctionExpression expression = AstTestFactory.functionExpression3(
-        AstTestFactory.typeParameterList([typeParameterName]),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null, null, functionName, expression);
-
-    ElementHolder holder = buildElementsForAst(declaration);
-    List<FunctionElement> functions = holder.functions;
-    expect(functions, hasLength(1));
-    FunctionElement function = functions[0];
-    expect(function, isNotNull);
-    expect(function.hasImplicitReturnType, isTrue);
-    expect(function.name, functionName);
-    expect(function.isExternal, isFalse);
-    expect(function.isSynthetic, isFalse);
-    expect(declaration.declaredElement, same(function));
-    expect(expression.declaredElement, same(function));
-    List<TypeParameterElement> typeParameters = function.typeParameters;
-    expect(typeParameters, hasLength(1));
-    TypeParameterElement typeParameter = typeParameters[0];
-    expect(typeParameter, isNotNull);
-    expect(typeParameter.name, typeParameterName);
-  }
-
-  void test_visitMethodDeclaration_abstract() {
-    // m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.emptyFunctionBody());
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(0));
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isTrue);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_duplicateField_synthetic() {
-    buildElementsForText(r'''
-class A {
-  int f;
-  int get f => 42;
-}
-''');
-    ClassDeclaration classNode = compilationUnit.declarations.single;
-    // ClassElement
-    ClassElement classElement = classNode.declaredElement;
-    expect(classElement.fields, hasLength(2));
-    expect(classElement.accessors, hasLength(3));
-    FieldElement notSyntheticFieldElement = classElement.fields
-        .singleWhere((f) => f.displayName == 'f' && !f.isSynthetic);
-    FieldElement syntheticFieldElement = classElement.fields
-        .singleWhere((f) => f.displayName == 'f' && f.isSynthetic);
-    PropertyAccessorElement syntheticGetterElement = classElement.accessors
-        .singleWhere(
-            (a) => a.displayName == 'f' && a.isGetter && a.isSynthetic);
-    PropertyAccessorElement syntheticSetterElement = classElement.accessors
-        .singleWhere(
-            (a) => a.displayName == 'f' && a.isSetter && a.isSynthetic);
-    PropertyAccessorElement notSyntheticGetterElement = classElement.accessors
-        .singleWhere(
-            (a) => a.displayName == 'f' && a.isGetter && !a.isSynthetic);
-    expect(notSyntheticFieldElement.getter, same(syntheticGetterElement));
-    expect(notSyntheticFieldElement.setter, same(syntheticSetterElement));
-    expect(syntheticFieldElement.getter, same(notSyntheticGetterElement));
-    expect(syntheticFieldElement.setter, isNull);
-    // class members nodes and their elements
-    FieldDeclaration fieldDeclNode = classNode.members[0];
-    VariableDeclaration fieldNode = fieldDeclNode.fields.variables.single;
-    MethodDeclaration getterNode = classNode.members[1];
-    expect(fieldNode.declaredElement, notSyntheticFieldElement);
-    expect(getterNode.declaredElement, notSyntheticGetterElement);
-  }
-
-  void test_visitMethodDeclaration_external() {
-    // external m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.emptyFunctionBody());
-    methodDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(0));
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isTrue);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_getter() {
-    // get m() {}
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        Keyword.GET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    methodDeclaration.documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    methodDeclaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.setter, isNull);
-    PropertyAccessorElement getter = field.getter;
-    expect(getter, isNotNull);
-    assertHasCodeRange(getter, 50, 31);
-    expect(getter.documentationComment, '/// aaa');
-    expect(getter.hasImplicitReturnType, isTrue);
-    expect(getter.isAbstract, isFalse);
-    expect(getter.isExternal, isFalse);
-    expect(getter.isGetter, isTrue);
-    expect(getter.isSynthetic, isFalse);
-    expect(getter.name, methodName);
-    expect(getter.variable, field);
-    expect(getter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_getter_abstract() {
-    // get m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        Keyword.GET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.emptyFunctionBody());
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.setter, isNull);
-    PropertyAccessorElement getter = field.getter;
-    expect(getter, isNotNull);
-    expect(getter.hasImplicitReturnType, isTrue);
-    expect(getter.isAbstract, isTrue);
-    expect(getter.isExternal, isFalse);
-    expect(getter.isGetter, isTrue);
-    expect(getter.isSynthetic, isFalse);
-    expect(getter.name, methodName);
-    expect(getter.variable, field);
-    expect(getter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_getter_external() {
-    // external get m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration(
-        null,
-        null,
-        Keyword.GET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList());
-    methodDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.setter, isNull);
-    PropertyAccessorElement getter = field.getter;
-    expect(getter, isNotNull);
-    expect(getter.hasImplicitReturnType, isTrue);
-    expect(getter.isAbstract, isFalse);
-    expect(getter.isExternal, isTrue);
-    expect(getter.isGetter, isTrue);
-    expect(getter.isSynthetic, isFalse);
-    expect(getter.name, methodName);
-    expect(getter.variable, field);
-    expect(getter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_minimal() {
-    // T m() {}
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        AstTestFactory.typeName4('T'),
-        null,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    methodDeclaration.documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    methodDeclaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    assertHasCodeRange(method, 50, 31);
-    expect(method.documentationComment, '/// aaa');
-    expect(method.hasImplicitReturnType, isFalse);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(0));
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_operator() {
-    // operator +(addend) {}
-    String methodName = "+";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        Keyword.OPERATOR,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(
-            [AstTestFactory.simpleFormalParameter3("addend")]),
-        AstTestFactory.blockFunctionBody2());
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(1));
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_setter() {
-    // set m() {}
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        Keyword.SET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    methodDeclaration.documentationComment =
-        AstTestFactory.documentationComment(
-            [TokenFactory.tokenFromString('/// aaa')..offset = 50], []);
-    methodDeclaration.endToken.offset = 80;
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.getter, isNull);
-
-    PropertyAccessorElement setter = field.setter;
-    expect(setter, isNotNull);
-    assertHasCodeRange(setter, 50, 31);
-    expect(setter.documentationComment, '/// aaa');
-    expect(setter.hasImplicitReturnType, isTrue);
-    expect(setter.isAbstract, isFalse);
-    expect(setter.isExternal, isFalse);
-    expect(setter.isSetter, isTrue);
-    expect(setter.isSynthetic, isFalse);
-    expect(setter.name, "$methodName=");
-    expect(setter.displayName, methodName);
-    expect(setter.variable, field);
-    expect(setter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_setter_abstract() {
-    // set m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        Keyword.SET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.emptyFunctionBody());
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.getter, isNull);
-    PropertyAccessorElement setter = field.setter;
-    expect(setter, isNotNull);
-    expect(setter.hasImplicitReturnType, isTrue);
-    expect(setter.isAbstract, isTrue);
-    expect(setter.isExternal, isFalse);
-    expect(setter.isSetter, isTrue);
-    expect(setter.isSynthetic, isFalse);
-    expect(setter.name, "$methodName=");
-    expect(setter.displayName, methodName);
-    expect(setter.variable, field);
-    expect(setter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_setter_external() {
-    // external m();
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration(
-        null,
-        null,
-        Keyword.SET,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList());
-    methodDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<FieldElement> fields = holder.fields;
-    expect(fields, hasLength(1));
-    FieldElement field = fields[0];
-    expect(field, isNotNull);
-    expect(field.name, methodName);
-    expect(field.isSynthetic, isTrue);
-    expect(field.getter, isNull);
-    PropertyAccessorElement setter = field.setter;
-    expect(setter, isNotNull);
-    expect(setter.hasImplicitReturnType, isTrue);
-    expect(setter.isAbstract, isFalse);
-    expect(setter.isExternal, isTrue);
-    expect(setter.isSetter, isTrue);
-    expect(setter.isSynthetic, isFalse);
-    expect(setter.name, "$methodName=");
-    expect(setter.displayName, methodName);
-    expect(setter.variable, field);
-    expect(setter.parameters, hasLength(0));
-  }
-
-  void test_visitMethodDeclaration_static() {
-    // static m() {}
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        Keyword.STATIC,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(0));
-    expect(method.typeParameters, hasLength(0));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isTrue);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMethodDeclaration_typeParameters() {
-    // m<E>() {}
-    String methodName = "m";
-    MethodDeclaration methodDeclaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3(methodName),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    methodDeclaration.typeParameters = AstTestFactory.typeParameterList(['E']);
-
-    ElementHolder holder = buildElementsForAst(methodDeclaration);
-    List<MethodElement> methods = holder.methods;
-    expect(methods, hasLength(1));
-    MethodElement method = methods[0];
-    expect(method, isNotNull);
-    expect(method.hasImplicitReturnType, isTrue);
-    expect(method.name, methodName);
-    expect(method.parameters, hasLength(0));
-    expect(method.typeParameters, hasLength(1));
-    expect(method.isAbstract, isFalse);
-    expect(method.isExternal, isFalse);
-    expect(method.isStatic, isFalse);
-    expect(method.isSynthetic, isFalse);
-  }
-
-  void test_visitMixinDeclaration() {
-    isMixinSupportEnabled = true;
-    var holder = buildElementsForText(r'''
-/// doc
-mixin M<T, U> on A, B implements C {
-  double f;
-  int get g => 0;
-  set s(int v) {}
-  int m(int v) => 0;
-}
-''');
-    var mixins = holder.mixins;
-    expect(mixins, hasLength(1));
-    var type = mixins[0];
-    expect(type.name, 'M');
-    expect(type.isMixin, isTrue);
-    expect(type.documentationComment, '/// doc');
-    assertHasCodeRange(type, 0, 115);
-
-    List<TypeParameterElement> typeParameters = type.typeParameters;
-    expect(typeParameters, hasLength(2));
-    expect(typeParameters[0].name, 'T');
-    expect(typeParameters[1].name, 'U');
-
-    var fields = type.fields;
-    expect(fields, hasLength(3));
-    expect(fields[0].name, 'f');
-    expect(fields[1].name, 'g');
-    expect(fields[2].name, 's');
-
-    var accessors = type.accessors;
-    expect(accessors, hasLength(4));
-    expect(accessors[0].name, 'f');
-    expect(accessors[1].name, 'f=');
-    expect(accessors[2].name, 'g');
-    expect(accessors[3].name, 's=');
-
-    var methods = type.methods;
-    expect(methods, hasLength(1));
-    expect(methods[0].name, 'm');
-  }
-
-  void test_visitTypeAlias_minimal() {
-    String aliasName = "F";
-    TypeAlias typeAlias = AstTestFactory.typeAlias(null, aliasName, null, null);
-    ElementHolder holder = buildElementsForAst(typeAlias);
-    List<FunctionTypeAliasElement> aliases = holder.typeAliases;
-    expect(aliases, hasLength(1));
-    FunctionTypeAliasElement alias = aliases[0];
-    expect(alias, isNotNull);
-    expect(alias.name, aliasName);
-    expect(alias.type, isNotNull);
-    expect(alias.isSynthetic, isFalse);
-  }
-
-  void test_visitTypeAlias_withFormalParameters() {
-    String aliasName = "F";
-    String firstParameterName = "x";
-    String secondParameterName = "y";
-    TypeAlias typeAlias = AstTestFactory.typeAlias(
-        null,
-        aliasName,
-        AstTestFactory.typeParameterList(),
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3(firstParameterName),
-          AstTestFactory.simpleFormalParameter3(secondParameterName)
-        ]));
-    typeAlias.beginToken.offset = 50;
-    typeAlias.endToken.offset = 80;
-    ElementHolder holder = buildElementsForAst(typeAlias);
-    List<FunctionTypeAliasElement> aliases = holder.typeAliases;
-    expect(aliases, hasLength(1));
-    GenericTypeAliasElementImpl alias = aliases[0];
-    expect(alias, isNotNull);
-    assertHasCodeRange(alias, 50, 31);
-    expect(alias.name, aliasName);
-    expect(
-      alias.instantiate2(
-        typeArguments: [],
-        nullabilitySuffix: NullabilitySuffix.none,
-      ),
-      isNotNull,
-    );
-    expect(alias.isSynthetic, isFalse);
-    List<VariableElement> parameters = alias.parameters;
-    expect(parameters, hasLength(2));
-    expect(parameters[0].name, firstParameterName);
-    expect(parameters[1].name, secondParameterName);
-    List<TypeParameterElement> typeParameters = alias.typeParameters;
-    expect(typeParameters, isNotNull);
-    expect(typeParameters, hasLength(0));
-  }
-
-  void test_visitTypeAlias_withTypeParameters() {
-    String aliasName = "F";
-    String firstTypeParameterName = "A";
-    String secondTypeParameterName = "B";
-    TypeAlias typeAlias = AstTestFactory.typeAlias(
-        null,
-        aliasName,
-        AstTestFactory.typeParameterList(
-            [firstTypeParameterName, secondTypeParameterName]),
-        AstTestFactory.formalParameterList());
-    ElementHolder holder = buildElementsForAst(typeAlias);
-    List<FunctionTypeAliasElement> aliases = holder.typeAliases;
-    expect(aliases, hasLength(1));
-    GenericTypeAliasElementImpl alias = aliases[0];
-    expect(alias, isNotNull);
-    expect(alias.name, aliasName);
-    expect(alias.isSynthetic, isFalse);
-    List<VariableElement> parameters = alias.parameters;
-    expect(parameters, isNotNull);
-    expect(parameters, hasLength(0));
-    List<TypeParameterElement> typeParameters = alias.typeParameters;
-    expect(typeParameters, hasLength(2));
-    expect(typeParameters[0].name, firstTypeParameterName);
-    expect(typeParameters[1].name, secondTypeParameterName);
-  }
-
-  void test_visitTypeParameter() {
-    String parameterName = "E";
-    TypeParameter typeParameter = AstTestFactory.typeParameter(parameterName);
-    typeParameter.beginToken.offset = 50;
-    ElementHolder holder = buildElementsForAst(typeParameter);
-    List<TypeParameterElement> typeParameters = holder.typeParameters;
-    expect(typeParameters, hasLength(1));
-    TypeParameterElement typeParameterElement = typeParameters[0];
-    expect(typeParameterElement, isNotNull);
-    assertHasCodeRange(typeParameterElement, 50, 1);
-    expect(typeParameterElement.name, parameterName);
-    expect(typeParameterElement.bound, isNull);
-    expect(typeParameterElement.isSynthetic, isFalse);
-  }
-
-  void _assertHasVariableInitializer(VariableElement element) {
-    expect(element.initializer, isNotNull);
-  }
-}
-
-abstract class _BaseTest extends ParserTestCase {
-  CompilationUnitElement compilationUnitElement;
-  CompilationUnit _compilationUnit;
-  FindNode findNode;
-
-  CompilationUnit get compilationUnit => _compilationUnit;
-
-  void assertHasCodeRange(Element element, int offset, int length) {
-    ElementImpl elementImpl = element;
-    expect(elementImpl.codeOffset, offset);
-    expect(elementImpl.codeLength, length);
-  }
-
-  /**
-   * Build elements using [ApiElementBuilder].
-   */
-  ElementHolder buildElementsForAst(AstNode node) {
-    ElementHolder holder = new ElementHolder();
-    AstVisitor builder = createElementBuilder(holder);
-    node.accept(builder);
-    return holder;
-  }
-
-  /**
-   * Parse the given [code], and build elements using [ApiElementBuilder].
-   */
-  ElementHolder buildElementsForText(String code) {
-    ElementHolder holder = new ElementHolder();
-    AstVisitor builder = createElementBuilder(holder);
-    _visitAstOfCode(code, builder);
-    return holder;
-  }
-
-  /**
-   * Verify that the given [metadata] has exactly one annotation, and that its
-   * [ElementAnnotationImpl] is unresolved.
-   */
-  void checkAnnotation(NodeList<Annotation> metadata) {
-    expect(metadata, hasLength(1));
-    expect(metadata[0], new TypeMatcher<AnnotationImpl>());
-    AnnotationImpl annotation = metadata[0];
-    expect(
-        annotation.elementAnnotation, new TypeMatcher<ElementAnnotationImpl>());
-    ElementAnnotationImpl elementAnnotation = annotation.elementAnnotation;
-    expect(elementAnnotation.element, isNull); // Not yet resolved
-    expect(elementAnnotation.compilationUnit, isNotNull);
-    expect(elementAnnotation.compilationUnit, compilationUnitElement);
-  }
-
-  /**
-   * Verify that the given [element] has exactly one annotation, and that its
-   * [ElementAnnotationImpl] is unresolved.
-   */
-  void checkMetadata(Element element) {
-    expect(element.metadata, hasLength(1));
-    expect(element.metadata[0], new TypeMatcher<ElementAnnotationImpl>());
-    ElementAnnotationImpl elementAnnotation = element.metadata[0];
-    expect(elementAnnotation.element, isNull); // Not yet resolved
-    expect(elementAnnotation.compilationUnit, isNotNull);
-    expect(elementAnnotation.compilationUnit, compilationUnitElement);
-  }
-
-  AstVisitor createElementBuilder(ElementHolder holder);
-
-  LabelElement findLabel(String prefix) {
-    return findNode.simple(prefix).staticElement;
-  }
-
-  FunctionElement findLocalFunction(String search) {
-    return findNode.functionDeclaration(search).declaredElement;
-  }
-
-  LocalVariableElement findLocalVariable(String search) {
-    return findNode.simple(search).staticElement;
-  }
-
-  void setUp() {
-    compilationUnitElement = new CompilationUnitElementImpl();
-  }
-
-  void _assertVisibleRange(LocalElement element, int offset, int end) {
-    SourceRange visibleRange = element.visibleRange;
-    expect(visibleRange.offset, offset);
-    expect(visibleRange.end, end);
-  }
-
-  /**
-   * Parse the given [code], and visit it with the given [visitor].
-   * Fail if any error is logged.
-   */
-  void _visitAstOfCode(String code, AstVisitor visitor) {
-    TestLogger logger = new TestLogger();
-    AnalysisEngine.instance.logger = logger;
-    try {
-      _compilationUnit = parseCompilationUnit(code);
-      findNode = FindNode(code, _compilationUnit);
-      compilationUnit.accept(visitor);
-    } finally {
-      expect(logger.log, hasLength(0));
-      AnalysisEngine.instance.logger = Logger.NULL;
-    }
-  }
-}
diff --git a/pkg/analyzer/test/dart/element/test_all.dart b/pkg/analyzer/test/dart/element/test_all.dart
index 92caf27..a73506a 100644
--- a/pkg/analyzer/test/dart/element/test_all.dart
+++ b/pkg/analyzer/test/dart/element/test_all.dart
@@ -4,13 +4,11 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'builder_test.dart' as builder;
 import 'element_test.dart' as element;
 
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
-    builder.main();
     element.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/embedder_tests.dart b/pkg/analyzer/test/embedder_tests.dart
index 058f4b1..71101ab 100644
--- a/pkg/analyzer/test/embedder_tests.dart
+++ b/pkg/analyzer/test/embedder_tests.dart
@@ -25,11 +25,11 @@
       ..newFolder('/home/.pub-cache/fox/lib')
       ..newFile('/home/.pub-cache/fox/lib/_embedder.yaml', r'''
 embedded_libs:
+  "dart:deep": "deep/directory/file.dart"
   "dart:core" : "core.dart"
   "dart:fox": "slippy.dart"
   "dart:bear": "grizzly.dart"
   "dart:relative": "../relative.dart"
-  "dart:deep": "deep/directory/file.dart"
   "fart:loudly": "nomatter.dart"
 ''');
   }
diff --git a/pkg/analyzer/test/error/error_test.dart b/pkg/analyzer/test/error/error_test.dart
index 8ad29bf..3d0c973 100644
--- a/pkg/analyzer/test/error/error_test.dart
+++ b/pkg/analyzer/test/error/error_test.dart
@@ -87,7 +87,7 @@
       ['lib', 'src', 'dart', 'error', 'todo_codes.dart'],
       ['lib', 'src', 'dart', 'error', 'syntactic_errors.dart'],
       ['lib', 'src', 'error', 'codes.dart'],
-      ['..', 'front_end', 'lib', 'src', 'scanner', 'errors.dart']
+      ['..', '_fe_analyzer_shared', 'lib', 'src', 'scanner', 'errors.dart']
     ];
     for (List<String> path in declaringPaths) {
       for (String declaredCode in getDeclaredCodes(path)) {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index be17274..4e274a6 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1933,79 +1933,6 @@
     ]);
   }
 
-  test_implicitThisReferenceInInitializer_field() async {
-    await assertErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_field2() async {
-    await assertErrorsInCode(r'''
-class A {
-  final x = 0;
-  final y = x;
-}
-''', [
-      error(StrongModeCode.TOP_LEVEL_INSTANCE_GETTER, 37, 1),
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 37, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_invocation() async {
-    await assertErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f();
-  f() {}
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_invocationInStatic() async {
-    await assertErrorsInCode(r'''
-class A {
-  static var F = m();
-  int m() => 0;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 27, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p) {}
-  A.named() : this(f);
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 39, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_superConstructorInvocation() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p) {}
-}
-class B extends A {
-  B() : super(f);
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 56, 1),
-    ]);
-  }
-
   test_importInternalLibrary() async {
     // Note, in these error cases we may generate an UNUSED_IMPORT hint, while
     // we could prevent the hint from being generated by testing the import
@@ -4418,17 +4345,6 @@
     ]);
   }
 
-  test_redirectToNonConstConstructor() async {
-    await assertErrorsInCode(r'''
-class A {
-  A.a() {}
-  const factory A.b() = A.a;
-}
-''', [
-      error(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, 45, 3),
-    ]);
-  }
-
   test_referencedBeforeDeclaration_hideInBlock_comment() async {
     await assertNoErrorsInCode(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index accf42d..c234d8a 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,7 +5,6 @@
 @deprecated
 library analyzer.test.constant_test;
 
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -478,11 +477,7 @@
   Future<void> _assertValueString(String expectedValue, String contents) async {
     var result = await _getExpressionValue(contents);
     DartObject value = result.value;
-    expect(value, isNotNull);
-    ParameterizedType type = value.type;
-    expect(type, isNotNull);
-    expect(type.name, "String");
-    expect(value.toStringValue(), expectedValue);
+    assertElementTypeString(value.type, 'String');
   }
 
   Future<EvaluationResult> _getExpressionValue(String expressionCode,
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
deleted file mode 100644
index e223c2f..0000000
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ /dev/null
@@ -1,761 +0,0 @@
-// 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.
-
-import 'dart:async';
-
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/declaration_resolver.dart';
-import 'package:analyzer/src/generated/parser.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 '../src/dart/resolution/driver_resolution.dart';
-import '../util/element_type_matchers.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(DeclarationResolverMetadataTest);
-    defineReflectiveTests(DeclarationResolverTest);
-  });
-}
-
-CompilationUnit _cloneResolveUnit(CompilationUnit unit) {
-  CompilationUnit clonedUnit = AstCloner.clone(unit);
-  new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
-  return clonedUnit;
-}
-
-@reflectiveTest
-class DeclarationResolverMetadataTest extends DriverResolutionTest {
-  String code;
-  CompilationUnit unit;
-  CompilationUnit unit2;
-
-  void checkMetadata(String search, {bool expectDifferent: false}) {
-    NodeList<Annotation> metadata = _findMetadata(unit, search);
-    NodeList<Annotation> metadata2 = _findMetadata(unit2, search);
-    expect(metadata, isNotEmpty);
-    for (int i = 0; i < metadata.length; i++) {
-      Matcher expectation = same(metadata[i].elementAnnotation);
-      if (expectDifferent) {
-        expectation = isNot(expectation);
-      }
-      expect(metadata2[i].elementAnnotation, expectation);
-    }
-  }
-
-  Future<void> setupCode(String code) async {
-    this.code = code;
-
-    await resolveTestCode(code + ' const a = null;');
-    unit = result.unit;
-    unit2 = _cloneResolveUnit(unit);
-  }
-
-  test_classDeclaration() async {
-    await setupCode('@a class C {}');
-    checkMetadata('C');
-  }
-
-  test_classTypeAlias() async {
-    await setupCode('@a class C = D with E; class D {} class E {}');
-    checkMetadata('C');
-  }
-
-  test_constructorDeclaration_named() async {
-    await setupCode('class C { @a C.x(); }');
-    checkMetadata('x');
-  }
-
-  test_constructorDeclaration_unnamed() async {
-    await setupCode('class C { @a C(); }');
-    checkMetadata('C()');
-  }
-
-  test_declaredIdentifier() async {
-    await setupCode('f(x, y) { for (@a var x in y) {} }');
-    checkMetadata('var', expectDifferent: true);
-  }
-
-  test_enumDeclaration() async {
-    await setupCode('@a enum E { v }');
-    checkMetadata('E');
-  }
-
-  test_enumDeclaration_constant() async {
-    await setupCode('enum E { @a v }');
-    checkMetadata('v');
-  }
-
-  test_exportDirective() async {
-    newFile('/test/lib/foo.dart', content: 'class C {}');
-    await setupCode('@a export "foo.dart";');
-    checkMetadata('export');
-  }
-
-  test_exportDirective_resynthesized() async {
-    await resolveTestCode(r'''
-@a
-export "dart:async";
-
-@b
-export "dart:math";
-
-const a = null;
-const b = null;
-''');
-    unit = result.unit;
-
-    expect(unit.directives[0].metadata.single.name.name, 'a');
-    expect(unit.directives[1].metadata.single.name.name, 'b');
-    var unitElement = unit.declaredElement as CompilationUnitElementImpl;
-
-    // Damage the unit element - as if "setAnnotations" were not called.
-    // The ExportElement(s) still have the metadata, we should use it.
-    unitElement.setAnnotations(unit.directives[0].offset, []);
-    unitElement.setAnnotations(unit.directives[1].offset, []);
-    expect(unitElement.library.exports[0].metadata, hasLength(1));
-    expect(unitElement.library.exports[1].metadata, hasLength(1));
-
-    // DeclarationResolver on the clone should succeed.
-    CompilationUnit clonedUnit = AstCloner.clone(unit);
-    new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
-    expect(unit.directives[0].metadata.single.name.name, 'a');
-    expect(unit.directives[1].metadata.single.name.name, 'b');
-  }
-
-  test_fieldDeclaration() async {
-    await setupCode('class C { @a int x; }');
-    checkMetadata('x');
-  }
-
-  test_fieldFormalParameter() async {
-    await setupCode('class C { var x; C(@a this.x); }');
-    checkMetadata('this');
-  }
-
-  test_fieldFormalParameter_withDefault() async {
-    await setupCode('class C { var x; C([@a this.x = null]); }');
-    checkMetadata('this');
-  }
-
-  test_functionDeclaration_function() async {
-    await setupCode('@a f() {}');
-    checkMetadata('f');
-  }
-
-  test_functionDeclaration_getter() async {
-    await setupCode('@a get f() => null;');
-    checkMetadata('f');
-  }
-
-  test_functionDeclaration_setter() async {
-    await setupCode('@a set f(value) {}');
-    checkMetadata('f');
-  }
-
-  test_functionTypeAlias() async {
-    await setupCode('@a typedef F();');
-    checkMetadata('F');
-  }
-
-  test_functionTypedFormalParameter() async {
-    await setupCode('f(@a g()) {}');
-    checkMetadata('g');
-  }
-
-  test_functionTypedFormalParameter_withDefault() async {
-    await setupCode('f([@a g() = null]) {}');
-    checkMetadata('g');
-  }
-
-  test_importDirective() async {
-    newFile('/test/lib/foo.dart', content: 'class C {}');
-    await setupCode('@a import "foo.dart";');
-    checkMetadata('import');
-  }
-
-  test_importDirective_resynthesized() async {
-    await resolveTestCode(r'''
-@a
-import "dart:async";
-
-@b
-import "dart:math";
-
-const a = null;
-const b = null;
-''');
-    unit = result.unit;
-
-    expect(unit.directives[0].metadata.single.name.name, 'a');
-    expect(unit.directives[1].metadata.single.name.name, 'b');
-    var unitElement = unit.declaredElement as CompilationUnitElementImpl;
-
-    // Damage the unit element - as if "setAnnotations" were not called.
-    // The ImportElement(s) still have the metadata, we should use it.
-    unitElement.setAnnotations(unit.directives[0].offset, []);
-    unitElement.setAnnotations(unit.directives[1].offset, []);
-    expect(unitElement.library.imports[0].metadata, hasLength(1));
-    expect(unitElement.library.imports[1].metadata, hasLength(1));
-
-    // DeclarationResolver on the clone should succeed.
-    CompilationUnit clonedUnit = AstCloner.clone(unit);
-    new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
-    expect(unit.directives[0].metadata.single.name.name, 'a');
-    expect(unit.directives[1].metadata.single.name.name, 'b');
-  }
-
-  test_libraryDirective() async {
-    await setupCode('@a library L;');
-    checkMetadata('L');
-  }
-
-  test_libraryDirective_resynthesized() async {
-    await resolveTestCode('@a library L; const a = null;');
-    unit = result.unit;
-
-    expect(unit.directives.single.metadata.single.name.name, 'a');
-    var unitElement = unit.declaredElement as CompilationUnitElementImpl;
-
-    // Damage the unit element - as if "setAnnotations" were not called.
-    // The LibraryElement still has the metadata, we should use it.
-    unitElement.setAnnotations(unit.directives.single.offset, []);
-    expect(unitElement.library.metadata, hasLength(1));
-
-    // DeclarationResolver on the clone should succeed.
-    CompilationUnit clonedUnit = AstCloner.clone(unit);
-    new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
-    expect(clonedUnit.directives.single.metadata.single.name.name, 'a');
-  }
-
-  test_localFunctionDeclaration() async {
-    await setupCode('f() { @a g() {} }');
-    // Note: metadata on local function declarations is ignored by the
-    // analyzer.  TODO(paulberry): is this a bug?
-    var node = FindNode(code, unit).functionDeclaration('g()');
-    NodeList<Annotation> metadata = node.metadata;
-    if (Parser.useFasta) {
-      expect(metadata, hasLength(1));
-    } else {
-      expect(metadata, isEmpty);
-    }
-  }
-
-  test_localVariableDeclaration() async {
-    await setupCode('f() { @a int x; }');
-    checkMetadata('x', expectDifferent: true);
-  }
-
-  test_methodDeclaration_getter() async {
-    await setupCode('class C { @a get m => null; }');
-    checkMetadata('m');
-  }
-
-  test_methodDeclaration_method() async {
-    await setupCode('class C { @a m() {} }');
-    checkMetadata('m');
-  }
-
-  test_methodDeclaration_setter() async {
-    await setupCode('class C { @a set m(value) {} }');
-    checkMetadata('m');
-  }
-
-  test_partDirective() async {
-    newFile('/test/lib/foo.dart', content: 'part of L;');
-    await setupCode('library L; @a part "foo.dart";');
-    checkMetadata('part');
-  }
-
-  test_partDirective_resynthesized() async {
-    newFile('/test/lib/part_a.dart', content: 'part of L;');
-    newFile('/test/lib/part_b.dart', content: 'part of L;');
-
-    await resolveTestCode(r'''
-library L;
-
-@a
-part "part_a.dart";
-
-@b
-part "part_b.dart";
-
-const a = null;
-const b = null;
-''');
-    unit = result.unit;
-
-    expect(unit.directives[1].metadata.single.name.name, 'a');
-    expect(unit.directives[2].metadata.single.name.name, 'b');
-    var unitElement = unit.declaredElement as CompilationUnitElementImpl;
-
-    // Damage the unit element - as if "setAnnotations" were not called.
-    // The ImportElement(s) still have the metadata, we should use it.
-    unitElement.setAnnotations(unit.directives[1].offset, []);
-    unitElement.setAnnotations(unit.directives[2].offset, []);
-    expect(unitElement.library.parts[0].metadata, hasLength(1));
-    expect(unitElement.library.parts[1].metadata, hasLength(1));
-
-    // DeclarationResolver on the clone should succeed.
-    CompilationUnit clonedUnit = AstCloner.clone(unit);
-    new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
-    expect(unit.directives[1].metadata.single.name.name, 'a');
-    expect(unit.directives[2].metadata.single.name.name, 'b');
-  }
-
-  test_simpleFormalParameter() async {
-    await setupCode('f(@a x) {}) {}');
-    checkMetadata('x');
-  }
-
-  test_simpleFormalParameter_withDefault() async {
-    await setupCode('f([@a x = null]) {}');
-    checkMetadata('x');
-  }
-
-  test_topLevelVariableDeclaration() async {
-    await setupCode('@a int x;');
-    checkMetadata('x');
-  }
-
-  test_typeParameter_ofClass() async {
-    await setupCode('class C<@a T> {}');
-    checkMetadata('T');
-  }
-
-  test_typeParameter_ofClassTypeAlias() async {
-    await setupCode('class C<@a T> = D with E; class D {} class E {}');
-    checkMetadata('T');
-  }
-
-  test_typeParameter_ofFunction() async {
-    await setupCode('f<@a T>() {}');
-    checkMetadata('T');
-  }
-
-  test_typeParameter_ofTypedef() async {
-    await setupCode('typedef F<@a T>();');
-    checkMetadata('T');
-  }
-
-  NodeList<Annotation> _findMetadata(CompilationUnit unit, String search) {
-    var node = FindNode(code, unit).any(search);
-    while (node != null) {
-      if (node is AnnotatedNode && node.metadata.isNotEmpty) {
-        return node.metadata;
-      }
-      if (node is NormalFormalParameter && node.metadata.isNotEmpty) {
-        return node.metadata;
-      }
-      node = node.parent;
-    }
-    fail('Node not found');
-  }
-}
-
-@reflectiveTest
-class DeclarationResolverTest extends DriverResolutionTest {
-  test_closure_inside_catch_block() async {
-    await resolveTestCode('''
-f() {
-  try {
-  } catch (e) {
-    return () => null;
-  }
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_closure_inside_labeled_statement() async {
-    await resolveTestCode('''
-f(b) {
-  foo: while (true) {
-    if (b) {
-      break foo;
-    }
-    return () => null;
-  }
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_closure_inside_switch_case() async {
-    await resolveTestCode('''
-void f(k, m) {
-  switch (k) {
-    case 0:
-      m.forEach((key, value) {});
-    break;
-  }
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_closure_inside_switch_default() async {
-    await resolveTestCode('''
-void f(k, m) {
-  switch (k) {
-    default:
-      m.forEach((key, value) {});
-    break;
-  }
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_functionDeclaration_getter() async {
-    await resolveTestCode(r'''
-int get zzz => 42;
-''');
-    var getterElement = findElement.topGet('zzz');
-    expect(getterElement.isGetter, isTrue);
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var getterName = FindNode(result.content, unit2).simple('zzz =>');
-    expect(getterName.staticElement, same(getterElement));
-  }
-
-  test_functionDeclaration_setter() async {
-    await resolveTestCode(r'''
-void set zzz(_) {}
-''');
-    var setterElement = findElement.topSet('zzz');
-    expect(setterElement.isSetter, isTrue);
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var getterName = FindNode(result.content, unit2).simple('zzz(_)');
-    expect(getterName.staticElement, same(setterElement));
-  }
-
-  test_genericFunction_asFunctionReturnType() async {
-    await resolveTestCode(r'''
-Function(int, String) f() => null;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asGenericFunctionReturnType() async {
-    await resolveTestCode(r'''
-typedef F<T> = int Function(T t, S s) Function<S>(int);
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asMethodReturnType() async {
-    await resolveTestCode(r'''
-class C {
-  Function(int, String) m() => null;
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asParameterReturnType() async {
-    await resolveTestCode(r'''
-f(Function(int, String) p) => null;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTopLevelVariableType() async {
-    await resolveTestCode(r'''
-int Function(int, String) v;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTypeArgument() async {
-    await resolveTestCode(r'''
-List<Function(int)> v;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTypeArgument_lessNodes() async {
-    await resolveTestCode(r'''
-Map<Function<int>> v;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTypeArgument_moreNodes() async {
-    await resolveTestCode(r'''
-List<Function<int>, Function<String>> v;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTypeArgument_noNodes() async {
-    await resolveTestCode(r'''
-List v;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_genericFunction_asTypeArgument_ofInitializer() async {
-    String code = r'''
-var v = <Function(int)>[];
-''';
-    await resolveTestCode(code);
-    var newUnit = _cloneResolveUnit(result.unit);
-    var initializer = FindNode(result.content, newUnit).listLiteral('>[]');
-    expect(initializer.typeArguments.arguments[0].type, isNotNull);
-  }
-
-  test_genericFunction_invalid_missingParameterName() async {
-    await resolveTestCode(r'''
-typedef F = Function({int});
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_invalid_functionDeclaration_getter_inFunction() async {
-    await resolveTestCode(r'''
-var v = (() {
-  main() {
-    int get zzz => 42;
-  }
-});
-''');
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var getterName = FindNode(result.content, unit2).simple('zzz =>');
-
-    // Local getters are not allowed, so a FunctionElement is created.
-    expect(getterName.staticElement, isFunctionElement);
-  }
-
-  test_invalid_functionDeclaration_setter_inFunction() async {
-    await resolveTestCode(r'''
-var v = (() {
-  main() {
-    set zzz(x) {}
-  }
-});
-''');
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var setterName = FindNode(result.content, unit2).simple('zzz(x)');
-
-    // Local getters are not allowed, so a FunctionElement is created.
-    expect(setterName.staticElement, isFunctionElement);
-  }
-
-  test_visitExportDirective_notExistingSource() async {
-    await resolveTestCode(r'''
-export 'foo.dart';
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitExportDirective_unresolvedUri() async {
-    await resolveTestCode(r'''
-export 'package:foo/bar.dart';
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitFunctionExpression() async {
-    await resolveTestCode(r'''
-main(List<String> items) {
-  items.forEach((item) {});
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitGenericTypeAlias_0() async {
-    await resolveTestCode(r'''
-typedef F<T> = Function<S>(List<S> list, Function<A>(A), T);
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitGenericTypeAlias_1() async {
-    await resolveTestCode(r'''
-typedef F = Function({int});
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitGenericTypeAlias_2() async {
-    await resolveTestCode(r'''
-typedef F = int;
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitImportDirective_notExistingSource() async {
-    await resolveTestCode(r'''
-import 'foo.dart';
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitImportDirective_unresolvedUri() async {
-    await resolveTestCode(r'''
-import 'package:foo/bar.dart';
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitMethodDeclaration_getter_duplicate() async {
-    await resolveTestCode(r'''
-class C {
-  int get zzz => 1;
-  String get zzz => null;
-}
-''');
-    var firstElement = findNode.simple('zzz => 1').staticElement;
-    var secondElement = findNode.simple('zzz => null').staticElement;
-    expect(firstElement, isNot(same(secondElement)));
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var findNode2 = FindNode(result.content, unit2);
-    var firstName = findNode2.simple('zzz => 1');
-    var secondName = findNode2.simple('zzz => null');
-    expect(firstName.staticElement, same(firstElement));
-    expect(secondName.staticElement, same(secondElement));
-  }
-
-  test_visitMethodDeclaration_getterSetter() async {
-    await resolveTestCode(r'''
-class C {
-  int _field = 0;
-  int get field => _field;
-  void set field(value) {_field = value;}
-}
-''');
-    var getterElement = findElement.getter('field');
-    var setterElement = findElement.setter('field');
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var findNode2 = FindNode(result.content, unit2);
-    var getterName = findNode2.simple('field =>');
-    var setterName = findNode2.simple('field(value)');
-    expect(getterName.staticElement, same(getterElement));
-    expect(setterName.staticElement, same(setterElement));
-  }
-
-  test_visitMethodDeclaration_method_duplicate() async {
-    await resolveTestCode(r'''
-class C {
-  void zzz(x) {}
-  void zzz(y) {}
-}
-''');
-    MethodElement firstElement = findNode.simple('zzz(x)').staticElement;
-    MethodElement secondElement = findNode.simple('zzz(y)').staticElement;
-    expect(firstElement, isNot(same(secondElement)));
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var findNode2 = FindNode(result.content, unit2);
-    var firstName = findNode2.simple('zzz(x)');
-    var secondName = findNode2.simple('zzz(y)');
-    expect(firstName.staticElement, same(firstElement));
-    expect(secondName.staticElement, same(secondElement));
-  }
-
-  test_visitMethodDeclaration_setter_duplicate() async {
-    // https://github.com/dart-lang/sdk/issues/25601
-    await resolveTestCode(r'''
-class C {
-  set zzz(x) {}
-  set zzz(y) {}
-}
-''');
-    PropertyAccessorElement firstElement =
-        findNode.simple('zzz(x)').staticElement;
-    PropertyAccessorElement secondElement =
-        findNode.simple('zzz(y)').staticElement;
-    expect(firstElement, isNot(same(secondElement)));
-
-    // re-resolve
-    var unit2 = _cloneResolveUnit(result.unit);
-    var findNode2 = FindNode(result.content, unit2);
-    var firstName = findNode2.simple('zzz(x)');
-    var secondName = findNode2.simple('zzz(y)');
-    expect(firstName.staticElement, same(firstElement));
-    expect(secondName.staticElement, same(secondElement));
-  }
-
-  test_visitMethodDeclaration_unaryMinus() async {
-    await resolveTestCode(r'''
-class C {
-  C operator -() => null;
-  C operator -(C other) => null;
-}
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-
-  test_visitPartDirective_notExistingSource() async {
-    await resolveTestCode(r'''
-part 'foo.bar';
-''');
-    // re-resolve
-    _cloneResolveUnit(result.unit);
-    // no other validations than built into DeclarationResolver
-  }
-}
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index fe87f3d..a13cddc 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -34,58 +34,15 @@
     return element;
   }
 
-  FunctionType functionType({
-    List<TypeParameterElement> typeFormals,
-    List<DartType> required,
-    List<DartType> optional,
-    Map<String, DartType> named,
-    DartType returns,
-    NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+  FunctionTypeImpl functionType({
+    @required List<TypeParameterElement> typeFormals,
+    @required List<ParameterElement> parameters,
+    @required DartType returnType,
+    @required NullabilitySuffix nullabilitySuffix,
   }) {
-    if (optional != null && named != null) {
-      throw ArgumentError(
-        'Cannot have both optional positional and named parameters.',
-      );
-    }
-
-    var parameters = <ParameterElement>[];
-    if (required != null) {
-      for (var i = 0; i < required.length; ++i) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            'r$i',
-            required[i],
-            ParameterKind.REQUIRED,
-          ),
-        );
-      }
-    }
-    if (optional != null) {
-      for (var i = 0; i < optional.length; ++i) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            'p$i',
-            optional[i],
-            ParameterKind.POSITIONAL,
-          ),
-        );
-      }
-    }
-    if (named != null) {
-      for (var namedEntry in named.entries) {
-        parameters.add(
-          ParameterElementImpl.synthetic(
-            namedEntry.key,
-            namedEntry.value,
-            ParameterKind.NAMED,
-          ),
-        );
-      }
-    }
-
     return FunctionTypeImpl.synthetic(
-      returns ?? typeProvider.voidType,
-      typeFormals ?? const <TypeParameterElement>[],
+      returnType,
+      typeFormals,
       parameters,
       nullabilitySuffix: nullabilitySuffix,
     );
@@ -96,12 +53,51 @@
     List<DartType> typeArguments = const [],
     NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
   }) {
-    return element.instantiate2(
+    return element.instantiate(
       typeArguments: typeArguments,
       nullabilitySuffix: nullabilitySuffix,
     );
   }
 
+  FunctionTypeImpl functionTypeNone({
+    List<TypeParameterElement> typeFormals = const [],
+    List<ParameterElement> parameters = const [],
+    @required DartType returnType,
+  }) {
+    return functionType(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  FunctionTypeImpl functionTypeQuestion({
+    List<TypeParameterElement> typeFormals = const [],
+    List<ParameterElement> parameters = const [],
+    @required DartType returnType,
+  }) {
+    return functionType(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  FunctionTypeImpl functionTypeStar({
+    List<TypeParameterElement> typeFormals = const [],
+    List<ParameterElement> parameters = const [],
+    @required DartType returnType,
+  }) {
+    return functionType(
+      typeFormals: typeFormals,
+      parameters: parameters,
+      returnType: returnType,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
   DartType futureType(DartType T) {
     var futureElement = typeProvider.futureElement;
     return interfaceType(futureElement, typeArguments: [T]);
@@ -148,31 +144,32 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    var element = MethodElementImpl(name, 0)
+    return MethodElementImpl(name, 0)
       ..isStatic = isStatic
       ..parameters = parameters
       ..returnType = returnType
       ..typeParameters = typeFormals;
-    element.type = _typeOfExecutableElement(element);
-    return element;
   }
 
-  ParameterElement namedParameter(String name, {@required DartType type}) {
+  ParameterElement namedParameter({
+    @required String name,
+    @required DartType type,
+  }) {
     var parameter = ParameterElementImpl(name, 0);
     parameter.parameterKind = ParameterKind.NAMED;
     parameter.type = type;
     return parameter;
   }
 
-  ParameterElement positionalParameter(String name, {@required DartType type}) {
-    var parameter = ParameterElementImpl(name, 0);
+  ParameterElement positionalParameter({String name, @required DartType type}) {
+    var parameter = ParameterElementImpl(name ?? '', 0);
     parameter.parameterKind = ParameterKind.POSITIONAL;
     parameter.type = type;
     return parameter;
   }
 
-  ParameterElement requiredParameter(String name, {@required DartType type}) {
-    var parameter = ParameterElementImpl(name, 0);
+  ParameterElement requiredParameter({String name, @required DartType type}) {
+    var parameter = ParameterElementImpl(name ?? '', 0);
     parameter.parameterKind = ParameterKind.REQUIRED;
     parameter.type = type;
     return parameter;
@@ -193,14 +190,4 @@
       nullabilitySuffix: nullabilitySuffix,
     );
   }
-
-  /// TODO(scheglov) We should do the opposite - build type in the element.
-  /// But build a similar synthetic / structured type.
-  FunctionType _typeOfExecutableElement(ExecutableElement element) {
-    return FunctionTypeImpl.synthetic(
-      element.returnType,
-      element.typeParameters,
-      element.parameters,
-    );
-  }
 }
diff --git a/pkg/analyzer/test/generated/inheritance_manager_test.dart b/pkg/analyzer/test/generated/inheritance_manager_test.dart
deleted file mode 100644
index 2b47aa3..0000000
--- a/pkg/analyzer/test/generated/inheritance_manager_test.dart
+++ /dev/null
@@ -1,1168 +0,0 @@
-// 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.
-
-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/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/source/source_resource.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'test_analysis_context.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(InheritanceManagerTest);
-  });
-}
-
-@reflectiveTest
-class InheritanceManagerTest with ResourceProviderMixin {
-  /**
-   * The type provider used to access the types.
-   */
-  TestTypeProvider _typeProvider;
-
-  /**
-   * The library containing the code being resolved.
-   */
-  LibraryElementImpl _definingLibrary;
-
-  /**
-   * The inheritance manager being tested.
-   */
-  @deprecated
-  InheritanceManager _inheritanceManager;
-
-  /**
-   * The number of members that Object implements (as determined by [TestTypeProvider]).
-   */
-  int _numOfMembersInObject = 0;
-
-  @deprecated
-  void setUp() {
-    _typeProvider = new TestTypeProvider();
-    _inheritanceManager = _createInheritanceManager();
-    InterfaceType objectType = _typeProvider.objectType;
-    _numOfMembersInObject =
-        objectType.methods.length + objectType.accessors.length;
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_accessor_extends() {
-    // class A { int get g; }
-    // class B extends A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[getterName], same(getterG));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_accessor_implements() {
-    // class A { int get g; }
-    // class B implements A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject);
-    expect(mapB[getterName], isNull);
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_accessor_with() {
-    // class A { int get g; }
-    // class B extends Object with A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[getterName], same(getterG));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_implicitExtends() {
-    // class A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_method_extends() {
-    // class A { int g(); }
-    // class B extends A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.supertype = _interfaceType(classA);
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[methodName], same(methodM));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_method_implements() {
-    // class A { int g(); }
-    // class B implements A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject);
-    expect(mapB[methodName], isNull);
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_method_with() {
-    // class A { int g(); }
-    // class B extends Object with A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromClasses(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[methodName], same(methodM));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromClasses_method_with_two_mixins() {
-    // class A1 { int m(); }
-    // class A2 { int m(); }
-    // class B extends Object with A1, A2 {}
-    ClassElementImpl classA1 = ElementFactory.classElement2("A1");
-    String methodName = "m";
-    MethodElement methodA1M =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA1.methods = <MethodElement>[methodA1M];
-    ClassElementImpl classA2 = ElementFactory.classElement2("A2");
-    MethodElement methodA2M =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA2.methods = <MethodElement>[methodA2M];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[
-      _interfaceType(classA1),
-      _interfaceType(classA2)
-    ];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromClasses(classB);
-    expect(mapB[methodName], same(methodA2M));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_accessor_extends() {
-    // class A { int get g; }
-    // class B extends A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[getterName], same(getterG));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_accessor_implements() {
-    // class A { int get g; }
-    // class B implements A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[getterName], same(getterG));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_accessor_with() {
-    // class A { int get g; }
-    // class B extends Object with A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[getterName], same(getterG));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_field_indirectWith() {
-    // class A { int f; }
-    // class B extends A {}
-    // class C extends Object with B {}
-    ClassElementImpl classA = ElementFactory.classElement2('A');
-    String fieldName = "f";
-    FieldElement fieldF = ElementFactory.fieldElement(
-        fieldName, false, false, false, _typeProvider.intType);
-    classA.fields = <FieldElement>[fieldF];
-    classA.accessors = <PropertyAccessorElement>[fieldF.getter, fieldF.setter];
-
-    ClassElementImpl classB =
-        ElementFactory.classElement('B', _interfaceType(classA));
-
-    ClassElementImpl classC = ElementFactory.classElement2('C');
-    classC.mixins = <InterfaceType>[_interfaceType(classB)];
-
-    Map<String, ExecutableElement> mapC =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classC);
-    expect(mapC, hasLength(_numOfMembersInObject + 2));
-    expect(mapC[fieldName], same(fieldF.getter));
-    expect(mapC['$fieldName='], same(fieldF.setter));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_implicitExtends() {
-    // class A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_method_extends() {
-    // class A { int g(); }
-    // class B extends A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[methodName], same(methodM));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_method_implements() {
-    // class A { int g(); }
-    // class B implements A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[methodName], same(methodM));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_method_with() {
-    // class A { int g(); }
-    // class B extends Object with A {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    Map<String, ExecutableElement> mapB =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classB);
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject);
-    expect(mapB.length, _numOfMembersInObject + 1);
-    expect(mapB[methodName], same(methodM));
-  }
-
-  @deprecated
-  void test_getMapOfMembersInheritedFromInterfaces_union_differentNames() {
-    // class I1 { int m1(); }
-    // class I2 { int m2(); }
-    // class A implements I1, I2 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName1 = "m1";
-    MethodElement methodM1 =
-        ElementFactory.methodElement(methodName1, _typeProvider.intType);
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    String methodName2 = "m2";
-    MethodElement methodM2 =
-        ElementFactory.methodElement(methodName2, _typeProvider.intType);
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 2);
-    expect(mapA[methodName1], same(methodM1));
-    expect(mapA[methodName2], same(methodM2));
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_getters() {
-    // class I1 { int get g; }
-    // class I2 { num get g; }
-    // class A implements I1, I2 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String accessorName = "g";
-    PropertyAccessorElement getter1 = ElementFactory.getterElement(
-        accessorName, false, _typeProvider.intType);
-    classI1.accessors = <PropertyAccessorElement>[getter1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement getter2 = ElementFactory.getterElement(
-        accessorName, false, _typeProvider.numType);
-    classI2.accessors = <PropertyAccessorElement>[getter2];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    PropertyAccessorElement syntheticAccessor;
-    syntheticAccessor = ElementFactory.getterElement(
-        accessorName, false, _typeProvider.intType);
-    expect(mapA[accessorName].type, syntheticAccessor.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_methods() {
-    // class I1 { dynamic m(int); }
-    // class I2 { dynamic m(num); }
-    // class A implements I1, I2 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName = "m";
-    MethodElementImpl methodM1 =
-        ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
-    ParameterElementImpl parameter1 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter1.type = _typeProvider.intType;
-    parameter1.parameterKind = ParameterKind.REQUIRED;
-    methodM1.parameters = <ParameterElement>[parameter1];
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElementImpl methodM2 =
-        ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
-    ParameterElementImpl parameter2 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter2.type = _typeProvider.numType;
-    parameter2.parameterKind = ParameterKind.REQUIRED;
-    methodM2.parameters = <ParameterElement>[parameter2];
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    MethodElement syntheticMethod;
-    syntheticMethod = ElementFactory.methodElement(
-        methodName, _typeProvider.dynamicType, [_typeProvider.numType]);
-    expect(mapA[methodName].type, syntheticMethod.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_setters() {
-    // class I1 { set s(int); }
-    // class I2 { set s(num); }
-    // class A implements I1, I2 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String accessorName = "s";
-    PropertyAccessorElement setter1 = ElementFactory.setterElement(
-        accessorName, false, _typeProvider.intType);
-    classI1.accessors = <PropertyAccessorElement>[setter1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement setter2 = ElementFactory.setterElement(
-        accessorName, false, _typeProvider.numType);
-    classI2.accessors = <PropertyAccessorElement>[setter2];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    PropertyAccessorElementImpl syntheticAccessor;
-    syntheticAccessor = ElementFactory.setterElement(
-        accessorName, false, _typeProvider.numType);
-    syntheticAccessor.returnType = VoidTypeImpl.instance;
-    expect(mapA["$accessorName="].type, syntheticAccessor.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_getters() {
-    // class A {}
-    // class B extends A {}
-    // class C extends B {}
-    // class I1 { A get g; }
-    // class I2 { B get g; }
-    // class I3 { C get g; }
-    // class D implements I1, I2, I3 {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    ClassElementImpl classC =
-        ElementFactory.classElement("C", _interfaceType(classB));
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String accessorName = "g";
-    PropertyAccessorElement getter1 = ElementFactory.getterElement(
-        accessorName, false, _interfaceType(classA));
-    classI1.accessors = <PropertyAccessorElement>[getter1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement getter2 = ElementFactory.getterElement(
-        accessorName, false, _interfaceType(classB));
-    classI2.accessors = <PropertyAccessorElement>[getter2];
-    ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    PropertyAccessorElement getter3 = ElementFactory.getterElement(
-        accessorName, false, _interfaceType(classC));
-    classI3.accessors = <PropertyAccessorElement>[getter3];
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    classD.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2),
-      _interfaceType(classI3),
-    ];
-    Map<String, ExecutableElement> mapD =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
-    expect(mapD.length, _numOfMembersInObject + 1);
-    PropertyAccessorElement syntheticAccessor;
-    syntheticAccessor = ElementFactory.getterElement(
-        accessorName, false, _interfaceType(classC));
-    expect(mapD[accessorName].type, syntheticAccessor.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_methods() {
-    // class A {}
-    // class B extends A {}
-    // class C extends B {}
-    // class I1 { dynamic m(A a); }
-    // class I2 { dynamic m(B b); }
-    // class I3 { dynamic m(C c); }
-    // class D implements I1, I2, I3 {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    ClassElementImpl classC =
-        ElementFactory.classElement("C", _interfaceType(classB));
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName = "m";
-    MethodElementImpl methodM1 =
-        ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
-    ParameterElementImpl parameter1 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter1.type = _interfaceType(classA);
-    parameter1.parameterKind = ParameterKind.REQUIRED;
-    methodM1.parameters = <ParameterElement>[parameter1];
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElementImpl methodM2 =
-        ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
-    ParameterElementImpl parameter2 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter2.type = _interfaceType(classB);
-    parameter2.parameterKind = ParameterKind.REQUIRED;
-    methodM2.parameters = <ParameterElement>[parameter2];
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    MethodElementImpl methodM3 =
-        ElementFactory.methodElement(methodName, _typeProvider.dynamicType);
-    ParameterElementImpl parameter3 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a0"));
-    parameter3.type = _interfaceType(classC);
-    parameter3.parameterKind = ParameterKind.REQUIRED;
-    methodM3.parameters = <ParameterElement>[parameter3];
-    classI3.methods = <MethodElement>[methodM3];
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    classD.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2),
-      _interfaceType(classI3)
-    ];
-    Map<String, ExecutableElement> mapD =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
-    expect(mapD.length, _numOfMembersInObject + 1);
-    MethodElement syntheticMethod;
-    syntheticMethod = ElementFactory.methodElement(
-        methodName, _typeProvider.dynamicType, [_interfaceType(classA)]);
-    expect(mapD[methodName].type, syntheticMethod.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_setters() {
-    // class A {}
-    // class B extends A {}
-    // class C extends B {}
-    // class I1 { set s(A); }
-    // class I2 { set s(B); }
-    // class I3 { set s(C); }
-    // class D implements I1, I2, I3 {}
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    ClassElementImpl classC =
-        ElementFactory.classElement("C", _interfaceType(classB));
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String accessorName = "s";
-    PropertyAccessorElement setter1 = ElementFactory.setterElement(
-        accessorName, false, _interfaceType(classA));
-    classI1.accessors = <PropertyAccessorElement>[setter1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    PropertyAccessorElement setter2 = ElementFactory.setterElement(
-        accessorName, false, _interfaceType(classB));
-    classI2.accessors = <PropertyAccessorElement>[setter2];
-    ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    PropertyAccessorElement setter3 = ElementFactory.setterElement(
-        accessorName, false, _interfaceType(classC));
-    classI3.accessors = <PropertyAccessorElement>[setter3];
-    ClassElementImpl classD = ElementFactory.classElement2("D");
-    classD.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2),
-      _interfaceType(classI3)
-    ];
-    Map<String, ExecutableElement> mapD =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classD);
-    expect(mapD.length, _numOfMembersInObject + 1);
-    PropertyAccessorElementImpl syntheticAccessor;
-    syntheticAccessor = ElementFactory.setterElement(
-        accessorName, false, _interfaceType(classA));
-    syntheticAccessor.returnType = VoidTypeImpl.instance;
-    expect(mapD["$accessorName="].type, syntheticAccessor.type);
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() {
-    // class I1 { int m(); }
-    // class I2 { int m([int]); }
-    // class A implements I1, I2 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName = "m";
-    MethodElement methodM1 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElementImpl methodM2 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    ParameterElementImpl parameter1 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a1"));
-    parameter1.type = _typeProvider.intType;
-    parameter1.parameterKind = ParameterKind.POSITIONAL;
-    methodM2.parameters = <ParameterElement>[parameter1];
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    expect(mapA[methodName], same(methodM2));
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() {
-    // class I1 { int m(); }
-    // class I2 { int m([int]); }
-    // class I3 { int m([int, int]); }
-    // class A implements I1, I2, I3 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName = "m";
-    MethodElementImpl methodM1 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElementImpl methodM2 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    ParameterElementImpl parameter1 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a1"));
-    parameter1.type = _typeProvider.intType;
-    parameter1.parameterKind = ParameterKind.POSITIONAL;
-    methodM1.parameters = <ParameterElement>[parameter1];
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    MethodElementImpl methodM3 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    ParameterElementImpl parameter2 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a2"));
-    parameter2.type = _typeProvider.intType;
-    parameter2.parameterKind = ParameterKind.POSITIONAL;
-    ParameterElementImpl parameter3 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a3"));
-    parameter3.type = _typeProvider.intType;
-    parameter3.parameterKind = ParameterKind.POSITIONAL;
-    methodM3.parameters = <ParameterElement>[parameter2, parameter3];
-    classI3.methods = <MethodElement>[methodM3];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2),
-      _interfaceType(classI3)
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    expect(mapA[methodName], same(methodM3));
-  }
-
-  @deprecated
-  void
-      test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() {
-    // class I1 { int m(); }
-    // class I2 { int m(); }
-    // class I3 { int m([int]); }
-    // class I4 { int m([int, int]); }
-    // class A implements I1, I2, I3, I4 {}
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName = "m";
-    MethodElement methodM1 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    MethodElement methodM2 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classI2.methods = <MethodElement>[methodM2];
-    ClassElementImpl classI3 = ElementFactory.classElement2("I3");
-    MethodElementImpl methodM3 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    ParameterElementImpl parameter1 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a1"));
-    parameter1.type = _typeProvider.intType;
-    parameter1.parameterKind = ParameterKind.POSITIONAL;
-    methodM3.parameters = <ParameterElement>[parameter1];
-    classI3.methods = <MethodElement>[methodM3];
-    ClassElementImpl classI4 = ElementFactory.classElement2("I4");
-    MethodElementImpl methodM4 =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    ParameterElementImpl parameter2 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a2"));
-    parameter2.type = _typeProvider.intType;
-    parameter2.parameterKind = ParameterKind.POSITIONAL;
-    ParameterElementImpl parameter3 =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("a3"));
-    parameter3.type = _typeProvider.intType;
-    parameter3.parameterKind = ParameterKind.POSITIONAL;
-    methodM4.parameters = <ParameterElement>[parameter2, parameter3];
-    classI4.methods = <MethodElement>[methodM4];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[
-      _interfaceType(classI1),
-      _interfaceType(classI2),
-      _interfaceType(classI3),
-      _interfaceType(classI4),
-    ];
-    Map<String, ExecutableElement> mapA =
-        _inheritanceManager.getMembersInheritedFromInterfaces(classA);
-    expect(mapA.length, _numOfMembersInObject + 1);
-    expect(mapA[methodName], same(methodM4));
-  }
-
-  @deprecated
-  void test_getMembersInheritedFromClasses_field_indirectWith() {
-    // class A { int f; }
-    // class B extends A {}
-    // class C extends Object with B {}
-    ClassElementImpl classA = ElementFactory.classElement2('A');
-    String fieldName = "f";
-    FieldElement fieldF = ElementFactory.fieldElement(
-        fieldName, false, false, false, _typeProvider.intType);
-    classA.fields = <FieldElement>[fieldF];
-    classA.accessors = <PropertyAccessorElement>[fieldF.getter, fieldF.setter];
-
-    ClassElementImpl classB =
-        ElementFactory.classElement('B', _interfaceType(classA));
-
-    ClassElementImpl classC = ElementFactory.classElement2('C');
-    classC.mixins = <InterfaceType>[_interfaceType(classB)];
-
-    Map<String, ExecutableElement> mapC =
-        _inheritanceManager.getMembersInheritedFromClasses(classC);
-    expect(mapC, hasLength(_numOfMembersInObject));
-  }
-
-  @deprecated
-  void test_lookupInheritance_interface_getter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, getterName),
-        same(getterG));
-  }
-
-  @deprecated
-  void test_lookupInheritance_interface_method() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, methodName),
-        same(methodM));
-  }
-
-  @deprecated
-  void test_lookupInheritance_interface_setter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String setterName = "s";
-    PropertyAccessorElement setterS =
-        ElementFactory.setterElement(setterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setterS];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
-        same(setterS));
-  }
-
-  @deprecated
-  void test_lookupInheritance_interface_staticMember() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    (methodM as MethodElementImpl).isStatic = true;
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_interfaces_infiniteLoop() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_interfaces_infiniteLoop2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classA.interfaces = <InterfaceType>[_interfaceType(classB)];
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_interfaces_union2() {
-    ClassElementImpl classI1 = ElementFactory.classElement2("I1");
-    String methodName1 = "m1";
-    MethodElement methodM1 =
-        ElementFactory.methodElement(methodName1, _typeProvider.intType);
-    classI1.methods = <MethodElement>[methodM1];
-    ClassElementImpl classI2 = ElementFactory.classElement2("I2");
-    String methodName2 = "m2";
-    MethodElement methodM2 =
-        ElementFactory.methodElement(methodName2, _typeProvider.intType);
-    classI2.methods = <MethodElement>[methodM2];
-    classI2.interfaces = <InterfaceType>[_interfaceType(classI1)];
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.interfaces = <InterfaceType>[_interfaceType(classI2)];
-    expect(_inheritanceManager.lookupInheritance(classA, methodName1),
-        same(methodM1));
-    expect(_inheritanceManager.lookupInheritance(classA, methodName2),
-        same(methodM2));
-  }
-
-  @deprecated
-  void test_lookupInheritance_mixin_getter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, getterName),
-        same(getterG));
-  }
-
-  @deprecated
-  void test_lookupInheritance_mixin_method() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, methodName),
-        same(methodM));
-  }
-
-  @deprecated
-  void test_lookupInheritance_mixin_setter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String setterName = "s";
-    PropertyAccessorElement setterS =
-        ElementFactory.setterElement(setterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setterS];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
-        same(setterS));
-  }
-
-  @deprecated
-  void test_lookupInheritance_mixin_staticMember() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    (methodM as MethodElementImpl).isStatic = true;
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.mixins = <InterfaceType>[_interfaceType(classA)];
-    expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_noMember() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    expect(_inheritanceManager.lookupInheritance(classA, "a"), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_getter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    expect(_inheritanceManager.lookupInheritance(classB, getterName),
-        same(getterG));
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_infiniteLoop() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.supertype = _interfaceType(classA);
-    expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_infiniteLoop2() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classA.supertype = _interfaceType(classB);
-    classB.supertype = _interfaceType(classA);
-    expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull);
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_method() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    expect(_inheritanceManager.lookupInheritance(classB, methodName),
-        same(methodM));
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_setter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String setterName = "s";
-    PropertyAccessorElement setterS =
-        ElementFactory.setterElement(setterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setterS];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    expect(_inheritanceManager.lookupInheritance(classB, "$setterName="),
-        same(setterS));
-  }
-
-  @deprecated
-  void test_lookupInheritance_superclass_staticMember() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    (methodM as MethodElementImpl).isStatic = true;
-    classA.methods = <MethodElement>[methodM];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull);
-  }
-
-  @deprecated
-  void test_lookupMember_getter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    expect(_inheritanceManager.lookupMember(classA, getterName), same(getterG));
-  }
-
-  @deprecated
-  void test_lookupMember_getter_static() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String getterName = "g";
-    PropertyAccessorElement getterG =
-        ElementFactory.getterElement(getterName, true, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getterG];
-    expect(_inheritanceManager.lookupMember(classA, getterName), isNull);
-  }
-
-  @deprecated
-  void test_lookupMember_method() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    expect(_inheritanceManager.lookupMember(classA, methodName), same(methodM));
-  }
-
-  @deprecated
-  void test_lookupMember_method_static() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElement methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    (methodM as MethodElementImpl).isStatic = true;
-    classA.methods = <MethodElement>[methodM];
-    expect(_inheritanceManager.lookupMember(classA, methodName), isNull);
-  }
-
-  @deprecated
-  void test_lookupMember_noMember() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    expect(_inheritanceManager.lookupMember(classA, "a"), isNull);
-  }
-
-  @deprecated
-  void test_lookupMember_setter() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String setterName = "s";
-    PropertyAccessorElement setterS =
-        ElementFactory.setterElement(setterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setterS];
-    expect(_inheritanceManager.lookupMember(classA, "$setterName="),
-        same(setterS));
-  }
-
-  @deprecated
-  void test_lookupMember_setter_static() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String setterName = "s";
-    PropertyAccessorElement setterS =
-        ElementFactory.setterElement(setterName, true, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setterS];
-    expect(_inheritanceManager.lookupMember(classA, setterName), isNull);
-  }
-
-  @deprecated
-  void test_lookupOverrides_noParentClasses() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElementImpl methodM =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodM];
-    expect(
-        _inheritanceManager.lookupOverrides(classA, methodName), hasLength(0));
-  }
-
-  @deprecated
-  void test_lookupOverrides_overrideBaseClass() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElementImpl methodMinA =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodMinA];
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", _interfaceType(classA));
-    MethodElementImpl methodMinB =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classB.methods = <MethodElement>[methodMinB];
-    List<ExecutableElement> overrides =
-        _inheritanceManager.lookupOverrides(classB, methodName);
-    expect(overrides, unorderedEquals([methodMinA]));
-  }
-
-  @deprecated
-  void test_lookupOverrides_overrideInterface() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElementImpl methodMinA =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodMinA];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    classB.interfaces = <InterfaceType>[_interfaceType(classA)];
-    MethodElementImpl methodMinB =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classB.methods = <MethodElement>[methodMinB];
-    List<ExecutableElement> overrides =
-        _inheritanceManager.lookupOverrides(classB, methodName);
-    expect(overrides, unorderedEquals([methodMinA]));
-  }
-
-  @deprecated
-  void test_lookupOverrides_overrideTwoInterfaces() {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    String methodName = "m";
-    MethodElementImpl methodMinA =
-        ElementFactory.methodElement(methodName, _typeProvider.intType);
-    classA.methods = <MethodElement>[methodMinA];
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    MethodElementImpl methodMinB =
-        ElementFactory.methodElement(methodName, _typeProvider.doubleType);
-    classB.methods = <MethodElement>[methodMinB];
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    classC.interfaces = <InterfaceType>[
-      _interfaceType(classA),
-      _interfaceType(classB)
-    ];
-    MethodElementImpl methodMinC =
-        ElementFactory.methodElement(methodName, _typeProvider.numType);
-    classC.methods = <MethodElement>[methodMinC];
-    List<ExecutableElement> overrides =
-        _inheritanceManager.lookupOverrides(classC, methodName);
-    expect(overrides, unorderedEquals([methodMinA, methodMinB]));
-  }
-
-  /**
-   * Create the inheritance manager used by the tests.
-   *
-   * @return the inheritance manager that was created
-   */
-  @deprecated
-  InheritanceManager _createInheritanceManager() {
-    AnalysisContext context = TestAnalysisContext();
-    Source source = new FileSource(getFile("/test.dart"));
-    CompilationUnitElementImpl definingCompilationUnit =
-        new CompilationUnitElementImpl();
-    definingCompilationUnit.librarySource =
-        definingCompilationUnit.source = source;
-    _definingLibrary = ElementFactory.library(context, "test");
-    _definingLibrary.definingCompilationUnit = definingCompilationUnit;
-    return new InheritanceManager(_definingLibrary);
-  }
-
-  static InterfaceType _interfaceType(ClassElement element) {
-    return element.instantiate(
-      typeArguments: [],
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-  }
-}
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index f5d274f..c1531fd 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -55,9 +56,12 @@
     await _assertCanBeAnalyzed(r'''
 typedef F = void Function(bool, int a(double b));
 ''');
-    var function = findElement.genericTypeAlias('F').function;
+    var alias = findElement.genericTypeAlias('F');
     assertElementTypeString(
-      function.type,
+      alias.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
       'void Function(bool, int Function(double))',
     );
   }
@@ -122,9 +126,12 @@
     await _assertCanBeAnalyzed(r'''
 typedef void F(int a, this.b);
 ''');
-    var function = findElement.genericTypeAlias('F').function;
+    var alias = findElement.genericTypeAlias('F');
     assertElementTypeString(
-      function.type,
+      alias.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: NullabilitySuffix.star,
+      ),
       'void Function(int, dynamic)',
     );
   }
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 203d6db..658ae27 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -2,10 +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:front_end/src/fasta/messages.dart' show MessageCode;
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/forwarding_listener.dart';
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/messages/codes.dart' show MessageCode;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:test/test.dart';
 
 /**
@@ -58,8 +58,8 @@
   }
 
   @override
-  void beginBlock(Token token) {
-    super.beginBlock(token);
+  void beginBlock(Token token, BlockKind blockKind) {
+    super.beginBlock(token, blockKind);
     begin('Block');
   }
 
@@ -569,9 +569,10 @@
   }
 
   @override
-  void endBlock(int count, Token beginToken, Token endToken) {
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
     end('Block');
-    super.endBlock(count, beginToken, endToken);
+    super.endBlock(count, beginToken, endToken, blockKind);
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 0bb8690..761699e 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.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.
 
+import 'package:_fe_analyzer_shared/src/parser/async_modifier.dart';
+import 'package:_fe_analyzer_shared/src/parser/forwarding_listener.dart'
+    as fasta;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show LanguageVersionToken, ScannerConfiguration, ScannerResult, scanString;
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart'
+    show ErrorToken;
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart' as analyzer;
@@ -16,13 +25,6 @@
 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:front_end/src/fasta/parser/async_modifier.dart';
-import 'package:front_end/src/fasta/parser/forwarding_listener.dart' as fasta;
-import 'package:front_end/src/fasta/parser/parser.dart' as fasta;
-import 'package:front_end/src/fasta/scanner.dart' as fasta;
-import 'package:front_end/src/fasta/scanner.dart'
-    show LanguageVersionToken, ScannerConfiguration, ScannerResult, scanString;
-import 'package:front_end/src/fasta/scanner/error_token.dart' show ErrorToken;
 import 'package:pub_semver/src/version.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -61,6 +63,31 @@
   final tripleShift = FeatureSet.forTesting(
       sdkVersion: '2.0.0', additionalFeatures: [Feature.triple_shift]);
 
+  void test_parse_member_called_late() {
+    CompilationUnitImpl unit = parseCompilationUnit(
+        'class C { void late() { new C().late(); } }',
+        featureSet: nonNullable);
+    ClassDeclaration declaration = unit.declarations[0];
+    MethodDeclaration method = declaration.members[0];
+
+    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);
+
+    BlockFunctionBody body = method.body;
+    ExpressionStatement statement = body.block.statements[0];
+    MethodInvocation invocation = statement.expression;
+    expect(invocation.operator.lexeme, '.');
+    expect(invocation.toSource(), 'new C().late()');
+  }
+
   void test_parseClassMember_operator_gtgtgt() {
     CompilationUnitImpl unit = parseCompilationUnit(
         'class C { bool operator >>>(other) => false; }',
@@ -298,31 +325,6 @@
     VariableDeclaration variable = variables[0];
     expect(variable.name, isNotNull);
   }
-
-  void test_parse_member_called_late() {
-    CompilationUnitImpl unit = parseCompilationUnit(
-        'class C { void late() { new C().late(); } }',
-        featureSet: nonNullable);
-    ClassDeclaration declaration = unit.declarations[0];
-    MethodDeclaration method = declaration.members[0];
-
-    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);
-
-    BlockFunctionBody body = method.body;
-    ExpressionStatement statement = body.block.statements[0];
-    MethodInvocation invocation = statement.expression;
-    expect(invocation.operator.lexeme, '.');
-    expect(invocation.toSource(), 'new C().late()');
-  }
 }
 
 /**
@@ -1640,25 +1642,6 @@
             ));
   }
 
-  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_complex_extends() {
     var unit = parseCompilationUnit(
         'extension E extends A with B, C implements D { }',
@@ -1792,6 +1775,25 @@
     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));
@@ -2097,7 +2099,6 @@
     astBuilder.allowNativeClause = allowNativeClause;
     parser.parseUnit(_fastaTokens);
     CompilationUnitImpl unit = astBuilder.pop();
-    unit.localDeclarations = astBuilder.localDeclarations;
 
     expect(unit, isNotNull);
     return unit;
@@ -2424,6 +2425,20 @@
     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);
+  }
+
   void test_parseFormalParameter_covariant_required_named() {
     ParameterKind kind = ParameterKind.NAMED;
     FormalParameter parameter = parseNNBDFormalParameter(
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index ed1b914..207f917 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.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.
 
+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';
@@ -17,11 +22,6 @@
 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:front_end/src/fasta/scanner.dart'
-    show ScannerResult, scanString;
-import 'package:front_end/src/fasta/scanner/abstract_scanner.dart'
-    show AbstractScanner;
-import 'package:front_end/src/scanner/errors.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index e6f891e..58fc71e 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -4,36 +4,23 @@
 
 import 'dart:collection';
 
-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/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:analyzer/src/source/source_resource.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/dart/resolution/driver_resolution.dart';
-import 'elements_types_mixin.dart';
-import 'parser_test.dart';
 import 'resolver_test_case.dart';
 import 'test_analysis_context.dart';
-import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -45,19 +32,9 @@
     defineReflectiveTests(ScopeTest);
     defineReflectiveTests(StrictModeTest);
     defineReflectiveTests(TypePropagationTest);
-    defineReflectiveTests(TypeResolverVisitorTest);
   });
 }
 
-/// Wrapper around the test package's `fail` function.
-///
-/// Unlike the test package's `fail` function, this function is not annotated
-/// with @alwaysThrows, so we can call it at the top of a test method without
-/// causing the rest of the method to be flagged as dead code.
-void _fail(String message) {
-  fail(message);
-}
-
 @reflectiveTest
 class EnclosedScopeTest extends DriverResolutionTest {
   test_define_duplicate() async {
@@ -484,11 +461,6 @@
   }
 }
 
-class SourceContainer_ChangeSetTest_test_toString implements SourceContainer {
-  @override
-  bool contains(Source source) => false;
-}
-
 /**
  * Instances of the class `StaticTypeVerifier` verify that all of the nodes in an AST
  * structure that should have a static type associated with them do have a static type.
@@ -725,7 +697,7 @@
     sum += list[i];
   }
 }''', [
-      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.MISSING_RETURN, 4, 1),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 3),
     ]);
   }
@@ -738,7 +710,7 @@
     sum += n & 0x0F;
   }
 }''', [
-      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.MISSING_RETURN, 4, 1),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 3),
       error(StaticTypeWarningCode.UNDEFINED_OPERATOR, 76, 1),
     ]);
@@ -823,7 +795,8 @@
   return v; // return
 }''';
     await resolveTestCode(code);
-    assertType(findNode.simple('v; // declare'), 'int');
+    assertElementTypeString(findElement.localVar('v').type, 'int');
+    assertTypeNull(findNode.simple('v; // declare'));
     assertType(findNode.simple('v = null;'), 'int');
     assertType(findNode.simple('v; // return'), 'int');
   }
@@ -848,7 +821,8 @@
   int v = 0;
   return v;
 }''');
-    assertType(findNode.simple('v = 0;'), 'int');
+    assertElementTypeString(findElement.localVar('v').type, 'int');
+    assertTypeNull(findNode.simple('v = 0;'));
     assertType(findNode.simple('v;'), 'int');
   }
 
@@ -858,7 +832,8 @@
   List<int> v = <int>[];
   return v;
 }''');
-    assertType(findNode.simple('v ='), 'List<int>');
+    assertElementTypeString(findElement.localVar('v').type, 'List<int>');
+    assertTypeNull(findNode.simple('v ='));
     assertType(findNode.simple('v;'), 'List<int>');
   }
 
@@ -868,7 +843,8 @@
   int v = null;
   return v;
 }''');
-    assertType(findNode.simple('v ='), 'int');
+    assertElementTypeString(findElement.localVar('v').type, 'int');
+    assertTypeNull(findNode.simple('v ='));
     assertType(findNode.simple('v;'), 'int');
   }
 
@@ -975,7 +951,8 @@
   dynamic toString = () => null;
   toString(); // marker
 }''');
-    assertTypeDynamic(findNode.simple('toString ='));
+    assertElementTypeDynamic(findElement.localVar('toString').type);
+    assertTypeNull(findNode.simple('toString ='));
     assertTypeDynamic(findNode.simple('toString(); // marker'));
   }
 
@@ -990,969 +967,9 @@
   }
 }
 
-@reflectiveTest
-class TypeResolverVisitorTest extends ParserTestCase
-    with ResourceProviderMixin, ElementsTypesMixin {
-  /**
-   * The error listener to which errors will be reported.
-   */
-  GatheringErrorListener _listener;
-
-  /**
-   * The type provider used to access the types.
-   */
-  TestTypeProvider _typeProvider;
-
-  /**
-   * The library scope in which types are to be resolved.
-   */
-  LibraryScope libraryScope;
-
-  /**
-   * The visitor used to resolve types needed to form the type hierarchy.
-   */
-  TypeResolverVisitor _visitor;
-
-  TypeProvider get typeProvider => _typeProvider;
-
-  fail_visitConstructorDeclaration() async {
-    _fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  fail_visitFunctionTypeAlias() async {
-    _fail("Not yet tested");
-    _listener.assertNoErrors();
-  }
-
-  fail_visitVariableDeclaration() async {
-    _fail("Not yet tested");
-    ClassElement type = ElementFactory.classElement2("A");
-    VariableDeclaration node = AstTestFactory.variableDeclaration("a");
-    AstTestFactory.variableDeclarationList(
-        null, AstTestFactory.typeName(type), [node]);
-    //resolve(node);
-    expect(node.name.staticType, interfaceType(type));
-    _listener.assertNoErrors();
-  }
-
-  void setUp() {
-    _listener = new GatheringErrorListener();
-    AnalysisContext context = TestAnalysisContext();
-    Source librarySource = new FileSource(getFile("/lib.dart"));
-    // TODO(paulberry): make it possible to override the feature set so we can
-    // test NNBD features.
-    var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
-    LibraryElementImpl element = new LibraryElementImpl.forNode(
-        context,
-        null,
-        AstTestFactory.libraryIdentifier2(["lib"]),
-        featureSet.isEnabled(Feature.non_nullable));
-    element.definingCompilationUnit = new CompilationUnitElementImpl();
-    _typeProvider = new TestTypeProvider();
-    libraryScope = new LibraryScope(element);
-    _visitor = new TypeResolverVisitor(
-        element, librarySource, _typeProvider, _listener,
-        featureSet: featureSet, nameScope: libraryScope);
-  }
-
-  test_modeApi() async {
-    CompilationUnit unit = parseCompilationUnit(r'''
-class C extends A with A implements A {
-  A f = new A();
-  A m() {
-    A v1;
-  }
-}
-A f([A p = const A()]) {
-  A v2;
-}
-A V = new A();
-''');
-    var unitElement = new CompilationUnitElementImpl();
-    ClassElementImpl A = ElementFactory.classElement2('A');
-
-    // Build API elements.
-    {
-      var holder = new ElementHolder();
-      unit.accept(new ApiElementBuilder(holder, unitElement));
-    }
-
-    // Resolve API types.
-    {
-      AnalysisContext context = TestAnalysisContext();
-      var source = getFile('/test.dart').createSource();
-      // TODO(paulberry): make it possible to override the feature set so we can
-      // test NNBD features.
-      var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
-      var libraryElement = new LibraryElementImpl.forNode(
-          context, null, null, featureSet.isEnabled(Feature.non_nullable))
-        ..definingCompilationUnit = unitElement;
-      var libraryScope = new LibraryScope(libraryElement);
-      var visitor = new TypeResolverVisitor(
-          libraryElement, source, _typeProvider, _listener,
-          featureSet: featureSet,
-          nameScope: libraryScope,
-          mode: TypeResolverMode.api);
-      libraryScope.define(A);
-      unit.accept(visitor);
-    }
-
-    // Top-level: C
-    {
-      var c = unit.declarations[0] as ClassDeclaration;
-
-      // The extends/with/implements types are resolved.
-      expect(c.extendsClause.superclass.toString(), 'A');
-      expect(c.withClause.mixinTypes[0].type.toString(), 'A');
-      expect(c.implementsClause.interfaces[0].type.toString(), 'A');
-
-      {
-        var fd = c.members[0] as FieldDeclaration;
-        // The field type is resolved.
-        expect(fd.fields.type.type.toString(), 'A');
-        // The type in the initializer is not resolved.
-        var f = fd.fields.variables[0];
-        var fi = f.initializer as InstanceCreationExpression;
-        expect(fi.constructorName.type.type, isNull);
-      }
-
-      {
-        var m = c.members[1] as MethodDeclaration;
-        // The return type is resolved.
-        expect(m.returnType.type.toString(), 'A');
-        // The local variable type is not resolved.
-        var body = m.body as BlockFunctionBody;
-        var vd = body.block.statements.single as VariableDeclarationStatement;
-        expect(vd.variables.type.type, isNull);
-      }
-    }
-
-    // Top-level: f
-    {
-      var f = unit.declarations[1] as FunctionDeclaration;
-      FunctionExpression fe = f.functionExpression;
-      // The return type is resolved.
-      expect(f.returnType.type.toString(), 'A');
-      // The parameter type is resolved.
-      var pd = fe.parameters.parameters[0] as DefaultFormalParameter;
-      var p = pd.parameter as SimpleFormalParameter;
-      expect(p.type.type.toString(), 'A');
-      // The parameter default is not resolved.
-      {
-        var pde = pd.defaultValue as InstanceCreationExpression;
-        expect(pde.constructorName.type.type, isNull);
-      }
-      // The local variable type is not resolved.
-      var body = fe.body as BlockFunctionBody;
-      var vd = body.block.statements.single as VariableDeclarationStatement;
-      expect(vd.variables.type.type, isNull);
-    }
-
-    // Top-level: V
-    {
-      var vd = unit.declarations[2] as TopLevelVariableDeclaration;
-      // The type is resolved.
-      expect(vd.variables.type.toString(), 'A');
-      // The initializer is not resolved.
-      VariableDeclaration v = vd.variables.variables[0];
-      var vi = v.initializer as InstanceCreationExpression;
-      expect(vi.constructorName.type.type, isNull);
-    }
-  }
-
-  test_modeLocal_noContext() async {
-    CompilationUnit unit;
-    _resolveTypeModeLocal(r'''
-class C {
-  A f = new A();
-  A m([A p = const A()]) {
-    A v;
-  }
-}
-A f([A p = const A()]) {
-  A v1 = new A();
-  A f2(A p2) {
-    A v2;
-  }
-}
-A V = new A();
-A get G => new A();
-''', (CompilationUnit u) {
-      unit = u;
-      return u;
-    });
-
-    // Top-level: C
-    {
-      var c = unit.declarations[0] as ClassDeclaration;
-      {
-        var fd = c.members[0] as FieldDeclaration;
-        // The type of "f" is not resolved.
-        expect(fd.fields.type.type, isNull);
-        // The initializer of "f" is resolved.
-        var f = fd.fields.variables[0];
-        var fi = f.initializer as InstanceCreationExpression;
-        expect(fi.constructorName.type.type.toString(), 'A');
-      }
-      {
-        var m = c.members[1] as MethodDeclaration;
-        // The return type of "m" is not resolved.
-        expect(m.returnType.type, isNull);
-        // The type of the parameter "p" is not resolved.
-        var pd = m.parameters.parameters[0] as DefaultFormalParameter;
-        var p = pd.parameter as SimpleFormalParameter;
-        expect(p.type.type, isNull);
-        // The default value of the parameter "p" is resolved.
-        var pdd = pd.defaultValue as InstanceCreationExpression;
-        expect(pdd.constructorName.type.type.toString(), 'A');
-        // The type of "v" is resolved.
-        var mb = m.body as BlockFunctionBody;
-        var vd = mb.block.statements[0] as VariableDeclarationStatement;
-        expect(vd.variables.type.type.toString(), 'A');
-      }
-    }
-
-    // Top-level: f
-    {
-      var f = unit.declarations[1] as FunctionDeclaration;
-      // The return type of "f" is not resolved.
-      expect(f.returnType.type, isNull);
-      // The type of the parameter "p" is not resolved.
-      var fe = f.functionExpression;
-      var pd = fe.parameters.parameters[0] as DefaultFormalParameter;
-      var p = pd.parameter as SimpleFormalParameter;
-      expect(p.type.type, isNull);
-      // The default value of the parameter "p" is resolved.
-      var pdd = pd.defaultValue as InstanceCreationExpression;
-      expect(pdd.constructorName.type.type.toString(), 'A');
-      // The type of "v1" is resolved.
-      var fb = fe.body as BlockFunctionBody;
-      var vd = fb.block.statements[0] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'A');
-      // The initializer of "v1" is resolved.
-      var v = vd.variables.variables[0];
-      var vi = v.initializer as InstanceCreationExpression;
-      expect(vi.constructorName.type.type.toString(), 'A');
-      // Local: f2
-      {
-        var f2s = fb.block.statements[1] as FunctionDeclarationStatement;
-        var f2 = f2s.functionDeclaration;
-        // The return type of "f2" is resolved.
-        expect(f2.returnType.type.toString(), 'A');
-        // The type of the parameter "p2" is resolved.
-        var f2e = f2.functionExpression;
-        var p2 = f2e.parameters.parameters[0] as SimpleFormalParameter;
-        expect(p2.type.type.toString(), 'A');
-        // The type of "v2" is resolved.
-        var f2b = f2e.body as BlockFunctionBody;
-        var v2d = f2b.block.statements[0] as VariableDeclarationStatement;
-        expect(v2d.variables.type.type.toString(), 'A');
-      }
-    }
-
-    // Top-level: V
-    {
-      var vd = unit.declarations[2] as TopLevelVariableDeclaration;
-      // The type is not resolved.
-      expect(vd.variables.type.type, isNull);
-      // The initializer is resolved.
-      VariableDeclaration v = vd.variables.variables[0];
-      var vi = v.initializer as InstanceCreationExpression;
-      expect(vi.constructorName.type.type.toString(), 'A');
-    }
-
-    // Top-level: G
-    {
-      var g = unit.declarations[3] as FunctionDeclaration;
-      // The return type is not resolved.
-      expect(g.returnType.type, isNull);
-      // The body is resolved.
-      var gb = g.functionExpression.body as ExpressionFunctionBody;
-      var ge = gb.expression as InstanceCreationExpression;
-      expect(ge.constructorName.type.type.toString(), 'A');
-    }
-  }
-
-  test_modeLocal_withContext_bad_methodBody() async {
-    expect(() {
-      _resolveTypeModeLocal(r'''
-class C<T1> {
-  A m<T2>() {
-    T1 v1;
-    T2 v2;
-  }
-}
-''', (CompilationUnit u) {
-        var c = u.declarations[0] as ClassDeclaration;
-        var m = c.members[0] as MethodDeclaration;
-        var mb = m.body as BlockFunctionBody;
-        return mb;
-      });
-    }, throwsStateError);
-  }
-
-  test_modeLocal_withContext_bad_topLevelVariable_declaration() async {
-    expect(() {
-      _resolveTypeModeLocal(r'''
-var v = new A();
-''', (CompilationUnit u) {
-        var tlv = u.declarations[0] as TopLevelVariableDeclaration;
-        return tlv.variables.variables[0];
-      });
-    }, throwsStateError);
-  }
-
-  test_modeLocal_withContext_bad_topLevelVariable_initializer() async {
-    expect(() {
-      _resolveTypeModeLocal(r'''
-var v = new A();
-''', (CompilationUnit u) {
-        var tlv = u.declarations[0] as TopLevelVariableDeclaration;
-        return tlv.variables.variables[0].initializer;
-      });
-    }, throwsStateError);
-  }
-
-  test_modeLocal_withContext_class() async {
-    ClassDeclaration c;
-    _resolveTypeModeLocal(r'''
-class C<T1> {
-  A m<T2>() {
-    T1 v1;
-    T2 v2;
-  }
-}
-''', (CompilationUnit u) {
-      c = u.declarations[0] as ClassDeclaration;
-      return c;
-    });
-    var m = c.members[0] as MethodDeclaration;
-
-    // The return type of "m" is not resolved.
-    expect(m.returnType.type, isNull);
-
-    var mb = m.body as BlockFunctionBody;
-    var ms = mb.block.statements;
-
-    // The type of "v1" is resolved.
-    {
-      var vd = ms[0] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'T1');
-    }
-
-    // The type of "v2" is resolved.
-    {
-      var vd = ms[1] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'T2');
-    }
-  }
-
-  test_modeLocal_withContext_inClass_constructor() async {
-    ConstructorDeclaration cc;
-    _resolveTypeModeLocal(r'''
-class C<T> {
-  C() {
-    T v1;
-  }
-}
-''', (CompilationUnit u) {
-      var c = u.declarations[0] as ClassDeclaration;
-      cc = c.members[0] as ConstructorDeclaration;
-      return cc;
-    });
-
-    var ccb = cc.body as BlockFunctionBody;
-    var ccs = ccb.block.statements;
-
-    // The type of "v" is resolved.
-    {
-      var vd = ccs[0] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'T');
-    }
-  }
-
-  test_modeLocal_withContext_inClass_method() async {
-    MethodDeclaration m;
-    _resolveTypeModeLocal(r'''
-class C<T1> {
-  A m<T2>() {
-    T1 v1;
-    T2 v2;
-  }
-}
-''', (CompilationUnit u) {
-      var c = u.declarations[0] as ClassDeclaration;
-      m = c.members[0] as MethodDeclaration;
-      return m;
-    });
-
-    // The return type of "m" is not resolved.
-    expect(m.returnType.type, isNull);
-
-    var mb = m.body as BlockFunctionBody;
-    var ms = mb.block.statements;
-
-    // The type of "v1" is resolved.
-    {
-      var vd = ms[0] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'T1');
-    }
-
-    // The type of "v2" is resolved.
-    {
-      var vd = ms[1] as VariableDeclarationStatement;
-      expect(vd.variables.type.type.toString(), 'T2');
-    }
-  }
-
-  test_modeLocal_withContext_topLevelFunction() async {
-    FunctionDeclaration f;
-    _resolveTypeModeLocal(r'''
-A m<T>() {
-  T v;
-}
-''', (CompilationUnit u) {
-      f = u.declarations[0] as FunctionDeclaration;
-      return f;
-    });
-
-    // The return type of "f" is not resolved.
-    expect(f.returnType.type, isNull);
-
-    var fb = f.functionExpression.body as BlockFunctionBody;
-    var fs = fb.block.statements;
-
-    // The type of "v" is resolved.
-    var vd = fs[0] as VariableDeclarationStatement;
-    expect(vd.variables.type.type.toString(), 'T');
-  }
-
-  test_modeLocal_withContext_topLevelVariable() async {
-    TopLevelVariableDeclaration v;
-    _resolveTypeModeLocal(r'''
-A v = new A();
-''', (CompilationUnit u) {
-      v = u.declarations[0] as TopLevelVariableDeclaration;
-      return v;
-    });
-
-    // The type of "v" is not resolved.
-    expect(v.variables.type.type, isNull);
-
-    // The type of "v" initializer is resolved.
-    var vi = v.variables.variables[0].initializer as InstanceCreationExpression;
-    expect(vi.constructorName.type.type.toString(), 'A');
-  }
-
-  test_visitCatchClause_exception() async {
-    // catch (e)
-    CatchClause clause = AstTestFactory.catchClause("e");
-    SimpleIdentifier exceptionParameter = clause.exceptionParameter;
-    exceptionParameter.staticElement =
-        new LocalVariableElementImpl.forNode(exceptionParameter);
-    _resolveCatchClause(clause, _typeProvider.dynamicType, null);
-    _listener.assertNoErrors();
-  }
-
-  test_visitCatchClause_exception_stackTrace() async {
-    // catch (e, s)
-    CatchClause clause = AstTestFactory.catchClause2("e", "s");
-    SimpleIdentifier exceptionParameter = clause.exceptionParameter;
-    exceptionParameter.staticElement =
-        new LocalVariableElementImpl.forNode(exceptionParameter);
-    SimpleIdentifier stackTraceParameter = clause.stackTraceParameter;
-    stackTraceParameter.staticElement =
-        new LocalVariableElementImpl.forNode(stackTraceParameter);
-    _resolveCatchClause(
-        clause, _typeProvider.dynamicType, _typeProvider.stackTraceType);
-    _listener.assertNoErrors();
-  }
-
-  test_visitCatchClause_on_exception() async {
-    // on E catch (e)
-    ClassElement exceptionElement = ElementFactory.classElement2("E");
-    TypeName exceptionType = AstTestFactory.typeName(exceptionElement);
-    CatchClause clause = AstTestFactory.catchClause4(exceptionType, "e");
-    SimpleIdentifier exceptionParameter = clause.exceptionParameter;
-    exceptionParameter.staticElement =
-        new LocalVariableElementImpl.forNode(exceptionParameter);
-    _resolveCatchClause(
-        clause, interfaceType(exceptionElement), null, [exceptionElement]);
-    _listener.assertNoErrors();
-  }
-
-  test_visitCatchClause_on_exception_stackTrace() async {
-    // on E catch (e, s)
-    ClassElement exceptionElement = ElementFactory.classElement2("E");
-    TypeName exceptionType = AstTestFactory.typeName(exceptionElement);
-    (exceptionType.name as SimpleIdentifier).staticElement = exceptionElement;
-    CatchClause clause = AstTestFactory.catchClause5(exceptionType, "e", "s");
-    SimpleIdentifier exceptionParameter = clause.exceptionParameter;
-    exceptionParameter.staticElement =
-        new LocalVariableElementImpl.forNode(exceptionParameter);
-    SimpleIdentifier stackTraceParameter = clause.stackTraceParameter;
-    stackTraceParameter.staticElement =
-        new LocalVariableElementImpl.forNode(stackTraceParameter);
-    _resolveCatchClause(clause, interfaceType(exceptionElement),
-        _typeProvider.stackTraceType, [exceptionElement]);
-    _listener.assertNoErrors();
-  }
-
-  test_visitFieldFormalParameter_functionType() async {
-    InterfaceType intType = _typeProvider.intType;
-    TypeName intTypeName = AstTestFactory.typeName4('int');
-
-    String aName = 'a';
-    SimpleFormalParameterImpl aNode =
-        AstTestFactory.simpleFormalParameter3(aName);
-    aNode.declaredElement = aNode.identifier.staticElement =
-        ElementFactory.requiredParameter(aName);
-
-    String pName = 'p';
-    FormalParameter pNode = AstTestFactory.fieldFormalParameter(
-        null, intTypeName, pName, AstTestFactory.formalParameterList([aNode]));
-    var pElement = ElementFactory.requiredParameter(pName);
-    pNode.identifier.staticElement = pElement;
-
-    FunctionType pType = new FunctionTypeImpl(
-        new GenericFunctionTypeElementImpl.forOffset(-1)
-          ..parameters = [aNode.declaredElement]);
-    pElement.type = pType;
-
-    _resolveFormalParameter(pNode, [intType.element]);
-    expect(pType.returnType, intType);
-    expect(pType.parameters, hasLength(1));
-    _listener.assertNoErrors();
-  }
-
-  test_visitFieldFormalParameter_noType() async {
-    String parameterName = "p";
-    FormalParameter node =
-        AstTestFactory.fieldFormalParameter(Keyword.VAR, null, parameterName);
-    node.identifier.staticElement =
-        ElementFactory.requiredParameter(parameterName);
-    expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType));
-    _listener.assertNoErrors();
-  }
-
-  test_visitFieldFormalParameter_type() async {
-    InterfaceType intType = _typeProvider.intType;
-    TypeName intTypeName = AstTestFactory.typeName4("int");
-    String parameterName = "p";
-    FormalParameter node =
-        AstTestFactory.fieldFormalParameter(null, intTypeName, parameterName);
-    node.identifier.staticElement =
-        ElementFactory.requiredParameter(parameterName);
-    expect(_resolveFormalParameter(node, [intType.element]), intType);
-    _listener.assertNoErrors();
-  }
-
-  test_visitFunctionDeclaration() async {
-    // R f(P p) {}
-    // class R {}
-    // class P {}
-    ClassElement elementR = ElementFactory.classElement2('R');
-    ClassElement elementP = ElementFactory.classElement2('P');
-    FunctionElement elementF = ElementFactory.functionElement('f');
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        AstTestFactory.typeName4('R'),
-        null,
-        'f',
-        AstTestFactory.functionExpression2(
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4('P'), 'p')
-            ]),
-            null));
-    declaration.name.staticElement = elementF;
-    _resolveNode(declaration, [elementR, elementP]);
-    expect(declaration.returnType.type, interfaceType(elementR));
-    SimpleFormalParameter parameter =
-        declaration.functionExpression.parameters.parameters[0];
-    expect(parameter.type.type, interfaceType(elementP));
-    _listener.assertNoErrors();
-  }
-
-  test_visitFunctionDeclaration_typeParameter() async {
-    // E f<E>(E e) {}
-    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
-    FunctionElementImpl elementF = ElementFactory.functionElement('f');
-    elementF.typeParameters = <TypeParameterElement>[elementE];
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        AstTestFactory.typeName4('E'),
-        null,
-        'f',
-        AstTestFactory.functionExpression2(
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4('E'), 'e')
-            ]),
-            null));
-    declaration.name.staticElement = elementF;
-    _resolveNode(declaration, []);
-    expect(declaration.returnType.type, typeParameterType(elementE));
-    SimpleFormalParameter parameter =
-        declaration.functionExpression.parameters.parameters[0];
-    expect(parameter.type.type, typeParameterType(elementE));
-    _listener.assertNoErrors();
-  }
-
-  test_visitFunctionTypedFormalParameter() async {
-    // R f(R g(P p)) {}
-    // class R {}
-    // class P {}
-    ClassElement elementR = ElementFactory.classElement2('R');
-    ClassElement elementP = ElementFactory.classElement2('P');
-
-    SimpleFormalParameter pNode = AstTestFactory.simpleFormalParameter4(
-        AstTestFactory.typeName4('P'), 'p');
-    ParameterElementImpl pElement = ElementFactory.requiredParameter('p');
-    pNode.identifier.staticElement = pElement;
-
-    FunctionTypedFormalParameter gNode =
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4('R'), 'g', [pNode]);
-    ParameterElementImpl gElement = ElementFactory.requiredParameter('g');
-    gNode.identifier.staticElement = gElement;
-
-    FunctionTypeImpl gType = new FunctionTypeImpl(
-        new GenericFunctionTypeElementImpl.forOffset(-1)
-          ..parameters = [pElement]);
-    gElement.type = gType;
-
-    FunctionDeclaration fNode = AstTestFactory.functionDeclaration(
-        AstTestFactory.typeName4('R'),
-        null,
-        'f',
-        AstTestFactory.functionExpression2(
-            AstTestFactory.formalParameterList([gNode]), null));
-    fNode.name.staticElement = ElementFactory.functionElement('f');
-
-    _resolveNode(fNode, [elementR, elementP]);
-
-    expect(fNode.returnType.type, interfaceType(elementR));
-    expect(gType.returnType, interfaceType(elementR));
-    expect(gNode.returnType.type, interfaceType(elementR));
-    expect(pNode.type.type, interfaceType(elementP));
-
-    _listener.assertNoErrors();
-  }
-
-  test_visitFunctionTypedFormalParameter_typeParameter() async {
-    // R f(R g<E>(E e)) {}
-    // class R {}
-    ClassElement elementR = ElementFactory.classElement2('R');
-    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
-
-    SimpleFormalParameterImpl eNode = AstTestFactory.simpleFormalParameter4(
-        AstTestFactory.typeName4('E'), 'e');
-    eNode.declaredElement = ElementFactory.requiredParameter('e');
-
-    FunctionTypedFormalParameter gNode =
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4('R'), 'g', [eNode]);
-    ParameterElementImpl gElement = ElementFactory.requiredParameter('g');
-    gElement.typeParameters = [elementE];
-    gNode.identifier.staticElement = gElement;
-
-    FunctionTypeImpl gType =
-        new FunctionTypeImpl(new GenericFunctionTypeElementImpl.forOffset(-1)
-          ..typeParameters = [elementE]
-          ..parameters = [eNode.declaredElement]);
-    gElement.type = gType;
-
-    FunctionDeclaration fNode = AstTestFactory.functionDeclaration(
-        AstTestFactory.typeName4('R'),
-        null,
-        'f',
-        AstTestFactory.functionExpression2(
-            AstTestFactory.formalParameterList([gNode]), null));
-    fNode.name.staticElement = ElementFactory.functionElement('f');
-
-    _resolveNode(fNode, [elementR]);
-
-    expect(fNode.returnType.type, interfaceType(elementR));
-    expect(gType.returnType, interfaceType(elementR));
-    expect(gNode.returnType.type, interfaceType(elementR));
-    expect(eNode.type.type, typeParameterType(elementE));
-
-    _listener.assertNoErrors();
-  }
-
-  test_visitMethodDeclaration() async {
-    // class A {
-    //   R m(P p) {}
-    // }
-    // class R {}
-    // class P {}
-    ClassElementImpl elementA = ElementFactory.classElement2('A');
-    ClassElement elementR = ElementFactory.classElement2('R');
-    ClassElement elementP = ElementFactory.classElement2('P');
-    MethodElement elementM = ElementFactory.methodElement('m', null);
-    elementA.methods = <MethodElement>[elementM];
-    MethodDeclaration declaration = AstTestFactory.methodDeclaration(
-        null,
-        AstTestFactory.typeName4('R'),
-        null,
-        null,
-        AstTestFactory.identifier3('m'),
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter4(
-              AstTestFactory.typeName4('P'), 'p')
-        ]));
-    declaration.name.staticElement = elementM;
-    _resolveNode(declaration, [elementA, elementR, elementP]);
-    expect(declaration.returnType.type, interfaceType(elementR));
-    SimpleFormalParameter parameter = declaration.parameters.parameters[0];
-    expect(parameter.type.type, interfaceType(elementP));
-    _listener.assertNoErrors();
-  }
-
-  test_visitMethodDeclaration_typeParameter() async {
-    // class A {
-    //   E m<E>(E e) {}
-    // }
-    ClassElementImpl elementA = ElementFactory.classElement2('A');
-    TypeParameterElement elementE = ElementFactory.typeParameterElement('E');
-    MethodElementImpl elementM = ElementFactory.methodElement('m', null);
-    elementM.typeParameters = <TypeParameterElement>[elementE];
-    elementA.methods = <MethodElement>[elementM];
-    MethodDeclaration declaration = AstTestFactory.methodDeclaration(
-        null,
-        AstTestFactory.typeName4('E'),
-        null,
-        null,
-        AstTestFactory.identifier3('m'),
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter4(
-              AstTestFactory.typeName4('E'), 'e')
-        ]));
-    declaration.name.staticElement = elementM;
-    _resolveNode(declaration, [elementA]);
-    expect(declaration.returnType.type, typeParameterType(elementE));
-    SimpleFormalParameter parameter = declaration.parameters.parameters[0];
-    expect(parameter.type.type, typeParameterType(elementE));
-    _listener.assertNoErrors();
-  }
-
-  test_visitSimpleFormalParameter_noType() async {
-    // p
-    SimpleFormalParameterImpl node = AstTestFactory.simpleFormalParameter3("p");
-    node.declaredElement = node.identifier.staticElement =
-        new ParameterElementImpl.forNode(AstTestFactory.identifier3("p"));
-    expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType));
-    _listener.assertNoErrors();
-  }
-
-  test_visitSimpleFormalParameter_type() async {
-    // int p
-    InterfaceType intType = _typeProvider.intType;
-    ClassElement intElement = intType.element;
-    SimpleFormalParameterImpl node = AstTestFactory.simpleFormalParameter4(
-        AstTestFactory.typeName(intElement), "p");
-    SimpleIdentifier identifier = node.identifier;
-    ParameterElementImpl element = new ParameterElementImpl.forNode(identifier);
-    node.declaredElement = identifier.staticElement = element;
-    expect(_resolveFormalParameter(node, [intElement]), intType);
-    _listener.assertNoErrors();
-  }
-
-  test_visitTypeName_noParameters_noArguments() async {
-    ClassElement classA = ElementFactory.classElement2("A");
-    TypeName typeName = AstTestFactory.typeName(classA);
-    typeName.type = null;
-    _resolveNode(typeName, [classA]);
-    expect(typeName.type, interfaceType(classA));
-    _listener.assertNoErrors();
-  }
-
-  test_visitTypeName_noParameters_noArguments_undefined() async {
-    SimpleIdentifier id = AstTestFactory.identifier3("unknown")
-      ..staticElement = new _StaleElement();
-    TypeName typeName = astFactory.typeName(id, null);
-    _resolveNode(typeName, []);
-    expect(typeName.type, DynamicTypeImpl.instance);
-    expect(typeName.name.staticElement, null);
-    _listener.assertErrorsWithCodes([CompileTimeErrorCode.UNDEFINED_CLASS]);
-  }
-
-  test_visitTypeName_parameters_arguments() async {
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classB = ElementFactory.classElement2("B");
-    TypeName typeName =
-        AstTestFactory.typeName(classA, [AstTestFactory.typeName(classB)]);
-    typeName.type = null;
-    _resolveNode(typeName, [classA, classB]);
-    InterfaceType resultType = typeName.type as InterfaceType;
-    expect(resultType.element, same(classA));
-    List<DartType> resultArguments = resultType.typeArguments;
-    expect(resultArguments, hasLength(1));
-    expect(resultArguments[0], interfaceType(classB));
-    _listener.assertNoErrors();
-  }
-
-  test_visitTypeName_parameters_noArguments() async {
-    var tpE = ElementFactory.typeParameterElement('E');
-    tpE.defaultType = DynamicTypeImpl.instance;
-
-    ClassElement classA =
-        ElementFactory.classElement3(name: 'A', typeParameters: [tpE]);
-    TypeName typeName = AstTestFactory.typeName(classA);
-    typeName.type = null;
-    _resolveNode(typeName, [classA]);
-    InterfaceType resultType = typeName.type as InterfaceType;
-    expect(resultType.element, same(classA));
-    List<DartType> resultArguments = resultType.typeArguments;
-    expect(resultArguments, hasLength(1));
-    expect(resultArguments[0], same(DynamicTypeImpl.instance));
-    _listener.assertNoErrors();
-  }
-
-  test_visitTypeName_prefixed_noParameters_noArguments_undefined() async {
-    SimpleIdentifier prefix = AstTestFactory.identifier3("unknownPrefix")
-      ..staticElement = new _StaleElement();
-    SimpleIdentifier suffix = AstTestFactory.identifier3("unknownSuffix")
-      ..staticElement = new _StaleElement();
-    TypeName typeName =
-        astFactory.typeName(AstTestFactory.identifier(prefix, suffix), null);
-    _resolveNode(typeName, []);
-    expect(typeName.type, DynamicTypeImpl.instance);
-    expect(prefix.staticElement, null);
-    expect(suffix.staticElement, null);
-    _listener.assertErrorsWithCodes([CompileTimeErrorCode.UNDEFINED_CLASS]);
-  }
-
-  test_visitTypeName_void() async {
-    ClassElement classA = ElementFactory.classElement2("A");
-    TypeName typeName = AstTestFactory.typeName4("void");
-    _resolveNode(typeName, [classA]);
-    expect(typeName.type, same(VoidTypeImpl.instance));
-    _listener.assertNoErrors();
-  }
-
-  /**
-   * Analyze the given catch clause and assert that the types of the parameters have been set to the
-   * given types. The types can be null if the catch clause does not have the corresponding
-   * parameter.
-   *
-   * @param node the catch clause to be analyzed
-   * @param exceptionType the expected type of the exception parameter
-   * @param stackTraceType the expected type of the stack trace parameter
-   * @param definedElements the elements that are to be defined in the scope in which the element is
-   *          being resolved
-   */
-  void _resolveCatchClause(
-      CatchClause node, DartType exceptionType, InterfaceType stackTraceType,
-      [List<Element> definedElements]) {
-    _resolveNode(node, definedElements);
-    SimpleIdentifier exceptionParameter = node.exceptionParameter;
-    if (exceptionParameter != null) {
-      expect(exceptionParameter.staticType, exceptionType);
-    }
-    SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
-    if (stackTraceParameter != null) {
-      expect(stackTraceParameter.staticType, stackTraceType);
-    }
-  }
-
-  /**
-   * Return the type associated with the given parameter after the static type analyzer has computed
-   * a type for it.
-   *
-   * @param node the parameter with which the type is associated
-   * @param definedElements the elements that are to be defined in the scope in which the element is
-   *          being resolved
-   * @return the type associated with the parameter
-   */
-  DartType _resolveFormalParameter(FormalParameter node,
-      [List<Element> definedElements]) {
-    _resolveNode(node, definedElements);
-    return (node.identifier.staticElement as ParameterElement).type;
-  }
-
-  /**
-   * Return the element associated with the given identifier after the resolver has resolved the
-   * identifier.
-   *
-   * @param node the expression to be resolved
-   * @param definedElements the elements that are to be defined in the scope in which the element is
-   *          being resolved
-   * @return the element to which the expression was resolved
-   */
-  void _resolveNode(AstNode node, [List<Element> definedElements]) {
-    if (definedElements != null) {
-      for (Element element in definedElements) {
-        libraryScope.define(element);
-      }
-    }
-    node.accept(_visitor);
-  }
-
-  /**
-   * Parse the given [code], build elements and resolve in the
-   * [TypeResolverMode.local] mode. The [code] is allowed to use only the type
-   * named `A`.
-   */
-  void _resolveTypeModeLocal(
-      String code, AstNode getNodeToResolve(CompilationUnit unit)) {
-    CompilationUnit unit = parseCompilationUnit2(code);
-    var unitElement = new CompilationUnitElementImpl();
-
-    // Build API elements.
-    {
-      var holder = new ElementHolder();
-      unit.accept(new ElementBuilder(holder, unitElement));
-    }
-
-    // Prepare for resolution.
-    LibraryScope libraryScope;
-    TypeResolverVisitor visitor;
-    {
-      AnalysisContext context = TestAnalysisContext();
-      var source = getFile('/test.dart').createSource();
-      // TODO(paulberry): make it possible to override the feature set so we can
-      // test NNBD features.
-      var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
-      var libraryElement = new LibraryElementImpl.forNode(
-          context, null, null, featureSet.isEnabled(Feature.non_nullable))
-        ..definingCompilationUnit = unitElement;
-      libraryScope = new LibraryScope(libraryElement);
-      visitor = new TypeResolverVisitor(
-          libraryElement, source, _typeProvider, _listener,
-          featureSet: featureSet,
-          nameScope: libraryScope,
-          mode: TypeResolverMode.local);
-    }
-
-    // Define top-level types.
-    ClassElementImpl A = ElementFactory.classElement2('A');
-    libraryScope.define(A);
-
-    // Perform resolution.
-    AstNode nodeToResolve = getNodeToResolve(unit);
-    nodeToResolve.accept(visitor);
-  }
-}
-
 class _RootScope extends Scope {
   @override
   Element internalLookup(Identifier identifier, String name,
           LibraryElement referencingLibrary) =>
       null;
 }
-
-/**
- * Represents an element left over from a previous resolver run.
- *
- * A _StaleElement should always be replaced with either null or a new Element.
- */
-class _StaleElement extends ElementImpl {
-  _StaleElement() : super("_StaleElement", -1);
-
-  @override
-  get kind => throw "_StaleElement's kind shouldn't be accessed";
-
-  @override
-  T accept<T>(_) => throw "_StaleElement shouldn't be visited";
-}
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index cc089a6..8978aa5 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -732,26 +732,24 @@
     }
 
     SimpleIdentifier identifier = findNode.simple(name);
-    // Element is either ExecutableElement or ParameterElement.
     var element = identifier.staticElement;
-    FunctionTypeImpl functionType = (element as dynamic).type;
+    var functionType = _getFunctionTypedElementType(identifier);
     expect(functionType.toString(), type);
-    expect(identifier.staticType.toString(), identifierType);
+    expect(identifier.staticType, isNull);
     expect(typeParameters(element).toString(), elementTypeParams);
-    expect(functionType.typeParameters.toString(), typeParams);
     expect(functionType.typeArguments.toString(), typeArgs);
     expect(functionType.typeFormals.toString(), typeFormals);
     return functionType;
   }
 
   /**
-   * Looks up the identifier with [name] and validates that its type type
+   * Looks up the identifier with [name] and validates that its element type
    * stringifies to [type] and that its generics match the given stringified
    * output.
    */
   FunctionTypeImpl expectFunctionType2(String name, String type) {
-    SimpleIdentifier identifier = findNode.simple(name);
-    FunctionTypeImpl functionType = identifier.staticType;
+    var identifier = findNode.simple(name);
+    var functionType = _getFunctionTypedElementType(identifier);
     expect('$functionType', type);
     return functionType;
   }
@@ -797,6 +795,17 @@
       expect(type, expected);
     }
   }
+
+  FunctionTypeImpl _getFunctionTypedElementType(SimpleIdentifier identifier) {
+    var element = identifier.staticElement;
+    if (element is ExecutableElement) {
+      return element.type;
+    } else if (element is VariableElement) {
+      return element.type;
+    } else {
+      fail('Unexpected element: (${element.runtimeType}) $element');
+    }
+  }
 }
 
 class TestAnalysisResult {
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 6b7c83e..1a32f9c 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_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:_fe_analyzer_shared/src/scanner/error_token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/source/line_info.dart';
@@ -9,7 +10,6 @@
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/scanner/error_token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/generated/source_factory_test.dart b/pkg/analyzer/test/generated/source_factory_test.dart
index ad4c7bd..41aac7a 100644
--- a/pkg/analyzer/test/generated/source_factory_test.dart
+++ b/pkg/analyzer/test/generated/source_factory_test.dart
@@ -6,8 +6,9 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine, Logger;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
@@ -67,15 +68,17 @@
     }
     SourceFactory factory = new SourceFactory(resolvers, packages);
 
-    expect(AnalysisEngine.instance.logger, Logger.NULL);
-    var logger = new TestLogger();
-    AnalysisEngine.instance.logger = logger;
+    expect(AnalysisEngine.instance.instrumentationService,
+        InstrumentationService.NULL_SERVICE);
+    var instrumentor = new TestInstrumentor();
+    AnalysisEngine.instance.instrumentationService = instrumentor;
     try {
       Source source = factory.resolveUri(containingSource, uri);
-      expect(logger.log, []);
+      expect(instrumentor.log, []);
       return source != null ? source.fullName : null;
     } finally {
-      AnalysisEngine.instance.logger = Logger.NULL;
+      AnalysisEngine.instance.instrumentationService =
+          InstrumentationService.NULL_SERVICE;
     }
   }
 
@@ -223,24 +226,6 @@
     expect(new SourceFactory([]), isNotNull);
   }
 
-  void test_fromEncoding_invalidUri() {
-    SourceFactory factory = new SourceFactory([]);
-    expect(() => factory.fromEncoding("<:&%>"), throwsArgumentError);
-  }
-
-  void test_fromEncoding_noResolver() {
-    SourceFactory factory = new SourceFactory([]);
-    expect(() => factory.fromEncoding("foo:/does/not/exist.dart"),
-        throwsArgumentError);
-  }
-
-  void test_fromEncoding_valid() {
-    String encoding = "file:///does/not/exist.dart";
-    SourceFactory factory = new SourceFactory(
-        [new UriResolver_SourceFactoryTest_test_fromEncoding_valid(encoding)]);
-    expect(factory.fromEncoding(encoding), isNotNull);
-  }
-
   void test_resolveUri_absolute() {
     UriResolver_absolute resolver = new UriResolver_absolute();
     SourceFactory factory = new SourceFactory([resolver]);
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index d823202..3e27401 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -1379,7 +1379,6 @@
         AstTestFactory.functionExpression2(parameters, body);
     FunctionElementImpl element = new FunctionElementImpl.forNode(null);
     element.parameters = parameterElements;
-    element.type = new FunctionTypeImpl(element);
     (node as FunctionExpressionImpl).declaredElement = element;
     return node;
   }
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 59ffc3d..033dc53 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -406,7 +406,7 @@
 int f() async {}
 ''', [
       error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
-      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.MISSING_RETURN, 4, 1),
     ]);
   }
 
@@ -428,7 +428,7 @@
   int m() async {}
 }
 ''', [
-      error(HintCode.MISSING_RETURN, 12, 3),
+      error(HintCode.MISSING_RETURN, 16, 1),
       error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 12, 3),
     ]);
   }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 29f2ccc..3b2b23d 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -15,7 +16,6 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/task/strong/ast_properties.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
-import 'package:front_end/src/base/errors.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -3999,13 +3999,9 @@
 C<Object> c = throw '';
 C cD = throw '';
 C<Null> cNu = throw '';
-C<Never> cN = throw '';
 F<Object> f = throw '';
-F<Never> fN = throw '';
 R<F<Object>> rf = throw '';
-R<F<Never>> rfN = throw '';
 R<R<F<Object>>> rrf = throw '';
-R<R<F<Never>>> rrfN = throw '';
 Object obj = throw '';
 F<int> fi = throw '';
 R<F<int>> rfi = throw '';
@@ -4018,13 +4014,6 @@
   c.m1();
   c.m2();
 
-  fN = c.f;
-  fN = c.g;
-  rfN = c.m1;
-  rrfN = c.m2;
-  fN = c.m1();
-  rfN = c.m2();
-
   f = c.f;
   f = c.g;
   rf = c.m1;
@@ -4067,7 +4056,56 @@
   (d.g)(42);
   d.m1()(42);
   d.m2()()(42);
+}
+''');
+    var unit = (await computeAnalysisResult(source)).unit;
+    assertNoErrors(source);
 
+    for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+      _expectCast(s, false);
+    }
+    for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+      _expectCast(s, true);
+    }
+    for (var s in AstFinder.getStatementsInMethod(unit, 'D', 'noCasts')) {
+      _expectCast(s, false);
+    }
+    for (var s in AstFinder.getStatementsInTopLevelFunction(unit, 'noCasts')) {
+      _expectCast(s, false);
+    }
+    for (var s in AstFinder.getStatementsInTopLevelFunction(unit, 'casts')) {
+      _expectCast(s, true);
+    }
+  }
+
+  test_covarianceChecks_returnFunction_never() async {
+    var source = addSource(r'''
+typedef F<T>(T t);
+typedef T R<T>();
+class C<T> {
+  F<T> f = throw '';
+
+  F<T> get g => throw '';
+  F<T> m1() => throw '';
+  R<F<T>> m2() => throw '';
+}
+
+C<Object> c = throw '';
+C<Never> cN = throw '';
+F<Never> fN = throw '';
+R<F<Never>> rfN = throw '';
+R<R<F<Never>>> rrfN = throw '';
+
+casts() {
+  fN = c.f;
+  fN = c.g;
+  rfN = c.m1;
+  rrfN = c.m2;
+  fN = c.m1();
+  rfN = c.m2();
+
+  // The cases below used to be noCasts().
+  // This is a DDC optimization that we do not support anymore.
   cN.f;
   cN.g;
   cN.m1;
@@ -4078,45 +4116,33 @@
     var unit = (await computeAnalysisResult(source)).unit;
     assertNoErrors(source);
 
-    void expectCast(Statement statement, bool hasCast) {
-      var value = (statement as ExpressionStatement).expression;
-      if (value is AssignmentExpression) {
-        value = (value as AssignmentExpression).rightHandSide;
-      }
-      while (value is FunctionExpressionInvocation) {
-        value = (value as FunctionExpressionInvocation).function;
-      }
-      while (value is ParenthesizedExpression) {
-        value = (value as ParenthesizedExpression).expression;
-      }
-      var isCallingGetter =
-          value is MethodInvocation && !value.methodName.name.startsWith('m');
-      var cast = isCallingGetter
-          ? getImplicitOperationCast(value)
-          : getImplicitCast(value);
-      var castKind = isCallingGetter ? 'special cast' : 'cast';
-      expect(cast, hasCast ? isNotNull : isNull,
-          reason: '`$statement` should ' +
-              (hasCast ? '' : 'not ') +
-              'have a $castKind on `$value`.');
-    }
-
-    for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
-      expectCast(s, false);
-    }
-    for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
-      expectCast(s, true);
-    }
-    for (var s in AstFinder.getStatementsInMethod(unit, 'D', 'noCasts')) {
-      expectCast(s, false);
-    }
-    for (var s in AstFinder.getStatementsInTopLevelFunction(unit, 'noCasts')) {
-      expectCast(s, false);
-    }
     for (var s in AstFinder.getStatementsInTopLevelFunction(unit, 'casts')) {
-      expectCast(s, true);
+      _expectCast(s, true);
     }
   }
+
+  void _expectCast(Statement statement, bool hasCast) {
+    var value = (statement as ExpressionStatement).expression;
+    if (value is AssignmentExpression) {
+      value = (value as AssignmentExpression).rightHandSide;
+    }
+    while (value is FunctionExpressionInvocation) {
+      value = (value as FunctionExpressionInvocation).function;
+    }
+    while (value is ParenthesizedExpression) {
+      value = (value as ParenthesizedExpression).expression;
+    }
+    var isCallingGetter =
+        value is MethodInvocation && !value.methodName.name.startsWith('m');
+    var cast = isCallingGetter
+        ? getImplicitOperationCast(value)
+        : getImplicitCast(value);
+    var castKind = isCallingGetter ? 'special cast' : 'cast';
+    expect(cast, hasCast ? isNotNull : isNull,
+        reason: '`$statement` should ' +
+            (hasCast ? '' : 'not ') +
+            'have a $castKind on `$value`.');
+  }
 }
 
 @reflectiveTest
@@ -4657,8 +4683,7 @@
     MethodInvocation f = findNode.methodInvocation('f<int>(3);');
     expect(f.staticInvokeType.toString(), 'S Function(int)');
     FunctionType ft = f.staticInvokeType;
-    expect('${ft.typeArguments}/${ft.typeParameters}',
-        '[S, int]/[T, S extends T]');
+    expect('${ft.typeArguments}', '[S, int]');
 
     expectIdentifierType('f;', 'S Function<Sâ‚€ extends S>(Sâ‚€)');
   }
@@ -5094,7 +5119,7 @@
   return;
 }
 ''', [
-      error(HintCode.MISSING_RETURN, 0, 2),
+      error(HintCode.MISSING_RETURN, 3, 1),
       error(HintCode.UNUSED_LOCAL_VARIABLE, 69, 1),
       error(StrongModeCode.COULD_NOT_INFER, 73, 1),
     ]);
diff --git a/pkg/analyzer/test/generated/test_all.dart b/pkg/analyzer/test/generated/test_all.dart
index 8f0cb6f..f3db5e9 100644
--- a/pkg/analyzer/test/generated/test_all.dart
+++ b/pkg/analyzer/test/generated/test_all.dart
@@ -10,11 +10,9 @@
 import 'compile_time_error_code_test.dart' as compile_time_error_code;
 // ignore: deprecated_member_use_from_same_package
 import 'constant_test.dart' as constant_test;
-import 'declaration_resolver_test.dart' as declaration_resolver_test;
 import 'element_resolver_test.dart' as element_resolver_test;
 import 'engine_test.dart' as engine_test;
 import 'error_suppression_test.dart' as error_suppression;
-import 'inheritance_manager_test.dart' as inheritance_manager_test;
 import 'invalid_code_test.dart' as invalid_code;
 import 'issues_test.dart' as issues;
 import 'java_core_test.dart' as java_core_test;
@@ -42,11 +40,9 @@
     checked_mode_compile_time_error_code.main();
     compile_time_error_code.main();
     constant_test.main();
-    declaration_resolver_test.main();
     element_resolver_test.main();
     engine_test.main();
     error_suppression.main();
-    inheritance_manager_test.main();
     invalid_code.main();
     issues.main();
     java_core_test.main();
diff --git a/pkg/analyzer/test/generated/test_support.dart b/pkg/analyzer/test/generated/test_support.dart
index 4b73b9c..73583f8 100644
--- a/pkg/analyzer/test/generated/test_support.dart
+++ b/pkg/analyzer/test/generated/test_support.dart
@@ -5,9 +5,8 @@
 import 'package:analyzer/diagnostic/diagnostic.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:test/test.dart';
@@ -357,19 +356,26 @@
   }
 }
 
-/// Instances of the class [TestLogger] implement a logger that can be used by
-/// tests.
-class TestLogger implements Logger {
+/// Instances of the class [TestInstrumentor] implement an instrumentation
+/// service that can be used by tests.
+class TestInstrumentor extends InstrumentationService {
   /// All logged messages.
   List<String> log = [];
 
+  TestInstrumentor() : super(null);
+
   @override
-  void logError(String message, [CaughtException exception]) {
+  void logError(String message) {
     log.add("error: $message");
   }
 
   @override
-  void logInformation(String message, [CaughtException exception]) {
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    log.add("error: $exception $stackTrace");
+  }
+
+  @override
+  void logInfo(String message, [dynamic exception]) {
     log.add("info: $message");
   }
 }
@@ -432,9 +438,6 @@
   }
 
   bool exists() => exists2;
-  void getContentsToReceiver(Source_ContentReceiver receiver) {
-    throw new UnsupportedError('getContentsToReceiver');
-  }
 
   Source resolve(String uri) {
     throw new UnsupportedError('resolve');
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 19384d1..ff7a764 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/token.dart' show KeywordToken;
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -36,8 +37,6 @@
     defineReflectiveTests(GreatestLowerBoundTest);
     defineReflectiveTests(LeastUpperBoundFunctionsTest);
     defineReflectiveTests(LeastUpperBoundTest);
-    defineReflectiveTests(NonNullableSubtypingTest);
-    defineReflectiveTests(SubtypingTest);
     defineReflectiveTests(TypeSystemTest);
   });
 }
@@ -198,12 +197,10 @@
     List<TypeParameterElement> typeFormals = const [],
     List<ParameterElement> parameters = const [],
   }) {
-    var element = MethodElementImpl(name, 0)
+    return MethodElementImpl(name, 0)
       ..parameters = parameters
       ..returnType = returnType
       ..typeParameters = typeFormals;
-    element.type = _typeOfExecutableElement(element);
-    return element;
   }
 
   ParameterElement _requiredParameter(String name, DartType type) {
@@ -213,16 +210,6 @@
     return parameter;
   }
 
-  /// TODO(scheglov) We should do the opposite - build type in the element.
-  /// But build a similar synthetic / structured type.
-  FunctionType _typeOfExecutableElement(ExecutableElement element) {
-    return FunctionTypeImpl.synthetic(
-      element.returnType,
-      element.typeParameters,
-      element.parameters,
-    );
-  }
-
   TypeParameterElementImpl _typeParameter(String name, {DartType bound}) {
     var element = TypeParameterElementImpl.synthetic(name);
     element.bound = bound;
@@ -2693,603 +2680,6 @@
   }
 }
 
-@reflectiveTest
-class NonNullableSubtypingTest extends SubtypingTestBase {
-  @override
-  FeatureSet get testFeatureSet {
-    return FeatureSet.forTesting(
-      additionalFeatures: [Feature.non_nullable],
-    );
-  }
-
-  void test_dynamicType() {
-    List<DartType> equivalents = <DartType>[
-      voidType,
-      _question(objectType),
-      _star(objectType),
-    ];
-    List<DartType> subtypes = <DartType>[bottomType, nullType, objectType];
-    _checkGroups(dynamicType, equivalents: equivalents, subtypes: subtypes);
-  }
-
-  @failingTest
-  void test_futureOr_topTypes() {
-    var objectStar =
-        (objectType as TypeImpl).withNullability(NullabilitySuffix.star);
-    var objectQuestion =
-        (objectType as TypeImpl).withNullability(NullabilitySuffix.question);
-    var futureOrObject = futureOrType(objectType);
-    var futureOrObjectStar = futureOrType(objectStar);
-    var futureOrObjectQuestion = futureOrType(objectQuestion);
-    var futureOrStarObject =
-        (futureOrObject as TypeImpl).withNullability(NullabilitySuffix.star);
-    var futureOrQuestionObject = (futureOrObject as TypeImpl)
-        .withNullability(NullabilitySuffix.question);
-    var futureOrStarObjectStar = (futureOrObjectStar as TypeImpl)
-        .withNullability(NullabilitySuffix.star);
-    var futureOrQuestionObjectStar = (futureOrObjectStar as TypeImpl)
-        .withNullability(NullabilitySuffix.question);
-    var futureOrStarObjectQuestion = (futureOrObjectQuestion as TypeImpl)
-        .withNullability(NullabilitySuffix.star);
-    var futureOrQuestionObjectQuestion = (futureOrObjectQuestion as TypeImpl)
-        .withNullability(NullabilitySuffix.question);
-
-    //FutureOr<Object> <: FutureOr*<Object?>
-    _checkGroups(futureOrObject, equivalents: [
-      objectStar,
-      futureOrObjectStar,
-      futureOrStarObject,
-      futureOrStarObjectStar,
-      objectType
-    ], subtypes: [], supertypes: [
-      objectQuestion,
-      futureOrQuestionObject,
-      futureOrObjectQuestion,
-      futureOrQuestionObject,
-      futureOrQuestionObjectStar,
-      futureOrStarObjectQuestion,
-      futureOrQuestionObjectQuestion,
-    ]);
-  }
-
-  void test_int_nullableTypes() {
-    List<DartType> equivalents = <DartType>[
-      intType,
-      _star(intType),
-    ];
-    List<DartType> subtypes = <DartType>[
-      bottomType,
-    ];
-    List<DartType> supertypes = <DartType>[
-      _question(intType),
-      objectType,
-      _question(objectType),
-    ];
-    List<DartType> unrelated = <DartType>[
-      doubleType,
-      nullType,
-      _star(nullType),
-      _question(nullType),
-      _question(bottomType),
-    ];
-    _checkGroups(intType,
-        equivalents: equivalents,
-        supertypes: supertypes,
-        unrelated: unrelated,
-        subtypes: subtypes);
-  }
-
-  void test_intQuestion_nullableTypes() {
-    List<DartType> equivalents = <DartType>[
-      _question(intType),
-      _star(intType),
-    ];
-    List<DartType> subtypes = <DartType>[
-      intType,
-      nullType,
-      _question(nullType),
-      _star(nullType),
-      bottomType,
-      _question(bottomType),
-      _star(bottomType),
-    ];
-    List<DartType> supertypes = <DartType>[
-      _question(numType),
-      _star(numType),
-      _question(objectType),
-      _star(objectType),
-    ];
-    List<DartType> unrelated = <DartType>[doubleType, numType, objectType];
-    _checkGroups(_question(intType),
-        equivalents: equivalents,
-        supertypes: supertypes,
-        unrelated: unrelated,
-        subtypes: subtypes);
-  }
-
-  void test_intStar_nullableTypes() {
-    List<DartType> equivalents = <DartType>[
-      intType,
-      _question(intType),
-      _star(intType),
-    ];
-    List<DartType> subtypes = <DartType>[
-      nullType,
-      _star(nullType),
-      _question(nullType),
-      bottomType,
-      _star(bottomType),
-      _question(bottomType),
-    ];
-    List<DartType> supertypes = <DartType>[
-      numType,
-      _question(numType),
-      _star(numType),
-      objectType,
-      _question(objectType),
-    ];
-    List<DartType> unrelated = <DartType>[doubleType];
-    _checkGroups(_star(intType),
-        equivalents: equivalents,
-        supertypes: supertypes,
-        unrelated: unrelated,
-        subtypes: subtypes);
-  }
-
-  void test_nullType() {
-    List<DartType> equivalents = <DartType>[
-      nullType,
-      _question(nullType),
-      _star(nullType),
-      _question(bottomType),
-    ];
-    List<DartType> supertypes = <DartType>[
-      _question(intType),
-      _star(intType),
-      _question(objectType),
-      _star(objectType),
-      dynamicType,
-      voidType,
-    ];
-    List<DartType> subtypes = <DartType>[bottomType];
-    List<DartType> unrelated = <DartType>[
-      doubleType,
-      intType,
-      numType,
-      objectType,
-    ];
-
-    for (final formOfNull in equivalents) {
-      _checkGroups(formOfNull,
-          equivalents: equivalents,
-          supertypes: supertypes,
-          unrelated: unrelated,
-          subtypes: subtypes);
-    }
-  }
-
-  void test_objectType() {
-    List<DartType> equivalents = <DartType>[
-      _star(objectType),
-    ];
-    List<DartType> supertypes = <DartType>[
-      _question(objectType),
-      dynamicType,
-      voidType,
-    ];
-    List<DartType> subtypes = <DartType>[bottomType];
-    List<DartType> unrelated = <DartType>[
-      _question(doubleType),
-      _question(numType),
-      _question(intType),
-      nullType,
-    ];
-    _checkGroups(objectType,
-        equivalents: equivalents,
-        supertypes: supertypes,
-        unrelated: unrelated,
-        subtypes: subtypes);
-  }
-
-  DartType _question(DartType dartType) =>
-      (dartType as TypeImpl).withNullability(NullabilitySuffix.question);
-
-  DartType _star(DartType dartType) =>
-      (dartType as TypeImpl).withNullability(NullabilitySuffix.star);
-}
-
-@reflectiveTest
-class SubtypingTest extends SubtypingTestBase {
-  void test_bottom_isBottom() {
-    var A = _class(name: 'A');
-    List<DartType> equivalents = <DartType>[bottomType];
-    List<DartType> supertypes = <DartType>[
-      dynamicType,
-      objectType,
-      intType,
-      doubleType,
-      numType,
-      stringType,
-      functionType,
-      _interfaceType(A),
-    ];
-    _checkGroups(bottomType, equivalents: equivalents, supertypes: supertypes);
-  }
-
-  void test_call_method() {
-    var A = _class(name: 'A', methods: [
-      _method('call', objectType, parameters: [
-        _requiredParameter('_', intType),
-      ]),
-    ]);
-
-    _checkIsNotSubtypeOf(
-      _interfaceType(A),
-      _functionType(required: [intType], returns: objectType),
-    );
-  }
-
-  void test_classes() {
-    var A = _class(name: 'A');
-    var typeA = _interfaceType(A);
-
-    var B = _class(name: 'B', superType: typeA);
-    var typeB = _interfaceType(B);
-
-    var C = _class(name: 'C', superType: typeA);
-    var typeC = _interfaceType(C);
-
-    var D = _class(
-      name: 'D',
-      superType: _interfaceType(B),
-      interfaces: [typeC],
-    );
-    var typeD = _interfaceType(D);
-
-    _checkLattice(typeA, typeB, typeC, typeD);
-  }
-
-  void test_double() {
-    List<DartType> equivalents = <DartType>[doubleType];
-    List<DartType> supertypes = <DartType>[numType];
-    List<DartType> unrelated = <DartType>[intType];
-    _checkGroups(doubleType,
-        equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
-  }
-
-  void test_dynamic_isTop() {
-    var A = _class(name: 'A');
-    List<DartType> equivalents = <DartType>[dynamicType, objectType, voidType];
-    List<DartType> subtypes = <DartType>[
-      intType,
-      doubleType,
-      numType,
-      stringType,
-      functionType,
-      _interfaceType(A),
-      bottomType,
-    ];
-    _checkGroups(dynamicType, equivalents: equivalents, subtypes: subtypes);
-  }
-
-  void test_function_subtypes_itself_top_types() {
-    var tops = [dynamicType, objectType, voidType];
-    // Add FutureOr<T> for T := dynamic, object, void
-    tops.addAll(tops.map((t) => futureOrType(t)).toList());
-    // Add FutureOr<FutureOr<T>> for T := dynamic, object, void
-    tops.addAll(tops.skip(3).map((t) => futureOrType(t)).toList());
-
-    // Function should subtype all of those top types.
-    _checkGroups(functionType, supertypes: [
-      dynamicType,
-      objectType,
-      voidType,
-    ]);
-
-    // Create a non-identical but equal copy of Function, and verify subtyping
-    var copyOfFunction = _interfaceType(functionType.element);
-    _checkEquivalent(functionType, copyOfFunction);
-  }
-
-  void test_genericFunction_generic_monomorphic() {
-    var S = _typeParameter('S');
-    var T = _typeParameter('T', bound: _typeParameterType(S));
-    var U = _typeParameter('U', bound: intType);
-    var V = _typeParameter('V', bound: _typeParameterType(U));
-
-    var A = _typeParameter('A');
-    var B = _typeParameter('B', bound: _typeParameterType(A));
-    var C = _typeParameter('C', bound: intType);
-    var D = _typeParameter('D', bound: _typeParameterType(C));
-
-    _checkIsStrictSubtypeOf(
-      _functionType(
-        typeFormals: [S, T],
-        required: [_typeParameterType(S)],
-        returns: _typeParameterType(T),
-      ),
-      _functionType(
-        typeFormals: [A, B],
-        required: [bottomType],
-        returns: dynamicType,
-      ),
-    );
-
-    _checkIsNotSubtypeOf(
-      _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(V),
-      ),
-      _functionType(
-        typeFormals: [C, D],
-        required: [objectType],
-        returns: objectType,
-      ),
-    );
-
-    _checkIsNotSubtypeOf(
-      _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(V),
-      ),
-      _functionType(
-        typeFormals: [C, D],
-        required: [intType],
-        returns: intType,
-      ),
-    );
-  }
-
-  void test_genericFunction_genericDoesNotSubtypeNonGeneric() {
-    var S = _typeParameter('S');
-    var T = _typeParameter('T', bound: _typeParameterType(S));
-    var U = _typeParameter('U', bound: intType);
-    var V = _typeParameter('V', bound: _typeParameterType(U));
-
-    _checkIsNotSubtypeOf(
-      _functionType(
-        typeFormals: [S, T],
-        required: [_typeParameterType(S)],
-        returns: _typeParameterType(T),
-      ),
-      _functionType(required: [dynamicType], returns: dynamicType),
-    );
-
-    _checkIsNotSubtypeOf(
-      _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(V),
-      ),
-      _functionType(required: [objectType], returns: objectType),
-    );
-
-    _checkIsNotSubtypeOf(
-      _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(V),
-      ),
-      _functionType(required: [intType], returns: intType),
-    );
-  }
-
-  void test_genericFunction_simple() {
-    var S = _typeParameter('S');
-    var T = _typeParameter('T');
-
-    _checkEquivalent(
-      _functionType(typeFormals: [T]),
-      _functionType(typeFormals: [S]),
-    );
-
-    _checkEquivalent(
-      _functionType(
-        typeFormals: [T],
-        required: [_typeParameterType(T)],
-        returns: _typeParameterType(T),
-      ),
-      _functionType(
-        typeFormals: [S],
-        required: [_typeParameterType(S)],
-        returns: _typeParameterType(S),
-      ),
-    );
-  }
-
-  void test_genericFunction_simple_bounded() {
-    var S = _typeParameter('S');
-    var T = _typeParameter('T', bound: _typeParameterType(S));
-    var U = _typeParameter('U');
-    var V = _typeParameter('V', bound: _typeParameterType(U));
-
-    _checkEquivalent(
-      _functionType(typeFormals: [S, T]),
-      _functionType(typeFormals: [U, V]),
-    );
-
-    _checkEquivalent(
-      _functionType(
-        typeFormals: [S, T],
-        required: [_typeParameterType(S)],
-        returns: _typeParameterType(T),
-      ),
-      _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(V),
-      ),
-    );
-
-    {
-      var top = _functionType(
-        typeFormals: [S, T],
-        required: [_typeParameterType(T)],
-        returns: _typeParameterType(S),
-      );
-      var left = _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(U)],
-        returns: _typeParameterType(U),
-      );
-      var right = _functionType(
-        typeFormals: [U, V],
-        required: [_typeParameterType(V)],
-        returns: _typeParameterType(V),
-      );
-      var bottom = _functionType(
-        typeFormals: [S, T],
-        required: [_typeParameterType(S)],
-        returns: _typeParameterType(T),
-      );
-      _checkLattice(top, left, right, bottom);
-    }
-  }
-
-  void test_generics() {
-    var LT = _typeParameter('T');
-    var L = _class(name: 'L', typeParameters: [LT]);
-
-    var MT = _typeParameter('T');
-    var M = _class(
-      name: 'M',
-      typeParameters: [MT],
-      interfaces: [
-        _interfaceType(
-          L,
-          typeArguments: [_typeParameterType(MT)],
-        )
-      ],
-    );
-
-    var top = _interfaceType(L, typeArguments: [dynamicType]);
-    var left = _interfaceType(M, typeArguments: [dynamicType]);
-    var right = _interfaceType(L, typeArguments: [intType]);
-    var bottom = _interfaceType(M, typeArguments: [intType]);
-
-    _checkLattice(top, left, right, bottom);
-  }
-
-  void test_int() {
-    List<DartType> equivalents = <DartType>[intType];
-    List<DartType> supertypes = <DartType>[numType];
-    List<DartType> unrelated = <DartType>[doubleType];
-    _checkGroups(intType,
-        equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
-  }
-
-  void test_named_optional() {
-    var r = _functionType(required: [intType], returns: intType);
-    var o = _functionType(optional: [intType], returns: intType);
-    var n = _functionType(named: {'x': intType}, returns: intType);
-
-    var rr = _functionType(
-      required: [intType, intType],
-      returns: intType,
-    );
-    var ro = _functionType(
-      required: [intType],
-      optional: [intType],
-      returns: intType,
-    );
-    var rn = _functionType(
-      required: [intType],
-      named: {'x': intType},
-      returns: intType,
-    );
-    var oo = _functionType(
-      optional: [intType, intType],
-      returns: intType,
-    );
-    var nn = _functionType(
-      named: {'x': intType, 'y': intType},
-      returns: intType,
-    );
-    var nnn = _functionType(
-      named: {'x': intType, 'y': intType, 'z': intType},
-      returns: intType,
-    );
-
-    _checkGroups(r,
-        equivalents: [r],
-        subtypes: [o, ro, rn, oo],
-        unrelated: [n, rr, nn, nnn]);
-    _checkGroups(o,
-        equivalents: [o], subtypes: [oo], unrelated: [n, rr, ro, rn, nn, nnn]);
-    _checkGroups(n,
-        equivalents: [n],
-        subtypes: [nn, nnn],
-        unrelated: [r, o, rr, ro, rn, oo]);
-    _checkGroups(rr,
-        equivalents: [rr],
-        subtypes: [ro, oo],
-        unrelated: [r, o, n, rn, nn, nnn]);
-    _checkGroups(ro,
-        equivalents: [ro], subtypes: [oo], unrelated: [o, n, rn, nn, nnn]);
-    _checkGroups(rn,
-        equivalents: [rn],
-        subtypes: [],
-        unrelated: [o, n, rr, ro, oo, nn, nnn]);
-    _checkGroups(oo,
-        equivalents: [oo], subtypes: [], unrelated: [n, rn, nn, nnn]);
-    _checkGroups(nn,
-        equivalents: [nn], subtypes: [nnn], unrelated: [r, o, rr, ro, rn, oo]);
-    _checkGroups(nnn,
-        equivalents: [nnn], subtypes: [], unrelated: [r, o, rr, ro, rn, oo]);
-  }
-
-  void test_num() {
-    List<DartType> equivalents = <DartType>[numType];
-    List<DartType> supertypes = <DartType>[];
-    List<DartType> unrelated = <DartType>[stringType];
-    List<DartType> subtypes = <DartType>[intType, doubleType];
-    _checkGroups(numType,
-        equivalents: equivalents,
-        supertypes: supertypes,
-        unrelated: unrelated,
-        subtypes: subtypes);
-  }
-
-  void test_simple_function() {
-    var top = _functionType(required: [intType], returns: objectType);
-    var left = _functionType(required: [intType], returns: intType);
-    var right = _functionType(required: [objectType], returns: objectType);
-    var bottom = _functionType(required: [objectType], returns: intType);
-
-    _checkLattice(top, left, right, bottom);
-  }
-
-  /// Regression test for https://github.com/dart-lang/sdk/issues/25069
-  void test_simple_function_void() {
-    var functionType = _functionType(required: [intType], returns: objectType);
-    _checkIsNotSubtypeOf(voidType, functionType);
-  }
-
-  void test_void_functions() {
-    var top = _functionType(required: [intType], returns: voidType);
-    var bottom = _functionType(required: [objectType], returns: intType);
-
-    _checkIsStrictSubtypeOf(bottom, top);
-  }
-
-  void test_void_isTop() {
-    var A = _class(name: 'A');
-    List<DartType> equivalents = <DartType>[dynamicType, objectType, voidType];
-    List<DartType> subtypes = <DartType>[
-      intType,
-      doubleType,
-      numType,
-      stringType,
-      functionType,
-      _interfaceType(A),
-      bottomType
-    ];
-    _checkGroups(voidType, equivalents: equivalents, subtypes: subtypes);
-  }
-}
-
 class SubtypingTestBase extends AbstractTypeSystemTest {
   void _checkEquivalent(DartType type1, DartType type2) {
     _checkIsSubtypeOf(type1, type2);
@@ -3324,8 +2714,10 @@
   }
 
   void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
+    var strType1 = _toStringWithNullability(type1);
+    var strType2 = _toStringWithNullability(type2);
     expect(typeSystem.isSubtypeOf(type1, type2), false,
-        reason: '$type1 was not supposed to be a subtype of $type2');
+        reason: '$strType1 was not supposed to be a subtype of $strType2');
   }
 
   void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
@@ -3362,6 +2754,10 @@
     _checkIsNotSubtypeOf(type1, type2);
     _checkIsNotSubtypeOf(type2, type1);
   }
+
+  static String _toStringWithNullability(DartType type) {
+    return (type as TypeImpl).toString(withNullability: true);
+  }
 }
 
 @reflectiveTest
@@ -4044,56 +3440,94 @@
   }
 
   test_promoteToNonNull_typeParameter_noneBound_none() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeNone(bound: noneType),
-      ),
-      typeParameterTypeNone(bound: noneType),
+    var element = _typeParameter('T', bound: noneType);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    expect(typeSystem.promoteToNonNull(type), same(type));
+  }
+
+  test_promoteToNonNull_typeParameter_noneBound_question() {
+    var element = _typeParameter('T', bound: stringClassTypeNone);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   test_promoteToNonNull_typeParameter_nullBound_none() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeNone(bound: null),
-      ),
-      typeParameterTypeNone(bound: objectClassTypeNone),
+    var element = _typeParameter('T', bound: null);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedBound: objectClassTypeNone,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   test_promoteToNonNull_typeParameter_questionBound_none() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeNone(bound: stringClassTypeQuestion),
-      ),
-      typeParameterTypeNone(bound: stringClassTypeNone),
+    var element = _typeParameter('T', bound: stringClassTypeQuestion);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedBound: stringClassTypeNone,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   test_promoteToNonNull_typeParameter_questionBound_question() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeQuestion(bound: stringClassTypeQuestion),
-      ),
-      typeParameterTypeNone(bound: stringClassTypeNone),
+    var element = _typeParameter('T', bound: stringClassTypeQuestion);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedBound: stringClassTypeNone,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   test_promoteToNonNull_typeParameter_questionBound_star() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeStar(bound: stringClassTypeQuestion),
-      ),
-      typeParameterTypeNone(bound: stringClassTypeNone),
+    var element = _typeParameter('T', bound: stringClassTypeQuestion);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedBound: stringClassTypeNone,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
   test_promoteToNonNull_typeParameter_starBound_none() {
-    expect(
-      typeSystem.promoteToNonNull(
-        typeParameterTypeNone(bound: stringClassTypeStar),
-      ),
-      typeParameterTypeNone(bound: stringClassTypeNone),
+    var element = _typeParameter('T', bound: stringClassTypeStar);
+    var type = _typeParameterType(
+      element,
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    _assertPromotedTypeParameterType(
+      typeSystem.promoteToNonNull(type),
+      baseElement: element,
+      expectedBound: stringClassTypeNone,
+      expectedNullabilitySuffix: NullabilitySuffix.none,
     );
   }
 
@@ -4127,4 +3561,23 @@
       nullabilitySuffix: NullabilitySuffix.star,
     );
   }
+
+  /// If [expectedBound] is `null`, the element of [actual] must be the same
+  /// as the [baseElement].  Otherwise the element of [actual] must be a
+  /// [TypeParameterMember] with the [baseElement] and the [expectedBound].
+  void _assertPromotedTypeParameterType(
+    TypeParameterTypeImpl actual, {
+    @required TypeParameterElement baseElement,
+    TypeImpl expectedBound,
+    @required NullabilitySuffix expectedNullabilitySuffix,
+  }) {
+    if (expectedBound != null) {
+      var actualMember = actual.element as TypeParameterMember;
+      expect(actualMember.baseElement, same(baseElement));
+      expect(actualMember.bound, expectedBound);
+    } else {
+      expect(actual.element, same(baseElement));
+    }
+    expect(actual.nullabilitySuffix, expectedNullabilitySuffix);
+  }
 }
diff --git a/pkg/analyzer/test/id_tests/assigned_variables_test.dart b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
new file mode 100644
index 0000000..31fb94e
--- /dev/null
+++ b/pkg/analyzer/test/id_tests/assigned_variables_test.dart
@@ -0,0 +1,161 @@
+// 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:io';
+
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/analysis/testing_data.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/util/ast_data_extractor.dart';
+
+import '../util/id_testing_helper.dart';
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/'
+      'data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(
+          const _AssignedVariablesDataComputer(), [analyzerNnbdConfig]));
+}
+
+class _AssignedVariablesDataComputer extends DataComputer<_Data> {
+  const _AssignedVariablesDataComputer();
+
+  @override
+  DataInterpreter<_Data> get dataValidator =>
+      const _AssignedVariablesDataInterpreter();
+
+  @override
+  void computeUnitData(TestingData testingData, CompilationUnit unit,
+      Map<Id, ActualData<_Data>> actualMap) {
+    var flowResult =
+        testingData.uriToFlowAnalysisData[unit.declaredElement.source.uri];
+    _AssignedVariablesDataExtractor(
+            unit.declaredElement.source.uri, actualMap, flowResult)
+        .run(unit);
+  }
+}
+
+class _AssignedVariablesDataExtractor extends AstDataExtractor<_Data> {
+  final FlowAnalysisDataForTesting _flowResult;
+
+  Declaration _currentDeclaration;
+
+  AssignedVariablesForTesting<AstNode, PromotableElement>
+      _currentAssignedVariables;
+
+  _AssignedVariablesDataExtractor(
+      Uri uri, Map<Id, ActualData<_Data>> actualMap, this._flowResult)
+      : super(uri, actualMap);
+
+  @override
+  _Data computeNodeValue(Id id, AstNode node) {
+    if (node is FunctionDeclarationStatement) {
+      node = (node as FunctionDeclarationStatement).functionDeclaration;
+    }
+    if (_currentAssignedVariables == null) return null;
+    if (node == _currentDeclaration) {
+      return _Data(
+          _convertVars(_currentAssignedVariables.declaredAtTopLevel),
+          _convertVars(_currentAssignedVariables.writtenAnywhere),
+          _convertVars(_currentAssignedVariables.capturedAnywhere));
+    }
+    if (!_currentAssignedVariables.isTracked(node)) return null;
+    return _Data(
+        _convertVars(_currentAssignedVariables.declaredInNode(node)),
+        _convertVars(_currentAssignedVariables.writtenInNode(node)),
+        _convertVars(_currentAssignedVariables.capturedInNode(node)));
+  }
+
+  @override
+  visitConstructorDeclaration(ConstructorDeclaration node) {
+    _handlePossibleTopLevelDeclaration(
+        node, () => super.visitConstructorDeclaration(node));
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    _handlePossibleTopLevelDeclaration(
+        node, () => super.visitFunctionDeclaration(node));
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    _handlePossibleTopLevelDeclaration(
+        node, () => super.visitVariableDeclaration(node));
+  }
+
+  Set<String> _convertVars(Iterable<PromotableElement> x) =>
+      x.map((e) => e.name).toSet();
+
+  void _handlePossibleTopLevelDeclaration(AstNode node, void callback()) {
+    if (_currentDeclaration == null) {
+      _currentDeclaration = node;
+      _currentAssignedVariables = _flowResult.assignedVariables[node];
+      callback();
+      _currentDeclaration = null;
+      _currentAssignedVariables = null;
+    } else {
+      callback();
+    }
+  }
+}
+
+class _AssignedVariablesDataInterpreter implements DataInterpreter<_Data> {
+  const _AssignedVariablesDataInterpreter();
+
+  @override
+  String getText(_Data actualData) {
+    var parts = <String>[];
+    if (actualData.declared.isNotEmpty) {
+      parts.add('declared=${_setToString(actualData.declared)}');
+    }
+    if (actualData.assigned.isNotEmpty) {
+      parts.add('assigned=${_setToString(actualData.assigned)}');
+    }
+    if (actualData.captured.isNotEmpty) {
+      parts.add('captured=${_setToString(actualData.captured)}');
+    }
+    if (parts.isEmpty) return 'none';
+    return parts.join(', ');
+  }
+
+  @override
+  String isAsExpected(_Data actualData, String expectedData) {
+    var actualDataText = getText(actualData);
+    if (actualDataText == expectedData) {
+      return null;
+    } else {
+      return 'Expected "$expectedData", got "$actualDataText"';
+    }
+  }
+
+  @override
+  bool isEmpty(_Data actualData) =>
+      actualData.assigned.isEmpty && actualData.captured.isEmpty;
+
+  String _setToString(Set<String> values) {
+    List<String> sortedValues = values.toList()..sort();
+    return '{${sortedValues.join(', ')}}';
+  }
+}
+
+class _Data {
+  final Set<String> declared;
+
+  final Set<String> assigned;
+
+  final Set<String> captured;
+
+  _Data(this.declared, this.assigned, this.captured);
+}
diff --git a/pkg/analyzer/test/id_tests/constant_test.dart b/pkg/analyzer/test/id_tests/constant_test.dart
index bf88745..0b01e0a 100644
--- a/pkg/analyzer/test/id_tests/constant_test.dart
+++ b/pkg/analyzer/test/id_tests/constant_test.dart
@@ -4,20 +4,20 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/constant/value.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart';
 
 import '../util/id_testing_helper.dart';
 
 main(List<String> args) async {
-  Directory dataDir = new Directory.fromUri(
-      Platform.script.resolve('../../../front_end/test/constants/data'));
+  Directory dataDir = new Directory.fromUri(Platform.script
+      .resolve('../../../_fe_analyzer_shared/test/constants/data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
diff --git a/pkg/analyzer/test/id_tests/definite_assignment_test.dart b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
index 9bbd456..cb5e417 100644
--- a/pkg/analyzer/test/id_tests/definite_assignment_test.dart
+++ b/pkg/analyzer/test/id_tests/definite_assignment_test.dart
@@ -4,19 +4,20 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart';
 
 import '../util/id_testing_helper.dart';
 
 main(List<String> args) async {
   Directory dataDir = new Directory.fromUri(Platform.script.resolve(
-      '../../../front_end/test/flow_analysis/definite_assignment/data'));
+      '../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/'
+      'data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
@@ -37,7 +38,7 @@
   void computeUnitData(TestingData testingData, CompilationUnit unit,
       Map<Id, ActualData<String>> actualMap) {
     var flowResult =
-        testingData.uriToFlowAnalysisResult[unit.declaredElement.source.uri];
+        testingData.uriToFlowAnalysisData[unit.declaredElement.source.uri];
     _DefiniteAssignmentDataExtractor(
             unit.declaredElement.source.uri, actualMap, flowResult)
         .run(unit);
@@ -45,7 +46,7 @@
 }
 
 class _DefiniteAssignmentDataExtractor extends AstDataExtractor<String> {
-  final FlowAnalysisResult _flowResult;
+  final FlowAnalysisDataForTesting _flowResult;
 
   _DefiniteAssignmentDataExtractor(
       Uri uri, Map<Id, ActualData<String>> actualMap, this._flowResult)
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index b59081c..cba7b8c 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -4,6 +4,8 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -12,15 +14,13 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:test/test.dart';
 
 import '../util/id_testing_helper.dart';
 
 main(List<String> args) async {
-  Directory dataDir = new Directory.fromUri(Platform.script
-      .resolve('../../../front_end/test/flow_analysis/nullability/data'));
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../_fe_analyzer_shared/test/flow_analysis/nullability/data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
@@ -31,7 +31,7 @@
 }
 
 class FlowTestBase {
-  FlowAnalysisResult flowResult;
+  FlowAnalysisDataForTesting flowResult;
 
   /// Resolve the given [code] and track nullability in the unit.
   Future<void> trackCode(String code) async {
diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart
index 6013f56..6c8463c 100644
--- a/pkg/analyzer/test/id_tests/reachability_test.dart
+++ b/pkg/analyzer/test/id_tests/reachability_test.dart
@@ -4,20 +4,20 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/analysis/testing_data.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:test/test.dart';
 
 import '../util/id_testing_helper.dart';
 
 main(List<String> args) async {
-  Directory dataDir = new Directory.fromUri(Platform.script
-      .resolve('../../../front_end/test/flow_analysis/reachability/data'));
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../_fe_analyzer_shared/test/flow_analysis/reachability/data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
@@ -28,7 +28,7 @@
 }
 
 class FlowTestBase {
-  FlowAnalysisResult flowResult;
+  FlowAnalysisDataForTesting flowResult;
 
   /// Resolve the given [code] and track nullability in the unit.
   Future<void> trackCode(String code) async {
@@ -59,7 +59,7 @@
   void computeUnitData(TestingData testingData, CompilationUnit unit,
       Map<Id, ActualData<Set<_ReachabilityAssertion>>> actualMap) {
     var flowResult =
-        testingData.uriToFlowAnalysisResult[unit.declaredElement.source.uri];
+        testingData.uriToFlowAnalysisData[unit.declaredElement.source.uri];
     _ReachabilityDataExtractor(
             unit.declaredElement.source.uri, actualMap, flowResult)
         .run(unit);
@@ -68,7 +68,7 @@
 
 class _ReachabilityDataExtractor
     extends AstDataExtractor<Set<_ReachabilityAssertion>> {
-  final FlowAnalysisResult _flowResult;
+  final FlowAnalysisDataForTesting _flowResult;
 
   _ReachabilityDataExtractor(
       Uri uri,
@@ -79,18 +79,33 @@
   @override
   Set<_ReachabilityAssertion> computeNodeValue(Id id, AstNode node) {
     Set<_ReachabilityAssertion> result = {};
-    if (_flowResult.unreachableNodes.contains(node)) {
+    if (node is Expression && node.parent is ExpressionStatement) {
+      // The reachability of an expression statement and the statement it
+      // contains should always be the same.  We check this with an assert
+      // statement, and only annotate the expression statement, to reduce the
+      // amount of redundancy in the test files.
+      assert(_flowResult.unreachableNodes.contains(node) ==
+          _flowResult.unreachableNodes.contains(node.parent));
+    } else if (_flowResult.unreachableNodes.contains(node)) {
       result.add(_ReachabilityAssertion.unreachable);
     }
     if (node is FunctionDeclaration) {
-      var body = node.functionExpression.body;
-      if (body != null &&
-          _flowResult.functionBodiesThatDontComplete.contains(body)) {
-        result.add(_ReachabilityAssertion.doesNotComplete);
-      }
+      _checkBodyCompletion(node.functionExpression.body, result);
+    } else if (node is ConstructorDeclaration) {
+      _checkBodyCompletion(node.body, result);
+    } else if (node is MethodDeclaration) {
+      _checkBodyCompletion(node.body, result);
     }
     return result.isEmpty ? null : result;
   }
+
+  void _checkBodyCompletion(
+      FunctionBody body, Set<_ReachabilityAssertion> result) {
+    if (body != null &&
+        _flowResult.functionBodiesThatDontComplete.contains(body)) {
+      result.add(_ReachabilityAssertion.doesNotComplete);
+    }
+  }
 }
 
 class _ReachabilityDataInterpreter
diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart
index 059c251..e6ab989 100644
--- a/pkg/analyzer/test/id_tests/type_promotion_test.dart
+++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart
@@ -4,20 +4,22 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 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/analysis/testing_data.dart';
+import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/util/ast_data_extractor.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart';
 
 import '../util/id_testing_helper.dart';
 
 main(List<String> args) async {
   Directory dataDir = new Directory.fromUri(Platform.script
-      .resolve('../../../front_end/test/flow_analysis/type_promotion/data'));
+      .resolve('../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/'
+          'data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
@@ -67,17 +69,30 @@
   const _TypePromotionDataInterpreter();
 
   @override
-  String getText(DartType actualData) => actualData.toString();
+  String getText(DartType actualData) {
+    if (actualData is TypeParameterType) {
+      var element = actualData.element;
+      if (element is TypeParameterMember) {
+        return '${element.name} & ${_typeToString(element.bound)}';
+      }
+    }
+    return _typeToString(actualData);
+  }
 
   @override
   String isAsExpected(DartType actualData, String expectedData) {
-    if (actualData.toString() == expectedData) {
+    var actualDataText = getText(actualData);
+    if (actualDataText == expectedData) {
       return null;
     } else {
-      return 'Expected $expectedData, got $actualData';
+      return 'Expected $expectedData, got $actualDataText';
     }
   }
 
   @override
   bool isEmpty(DartType actualData) => actualData == null;
+
+  String _typeToString(TypeImpl type) {
+    return type.toString(withNullability: true);
+  }
 }
diff --git a/pkg/analyzer/test/instrumentation/instrumentation_test.dart b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
index 302a916..c4b408e 100644
--- a/pkg/analyzer/test/instrumentation/instrumentation_test.dart
+++ b/pkg/analyzer/test/instrumentation/instrumentation_test.dart
@@ -49,7 +49,7 @@
     TestInstrumentationServer server = new TestInstrumentationServer();
     InstrumentationService service = new InstrumentationService(server);
     String message = 'exceptionMessage';
-    service.logException(message, null);
+    service.logException(message);
     assertNormal(server, InstrumentationService.TAG_EXCEPTION, '$message:null');
   }
 
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 f1b3cfc..b97a484 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -76,6 +76,16 @@
   TypeProvider get typeProvider =>
       result.unit.declaredElement.context.typeProvider;
 
+  void assertDeclaredVariableType(SimpleIdentifier node, String expected) {
+    VariableElement element = node.staticElement;
+    assertElementTypeString(element.type, expected);
+  }
+
+  void assertDeclaredVariableTypeDynamic(SimpleIdentifier node) {
+    VariableElement element = node.staticElement;
+    expect(element.type, isDynamicType);
+  }
+
   void assertElement(AstNode node, Element expected) {
     Element actual = getNodeElement(node);
     expect(actual, same(expected));
@@ -86,6 +96,10 @@
     expect(actual, isNull);
   }
 
+  void assertElementTypeString(DartType type, String expected) {
+    expect('$type', expected);
+  }
+
   void assertIdentifierTopGetRef(SimpleIdentifier ref, String name) {
     var getter = findElement.topGet(name);
     assertElement(ref, getter);
@@ -167,7 +181,7 @@
     if (expectedPrefix == null) {
       var name = node.name as SimpleIdentifier;
       assertElement(name, expectedElement);
-      assertType(name, expectedType);
+      assertTypeNull(name);
     } else {
       var name = node.name as PrefixedIdentifier;
 
@@ -721,7 +735,7 @@
     PrefixedIdentifier prefixed = annotation.name;
 
     expect(prefixed.prefix.staticElement, same(aClass));
-    expect(prefixed.prefix.staticType, interfaceType(aClass));
+    assertTypeNull(prefixed.prefix);
 
     expect(prefixed.identifier.staticElement, same(aGetter));
     expect(prefixed.identifier.staticType, typeProvider.intType);
@@ -781,7 +795,7 @@
     PrefixedIdentifier prefixed = annotation.name;
 
     expect(prefixed.prefix.staticElement, same(aClass));
-    expect(prefixed.prefix.staticType, interfaceType(aClass));
+    assertTypeNull(prefixed.prefix);
 
     expect(prefixed.identifier.staticElement, same(constructor));
     expect(
@@ -899,7 +913,7 @@
 
       TypeName intName = asExpression.type;
       expect(intName.name.staticElement, typeProvider.intType.element);
-      expect(intName.name.staticType, typeProvider.intType);
+      expect(intName.name.staticType, isNull);
     }
   }
 
@@ -1458,7 +1472,7 @@
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, interfaceType(aElement));
+      expect(identifier.staticType, isNull);
 
       expect(constructorName.name, isNull);
     }
@@ -1478,7 +1492,7 @@
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, interfaceType(aElement));
+      expect(identifier.staticType, isNull);
 
       expect(constructorName.name.staticElement, aNamed);
       expect(constructorName.name.staticType, isNull);
@@ -1527,7 +1541,7 @@
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, auType);
+      expect(identifier.staticType, isNull);
 
       expect(constructorName.name, isNull);
     }
@@ -1549,7 +1563,7 @@
 
       SimpleIdentifier identifier = typeName.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, auType);
+      expect(identifier.staticType, isNull);
 
       expect(constructorName.name.staticElement, same(actualMember));
       expect(constructorName.name.staticType, isNull);
@@ -1864,7 +1878,7 @@
     expect(typeName.typeArguments.arguments[0].type, typeProvider.intType);
 
     VariableDeclaration vNode = statement.variables.variables[0];
-    expect(vNode.name.staticType, isDynamicType);
+    expect(vNode.name.staticType, isNull);
     expect(vNode.declaredElement.type, isDynamicType);
   }
 
@@ -1926,7 +1940,7 @@
     expect(p.declaredElement, same(constructor.declaredElement.parameters[0]));
 
     {
-      FunctionType type = p.identifier.staticType;
+      FunctionType type = (p.identifier.staticElement as ParameterElement).type;
       expect(type.returnType, typeProvider.stringType);
 
       expect(type.parameters, hasLength(1));
@@ -1938,7 +1952,7 @@
     {
       SimpleFormalParameter a = p.parameters.parameters[0];
       _assertTypeNameSimple(a.type, typeProvider.intType);
-      expect(a.identifier.staticType, typeProvider.intType);
+      expect(a.identifier.staticType, isNull);
     }
   }
 
@@ -1984,7 +1998,7 @@
     {
       SimpleFormalParameter a = p.parameters.parameters[0];
       _assertTypeNameSimple(a.type, typeProvider.intType);
-      expect(a.identifier.staticType, typeProvider.intType);
+      expect(a.identifier.staticType, isNull);
     }
   }
 
@@ -2130,9 +2144,8 @@
 }
 ''');
     await resolveTestFile();
-    var f = findNode.simple('f;');
-    assertType(f, 'void Function<T>(T)');
-    var fType = f.staticType as FunctionType;
+    assertTypeNull(findNode.simple('f;'));
+    var fType = findElement.localVar('f').type as FunctionType;
     var fTypeTypeParameter = fType.typeFormals[0];
     var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
     expect(fTypeParameter.element, same(fTypeTypeParameter));
@@ -2211,7 +2224,7 @@
 
       Identifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, interfaceType(cElement));
+      expect(typeIdentifier.staticType, isNull);
 
       expect(value.constructorName.name, isNull);
     }
@@ -2228,7 +2241,7 @@
 
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, interfaceType(cElement));
+      expect(typeIdentifier.staticType, isNull);
 
       SimpleIdentifier constructorName = value.constructorName.name;
       expect(constructorName.staticElement, namedConstructor);
@@ -2264,7 +2277,7 @@
 
     Identifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, xElement);
-    expect(typeIdentifier.staticType, interfaceType(xElement));
+    expect(typeIdentifier.staticType, isNull);
 
     expect(creation.constructorName.name, isNull);
 
@@ -2304,7 +2317,7 @@
 
       Identifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, interfaceType(cElement));
+      expect(typeIdentifier.staticType, isNull);
 
       expect(value.constructorName.name, isNull);
 
@@ -2324,7 +2337,7 @@
 
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, interfaceType(cElement));
+      expect(typeIdentifier.staticType, isNull);
 
       SimpleIdentifier constructorName = value.constructorName.name;
       expect(constructorName.staticElement, namedConstructor);
@@ -2360,10 +2373,6 @@
     ClassElement cElement = aLibrary.getType('C');
     ConstructorElement defaultConstructor = cElement.constructors[0];
     ConstructorElement namedConstructor = cElement.constructors[1];
-    InterfaceType cTypeDynamic = cElement.instantiate(
-      typeArguments: [DynamicTypeImpl.instance],
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
 
     var statements = _getMainStatements(result);
     {
@@ -2382,7 +2391,7 @@
 
       PrefixedIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, same(cElement));
-      expect(typeIdentifier.staticType, cTypeDynamic);
+      expect(typeIdentifier.staticType, isNull);
 
       SimpleIdentifier typePrefix = typeIdentifier.prefix;
       expect(typePrefix.name, 'p');
@@ -2410,7 +2419,7 @@
 
       PrefixedIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cTypeDynamic);
+      expect(typeIdentifier.staticType, isNull);
 
       SimpleIdentifier typePrefix = typeIdentifier.prefix;
       expect(typePrefix.name, 'p');
@@ -2442,7 +2451,7 @@
 
       PrefixedIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, cElement);
-      expect(typeIdentifier.staticType, cTypeBool);
+      expect(typeIdentifier.staticType, isNull);
 
       SimpleIdentifier typePrefix = typeIdentifier.prefix;
       expect(typePrefix.name, 'p');
@@ -2457,7 +2466,6 @@
     }
   }
 
-  @failingTest
   test_instanceCreation_unprefixed() async {
     addTestFile(r'''
 main() {
@@ -2480,11 +2488,13 @@
     ClassElement cElement = unitElement.getType('C');
     ConstructorElement defaultConstructor = cElement.constructors[0];
     ConstructorElement namedConstructor = cElement.constructors[1];
-    InterfaceType cType = interfaceType(cElement);
 
     var statements = _getMainStatements(result);
     {
-      var cTypeInt = cType.instantiate([typeProvider.intType]);
+      var cTypeInt = cElement.instantiate(
+        typeArguments: [typeProvider.intType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[0];
       InstanceCreationExpression creation = statement.expression;
@@ -2502,7 +2512,10 @@
     }
 
     {
-      var cTypeBool = cType.instantiate([typeProvider.boolType]);
+      var cTypeBool = cElement.instantiate(
+        typeArguments: [typeProvider.boolType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[1];
       InstanceCreationExpression creation = statement.expression;
@@ -2522,7 +2535,10 @@
     }
 
     {
-      var cTypeDouble = cType.instantiate([typeProvider.doubleType]);
+      var cTypeDouble = cElement.instantiate(
+        typeArguments: [typeProvider.doubleType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[2];
       InstanceCreationExpression creation = statement.expression;
@@ -2544,7 +2560,10 @@
     }
 
     {
-      var cTypeBool = cType.instantiate([typeProvider.boolType]);
+      var cTypeBool = cElement.instantiate(
+        typeArguments: [typeProvider.boolType],
+        nullabilitySuffix: NullabilitySuffix.star,
+      );
 
       ExpressionStatement statement = statements[3];
       InstanceCreationExpression creation = statement.expression;
@@ -2660,8 +2679,8 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    assertTypeDynamic(findNode.simple('x,'));
-    assertType(findNode.simple('y,'), 'StackTrace');
+    assertDeclaredVariableTypeDynamic(findNode.simple('x,'));
+    assertDeclaredVariableType(findNode.simple('y,'), 'StackTrace');
   }
 
   test_invalid_catch_parameters_empty() async {
@@ -2683,8 +2702,8 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    assertTypeDynamic(findNode.simple('e,'));
-    assertType(findNode.simple('s})'), 'StackTrace');
+    assertDeclaredVariableTypeDynamic(findNode.simple('e,'));
+    assertDeclaredVariableType(findNode.simple('s})'), 'StackTrace');
   }
 
   test_invalid_catch_parameters_optional_stack() async {
@@ -2696,8 +2715,8 @@
     await resolveTestFile();
     expect(result.errors, isNotEmpty);
 
-    assertTypeDynamic(findNode.simple('e,'));
-    assertType(findNode.simple('s])'), 'StackTrace');
+    assertDeclaredVariableTypeDynamic(findNode.simple('e,'));
+    assertDeclaredVariableType(findNode.simple('s])'), 'StackTrace');
   }
 
   test_invalid_const_as() async {
@@ -3932,7 +3951,7 @@
 
       TypeName numName = isExpression.type;
       expect(numName.name.staticElement, typeProvider.numType.element);
-      expect(numName.name.staticType, typeProvider.numType);
+      expect(numName.name.staticType, isNull);
     }
   }
 
@@ -3971,7 +3990,7 @@
 
       TypeName numName = isExpression.type;
       expect(numName.name.staticElement, typeProvider.numType.element);
-      expect(numName.name.staticType, typeProvider.numType);
+      expect(numName.name.staticType, isNull);
     }
   }
 
@@ -4047,11 +4066,11 @@
 
     var intRef = findNode.simple('int, double');
     assertElement(intRef, intElement);
-    assertType(intRef, 'int');
+    assertTypeNull(intRef);
 
     var doubleRef = findNode.simple('double>[]');
     assertElement(doubleRef, doubleElement);
-    assertType(doubleRef, 'double');
+    assertTypeNull(doubleRef);
   }
 
   test_local_function() async {
@@ -4076,7 +4095,7 @@
     expect(fElement.type.toString(), fTypeString);
 
     expect(fNode.name.staticElement, same(fElement));
-    expect(fNode.name.staticType, fElement.type);
+    expect(fNode.name.staticType, isNull);
 
     TypeName fReturnTypeNode = fNode.returnType;
     expect(fReturnTypeNode.name.staticElement, same(doubleType.element));
@@ -4304,7 +4323,7 @@
     expect(fElement.type.toString(), fTypeString);
 
     expect(fNode.name.staticElement, same(fElement));
-    expect(fNode.name.staticType, fElement.type);
+    expect(fNode.name.staticType, isNull);
 
     TypeName fReturnTypeNode = fNode.returnType;
     expect(fReturnTypeNode.name.staticElement, same(doubleType.element));
@@ -4369,7 +4388,7 @@
     expect(fElement.type.toString(), 'Null Function()');
 
     expect(fNode.name.staticElement, same(fElement));
-    expect(fNode.name.staticType, fElement.type);
+    expect(fNode.name.staticType, isNull);
 
     expect(fExpression.declaredElement, same(fElement));
   }
@@ -4396,7 +4415,7 @@
     expect(fElement.type.toString(), fTypeString);
 
     expect(fNode.name.staticElement, same(fElement));
-    expect(fNode.name.staticType, fElement.type);
+    expect(fNode.name.staticType, isNull);
 
     TypeName fReturnTypeNode = fNode.returnType;
     expect(fReturnTypeNode.name.staticElement, same(doubleType.element));
@@ -4458,19 +4477,23 @@
 }
 ''');
     await resolveTestFile();
-    var callback = findNode.simple('callback');
-    assertType(callback, 'C Function<T extends E>(D)');
+    var callbackIdentifier = findNode.simple('callback<');
+    var callbackElement = callbackIdentifier.staticElement as ParameterElement;
+    assertElementTypeString(
+      callbackElement.type,
+      'C Function<T extends E>(D)',
+    );
     var cReference = findNode.simple('C callback');
     var cElement = findElement.class_('C');
-    assertType(cReference, 'C');
+    assertTypeNull(cReference);
     assertElement(cReference, cElement);
     var dReference = findNode.simple('D d');
     var dElement = findElement.class_('D');
-    assertType(dReference, 'D');
+    assertTypeNull(dReference);
     assertElement(dReference, dElement);
     var eReference = findNode.simple('E>');
     var eElement = findElement.class_('E');
-    assertType(eReference, 'E');
+    assertTypeNull(eReference);
     assertElement(eReference, eElement);
   }
 
@@ -4614,8 +4637,7 @@
             .type as TypeName;
     var tReference = gParameterType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_function_normal_parameter_type() async {
@@ -4646,8 +4668,7 @@
             as TypeName;
     var tReference = gParameterType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_function_optional_parameter_type() async {
@@ -4679,8 +4700,7 @@
             .type as TypeName;
     var tReference = gParameterType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_function_return_type() async {
@@ -4708,8 +4728,7 @@
     var gReturnType = gType.returnType as TypeName;
     var tReference = gReturnType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_interface_type_parameter() async {
@@ -4737,8 +4756,7 @@
     var yElementType = yType.typeArguments.arguments[0] as TypeName;
     var tReference = yElementType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_simple() async {
@@ -4762,8 +4780,7 @@
     var yType = yDeclaration.variables.type as TypeName;
     var tReference = yType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_typedef_named_parameter_type() async {
@@ -4790,8 +4807,7 @@
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_typedef_normal_parameter_type() async {
@@ -4818,8 +4834,7 @@
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_typedef_optional_parameter_type() async {
@@ -4846,8 +4861,7 @@
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_type_parameter_reference_typedef_return_type() async {
@@ -4873,8 +4887,7 @@
     var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
     var tReference = gArgumentType.name;
     assertElement(tReference, tElement);
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
+    assertTypeNull(tReference);
   }
 
   test_local_variable() async {
@@ -4893,7 +4906,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), 'void Function()');
+    expect(main.name.staticType, isNull);
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -4903,7 +4916,7 @@
     {
       VariableDeclarationStatement statement = statements[0];
       VariableDeclaration vNode = statement.variables.variables[0];
-      expect(vNode.name.staticType, intType);
+      expect(vNode.name.staticType, isNull);
       expect(vNode.initializer.staticType, intType);
 
       vElement = vNode.name.staticElement;
@@ -5056,7 +5069,7 @@
     expect(vElement.type, typeProvider.intType);
 
     expect(vNode.identifier.staticElement, vElement);
-    expect(vNode.identifier.staticType, typeProvider.intType);
+    expect(vNode.identifier.staticType, isNull);
 
     ExpressionStatement statement = forBlock.statements[0];
     SimpleIdentifier identifier = statement.expression;
@@ -5092,10 +5105,10 @@
 
     SimpleIdentifier vTypeIdentifier = vTypeName.name;
     expect(vTypeIdentifier.staticElement, typeProvider.numType.element);
-    expect(vTypeIdentifier.staticType, typeProvider.numType);
+    expect(vTypeIdentifier.staticType, isNull);
 
     expect(vNode.identifier.staticElement, vElement);
-    expect(vNode.identifier.staticType, typeProvider.numType);
+    expect(vNode.identifier.staticType, isNull);
 
     ExpressionStatement statement = forBlock.statements[0];
     SimpleIdentifier identifier = statement.expression;
@@ -5231,15 +5244,15 @@
 
     var boolRef = findNode.simple('bool, ');
     assertElement(boolRef, boolElement);
-    assertType(boolRef, 'bool');
+    assertTypeNull(boolRef);
 
     var intRef = findNode.simple('int, ');
     assertElement(intRef, intElement);
-    assertType(intRef, 'int');
+    assertTypeNull(intRef);
 
     var doubleRef = findNode.simple('double>');
     assertElement(doubleRef, doubleElement);
-    assertType(doubleRef, 'double');
+    assertTypeNull(doubleRef);
   }
 
   test_method_namedParameters() async {
@@ -5264,7 +5277,7 @@
     expect(methodElement.type.toString(), fTypeString);
 
     expect(methodDeclaration.name.staticElement, same(methodElement));
-    expect(methodDeclaration.name.staticType, methodElement.type);
+    expect(methodDeclaration.name.staticType, isNull);
 
     TypeName fReturnTypeNode = methodDeclaration.returnType;
     expect(fReturnTypeNode.name.staticElement, same(doubleType.element));
@@ -5628,7 +5641,7 @@
 
       SimpleIdentifier target = invocation.target;
       expect(target.staticElement, same(cElement));
-      expect(target.staticType, interfaceType(cElement));
+      assertTypeNull(target);
 
       var invokeTypeStr = 'void Function(int)';
       expect(invocation.staticType.toString(), 'void');
@@ -6313,7 +6326,7 @@
 
     SimpleIdentifier prefix = prefixed.prefix;
     expect(prefix.staticElement, same(cElement));
-    expect(prefix.staticType, interfaceType(cElement));
+    assertTypeNull(prefix);
 
     SimpleIdentifier identifier = prefixed.identifier;
     expect(identifier.staticElement, same(fElement.getter));
@@ -6663,9 +6676,8 @@
     await resolveTestFile();
     var tElement = findElement.class_('C').typeParameters[0];
     var tReference = findNode.simple('T x');
-    var tReferenceType = tReference.staticType as TypeParameterType;
-    expect(tReferenceType.element, same(tElement));
     assertElement(tReference, tElement);
+    assertTypeNull(tReference);
   }
 
   test_setLiteral() async {
@@ -6683,7 +6695,7 @@
 
     var intRef = findNode.simple('int>{}');
     assertElement(intRef, intElement);
-    assertType(intRef, 'int');
+    assertTypeNull(intRef);
   }
 
   test_stringInterpolation() async {
@@ -6703,7 +6715,7 @@
     FunctionDeclaration main = result.unit.declarations[0];
     expect(main.declaredElement, isNotNull);
     expect(main.name.staticElement, isNotNull);
-    expect(main.name.staticType.toString(), 'void Function()');
+    expect(main.name.staticType, isNull);
 
     BlockFunctionBody body = main.functionExpression.body;
     NodeList<Statement> statements = body.block.statements;
@@ -7058,7 +7070,7 @@
 
     SimpleIdentifier dName = dNode.name;
     expect(dName.staticElement, same(dElement));
-    expect(dName.staticType, typeProvider.typeType);
+    expect(dName.staticType, isNull);
 
     {
       var expectedType = aElement.instantiate(
@@ -7071,7 +7083,7 @@
 
       SimpleIdentifier identifier = superClass.name;
       expect(identifier.staticElement, aElement);
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
 
     {
@@ -7085,7 +7097,7 @@
 
       SimpleIdentifier identifier = mixinType.name;
       expect(identifier.staticElement, bElement);
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
 
     {
@@ -7099,7 +7111,7 @@
 
       SimpleIdentifier identifier = implementedType.name;
       expect(identifier.staticElement, cElement);
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
   }
 
@@ -7127,7 +7139,7 @@
 
     SimpleIdentifier dName = dNode.name;
     expect(dName.staticElement, same(dElement));
-    expect(dName.staticType, typeProvider.typeType);
+    expect(dName.staticType, isNull);
 
     {
       var expectedType = aElement.instantiate(
@@ -7140,7 +7152,7 @@
 
       SimpleIdentifier identifier = superClass.name;
       expect(identifier.staticElement, same(aElement));
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
 
     {
@@ -7154,7 +7166,7 @@
 
       SimpleIdentifier identifier = mixinType.name;
       expect(identifier.staticElement, same(bElement));
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
 
     {
@@ -7168,7 +7180,7 @@
 
       SimpleIdentifier identifier = interfaceType.name;
       expect(identifier.staticElement, same(cElement));
-      expect(identifier.staticType, expectedType);
+      expect(identifier.staticType, isNull);
     }
   }
 
@@ -7193,7 +7205,7 @@
       var aNode = enumNode.constants[0];
       expect(aNode.declaredElement, same(aElement));
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, interfaceType(enumElement));
+      expect(aNode.name.staticType, isNull);
     }
 
     {
@@ -7201,7 +7213,7 @@
       var bNode = enumNode.constants[1];
       expect(bNode.declaredElement, same(bElement));
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, interfaceType(enumElement));
+      expect(bNode.name.staticType, isNull);
     }
   }
 
@@ -7221,7 +7233,6 @@
     await resolveTestFile();
     expect(result.path, testFile);
 
-    InterfaceType typeType = typeProvider.typeType;
     InterfaceType doubleType = typeProvider.doubleType;
     InterfaceType intType = typeProvider.intType;
     ClassElement doubleElement = doubleType.element;
@@ -7232,7 +7243,7 @@
 
     // The class name identifier.
     expect(cNode.name.staticElement, same(cElement));
-    expect(cNode.name.staticType, typeType);
+    expect(cNode.name.staticType, isNull);
 
     // unnamed constructor
     {
@@ -7240,7 +7251,7 @@
       expect(node.declaredElement, isNotNull);
       expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
-      expect(node.returnType.staticType, typeType);
+      expect(node.returnType.staticType, isNull);
       expect(node.name, isNull);
     }
 
@@ -7250,9 +7261,9 @@
       expect(node.declaredElement, isNotNull);
       expect(node.declaredElement.type.toString(), 'C Function(int)');
       expect(node.returnType.staticElement, same(cElement));
-      expect(node.returnType.staticType, typeType);
+      expect(node.returnType.staticType, isNull);
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType.toString(), 'C Function(int)');
+      expect(node.name.staticType, isNull);
     }
 
     // publicMethod()
@@ -7266,11 +7277,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, intType);
       expect(returnTypeName.staticElement, intElement);
-      expect(returnTypeName.staticType, intType);
+      expect(returnTypeName.staticType, isNull);
 
       // method name
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType, same(node.declaredElement.type));
+      expect(node.name.staticType, isNull);
 
       // method parameter
       {
@@ -7280,10 +7291,10 @@
 
         TypeName pType = pNode.type;
         expect(pType.name.staticElement, doubleElement);
-        expect(pType.name.staticType, doubleType);
+        expect(pType.name.staticType, isNull);
 
         expect(pNode.identifier.staticElement, pNode.declaredElement);
-        expect(pNode.identifier.staticType, doubleType);
+        expect(pNode.identifier.staticType, isNull);
       }
     }
 
@@ -7298,11 +7309,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, intType);
       expect(returnTypeName.staticElement, intElement);
-      expect(returnTypeName.staticType, intType);
+      expect(returnTypeName.staticType, isNull);
 
       // getter name
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType, intType);
+      expect(node.name.staticType, isNull);
     }
 
     // publicSetter()
@@ -7316,11 +7327,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, VoidTypeImpl.instance);
       expect(returnTypeName.staticElement, isNull);
-      expect(returnTypeName.staticType, VoidTypeImpl.instance);
+      expect(returnTypeName.staticType, isNull);
 
       // setter name
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType, doubleType);
+      expect(node.name.staticType, isNull);
 
       // setter parameter
       {
@@ -7330,10 +7341,10 @@
 
         TypeName pType = pNode.type;
         expect(pType.name.staticElement, doubleElement);
-        expect(pType.name.staticType, doubleType);
+        expect(pType.name.staticType, isNull);
 
         expect(pNode.identifier.staticElement, pNode.declaredElement);
-        expect(pNode.identifier.staticType, doubleType);
+        expect(pNode.identifier.staticType, isNull);
       }
     }
   }
@@ -7365,11 +7376,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, intType);
       expect(returnTypeName.staticElement, intElement);
-      expect(returnTypeName.staticType, intType);
+      expect(returnTypeName.staticType, isNull);
 
       // function name
       expect(node.name.staticElement, same(node.declaredElement));
-      expect(node.name.staticType, same(node.declaredElement.type));
+      expect(node.name.staticType, isNull);
 
       // function parameter
       {
@@ -7380,10 +7391,10 @@
 
         TypeName pType = pNode.type;
         expect(pType.name.staticElement, doubleElement);
-        expect(pType.name.staticType, doubleType);
+        expect(pType.name.staticType, isNull);
 
         expect(pNode.identifier.staticElement, pNode.declaredElement);
-        expect(pNode.identifier.staticType, doubleType);
+        expect(pNode.identifier.staticType, isNull);
       }
     }
 
@@ -7398,13 +7409,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, intType);
       expect(returnTypeName.staticElement, intElement);
-      expect(returnTypeName.staticType, intType);
+      expect(returnTypeName.staticType, isNull);
 
       // getter name
       expect(node.name.staticElement, same(node.declaredElement));
-      // TODO(scheglov) must be null
-//      assertTypeNull(node.name);
-//      expect(node.name.staticType, intType);
+      expect(node.name.staticType, isNull);
     }
 
     // topSetter()
@@ -7418,13 +7427,11 @@
       SimpleIdentifier returnTypeName = returnType.name;
       expect(returnType.type, VoidTypeImpl.instance);
       expect(returnTypeName.staticElement, isNull);
-      expect(returnTypeName.staticType, VoidTypeImpl.instance);
+      expect(returnTypeName.staticType, isNull);
 
       // setter name
       expect(node.name.staticElement, same(node.declaredElement));
-      // TODO(scheglov) must be null
-//      assertTypeNull(node.name);
-//      expect(node.name.staticType, doubleType);
+      expect(node.name.staticType, isNull);
 
       // setter parameter
       {
@@ -7435,10 +7442,10 @@
 
         TypeName pType = pNode.type;
         expect(pType.name.staticElement, doubleElement);
-        expect(pType.name.staticType, doubleType);
+        expect(pType.name.staticType, isNull);
 
         expect(pNode.identifier.staticElement, pNode.declaredElement);
-        expect(pNode.identifier.staticType, doubleType);
+        expect(pNode.identifier.staticType, isNull);
       }
     }
   }
@@ -7469,7 +7476,7 @@
       expect(aNode.declaredElement, same(aElement));
       expect(aElement.type, typeProvider.intType);
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, same(aElement.type));
+      expect(aNode.name.staticType, isNull);
 
       Expression aValue = aNode.initializer;
       expect(aValue.staticType, typeProvider.intType);
@@ -7482,13 +7489,13 @@
       TypeName typeName = bDeclaration.fields.type;
       SimpleIdentifier typeIdentifier = typeName.name;
       expect(typeIdentifier.staticElement, same(tElement));
-      expect(typeIdentifier.staticType, typeParameterType(tElement));
+      expect(typeIdentifier.staticType, isNull);
 
       VariableDeclaration bNode = bDeclaration.fields.variables[0];
       expect(bNode.declaredElement, same(bElement));
       expect(bElement.type, typeParameterType(tElement));
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, same(bElement.type));
+      expect(bNode.name.staticType, isNull);
     }
   }
 
@@ -7518,7 +7525,7 @@
       expect(aElement.type, typeProvider.intType);
 
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, same(aElement.type));
+      expect(aNode.name.staticType, isNull);
 
       Expression aValue = aNode.initializer;
       expect(aValue.staticType, typeProvider.intType);
@@ -7532,7 +7539,7 @@
       expect(bElement.type, typeProvider.doubleType);
 
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, same(bElement.type));
+      expect(bNode.name.staticType, isNull);
 
       Expression aValue = bNode.initializer;
       expect(aValue.staticType, typeProvider.doubleType);
@@ -7558,7 +7565,7 @@
       expect(aElement, same(unitElement.topLevelVariables[0]));
       expect(aElement.type, typeProvider.intType);
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, same(aElement.type));
+      expect(aNode.name.staticType, isNull);
 
       Expression aValue = aNode.initializer;
       expect(aValue.staticType, typeProvider.intType);
@@ -7576,7 +7583,7 @@
       _assertTypeNameSimple(typeName, typeProvider.doubleType);
 
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, same(bElement.type));
+      expect(bNode.name.staticType, isNull);
 
       Expression aValue = bNode.initializer;
       expect(aValue.staticType, typeProvider.doubleType);
@@ -7604,7 +7611,7 @@
       expect(aElement.type, typeProvider.intType);
 
       expect(aNode.name.staticElement, same(aElement));
-      expect(aNode.name.staticType, aElement.type);
+      expect(aNode.name.staticType, isNull);
 
       Expression aValue = aNode.initializer;
       expect(aValue.staticType, typeProvider.intType);
@@ -7617,7 +7624,7 @@
       expect(bElement.type, typeProvider.doubleType);
 
       expect(bNode.name.staticElement, same(bElement));
-      expect(bNode.name.staticType, bElement.type);
+      expect(bNode.name.staticType, isNull);
 
       Expression aValue = bNode.initializer;
       expect(aValue.staticType, typeProvider.doubleType);
@@ -7643,7 +7650,7 @@
     expect(fElement.type.toString(), fTypeString);
 
     expect(fDeclaration.name.staticElement, same(fElement));
-    expect(fDeclaration.name.staticType, fElement.type);
+    expect(fDeclaration.name.staticType, isNull);
 
     TypeName fReturnTypeNode = fDeclaration.returnType;
     expect(fReturnTypeNode.name.staticElement, same(doubleType.element));
@@ -7711,20 +7718,21 @@
 
     FunctionTypeAlias alias = unit.declarations[0];
     FunctionTypeAliasElement aliasElement = alias.declaredElement;
+    GenericFunctionTypeElement aliasFunction = aliasElement.function;
     expect(aliasElement, same(unitElement.functionTypeAliases[0]));
-    expect(aliasElement.returnType, typeProvider.intType);
+    expect(aliasFunction.returnType, typeProvider.intType);
 
     _assertTypeNameSimple(alias.returnType, typeProvider.intType);
 
     _assertSimpleParameter(
-        alias.parameters.parameters[0], aliasElement.parameters[0],
+        alias.parameters.parameters[0], aliasFunction.parameters[0],
         name: 'a',
         offset: 22,
         kind: ParameterKind.REQUIRED,
         type: typeProvider.boolType);
 
     _assertSimpleParameter(
-        alias.parameters.parameters[1], aliasElement.parameters[1],
+        alias.parameters.parameters[1], aliasFunction.parameters[1],
         name: 'b',
         offset: 27,
         kind: ParameterKind.REQUIRED,
@@ -7759,7 +7767,7 @@
 
       SimpleIdentifier boundIdentifier = bound.name;
       expect(boundIdentifier.staticElement, same(aElement));
-      expect(boundIdentifier.staticType, interfaceType(aElement));
+      expect(boundIdentifier.staticType, isNull);
     }
 
     {
@@ -7777,14 +7785,14 @@
 
       SimpleIdentifier listIdentifier = bound.name;
       expect(listIdentifier.staticElement, same(listElement));
-      expect(listIdentifier.staticType, listOfA);
+      expect(listIdentifier.staticType, isNull);
 
       TypeName aTypeName = bound.typeArguments.arguments[0];
       expect(aTypeName.type, interfaceType(aElement));
 
       SimpleIdentifier aIdentifier = aTypeName.name;
       expect(aIdentifier.staticElement, same(aElement));
-      expect(aIdentifier.staticType, interfaceType(aElement));
+      expect(aIdentifier.staticType, isNull);
     }
 
     {
@@ -7921,7 +7929,7 @@
     var type = variableDeclarationStatement.variables.type as TypeName;
     expect(type.type, isDynamicType);
     var typeName = type.name;
-    assertTypeDynamic(typeName);
+    assertTypeNull(typeName);
     expect(typeName.staticElement, same(typeProvider.dynamicType.element));
   }
 
@@ -7945,7 +7953,7 @@
 
     SimpleIdentifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, same(aliasElement));
-    expect('${typeIdentifier.staticType}', 'int Function(bool)');
+    expect(typeIdentifier.staticType, isNull);
 
     List<TypeAnnotation> typeArguments = typeName.typeArguments.arguments;
     expect(typeArguments, hasLength(1));
@@ -7965,7 +7973,7 @@
     var type = variableDeclarationStatement.variables.type as TypeName;
     expect(type.type, isVoidType);
     var typeName = type.name;
-    expect(typeName.staticType, isVoidType);
+    expect(typeName.staticType, isNull);
     expect(typeName.staticElement, isNull);
   }
 
@@ -8085,7 +8093,7 @@
 
     SimpleIdentifier typeIdentifier = typeName.name;
     expect(typeIdentifier.staticElement, isNull);
-    expect(typeIdentifier.staticType, isDynamicType);
+    expect(typeIdentifier.staticType, isNull);
 
     assertTypeArguments(typeName.typeArguments, [intType, doubleType]);
     _assertInvocationArguments(creation.argumentList,
@@ -8176,7 +8184,6 @@
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
 
-  @failingTest
   test_unresolved_instanceCreation_name_31() async {
     addTestFile(r'''
 int arg1, arg2;
@@ -8218,7 +8225,6 @@
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
 
-  @failingTest
   test_unresolved_instanceCreation_name_32() async {
     addTestFile(r'''
 import 'dart:math' as foo;
@@ -8265,7 +8271,6 @@
         [checkTopVarRef('arg1'), checkTopVarUndefinedNamedRef('arg2')]);
   }
 
-  @failingTest
   test_unresolved_instanceCreation_name_33() async {
     addTestFile(r'''
 import 'dart:math' as foo;
@@ -8661,7 +8666,7 @@
 
     var bRef = findNode.simple('B.');
     assertElement(bRef, findElement.class_('B'));
-    assertType(bRef, 'B');
+    assertTypeNull(bRef);
 
     var namedRef = findNode.simple('named;');
     assertElementNull(namedRef);
@@ -8745,7 +8750,7 @@
 
     SimpleIdentifier typeIdentifier = typeName.name;
     assertElement(typeIdentifier, classElement);
-    assertType(typeIdentifier, classElement.name);
+    assertTypeNull(typeIdentifier);
 
     // Only unnamed constructors are supported now.
     expect(constructorName.name, isNull);
@@ -8806,7 +8811,7 @@
 
     SimpleIdentifier identifier = typeName.name;
     expect(identifier.staticElement, same(type.element));
-    expect(identifier.staticType, type);
+    expect(identifier.staticType, isNull);
   }
 
   List<Statement> _getMainStatements(ResolvedUnitResult result) {
diff --git a/pkg/analyzer/test/src/dart/ast/test_all.dart b/pkg/analyzer/test/src/dart/ast/test_all.dart
index 2f66d8c..937645a 100644
--- a/pkg/analyzer/test/src/dart/ast/test_all.dart
+++ b/pkg/analyzer/test/src/dart/ast/test_all.dart
@@ -7,6 +7,7 @@
 import 'ast_test.dart' as ast;
 import 'constant_evaluator_test.dart' as constant_evaluator;
 import 'element_locator_test.dart' as element_locator;
+import 'to_source_visitor_test.dart' as to_source_visitor;
 import 'utilities_test.dart' as utilities;
 
 main() {
@@ -14,6 +15,7 @@
     ast.main();
     constant_evaluator.main();
     element_locator.main();
+    to_source_visitor.main();
     utilities.main();
   }, name: 'ast');
 }
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
new file mode 100644
index 0000000..a56c686
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -0,0 +1,2834 @@
+// 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
+import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
+import 'package:analyzer/src/generated/testing/token_factory.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ToSourceVisitor2Test);
+  });
+}
+
+@reflectiveTest
+class ToSourceVisitor2Test {
+  void test_visitAdjacentStrings() {
+    _assertSource(
+        "'a' 'b'",
+        AstTestFactory.adjacentStrings(
+            [AstTestFactory.string2("a"), AstTestFactory.string2("b")]));
+  }
+
+  void test_visitAnnotation_constant() {
+    _assertSource(
+        "@A", AstTestFactory.annotation(AstTestFactory.identifier3("A")));
+  }
+
+  void test_visitAnnotation_constructor() {
+    _assertSource(
+        "@A.c()",
+        AstTestFactory.annotation2(AstTestFactory.identifier3("A"),
+            AstTestFactory.identifier3("c"), AstTestFactory.argumentList()));
+  }
+
+  void test_visitArgumentList() {
+    _assertSource(
+        "(a, b)",
+        AstTestFactory.argumentList([
+          AstTestFactory.identifier3("a"),
+          AstTestFactory.identifier3("b")
+        ]));
+  }
+
+  void test_visitAsExpression() {
+    _assertSource(
+        "e as T",
+        AstTestFactory.asExpression(
+            AstTestFactory.identifier3("e"), AstTestFactory.typeName4("T")));
+  }
+
+  void test_visitAssertStatement() {
+    _assertSource("assert (a);",
+        AstTestFactory.assertStatement(AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitAssertStatement_withMessage() {
+    _assertSource(
+        "assert (a, b);",
+        AstTestFactory.assertStatement(
+            AstTestFactory.identifier3("a"), AstTestFactory.identifier3('b')));
+  }
+
+  void test_visitAssignmentExpression() {
+    _assertSource(
+        "a = b",
+        AstTestFactory.assignmentExpression(AstTestFactory.identifier3("a"),
+            TokenType.EQ, AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitAwaitExpression() {
+    _assertSource("await e",
+        AstTestFactory.awaitExpression(AstTestFactory.identifier3("e")));
+  }
+
+  void test_visitBinaryExpression() {
+    _assertSource(
+        "a + b",
+        AstTestFactory.binaryExpression(AstTestFactory.identifier3("a"),
+            TokenType.PLUS, AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitBinaryExpression_precedence() {
+    var a = AstTestFactory.identifier3('a');
+    var b = AstTestFactory.identifier3('b');
+    var c = AstTestFactory.identifier3('c');
+    _assertSource(
+        'a * (b + c)',
+        AstTestFactory.binaryExpression(a, TokenType.STAR,
+            AstTestFactory.binaryExpression(b, TokenType.PLUS, c)));
+  }
+
+  void test_visitBlock_empty() {
+    _assertSource("{}", AstTestFactory.block());
+  }
+
+  void test_visitBlock_nonEmpty() {
+    _assertSource(
+        "{break; break;}",
+        AstTestFactory.block([
+          AstTestFactory.breakStatement(),
+          AstTestFactory.breakStatement()
+        ]));
+  }
+
+  void test_visitBlockFunctionBody_async() {
+    _assertSource("async {}", AstTestFactory.asyncBlockFunctionBody());
+  }
+
+  void test_visitBlockFunctionBody_async_star() {
+    _assertSource(
+        "async* {}", AstTestFactory.asyncGeneratorBlockFunctionBody());
+  }
+
+  void test_visitBlockFunctionBody_simple() {
+    _assertSource("{}", AstTestFactory.blockFunctionBody2());
+  }
+
+  void test_visitBlockFunctionBody_sync() {
+    _assertSource("sync {}", AstTestFactory.syncBlockFunctionBody());
+  }
+
+  void test_visitBlockFunctionBody_sync_star() {
+    _assertSource("sync* {}", AstTestFactory.syncGeneratorBlockFunctionBody());
+  }
+
+  void test_visitBooleanLiteral_false() {
+    _assertSource("false", AstTestFactory.booleanLiteral(false));
+  }
+
+  void test_visitBooleanLiteral_true() {
+    _assertSource("true", AstTestFactory.booleanLiteral(true));
+  }
+
+  void test_visitBreakStatement_label() {
+    _assertSource("break l;", AstTestFactory.breakStatement2("l"));
+  }
+
+  void test_visitBreakStatement_noLabel() {
+    _assertSource("break;", AstTestFactory.breakStatement());
+  }
+
+  void test_visitCascadeExpression_field() {
+    _assertSource(
+        "a..b..c",
+        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
+          AstTestFactory.cascadedPropertyAccess("b"),
+          AstTestFactory.cascadedPropertyAccess("c")
+        ]));
+  }
+
+  void test_visitCascadeExpression_index() {
+    _assertSource(
+        "a..[0]..[1]",
+        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
+          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(0)),
+          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(1))
+        ]));
+  }
+
+  void test_visitCascadeExpression_method() {
+    _assertSource(
+        "a..b()..c()",
+        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
+          AstTestFactory.cascadedMethodInvocation("b"),
+          AstTestFactory.cascadedMethodInvocation("c")
+        ]));
+  }
+
+  void test_visitCatchClause_catch_noStack() {
+    _assertSource("catch (e) {}", AstTestFactory.catchClause("e"));
+  }
+
+  void test_visitCatchClause_catch_stack() {
+    _assertSource("catch (e, s) {}", AstTestFactory.catchClause2("e", "s"));
+  }
+
+  void test_visitCatchClause_on() {
+    _assertSource(
+        "on E {}", AstTestFactory.catchClause3(AstTestFactory.typeName4("E")));
+  }
+
+  void test_visitCatchClause_on_catch() {
+    _assertSource("on E catch (e) {}",
+        AstTestFactory.catchClause4(AstTestFactory.typeName4("E"), "e"));
+  }
+
+  void test_visitClassDeclaration_abstract() {
+    _assertSource(
+        "abstract class C {}",
+        AstTestFactory.classDeclaration(
+            Keyword.ABSTRACT, "C", null, null, null, null));
+  }
+
+  void test_visitClassDeclaration_empty() {
+    _assertSource("class C {}",
+        AstTestFactory.classDeclaration(null, "C", null, null, null, null));
+  }
+
+  void test_visitClassDeclaration_extends() {
+    _assertSource(
+        "class C extends A {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            null,
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            null,
+            null));
+  }
+
+  void test_visitClassDeclaration_extends_implements() {
+    _assertSource(
+        "class C extends A implements B {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            null,
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            null,
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_extends_with() {
+    _assertSource(
+        "class C extends A with M {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            null,
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
+            null));
+  }
+
+  void test_visitClassDeclaration_extends_with_implements() {
+    _assertSource(
+        "class C extends A with M implements B {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            null,
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_implements() {
+    _assertSource(
+        "class C implements B {}",
+        AstTestFactory.classDeclaration(null, "C", null, null, null,
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_multipleMember() {
+    _assertSource(
+        "class C {var a; var b;}",
+        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
+          AstTestFactory.fieldDeclaration2(
+              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]),
+          AstTestFactory.fieldDeclaration2(
+              false, Keyword.VAR, [AstTestFactory.variableDeclaration("b")])
+        ]));
+  }
+
+  void test_visitClassDeclaration_parameters() {
+    _assertSource(
+        "class C<E> {}",
+        AstTestFactory.classDeclaration(null, "C",
+            AstTestFactory.typeParameterList(["E"]), null, null, null));
+  }
+
+  void test_visitClassDeclaration_parameters_extends() {
+    _assertSource(
+        "class C<E> extends A {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            null,
+            null));
+  }
+
+  void test_visitClassDeclaration_parameters_extends_implements() {
+    _assertSource(
+        "class C<E> extends A implements B {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            null,
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_parameters_extends_with() {
+    _assertSource(
+        "class C<E> extends A with M {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
+            null));
+  }
+
+  void test_visitClassDeclaration_parameters_extends_with_implements() {
+    _assertSource(
+        "class C<E> extends A with M implements B {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_parameters_implements() {
+    _assertSource(
+        "class C<E> implements B {}",
+        AstTestFactory.classDeclaration(
+            null,
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            null,
+            null,
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
+  }
+
+  void test_visitClassDeclaration_singleMember() {
+    _assertSource(
+        "class C {var a;}",
+        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
+          AstTestFactory.fieldDeclaration2(
+              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
+        ]));
+  }
+
+  void test_visitClassDeclaration_withMetadata() {
+    ClassDeclaration declaration =
+        AstTestFactory.classDeclaration(null, "C", null, null, null, null);
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated class C {}", declaration);
+  }
+
+  void test_visitClassTypeAlias_abstract() {
+    _assertSource(
+        "abstract class C = S with M1;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            null,
+            Keyword.ABSTRACT,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            null));
+  }
+
+  void test_visitClassTypeAlias_abstract_implements() {
+    _assertSource(
+        "abstract class C = S with M1 implements I;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            null,
+            Keyword.ABSTRACT,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
+  }
+
+  void test_visitClassTypeAlias_generic() {
+    _assertSource(
+        "class C<E> = S<E> with M1<E>;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            null,
+            AstTestFactory.typeName4("S", [AstTestFactory.typeName4("E")]),
+            AstTestFactory.withClause([
+              AstTestFactory.typeName4("M1", [AstTestFactory.typeName4("E")])
+            ]),
+            null));
+  }
+
+  void test_visitClassTypeAlias_implements() {
+    _assertSource(
+        "class C = S with M1 implements I;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            null,
+            null,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
+  }
+
+  void test_visitClassTypeAlias_minimal() {
+    _assertSource(
+        "class C = S with M1;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            null,
+            null,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            null));
+  }
+
+  void test_visitClassTypeAlias_parameters_abstract() {
+    _assertSource(
+        "abstract class C<E> = S with M1;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            Keyword.ABSTRACT,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            null));
+  }
+
+  void test_visitClassTypeAlias_parameters_abstract_implements() {
+    _assertSource(
+        "abstract class C<E> = S with M1 implements I;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            Keyword.ABSTRACT,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
+  }
+
+  void test_visitClassTypeAlias_parameters_implements() {
+    _assertSource(
+        "class C<E> = S with M1 implements I;",
+        AstTestFactory.classTypeAlias(
+            "C",
+            AstTestFactory.typeParameterList(["E"]),
+            null,
+            AstTestFactory.typeName4("S"),
+            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
+  }
+
+  void test_visitClassTypeAlias_withMetadata() {
+    ClassTypeAlias declaration = AstTestFactory.classTypeAlias(
+        "C",
+        null,
+        null,
+        AstTestFactory.typeName4("S"),
+        AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
+        null);
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated class C = S with M1;", declaration);
+  }
+
+  void test_visitComment() {
+    _assertSource(
+        "",
+        astFactory.blockComment(
+            <Token>[TokenFactory.tokenFromString("/* comment */")]));
+  }
+
+  void test_visitCommentReference() {
+    _assertSource(
+        "", astFactory.commentReference(null, AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitCompilationUnit_declaration() {
+    _assertSource(
+        "var a;",
+        AstTestFactory.compilationUnit2([
+          AstTestFactory.topLevelVariableDeclaration2(
+              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
+        ]));
+  }
+
+  void test_visitCompilationUnit_directive() {
+    _assertSource(
+        "library l;",
+        AstTestFactory.compilationUnit3(
+            [AstTestFactory.libraryDirective2("l")]));
+  }
+
+  void test_visitCompilationUnit_directive_declaration() {
+    _assertSource(
+        "library l; var a;",
+        AstTestFactory.compilationUnit4([
+          AstTestFactory.libraryDirective2("l")
+        ], [
+          AstTestFactory.topLevelVariableDeclaration2(
+              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
+        ]));
+  }
+
+  void test_visitCompilationUnit_empty() {
+    _assertSource("", AstTestFactory.compilationUnit());
+  }
+
+  void test_visitCompilationUnit_script() {
+    _assertSource(
+        "!#/bin/dartvm", AstTestFactory.compilationUnit5("!#/bin/dartvm"));
+  }
+
+  void test_visitCompilationUnit_script_declaration() {
+    _assertSource(
+        "!#/bin/dartvm var a;",
+        AstTestFactory.compilationUnit6("!#/bin/dartvm", [
+          AstTestFactory.topLevelVariableDeclaration2(
+              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
+        ]));
+  }
+
+  void test_visitCompilationUnit_script_directive() {
+    _assertSource(
+        "!#/bin/dartvm library l;",
+        AstTestFactory.compilationUnit7(
+            "!#/bin/dartvm", [AstTestFactory.libraryDirective2("l")]));
+  }
+
+  void test_visitCompilationUnit_script_directives_declarations() {
+    _assertSource(
+        "!#/bin/dartvm library l; var a;",
+        AstTestFactory.compilationUnit8("!#/bin/dartvm", [
+          AstTestFactory.libraryDirective2("l")
+        ], [
+          AstTestFactory.topLevelVariableDeclaration2(
+              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
+        ]));
+  }
+
+  void test_visitConditionalExpression() {
+    _assertSource(
+        "a ? b : c",
+        AstTestFactory.conditionalExpression(AstTestFactory.identifier3("a"),
+            AstTestFactory.identifier3("b"), AstTestFactory.identifier3("c")));
+  }
+
+  void test_visitConstructorDeclaration_const() {
+    _assertSource(
+        "const C() {}",
+        AstTestFactory.constructorDeclaration2(
+            Keyword.CONST,
+            null,
+            AstTestFactory.identifier3("C"),
+            null,
+            AstTestFactory.formalParameterList(),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_external() {
+    _assertSource(
+        "external C();",
+        AstTestFactory.constructorDeclaration(AstTestFactory.identifier3("C"),
+            null, AstTestFactory.formalParameterList(), null));
+  }
+
+  void test_visitConstructorDeclaration_minimal() {
+    _assertSource(
+        "C() {}",
+        AstTestFactory.constructorDeclaration2(
+            null,
+            null,
+            AstTestFactory.identifier3("C"),
+            null,
+            AstTestFactory.formalParameterList(),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_multipleInitializers() {
+    _assertSource(
+        "C() : a = b, c = d {}",
+        AstTestFactory.constructorDeclaration2(
+            null,
+            null,
+            AstTestFactory.identifier3("C"),
+            null,
+            AstTestFactory.formalParameterList(),
+            [
+              AstTestFactory.constructorFieldInitializer(
+                  false, "a", AstTestFactory.identifier3("b")),
+              AstTestFactory.constructorFieldInitializer(
+                  false, "c", AstTestFactory.identifier3("d"))
+            ],
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_multipleParameters() {
+    _assertSource(
+        "C(var a, var b) {}",
+        AstTestFactory.constructorDeclaration2(
+            null,
+            null,
+            AstTestFactory.identifier3("C"),
+            null,
+            AstTestFactory.formalParameterList([
+              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
+              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
+            ]),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_named() {
+    _assertSource(
+        "C.m() {}",
+        AstTestFactory.constructorDeclaration2(
+            null,
+            null,
+            AstTestFactory.identifier3("C"),
+            "m",
+            AstTestFactory.formalParameterList(),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_singleInitializer() {
+    _assertSource(
+        "C() : a = b {}",
+        AstTestFactory.constructorDeclaration2(
+            null,
+            null,
+            AstTestFactory.identifier3("C"),
+            null,
+            AstTestFactory.formalParameterList(),
+            [
+              AstTestFactory.constructorFieldInitializer(
+                  false, "a", AstTestFactory.identifier3("b"))
+            ],
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitConstructorDeclaration_withMetadata() {
+    ConstructorDeclaration declaration = AstTestFactory.constructorDeclaration2(
+        null,
+        null,
+        AstTestFactory.identifier3("C"),
+        null,
+        AstTestFactory.formalParameterList(),
+        null,
+        AstTestFactory.blockFunctionBody2());
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated C() {}", declaration);
+  }
+
+  void test_visitConstructorFieldInitializer_withoutThis() {
+    _assertSource(
+        "a = b",
+        AstTestFactory.constructorFieldInitializer(
+            false, "a", AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitConstructorFieldInitializer_withThis() {
+    _assertSource(
+        "this.a = b",
+        AstTestFactory.constructorFieldInitializer(
+            true, "a", AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitConstructorName_named_prefix() {
+    _assertSource(
+        "p.C.n",
+        AstTestFactory.constructorName(
+            AstTestFactory.typeName4("p.C.n"), null));
+  }
+
+  void test_visitConstructorName_unnamed_noPrefix() {
+    _assertSource("C",
+        AstTestFactory.constructorName(AstTestFactory.typeName4("C"), null));
+  }
+
+  void test_visitConstructorName_unnamed_prefix() {
+    _assertSource(
+        "p.C",
+        AstTestFactory.constructorName(
+            AstTestFactory.typeName3(AstTestFactory.identifier5("p", "C")),
+            null));
+  }
+
+  void test_visitContinueStatement_label() {
+    _assertSource("continue l;", AstTestFactory.continueStatement("l"));
+  }
+
+  void test_visitContinueStatement_noLabel() {
+    _assertSource("continue;", AstTestFactory.continueStatement());
+  }
+
+  void test_visitDefaultFormalParameter_annotation() {
+    DefaultFormalParameter parameter = AstTestFactory.positionalFormalParameter(
+        AstTestFactory.simpleFormalParameter3("p"), AstTestFactory.integer(0));
+    parameter.metadata
+        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
+    _assertSource('@A p = 0', parameter);
+  }
+
+  void test_visitDefaultFormalParameter_named_noValue() {
+    _assertSource(
+        "p",
+        AstTestFactory.namedFormalParameter(
+            AstTestFactory.simpleFormalParameter3("p"), null));
+  }
+
+  void test_visitDefaultFormalParameter_named_value() {
+    _assertSource(
+        "p: 0",
+        AstTestFactory.namedFormalParameter(
+            AstTestFactory.simpleFormalParameter3("p"),
+            AstTestFactory.integer(0)));
+  }
+
+  void test_visitDefaultFormalParameter_positional_noValue() {
+    _assertSource(
+        "p",
+        AstTestFactory.positionalFormalParameter(
+            AstTestFactory.simpleFormalParameter3("p"), null));
+  }
+
+  void test_visitDefaultFormalParameter_positional_value() {
+    _assertSource(
+        "p = 0",
+        AstTestFactory.positionalFormalParameter(
+            AstTestFactory.simpleFormalParameter3("p"),
+            AstTestFactory.integer(0)));
+  }
+
+  void test_visitDoStatement() {
+    _assertSource(
+        "do {} while (c);",
+        AstTestFactory.doStatement(
+            AstTestFactory.block(), AstTestFactory.identifier3("c")));
+  }
+
+  void test_visitDoubleLiteral() {
+    _assertSource("4.2", AstTestFactory.doubleLiteral(4.2));
+  }
+
+  void test_visitEmptyFunctionBody() {
+    _assertSource(";", AstTestFactory.emptyFunctionBody());
+  }
+
+  void test_visitEmptyStatement() {
+    _assertSource(";", AstTestFactory.emptyStatement());
+  }
+
+  void test_visitEnumDeclaration_multiple() {
+    _assertSource("enum E {ONE, TWO}",
+        AstTestFactory.enumDeclaration2("E", ["ONE", "TWO"]));
+  }
+
+  void test_visitEnumDeclaration_single() {
+    _assertSource(
+        "enum E {ONE}", AstTestFactory.enumDeclaration2("E", ["ONE"]));
+  }
+
+  void test_visitExportDirective_combinator() {
+    _assertSource(
+        "export 'a.dart' show A;",
+        AstTestFactory.exportDirective2("a.dart", [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
+        ]));
+  }
+
+  void test_visitExportDirective_combinators() {
+    _assertSource(
+        "export 'a.dart' show A hide B;",
+        AstTestFactory.exportDirective2("a.dart", [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
+          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
+        ]));
+  }
+
+  void test_visitExportDirective_minimal() {
+    _assertSource(
+        "export 'a.dart';", AstTestFactory.exportDirective2("a.dart"));
+  }
+
+  void test_visitExportDirective_withMetadata() {
+    ExportDirective directive = AstTestFactory.exportDirective2("a.dart");
+    directive.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated export 'a.dart';", directive);
+  }
+
+  void test_visitExpressionFunctionBody_async() {
+    _assertSource(
+        "async => a;",
+        AstTestFactory.asyncExpressionFunctionBody(
+            AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitExpressionFunctionBody_simple() {
+    _assertSource("=> a;",
+        AstTestFactory.expressionFunctionBody(AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitExpressionStatement() {
+    _assertSource("a;",
+        AstTestFactory.expressionStatement(AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitExtendsClause() {
+    _assertSource("extends C",
+        AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitExtensionDeclaration_empty() {
+    _assertSource(
+        'extension E on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E', extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_multipleMember() {
+    _assertSource(
+        'extension E on C {var a; var b;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+                  [AstTestFactory.variableDeclaration('a')]),
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+            ]));
+  }
+
+  void test_visitExtensionDeclaration_parameters() {
+    _assertSource(
+        'extension E<T> on C {}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            typeParameters: AstTestFactory.typeParameterList(['T']),
+            extendedType: AstTestFactory.typeName4('C')));
+  }
+
+  void test_visitExtensionDeclaration_singleMember() {
+    _assertSource(
+        'extension E on C {var a;}',
+        AstTestFactory.extensionDeclaration(
+            name: 'E',
+            extendedType: AstTestFactory.typeName4('C'),
+            members: [
+              AstTestFactory.fieldDeclaration2(
+                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+            ]));
+  }
+
+  void test_visitExtensionOverride_prefixedName_noTypeArgs() {
+    _assertSource(
+        'p.E(o)',
+        AstTestFactory.extensionOverride(
+            extensionName: AstTestFactory.identifier5('p', 'E'),
+            argumentList: AstTestFactory.argumentList(
+                [AstTestFactory.identifier3('o')])));
+  }
+
+  void test_visitExtensionOverride_prefixedName_typeArgs() {
+    _assertSource(
+        'p.E<A>(o)',
+        AstTestFactory.extensionOverride(
+            extensionName: AstTestFactory.identifier5('p', 'E'),
+            typeArguments: AstTestFactory.typeArgumentList(
+                [AstTestFactory.typeName4('A')]),
+            argumentList: AstTestFactory.argumentList(
+                [AstTestFactory.identifier3('o')])));
+  }
+
+  void test_visitExtensionOverride_simpleName_noTypeArgs() {
+    _assertSource(
+        'E(o)',
+        AstTestFactory.extensionOverride(
+            extensionName: AstTestFactory.identifier3('E'),
+            argumentList: AstTestFactory.argumentList(
+                [AstTestFactory.identifier3('o')])));
+  }
+
+  void test_visitExtensionOverride_simpleName_typeArgs() {
+    _assertSource(
+        'E<A>(o)',
+        AstTestFactory.extensionOverride(
+            extensionName: AstTestFactory.identifier3('E'),
+            typeArguments: AstTestFactory.typeArgumentList(
+                [AstTestFactory.typeName4('A')]),
+            argumentList: AstTestFactory.argumentList(
+                [AstTestFactory.identifier3('o')])));
+  }
+
+  void test_visitFieldDeclaration_instance() {
+    _assertSource(
+        "var a;",
+        AstTestFactory.fieldDeclaration2(
+            false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
+  }
+
+  void test_visitFieldDeclaration_static() {
+    _assertSource(
+        "static var a;",
+        AstTestFactory.fieldDeclaration2(
+            true, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
+  }
+
+  void test_visitFieldDeclaration_withMetadata() {
+    FieldDeclaration declaration = AstTestFactory.fieldDeclaration2(
+        false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]);
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated var a;", declaration);
+  }
+
+  void test_visitFieldFormalParameter_annotation() {
+    FieldFormalParameter parameter = AstTestFactory.fieldFormalParameter2('f');
+    parameter.metadata
+        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
+    _assertSource('@A this.f', parameter);
+  }
+
+  void test_visitFieldFormalParameter_functionTyped() {
+    _assertSource(
+        "A this.a(b)",
+        AstTestFactory.fieldFormalParameter(
+            null,
+            AstTestFactory.typeName4("A"),
+            "a",
+            AstTestFactory.formalParameterList(
+                [AstTestFactory.simpleFormalParameter3("b")])));
+  }
+
+  void test_visitFieldFormalParameter_functionTyped_typeParameters() {
+    _assertSource(
+        "A this.a<E, F>(b)",
+        astFactory.fieldFormalParameter2(
+            type: AstTestFactory.typeName4('A'),
+            thisKeyword: TokenFactory.tokenFromKeyword(Keyword.THIS),
+            period: TokenFactory.tokenFromType(TokenType.PERIOD),
+            identifier: AstTestFactory.identifier3('a'),
+            typeParameters: AstTestFactory.typeParameterList(['E', 'F']),
+            parameters: AstTestFactory.formalParameterList(
+                [AstTestFactory.simpleFormalParameter3("b")])));
+  }
+
+  void test_visitFieldFormalParameter_keyword() {
+    _assertSource("var this.a",
+        AstTestFactory.fieldFormalParameter(Keyword.VAR, null, "a"));
+  }
+
+  void test_visitFieldFormalParameter_keywordAndType() {
+    _assertSource(
+        "final A this.a",
+        AstTestFactory.fieldFormalParameter(
+            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
+  }
+
+  void test_visitFieldFormalParameter_type() {
+    _assertSource(
+        "A this.a",
+        AstTestFactory.fieldFormalParameter(
+            null, AstTestFactory.typeName4("A"), "a"));
+  }
+
+  void test_visitFieldFormalParameter_type_covariant() {
+    FieldFormalParameterImpl expected = AstTestFactory.fieldFormalParameter(
+        null, AstTestFactory.typeName4("A"), "a");
+    expected.covariantKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
+    _assertSource("covariant A this.a", expected);
+  }
+
+  void test_visitForEachPartsWithDeclaration() {
+    _assertSource(
+        'var e in l',
+        astFactory.forEachPartsWithDeclaration(
+            loopVariable: AstTestFactory.declaredIdentifier3('e'),
+            iterable: AstTestFactory.identifier3('l')));
+  }
+
+  void test_visitForEachPartsWithIdentifier() {
+    _assertSource(
+        'e in l',
+        astFactory.forEachPartsWithIdentifier(
+            identifier: AstTestFactory.identifier3('e'),
+            iterable: AstTestFactory.identifier3('l')));
+  }
+
+  void test_visitForEachStatement_declared() {
+    _assertSource(
+        "for (var a in b) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forEachPartsWithDeclaration(
+                AstTestFactory.declaredIdentifier3("a"),
+                AstTestFactory.identifier3("b")),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForEachStatement_variable() {
+    _assertSource(
+        "for (a in b) {}",
+        astFactory.forStatement(
+            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3("a"),
+                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
+                iterable: AstTestFactory.identifier3("b")),
+            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+            body: AstTestFactory.block()));
+  }
+
+  void test_visitForEachStatement_variable_await() {
+    _assertSource(
+        "await for (a in b) {}",
+        astFactory.forStatement(
+            awaitKeyword: TokenFactory.tokenFromString("await"),
+            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
+            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3("a"),
+                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
+                iterable: AstTestFactory.identifier3("b")),
+            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
+            body: AstTestFactory.block()));
+  }
+
+  void test_visitForElement() {
+    _assertSource(
+        'for (e in l) 0',
+        astFactory.forElement(
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3('e'),
+                iterable: AstTestFactory.identifier3('l')),
+            body: AstTestFactory.integer(0)));
+  }
+
+  void test_visitFormalParameterList_empty() {
+    _assertSource("()", AstTestFactory.formalParameterList());
+  }
+
+  void test_visitFormalParameterList_n() {
+    _assertSource(
+        "({a: 0})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("a"),
+              AstTestFactory.integer(0))
+        ]));
+  }
+
+  void test_visitFormalParameterList_nn() {
+    _assertSource(
+        "({a: 0, b: 1})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("a"),
+              AstTestFactory.integer(0)),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1))
+        ]));
+  }
+
+  void test_visitFormalParameterList_p() {
+    _assertSource(
+        "([a = 0])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("a"),
+              AstTestFactory.integer(0))
+        ]));
+  }
+
+  void test_visitFormalParameterList_pp() {
+    _assertSource(
+        "([a = 0, b = 1])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("a"),
+              AstTestFactory.integer(0)),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1))
+        ]));
+  }
+
+  void test_visitFormalParameterList_r() {
+    _assertSource(
+        "(a)",
+        AstTestFactory.formalParameterList(
+            [AstTestFactory.simpleFormalParameter3("a")]));
+  }
+
+  void test_visitFormalParameterList_rn() {
+    _assertSource(
+        "(a, {b: 1})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rnn() {
+    _assertSource(
+        "(a, {b: 1, c: 2})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1)),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(2))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rp() {
+    _assertSource(
+        "(a, [b = 1])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rpp() {
+    _assertSource(
+        "(a, [b = 1, c = 2])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("b"),
+              AstTestFactory.integer(1)),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(2))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rr() {
+    _assertSource(
+        "(a, b)",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.simpleFormalParameter3("b")
+        ]));
+  }
+
+  void test_visitFormalParameterList_rrn() {
+    _assertSource(
+        "(a, b, {c: 3})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.simpleFormalParameter3("b"),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(3))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rrnn() {
+    _assertSource(
+        "(a, b, {c: 3, d: 4})",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.simpleFormalParameter3("b"),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(3)),
+          AstTestFactory.namedFormalParameter(
+              AstTestFactory.simpleFormalParameter3("d"),
+              AstTestFactory.integer(4))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rrp() {
+    _assertSource(
+        "(a, b, [c = 3])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.simpleFormalParameter3("b"),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(3))
+        ]));
+  }
+
+  void test_visitFormalParameterList_rrpp() {
+    _assertSource(
+        "(a, b, [c = 3, d = 4])",
+        AstTestFactory.formalParameterList([
+          AstTestFactory.simpleFormalParameter3("a"),
+          AstTestFactory.simpleFormalParameter3("b"),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("c"),
+              AstTestFactory.integer(3)),
+          AstTestFactory.positionalFormalParameter(
+              AstTestFactory.simpleFormalParameter3("d"),
+              AstTestFactory.integer(4))
+        ]));
+  }
+
+  void test_visitForPartsWithDeclarations() {
+    _assertSource(
+        'var v; b; u',
+        astFactory.forPartsWithDeclarations(
+            variables: AstTestFactory.variableDeclarationList2(
+                Keyword.VAR, [AstTestFactory.variableDeclaration('v')]),
+            condition: AstTestFactory.identifier3('b'),
+            updaters: [AstTestFactory.identifier3('u')]));
+  }
+
+  void test_visitForPartsWithExpression() {
+    _assertSource(
+        'v; b; u',
+        astFactory.forPartsWithExpression(
+            initialization: AstTestFactory.identifier3('v'),
+            condition: AstTestFactory.identifier3('b'),
+            updaters: [AstTestFactory.identifier3('u')]));
+  }
+
+  void test_visitForStatement() {
+    _assertSource(
+        'for (e in l) s;',
+        astFactory.forStatement(
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3('e'),
+                iterable: AstTestFactory.identifier3('l')),
+            body: AstTestFactory.expressionStatement(
+                AstTestFactory.identifier3('s'))));
+  }
+
+  void test_visitForStatement_c() {
+    _assertSource(
+        "for (; c;) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                null, AstTestFactory.identifier3("c"), null),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_cu() {
+    _assertSource(
+        "for (; c; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                null,
+                AstTestFactory.identifier3("c"),
+                [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_e() {
+    _assertSource(
+        "for (e;;) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                AstTestFactory.identifier3("e"), null, null),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_ec() {
+    _assertSource(
+        "for (e; c;) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                AstTestFactory.identifier3("e"),
+                AstTestFactory.identifier3("c"),
+                null),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_ecu() {
+    _assertSource(
+        "for (e; c; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                AstTestFactory.identifier3("e"),
+                AstTestFactory.identifier3("c"),
+                [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_eu() {
+    _assertSource(
+        "for (e;; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                AstTestFactory.identifier3("e"),
+                null,
+                [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_i() {
+    _assertSource(
+        "for (var i;;) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithDeclarations(
+                AstTestFactory.variableDeclarationList2(
+                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
+                null,
+                null),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_ic() {
+    _assertSource(
+        "for (var i; c;) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithDeclarations(
+                AstTestFactory.variableDeclarationList2(
+                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
+                AstTestFactory.identifier3("c"),
+                null),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_icu() {
+    _assertSource(
+        "for (var i; c; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithDeclarations(
+                AstTestFactory.variableDeclarationList2(
+                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
+                AstTestFactory.identifier3("c"),
+                [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_iu() {
+    _assertSource(
+        "for (var i;; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithDeclarations(
+                AstTestFactory.variableDeclarationList2(
+                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
+                null,
+                [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitForStatement_u() {
+    _assertSource(
+        "for (;; u) {}",
+        AstTestFactory.forStatement(
+            AstTestFactory.forPartsWithExpression(
+                null, null, [AstTestFactory.identifier3("u")]),
+            AstTestFactory.block()));
+  }
+
+  void test_visitFunctionDeclaration_external() {
+    FunctionDeclaration functionDeclaration =
+        AstTestFactory.functionDeclaration(
+            null,
+            null,
+            "f",
+            AstTestFactory.functionExpression2(
+                AstTestFactory.formalParameterList(),
+                AstTestFactory.emptyFunctionBody()));
+    functionDeclaration.externalKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
+    _assertSource("external f();", functionDeclaration);
+  }
+
+  void test_visitFunctionDeclaration_getter() {
+    _assertSource(
+        "get f() {}",
+        AstTestFactory.functionDeclaration(
+            null, Keyword.GET, "f", AstTestFactory.functionExpression()));
+  }
+
+  void test_visitFunctionDeclaration_local_blockBody() {
+    FunctionDeclaration f = AstTestFactory.functionDeclaration(
+        null, null, "f", AstTestFactory.functionExpression());
+    FunctionDeclarationStatement fStatement =
+        astFactory.functionDeclarationStatement(f);
+    _assertSource(
+        "main() {f() {} 42;}",
+        AstTestFactory.functionDeclaration(
+            null,
+            null,
+            "main",
+            AstTestFactory.functionExpression2(
+                AstTestFactory.formalParameterList(),
+                AstTestFactory.blockFunctionBody2([
+                  fStatement,
+                  AstTestFactory.expressionStatement(AstTestFactory.integer(42))
+                ]))));
+  }
+
+  void test_visitFunctionDeclaration_local_expressionBody() {
+    FunctionDeclaration f = AstTestFactory.functionDeclaration(
+        null,
+        null,
+        "f",
+        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
+            AstTestFactory.expressionFunctionBody(AstTestFactory.integer(1))));
+    FunctionDeclarationStatement fStatement =
+        astFactory.functionDeclarationStatement(f);
+    _assertSource(
+        "main() {f() => 1; 2;}",
+        AstTestFactory.functionDeclaration(
+            null,
+            null,
+            "main",
+            AstTestFactory.functionExpression2(
+                AstTestFactory.formalParameterList(),
+                AstTestFactory.blockFunctionBody2([
+                  fStatement,
+                  AstTestFactory.expressionStatement(AstTestFactory.integer(2))
+                ]))));
+  }
+
+  void test_visitFunctionDeclaration_normal() {
+    _assertSource(
+        "f() {}",
+        AstTestFactory.functionDeclaration(
+            null, null, "f", AstTestFactory.functionExpression()));
+  }
+
+  void test_visitFunctionDeclaration_setter() {
+    _assertSource(
+        "set f() {}",
+        AstTestFactory.functionDeclaration(
+            null, Keyword.SET, "f", AstTestFactory.functionExpression()));
+  }
+
+  void test_visitFunctionDeclaration_typeParameters() {
+    _assertSource(
+        "f<E>() {}",
+        AstTestFactory.functionDeclaration(
+            null,
+            null,
+            "f",
+            AstTestFactory.functionExpression3(
+                AstTestFactory.typeParameterList(['E']),
+                AstTestFactory.formalParameterList(),
+                AstTestFactory.blockFunctionBody2())));
+  }
+
+  void test_visitFunctionDeclaration_withMetadata() {
+    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
+        null, null, "f", AstTestFactory.functionExpression());
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated f() {}", declaration);
+  }
+
+  void test_visitFunctionDeclarationStatement() {
+    _assertSource(
+        "f() {}",
+        AstTestFactory.functionDeclarationStatement(
+            null, null, "f", AstTestFactory.functionExpression()));
+  }
+
+  void test_visitFunctionExpression() {
+    _assertSource("() {}", AstTestFactory.functionExpression());
+  }
+
+  void test_visitFunctionExpression_typeParameters() {
+    _assertSource(
+        "<E>() {}",
+        AstTestFactory.functionExpression3(
+            AstTestFactory.typeParameterList(['E']),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitFunctionExpressionInvocation_minimal() {
+    _assertSource(
+        "f()",
+        AstTestFactory.functionExpressionInvocation(
+            AstTestFactory.identifier3("f")));
+  }
+
+  void test_visitFunctionExpressionInvocation_typeArguments() {
+    _assertSource(
+        "f<A>()",
+        AstTestFactory.functionExpressionInvocation2(
+            AstTestFactory.identifier3("f"),
+            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
+  }
+
+  void test_visitFunctionTypeAlias_generic() {
+    _assertSource(
+        "typedef A F<B>();",
+        AstTestFactory.typeAlias(
+            AstTestFactory.typeName4("A"),
+            "F",
+            AstTestFactory.typeParameterList(["B"]),
+            AstTestFactory.formalParameterList()));
+  }
+
+  void test_visitFunctionTypeAlias_nonGeneric() {
+    _assertSource(
+        "typedef A F();",
+        AstTestFactory.typeAlias(AstTestFactory.typeName4("A"), "F", null,
+            AstTestFactory.formalParameterList()));
+  }
+
+  void test_visitFunctionTypeAlias_withMetadata() {
+    FunctionTypeAlias declaration = AstTestFactory.typeAlias(
+        AstTestFactory.typeName4("A"),
+        "F",
+        null,
+        AstTestFactory.formalParameterList());
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated typedef A F();", declaration);
+  }
+
+  void test_visitFunctionTypedFormalParameter_annotation() {
+    FunctionTypedFormalParameter parameter =
+        AstTestFactory.functionTypedFormalParameter(null, "f");
+    parameter.metadata
+        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
+    _assertSource('@A f()', parameter);
+  }
+
+  void test_visitFunctionTypedFormalParameter_noType() {
+    _assertSource(
+        "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
+  }
+
+  void test_visitFunctionTypedFormalParameter_nullable() {
+    _assertSource(
+        "T f()?",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            parameters: AstTestFactory.formalParameterList([]),
+            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+  }
+
+  void test_visitFunctionTypedFormalParameter_type() {
+    _assertSource(
+        "T f()",
+        AstTestFactory.functionTypedFormalParameter(
+            AstTestFactory.typeName4("T"), "f"));
+  }
+
+  void test_visitFunctionTypedFormalParameter_type_covariant() {
+    FunctionTypedFormalParameterImpl expected =
+        AstTestFactory.functionTypedFormalParameter(
+            AstTestFactory.typeName4("T"), "f");
+    expected.covariantKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
+    _assertSource("covariant T f()", expected);
+  }
+
+  void test_visitFunctionTypedFormalParameter_typeParameters() {
+    _assertSource(
+        "T f<E>()",
+        astFactory.functionTypedFormalParameter2(
+            returnType: AstTestFactory.typeName4("T"),
+            identifier: AstTestFactory.identifier3('f'),
+            typeParameters: AstTestFactory.typeParameterList(['E']),
+            parameters: AstTestFactory.formalParameterList([])));
+  }
+
+  void test_visitGenericFunctionType() {
+    _assertSource(
+        "int Function<T>(T)",
+        AstTestFactory.genericFunctionType(
+            AstTestFactory.typeName4("int"),
+            AstTestFactory.typeParameterList(['T']),
+            AstTestFactory.formalParameterList([
+              AstTestFactory.simpleFormalParameter4(
+                  AstTestFactory.typeName4("T"), null)
+            ])));
+  }
+
+  void test_visitGenericFunctionType_withQuestion() {
+    _assertSource(
+        "int Function<T>(T)?",
+        AstTestFactory.genericFunctionType(
+            AstTestFactory.typeName4("int"),
+            AstTestFactory.typeParameterList(['T']),
+            AstTestFactory.formalParameterList([
+              AstTestFactory.simpleFormalParameter4(
+                  AstTestFactory.typeName4("T"), null)
+            ]),
+            question: true));
+  }
+
+  void test_visitGenericTypeAlias() {
+    _assertSource(
+        "typedef X<S> = S Function<T>(T)",
+        AstTestFactory.genericTypeAlias(
+            'X',
+            AstTestFactory.typeParameterList(['S']),
+            AstTestFactory.genericFunctionType(
+                AstTestFactory.typeName4("S"),
+                AstTestFactory.typeParameterList(['T']),
+                AstTestFactory.formalParameterList([
+                  AstTestFactory.simpleFormalParameter4(
+                      AstTestFactory.typeName4("T"), null)
+                ]))));
+  }
+
+  void test_visitIfElement_else() {
+    _assertSource(
+        'if (b) 1 else 0',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1),
+            elseElement: AstTestFactory.integer(0)));
+  }
+
+  void test_visitIfElement_then() {
+    _assertSource(
+        'if (b) 1',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1)));
+  }
+
+  void test_visitIfStatement_withElse() {
+    _assertSource(
+        "if (c) {} else {}",
+        AstTestFactory.ifStatement2(AstTestFactory.identifier3("c"),
+            AstTestFactory.block(), AstTestFactory.block()));
+  }
+
+  void test_visitIfStatement_withoutElse() {
+    _assertSource(
+        "if (c) {}",
+        AstTestFactory.ifStatement(
+            AstTestFactory.identifier3("c"), AstTestFactory.block()));
+  }
+
+  void test_visitImplementsClause_multiple() {
+    _assertSource(
+        "implements A, B",
+        AstTestFactory.implementsClause(
+            [AstTestFactory.typeName4("A"), AstTestFactory.typeName4("B")]));
+  }
+
+  void test_visitImplementsClause_single() {
+    _assertSource("implements A",
+        AstTestFactory.implementsClause([AstTestFactory.typeName4("A")]));
+  }
+
+  void test_visitImportDirective_combinator() {
+    _assertSource(
+        "import 'a.dart' show A;",
+        AstTestFactory.importDirective3("a.dart", null, [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
+        ]));
+  }
+
+  void test_visitImportDirective_combinators() {
+    _assertSource(
+        "import 'a.dart' show A hide B;",
+        AstTestFactory.importDirective3("a.dart", null, [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
+          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
+        ]));
+  }
+
+  void test_visitImportDirective_deferred() {
+    _assertSource("import 'a.dart' deferred as p;",
+        AstTestFactory.importDirective2("a.dart", true, "p"));
+  }
+
+  void test_visitImportDirective_minimal() {
+    _assertSource(
+        "import 'a.dart';", AstTestFactory.importDirective3("a.dart", null));
+  }
+
+  void test_visitImportDirective_prefix() {
+    _assertSource("import 'a.dart' as p;",
+        AstTestFactory.importDirective3("a.dart", "p"));
+  }
+
+  void test_visitImportDirective_prefix_combinator() {
+    _assertSource(
+        "import 'a.dart' as p show A;",
+        AstTestFactory.importDirective3("a.dart", "p", [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
+        ]));
+  }
+
+  void test_visitImportDirective_prefix_combinators() {
+    _assertSource(
+        "import 'a.dart' as p show A hide B;",
+        AstTestFactory.importDirective3("a.dart", "p", [
+          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
+          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
+        ]));
+  }
+
+  void test_visitImportDirective_withMetadata() {
+    ImportDirective directive = AstTestFactory.importDirective3("a.dart", null);
+    directive.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated import 'a.dart';", directive);
+  }
+
+  void test_visitImportHideCombinator_multiple() {
+    _assertSource(
+        "hide a, b",
+        AstTestFactory.hideCombinator([
+          AstTestFactory.identifier3("a"),
+          AstTestFactory.identifier3("b")
+        ]));
+  }
+
+  void test_visitImportHideCombinator_single() {
+    _assertSource("hide a",
+        AstTestFactory.hideCombinator([AstTestFactory.identifier3("a")]));
+  }
+
+  void test_visitImportShowCombinator_multiple() {
+    _assertSource(
+        "show a, b",
+        AstTestFactory.showCombinator([
+          AstTestFactory.identifier3("a"),
+          AstTestFactory.identifier3("b")
+        ]));
+  }
+
+  void test_visitImportShowCombinator_single() {
+    _assertSource("show a",
+        AstTestFactory.showCombinator([AstTestFactory.identifier3("a")]));
+  }
+
+  void test_visitIndexExpression() {
+    _assertSource(
+        "a[i]",
+        AstTestFactory.indexExpression(
+            AstTestFactory.identifier3("a"), AstTestFactory.identifier3("i")));
+  }
+
+  void test_visitInstanceCreationExpression_const() {
+    _assertSource(
+        "const C()",
+        AstTestFactory.instanceCreationExpression2(
+            Keyword.CONST, AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitInstanceCreationExpression_named() {
+    _assertSource(
+        "new C.c()",
+        AstTestFactory.instanceCreationExpression3(
+            Keyword.NEW, AstTestFactory.typeName4("C"), "c"));
+  }
+
+  void test_visitInstanceCreationExpression_unnamed() {
+    _assertSource(
+        "new C()",
+        AstTestFactory.instanceCreationExpression2(
+            Keyword.NEW, AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitIntegerLiteral() {
+    _assertSource("42", AstTestFactory.integer(42));
+  }
+
+  void test_visitInterpolationExpression_expression() {
+    _assertSource(
+        "\${a}",
+        AstTestFactory.interpolationExpression(
+            AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitInterpolationExpression_identifier() {
+    _assertSource("\$a", AstTestFactory.interpolationExpression2("a"));
+  }
+
+  void test_visitInterpolationString() {
+    _assertSource("'x", AstTestFactory.interpolationString("'x", "x"));
+  }
+
+  void test_visitIsExpression_negated() {
+    _assertSource(
+        "a is! C",
+        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), true,
+            AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitIsExpression_normal() {
+    _assertSource(
+        "a is C",
+        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), false,
+            AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitLabel() {
+    _assertSource("a:", AstTestFactory.label2("a"));
+  }
+
+  void test_visitLabeledStatement_multiple() {
+    _assertSource(
+        "a: b: return;",
+        AstTestFactory.labeledStatement(
+            [AstTestFactory.label2("a"), AstTestFactory.label2("b")],
+            AstTestFactory.returnStatement()));
+  }
+
+  void test_visitLabeledStatement_single() {
+    _assertSource(
+        "a: return;",
+        AstTestFactory.labeledStatement(
+            [AstTestFactory.label2("a")], AstTestFactory.returnStatement()));
+  }
+
+  void test_visitLibraryDirective() {
+    _assertSource("library l;", AstTestFactory.libraryDirective2("l"));
+  }
+
+  void test_visitLibraryDirective_withMetadata() {
+    LibraryDirective directive = AstTestFactory.libraryDirective2("l");
+    directive.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated library l;", directive);
+  }
+
+  void test_visitLibraryIdentifier_multiple() {
+    _assertSource(
+        "a.b.c",
+        AstTestFactory.libraryIdentifier([
+          AstTestFactory.identifier3("a"),
+          AstTestFactory.identifier3("b"),
+          AstTestFactory.identifier3("c")
+        ]));
+  }
+
+  void test_visitLibraryIdentifier_single() {
+    _assertSource("a",
+        AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("a")]));
+  }
+
+  void test_visitListLiteral_complex() {
+    _assertSource(
+        '<int>[0, for (e in l) 0, if (b) 1, ...[0]]',
+        astFactory.listLiteral(
+            null,
+            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
+            null,
+            [
+              AstTestFactory.integer(0),
+              astFactory.forElement(
+                  forLoopParts: astFactory.forEachPartsWithIdentifier(
+                      identifier: AstTestFactory.identifier3('e'),
+                      iterable: AstTestFactory.identifier3('l')),
+                  body: AstTestFactory.integer(0)),
+              astFactory.ifElement(
+                  condition: AstTestFactory.identifier3('b'),
+                  thenElement: AstTestFactory.integer(1)),
+              astFactory.spreadElement(
+                  spreadOperator: TokenFactory.tokenFromType(
+                      TokenType.PERIOD_PERIOD_PERIOD),
+                  expression: astFactory.listLiteral(
+                      null, null, null, [AstTestFactory.integer(0)], null))
+            ],
+            null));
+  }
+
+  void test_visitListLiteral_const() {
+    _assertSource("const []", AstTestFactory.listLiteral2(Keyword.CONST, null));
+  }
+
+  void test_visitListLiteral_empty() {
+    _assertSource("[]", AstTestFactory.listLiteral());
+  }
+
+  void test_visitListLiteral_nonEmpty() {
+    _assertSource(
+        "[a, b, c]",
+        AstTestFactory.listLiteral([
+          AstTestFactory.identifier3("a"),
+          AstTestFactory.identifier3("b"),
+          AstTestFactory.identifier3("c")
+        ]));
+  }
+
+  void test_visitListLiteral_withConst_withoutTypeArgs() {
+    _assertSource(
+        'const [0]',
+        astFactory.listLiteral(TokenFactory.tokenFromKeyword(Keyword.CONST),
+            null, null, [AstTestFactory.integer(0)], null));
+  }
+
+  void test_visitListLiteral_withConst_withTypeArgs() {
+    _assertSource(
+        'const <int>[0]',
+        astFactory.listLiteral(
+            TokenFactory.tokenFromKeyword(Keyword.CONST),
+            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
+            null,
+            [AstTestFactory.integer(0)],
+            null));
+  }
+
+  void test_visitListLiteral_withoutConst_withoutTypeArgs() {
+    _assertSource(
+        '[0]',
+        astFactory.listLiteral(
+            null, null, null, [AstTestFactory.integer(0)], null));
+  }
+
+  void test_visitListLiteral_withoutConst_withTypeArgs() {
+    _assertSource(
+        '<int>[0]',
+        astFactory.listLiteral(
+            null,
+            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
+            null,
+            [AstTestFactory.integer(0)],
+            null));
+  }
+
+  void test_visitMapLiteral_const() {
+    _assertSource(
+        "const {}", AstTestFactory.setOrMapLiteral(Keyword.CONST, null));
+  }
+
+  void test_visitMapLiteral_empty() {
+    _assertSource("{}", AstTestFactory.setOrMapLiteral(null, null));
+  }
+
+  void test_visitMapLiteral_nonEmpty() {
+    _assertSource(
+        "{'a' : a, 'b' : b, 'c' : c}",
+        AstTestFactory.setOrMapLiteral(null, null, [
+          AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("a")),
+          AstTestFactory.mapLiteralEntry("b", AstTestFactory.identifier3("b")),
+          AstTestFactory.mapLiteralEntry("c", AstTestFactory.identifier3("c"))
+        ]));
+  }
+
+  void test_visitMapLiteralEntry() {
+    _assertSource("'a' : b",
+        AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitMethodDeclaration_external() {
+    _assertSource(
+        "external m();",
+        AstTestFactory.methodDeclaration(
+            null,
+            null,
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList()));
+  }
+
+  void test_visitMethodDeclaration_external_returnType() {
+    _assertSource(
+        "external T m();",
+        AstTestFactory.methodDeclaration(
+            null,
+            AstTestFactory.typeName4("T"),
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList()));
+  }
+
+  void test_visitMethodDeclaration_getter() {
+    _assertSource(
+        "get m {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            null,
+            Keyword.GET,
+            null,
+            AstTestFactory.identifier3("m"),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_getter_returnType() {
+    _assertSource(
+        "T get m {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            AstTestFactory.typeName4("T"),
+            Keyword.GET,
+            null,
+            AstTestFactory.identifier3("m"),
+            null,
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_getter_seturnType() {
+    _assertSource(
+        "T set m(var v) {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            AstTestFactory.typeName4("T"),
+            Keyword.SET,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(
+                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_minimal() {
+    _assertSource(
+        "m() {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            null,
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_multipleParameters() {
+    _assertSource(
+        "m(var a, var b) {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            null,
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList([
+              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
+              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
+            ]),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_operator() {
+    _assertSource(
+        "operator +() {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            null,
+            null,
+            Keyword.OPERATOR,
+            AstTestFactory.identifier3("+"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_operator_returnType() {
+    _assertSource(
+        "T operator +() {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            AstTestFactory.typeName4("T"),
+            null,
+            Keyword.OPERATOR,
+            AstTestFactory.identifier3("+"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_returnType() {
+    _assertSource(
+        "T m() {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            AstTestFactory.typeName4("T"),
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_setter() {
+    _assertSource(
+        "set m(var v) {}",
+        AstTestFactory.methodDeclaration2(
+            null,
+            null,
+            Keyword.SET,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(
+                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_static() {
+    _assertSource(
+        "static m() {}",
+        AstTestFactory.methodDeclaration2(
+            Keyword.STATIC,
+            null,
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_static_returnType() {
+    _assertSource(
+        "static T m() {}",
+        AstTestFactory.methodDeclaration2(
+            Keyword.STATIC,
+            AstTestFactory.typeName4("T"),
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_typeParameters() {
+    _assertSource(
+        "m<E>() {}",
+        AstTestFactory.methodDeclaration3(
+            null,
+            null,
+            null,
+            null,
+            AstTestFactory.identifier3("m"),
+            AstTestFactory.typeParameterList(['E']),
+            AstTestFactory.formalParameterList(),
+            AstTestFactory.blockFunctionBody2()));
+  }
+
+  void test_visitMethodDeclaration_withMetadata() {
+    MethodDeclaration declaration = AstTestFactory.methodDeclaration2(
+        null,
+        null,
+        null,
+        null,
+        AstTestFactory.identifier3("m"),
+        AstTestFactory.formalParameterList(),
+        AstTestFactory.blockFunctionBody2());
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated m() {}", declaration);
+  }
+
+  void test_visitMethodInvocation_conditional() {
+    _assertSource(
+        "t?.m()",
+        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m",
+            null, TokenType.QUESTION_PERIOD));
+  }
+
+  void test_visitMethodInvocation_noTarget() {
+    _assertSource("m()", AstTestFactory.methodInvocation2("m"));
+  }
+
+  void test_visitMethodInvocation_target() {
+    _assertSource("t.m()",
+        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m"));
+  }
+
+  void test_visitMethodInvocation_typeArguments() {
+    _assertSource(
+        "m<A>()",
+        AstTestFactory.methodInvocation3(null, "m",
+            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
+  }
+
+  void test_visitNamedExpression() {
+    _assertSource("a: b",
+        AstTestFactory.namedExpression2("a", AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitNamedFormalParameter() {
+    _assertSource(
+        "var a: 0",
+        AstTestFactory.namedFormalParameter(
+            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
+            AstTestFactory.integer(0)));
+  }
+
+  void test_visitNativeClause() {
+    _assertSource("native 'code'", AstTestFactory.nativeClause("code"));
+  }
+
+  void test_visitNativeFunctionBody() {
+    _assertSource("native 'str';", AstTestFactory.nativeFunctionBody("str"));
+  }
+
+  void test_visitNullLiteral() {
+    _assertSource("null", AstTestFactory.nullLiteral());
+  }
+
+  void test_visitParenthesizedExpression() {
+    _assertSource(
+        "(a)",
+        AstTestFactory.parenthesizedExpression(
+            AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitPartDirective() {
+    _assertSource("part 'a.dart';", AstTestFactory.partDirective2("a.dart"));
+  }
+
+  void test_visitPartDirective_withMetadata() {
+    PartDirective directive = AstTestFactory.partDirective2("a.dart");
+    directive.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated part 'a.dart';", directive);
+  }
+
+  void test_visitPartOfDirective() {
+    _assertSource(
+        "part of l;",
+        AstTestFactory.partOfDirective(
+            AstTestFactory.libraryIdentifier2(["l"])));
+  }
+
+  void test_visitPartOfDirective_withMetadata() {
+    PartOfDirective directive = AstTestFactory.partOfDirective(
+        AstTestFactory.libraryIdentifier2(["l"]));
+    directive.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated part of l;", directive);
+  }
+
+  void test_visitPositionalFormalParameter() {
+    _assertSource(
+        "var a = 0",
+        AstTestFactory.positionalFormalParameter(
+            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
+            AstTestFactory.integer(0)));
+  }
+
+  void test_visitPostfixExpression() {
+    _assertSource(
+        "a++",
+        AstTestFactory.postfixExpression(
+            AstTestFactory.identifier3("a"), TokenType.PLUS_PLUS));
+  }
+
+  void test_visitPrefixedIdentifier() {
+    _assertSource("a.b", AstTestFactory.identifier5("a", "b"));
+  }
+
+  void test_visitPrefixExpression() {
+    _assertSource(
+        "-a",
+        AstTestFactory.prefixExpression(
+            TokenType.MINUS, AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitPrefixExpression_precedence() {
+    var a = AstTestFactory.identifier3('a');
+    var b = AstTestFactory.identifier3('b');
+    _assertSource(
+        '!(a == b)',
+        AstTestFactory.prefixExpression(TokenType.BANG,
+            AstTestFactory.binaryExpression(a, TokenType.EQ_EQ, b)));
+  }
+
+  void test_visitPropertyAccess() {
+    _assertSource("a.b",
+        AstTestFactory.propertyAccess2(AstTestFactory.identifier3("a"), "b"));
+  }
+
+  void test_visitPropertyAccess_conditional() {
+    _assertSource(
+        "a?.b",
+        AstTestFactory.propertyAccess2(
+            AstTestFactory.identifier3("a"), "b", TokenType.QUESTION_PERIOD));
+  }
+
+  void test_visitRedirectingConstructorInvocation_named() {
+    _assertSource(
+        "this.c()", AstTestFactory.redirectingConstructorInvocation2("c"));
+  }
+
+  void test_visitRedirectingConstructorInvocation_unnamed() {
+    _assertSource("this()", AstTestFactory.redirectingConstructorInvocation());
+  }
+
+  void test_visitRethrowExpression() {
+    _assertSource("rethrow", AstTestFactory.rethrowExpression());
+  }
+
+  void test_visitReturnStatement_expression() {
+    _assertSource("return a;",
+        AstTestFactory.returnStatement2(AstTestFactory.identifier3("a")));
+  }
+
+  void test_visitReturnStatement_noExpression() {
+    _assertSource("return;", AstTestFactory.returnStatement());
+  }
+
+  void test_visitScriptTag() {
+    String scriptTag = "!#/bin/dart.exe";
+    _assertSource(scriptTag, AstTestFactory.scriptTag(scriptTag));
+  }
+
+  void test_visitSetOrMapLiteral_map_complex() {
+    _assertSource(
+        "<String, String>{'a' : 'b', for (c in d) 'e' : 'f', if (g) 'h' : 'i', ...{'j' : 'k'}}",
+        astFactory.setOrMapLiteral(
+            typeArguments: AstTestFactory.typeArgumentList([
+              AstTestFactory.typeName4('String'),
+              AstTestFactory.typeName4('String')
+            ]),
+            elements: [
+              AstTestFactory.mapLiteralEntry3('a', 'b'),
+              astFactory.forElement(
+                  forLoopParts: astFactory.forEachPartsWithIdentifier(
+                      identifier: AstTestFactory.identifier3('c'),
+                      iterable: AstTestFactory.identifier3('d')),
+                  body: AstTestFactory.mapLiteralEntry3('e', 'f')),
+              astFactory.ifElement(
+                  condition: AstTestFactory.identifier3('g'),
+                  thenElement: AstTestFactory.mapLiteralEntry3('h', 'i')),
+              astFactory.spreadElement(
+                  spreadOperator: TokenFactory.tokenFromType(
+                      TokenType.PERIOD_PERIOD_PERIOD),
+                  expression: astFactory.setOrMapLiteral(
+                      elements: [AstTestFactory.mapLiteralEntry3('j', 'k')]))
+            ]));
+  }
+
+  void test_visitSetOrMapLiteral_map_withConst_withoutTypeArgs() {
+    _assertSource(
+        "const {'a' : 'b'}",
+        astFactory.setOrMapLiteral(
+            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
+  }
+
+  void test_visitSetOrMapLiteral_map_withConst_withTypeArgs() {
+    _assertSource(
+        "const <String, String>{'a' : 'b'}",
+        astFactory.setOrMapLiteral(
+            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+            typeArguments: AstTestFactory.typeArgumentList([
+              AstTestFactory.typeName4('String'),
+              AstTestFactory.typeName4('String')
+            ]),
+            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
+  }
+
+  void test_visitSetOrMapLiteral_map_withoutConst_withoutTypeArgs() {
+    _assertSource(
+        "{'a' : 'b'}",
+        astFactory.setOrMapLiteral(
+            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
+  }
+
+  void test_visitSetOrMapLiteral_map_withoutConst_withTypeArgs() {
+    _assertSource(
+        "<String, String>{'a' : 'b'}",
+        astFactory.setOrMapLiteral(
+            typeArguments: AstTestFactory.typeArgumentList([
+              AstTestFactory.typeName4('String'),
+              AstTestFactory.typeName4('String')
+            ]),
+            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
+  }
+
+  void test_visitSetOrMapLiteral_set_complex() {
+    _assertSource(
+        '<int>{0, for (e in l) 0, if (b) 1, ...[0]}',
+        astFactory.setOrMapLiteral(
+            typeArguments: AstTestFactory.typeArgumentList(
+                [AstTestFactory.typeName4('int')]),
+            elements: [
+              AstTestFactory.integer(0),
+              astFactory.forElement(
+                  forLoopParts: astFactory.forEachPartsWithIdentifier(
+                      identifier: AstTestFactory.identifier3('e'),
+                      iterable: AstTestFactory.identifier3('l')),
+                  body: AstTestFactory.integer(0)),
+              astFactory.ifElement(
+                  condition: AstTestFactory.identifier3('b'),
+                  thenElement: AstTestFactory.integer(1)),
+              astFactory.spreadElement(
+                  spreadOperator: TokenFactory.tokenFromType(
+                      TokenType.PERIOD_PERIOD_PERIOD),
+                  expression: astFactory.listLiteral(
+                      null, null, null, [AstTestFactory.integer(0)], null))
+            ]));
+  }
+
+  void test_visitSetOrMapLiteral_set_withConst_withoutTypeArgs() {
+    _assertSource(
+        'const {0}',
+        astFactory.setOrMapLiteral(
+            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+            elements: [AstTestFactory.integer(0)]));
+  }
+
+  void test_visitSetOrMapLiteral_set_withConst_withTypeArgs() {
+    _assertSource(
+        'const <int>{0}',
+        astFactory.setOrMapLiteral(
+            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
+            typeArguments: AstTestFactory.typeArgumentList(
+                [AstTestFactory.typeName4('int')]),
+            elements: [AstTestFactory.integer(0)]));
+  }
+
+  void test_visitSetOrMapLiteral_set_withoutConst_withoutTypeArgs() {
+    _assertSource('{0}',
+        astFactory.setOrMapLiteral(elements: [AstTestFactory.integer(0)]));
+  }
+
+  void test_visitSetOrMapLiteral_set_withoutConst_withTypeArgs() {
+    _assertSource(
+        '<int>{0}',
+        astFactory.setOrMapLiteral(
+            typeArguments: AstTestFactory.typeArgumentList(
+                [AstTestFactory.typeName4('int')]),
+            elements: [AstTestFactory.integer(0)]));
+  }
+
+  void test_visitSimpleFormalParameter_annotation() {
+    SimpleFormalParameter parameter =
+        AstTestFactory.simpleFormalParameter3('x');
+    parameter.metadata
+        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
+    _assertSource('@A x', parameter);
+  }
+
+  void test_visitSimpleFormalParameter_keyword() {
+    _assertSource(
+        "var a", AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"));
+  }
+
+  void test_visitSimpleFormalParameter_keyword_type() {
+    _assertSource(
+        "final A a",
+        AstTestFactory.simpleFormalParameter2(
+            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
+  }
+
+  void test_visitSimpleFormalParameter_type() {
+    _assertSource(
+        "A a",
+        AstTestFactory.simpleFormalParameter4(
+            AstTestFactory.typeName4("A"), "a"));
+  }
+
+  void test_visitSimpleFormalParameter_type_covariant() {
+    SimpleFormalParameterImpl expected = AstTestFactory.simpleFormalParameter4(
+        AstTestFactory.typeName4("A"), "a");
+    expected.covariantKeyword =
+        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
+    _assertSource("covariant A a", expected);
+  }
+
+  void test_visitSimpleIdentifier() {
+    _assertSource("a", AstTestFactory.identifier3("a"));
+  }
+
+  void test_visitSimpleStringLiteral() {
+    _assertSource("'a'", AstTestFactory.string2("a"));
+  }
+
+  void test_visitSpreadElement_nonNullable() {
+    _assertSource(
+        '...[0]',
+        astFactory.spreadElement(
+            spreadOperator:
+                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
+            expression: astFactory.listLiteral(
+                null, null, null, [AstTestFactory.integer(0)], null)));
+  }
+
+  @failingTest
+  void test_visitSpreadElement_nullable() {
+    // TODO(brianwilkerson) Replace the token type below when there is one for
+    //  '...?'.
+    _assertSource(
+        '...?[0]',
+        astFactory.spreadElement(
+            spreadOperator:
+                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
+            expression: astFactory.listLiteral(
+                null, null, null, [AstTestFactory.integer(0)], null)));
+  }
+
+  void test_visitStringInterpolation() {
+    _assertSource(
+        "'a\${e}b'",
+        AstTestFactory.string([
+          AstTestFactory.interpolationString("'a", "a"),
+          AstTestFactory.interpolationExpression(
+              AstTestFactory.identifier3("e")),
+          AstTestFactory.interpolationString("b'", "b")
+        ]));
+  }
+
+  void test_visitSuperConstructorInvocation() {
+    _assertSource("super()", AstTestFactory.superConstructorInvocation());
+  }
+
+  void test_visitSuperConstructorInvocation_named() {
+    _assertSource("super.c()", AstTestFactory.superConstructorInvocation2("c"));
+  }
+
+  void test_visitSuperExpression() {
+    _assertSource("super", AstTestFactory.superExpression());
+  }
+
+  void test_visitSwitchCase_multipleLabels() {
+    _assertSource(
+        "l1: l2: case a: {}",
+        AstTestFactory.switchCase2(
+            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
+            AstTestFactory.identifier3("a"),
+            [AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchCase_multipleStatements() {
+    _assertSource(
+        "case a: {} {}",
+        AstTestFactory.switchCase(AstTestFactory.identifier3("a"),
+            [AstTestFactory.block(), AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchCase_noLabels() {
+    _assertSource(
+        "case a: {}",
+        AstTestFactory.switchCase(
+            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchCase_singleLabel() {
+    _assertSource(
+        "l1: case a: {}",
+        AstTestFactory.switchCase2([AstTestFactory.label2("l1")],
+            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchDefault_multipleLabels() {
+    _assertSource(
+        "l1: l2: default: {}",
+        AstTestFactory.switchDefault(
+            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
+            [AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchDefault_multipleStatements() {
+    _assertSource(
+        "default: {} {}",
+        AstTestFactory.switchDefault2(
+            [AstTestFactory.block(), AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchDefault_noLabels() {
+    _assertSource(
+        "default: {}", AstTestFactory.switchDefault2([AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchDefault_singleLabel() {
+    _assertSource(
+        "l1: default: {}",
+        AstTestFactory.switchDefault(
+            [AstTestFactory.label2("l1")], [AstTestFactory.block()]));
+  }
+
+  void test_visitSwitchStatement() {
+    _assertSource(
+        "switch (a) {case 'b': {} default: {}}",
+        AstTestFactory.switchStatement(AstTestFactory.identifier3("a"), [
+          AstTestFactory.switchCase(
+              AstTestFactory.string2("b"), [AstTestFactory.block()]),
+          AstTestFactory.switchDefault2([AstTestFactory.block()])
+        ]));
+  }
+
+  void test_visitSymbolLiteral_multiple() {
+    _assertSource("#a.b.c", AstTestFactory.symbolLiteral(["a", "b", "c"]));
+  }
+
+  void test_visitSymbolLiteral_single() {
+    _assertSource("#a", AstTestFactory.symbolLiteral(["a"]));
+  }
+
+  void test_visitThisExpression() {
+    _assertSource("this", AstTestFactory.thisExpression());
+  }
+
+  void test_visitThrowStatement() {
+    _assertSource("throw e",
+        AstTestFactory.throwExpression2(AstTestFactory.identifier3("e")));
+  }
+
+  void test_visitTopLevelVariableDeclaration_multiple() {
+    _assertSource(
+        "var a;",
+        AstTestFactory.topLevelVariableDeclaration2(
+            Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
+  }
+
+  void test_visitTopLevelVariableDeclaration_single() {
+    _assertSource(
+        "var a, b;",
+        AstTestFactory.topLevelVariableDeclaration2(Keyword.VAR, [
+          AstTestFactory.variableDeclaration("a"),
+          AstTestFactory.variableDeclaration("b")
+        ]));
+  }
+
+  void test_visitTryStatement_catch() {
+    _assertSource(
+        "try {} on E {}",
+        AstTestFactory.tryStatement2(AstTestFactory.block(),
+            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))]));
+  }
+
+  void test_visitTryStatement_catches() {
+    _assertSource(
+        "try {} on E {} on F {}",
+        AstTestFactory.tryStatement2(AstTestFactory.block(), [
+          AstTestFactory.catchClause3(AstTestFactory.typeName4("E")),
+          AstTestFactory.catchClause3(AstTestFactory.typeName4("F"))
+        ]));
+  }
+
+  void test_visitTryStatement_catchFinally() {
+    _assertSource(
+        "try {} on E {} finally {}",
+        AstTestFactory.tryStatement3(
+            AstTestFactory.block(),
+            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))],
+            AstTestFactory.block()));
+  }
+
+  void test_visitTryStatement_finally() {
+    _assertSource(
+        "try {} finally {}",
+        AstTestFactory.tryStatement(
+            AstTestFactory.block(), AstTestFactory.block()));
+  }
+
+  void test_visitTypeArgumentList_multiple() {
+    _assertSource(
+        "<E, F>",
+        AstTestFactory.typeArgumentList(
+            [AstTestFactory.typeName4("E"), AstTestFactory.typeName4("F")]));
+  }
+
+  void test_visitTypeArgumentList_single() {
+    _assertSource("<E>",
+        AstTestFactory.typeArgumentList([AstTestFactory.typeName4("E")]));
+  }
+
+  void test_visitTypeName_multipleArgs() {
+    _assertSource(
+        "C<D, E>",
+        AstTestFactory.typeName4("C",
+            [AstTestFactory.typeName4("D"), AstTestFactory.typeName4("E")]));
+  }
+
+  void test_visitTypeName_nestedArg() {
+    _assertSource(
+        "C<D<E>>",
+        AstTestFactory.typeName4("C", [
+          AstTestFactory.typeName4("D", [AstTestFactory.typeName4("E")])
+        ]));
+  }
+
+  void test_visitTypeName_noArgs() {
+    _assertSource("C", AstTestFactory.typeName4("C"));
+  }
+
+  void test_visitTypeName_noArgs_withQuestion() {
+    _assertSource("C?", AstTestFactory.typeName4("C", null, true));
+  }
+
+  void test_visitTypeName_singleArg() {
+    _assertSource(
+        "C<D>", AstTestFactory.typeName4("C", [AstTestFactory.typeName4("D")]));
+  }
+
+  void test_visitTypeName_singleArg_withQuestion() {
+    _assertSource("C<D>?",
+        AstTestFactory.typeName4("C", [AstTestFactory.typeName4("D")], true));
+  }
+
+  void test_visitTypeParameter_withExtends() {
+    _assertSource("E extends C",
+        AstTestFactory.typeParameter2("E", AstTestFactory.typeName4("C")));
+  }
+
+  void test_visitTypeParameter_withMetadata() {
+    TypeParameter parameter = AstTestFactory.typeParameter("E");
+    parameter.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated E", parameter);
+  }
+
+  void test_visitTypeParameter_withoutExtends() {
+    _assertSource("E", AstTestFactory.typeParameter("E"));
+  }
+
+  void test_visitTypeParameterList_multiple() {
+    _assertSource("<E, F>", AstTestFactory.typeParameterList(["E", "F"]));
+  }
+
+  void test_visitTypeParameterList_single() {
+    _assertSource("<E>", AstTestFactory.typeParameterList(["E"]));
+  }
+
+  void test_visitVariableDeclaration_initialized() {
+    _assertSource(
+        "a = b",
+        AstTestFactory.variableDeclaration2(
+            "a", AstTestFactory.identifier3("b")));
+  }
+
+  void test_visitVariableDeclaration_uninitialized() {
+    _assertSource("a", AstTestFactory.variableDeclaration("a"));
+  }
+
+  void test_visitVariableDeclaration_withMetadata() {
+    VariableDeclaration declaration = AstTestFactory.variableDeclaration("a");
+    declaration.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated a", declaration);
+  }
+
+  void test_visitVariableDeclarationList_const_type() {
+    _assertSource(
+        "const C a, b",
+        AstTestFactory.variableDeclarationList(
+            Keyword.CONST, AstTestFactory.typeName4("C"), [
+          AstTestFactory.variableDeclaration("a"),
+          AstTestFactory.variableDeclaration("b")
+        ]));
+  }
+
+  void test_visitVariableDeclarationList_final_noType() {
+    _assertSource(
+        "final a, b",
+        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
+          AstTestFactory.variableDeclaration("a"),
+          AstTestFactory.variableDeclaration("b")
+        ]));
+  }
+
+  void test_visitVariableDeclarationList_final_withMetadata() {
+    VariableDeclarationList declarationList =
+        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
+      AstTestFactory.variableDeclaration("a"),
+      AstTestFactory.variableDeclaration("b")
+    ]);
+    declarationList.metadata.add(
+        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
+    _assertSource("@deprecated final a, b", declarationList);
+  }
+
+  void test_visitVariableDeclarationList_type() {
+    _assertSource(
+        "C a, b",
+        AstTestFactory.variableDeclarationList(
+            null, AstTestFactory.typeName4("C"), [
+          AstTestFactory.variableDeclaration("a"),
+          AstTestFactory.variableDeclaration("b")
+        ]));
+  }
+
+  void test_visitVariableDeclarationList_var() {
+    _assertSource(
+        "var a, b",
+        AstTestFactory.variableDeclarationList2(Keyword.VAR, [
+          AstTestFactory.variableDeclaration("a"),
+          AstTestFactory.variableDeclaration("b")
+        ]));
+  }
+
+  void test_visitVariableDeclarationStatement() {
+    _assertSource(
+        "C c;",
+        AstTestFactory.variableDeclarationStatement(
+            null,
+            AstTestFactory.typeName4("C"),
+            [AstTestFactory.variableDeclaration("c")]));
+  }
+
+  void test_visitWhileStatement() {
+    _assertSource(
+        "while (c) {}",
+        AstTestFactory.whileStatement(
+            AstTestFactory.identifier3("c"), AstTestFactory.block()));
+  }
+
+  void test_visitWithClause_multiple() {
+    _assertSource(
+        "with A, B, C",
+        AstTestFactory.withClause([
+          AstTestFactory.typeName4("A"),
+          AstTestFactory.typeName4("B"),
+          AstTestFactory.typeName4("C")
+        ]));
+  }
+
+  void test_visitWithClause_single() {
+    _assertSource(
+        "with A", AstTestFactory.withClause([AstTestFactory.typeName4("A")]));
+  }
+
+  void test_visitYieldStatement() {
+    _assertSource("yield e;",
+        AstTestFactory.yieldStatement(AstTestFactory.identifier3("e")));
+  }
+
+  void test_visitYieldStatement_each() {
+    _assertSource("yield* e;",
+        AstTestFactory.yieldEachStatement(AstTestFactory.identifier3("e")));
+  }
+
+  /**
+   * Assert that a `ToSourceVisitor2` will produce the [expectedSource] when
+   * visiting the given [node].
+   */
+  void _assertSource(String expectedSource, AstNode node) {
+    StringBuffer buffer = new StringBuffer();
+    node.accept(new ToSourceVisitor(buffer));
+    expect(buffer.toString(), expectedSource);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 676ada5..bc1afd0 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
@@ -28,9 +27,6 @@
     defineReflectiveTests(NodeLocatorTest);
     defineReflectiveTests(NodeLocator2Test);
     defineReflectiveTests(ResolutionCopierTest);
-    // ignore: deprecated_member_use_from_same_package
-    defineReflectiveTests(ToSourceVisitorTest);
-    defineReflectiveTests(ToSourceVisitor2Test);
   });
 }
 
@@ -504,8 +500,7 @@
         AstTestFactory.identifier3("a"), AstTestFactory.integer(0));
     MethodElement staticElement = ElementFactory.methodElement(
         "m", interfaceType(ElementFactory.classElement2('C')));
-    AuxiliaryElements auxiliaryElements =
-        new AuxiliaryElements(staticElement, null);
+    AuxiliaryElements auxiliaryElements = new AuxiliaryElements(staticElement);
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
     DartType staticType = interfaceType(ElementFactory.classElement2('C'));
@@ -785,8 +780,7 @@
     SimpleIdentifier fromNode = AstTestFactory.identifier3("x");
     MethodElement staticElement = ElementFactory.methodElement(
         "m", interfaceType(ElementFactory.classElement2('C')));
-    AuxiliaryElements auxiliaryElements =
-        new AuxiliaryElements(staticElement, null);
+    AuxiliaryElements auxiliaryElements = new AuxiliaryElements(staticElement);
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
     DartType staticType = interfaceType(ElementFactory.classElement2('C'));
@@ -919,5606 +913,3 @@
     }
   }
 }
-
-@reflectiveTest
-class ToSourceVisitor2Test {
-  void test_visitAdjacentStrings() {
-    _assertSource(
-        "'a' 'b'",
-        AstTestFactory.adjacentStrings(
-            [AstTestFactory.string2("a"), AstTestFactory.string2("b")]));
-  }
-
-  void test_visitAnnotation_constant() {
-    _assertSource(
-        "@A", AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-  }
-
-  void test_visitAnnotation_constructor() {
-    _assertSource(
-        "@A.c()",
-        AstTestFactory.annotation2(AstTestFactory.identifier3("A"),
-            AstTestFactory.identifier3("c"), AstTestFactory.argumentList()));
-  }
-
-  void test_visitArgumentList() {
-    _assertSource(
-        "(a, b)",
-        AstTestFactory.argumentList([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitAsExpression() {
-    _assertSource(
-        "e as T",
-        AstTestFactory.asExpression(
-            AstTestFactory.identifier3("e"), AstTestFactory.typeName4("T")));
-  }
-
-  void test_visitAssertStatement() {
-    _assertSource("assert (a);",
-        AstTestFactory.assertStatement(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitAssertStatement_withMessage() {
-    _assertSource(
-        "assert (a, b);",
-        AstTestFactory.assertStatement(
-            AstTestFactory.identifier3("a"), AstTestFactory.identifier3('b')));
-  }
-
-  void test_visitAssignmentExpression() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.assignmentExpression(AstTestFactory.identifier3("a"),
-            TokenType.EQ, AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitAwaitExpression() {
-    _assertSource("await e",
-        AstTestFactory.awaitExpression(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitBinaryExpression() {
-    _assertSource(
-        "a + b",
-        AstTestFactory.binaryExpression(AstTestFactory.identifier3("a"),
-            TokenType.PLUS, AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitBinaryExpression_precedence() {
-    var a = AstTestFactory.identifier3('a');
-    var b = AstTestFactory.identifier3('b');
-    var c = AstTestFactory.identifier3('c');
-    _assertSource(
-        'a * (b + c)',
-        AstTestFactory.binaryExpression(a, TokenType.STAR,
-            AstTestFactory.binaryExpression(b, TokenType.PLUS, c)));
-  }
-
-  void test_visitBlock_empty() {
-    _assertSource("{}", AstTestFactory.block());
-  }
-
-  void test_visitBlock_nonEmpty() {
-    _assertSource(
-        "{break; break;}",
-        AstTestFactory.block([
-          AstTestFactory.breakStatement(),
-          AstTestFactory.breakStatement()
-        ]));
-  }
-
-  void test_visitBlockFunctionBody_async() {
-    _assertSource("async {}", AstTestFactory.asyncBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_async_star() {
-    _assertSource(
-        "async* {}", AstTestFactory.asyncGeneratorBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_simple() {
-    _assertSource("{}", AstTestFactory.blockFunctionBody2());
-  }
-
-  void test_visitBlockFunctionBody_sync() {
-    _assertSource("sync {}", AstTestFactory.syncBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_sync_star() {
-    _assertSource("sync* {}", AstTestFactory.syncGeneratorBlockFunctionBody());
-  }
-
-  void test_visitBooleanLiteral_false() {
-    _assertSource("false", AstTestFactory.booleanLiteral(false));
-  }
-
-  void test_visitBooleanLiteral_true() {
-    _assertSource("true", AstTestFactory.booleanLiteral(true));
-  }
-
-  void test_visitBreakStatement_label() {
-    _assertSource("break l;", AstTestFactory.breakStatement2("l"));
-  }
-
-  void test_visitBreakStatement_noLabel() {
-    _assertSource("break;", AstTestFactory.breakStatement());
-  }
-
-  void test_visitCascadeExpression_field() {
-    _assertSource(
-        "a..b..c",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedPropertyAccess("b"),
-          AstTestFactory.cascadedPropertyAccess("c")
-        ]));
-  }
-
-  void test_visitCascadeExpression_index() {
-    _assertSource(
-        "a..[0]..[1]",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(0)),
-          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitCascadeExpression_method() {
-    _assertSource(
-        "a..b()..c()",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedMethodInvocation("b"),
-          AstTestFactory.cascadedMethodInvocation("c")
-        ]));
-  }
-
-  void test_visitCatchClause_catch_noStack() {
-    _assertSource("catch (e) {}", AstTestFactory.catchClause("e"));
-  }
-
-  void test_visitCatchClause_catch_stack() {
-    _assertSource("catch (e, s) {}", AstTestFactory.catchClause2("e", "s"));
-  }
-
-  void test_visitCatchClause_on() {
-    _assertSource(
-        "on E {}", AstTestFactory.catchClause3(AstTestFactory.typeName4("E")));
-  }
-
-  void test_visitCatchClause_on_catch() {
-    _assertSource("on E catch (e) {}",
-        AstTestFactory.catchClause4(AstTestFactory.typeName4("E"), "e"));
-  }
-
-  void test_visitClassDeclaration_abstract() {
-    _assertSource(
-        "abstract class C {}",
-        AstTestFactory.classDeclaration(
-            Keyword.ABSTRACT, "C", null, null, null, null));
-  }
-
-  void test_visitClassDeclaration_empty() {
-    _assertSource("class C {}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null));
-  }
-
-  void test_visitClassDeclaration_extends() {
-    _assertSource(
-        "class C extends A {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            null));
-  }
-
-  void test_visitClassDeclaration_extends_implements() {
-    _assertSource(
-        "class C extends A implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_extends_with() {
-    _assertSource(
-        "class C extends A with M {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            null));
-  }
-
-  void test_visitClassDeclaration_extends_with_implements() {
-    _assertSource(
-        "class C extends A with M implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_implements() {
-    _assertSource(
-        "class C implements B {}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_multipleMember() {
-    _assertSource(
-        "class C {var a; var b;}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]),
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("b")])
-        ]));
-  }
-
-  void test_visitClassDeclaration_parameters() {
-    _assertSource(
-        "class C<E> {}",
-        AstTestFactory.classDeclaration(null, "C",
-            AstTestFactory.typeParameterList(["E"]), null, null, null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends() {
-    _assertSource(
-        "class C<E> extends A {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_implements() {
-    _assertSource(
-        "class C<E> extends A implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with() {
-    _assertSource(
-        "class C<E> extends A with M {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with_implements() {
-    _assertSource(
-        "class C<E> extends A with M implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_parameters_implements() {
-    _assertSource(
-        "class C<E> implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_singleMember() {
-    _assertSource(
-        "class C {var a;}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitClassDeclaration_withMetadata() {
-    ClassDeclaration declaration =
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated class C {}", declaration);
-  }
-
-  void test_visitClassTypeAlias_abstract() {
-    _assertSource(
-        "abstract class C = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_abstract_implements() {
-    _assertSource(
-        "abstract class C = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_generic() {
-    _assertSource(
-        "class C<E> = S<E> with M1<E>;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            AstTestFactory.typeName4("S", [AstTestFactory.typeName4("E")]),
-            AstTestFactory.withClause([
-              AstTestFactory.typeName4("M1", [AstTestFactory.typeName4("E")])
-            ]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_implements() {
-    _assertSource(
-        "class C = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_minimal() {
-    _assertSource(
-        "class C = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract() {
-    _assertSource(
-        "abstract class C<E> = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract_implements() {
-    _assertSource(
-        "abstract class C<E> = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_parameters_implements() {
-    _assertSource(
-        "class C<E> = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_withMetadata() {
-    ClassTypeAlias declaration = AstTestFactory.classTypeAlias(
-        "C",
-        null,
-        null,
-        AstTestFactory.typeName4("S"),
-        AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-        null);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated class C = S with M1;", declaration);
-  }
-
-  void test_visitComment() {
-    _assertSource(
-        "",
-        astFactory.blockComment(
-            <Token>[TokenFactory.tokenFromString("/* comment */")]));
-  }
-
-  void test_visitCommentReference() {
-    _assertSource(
-        "", astFactory.commentReference(null, AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitCompilationUnit_declaration() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.compilationUnit2([
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_directive() {
-    _assertSource(
-        "library l;",
-        AstTestFactory.compilationUnit3(
-            [AstTestFactory.libraryDirective2("l")]));
-  }
-
-  void test_visitCompilationUnit_directive_declaration() {
-    _assertSource(
-        "library l; var a;",
-        AstTestFactory.compilationUnit4([
-          AstTestFactory.libraryDirective2("l")
-        ], [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_empty() {
-    _assertSource("", AstTestFactory.compilationUnit());
-  }
-
-  void test_visitCompilationUnit_script() {
-    _assertSource(
-        "!#/bin/dartvm", AstTestFactory.compilationUnit5("!#/bin/dartvm"));
-  }
-
-  void test_visitCompilationUnit_script_declaration() {
-    _assertSource(
-        "!#/bin/dartvm var a;",
-        AstTestFactory.compilationUnit6("!#/bin/dartvm", [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_script_directive() {
-    _assertSource(
-        "!#/bin/dartvm library l;",
-        AstTestFactory.compilationUnit7(
-            "!#/bin/dartvm", [AstTestFactory.libraryDirective2("l")]));
-  }
-
-  void test_visitCompilationUnit_script_directives_declarations() {
-    _assertSource(
-        "!#/bin/dartvm library l; var a;",
-        AstTestFactory.compilationUnit8("!#/bin/dartvm", [
-          AstTestFactory.libraryDirective2("l")
-        ], [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitConditionalExpression() {
-    _assertSource(
-        "a ? b : c",
-        AstTestFactory.conditionalExpression(AstTestFactory.identifier3("a"),
-            AstTestFactory.identifier3("b"), AstTestFactory.identifier3("c")));
-  }
-
-  void test_visitConstructorDeclaration_const() {
-    _assertSource(
-        "const C() {}",
-        AstTestFactory.constructorDeclaration2(
-            Keyword.CONST,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_external() {
-    _assertSource(
-        "external C();",
-        AstTestFactory.constructorDeclaration(AstTestFactory.identifier3("C"),
-            null, AstTestFactory.formalParameterList(), null));
-  }
-
-  void test_visitConstructorDeclaration_minimal() {
-    _assertSource(
-        "C() {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_multipleInitializers() {
-    _assertSource(
-        "C() : a = b, c = d {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            [
-              AstTestFactory.constructorFieldInitializer(
-                  false, "a", AstTestFactory.identifier3("b")),
-              AstTestFactory.constructorFieldInitializer(
-                  false, "c", AstTestFactory.identifier3("d"))
-            ],
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_multipleParameters() {
-    _assertSource(
-        "C(var a, var b) {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
-            ]),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_named() {
-    _assertSource(
-        "C.m() {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            "m",
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_singleInitializer() {
-    _assertSource(
-        "C() : a = b {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            [
-              AstTestFactory.constructorFieldInitializer(
-                  false, "a", AstTestFactory.identifier3("b"))
-            ],
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_withMetadata() {
-    ConstructorDeclaration declaration = AstTestFactory.constructorDeclaration2(
-        null,
-        null,
-        AstTestFactory.identifier3("C"),
-        null,
-        AstTestFactory.formalParameterList(),
-        null,
-        AstTestFactory.blockFunctionBody2());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated C() {}", declaration);
-  }
-
-  void test_visitConstructorFieldInitializer_withoutThis() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.constructorFieldInitializer(
-            false, "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitConstructorFieldInitializer_withThis() {
-    _assertSource(
-        "this.a = b",
-        AstTestFactory.constructorFieldInitializer(
-            true, "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitConstructorName_named_prefix() {
-    _assertSource(
-        "p.C.n",
-        AstTestFactory.constructorName(
-            AstTestFactory.typeName4("p.C.n"), null));
-  }
-
-  void test_visitConstructorName_unnamed_noPrefix() {
-    _assertSource("C",
-        AstTestFactory.constructorName(AstTestFactory.typeName4("C"), null));
-  }
-
-  void test_visitConstructorName_unnamed_prefix() {
-    _assertSource(
-        "p.C",
-        AstTestFactory.constructorName(
-            AstTestFactory.typeName3(AstTestFactory.identifier5("p", "C")),
-            null));
-  }
-
-  void test_visitContinueStatement_label() {
-    _assertSource("continue l;", AstTestFactory.continueStatement("l"));
-  }
-
-  void test_visitContinueStatement_noLabel() {
-    _assertSource("continue;", AstTestFactory.continueStatement());
-  }
-
-  void test_visitDefaultFormalParameter_annotation() {
-    DefaultFormalParameter parameter = AstTestFactory.positionalFormalParameter(
-        AstTestFactory.simpleFormalParameter3("p"), AstTestFactory.integer(0));
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A p = 0', parameter);
-  }
-
-  void test_visitDefaultFormalParameter_named_noValue() {
-    _assertSource(
-        "p",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"), null));
-  }
-
-  void test_visitDefaultFormalParameter_named_value() {
-    _assertSource(
-        "p: 0",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitDefaultFormalParameter_positional_noValue() {
-    _assertSource(
-        "p",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"), null));
-  }
-
-  void test_visitDefaultFormalParameter_positional_value() {
-    _assertSource(
-        "p = 0",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitDoStatement() {
-    _assertSource(
-        "do {} while (c);",
-        AstTestFactory.doStatement(
-            AstTestFactory.block(), AstTestFactory.identifier3("c")));
-  }
-
-  void test_visitDoubleLiteral() {
-    _assertSource("4.2", AstTestFactory.doubleLiteral(4.2));
-  }
-
-  void test_visitEmptyFunctionBody() {
-    _assertSource(";", AstTestFactory.emptyFunctionBody());
-  }
-
-  void test_visitEmptyStatement() {
-    _assertSource(";", AstTestFactory.emptyStatement());
-  }
-
-  void test_visitEnumDeclaration_multiple() {
-    _assertSource("enum E {ONE, TWO}",
-        AstTestFactory.enumDeclaration2("E", ["ONE", "TWO"]));
-  }
-
-  void test_visitEnumDeclaration_single() {
-    _assertSource(
-        "enum E {ONE}", AstTestFactory.enumDeclaration2("E", ["ONE"]));
-  }
-
-  void test_visitExportDirective_combinator() {
-    _assertSource(
-        "export 'a.dart' show A;",
-        AstTestFactory.exportDirective2("a.dart", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitExportDirective_combinators() {
-    _assertSource(
-        "export 'a.dart' show A hide B;",
-        AstTestFactory.exportDirective2("a.dart", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitExportDirective_minimal() {
-    _assertSource(
-        "export 'a.dart';", AstTestFactory.exportDirective2("a.dart"));
-  }
-
-  void test_visitExportDirective_withMetadata() {
-    ExportDirective directive = AstTestFactory.exportDirective2("a.dart");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated export 'a.dart';", directive);
-  }
-
-  void test_visitExpressionFunctionBody_async() {
-    _assertSource(
-        "async => a;",
-        AstTestFactory.asyncExpressionFunctionBody(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExpressionFunctionBody_simple() {
-    _assertSource("=> a;",
-        AstTestFactory.expressionFunctionBody(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExpressionStatement() {
-    _assertSource("a;",
-        AstTestFactory.expressionStatement(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExtendsClause() {
-    _assertSource("extends C",
-        AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitExtensionDeclaration_empty() {
-    _assertSource(
-        'extension E on C {}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E', extendedType: AstTestFactory.typeName4('C')));
-  }
-
-  void test_visitExtensionDeclaration_multipleMember() {
-    _assertSource(
-        'extension E on C {var a; var b;}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            extendedType: AstTestFactory.typeName4('C'),
-            members: [
-              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
-                  [AstTestFactory.variableDeclaration('a')]),
-              AstTestFactory.fieldDeclaration2(
-                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
-            ]));
-  }
-
-  void test_visitExtensionDeclaration_parameters() {
-    _assertSource(
-        'extension E<T> on C {}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            typeParameters: AstTestFactory.typeParameterList(['T']),
-            extendedType: AstTestFactory.typeName4('C')));
-  }
-
-  void test_visitExtensionDeclaration_singleMember() {
-    _assertSource(
-        'extension E on C {var a;}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            extendedType: AstTestFactory.typeName4('C'),
-            members: [
-              AstTestFactory.fieldDeclaration2(
-                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
-            ]));
-  }
-
-  void test_visitExtensionOverride_prefixedName_noTypeArgs() {
-    _assertSource(
-        'p.E(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier5('p', 'E'),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_prefixedName_typeArgs() {
-    _assertSource(
-        'p.E<A>(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier5('p', 'E'),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('A')]),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_simpleName_noTypeArgs() {
-    _assertSource(
-        'E(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier3('E'),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_simpleName_typeArgs() {
-    _assertSource(
-        'E<A>(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier3('E'),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('A')]),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitFieldDeclaration_instance() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.fieldDeclaration2(
-            false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitFieldDeclaration_static() {
-    _assertSource(
-        "static var a;",
-        AstTestFactory.fieldDeclaration2(
-            true, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitFieldDeclaration_withMetadata() {
-    FieldDeclaration declaration = AstTestFactory.fieldDeclaration2(
-        false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated var a;", declaration);
-  }
-
-  void test_visitFieldFormalParameter_annotation() {
-    FieldFormalParameter parameter = AstTestFactory.fieldFormalParameter2('f');
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A this.f', parameter);
-  }
-
-  void test_visitFieldFormalParameter_functionTyped() {
-    _assertSource(
-        "A this.a(b)",
-        AstTestFactory.fieldFormalParameter(
-            null,
-            AstTestFactory.typeName4("A"),
-            "a",
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter3("b")])));
-  }
-
-  void test_visitFieldFormalParameter_functionTyped_typeParameters() {
-    _assertSource(
-        "A this.a<E, F>(b)",
-        astFactory.fieldFormalParameter2(
-            type: AstTestFactory.typeName4('A'),
-            thisKeyword: TokenFactory.tokenFromKeyword(Keyword.THIS),
-            period: TokenFactory.tokenFromType(TokenType.PERIOD),
-            identifier: AstTestFactory.identifier3('a'),
-            typeParameters: AstTestFactory.typeParameterList(['E', 'F']),
-            parameters: AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter3("b")])));
-  }
-
-  void test_visitFieldFormalParameter_keyword() {
-    _assertSource("var this.a",
-        AstTestFactory.fieldFormalParameter(Keyword.VAR, null, "a"));
-  }
-
-  void test_visitFieldFormalParameter_keywordAndType() {
-    _assertSource(
-        "final A this.a",
-        AstTestFactory.fieldFormalParameter(
-            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitFieldFormalParameter_type() {
-    _assertSource(
-        "A this.a",
-        AstTestFactory.fieldFormalParameter(
-            null, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitFieldFormalParameter_type_covariant() {
-    FieldFormalParameterImpl expected = AstTestFactory.fieldFormalParameter(
-        null, AstTestFactory.typeName4("A"), "a");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant A this.a", expected);
-  }
-
-  void test_visitForEachPartsWithDeclaration() {
-    _assertSource(
-        'var e in l',
-        astFactory.forEachPartsWithDeclaration(
-            loopVariable: AstTestFactory.declaredIdentifier3('e'),
-            iterable: AstTestFactory.identifier3('l')));
-  }
-
-  void test_visitForEachPartsWithIdentifier() {
-    _assertSource(
-        'e in l',
-        astFactory.forEachPartsWithIdentifier(
-            identifier: AstTestFactory.identifier3('e'),
-            iterable: AstTestFactory.identifier3('l')));
-  }
-
-  void test_visitForEachStatement_declared() {
-    _assertSource(
-        "for (var a in b) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forEachPartsWithDeclaration(
-                AstTestFactory.declaredIdentifier3("a"),
-                AstTestFactory.identifier3("b")),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForEachStatement_variable() {
-    _assertSource(
-        "for (a in b) {}",
-        astFactory.forStatement(
-            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3("a"),
-                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
-                iterable: AstTestFactory.identifier3("b")),
-            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-            body: AstTestFactory.block()));
-  }
-
-  void test_visitForEachStatement_variable_await() {
-    _assertSource(
-        "await for (a in b) {}",
-        astFactory.forStatement(
-            awaitKeyword: TokenFactory.tokenFromString("await"),
-            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3("a"),
-                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
-                iterable: AstTestFactory.identifier3("b")),
-            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-            body: AstTestFactory.block()));
-  }
-
-  void test_visitForElement() {
-    _assertSource(
-        'for (e in l) 0',
-        astFactory.forElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.integer(0)));
-  }
-
-  void test_visitFormalParameterList_empty() {
-    _assertSource("()", AstTestFactory.formalParameterList());
-  }
-
-  void test_visitFormalParameterList_n() {
-    _assertSource(
-        "({a: 0})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0))
-        ]));
-  }
-
-  void test_visitFormalParameterList_nn() {
-    _assertSource(
-        "({a: 0, b: 1})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_p() {
-    _assertSource(
-        "([a = 0])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0))
-        ]));
-  }
-
-  void test_visitFormalParameterList_pp() {
-    _assertSource(
-        "([a = 0, b = 1])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_r() {
-    _assertSource(
-        "(a)",
-        AstTestFactory.formalParameterList(
-            [AstTestFactory.simpleFormalParameter3("a")]));
-  }
-
-  void test_visitFormalParameterList_rn() {
-    _assertSource(
-        "(a, {b: 1})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rnn() {
-    _assertSource(
-        "(a, {b: 1, c: 2})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(2))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rp() {
-    _assertSource(
-        "(a, [b = 1])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rpp() {
-    _assertSource(
-        "(a, [b = 1, c = 2])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(2))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rr() {
-    _assertSource(
-        "(a, b)",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b")
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrn() {
-    _assertSource(
-        "(a, b, {c: 3})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrnn() {
-    _assertSource(
-        "(a, b, {c: 3, d: 4})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("d"),
-              AstTestFactory.integer(4))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrp() {
-    _assertSource(
-        "(a, b, [c = 3])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrpp() {
-    _assertSource(
-        "(a, b, [c = 3, d = 4])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("d"),
-              AstTestFactory.integer(4))
-        ]));
-  }
-
-  void test_visitForPartsWithDeclarations() {
-    _assertSource(
-        'var v; b; u',
-        astFactory.forPartsWithDeclarations(
-            variables: AstTestFactory.variableDeclarationList2(
-                Keyword.VAR, [AstTestFactory.variableDeclaration('v')]),
-            condition: AstTestFactory.identifier3('b'),
-            updaters: [AstTestFactory.identifier3('u')]));
-  }
-
-  void test_visitForPartsWithExpression() {
-    _assertSource(
-        'v; b; u',
-        astFactory.forPartsWithExpression(
-            initialization: AstTestFactory.identifier3('v'),
-            condition: AstTestFactory.identifier3('b'),
-            updaters: [AstTestFactory.identifier3('u')]));
-  }
-
-  void test_visitForStatement() {
-    _assertSource(
-        'for (e in l) s;',
-        astFactory.forStatement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.expressionStatement(
-                AstTestFactory.identifier3('s'))));
-  }
-
-  void test_visitForStatement_c() {
-    _assertSource(
-        "for (; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null, AstTestFactory.identifier3("c"), null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_cu() {
-    _assertSource(
-        "for (; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null,
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_e() {
-    _assertSource(
-        "for (e;;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"), null, null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ec() {
-    _assertSource(
-        "for (e; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                AstTestFactory.identifier3("c"),
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ecu() {
-    _assertSource(
-        "for (e; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_eu() {
-    _assertSource(
-        "for (e;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                null,
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_i() {
-    _assertSource(
-        "for (var i;;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                null,
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ic() {
-    _assertSource(
-        "for (var i; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                AstTestFactory.identifier3("c"),
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_icu() {
-    _assertSource(
-        "for (var i; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_iu() {
-    _assertSource(
-        "for (var i;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                null,
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_u() {
-    _assertSource(
-        "for (;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null, null, [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitFunctionDeclaration_external() {
-    FunctionDeclaration functionDeclaration =
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "f",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.emptyFunctionBody()));
-    functionDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-    _assertSource("external f();", functionDeclaration);
-  }
-
-  void test_visitFunctionDeclaration_getter() {
-    _assertSource(
-        "get f() {}",
-        AstTestFactory.functionDeclaration(
-            null, Keyword.GET, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_local_blockBody() {
-    FunctionDeclaration f = AstTestFactory.functionDeclaration(
-        null, null, "f", AstTestFactory.functionExpression());
-    FunctionDeclarationStatement fStatement =
-        astFactory.functionDeclarationStatement(f);
-    _assertSource(
-        "main() {f() {} 42;}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "main",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2([
-                  fStatement,
-                  AstTestFactory.expressionStatement(AstTestFactory.integer(42))
-                ]))));
-  }
-
-  void test_visitFunctionDeclaration_local_expressionBody() {
-    FunctionDeclaration f = AstTestFactory.functionDeclaration(
-        null,
-        null,
-        "f",
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.expressionFunctionBody(AstTestFactory.integer(1))));
-    FunctionDeclarationStatement fStatement =
-        astFactory.functionDeclarationStatement(f);
-    _assertSource(
-        "main() {f() => 1; 2;}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "main",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2([
-                  fStatement,
-                  AstTestFactory.expressionStatement(AstTestFactory.integer(2))
-                ]))));
-  }
-
-  void test_visitFunctionDeclaration_normal() {
-    _assertSource(
-        "f() {}",
-        AstTestFactory.functionDeclaration(
-            null, null, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_setter() {
-    _assertSource(
-        "set f() {}",
-        AstTestFactory.functionDeclaration(
-            null, Keyword.SET, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_typeParameters() {
-    _assertSource(
-        "f<E>() {}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "f",
-            AstTestFactory.functionExpression3(
-                AstTestFactory.typeParameterList(['E']),
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2())));
-  }
-
-  void test_visitFunctionDeclaration_withMetadata() {
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null, null, "f", AstTestFactory.functionExpression());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated f() {}", declaration);
-  }
-
-  void test_visitFunctionDeclarationStatement() {
-    _assertSource(
-        "f() {}",
-        AstTestFactory.functionDeclarationStatement(
-            null, null, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionExpression() {
-    _assertSource("() {}", AstTestFactory.functionExpression());
-  }
-
-  void test_visitFunctionExpression_typeParameters() {
-    _assertSource(
-        "<E>() {}",
-        AstTestFactory.functionExpression3(
-            AstTestFactory.typeParameterList(['E']),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitFunctionExpressionInvocation_minimal() {
-    _assertSource(
-        "f()",
-        AstTestFactory.functionExpressionInvocation(
-            AstTestFactory.identifier3("f")));
-  }
-
-  void test_visitFunctionExpressionInvocation_typeArguments() {
-    _assertSource(
-        "f<A>()",
-        AstTestFactory.functionExpressionInvocation2(
-            AstTestFactory.identifier3("f"),
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
-  }
-
-  void test_visitFunctionTypeAlias_generic() {
-    _assertSource(
-        "typedef A F<B>();",
-        AstTestFactory.typeAlias(
-            AstTestFactory.typeName4("A"),
-            "F",
-            AstTestFactory.typeParameterList(["B"]),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitFunctionTypeAlias_nonGeneric() {
-    _assertSource(
-        "typedef A F();",
-        AstTestFactory.typeAlias(AstTestFactory.typeName4("A"), "F", null,
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitFunctionTypeAlias_withMetadata() {
-    FunctionTypeAlias declaration = AstTestFactory.typeAlias(
-        AstTestFactory.typeName4("A"),
-        "F",
-        null,
-        AstTestFactory.formalParameterList());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated typedef A F();", declaration);
-  }
-
-  void test_visitFunctionTypedFormalParameter_annotation() {
-    FunctionTypedFormalParameter parameter =
-        AstTestFactory.functionTypedFormalParameter(null, "f");
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A f()', parameter);
-  }
-
-  void test_visitFunctionTypedFormalParameter_noType() {
-    _assertSource(
-        "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
-  }
-
-  void test_visitFunctionTypedFormalParameter_nullable() {
-    _assertSource(
-        "T f()?",
-        astFactory.functionTypedFormalParameter2(
-            returnType: AstTestFactory.typeName4("T"),
-            identifier: AstTestFactory.identifier3('f'),
-            parameters: AstTestFactory.formalParameterList([]),
-            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
-  }
-
-  void test_visitFunctionTypedFormalParameter_type() {
-    _assertSource(
-        "T f()",
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4("T"), "f"));
-  }
-
-  void test_visitFunctionTypedFormalParameter_type_covariant() {
-    FunctionTypedFormalParameterImpl expected =
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4("T"), "f");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant T f()", expected);
-  }
-
-  void test_visitFunctionTypedFormalParameter_typeParameters() {
-    _assertSource(
-        "T f<E>()",
-        astFactory.functionTypedFormalParameter2(
-            returnType: AstTestFactory.typeName4("T"),
-            identifier: AstTestFactory.identifier3('f'),
-            typeParameters: AstTestFactory.typeParameterList(['E']),
-            parameters: AstTestFactory.formalParameterList([])));
-  }
-
-  void test_visitGenericFunctionType() {
-    _assertSource(
-        "int Function<T>(T)",
-        AstTestFactory.genericFunctionType(
-            AstTestFactory.typeName4("int"),
-            AstTestFactory.typeParameterList(['T']),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4("T"), null)
-            ])));
-  }
-
-  void test_visitGenericFunctionType_withQuestion() {
-    _assertSource(
-        "int Function<T>(T)?",
-        AstTestFactory.genericFunctionType(
-            AstTestFactory.typeName4("int"),
-            AstTestFactory.typeParameterList(['T']),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4("T"), null)
-            ]),
-            question: true));
-  }
-
-  void test_visitGenericTypeAlias() {
-    _assertSource(
-        "typedef X<S> = S Function<T>(T)",
-        AstTestFactory.genericTypeAlias(
-            'X',
-            AstTestFactory.typeParameterList(['S']),
-            AstTestFactory.genericFunctionType(
-                AstTestFactory.typeName4("S"),
-                AstTestFactory.typeParameterList(['T']),
-                AstTestFactory.formalParameterList([
-                  AstTestFactory.simpleFormalParameter4(
-                      AstTestFactory.typeName4("T"), null)
-                ]))));
-  }
-
-  void test_visitIfElement_else() {
-    _assertSource(
-        'if (b) 1 else 0',
-        astFactory.ifElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1),
-            elseElement: AstTestFactory.integer(0)));
-  }
-
-  void test_visitIfElement_then() {
-    _assertSource(
-        'if (b) 1',
-        astFactory.ifElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1)));
-  }
-
-  void test_visitIfStatement_withElse() {
-    _assertSource(
-        "if (c) {} else {}",
-        AstTestFactory.ifStatement2(AstTestFactory.identifier3("c"),
-            AstTestFactory.block(), AstTestFactory.block()));
-  }
-
-  void test_visitIfStatement_withoutElse() {
-    _assertSource(
-        "if (c) {}",
-        AstTestFactory.ifStatement(
-            AstTestFactory.identifier3("c"), AstTestFactory.block()));
-  }
-
-  void test_visitImplementsClause_multiple() {
-    _assertSource(
-        "implements A, B",
-        AstTestFactory.implementsClause(
-            [AstTestFactory.typeName4("A"), AstTestFactory.typeName4("B")]));
-  }
-
-  void test_visitImplementsClause_single() {
-    _assertSource("implements A",
-        AstTestFactory.implementsClause([AstTestFactory.typeName4("A")]));
-  }
-
-  void test_visitImportDirective_combinator() {
-    _assertSource(
-        "import 'a.dart' show A;",
-        AstTestFactory.importDirective3("a.dart", null, [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitImportDirective_combinators() {
-    _assertSource(
-        "import 'a.dart' show A hide B;",
-        AstTestFactory.importDirective3("a.dart", null, [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitImportDirective_deferred() {
-    _assertSource("import 'a.dart' deferred as p;",
-        AstTestFactory.importDirective2("a.dart", true, "p"));
-  }
-
-  void test_visitImportDirective_minimal() {
-    _assertSource(
-        "import 'a.dart';", AstTestFactory.importDirective3("a.dart", null));
-  }
-
-  void test_visitImportDirective_prefix() {
-    _assertSource("import 'a.dart' as p;",
-        AstTestFactory.importDirective3("a.dart", "p"));
-  }
-
-  void test_visitImportDirective_prefix_combinator() {
-    _assertSource(
-        "import 'a.dart' as p show A;",
-        AstTestFactory.importDirective3("a.dart", "p", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitImportDirective_prefix_combinators() {
-    _assertSource(
-        "import 'a.dart' as p show A hide B;",
-        AstTestFactory.importDirective3("a.dart", "p", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitImportDirective_withMetadata() {
-    ImportDirective directive = AstTestFactory.importDirective3("a.dart", null);
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated import 'a.dart';", directive);
-  }
-
-  void test_visitImportHideCombinator_multiple() {
-    _assertSource(
-        "hide a, b",
-        AstTestFactory.hideCombinator([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitImportHideCombinator_single() {
-    _assertSource("hide a",
-        AstTestFactory.hideCombinator([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitImportShowCombinator_multiple() {
-    _assertSource(
-        "show a, b",
-        AstTestFactory.showCombinator([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitImportShowCombinator_single() {
-    _assertSource("show a",
-        AstTestFactory.showCombinator([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitIndexExpression() {
-    _assertSource(
-        "a[i]",
-        AstTestFactory.indexExpression(
-            AstTestFactory.identifier3("a"), AstTestFactory.identifier3("i")));
-  }
-
-  void test_visitInstanceCreationExpression_const() {
-    _assertSource(
-        "const C()",
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.CONST, AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitInstanceCreationExpression_named() {
-    _assertSource(
-        "new C.c()",
-        AstTestFactory.instanceCreationExpression3(
-            Keyword.NEW, AstTestFactory.typeName4("C"), "c"));
-  }
-
-  void test_visitInstanceCreationExpression_unnamed() {
-    _assertSource(
-        "new C()",
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.NEW, AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitIntegerLiteral() {
-    _assertSource("42", AstTestFactory.integer(42));
-  }
-
-  void test_visitInterpolationExpression_expression() {
-    _assertSource(
-        "\${a}",
-        AstTestFactory.interpolationExpression(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitInterpolationExpression_identifier() {
-    _assertSource("\$a", AstTestFactory.interpolationExpression2("a"));
-  }
-
-  void test_visitInterpolationString() {
-    _assertSource("'x", AstTestFactory.interpolationString("'x", "x"));
-  }
-
-  void test_visitIsExpression_negated() {
-    _assertSource(
-        "a is! C",
-        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), true,
-            AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitIsExpression_normal() {
-    _assertSource(
-        "a is C",
-        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), false,
-            AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitLabel() {
-    _assertSource("a:", AstTestFactory.label2("a"));
-  }
-
-  void test_visitLabeledStatement_multiple() {
-    _assertSource(
-        "a: b: return;",
-        AstTestFactory.labeledStatement(
-            [AstTestFactory.label2("a"), AstTestFactory.label2("b")],
-            AstTestFactory.returnStatement()));
-  }
-
-  void test_visitLabeledStatement_single() {
-    _assertSource(
-        "a: return;",
-        AstTestFactory.labeledStatement(
-            [AstTestFactory.label2("a")], AstTestFactory.returnStatement()));
-  }
-
-  void test_visitLibraryDirective() {
-    _assertSource("library l;", AstTestFactory.libraryDirective2("l"));
-  }
-
-  void test_visitLibraryDirective_withMetadata() {
-    LibraryDirective directive = AstTestFactory.libraryDirective2("l");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated library l;", directive);
-  }
-
-  void test_visitLibraryIdentifier_multiple() {
-    _assertSource(
-        "a.b.c",
-        AstTestFactory.libraryIdentifier([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b"),
-          AstTestFactory.identifier3("c")
-        ]));
-  }
-
-  void test_visitLibraryIdentifier_single() {
-    _assertSource("a",
-        AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitListLiteral_complex() {
-    _assertSource(
-        '<int>[0, for (e in l) 0, if (b) 1, ...[0]]',
-        astFactory.listLiteral(
-            null,
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [
-              AstTestFactory.integer(0),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('e'),
-                      iterable: AstTestFactory.identifier3('l')),
-                  body: AstTestFactory.integer(0)),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('b'),
-                  thenElement: AstTestFactory.integer(1)),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.listLiteral(
-                      null, null, null, [AstTestFactory.integer(0)], null))
-            ],
-            null));
-  }
-
-  void test_visitListLiteral_const() {
-    _assertSource("const []", AstTestFactory.listLiteral2(Keyword.CONST, null));
-  }
-
-  void test_visitListLiteral_empty() {
-    _assertSource("[]", AstTestFactory.listLiteral());
-  }
-
-  void test_visitListLiteral_nonEmpty() {
-    _assertSource(
-        "[a, b, c]",
-        AstTestFactory.listLiteral([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b"),
-          AstTestFactory.identifier3("c")
-        ]));
-  }
-
-  void test_visitListLiteral_withConst_withoutTypeArgs() {
-    _assertSource(
-        'const [0]',
-        astFactory.listLiteral(TokenFactory.tokenFromKeyword(Keyword.CONST),
-            null, null, [AstTestFactory.integer(0)], null));
-  }
-
-  void test_visitListLiteral_withConst_withTypeArgs() {
-    _assertSource(
-        'const <int>[0]',
-        astFactory.listLiteral(
-            TokenFactory.tokenFromKeyword(Keyword.CONST),
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [AstTestFactory.integer(0)],
-            null));
-  }
-
-  void test_visitListLiteral_withoutConst_withoutTypeArgs() {
-    _assertSource(
-        '[0]',
-        astFactory.listLiteral(
-            null, null, null, [AstTestFactory.integer(0)], null));
-  }
-
-  void test_visitListLiteral_withoutConst_withTypeArgs() {
-    _assertSource(
-        '<int>[0]',
-        astFactory.listLiteral(
-            null,
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [AstTestFactory.integer(0)],
-            null));
-  }
-
-  void test_visitMapLiteral_const() {
-    _assertSource(
-        "const {}", AstTestFactory.setOrMapLiteral(Keyword.CONST, null));
-  }
-
-  void test_visitMapLiteral_empty() {
-    _assertSource("{}", AstTestFactory.setOrMapLiteral(null, null));
-  }
-
-  void test_visitMapLiteral_nonEmpty() {
-    _assertSource(
-        "{'a' : a, 'b' : b, 'c' : c}",
-        AstTestFactory.setOrMapLiteral(null, null, [
-          AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("a")),
-          AstTestFactory.mapLiteralEntry("b", AstTestFactory.identifier3("b")),
-          AstTestFactory.mapLiteralEntry("c", AstTestFactory.identifier3("c"))
-        ]));
-  }
-
-  void test_visitMapLiteralEntry() {
-    _assertSource("'a' : b",
-        AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitMethodDeclaration_external() {
-    _assertSource(
-        "external m();",
-        AstTestFactory.methodDeclaration(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitMethodDeclaration_external_returnType() {
-    _assertSource(
-        "external T m();",
-        AstTestFactory.methodDeclaration(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitMethodDeclaration_getter() {
-    _assertSource(
-        "get m {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            Keyword.GET,
-            null,
-            AstTestFactory.identifier3("m"),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_getter_returnType() {
-    _assertSource(
-        "T get m {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            Keyword.GET,
-            null,
-            AstTestFactory.identifier3("m"),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_getter_seturnType() {
-    _assertSource(
-        "T set m(var v) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            Keyword.SET,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_minimal() {
-    _assertSource(
-        "m() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_multipleParameters() {
-    _assertSource(
-        "m(var a, var b) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
-            ]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_operator() {
-    _assertSource(
-        "operator +() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            Keyword.OPERATOR,
-            AstTestFactory.identifier3("+"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_operator_returnType() {
-    _assertSource(
-        "T operator +() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            Keyword.OPERATOR,
-            AstTestFactory.identifier3("+"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_returnType() {
-    _assertSource(
-        "T m() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_setter() {
-    _assertSource(
-        "set m(var v) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            Keyword.SET,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_static() {
-    _assertSource(
-        "static m() {}",
-        AstTestFactory.methodDeclaration2(
-            Keyword.STATIC,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_static_returnType() {
-    _assertSource(
-        "static T m() {}",
-        AstTestFactory.methodDeclaration2(
-            Keyword.STATIC,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_typeParameters() {
-    _assertSource(
-        "m<E>() {}",
-        AstTestFactory.methodDeclaration3(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.typeParameterList(['E']),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_withMetadata() {
-    MethodDeclaration declaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated m() {}", declaration);
-  }
-
-  void test_visitMethodInvocation_conditional() {
-    _assertSource(
-        "t?.m()",
-        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m",
-            null, TokenType.QUESTION_PERIOD));
-  }
-
-  void test_visitMethodInvocation_noTarget() {
-    _assertSource("m()", AstTestFactory.methodInvocation2("m"));
-  }
-
-  void test_visitMethodInvocation_target() {
-    _assertSource("t.m()",
-        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m"));
-  }
-
-  void test_visitMethodInvocation_typeArguments() {
-    _assertSource(
-        "m<A>()",
-        AstTestFactory.methodInvocation3(null, "m",
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
-  }
-
-  void test_visitNamedExpression() {
-    _assertSource("a: b",
-        AstTestFactory.namedExpression2("a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitNamedFormalParameter() {
-    _assertSource(
-        "var a: 0",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitNativeClause() {
-    _assertSource("native 'code'", AstTestFactory.nativeClause("code"));
-  }
-
-  void test_visitNativeFunctionBody() {
-    _assertSource("native 'str';", AstTestFactory.nativeFunctionBody("str"));
-  }
-
-  void test_visitNullLiteral() {
-    _assertSource("null", AstTestFactory.nullLiteral());
-  }
-
-  void test_visitParenthesizedExpression() {
-    _assertSource(
-        "(a)",
-        AstTestFactory.parenthesizedExpression(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitPartDirective() {
-    _assertSource("part 'a.dart';", AstTestFactory.partDirective2("a.dart"));
-  }
-
-  void test_visitPartDirective_withMetadata() {
-    PartDirective directive = AstTestFactory.partDirective2("a.dart");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated part 'a.dart';", directive);
-  }
-
-  void test_visitPartOfDirective() {
-    _assertSource(
-        "part of l;",
-        AstTestFactory.partOfDirective(
-            AstTestFactory.libraryIdentifier2(["l"])));
-  }
-
-  void test_visitPartOfDirective_withMetadata() {
-    PartOfDirective directive = AstTestFactory.partOfDirective(
-        AstTestFactory.libraryIdentifier2(["l"]));
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated part of l;", directive);
-  }
-
-  void test_visitPositionalFormalParameter() {
-    _assertSource(
-        "var a = 0",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitPostfixExpression() {
-    _assertSource(
-        "a++",
-        AstTestFactory.postfixExpression(
-            AstTestFactory.identifier3("a"), TokenType.PLUS_PLUS));
-  }
-
-  void test_visitPrefixedIdentifier() {
-    _assertSource("a.b", AstTestFactory.identifier5("a", "b"));
-  }
-
-  void test_visitPrefixExpression() {
-    _assertSource(
-        "-a",
-        AstTestFactory.prefixExpression(
-            TokenType.MINUS, AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitPrefixExpression_precedence() {
-    var a = AstTestFactory.identifier3('a');
-    var b = AstTestFactory.identifier3('b');
-    _assertSource(
-        '!(a == b)',
-        AstTestFactory.prefixExpression(TokenType.BANG,
-            AstTestFactory.binaryExpression(a, TokenType.EQ_EQ, b)));
-  }
-
-  void test_visitPropertyAccess() {
-    _assertSource("a.b",
-        AstTestFactory.propertyAccess2(AstTestFactory.identifier3("a"), "b"));
-  }
-
-  void test_visitPropertyAccess_conditional() {
-    _assertSource(
-        "a?.b",
-        AstTestFactory.propertyAccess2(
-            AstTestFactory.identifier3("a"), "b", TokenType.QUESTION_PERIOD));
-  }
-
-  void test_visitRedirectingConstructorInvocation_named() {
-    _assertSource(
-        "this.c()", AstTestFactory.redirectingConstructorInvocation2("c"));
-  }
-
-  void test_visitRedirectingConstructorInvocation_unnamed() {
-    _assertSource("this()", AstTestFactory.redirectingConstructorInvocation());
-  }
-
-  void test_visitRethrowExpression() {
-    _assertSource("rethrow", AstTestFactory.rethrowExpression());
-  }
-
-  void test_visitReturnStatement_expression() {
-    _assertSource("return a;",
-        AstTestFactory.returnStatement2(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitReturnStatement_noExpression() {
-    _assertSource("return;", AstTestFactory.returnStatement());
-  }
-
-  void test_visitScriptTag() {
-    String scriptTag = "!#/bin/dart.exe";
-    _assertSource(scriptTag, AstTestFactory.scriptTag(scriptTag));
-  }
-
-  void test_visitSetOrMapLiteral_map_complex() {
-    _assertSource(
-        "<String, String>{'a' : 'b', for (c in d) 'e' : 'f', if (g) 'h' : 'i', ...{'j' : 'k'}}",
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [
-              AstTestFactory.mapLiteralEntry3('a', 'b'),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('c'),
-                      iterable: AstTestFactory.identifier3('d')),
-                  body: AstTestFactory.mapLiteralEntry3('e', 'f')),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('g'),
-                  thenElement: AstTestFactory.mapLiteralEntry3('h', 'i')),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.setOrMapLiteral(
-                      elements: [AstTestFactory.mapLiteralEntry3('j', 'k')]))
-            ]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withConst_withoutTypeArgs() {
-    _assertSource(
-        "const {'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withConst_withTypeArgs() {
-    _assertSource(
-        "const <String, String>{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withoutConst_withoutTypeArgs() {
-    _assertSource(
-        "{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withoutConst_withTypeArgs() {
-    _assertSource(
-        "<String, String>{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_set_complex() {
-    _assertSource(
-        '<int>{0, for (e in l) 0, if (b) 1, ...[0]}',
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [
-              AstTestFactory.integer(0),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('e'),
-                      iterable: AstTestFactory.identifier3('l')),
-                  body: AstTestFactory.integer(0)),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('b'),
-                  thenElement: AstTestFactory.integer(1)),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.listLiteral(
-                      null, null, null, [AstTestFactory.integer(0)], null))
-            ]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withConst_withoutTypeArgs() {
-    _assertSource(
-        'const {0}',
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withConst_withTypeArgs() {
-    _assertSource(
-        'const <int>{0}',
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withoutConst_withoutTypeArgs() {
-    _assertSource('{0}',
-        astFactory.setOrMapLiteral(elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withoutConst_withTypeArgs() {
-    _assertSource(
-        '<int>{0}',
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSimpleFormalParameter_annotation() {
-    SimpleFormalParameter parameter =
-        AstTestFactory.simpleFormalParameter3('x');
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A x', parameter);
-  }
-
-  void test_visitSimpleFormalParameter_keyword() {
-    _assertSource(
-        "var a", AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"));
-  }
-
-  void test_visitSimpleFormalParameter_keyword_type() {
-    _assertSource(
-        "final A a",
-        AstTestFactory.simpleFormalParameter2(
-            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitSimpleFormalParameter_type() {
-    _assertSource(
-        "A a",
-        AstTestFactory.simpleFormalParameter4(
-            AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitSimpleFormalParameter_type_covariant() {
-    SimpleFormalParameterImpl expected = AstTestFactory.simpleFormalParameter4(
-        AstTestFactory.typeName4("A"), "a");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant A a", expected);
-  }
-
-  void test_visitSimpleIdentifier() {
-    _assertSource("a", AstTestFactory.identifier3("a"));
-  }
-
-  void test_visitSimpleStringLiteral() {
-    _assertSource("'a'", AstTestFactory.string2("a"));
-  }
-
-  void test_visitSpreadElement_nonNullable() {
-    _assertSource(
-        '...[0]',
-        astFactory.spreadElement(
-            spreadOperator:
-                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
-            expression: astFactory.listLiteral(
-                null, null, null, [AstTestFactory.integer(0)], null)));
-  }
-
-  @failingTest
-  void test_visitSpreadElement_nullable() {
-    // TODO(brianwilkerson) Replace the token type below when there is one for
-    //  '...?'.
-    _assertSource(
-        '...?[0]',
-        astFactory.spreadElement(
-            spreadOperator:
-                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
-            expression: astFactory.listLiteral(
-                null, null, null, [AstTestFactory.integer(0)], null)));
-  }
-
-  void test_visitStringInterpolation() {
-    _assertSource(
-        "'a\${e}b'",
-        AstTestFactory.string([
-          AstTestFactory.interpolationString("'a", "a"),
-          AstTestFactory.interpolationExpression(
-              AstTestFactory.identifier3("e")),
-          AstTestFactory.interpolationString("b'", "b")
-        ]));
-  }
-
-  void test_visitSuperConstructorInvocation() {
-    _assertSource("super()", AstTestFactory.superConstructorInvocation());
-  }
-
-  void test_visitSuperConstructorInvocation_named() {
-    _assertSource("super.c()", AstTestFactory.superConstructorInvocation2("c"));
-  }
-
-  void test_visitSuperExpression() {
-    _assertSource("super", AstTestFactory.superExpression());
-  }
-
-  void test_visitSwitchCase_multipleLabels() {
-    _assertSource(
-        "l1: l2: case a: {}",
-        AstTestFactory.switchCase2(
-            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
-            AstTestFactory.identifier3("a"),
-            [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_multipleStatements() {
-    _assertSource(
-        "case a: {} {}",
-        AstTestFactory.switchCase(AstTestFactory.identifier3("a"),
-            [AstTestFactory.block(), AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_noLabels() {
-    _assertSource(
-        "case a: {}",
-        AstTestFactory.switchCase(
-            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_singleLabel() {
-    _assertSource(
-        "l1: case a: {}",
-        AstTestFactory.switchCase2([AstTestFactory.label2("l1")],
-            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_multipleLabels() {
-    _assertSource(
-        "l1: l2: default: {}",
-        AstTestFactory.switchDefault(
-            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
-            [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_multipleStatements() {
-    _assertSource(
-        "default: {} {}",
-        AstTestFactory.switchDefault2(
-            [AstTestFactory.block(), AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_noLabels() {
-    _assertSource(
-        "default: {}", AstTestFactory.switchDefault2([AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_singleLabel() {
-    _assertSource(
-        "l1: default: {}",
-        AstTestFactory.switchDefault(
-            [AstTestFactory.label2("l1")], [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchStatement() {
-    _assertSource(
-        "switch (a) {case 'b': {} default: {}}",
-        AstTestFactory.switchStatement(AstTestFactory.identifier3("a"), [
-          AstTestFactory.switchCase(
-              AstTestFactory.string2("b"), [AstTestFactory.block()]),
-          AstTestFactory.switchDefault2([AstTestFactory.block()])
-        ]));
-  }
-
-  void test_visitSymbolLiteral_multiple() {
-    _assertSource("#a.b.c", AstTestFactory.symbolLiteral(["a", "b", "c"]));
-  }
-
-  void test_visitSymbolLiteral_single() {
-    _assertSource("#a", AstTestFactory.symbolLiteral(["a"]));
-  }
-
-  void test_visitThisExpression() {
-    _assertSource("this", AstTestFactory.thisExpression());
-  }
-
-  void test_visitThrowStatement() {
-    _assertSource("throw e",
-        AstTestFactory.throwExpression2(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitTopLevelVariableDeclaration_multiple() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.topLevelVariableDeclaration2(
-            Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitTopLevelVariableDeclaration_single() {
-    _assertSource(
-        "var a, b;",
-        AstTestFactory.topLevelVariableDeclaration2(Keyword.VAR, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitTryStatement_catch() {
-    _assertSource(
-        "try {} on E {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))]));
-  }
-
-  void test_visitTryStatement_catches() {
-    _assertSource(
-        "try {} on E {} on F {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(), [
-          AstTestFactory.catchClause3(AstTestFactory.typeName4("E")),
-          AstTestFactory.catchClause3(AstTestFactory.typeName4("F"))
-        ]));
-  }
-
-  void test_visitTryStatement_catchFinally() {
-    _assertSource(
-        "try {} on E {} finally {}",
-        AstTestFactory.tryStatement3(
-            AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))],
-            AstTestFactory.block()));
-  }
-
-  void test_visitTryStatement_finally() {
-    _assertSource(
-        "try {} finally {}",
-        AstTestFactory.tryStatement(
-            AstTestFactory.block(), AstTestFactory.block()));
-  }
-
-  void test_visitTypeArgumentList_multiple() {
-    _assertSource(
-        "<E, F>",
-        AstTestFactory.typeArgumentList(
-            [AstTestFactory.typeName4("E"), AstTestFactory.typeName4("F")]));
-  }
-
-  void test_visitTypeArgumentList_single() {
-    _assertSource("<E>",
-        AstTestFactory.typeArgumentList([AstTestFactory.typeName4("E")]));
-  }
-
-  void test_visitTypeName_multipleArgs() {
-    _assertSource(
-        "C<D, E>",
-        AstTestFactory.typeName4("C",
-            [AstTestFactory.typeName4("D"), AstTestFactory.typeName4("E")]));
-  }
-
-  void test_visitTypeName_nestedArg() {
-    _assertSource(
-        "C<D<E>>",
-        AstTestFactory.typeName4("C", [
-          AstTestFactory.typeName4("D", [AstTestFactory.typeName4("E")])
-        ]));
-  }
-
-  void test_visitTypeName_noArgs() {
-    _assertSource("C", AstTestFactory.typeName4("C"));
-  }
-
-  void test_visitTypeName_noArgs_withQuestion() {
-    _assertSource("C?", AstTestFactory.typeName4("C", null, true));
-  }
-
-  void test_visitTypeName_singleArg() {
-    _assertSource(
-        "C<D>", AstTestFactory.typeName4("C", [AstTestFactory.typeName4("D")]));
-  }
-
-  void test_visitTypeName_singleArg_withQuestion() {
-    _assertSource("C<D>?",
-        AstTestFactory.typeName4("C", [AstTestFactory.typeName4("D")], true));
-  }
-
-  void test_visitTypeParameter_withExtends() {
-    _assertSource("E extends C",
-        AstTestFactory.typeParameter2("E", AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitTypeParameter_withMetadata() {
-    TypeParameter parameter = AstTestFactory.typeParameter("E");
-    parameter.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated E", parameter);
-  }
-
-  void test_visitTypeParameter_withoutExtends() {
-    _assertSource("E", AstTestFactory.typeParameter("E"));
-  }
-
-  void test_visitTypeParameterList_multiple() {
-    _assertSource("<E, F>", AstTestFactory.typeParameterList(["E", "F"]));
-  }
-
-  void test_visitTypeParameterList_single() {
-    _assertSource("<E>", AstTestFactory.typeParameterList(["E"]));
-  }
-
-  void test_visitVariableDeclaration_initialized() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.variableDeclaration2(
-            "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitVariableDeclaration_uninitialized() {
-    _assertSource("a", AstTestFactory.variableDeclaration("a"));
-  }
-
-  void test_visitVariableDeclaration_withMetadata() {
-    VariableDeclaration declaration = AstTestFactory.variableDeclaration("a");
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated a", declaration);
-  }
-
-  void test_visitVariableDeclarationList_const_type() {
-    _assertSource(
-        "const C a, b",
-        AstTestFactory.variableDeclarationList(
-            Keyword.CONST, AstTestFactory.typeName4("C"), [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_final_noType() {
-    _assertSource(
-        "final a, b",
-        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_final_withMetadata() {
-    VariableDeclarationList declarationList =
-        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
-      AstTestFactory.variableDeclaration("a"),
-      AstTestFactory.variableDeclaration("b")
-    ]);
-    declarationList.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated final a, b", declarationList);
-  }
-
-  void test_visitVariableDeclarationList_type() {
-    _assertSource(
-        "C a, b",
-        AstTestFactory.variableDeclarationList(
-            null, AstTestFactory.typeName4("C"), [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_var() {
-    _assertSource(
-        "var a, b",
-        AstTestFactory.variableDeclarationList2(Keyword.VAR, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationStatement() {
-    _assertSource(
-        "C c;",
-        AstTestFactory.variableDeclarationStatement(
-            null,
-            AstTestFactory.typeName4("C"),
-            [AstTestFactory.variableDeclaration("c")]));
-  }
-
-  void test_visitWhileStatement() {
-    _assertSource(
-        "while (c) {}",
-        AstTestFactory.whileStatement(
-            AstTestFactory.identifier3("c"), AstTestFactory.block()));
-  }
-
-  void test_visitWithClause_multiple() {
-    _assertSource(
-        "with A, B, C",
-        AstTestFactory.withClause([
-          AstTestFactory.typeName4("A"),
-          AstTestFactory.typeName4("B"),
-          AstTestFactory.typeName4("C")
-        ]));
-  }
-
-  void test_visitWithClause_single() {
-    _assertSource(
-        "with A", AstTestFactory.withClause([AstTestFactory.typeName4("A")]));
-  }
-
-  void test_visitYieldStatement() {
-    _assertSource("yield e;",
-        AstTestFactory.yieldStatement(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitYieldStatement_each() {
-    _assertSource("yield* e;",
-        AstTestFactory.yieldEachStatement(AstTestFactory.identifier3("e")));
-  }
-
-  /**
-   * Assert that a `ToSourceVisitor2` will produce the [expectedSource] when
-   * visiting the given [node].
-   */
-  void _assertSource(String expectedSource, AstNode node) {
-    StringBuffer buffer = new StringBuffer();
-    node.accept(new ToSourceVisitor2(buffer));
-    expect(buffer.toString(), expectedSource);
-  }
-}
-
-@deprecated
-@reflectiveTest
-class ToSourceVisitorTest {
-  void test_visitAdjacentStrings() {
-    _assertSource(
-        "'a' 'b'",
-        AstTestFactory.adjacentStrings(
-            [AstTestFactory.string2("a"), AstTestFactory.string2("b")]));
-  }
-
-  void test_visitAnnotation_constant() {
-    _assertSource(
-        "@A", AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-  }
-
-  void test_visitAnnotation_constructor() {
-    _assertSource(
-        "@A.c()",
-        AstTestFactory.annotation2(AstTestFactory.identifier3("A"),
-            AstTestFactory.identifier3("c"), AstTestFactory.argumentList()));
-  }
-
-  void test_visitArgumentList() {
-    _assertSource(
-        "(a, b)",
-        AstTestFactory.argumentList([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitAsExpression() {
-    _assertSource(
-        "e as T",
-        AstTestFactory.asExpression(
-            AstTestFactory.identifier3("e"), AstTestFactory.typeName4("T")));
-  }
-
-  void test_visitAssertStatement() {
-    _assertSource("assert (a);",
-        AstTestFactory.assertStatement(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitAssertStatement_withMessage() {
-    _assertSource(
-        "assert (a, b);",
-        AstTestFactory.assertStatement(
-            AstTestFactory.identifier3("a"), AstTestFactory.identifier3('b')));
-  }
-
-  void test_visitAssignmentExpression() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.assignmentExpression(AstTestFactory.identifier3("a"),
-            TokenType.EQ, AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitAwaitExpression() {
-    _assertSource("await e",
-        AstTestFactory.awaitExpression(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitBinaryExpression() {
-    _assertSource(
-        "a + b",
-        AstTestFactory.binaryExpression(AstTestFactory.identifier3("a"),
-            TokenType.PLUS, AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitBlock_empty() {
-    _assertSource("{}", AstTestFactory.block());
-  }
-
-  void test_visitBlock_nonEmpty() {
-    _assertSource(
-        "{break; break;}",
-        AstTestFactory.block([
-          AstTestFactory.breakStatement(),
-          AstTestFactory.breakStatement()
-        ]));
-  }
-
-  void test_visitBlockFunctionBody_async() {
-    _assertSource("async {}", AstTestFactory.asyncBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_async_star() {
-    _assertSource(
-        "async* {}", AstTestFactory.asyncGeneratorBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_simple() {
-    _assertSource("{}", AstTestFactory.blockFunctionBody2());
-  }
-
-  void test_visitBlockFunctionBody_sync() {
-    _assertSource("sync {}", AstTestFactory.syncBlockFunctionBody());
-  }
-
-  void test_visitBlockFunctionBody_sync_star() {
-    _assertSource("sync* {}", AstTestFactory.syncGeneratorBlockFunctionBody());
-  }
-
-  void test_visitBooleanLiteral_false() {
-    _assertSource("false", AstTestFactory.booleanLiteral(false));
-  }
-
-  void test_visitBooleanLiteral_true() {
-    _assertSource("true", AstTestFactory.booleanLiteral(true));
-  }
-
-  void test_visitBreakStatement_label() {
-    _assertSource("break l;", AstTestFactory.breakStatement2("l"));
-  }
-
-  void test_visitBreakStatement_noLabel() {
-    _assertSource("break;", AstTestFactory.breakStatement());
-  }
-
-  void test_visitCascadeExpression_field() {
-    _assertSource(
-        "a..b..c",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedPropertyAccess("b"),
-          AstTestFactory.cascadedPropertyAccess("c")
-        ]));
-  }
-
-  void test_visitCascadeExpression_index() {
-    _assertSource(
-        "a..[0]..[1]",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(0)),
-          AstTestFactory.cascadedIndexExpression(AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitCascadeExpression_method() {
-    _assertSource(
-        "a..b()..c()",
-        AstTestFactory.cascadeExpression(AstTestFactory.identifier3("a"), [
-          AstTestFactory.cascadedMethodInvocation("b"),
-          AstTestFactory.cascadedMethodInvocation("c")
-        ]));
-  }
-
-  void test_visitCatchClause_catch_noStack() {
-    _assertSource("catch (e) {}", AstTestFactory.catchClause("e"));
-  }
-
-  void test_visitCatchClause_catch_stack() {
-    _assertSource("catch (e, s) {}", AstTestFactory.catchClause2("e", "s"));
-  }
-
-  void test_visitCatchClause_on() {
-    _assertSource(
-        "on E {}", AstTestFactory.catchClause3(AstTestFactory.typeName4("E")));
-  }
-
-  void test_visitCatchClause_on_catch() {
-    _assertSource("on E catch (e) {}",
-        AstTestFactory.catchClause4(AstTestFactory.typeName4("E"), "e"));
-  }
-
-  void test_visitClassDeclaration_abstract() {
-    _assertSource(
-        "abstract class C {}",
-        AstTestFactory.classDeclaration(
-            Keyword.ABSTRACT, "C", null, null, null, null));
-  }
-
-  void test_visitClassDeclaration_empty() {
-    _assertSource("class C {}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null));
-  }
-
-  void test_visitClassDeclaration_extends() {
-    _assertSource(
-        "class C extends A {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            null));
-  }
-
-  void test_visitClassDeclaration_extends_implements() {
-    _assertSource(
-        "class C extends A implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_extends_with() {
-    _assertSource(
-        "class C extends A with M {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            null));
-  }
-
-  void test_visitClassDeclaration_extends_with_implements() {
-    _assertSource(
-        "class C extends A with M implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            null,
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_implements() {
-    _assertSource(
-        "class C implements B {}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_multipleMember() {
-    _assertSource(
-        "class C {var a; var b;}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]),
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("b")])
-        ]));
-  }
-
-  void test_visitClassDeclaration_parameters() {
-    _assertSource(
-        "class C<E> {}",
-        AstTestFactory.classDeclaration(null, "C",
-            AstTestFactory.typeParameterList(["E"]), null, null, null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends() {
-    _assertSource(
-        "class C<E> extends A {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_implements() {
-    _assertSource(
-        "class C<E> extends A implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with() {
-    _assertSource(
-        "class C<E> extends A with M {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            null));
-  }
-
-  void test_visitClassDeclaration_parameters_extends_with_implements() {
-    _assertSource(
-        "class C<E> extends A with M implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            AstTestFactory.extendsClause(AstTestFactory.typeName4("A")),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_parameters_implements() {
-    _assertSource(
-        "class C<E> implements B {}",
-        AstTestFactory.classDeclaration(
-            null,
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            null,
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("B")])));
-  }
-
-  void test_visitClassDeclaration_singleMember() {
-    _assertSource(
-        "class C {var a;}",
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null, [
-          AstTestFactory.fieldDeclaration2(
-              false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitClassDeclaration_withMetadata() {
-    ClassDeclaration declaration =
-        AstTestFactory.classDeclaration(null, "C", null, null, null, null);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated class C {}", declaration);
-  }
-
-  void test_visitClassTypeAlias_abstract() {
-    _assertSource(
-        "abstract class C = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_abstract_implements() {
-    _assertSource(
-        "abstract class C = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_generic() {
-    _assertSource(
-        "class C<E> = S<E> with M1<E>;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            AstTestFactory.typeName4("S", [AstTestFactory.typeName4("E")]),
-            AstTestFactory.withClause([
-              AstTestFactory.typeName4("M1", [AstTestFactory.typeName4("E")])
-            ]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_implements() {
-    _assertSource(
-        "class C = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_minimal() {
-    _assertSource(
-        "class C = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            null,
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract() {
-    _assertSource(
-        "abstract class C<E> = S with M1;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            null));
-  }
-
-  void test_visitClassTypeAlias_parameters_abstract_implements() {
-    _assertSource(
-        "abstract class C<E> = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            Keyword.ABSTRACT,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_parameters_implements() {
-    _assertSource(
-        "class C<E> = S with M1 implements I;",
-        AstTestFactory.classTypeAlias(
-            "C",
-            AstTestFactory.typeParameterList(["E"]),
-            null,
-            AstTestFactory.typeName4("S"),
-            AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-            AstTestFactory.implementsClause([AstTestFactory.typeName4("I")])));
-  }
-
-  void test_visitClassTypeAlias_withMetadata() {
-    ClassTypeAlias declaration = AstTestFactory.classTypeAlias(
-        "C",
-        null,
-        null,
-        AstTestFactory.typeName4("S"),
-        AstTestFactory.withClause([AstTestFactory.typeName4("M1")]),
-        null);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated class C = S with M1;", declaration);
-  }
-
-  void test_visitComment() {
-    _assertSource(
-        "",
-        astFactory.blockComment(
-            <Token>[TokenFactory.tokenFromString("/* comment */")]));
-  }
-
-  void test_visitCommentReference() {
-    _assertSource(
-        "", astFactory.commentReference(null, AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitCompilationUnit_declaration() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.compilationUnit2([
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_directive() {
-    _assertSource(
-        "library l;",
-        AstTestFactory.compilationUnit3(
-            [AstTestFactory.libraryDirective2("l")]));
-  }
-
-  void test_visitCompilationUnit_directive_declaration() {
-    _assertSource(
-        "library l; var a;",
-        AstTestFactory.compilationUnit4([
-          AstTestFactory.libraryDirective2("l")
-        ], [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_empty() {
-    _assertSource("", AstTestFactory.compilationUnit());
-  }
-
-  void test_visitCompilationUnit_script() {
-    _assertSource(
-        "!#/bin/dartvm", AstTestFactory.compilationUnit5("!#/bin/dartvm"));
-  }
-
-  void test_visitCompilationUnit_script_declaration() {
-    _assertSource(
-        "!#/bin/dartvm var a;",
-        AstTestFactory.compilationUnit6("!#/bin/dartvm", [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitCompilationUnit_script_directive() {
-    _assertSource(
-        "!#/bin/dartvm library l;",
-        AstTestFactory.compilationUnit7(
-            "!#/bin/dartvm", [AstTestFactory.libraryDirective2("l")]));
-  }
-
-  void test_visitCompilationUnit_script_directives_declarations() {
-    _assertSource(
-        "!#/bin/dartvm library l; var a;",
-        AstTestFactory.compilationUnit8("!#/bin/dartvm", [
-          AstTestFactory.libraryDirective2("l")
-        ], [
-          AstTestFactory.topLevelVariableDeclaration2(
-              Keyword.VAR, [AstTestFactory.variableDeclaration("a")])
-        ]));
-  }
-
-  void test_visitConditionalExpression() {
-    _assertSource(
-        "a ? b : c",
-        AstTestFactory.conditionalExpression(AstTestFactory.identifier3("a"),
-            AstTestFactory.identifier3("b"), AstTestFactory.identifier3("c")));
-  }
-
-  void test_visitConstructorDeclaration_const() {
-    _assertSource(
-        "const C() {}",
-        AstTestFactory.constructorDeclaration2(
-            Keyword.CONST,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_external() {
-    _assertSource(
-        "external C();",
-        AstTestFactory.constructorDeclaration(AstTestFactory.identifier3("C"),
-            null, AstTestFactory.formalParameterList(), null));
-  }
-
-  void test_visitConstructorDeclaration_minimal() {
-    _assertSource(
-        "C() {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_multipleInitializers() {
-    _assertSource(
-        "C() : a = b, c = d {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            [
-              AstTestFactory.constructorFieldInitializer(
-                  false, "a", AstTestFactory.identifier3("b")),
-              AstTestFactory.constructorFieldInitializer(
-                  false, "c", AstTestFactory.identifier3("d"))
-            ],
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_multipleParameters() {
-    _assertSource(
-        "C(var a, var b) {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
-            ]),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_named() {
-    _assertSource(
-        "C.m() {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            "m",
-            AstTestFactory.formalParameterList(),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_singleInitializer() {
-    _assertSource(
-        "C() : a = b {}",
-        AstTestFactory.constructorDeclaration2(
-            null,
-            null,
-            AstTestFactory.identifier3("C"),
-            null,
-            AstTestFactory.formalParameterList(),
-            [
-              AstTestFactory.constructorFieldInitializer(
-                  false, "a", AstTestFactory.identifier3("b"))
-            ],
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitConstructorDeclaration_withMetadata() {
-    ConstructorDeclaration declaration = AstTestFactory.constructorDeclaration2(
-        null,
-        null,
-        AstTestFactory.identifier3("C"),
-        null,
-        AstTestFactory.formalParameterList(),
-        null,
-        AstTestFactory.blockFunctionBody2());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated C() {}", declaration);
-  }
-
-  void test_visitConstructorFieldInitializer_withoutThis() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.constructorFieldInitializer(
-            false, "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitConstructorFieldInitializer_withThis() {
-    _assertSource(
-        "this.a = b",
-        AstTestFactory.constructorFieldInitializer(
-            true, "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitConstructorName_named_prefix() {
-    _assertSource(
-        "p.C.n",
-        AstTestFactory.constructorName(
-            AstTestFactory.typeName4("p.C.n"), null));
-  }
-
-  void test_visitConstructorName_unnamed_noPrefix() {
-    _assertSource("C",
-        AstTestFactory.constructorName(AstTestFactory.typeName4("C"), null));
-  }
-
-  void test_visitConstructorName_unnamed_prefix() {
-    _assertSource(
-        "p.C",
-        AstTestFactory.constructorName(
-            AstTestFactory.typeName3(AstTestFactory.identifier5("p", "C")),
-            null));
-  }
-
-  void test_visitContinueStatement_label() {
-    _assertSource("continue l;", AstTestFactory.continueStatement("l"));
-  }
-
-  void test_visitContinueStatement_noLabel() {
-    _assertSource("continue;", AstTestFactory.continueStatement());
-  }
-
-  void test_visitDefaultFormalParameter_annotation() {
-    DefaultFormalParameter parameter = AstTestFactory.positionalFormalParameter(
-        AstTestFactory.simpleFormalParameter3("p"), AstTestFactory.integer(0));
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A p = 0', parameter);
-  }
-
-  void test_visitDefaultFormalParameter_named_noValue() {
-    _assertSource(
-        "p",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"), null));
-  }
-
-  void test_visitDefaultFormalParameter_named_value() {
-    _assertSource(
-        "p: 0",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitDefaultFormalParameter_positional_noValue() {
-    _assertSource(
-        "p",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"), null));
-  }
-
-  void test_visitDefaultFormalParameter_positional_value() {
-    _assertSource(
-        "p = 0",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter3("p"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitDoStatement() {
-    _assertSource(
-        "do {} while (c);",
-        AstTestFactory.doStatement(
-            AstTestFactory.block(), AstTestFactory.identifier3("c")));
-  }
-
-  void test_visitDoubleLiteral() {
-    _assertSource("4.2", AstTestFactory.doubleLiteral(4.2));
-  }
-
-  void test_visitEmptyFunctionBody() {
-    _assertSource(";", AstTestFactory.emptyFunctionBody());
-  }
-
-  void test_visitEmptyStatement() {
-    _assertSource(";", AstTestFactory.emptyStatement());
-  }
-
-  void test_visitEnumDeclaration_multiple() {
-    _assertSource("enum E {ONE, TWO}",
-        AstTestFactory.enumDeclaration2("E", ["ONE", "TWO"]));
-  }
-
-  void test_visitEnumDeclaration_single() {
-    _assertSource(
-        "enum E {ONE}", AstTestFactory.enumDeclaration2("E", ["ONE"]));
-  }
-
-  void test_visitExportDirective_combinator() {
-    _assertSource(
-        "export 'a.dart' show A;",
-        AstTestFactory.exportDirective2("a.dart", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitExportDirective_combinators() {
-    _assertSource(
-        "export 'a.dart' show A hide B;",
-        AstTestFactory.exportDirective2("a.dart", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitExportDirective_minimal() {
-    _assertSource(
-        "export 'a.dart';", AstTestFactory.exportDirective2("a.dart"));
-  }
-
-  void test_visitExportDirective_withMetadata() {
-    ExportDirective directive = AstTestFactory.exportDirective2("a.dart");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated export 'a.dart';", directive);
-  }
-
-  void test_visitExpressionFunctionBody_async() {
-    _assertSource(
-        "async => a;",
-        AstTestFactory.asyncExpressionFunctionBody(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExpressionFunctionBody_simple() {
-    _assertSource("=> a;",
-        AstTestFactory.expressionFunctionBody(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExpressionStatement() {
-    _assertSource("a;",
-        AstTestFactory.expressionStatement(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitExtendsClause() {
-    _assertSource("extends C",
-        AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitExtensionDeclaration_empty() {
-    _assertSource(
-        'extension E on C {}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E', extendedType: AstTestFactory.typeName4('C')));
-  }
-
-  void test_visitExtensionDeclaration_multipleMember() {
-    _assertSource(
-        'extension E on C {var a; var b;}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            extendedType: AstTestFactory.typeName4('C'),
-            members: [
-              AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
-                  [AstTestFactory.variableDeclaration('a')]),
-              AstTestFactory.fieldDeclaration2(
-                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
-            ]));
-  }
-
-  void test_visitExtensionDeclaration_parameters() {
-    _assertSource(
-        'extension E<T> on C {}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            typeParameters: AstTestFactory.typeParameterList(['T']),
-            extendedType: AstTestFactory.typeName4('C')));
-  }
-
-  void test_visitExtensionDeclaration_singleMember() {
-    _assertSource(
-        'extension E on C {var a;}',
-        AstTestFactory.extensionDeclaration(
-            name: 'E',
-            extendedType: AstTestFactory.typeName4('C'),
-            members: [
-              AstTestFactory.fieldDeclaration2(
-                  false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
-            ]));
-  }
-
-  void test_visitExtensionOverride_prefixedName_noTypeArgs() {
-    _assertSource(
-        'p.E(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier5('p', 'E'),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_prefixedName_typeArgs() {
-    _assertSource(
-        'p.E<A>(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier5('p', 'E'),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('A')]),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_simpleName_noTypeArgs() {
-    _assertSource(
-        'E(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier3('E'),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitExtensionOverride_simpleName_typeArgs() {
-    _assertSource(
-        'E<A>(o)',
-        AstTestFactory.extensionOverride(
-            extensionName: AstTestFactory.identifier3('E'),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('A')]),
-            argumentList: AstTestFactory.argumentList(
-                [AstTestFactory.identifier3('o')])));
-  }
-
-  void test_visitFieldDeclaration_instance() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.fieldDeclaration2(
-            false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitFieldDeclaration_static() {
-    _assertSource(
-        "static var a;",
-        AstTestFactory.fieldDeclaration2(
-            true, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitFieldDeclaration_withMetadata() {
-    FieldDeclaration declaration = AstTestFactory.fieldDeclaration2(
-        false, Keyword.VAR, [AstTestFactory.variableDeclaration("a")]);
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated var a;", declaration);
-  }
-
-  void test_visitFieldFormalParameter_annotation() {
-    FieldFormalParameter parameter = AstTestFactory.fieldFormalParameter2('f');
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A this.f', parameter);
-  }
-
-  void test_visitFieldFormalParameter_functionTyped() {
-    _assertSource(
-        "A this.a(b)",
-        AstTestFactory.fieldFormalParameter(
-            null,
-            AstTestFactory.typeName4("A"),
-            "a",
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter3("b")])));
-  }
-
-  void test_visitFieldFormalParameter_functionTyped_typeParameters() {
-    _assertSource(
-        "A this.a<E, F>(b)",
-        astFactory.fieldFormalParameter2(
-            type: AstTestFactory.typeName4('A'),
-            thisKeyword: TokenFactory.tokenFromKeyword(Keyword.THIS),
-            period: TokenFactory.tokenFromType(TokenType.PERIOD),
-            identifier: AstTestFactory.identifier3('a'),
-            typeParameters: AstTestFactory.typeParameterList(['E', 'F']),
-            parameters: AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter3("b")])));
-  }
-
-  void test_visitFieldFormalParameter_keyword() {
-    _assertSource("var this.a",
-        AstTestFactory.fieldFormalParameter(Keyword.VAR, null, "a"));
-  }
-
-  void test_visitFieldFormalParameter_keywordAndType() {
-    _assertSource(
-        "final A this.a",
-        AstTestFactory.fieldFormalParameter(
-            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitFieldFormalParameter_type() {
-    _assertSource(
-        "A this.a",
-        AstTestFactory.fieldFormalParameter(
-            null, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitFieldFormalParameter_type_covariant() {
-    FieldFormalParameterImpl expected = AstTestFactory.fieldFormalParameter(
-        null, AstTestFactory.typeName4("A"), "a");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant A this.a", expected);
-  }
-
-  void test_visitForEachPartsWithDeclaration() {
-    _assertSource(
-        'var e in l',
-        astFactory.forEachPartsWithDeclaration(
-            loopVariable: AstTestFactory.declaredIdentifier3('e'),
-            iterable: AstTestFactory.identifier3('l')));
-  }
-
-  void test_visitForEachPartsWithIdentifier() {
-    _assertSource(
-        'e in l',
-        astFactory.forEachPartsWithIdentifier(
-            identifier: AstTestFactory.identifier3('e'),
-            iterable: AstTestFactory.identifier3('l')));
-  }
-
-  void test_visitForEachStatement_declared() {
-    _assertSource(
-        "for (var a in b) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forEachPartsWithDeclaration(
-                AstTestFactory.declaredIdentifier3("a"),
-                AstTestFactory.identifier3("b")),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForEachStatement_variable() {
-    _assertSource(
-        "for (a in b) {}",
-        astFactory.forStatement(
-            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3("a"),
-                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
-                iterable: AstTestFactory.identifier3("b")),
-            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-            body: AstTestFactory.block()));
-  }
-
-  void test_visitForEachStatement_variable_await() {
-    _assertSource(
-        "await for (a in b) {}",
-        astFactory.forStatement(
-            awaitKeyword: TokenFactory.tokenFromString("await"),
-            forKeyword: TokenFactory.tokenFromKeyword(Keyword.FOR),
-            leftParenthesis: TokenFactory.tokenFromType(TokenType.OPEN_PAREN),
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3("a"),
-                inKeyword: TokenFactory.tokenFromKeyword(Keyword.IN),
-                iterable: AstTestFactory.identifier3("b")),
-            rightParenthesis: TokenFactory.tokenFromType(TokenType.CLOSE_PAREN),
-            body: AstTestFactory.block()));
-  }
-
-  void test_visitForElement() {
-    _assertSource(
-        'for (e in l) 0',
-        astFactory.forElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.integer(0)));
-  }
-
-  void test_visitFormalParameterList_empty() {
-    _assertSource("()", AstTestFactory.formalParameterList());
-  }
-
-  void test_visitFormalParameterList_n() {
-    _assertSource(
-        "({a: 0})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0))
-        ]));
-  }
-
-  void test_visitFormalParameterList_nn() {
-    _assertSource(
-        "({a: 0, b: 1})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_p() {
-    _assertSource(
-        "([a = 0])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0))
-        ]));
-  }
-
-  void test_visitFormalParameterList_pp() {
-    _assertSource(
-        "([a = 0, b = 1])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("a"),
-              AstTestFactory.integer(0)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_r() {
-    _assertSource(
-        "(a)",
-        AstTestFactory.formalParameterList(
-            [AstTestFactory.simpleFormalParameter3("a")]));
-  }
-
-  void test_visitFormalParameterList_rn() {
-    _assertSource(
-        "(a, {b: 1})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rnn() {
-    _assertSource(
-        "(a, {b: 1, c: 2})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(2))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rp() {
-    _assertSource(
-        "(a, [b = 1])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rpp() {
-    _assertSource(
-        "(a, [b = 1, c = 2])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("b"),
-              AstTestFactory.integer(1)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(2))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rr() {
-    _assertSource(
-        "(a, b)",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b")
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrn() {
-    _assertSource(
-        "(a, b, {c: 3})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrnn() {
-    _assertSource(
-        "(a, b, {c: 3, d: 4})",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3)),
-          AstTestFactory.namedFormalParameter(
-              AstTestFactory.simpleFormalParameter3("d"),
-              AstTestFactory.integer(4))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrp() {
-    _assertSource(
-        "(a, b, [c = 3])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3))
-        ]));
-  }
-
-  void test_visitFormalParameterList_rrpp() {
-    _assertSource(
-        "(a, b, [c = 3, d = 4])",
-        AstTestFactory.formalParameterList([
-          AstTestFactory.simpleFormalParameter3("a"),
-          AstTestFactory.simpleFormalParameter3("b"),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("c"),
-              AstTestFactory.integer(3)),
-          AstTestFactory.positionalFormalParameter(
-              AstTestFactory.simpleFormalParameter3("d"),
-              AstTestFactory.integer(4))
-        ]));
-  }
-
-  void test_visitForPartsWithDeclarations() {
-    _assertSource(
-        'var v; b; u',
-        astFactory.forPartsWithDeclarations(
-            variables: AstTestFactory.variableDeclarationList2(
-                Keyword.VAR, [AstTestFactory.variableDeclaration('v')]),
-            condition: AstTestFactory.identifier3('b'),
-            updaters: [AstTestFactory.identifier3('u')]));
-  }
-
-  void test_visitForPartsWithExpression() {
-    _assertSource(
-        'v; b; u',
-        astFactory.forPartsWithExpression(
-            initialization: AstTestFactory.identifier3('v'),
-            condition: AstTestFactory.identifier3('b'),
-            updaters: [AstTestFactory.identifier3('u')]));
-  }
-
-  void test_visitForStatement() {
-    _assertSource(
-        'for (e in l) s;',
-        astFactory.forStatement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.expressionStatement(
-                AstTestFactory.identifier3('s'))));
-  }
-
-  void test_visitForStatement_c() {
-    _assertSource(
-        "for (; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null, AstTestFactory.identifier3("c"), null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_cu() {
-    _assertSource(
-        "for (; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null,
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_e() {
-    _assertSource(
-        "for (e;;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"), null, null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ec() {
-    _assertSource(
-        "for (e; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                AstTestFactory.identifier3("c"),
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ecu() {
-    _assertSource(
-        "for (e; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_eu() {
-    _assertSource(
-        "for (e;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                AstTestFactory.identifier3("e"),
-                null,
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_i() {
-    _assertSource(
-        "for (var i;;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                null,
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_ic() {
-    _assertSource(
-        "for (var i; c;) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                AstTestFactory.identifier3("c"),
-                null),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_icu() {
-    _assertSource(
-        "for (var i; c; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                AstTestFactory.identifier3("c"),
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_iu() {
-    _assertSource(
-        "for (var i;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithDeclarations(
-                AstTestFactory.variableDeclarationList2(
-                    Keyword.VAR, [AstTestFactory.variableDeclaration("i")]),
-                null,
-                [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitForStatement_u() {
-    _assertSource(
-        "for (;; u) {}",
-        AstTestFactory.forStatement(
-            AstTestFactory.forPartsWithExpression(
-                null, null, [AstTestFactory.identifier3("u")]),
-            AstTestFactory.block()));
-  }
-
-  void test_visitFunctionDeclaration_external() {
-    FunctionDeclaration functionDeclaration =
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "f",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.emptyFunctionBody()));
-    functionDeclaration.externalKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.EXTERNAL);
-    _assertSource("external f();", functionDeclaration);
-  }
-
-  void test_visitFunctionDeclaration_getter() {
-    _assertSource(
-        "get f() {}",
-        AstTestFactory.functionDeclaration(
-            null, Keyword.GET, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_local_blockBody() {
-    FunctionDeclaration f = AstTestFactory.functionDeclaration(
-        null, null, "f", AstTestFactory.functionExpression());
-    FunctionDeclarationStatement fStatement =
-        astFactory.functionDeclarationStatement(f);
-    _assertSource(
-        "main() {f() {} 42;}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "main",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2([
-                  fStatement,
-                  AstTestFactory.expressionStatement(AstTestFactory.integer(42))
-                ]))));
-  }
-
-  void test_visitFunctionDeclaration_local_expressionBody() {
-    FunctionDeclaration f = AstTestFactory.functionDeclaration(
-        null,
-        null,
-        "f",
-        AstTestFactory.functionExpression2(AstTestFactory.formalParameterList(),
-            AstTestFactory.expressionFunctionBody(AstTestFactory.integer(1))));
-    FunctionDeclarationStatement fStatement =
-        astFactory.functionDeclarationStatement(f);
-    _assertSource(
-        "main() {f() => 1; 2;}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "main",
-            AstTestFactory.functionExpression2(
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2([
-                  fStatement,
-                  AstTestFactory.expressionStatement(AstTestFactory.integer(2))
-                ]))));
-  }
-
-  void test_visitFunctionDeclaration_normal() {
-    _assertSource(
-        "f() {}",
-        AstTestFactory.functionDeclaration(
-            null, null, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_setter() {
-    _assertSource(
-        "set f() {}",
-        AstTestFactory.functionDeclaration(
-            null, Keyword.SET, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionDeclaration_typeParameters() {
-    _assertSource(
-        "f<E>() {}",
-        AstTestFactory.functionDeclaration(
-            null,
-            null,
-            "f",
-            AstTestFactory.functionExpression3(
-                AstTestFactory.typeParameterList(['E']),
-                AstTestFactory.formalParameterList(),
-                AstTestFactory.blockFunctionBody2())));
-  }
-
-  void test_visitFunctionDeclaration_withMetadata() {
-    FunctionDeclaration declaration = AstTestFactory.functionDeclaration(
-        null, null, "f", AstTestFactory.functionExpression());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated f() {}", declaration);
-  }
-
-  void test_visitFunctionDeclarationStatement() {
-    _assertSource(
-        "f() {}",
-        AstTestFactory.functionDeclarationStatement(
-            null, null, "f", AstTestFactory.functionExpression()));
-  }
-
-  void test_visitFunctionExpression() {
-    _assertSource("() {}", AstTestFactory.functionExpression());
-  }
-
-  void test_visitFunctionExpression_typeParameters() {
-    _assertSource(
-        "<E>() {}",
-        AstTestFactory.functionExpression3(
-            AstTestFactory.typeParameterList(['E']),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitFunctionExpressionInvocation_minimal() {
-    _assertSource(
-        "f()",
-        AstTestFactory.functionExpressionInvocation(
-            AstTestFactory.identifier3("f")));
-  }
-
-  void test_visitFunctionExpressionInvocation_typeArguments() {
-    _assertSource(
-        "f<A>()",
-        AstTestFactory.functionExpressionInvocation2(
-            AstTestFactory.identifier3("f"),
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
-  }
-
-  void test_visitFunctionTypeAlias_generic() {
-    _assertSource(
-        "typedef A F<B>();",
-        AstTestFactory.typeAlias(
-            AstTestFactory.typeName4("A"),
-            "F",
-            AstTestFactory.typeParameterList(["B"]),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitFunctionTypeAlias_nonGeneric() {
-    _assertSource(
-        "typedef A F();",
-        AstTestFactory.typeAlias(AstTestFactory.typeName4("A"), "F", null,
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitFunctionTypeAlias_withMetadata() {
-    FunctionTypeAlias declaration = AstTestFactory.typeAlias(
-        AstTestFactory.typeName4("A"),
-        "F",
-        null,
-        AstTestFactory.formalParameterList());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated typedef A F();", declaration);
-  }
-
-  void test_visitFunctionTypedFormalParameter_annotation() {
-    FunctionTypedFormalParameter parameter =
-        AstTestFactory.functionTypedFormalParameter(null, "f");
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A f()', parameter);
-  }
-
-  void test_visitFunctionTypedFormalParameter_noType() {
-    _assertSource(
-        "f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
-  }
-
-  void test_visitFunctionTypedFormalParameter_nullable() {
-    _assertSource(
-        "T f()?",
-        astFactory.functionTypedFormalParameter2(
-            returnType: AstTestFactory.typeName4("T"),
-            identifier: AstTestFactory.identifier3('f'),
-            parameters: AstTestFactory.formalParameterList([]),
-            question: TokenFactory.tokenFromType(TokenType.QUESTION)));
-  }
-
-  void test_visitFunctionTypedFormalParameter_type() {
-    _assertSource(
-        "T f()",
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4("T"), "f"));
-  }
-
-  void test_visitFunctionTypedFormalParameter_type_covariant() {
-    FunctionTypedFormalParameterImpl expected =
-        AstTestFactory.functionTypedFormalParameter(
-            AstTestFactory.typeName4("T"), "f");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant T f()", expected);
-  }
-
-  void test_visitFunctionTypedFormalParameter_typeParameters() {
-    _assertSource(
-        "T f<E>()",
-        astFactory.functionTypedFormalParameter2(
-            returnType: AstTestFactory.typeName4("T"),
-            identifier: AstTestFactory.identifier3('f'),
-            typeParameters: AstTestFactory.typeParameterList(['E']),
-            parameters: AstTestFactory.formalParameterList([])));
-  }
-
-  void test_visitGenericFunctionType() {
-    _assertSource(
-        "int Function<T>(T)",
-        AstTestFactory.genericFunctionType(
-            AstTestFactory.typeName4("int"),
-            AstTestFactory.typeParameterList(['T']),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4("T"), null)
-            ])));
-  }
-
-  void test_visitGenericFunctionType_withQuestion() {
-    _assertSource(
-        "int Function<T>(T)?",
-        AstTestFactory.genericFunctionType(
-            AstTestFactory.typeName4("int"),
-            AstTestFactory.typeParameterList(['T']),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter4(
-                  AstTestFactory.typeName4("T"), null)
-            ]),
-            question: true));
-  }
-
-  void test_visitGenericTypeAlias() {
-    _assertSource(
-        "typedef X<S> = S Function<T>(T)",
-        AstTestFactory.genericTypeAlias(
-            'X',
-            AstTestFactory.typeParameterList(['S']),
-            AstTestFactory.genericFunctionType(
-                AstTestFactory.typeName4("S"),
-                AstTestFactory.typeParameterList(['T']),
-                AstTestFactory.formalParameterList([
-                  AstTestFactory.simpleFormalParameter4(
-                      AstTestFactory.typeName4("T"), null)
-                ]))));
-  }
-
-  void test_visitIfElement_else() {
-    _assertSource(
-        'if (b) 1 else 0',
-        astFactory.ifElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1),
-            elseElement: AstTestFactory.integer(0)));
-  }
-
-  void test_visitIfElement_then() {
-    _assertSource(
-        'if (b) 1',
-        astFactory.ifElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1)));
-  }
-
-  void test_visitIfStatement_withElse() {
-    _assertSource(
-        "if (c) {} else {}",
-        AstTestFactory.ifStatement2(AstTestFactory.identifier3("c"),
-            AstTestFactory.block(), AstTestFactory.block()));
-  }
-
-  void test_visitIfStatement_withoutElse() {
-    _assertSource(
-        "if (c) {}",
-        AstTestFactory.ifStatement(
-            AstTestFactory.identifier3("c"), AstTestFactory.block()));
-  }
-
-  void test_visitImplementsClause_multiple() {
-    _assertSource(
-        "implements A, B",
-        AstTestFactory.implementsClause(
-            [AstTestFactory.typeName4("A"), AstTestFactory.typeName4("B")]));
-  }
-
-  void test_visitImplementsClause_single() {
-    _assertSource("implements A",
-        AstTestFactory.implementsClause([AstTestFactory.typeName4("A")]));
-  }
-
-  void test_visitImportDirective_combinator() {
-    _assertSource(
-        "import 'a.dart' show A;",
-        AstTestFactory.importDirective3("a.dart", null, [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitImportDirective_combinators() {
-    _assertSource(
-        "import 'a.dart' show A hide B;",
-        AstTestFactory.importDirective3("a.dart", null, [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitImportDirective_deferred() {
-    _assertSource("import 'a.dart' deferred as p;",
-        AstTestFactory.importDirective2("a.dart", true, "p"));
-  }
-
-  void test_visitImportDirective_minimal() {
-    _assertSource(
-        "import 'a.dart';", AstTestFactory.importDirective3("a.dart", null));
-  }
-
-  void test_visitImportDirective_prefix() {
-    _assertSource("import 'a.dart' as p;",
-        AstTestFactory.importDirective3("a.dart", "p"));
-  }
-
-  void test_visitImportDirective_prefix_combinator() {
-    _assertSource(
-        "import 'a.dart' as p show A;",
-        AstTestFactory.importDirective3("a.dart", "p", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")])
-        ]));
-  }
-
-  void test_visitImportDirective_prefix_combinators() {
-    _assertSource(
-        "import 'a.dart' as p show A hide B;",
-        AstTestFactory.importDirective3("a.dart", "p", [
-          AstTestFactory.showCombinator([AstTestFactory.identifier3("A")]),
-          AstTestFactory.hideCombinator([AstTestFactory.identifier3("B")])
-        ]));
-  }
-
-  void test_visitImportDirective_withMetadata() {
-    ImportDirective directive = AstTestFactory.importDirective3("a.dart", null);
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated import 'a.dart';", directive);
-  }
-
-  void test_visitImportHideCombinator_multiple() {
-    _assertSource(
-        "hide a, b",
-        AstTestFactory.hideCombinator([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitImportHideCombinator_single() {
-    _assertSource("hide a",
-        AstTestFactory.hideCombinator([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitImportShowCombinator_multiple() {
-    _assertSource(
-        "show a, b",
-        AstTestFactory.showCombinator([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b")
-        ]));
-  }
-
-  void test_visitImportShowCombinator_single() {
-    _assertSource("show a",
-        AstTestFactory.showCombinator([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitIndexExpression() {
-    _assertSource(
-        "a[i]",
-        AstTestFactory.indexExpression(
-            AstTestFactory.identifier3("a"), AstTestFactory.identifier3("i")));
-  }
-
-  void test_visitInstanceCreationExpression_const() {
-    _assertSource(
-        "const C()",
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.CONST, AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitInstanceCreationExpression_named() {
-    _assertSource(
-        "new C.c()",
-        AstTestFactory.instanceCreationExpression3(
-            Keyword.NEW, AstTestFactory.typeName4("C"), "c"));
-  }
-
-  void test_visitInstanceCreationExpression_unnamed() {
-    _assertSource(
-        "new C()",
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.NEW, AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitIntegerLiteral() {
-    _assertSource("42", AstTestFactory.integer(42));
-  }
-
-  void test_visitInterpolationExpression_expression() {
-    _assertSource(
-        "\${a}",
-        AstTestFactory.interpolationExpression(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitInterpolationExpression_identifier() {
-    _assertSource("\$a", AstTestFactory.interpolationExpression2("a"));
-  }
-
-  void test_visitInterpolationString() {
-    _assertSource("'x", AstTestFactory.interpolationString("'x", "x"));
-  }
-
-  void test_visitIsExpression_negated() {
-    _assertSource(
-        "a is! C",
-        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), true,
-            AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitIsExpression_normal() {
-    _assertSource(
-        "a is C",
-        AstTestFactory.isExpression(AstTestFactory.identifier3("a"), false,
-            AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitLabel() {
-    _assertSource("a:", AstTestFactory.label2("a"));
-  }
-
-  void test_visitLabeledStatement_multiple() {
-    _assertSource(
-        "a: b: return;",
-        AstTestFactory.labeledStatement(
-            [AstTestFactory.label2("a"), AstTestFactory.label2("b")],
-            AstTestFactory.returnStatement()));
-  }
-
-  void test_visitLabeledStatement_single() {
-    _assertSource(
-        "a: return;",
-        AstTestFactory.labeledStatement(
-            [AstTestFactory.label2("a")], AstTestFactory.returnStatement()));
-  }
-
-  void test_visitLibraryDirective() {
-    _assertSource("library l;", AstTestFactory.libraryDirective2("l"));
-  }
-
-  void test_visitLibraryDirective_withMetadata() {
-    LibraryDirective directive = AstTestFactory.libraryDirective2("l");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated library l;", directive);
-  }
-
-  void test_visitLibraryIdentifier_multiple() {
-    _assertSource(
-        "a.b.c",
-        AstTestFactory.libraryIdentifier([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b"),
-          AstTestFactory.identifier3("c")
-        ]));
-  }
-
-  void test_visitLibraryIdentifier_single() {
-    _assertSource("a",
-        AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("a")]));
-  }
-
-  void test_visitListLiteral_complex() {
-    _assertSource(
-        '<int>[0, for (e in l) 0, if (b) 1, ...[0]]',
-        astFactory.listLiteral(
-            null,
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [
-              AstTestFactory.integer(0),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('e'),
-                      iterable: AstTestFactory.identifier3('l')),
-                  body: AstTestFactory.integer(0)),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('b'),
-                  thenElement: AstTestFactory.integer(1)),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.listLiteral(
-                      null, null, null, [AstTestFactory.integer(0)], null))
-            ],
-            null));
-  }
-
-  void test_visitListLiteral_const() {
-    _assertSource("const []", AstTestFactory.listLiteral2(Keyword.CONST, null));
-  }
-
-  void test_visitListLiteral_empty() {
-    _assertSource("[]", AstTestFactory.listLiteral());
-  }
-
-  void test_visitListLiteral_nonEmpty() {
-    _assertSource(
-        "[a, b, c]",
-        AstTestFactory.listLiteral([
-          AstTestFactory.identifier3("a"),
-          AstTestFactory.identifier3("b"),
-          AstTestFactory.identifier3("c")
-        ]));
-  }
-
-  void test_visitListLiteral_withConst_withoutTypeArgs() {
-    _assertSource(
-        'const [0]',
-        astFactory.listLiteral(TokenFactory.tokenFromKeyword(Keyword.CONST),
-            null, null, [AstTestFactory.integer(0)], null));
-  }
-
-  void test_visitListLiteral_withConst_withTypeArgs() {
-    _assertSource(
-        'const <int>[0]',
-        astFactory.listLiteral(
-            TokenFactory.tokenFromKeyword(Keyword.CONST),
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [AstTestFactory.integer(0)],
-            null));
-  }
-
-  void test_visitListLiteral_withoutConst_withoutTypeArgs() {
-    _assertSource(
-        '[0]',
-        astFactory.listLiteral(
-            null, null, null, [AstTestFactory.integer(0)], null));
-  }
-
-  void test_visitListLiteral_withoutConst_withTypeArgs() {
-    _assertSource(
-        '<int>[0]',
-        astFactory.listLiteral(
-            null,
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('int')]),
-            null,
-            [AstTestFactory.integer(0)],
-            null));
-  }
-
-  void test_visitMapLiteral_const() {
-    _assertSource(
-        "const {}", AstTestFactory.setOrMapLiteral(Keyword.CONST, null));
-  }
-
-  void test_visitMapLiteral_empty() {
-    _assertSource("{}", AstTestFactory.setOrMapLiteral(null, null));
-  }
-
-  void test_visitMapLiteral_nonEmpty() {
-    _assertSource(
-        "{'a' : a, 'b' : b, 'c' : c}",
-        AstTestFactory.setOrMapLiteral(null, null, [
-          AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("a")),
-          AstTestFactory.mapLiteralEntry("b", AstTestFactory.identifier3("b")),
-          AstTestFactory.mapLiteralEntry("c", AstTestFactory.identifier3("c"))
-        ]));
-  }
-
-  void test_visitMapLiteralEntry() {
-    _assertSource("'a' : b",
-        AstTestFactory.mapLiteralEntry("a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitMethodDeclaration_external() {
-    _assertSource(
-        "external m();",
-        AstTestFactory.methodDeclaration(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitMethodDeclaration_external_returnType() {
-    _assertSource(
-        "external T m();",
-        AstTestFactory.methodDeclaration(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList()));
-  }
-
-  void test_visitMethodDeclaration_getter() {
-    _assertSource(
-        "get m {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            Keyword.GET,
-            null,
-            AstTestFactory.identifier3("m"),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_getter_returnType() {
-    _assertSource(
-        "T get m {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            Keyword.GET,
-            null,
-            AstTestFactory.identifier3("m"),
-            null,
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_getter_seturnType() {
-    _assertSource(
-        "T set m(var v) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            Keyword.SET,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_minimal() {
-    _assertSource(
-        "m() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_multipleParameters() {
-    _assertSource(
-        "m(var a, var b) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList([
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-              AstTestFactory.simpleFormalParameter(Keyword.VAR, "b")
-            ]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_operator() {
-    _assertSource(
-        "operator +() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            null,
-            Keyword.OPERATOR,
-            AstTestFactory.identifier3("+"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_operator_returnType() {
-    _assertSource(
-        "T operator +() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            Keyword.OPERATOR,
-            AstTestFactory.identifier3("+"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_returnType() {
-    _assertSource(
-        "T m() {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_setter() {
-    _assertSource(
-        "set m(var v) {}",
-        AstTestFactory.methodDeclaration2(
-            null,
-            null,
-            Keyword.SET,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(
-                [AstTestFactory.simpleFormalParameter(Keyword.VAR, "v")]),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_static() {
-    _assertSource(
-        "static m() {}",
-        AstTestFactory.methodDeclaration2(
-            Keyword.STATIC,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_static_returnType() {
-    _assertSource(
-        "static T m() {}",
-        AstTestFactory.methodDeclaration2(
-            Keyword.STATIC,
-            AstTestFactory.typeName4("T"),
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_typeParameters() {
-    _assertSource(
-        "m<E>() {}",
-        AstTestFactory.methodDeclaration3(
-            null,
-            null,
-            null,
-            null,
-            AstTestFactory.identifier3("m"),
-            AstTestFactory.typeParameterList(['E']),
-            AstTestFactory.formalParameterList(),
-            AstTestFactory.blockFunctionBody2()));
-  }
-
-  void test_visitMethodDeclaration_withMetadata() {
-    MethodDeclaration declaration = AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.blockFunctionBody2());
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated m() {}", declaration);
-  }
-
-  void test_visitMethodInvocation_conditional() {
-    _assertSource(
-        "t?.m()",
-        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m",
-            null, TokenType.QUESTION_PERIOD));
-  }
-
-  void test_visitMethodInvocation_noTarget() {
-    _assertSource("m()", AstTestFactory.methodInvocation2("m"));
-  }
-
-  void test_visitMethodInvocation_target() {
-    _assertSource("t.m()",
-        AstTestFactory.methodInvocation(AstTestFactory.identifier3("t"), "m"));
-  }
-
-  void test_visitMethodInvocation_typeArguments() {
-    _assertSource(
-        "m<A>()",
-        AstTestFactory.methodInvocation3(null, "m",
-            AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')])));
-  }
-
-  void test_visitNamedExpression() {
-    _assertSource("a: b",
-        AstTestFactory.namedExpression2("a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitNamedFormalParameter() {
-    _assertSource(
-        "var a: 0",
-        AstTestFactory.namedFormalParameter(
-            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitNativeClause() {
-    _assertSource("native 'code'", AstTestFactory.nativeClause("code"));
-  }
-
-  void test_visitNativeFunctionBody() {
-    _assertSource("native 'str';", AstTestFactory.nativeFunctionBody("str"));
-  }
-
-  void test_visitNullLiteral() {
-    _assertSource("null", AstTestFactory.nullLiteral());
-  }
-
-  void test_visitParenthesizedExpression() {
-    _assertSource(
-        "(a)",
-        AstTestFactory.parenthesizedExpression(
-            AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitPartDirective() {
-    _assertSource("part 'a.dart';", AstTestFactory.partDirective2("a.dart"));
-  }
-
-  void test_visitPartDirective_withMetadata() {
-    PartDirective directive = AstTestFactory.partDirective2("a.dart");
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated part 'a.dart';", directive);
-  }
-
-  void test_visitPartOfDirective() {
-    _assertSource(
-        "part of l;",
-        AstTestFactory.partOfDirective(
-            AstTestFactory.libraryIdentifier2(["l"])));
-  }
-
-  void test_visitPartOfDirective_withMetadata() {
-    PartOfDirective directive = AstTestFactory.partOfDirective(
-        AstTestFactory.libraryIdentifier2(["l"]));
-    directive.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated part of l;", directive);
-  }
-
-  void test_visitPositionalFormalParameter() {
-    _assertSource(
-        "var a = 0",
-        AstTestFactory.positionalFormalParameter(
-            AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"),
-            AstTestFactory.integer(0)));
-  }
-
-  void test_visitPostfixExpression() {
-    _assertSource(
-        "a++",
-        AstTestFactory.postfixExpression(
-            AstTestFactory.identifier3("a"), TokenType.PLUS_PLUS));
-  }
-
-  void test_visitPrefixedIdentifier() {
-    _assertSource("a.b", AstTestFactory.identifier5("a", "b"));
-  }
-
-  void test_visitPrefixExpression() {
-    _assertSource(
-        "-a",
-        AstTestFactory.prefixExpression(
-            TokenType.MINUS, AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitPropertyAccess() {
-    _assertSource("a.b",
-        AstTestFactory.propertyAccess2(AstTestFactory.identifier3("a"), "b"));
-  }
-
-  void test_visitPropertyAccess_conditional() {
-    _assertSource(
-        "a?.b",
-        AstTestFactory.propertyAccess2(
-            AstTestFactory.identifier3("a"), "b", TokenType.QUESTION_PERIOD));
-  }
-
-  void test_visitRedirectingConstructorInvocation_named() {
-    _assertSource(
-        "this.c()", AstTestFactory.redirectingConstructorInvocation2("c"));
-  }
-
-  void test_visitRedirectingConstructorInvocation_unnamed() {
-    _assertSource("this()", AstTestFactory.redirectingConstructorInvocation());
-  }
-
-  void test_visitRethrowExpression() {
-    _assertSource("rethrow", AstTestFactory.rethrowExpression());
-  }
-
-  void test_visitReturnStatement_expression() {
-    _assertSource("return a;",
-        AstTestFactory.returnStatement2(AstTestFactory.identifier3("a")));
-  }
-
-  void test_visitReturnStatement_noExpression() {
-    _assertSource("return;", AstTestFactory.returnStatement());
-  }
-
-  void test_visitScriptTag() {
-    String scriptTag = "!#/bin/dart.exe";
-    _assertSource(scriptTag, AstTestFactory.scriptTag(scriptTag));
-  }
-
-  void test_visitSetOrMapLiteral_map_complex() {
-    _assertSource(
-        "<String, String>{'a' : 'b', for (c in d) 'e' : 'f', if (g) 'h' : 'i', ...{'j' : 'k'}}",
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [
-              AstTestFactory.mapLiteralEntry3('a', 'b'),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('c'),
-                      iterable: AstTestFactory.identifier3('d')),
-                  body: AstTestFactory.mapLiteralEntry3('e', 'f')),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('g'),
-                  thenElement: AstTestFactory.mapLiteralEntry3('h', 'i')),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.setOrMapLiteral(
-                      elements: [AstTestFactory.mapLiteralEntry3('j', 'k')]))
-            ]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withConst_withoutTypeArgs() {
-    _assertSource(
-        "const {'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withConst_withTypeArgs() {
-    _assertSource(
-        "const <String, String>{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withoutConst_withoutTypeArgs() {
-    _assertSource(
-        "{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_map_withoutConst_withTypeArgs() {
-    _assertSource(
-        "<String, String>{'a' : 'b'}",
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList([
-              AstTestFactory.typeName4('String'),
-              AstTestFactory.typeName4('String')
-            ]),
-            elements: [AstTestFactory.mapLiteralEntry3('a', 'b')]));
-  }
-
-  void test_visitSetOrMapLiteral_set_complex() {
-    _assertSource(
-        '<int>{0, for (e in l) 0, if (b) 1, ...[0]}',
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [
-              AstTestFactory.integer(0),
-              astFactory.forElement(
-                  forLoopParts: astFactory.forEachPartsWithIdentifier(
-                      identifier: AstTestFactory.identifier3('e'),
-                      iterable: AstTestFactory.identifier3('l')),
-                  body: AstTestFactory.integer(0)),
-              astFactory.ifElement(
-                  condition: AstTestFactory.identifier3('b'),
-                  thenElement: AstTestFactory.integer(1)),
-              astFactory.spreadElement(
-                  spreadOperator: TokenFactory.tokenFromType(
-                      TokenType.PERIOD_PERIOD_PERIOD),
-                  expression: astFactory.listLiteral(
-                      null, null, null, [AstTestFactory.integer(0)], null))
-            ]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withConst_withoutTypeArgs() {
-    _assertSource(
-        'const {0}',
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withConst_withTypeArgs() {
-    _assertSource(
-        'const <int>{0}',
-        astFactory.setOrMapLiteral(
-            constKeyword: TokenFactory.tokenFromKeyword(Keyword.CONST),
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withoutConst_withoutTypeArgs() {
-    _assertSource('{0}',
-        astFactory.setOrMapLiteral(elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSetOrMapLiteral_set_withoutConst_withTypeArgs() {
-    _assertSource(
-        '<int>{0}',
-        astFactory.setOrMapLiteral(
-            typeArguments: AstTestFactory.typeArgumentList(
-                [AstTestFactory.typeName4('int')]),
-            elements: [AstTestFactory.integer(0)]));
-  }
-
-  void test_visitSimpleFormalParameter_annotation() {
-    SimpleFormalParameter parameter =
-        AstTestFactory.simpleFormalParameter3('x');
-    parameter.metadata
-        .add(AstTestFactory.annotation(AstTestFactory.identifier3("A")));
-    _assertSource('@A x', parameter);
-  }
-
-  void test_visitSimpleFormalParameter_keyword() {
-    _assertSource(
-        "var a", AstTestFactory.simpleFormalParameter(Keyword.VAR, "a"));
-  }
-
-  void test_visitSimpleFormalParameter_keyword_type() {
-    _assertSource(
-        "final A a",
-        AstTestFactory.simpleFormalParameter2(
-            Keyword.FINAL, AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitSimpleFormalParameter_type() {
-    _assertSource(
-        "A a",
-        AstTestFactory.simpleFormalParameter4(
-            AstTestFactory.typeName4("A"), "a"));
-  }
-
-  void test_visitSimpleFormalParameter_type_covariant() {
-    SimpleFormalParameterImpl expected = AstTestFactory.simpleFormalParameter4(
-        AstTestFactory.typeName4("A"), "a");
-    expected.covariantKeyword =
-        TokenFactory.tokenFromKeyword(Keyword.COVARIANT);
-    _assertSource("covariant A a", expected);
-  }
-
-  void test_visitSimpleIdentifier() {
-    _assertSource("a", AstTestFactory.identifier3("a"));
-  }
-
-  void test_visitSimpleStringLiteral() {
-    _assertSource("'a'", AstTestFactory.string2("a"));
-  }
-
-  void test_visitSpreadElement_nonNullable() {
-    _assertSource(
-        '...[0]',
-        astFactory.spreadElement(
-            spreadOperator:
-                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
-            expression: astFactory.listLiteral(
-                null, null, null, [AstTestFactory.integer(0)], null)));
-  }
-
-  @failingTest
-  void test_visitSpreadElement_nullable() {
-    // TODO(brianwilkerson) Replace the token type below when there is one for
-    //  '...?'.
-    _assertSource(
-        '...?[0]',
-        astFactory.spreadElement(
-            spreadOperator:
-                TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD_PERIOD),
-            expression: astFactory.listLiteral(
-                null, null, null, [AstTestFactory.integer(0)], null)));
-  }
-
-  void test_visitStringInterpolation() {
-    _assertSource(
-        "'a\${e}b'",
-        AstTestFactory.string([
-          AstTestFactory.interpolationString("'a", "a"),
-          AstTestFactory.interpolationExpression(
-              AstTestFactory.identifier3("e")),
-          AstTestFactory.interpolationString("b'", "b")
-        ]));
-  }
-
-  void test_visitSuperConstructorInvocation() {
-    _assertSource("super()", AstTestFactory.superConstructorInvocation());
-  }
-
-  void test_visitSuperConstructorInvocation_named() {
-    _assertSource("super.c()", AstTestFactory.superConstructorInvocation2("c"));
-  }
-
-  void test_visitSuperExpression() {
-    _assertSource("super", AstTestFactory.superExpression());
-  }
-
-  void test_visitSwitchCase_multipleLabels() {
-    _assertSource(
-        "l1: l2: case a: {}",
-        AstTestFactory.switchCase2(
-            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
-            AstTestFactory.identifier3("a"),
-            [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_multipleStatements() {
-    _assertSource(
-        "case a: {} {}",
-        AstTestFactory.switchCase(AstTestFactory.identifier3("a"),
-            [AstTestFactory.block(), AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_noLabels() {
-    _assertSource(
-        "case a: {}",
-        AstTestFactory.switchCase(
-            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchCase_singleLabel() {
-    _assertSource(
-        "l1: case a: {}",
-        AstTestFactory.switchCase2([AstTestFactory.label2("l1")],
-            AstTestFactory.identifier3("a"), [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_multipleLabels() {
-    _assertSource(
-        "l1: l2: default: {}",
-        AstTestFactory.switchDefault(
-            [AstTestFactory.label2("l1"), AstTestFactory.label2("l2")],
-            [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_multipleStatements() {
-    _assertSource(
-        "default: {} {}",
-        AstTestFactory.switchDefault2(
-            [AstTestFactory.block(), AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_noLabels() {
-    _assertSource(
-        "default: {}", AstTestFactory.switchDefault2([AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchDefault_singleLabel() {
-    _assertSource(
-        "l1: default: {}",
-        AstTestFactory.switchDefault(
-            [AstTestFactory.label2("l1")], [AstTestFactory.block()]));
-  }
-
-  void test_visitSwitchStatement() {
-    _assertSource(
-        "switch (a) {case 'b': {} default: {}}",
-        AstTestFactory.switchStatement(AstTestFactory.identifier3("a"), [
-          AstTestFactory.switchCase(
-              AstTestFactory.string2("b"), [AstTestFactory.block()]),
-          AstTestFactory.switchDefault2([AstTestFactory.block()])
-        ]));
-  }
-
-  void test_visitSymbolLiteral_multiple() {
-    _assertSource("#a.b.c", AstTestFactory.symbolLiteral(["a", "b", "c"]));
-  }
-
-  void test_visitSymbolLiteral_single() {
-    _assertSource("#a", AstTestFactory.symbolLiteral(["a"]));
-  }
-
-  void test_visitThisExpression() {
-    _assertSource("this", AstTestFactory.thisExpression());
-  }
-
-  void test_visitThrowStatement() {
-    _assertSource("throw e",
-        AstTestFactory.throwExpression2(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitTopLevelVariableDeclaration_multiple() {
-    _assertSource(
-        "var a;",
-        AstTestFactory.topLevelVariableDeclaration2(
-            Keyword.VAR, [AstTestFactory.variableDeclaration("a")]));
-  }
-
-  void test_visitTopLevelVariableDeclaration_single() {
-    _assertSource(
-        "var a, b;",
-        AstTestFactory.topLevelVariableDeclaration2(Keyword.VAR, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitTryStatement_catch() {
-    _assertSource(
-        "try {} on E {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))]));
-  }
-
-  void test_visitTryStatement_catches() {
-    _assertSource(
-        "try {} on E {} on F {}",
-        AstTestFactory.tryStatement2(AstTestFactory.block(), [
-          AstTestFactory.catchClause3(AstTestFactory.typeName4("E")),
-          AstTestFactory.catchClause3(AstTestFactory.typeName4("F"))
-        ]));
-  }
-
-  void test_visitTryStatement_catchFinally() {
-    _assertSource(
-        "try {} on E {} finally {}",
-        AstTestFactory.tryStatement3(
-            AstTestFactory.block(),
-            [AstTestFactory.catchClause3(AstTestFactory.typeName4("E"))],
-            AstTestFactory.block()));
-  }
-
-  void test_visitTryStatement_finally() {
-    _assertSource(
-        "try {} finally {}",
-        AstTestFactory.tryStatement(
-            AstTestFactory.block(), AstTestFactory.block()));
-  }
-
-  void test_visitTypeArgumentList_multiple() {
-    _assertSource(
-        "<E, F>",
-        AstTestFactory.typeArgumentList(
-            [AstTestFactory.typeName4("E"), AstTestFactory.typeName4("F")]));
-  }
-
-  void test_visitTypeArgumentList_single() {
-    _assertSource("<E>",
-        AstTestFactory.typeArgumentList([AstTestFactory.typeName4("E")]));
-  }
-
-  void test_visitTypeName_multipleArgs() {
-    _assertSource(
-        "C<D, E>",
-        AstTestFactory.typeName4("C",
-            [AstTestFactory.typeName4("D"), AstTestFactory.typeName4("E")]));
-  }
-
-  void test_visitTypeName_nestedArg() {
-    _assertSource(
-        "C<D<E>>",
-        AstTestFactory.typeName4("C", [
-          AstTestFactory.typeName4("D", [AstTestFactory.typeName4("E")])
-        ]));
-  }
-
-  void test_visitTypeName_noArgs() {
-    _assertSource("C", AstTestFactory.typeName4("C"));
-  }
-
-  void test_visitTypeName_singleArg() {
-    _assertSource(
-        "C<D>", AstTestFactory.typeName4("C", [AstTestFactory.typeName4("D")]));
-  }
-
-  void test_visitTypeParameter_withExtends() {
-    _assertSource("E extends C",
-        AstTestFactory.typeParameter2("E", AstTestFactory.typeName4("C")));
-  }
-
-  void test_visitTypeParameter_withMetadata() {
-    TypeParameter parameter = AstTestFactory.typeParameter("E");
-    parameter.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated E", parameter);
-  }
-
-  void test_visitTypeParameter_withoutExtends() {
-    _assertSource("E", AstTestFactory.typeParameter("E"));
-  }
-
-  void test_visitTypeParameterList_multiple() {
-    _assertSource("<E, F>", AstTestFactory.typeParameterList(["E", "F"]));
-  }
-
-  void test_visitTypeParameterList_single() {
-    _assertSource("<E>", AstTestFactory.typeParameterList(["E"]));
-  }
-
-  void test_visitVariableDeclaration_initialized() {
-    _assertSource(
-        "a = b",
-        AstTestFactory.variableDeclaration2(
-            "a", AstTestFactory.identifier3("b")));
-  }
-
-  void test_visitVariableDeclaration_uninitialized() {
-    _assertSource("a", AstTestFactory.variableDeclaration("a"));
-  }
-
-  void test_visitVariableDeclaration_withMetadata() {
-    VariableDeclaration declaration = AstTestFactory.variableDeclaration("a");
-    declaration.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated a", declaration);
-  }
-
-  void test_visitVariableDeclarationList_const_type() {
-    _assertSource(
-        "const C a, b",
-        AstTestFactory.variableDeclarationList(
-            Keyword.CONST, AstTestFactory.typeName4("C"), [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_final_noType() {
-    _assertSource(
-        "final a, b",
-        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_final_withMetadata() {
-    VariableDeclarationList declarationList =
-        AstTestFactory.variableDeclarationList2(Keyword.FINAL, [
-      AstTestFactory.variableDeclaration("a"),
-      AstTestFactory.variableDeclaration("b")
-    ]);
-    declarationList.metadata.add(
-        AstTestFactory.annotation(AstTestFactory.identifier3("deprecated")));
-    _assertSource("@deprecated final a, b", declarationList);
-  }
-
-  void test_visitVariableDeclarationList_type() {
-    _assertSource(
-        "C a, b",
-        AstTestFactory.variableDeclarationList(
-            null, AstTestFactory.typeName4("C"), [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationList_var() {
-    _assertSource(
-        "var a, b",
-        AstTestFactory.variableDeclarationList2(Keyword.VAR, [
-          AstTestFactory.variableDeclaration("a"),
-          AstTestFactory.variableDeclaration("b")
-        ]));
-  }
-
-  void test_visitVariableDeclarationStatement() {
-    _assertSource(
-        "C c;",
-        AstTestFactory.variableDeclarationStatement(
-            null,
-            AstTestFactory.typeName4("C"),
-            [AstTestFactory.variableDeclaration("c")]));
-  }
-
-  void test_visitWhileStatement() {
-    _assertSource(
-        "while (c) {}",
-        AstTestFactory.whileStatement(
-            AstTestFactory.identifier3("c"), AstTestFactory.block()));
-  }
-
-  void test_visitWithClause_multiple() {
-    _assertSource(
-        "with A, B, C",
-        AstTestFactory.withClause([
-          AstTestFactory.typeName4("A"),
-          AstTestFactory.typeName4("B"),
-          AstTestFactory.typeName4("C")
-        ]));
-  }
-
-  void test_visitWithClause_single() {
-    _assertSource(
-        "with A", AstTestFactory.withClause([AstTestFactory.typeName4("A")]));
-  }
-
-  void test_visitYieldStatement() {
-    _assertSource("yield e;",
-        AstTestFactory.yieldStatement(AstTestFactory.identifier3("e")));
-  }
-
-  void test_visitYieldStatement_each() {
-    _assertSource("yield* e;",
-        AstTestFactory.yieldEachStatement(AstTestFactory.identifier3("e")));
-  }
-
-  /**
-   * Assert that a `ToSourceVisitor` will produce the [expectedSource] when
-   * visiting the given [node].
-   */
-  void _assertSource(String expectedSource, AstNode node) {
-    PrintStringWriter writer = new PrintStringWriter();
-    node.accept(new ToSourceVisitor(writer));
-    expect(writer.toString(), expectedSource);
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 2abcaba..47b7e88 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -116,6 +116,25 @@
     expect(result.toDoubleValue(), 3.0);
   }
 
+  test_visitPropertyAccess_fromExtension() async {
+    await resolveTestCode('''
+extension ExtObject on Object {
+  int get length => 4;
+}
+
+class B {
+  final l;
+  const B(Object o) : l = o.length;
+}
+
+const b = B('');
+''');
+    _evaluateConstant('b', errorCodes: [
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+      CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION
+    ]);
+  }
+
   test_visitSimpleIdentifier_className() async {
     await resolveTestCode('''
 const a = C;
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 3db01ca..9ef159d 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -1129,13 +1129,6 @@
 
 @reflectiveTest
 class FunctionTypeImplTest extends AbstractTypeTest {
-  void test_creation() {
-    expect(
-        new FunctionTypeImpl(
-            new FunctionElementImpl.forNode(AstTestFactory.identifier3("f"))),
-        isNotNull);
-  }
-
   void test_equality_recursive() {
     var s = ElementFactory.genericTypeAliasElement('s');
     var t = ElementFactory.genericTypeAliasElement('t');
@@ -1153,13 +1146,6 @@
     );
   }
 
-  void test_getElement() {
-    FunctionElementImpl typeElement =
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("f"));
-    FunctionTypeImpl type = new FunctionTypeImpl(typeElement);
-    expect(type.element, typeElement);
-  }
-
   void test_getNamedParameterTypes_namedParameters() {
     TestTypeProvider typeProvider = new TestTypeProvider();
     FunctionElement element = ElementFactory.functionElementWithParameters(
@@ -1264,446 +1250,6 @@
     expect(types[1], DynamicTypeImpl.instance);
   }
 
-  void test_getReturnType() {
-    DartType expectedReturnType = VoidTypeImpl.instance;
-    FunctionElementImpl functionElement =
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("f"));
-    functionElement.returnType = expectedReturnType;
-    FunctionTypeImpl type = new FunctionTypeImpl(functionElement);
-    DartType returnType = type.returnType;
-    expect(returnType, expectedReturnType);
-  }
-
-  void test_getTypeArguments() {
-    FunctionTypeImpl type = new FunctionTypeImpl(
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("f")));
-    List<DartType> types = type.typeArguments;
-    expect(types, hasLength(0));
-  }
-
-  void test_hashCode_element() {
-    FunctionTypeImpl type = new FunctionTypeImpl(
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("f")));
-    type.hashCode;
-  }
-
-  void test_hashCode_noElement() {
-    FunctionTypeImpl type = new FunctionTypeImpl(null);
-    type.hashCode;
-  }
-
-  void test_hashCode_recursive() {
-    var s = ElementFactory.genericTypeAliasElement('s');
-    var t = ElementFactory.genericTypeAliasElement('t');
-    s.function.returnType = functionTypeAliasType(t);
-    t.function.returnType = functionTypeAliasType(s);
-    // We don't care what the hash code is.  We just need its computation to
-    // terminate.
-    expect(functionTypeAliasType(t).hashCode, new TypeMatcher<int>());
-  }
-
-  void test_isAssignableTo_normalAndPositionalArgs() {
-    // ([a]) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[a]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isFalse);
-    // assignable iff subtype
-    // ignore: deprecated_member_use_from_same_package
-    expect(t.isAssignableTo(s), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(s.isAssignableTo(t), isFalse);
-  }
-
-  void test_isSubtypeOf_baseCase_classFunction() {
-    // () -> void <: Function
-    ClassElementImpl functionElement = ElementFactory.classElement2("Function");
-    InterfaceTypeImpl functionType =
-        new _FunctionTypeImplTest_isSubtypeOf_baseCase_classFunction(
-            functionElement);
-    FunctionType f = ElementFactory.functionElement("f").type;
-    expect(f.isSubtypeOf(functionType), isTrue);
-  }
-
-  void test_isSubtypeOf_baseCase_notFunctionType() {
-    // class C
-    // ! () -> void <: C
-    FunctionType f = ElementFactory.functionElement("f").type;
-    InterfaceType t = interfaceType(class_(name: 'C'));
-    expect(f.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_baseCase_null() {
-    // ! () -> void <: null
-    FunctionType f = ElementFactory.functionElement("f").type;
-    expect(f.isSubtypeOf(null), isFalse);
-  }
-
-  void test_isSubtypeOf_baseCase_self() {
-    // () -> void <: () -> void
-    FunctionType f = ElementFactory.functionElement("f").type;
-    expect(f.isSubtypeOf(f), isTrue);
-  }
-
-  void test_isSubtypeOf_namedParameters_isAssignable() {
-    // B extends A
-    // ({name: A}) -> void <: ({name: B}) -> void
-    // ({name: B}) -> void <: ({name: A}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["name"], <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["name"], <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isTrue);
-  }
-
-  void test_isSubtypeOf_namedParameters_isNotAssignable() {
-    // ! ({name: A}) -> void <: ({name: B}) -> void
-    FunctionType t = ElementFactory.functionElement4("t", null, null,
-        <String>["name"], <ClassElement>[class_(name: 'A')]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s",
-        null,
-        null,
-        <String>["name"],
-        <ClassElement>[ElementFactory.classElement2("B")]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_namedParameters_namesDifferent() {
-    // B extends A
-    // void t({A name}) {}
-    // void s({A diff}) {}
-    // ! t <: s
-    // ! s <: t
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["name"], <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["diff"], <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_namedParameters_orderOfParams() {
-    // B extends A
-    // ({A: A, B: B}) -> void <: ({B: B, A: A}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["A", "B"], <ClassElement>[a, b]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["B", "A"], <ClassElement>[b, a]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-  }
-
-  void test_isSubtypeOf_namedParameters_orderOfParams2() {
-    // B extends A
-    // ! ({B: B}) -> void <: ({B: B, A: A}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["B"], <ClassElement>[b]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["B", "A"], <ClassElement>[b, a]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_namedParameters_orderOfParams3() {
-    // B extends A
-    // ({A: A, B: B}) -> void <: ({A: A}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["A", "B"], <ClassElement>[a, b]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["B"], <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-  }
-
-  void test_isSubtypeOf_namedParameters_sHasMoreParams() {
-    // B extends A
-    // ! ({name: A}) -> void <: ({name: B, name2: B}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["name"], <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["name", "name2"], <ClassElement>[b, b]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_namedParameters_tHasMoreParams() {
-    // B extends A
-    // ({name: A, name2: A}) -> void <: ({name: B}) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t = ElementFactory.functionElement4(
-        "t", null, null, <String>["name", "name2"], <ClassElement>[a, a]).type;
-    FunctionType s = ElementFactory.functionElement4(
-        "s", null, null, <String>["name"], <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-  }
-
-  void test_isSubtypeOf_normalAndPositionalArgs_1() {
-    // ([a]) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[a]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_normalAndPositionalArgs_2() {
-    // (a, [a]) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t = ElementFactory.functionElement6(
-        "t", <ClassElement>[a], <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[a]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_normalAndPositionalArgs_3() {
-    // ([a]) -> void <: () -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement("s").type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_normalAndPositionalArgs_4() {
-    // (a, b, [c, d, e]) -> void <: (a, b, c, [d]) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement2("B");
-    ClassElement c = ElementFactory.classElement2("C");
-    ClassElement d = ElementFactory.classElement2("D");
-    ClassElement e = ElementFactory.classElement2("E");
-    FunctionType t = ElementFactory.functionElement6(
-        "t", <ClassElement>[a, b], <ClassElement>[c, d, e]).type;
-    FunctionType s = ElementFactory.functionElement6(
-        "s", <ClassElement>[a, b, c], <ClassElement>[d]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_normalParameters_isAssignable() {
-    // B extends A
-    // (a) -> void <: (b) -> void
-    // (b) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement5("t", <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isTrue);
-  }
-
-  void test_isSubtypeOf_normalParameters_isNotAssignable() {
-    // ! (a) -> void <: (b) -> void
-    FunctionType t =
-        ElementFactory.functionElement5("t", <ClassElement>[class_(name: 'A')])
-            .type;
-    FunctionType s = ElementFactory.functionElement5(
-        "s", <ClassElement>[ElementFactory.classElement2("B")]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_normalParameters_sHasMoreParams() {
-    // B extends A
-    // ! (a) -> void <: (b, b) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement5("t", <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[b, b]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_normalParameters_tHasMoreParams() {
-    // B extends A
-    // ! (a, a) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement5("t", <ClassElement>[a, a]).type;
-    FunctionType s =
-        ElementFactory.functionElement5("s", <ClassElement>[b]).type;
-    // note, this is a different assertion from the other "tHasMoreParams"
-    // tests, this is intentional as it is a difference of the "normal
-    // parameters"
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_Object() {
-    // () -> void <: Object
-    FunctionType f = ElementFactory.functionElement("f").type;
-    InterfaceType t = typeProvider.objectType;
-    expect(f.isSubtypeOf(t), isTrue);
-  }
-
-  void test_isSubtypeOf_positionalParameters_isAssignable() {
-    // B extends A
-    // ([a]) -> void <: ([b]) -> void
-    // ([b]) -> void <: ([a]) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement6("s", null, <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isTrue);
-  }
-
-  void test_isSubtypeOf_positionalParameters_isNotAssignable() {
-    // ! ([a]) -> void <: ([b]) -> void
-    FunctionType t = ElementFactory.functionElement6(
-        "t", null, <ClassElement>[class_(name: 'A')]).type;
-    FunctionType s = ElementFactory.functionElement6(
-        "s", null, <ClassElement>[ElementFactory.classElement2("B")]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_positionalParameters_sHasMoreParams() {
-    // B extends A
-    // ! ([a]) -> void <: ([b, b]) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s =
-        ElementFactory.functionElement6("s", null, <ClassElement>[b, b]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_positionalParameters_tHasMoreParams() {
-    // B extends A
-    // ([a, a]) -> void <: ([b]) -> void
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a, a]).type;
-    FunctionType s =
-        ElementFactory.functionElement6("s", null, <ClassElement>[b]).type;
-    expect(t.isSubtypeOf(s), isTrue);
-  }
-
-  void test_isSubtypeOf_returnType_sIsVoid() {
-    // () -> void <: void
-    FunctionType t = ElementFactory.functionElement("t").type;
-    FunctionType s = ElementFactory.functionElement("s").type;
-    // function s has the implicit return type of void, we assert it here
-    expect(VoidTypeImpl.instance == s.returnType, isTrue);
-    expect(t.isSubtypeOf(s), isTrue);
-  }
-
-  void test_isSubtypeOf_returnType_tAssignableToS() {
-    // B extends A
-    // () -> A <: () -> B
-    // () -> B <: () -> A
-    ClassElement a = class_(name: 'A');
-    ClassElement b = ElementFactory.classElement('B', interfaceType(a));
-    FunctionType t =
-        ElementFactory.functionElement2("t", interfaceType(a)).type;
-    FunctionType s =
-        ElementFactory.functionElement2("s", interfaceType(b)).type;
-    expect(t.isSubtypeOf(s), isTrue);
-    expect(s.isSubtypeOf(t), isTrue);
-  }
-
-  void test_isSubtypeOf_returnType_tNotAssignableToS() {
-    // ! () -> A <: () -> B
-    FunctionType t = ElementFactory.functionElement2(
-            "t", interfaceType(ElementFactory.classElement2('A')))
-        .type;
-    FunctionType s =
-        ElementFactory.functionElement2("s", interfaceType(class_(name: 'B')))
-            .type;
-    expect(t.isSubtypeOf(s), isFalse);
-  }
-
-  void test_isSubtypeOf_typeParameters_matchesBounds() {
-    TestTypeProvider provider = new TestTypeProvider();
-    InterfaceType boolType = provider.boolType;
-    InterfaceType stringType = provider.stringType;
-    TypeParameterElementImpl parameterB =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("B"));
-    parameterB.bound = boolType;
-    TypeParameterTypeImpl typeB = new TypeParameterTypeImpl(parameterB);
-    TypeParameterElementImpl parameterS =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("S"));
-    parameterS.bound = stringType;
-    TypeParameterTypeImpl typeS = new TypeParameterTypeImpl(parameterS);
-    FunctionElementImpl functionAliasElement =
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("func"));
-    functionAliasElement.parameters = <ParameterElement>[
-      ElementFactory.requiredParameter2("a", typeB),
-      ElementFactory.positionalParameter2("b", typeS)
-    ];
-    functionAliasElement.returnType = stringType;
-    FunctionTypeImpl functionAliasType =
-        new FunctionTypeImpl(functionAliasElement);
-    functionAliasElement.type = functionAliasType;
-    FunctionElementImpl functionElement =
-        new FunctionElementImpl.forNode(AstTestFactory.identifier3("f"));
-    functionElement.parameters = <ParameterElement>[
-      ElementFactory.requiredParameter2("c", boolType),
-      ElementFactory.positionalParameter2("d", stringType)
-    ];
-    functionElement.returnType = provider.dynamicType;
-    FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement);
-    functionElement.type = functionType;
-    expect(functionType.isAssignableTo(functionAliasType), isTrue);
-  }
-
-  void test_isSubtypeOf_wrongFunctionType_normal_named() {
-    // ! (a) -> void <: ({name: A}) -> void
-    // ! ({name: A}) -> void <: (a) -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t =
-        ElementFactory.functionElement5("t", <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement7(
-        "s", null, <String>["name"], <ClassElement>[a]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_isSubtypeOf_wrongFunctionType_optional_named() {
-    // ! ([a]) -> void <: ({name: A}) -> void
-    // ! ({name: A}) -> void <: ([a]) -> void
-    ClassElement a = class_(name: 'A');
-    FunctionType t =
-        ElementFactory.functionElement6("t", null, <ClassElement>[a]).type;
-    FunctionType s = ElementFactory.functionElement7(
-        "s", null, <String>["name"], <ClassElement>[a]).type;
-    expect(t.isSubtypeOf(s), isFalse);
-    expect(s.isSubtypeOf(t), isFalse);
-  }
-
-  void test_newPrune_non_typedef() {
-    // No pruning needs to be done for function types that aren't associated
-    // with typedefs because those types can't be directly referred to by the
-    // user (and hence can't participate in circularities).
-    FunctionElementImpl f = ElementFactory.functionElement('f');
-    FunctionTypeImpl type = f.type;
-    expect(type.newPrune, []);
-  }
-
   void test_resolveToBound() {
     FunctionElementImpl f = ElementFactory.functionElement('f');
     FunctionTypeImpl type = f.type;
@@ -1712,6 +1258,7 @@
     expect(type.resolveToBound(null), same(type));
   }
 
+  @deprecated
   void test_substitute2_equal() {
     ClassElementImpl definingClass = ElementFactory.classElement2("C", ["E"]);
     TypeParameterType parameterType =
@@ -1726,7 +1273,7 @@
     ];
     functionElement.returnType = parameterType;
     definingClass.methods = <MethodElement>[functionElement];
-    FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement);
+    FunctionTypeImpl functionType = functionElement.type;
     InterfaceTypeImpl argumentType = new InterfaceTypeImpl(
         new ClassElementImpl.forNode(AstTestFactory.identifier3("D")));
     FunctionType result = functionType
@@ -1743,6 +1290,7 @@
     expect(namedParameters[namedParameterName], argumentType);
   }
 
+  @deprecated
   void test_substitute2_notEqual() {
     DartType returnType = new InterfaceTypeImpl(
         new ClassElementImpl.forNode(AstTestFactory.identifier3("R")));
@@ -1761,7 +1309,7 @@
       ElementFactory.namedParameter2(namedParameterName, namedParameterType)
     ];
     functionElement.returnType = returnType;
-    FunctionTypeImpl functionType = new FunctionTypeImpl(functionElement);
+    FunctionTypeImpl functionType = functionElement.type;
     InterfaceTypeImpl argumentType = new InterfaceTypeImpl(
         new ClassElementImpl.forNode(AstTestFactory.identifier3("D")));
     TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(
@@ -1803,149 +1351,6 @@
       'dynamic Function()',
     );
   }
-
-  void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
-    //
-    // class C<S> {
-    //   Object m<T>() {
-    //     U f<U>() => null;
-    //   }
-    // }
-    //
-    ClassElementImpl classElement =
-        ElementFactory.classElement('C', null, ['S']);
-    MethodElementImpl method = new MethodElementImpl('m', 0);
-    method.enclosingElement = classElement;
-    method.returnType = ElementFactory.objectType;
-    method.typeParameters = ElementFactory.typeParameters(['T']);
-    method.type = new FunctionTypeImpl(method);
-    FunctionElementImpl function = ElementFactory.functionElement('f');
-    function.enclosingElement = method;
-    function.typeParameters = ElementFactory.typeParameters(['U']);
-    function.returnType = typeParameterType(function.typeParameters[0]);
-    function.type = new FunctionTypeImpl(function);
-
-    List<TypeParameterElement> inheritedParameters = <TypeParameterElement>[];
-    inheritedParameters.addAll(method.typeParameters);
-    inheritedParameters.addAll(classElement.typeParameters);
-    expect(function.type.typeArguments,
-        unorderedEquals(_toTypes(inheritedParameters)));
-    expect(function.type.typeFormals, unorderedEquals(function.typeParameters));
-    expect(function.type.typeParameters, unorderedEquals(inheritedParameters));
-  }
-
-  void test_typeParameters_genericMethod_genericClass() {
-    //
-    // class C<S> {
-    //   Object m<T>() => null;
-    // }
-    //
-    ClassElementImpl classElement =
-        ElementFactory.classElement('C', null, ['S']);
-    MethodElementImpl method = new MethodElementImpl('m', 0);
-    method.enclosingElement = classElement;
-    method.returnType = ElementFactory.objectType;
-    method.typeParameters = ElementFactory.typeParameters(['T']);
-    method.type = new FunctionTypeImpl(method);
-
-    expect(method.type.typeArguments,
-        unorderedEquals(_toTypes(classElement.typeParameters)));
-    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
-    expect(method.type.typeParameters,
-        unorderedEquals(classElement.typeParameters));
-  }
-
-  void test_typeParameters_genericMethod_simpleClass() {
-    //
-    // class C<S> {
-    //   Object m<T>() => null;
-    // }
-    //
-    ClassElementImpl classElement = class_(name: 'C');
-    MethodElementImpl method = new MethodElementImpl('m', 0);
-    method.enclosingElement = classElement;
-    method.returnType = ElementFactory.objectType;
-    method.typeParameters = ElementFactory.typeParameters(['T']);
-    method.type = new FunctionTypeImpl(method);
-
-    expect(method.type.typeArguments,
-        unorderedEquals(_toTypes(classElement.typeParameters)));
-    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
-    expect(method.type.typeParameters,
-        unorderedEquals(classElement.typeParameters));
-  }
-
-  void test_typeParameters_genericTopLevelFunction() {
-    //
-    // Object f<T>() => null;
-    //
-    FunctionElementImpl function = ElementFactory.functionElement('f');
-    function.returnType = ElementFactory.objectType;
-    function.typeParameters = ElementFactory.typeParameters(['T']);
-    function.type = new FunctionTypeImpl(function);
-
-    expect(function.type.typeArguments, isEmpty);
-    expect(function.type.typeFormals, unorderedEquals(function.typeParameters));
-    expect(function.type.typeParameters, isEmpty);
-  }
-
-  void test_typeParameters_simpleMethod_genericClass() {
-    //
-    // class C<S> {
-    //   Object m<T>() => null;
-    // }
-    //
-    ClassElementImpl classElement =
-        ElementFactory.classElement('C', null, ['S']);
-    MethodElementImpl method = new MethodElementImpl('m', 0);
-    method.enclosingElement = classElement;
-    method.typeParameters = ElementFactory.typeParameters(['T']);
-    method.returnType = ElementFactory.objectType;
-    method.type = new FunctionTypeImpl(method);
-
-    expect(method.type.typeArguments,
-        unorderedEquals(_toTypes(classElement.typeParameters)));
-    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
-    expect(method.type.typeParameters,
-        unorderedEquals(classElement.typeParameters));
-  }
-
-  void test_typeParameters_simpleMethod_simpleClass() {
-    //
-    // class C<S> {
-    //   Object m<T>() => null;
-    // }
-    //
-    ClassElementImpl classElement = class_(name: 'C');
-    MethodElementImpl method = new MethodElementImpl('m', 0);
-    method.enclosingElement = classElement;
-    method.typeParameters = ElementFactory.typeParameters(['T']);
-    method.returnType = ElementFactory.objectType;
-    method.type = new FunctionTypeImpl(method);
-
-    expect(method.type.typeArguments,
-        unorderedEquals(_toTypes(classElement.typeParameters)));
-    expect(method.type.typeFormals, unorderedEquals(method.typeParameters));
-    expect(method.type.typeParameters,
-        unorderedEquals(classElement.typeParameters));
-  }
-
-  void test_withTypeArguments() {
-    ClassElementImpl enclosingClass = ElementFactory.classElement2("C", ["E"]);
-    MethodElementImpl methodElement =
-        new MethodElementImpl.forNode(AstTestFactory.identifier3("m"));
-    enclosingClass.methods = <MethodElement>[methodElement];
-    FunctionTypeImpl type = new FunctionTypeImpl(methodElement);
-    DartType expectedType = typeParameterType(enclosingClass.typeParameters[0]);
-    List<DartType> arguments = type.typeArguments;
-    expect(arguments, hasLength(1));
-    expect(arguments[0], expectedType);
-  }
-
-  Iterable<DartType> _toTypes(List<TypeParameterElement> typeParameters) {
-    return typeParameters
-        .map((TypeParameterElement element) => typeParameterType(element));
-  }
 }
 
 @reflectiveTest
@@ -2082,7 +1487,6 @@
     PropertyAccessorElementImpl getterG =
         ElementFactory.getterElement(getterName, false, typeAE);
     A.accessors = <PropertyAccessorElement>[getterG];
-    getterG.type = new FunctionTypeImpl(getterG);
     //
     // A<I>
     //
@@ -2181,44 +1585,16 @@
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeB, []);
     classA.methods = <MethodElement>[methodM];
-    methodM.type = new FunctionTypeImpl(methodM);
     //
     // A<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
-    typeAI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeAI =
+        new InterfaceTypeImpl.explicit(classA, <DartType>[typeI]);
     MethodElement method = typeAI.getMethod(methodName);
     expect(method, isNotNull);
     FunctionType methodType = method.type;
-    expect(methodType.typeParameters, isEmpty);
-    expect(methodType.typeArguments, [same(typeI)]);
-  }
-
-  void test_getMethod_parameterized_flushCached_whenVersionChanges() {
-    //
-    // class A<E> { E m(E p) {} }
-    //
-    var E = typeParameter('E');
-    var A = class_(name: 'A', typeParameters: [E]);
-    DartType typeE = typeParameterType(E);
-    String methodName = "m";
-    MethodElementImpl methodM =
-        ElementFactory.methodElement(methodName, typeE, [typeE]);
-    A.methods = <MethodElement>[methodM];
-    methodM.type = new FunctionTypeImpl(methodM);
-    //
-    // A<I>
-    //
-    InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(A);
-    typeAI.typeArguments = <DartType>[typeI];
-    // Methods list is cached.
-    MethodElement method = typeAI.methods.single;
-    expect(typeAI.methods.single, same(method));
-    // Methods list is flushed on version change.
-    A.version++;
-    expect(typeAI.methods.single, isNot(same(method)));
+    expect(methodType.typeArguments, isEmpty);
   }
 
   void test_getMethod_parameterized_usesTypeParameter() {
@@ -2232,18 +1608,16 @@
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeE, [typeE]);
     A.methods = <MethodElement>[methodM];
-    methodM.type = new FunctionTypeImpl(methodM);
     //
     // A<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(A);
-    typeAI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeAI =
+        new InterfaceTypeImpl.explicit(A, <DartType>[typeI]);
     MethodElement method = typeAI.getMethod(methodName);
     expect(method, isNotNull);
     FunctionType methodType = method.type;
-    expect(methodType.typeParameters, isEmpty);
-    expect(methodType.typeArguments, [same(typeI)]);
+    expect(methodType.typeArguments, isEmpty);
     expect(methodType.returnType, same(typeI));
     List<DartType> parameterTypes = methodType.normalParameterTypes;
     expect(parameterTypes, hasLength(1));
@@ -2316,8 +1690,8 @@
     // B<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(B);
-    typeBI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeBI =
+        new InterfaceTypeImpl.explicit(B, <DartType>[typeI]);
     List<InterfaceType> interfaces = typeBI.mixins;
     expect(interfaces, hasLength(1));
     InterfaceType result = interfaces[0];
@@ -2349,13 +1723,12 @@
     PropertyAccessorElementImpl setterS =
         ElementFactory.setterElement(setterName, false, typeE);
     A.accessors = <PropertyAccessorElement>[setterS];
-    setterS.type = new FunctionTypeImpl(setterS);
     //
     // A<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(A);
-    typeAI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeAI =
+        new InterfaceTypeImpl.explicit(A, <DartType>[typeI]);
     PropertyAccessorElement setter = typeAI.getSetter(setterName);
     expect(setter, isNotNull);
     FunctionType setterType = setter.type;
@@ -2406,8 +1779,8 @@
     // B<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(classB);
-    typeBI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeBI =
+        new InterfaceTypeImpl.explicit(classB, <DartType>[typeI]);
     InterfaceType superclass = typeBI.superclass;
     expect(superclass.element, same(A));
     expect(superclass.typeArguments[0], same(typeI));
@@ -2424,507 +1797,6 @@
     expect(0 == typeA.hashCode, isFalse);
   }
 
-  void test_isAssignableTo_typeVariables() {
-    //
-    // class A<E> {}
-    // class B<F, G> {
-    //   A<F> af;
-    //   f (A<G> ag) {
-    //     af = ag;
-    //   }
-    // }
-    //
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classB = ElementFactory.classElement2("B", ["F", "G"]);
-    InterfaceTypeImpl typeAF = new InterfaceTypeImpl(classA);
-    typeAF.typeArguments = <DartType>[
-      typeParameterType(classB.typeParameters[0])
-    ];
-    InterfaceTypeImpl typeAG = new InterfaceTypeImpl(classA);
-    typeAG.typeArguments = <DartType>[
-      typeParameterType(classB.typeParameters[1])
-    ];
-    expect(typeAG.isAssignableTo(typeAF), isFalse);
-  }
-
-  void test_isAssignableTo_void() {
-    InterfaceTypeImpl intType = _typeProvider.intType;
-    expect(VoidTypeImpl.instance.isAssignableTo(intType), isFalse);
-  }
-
-  void test_isDirectSupertypeOf_extends() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isDirectSupertypeOf(typeB), isTrue);
-  }
-
-  void test_isDirectSupertypeOf_false() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB = ElementFactory.classElement2("B");
-    ClassElement classC =
-        ElementFactory.classElement("C", interfaceType(classB));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isDirectSupertypeOf(typeC), isFalse);
-  }
-
-  void test_isDirectSupertypeOf_implements() {
-    var classA = class_(name: 'A');
-    var classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    classB.interfaces = <InterfaceType>[typeA];
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isDirectSupertypeOf(typeB), isTrue);
-  }
-
-  void test_isDirectSupertypeOf_with() {
-    var classA = class_(name: 'A');
-    var classB = ElementFactory.classElement2("B");
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    classB.mixins = <InterfaceType>[typeA];
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isDirectSupertypeOf(typeB), isTrue);
-  }
-
-  void test_isMoreSpecificThan_bottom() {
-    DartType type = interfaceType(ElementFactory.classElement2('A'));
-    expect(BottomTypeImpl.instance.isMoreSpecificThan(type), isTrue);
-  }
-
-  void test_isMoreSpecificThan_covariance() {
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classI = ElementFactory.classElement2("I");
-    ClassElement classJ =
-        ElementFactory.classElement("J", interfaceType(classI));
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
-    InterfaceTypeImpl typeAJ = new InterfaceTypeImpl(classA);
-    typeAI.typeArguments = <DartType>[interfaceType(classI)];
-    typeAJ.typeArguments = <DartType>[interfaceType(classJ)];
-    expect(typeAJ.isMoreSpecificThan(typeAI), isTrue);
-    expect(typeAI.isMoreSpecificThan(typeAJ), isFalse);
-  }
-
-  void test_isMoreSpecificThan_directSupertype() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeB.isMoreSpecificThan(typeA), isTrue);
-    // the opposite test tests a different branch in isMoreSpecificThan()
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isMoreSpecificThan(typeB), isFalse);
-  }
-
-  void test_isMoreSpecificThan_dynamic() {
-    InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
-    // ignore: deprecated_member_use_from_same_package
-    expect(type.isMoreSpecificThan(DynamicTypeImpl.instance), isTrue);
-  }
-
-  void test_isMoreSpecificThan_generic() {
-    ClassElement A = class_(
-      name: 'A',
-      typeParameters: [typeParameter('E')],
-    );
-    ClassElement B = class_(name: 'B');
-
-    var AofDynamic = interfaceType(
-      A,
-      typeArguments: [dynamicType],
-    );
-    var AofB = interfaceType(
-      A,
-      typeArguments: [interfaceType(B)],
-    );
-
-    // ignore: deprecated_member_use_from_same_package
-    expect(AofDynamic.isMoreSpecificThan(AofB), isFalse);
-    // ignore: deprecated_member_use_from_same_package
-    expect(AofB.isMoreSpecificThan(AofDynamic), isTrue);
-  }
-
-  void test_isMoreSpecificThan_self() {
-    InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
-    // ignore: deprecated_member_use_from_same_package
-    expect(type.isMoreSpecificThan(type), isTrue);
-  }
-
-  void test_isMoreSpecificThan_transitive_interface() {
-    //
-    //  class A {}
-    //  class B extends A {}
-    //  class C implements B {}
-    //
-    var classA = class_(name: 'A');
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    classC.interfaces = <InterfaceType>[interfaceType(classB)];
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isMoreSpecificThan(typeA), isTrue);
-  }
-
-  void test_isMoreSpecificThan_transitive_mixin() {
-    //
-    //  class A {}
-    //  class B extends A {}
-    //  class C with B {}
-    //
-    var classA = class_(name: 'A');
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    classC.mixins = <InterfaceType>[interfaceType(classB)];
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isMoreSpecificThan(typeA), isTrue);
-  }
-
-  void test_isMoreSpecificThan_transitive_recursive() {
-    //
-    //  class A extends B {}
-    //  class B extends A {}
-    //  class C {}
-    //
-    var classA = class_(name: 'A');
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    classA.supertype = interfaceType(classB);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isMoreSpecificThan(typeC), isFalse);
-  }
-
-  void test_isMoreSpecificThan_transitive_superclass() {
-    //
-    //  class A {}
-    //  class B extends A {}
-    //  class C extends B {}
-    //
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    ClassElement classC =
-        ElementFactory.classElement("C", interfaceType(classB));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isMoreSpecificThan(typeA), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeParameterType() {
-    //
-    // class A<E> {}
-    //
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeA = interfaceType(classA);
-    TypeParameterType parameterType =
-        typeParameterType(classA.typeParameters[0]);
-    DartType objectType = _typeProvider.objectType;
-    // ignore: deprecated_member_use_from_same_package
-    expect(parameterType.isMoreSpecificThan(objectType), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(parameterType.isMoreSpecificThan(typeA), isFalse);
-  }
-
-  void test_isMoreSpecificThan_typeParameterType_withBound() {
-    //
-    // class A {}
-    // class B<E extends A> {}
-    //
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    var classB = ElementFactory.classElement2("B");
-    TypeParameterElementImpl parameterEA =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    TypeParameterType parameterAEType = new TypeParameterTypeImpl(parameterEA);
-    parameterEA.bound = typeA;
-    classB.typeParameters = <TypeParameterElementImpl>[parameterEA];
-    // ignore: deprecated_member_use_from_same_package
-    expect(parameterAEType.isMoreSpecificThan(typeA), isTrue);
-  }
-
-  void test_isSubtypeOf_directSubtype() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    expect(typeB.isSubtypeOf(typeA), isTrue);
-    expect(typeA.isSubtypeOf(typeB), isFalse);
-  }
-
-  void test_isSubtypeOf_dynamic() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    DartType dynamicType = DynamicTypeImpl.instance;
-    expect(dynamicType.isSubtypeOf(typeA), isTrue);
-    expect(typeA.isSubtypeOf(dynamicType), isTrue);
-  }
-
-  void test_isSubtypeOf_function() {
-    //
-    // void f(String s) {}
-    // class A {
-    //   void call(String s) {}
-    // }
-    //
-    InterfaceType stringType = _typeProvider.stringType;
-    var classA = class_(name: 'A');
-    classA.methods = <MethodElement>[
-      ElementFactory.methodElement("call", VoidTypeImpl.instance, [stringType])
-    ];
-    FunctionType functionType =
-        ElementFactory.functionElement5("f", <ClassElement>[stringType.element])
-            .type;
-    expect(interfaceType(classA).isSubtypeOf(functionType), isTrue);
-  }
-
-  void test_isSubtypeOf_generic() {
-    ClassElement A = ElementFactory.classElement2("A", ["E"]);
-    ClassElement B = ElementFactory.classElement2("B");
-    DartType dynamicType = DynamicTypeImpl.instance;
-    InterfaceType typeAOfDynamic =
-        interfaceType(A, typeArguments: [dynamicType]);
-    InterfaceType typeAOfB =
-        interfaceType(A, typeArguments: [interfaceType(B)]);
-    expect(typeAOfDynamic.isSubtypeOf(typeAOfB), isTrue);
-    expect(typeAOfB.isSubtypeOf(typeAOfDynamic), isTrue);
-  }
-
-  void test_isSubtypeOf_interface() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    InterfaceType typeC = interfaceType(classC);
-    classC.interfaces = <InterfaceType>[typeB];
-    expect(typeC.isSubtypeOf(typeB), isTrue);
-    expect(typeC.isSubtypeOf(typeObject), isTrue);
-    expect(typeC.isSubtypeOf(typeA), isTrue);
-    expect(typeA.isSubtypeOf(typeC), isFalse);
-  }
-
-  void test_isSubtypeOf_mixins() {
-    //
-    // class A {}
-    // class B extends A {}
-    // class C with B {}
-    //
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    InterfaceType typeC = interfaceType(classC);
-    classC.mixins = <InterfaceType>[typeB];
-    expect(typeC.isSubtypeOf(typeB), isTrue);
-    expect(typeC.isSubtypeOf(typeObject), isTrue);
-    expect(typeC.isSubtypeOf(typeA), isTrue);
-    expect(typeA.isSubtypeOf(typeC), isFalse);
-  }
-
-  void test_isSubtypeOf_object() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeObject = classA.supertype;
-    expect(typeA.isSubtypeOf(typeObject), isTrue);
-    expect(typeObject.isSubtypeOf(typeA), isFalse);
-  }
-
-  void test_isSubtypeOf_self() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    expect(typeA.isSubtypeOf(typeA), isTrue);
-  }
-
-  void test_isSubtypeOf_transitive_recursive() {
-    //
-    //  class A extends B {}
-    //  class B extends A {}
-    //  class C {}
-    //
-    var classA = class_(name: 'A');
-    ClassElementImpl classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    classA.supertype = interfaceType(classB);
-    expect(typeA.isSubtypeOf(typeC), isFalse);
-  }
-
-  void test_isSubtypeOf_transitive_superclass() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    ClassElement classC =
-        ElementFactory.classElement("C", interfaceType(classB));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    expect(typeC.isSubtypeOf(typeA), isTrue);
-    expect(typeA.isSubtypeOf(typeC), isFalse);
-  }
-
-  void test_isSubtypeOf_typeArguments() {
-    DartType dynamicType = DynamicTypeImpl.instance;
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    ClassElement classI = ElementFactory.classElement2("I");
-    ClassElement classJ =
-        ElementFactory.classElement("J", interfaceType(classI));
-    ClassElement classK = ElementFactory.classElement2("K");
-    InterfaceType typeA_dynamic =
-        interfaceType(classA, typeArguments: [dynamicType]);
-    InterfaceTypeImpl typeAI = new InterfaceTypeImpl(classA);
-    InterfaceTypeImpl typeAJ = new InterfaceTypeImpl(classA);
-    InterfaceTypeImpl typeAK = new InterfaceTypeImpl(classA);
-    typeAI.typeArguments = <DartType>[interfaceType(classI)];
-    typeAJ.typeArguments = <DartType>[interfaceType(classJ)];
-    typeAK.typeArguments = <DartType>[interfaceType(classK)];
-    // A<J> <: A<I> since J <: I
-    expect(typeAJ.isSubtypeOf(typeAI), isTrue);
-    expect(typeAI.isSubtypeOf(typeAJ), isFalse);
-    // A<I> <: A<I> since I <: I
-    expect(typeAI.isSubtypeOf(typeAI), isTrue);
-    // A <: A<I> and A <: A<J>
-    expect(typeA_dynamic.isSubtypeOf(typeAI), isTrue);
-    expect(typeA_dynamic.isSubtypeOf(typeAJ), isTrue);
-    // A<I> <: A and A<J> <: A
-    expect(typeAI.isSubtypeOf(typeA_dynamic), isTrue);
-    expect(typeAJ.isSubtypeOf(typeA_dynamic), isTrue);
-    // A<I> !<: A<K> and A<K> !<: A<I>
-    expect(typeAI.isSubtypeOf(typeAK), isFalse);
-    expect(typeAK.isSubtypeOf(typeAI), isFalse);
-  }
-
-  void test_isSubtypeOf_typeParameter() {
-    //
-    // class A<E> {}
-    //
-    ClassElement classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeA = interfaceType(classA);
-    TypeParameterType parameterType =
-        typeParameterType(classA.typeParameters[0]);
-    expect(typeA.isSubtypeOf(parameterType), isFalse);
-  }
-
-  void test_isSupertypeOf_directSupertype() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeB.isSupertypeOf(typeA), isFalse);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeB), isTrue);
-  }
-
-  void test_isSupertypeOf_dynamic() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    DartType dynamicType = DynamicTypeImpl.instance;
-    // ignore: deprecated_member_use_from_same_package
-    expect(dynamicType.isSupertypeOf(typeA), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(dynamicType), isTrue);
-  }
-
-  void test_isSupertypeOf_indirectSupertype() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    ClassElement classC =
-        ElementFactory.classElement("C", interfaceType(classB));
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeC = interfaceType(classC);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isSupertypeOf(typeA), isFalse);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeC), isTrue);
-  }
-
-  void test_isSupertypeOf_interface() {
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    InterfaceType typeC = interfaceType(classC);
-    classC.interfaces = <InterfaceType>[typeB];
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeB.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeObject.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isSupertypeOf(typeA), isFalse);
-  }
-
-  void test_isSupertypeOf_mixins() {
-    //
-    // class A {}
-    // class B extends A {}
-    // class C with B {}
-    //
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB =
-        ElementFactory.classElement("B", interfaceType(classA));
-    var classC = ElementFactory.classElement2("C");
-    InterfaceType typeObject = classA.supertype;
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeB = interfaceType(classB);
-    InterfaceType typeC = interfaceType(classC);
-    classC.mixins = <InterfaceType>[typeB];
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeB.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeObject.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeC), isTrue);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeC.isSupertypeOf(typeA), isFalse);
-  }
-
-  void test_isSupertypeOf_object() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    InterfaceType typeObject = classA.supertype;
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeObject), isFalse);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeObject.isSupertypeOf(typeA), isTrue);
-  }
-
-  void test_isSupertypeOf_self() {
-    ClassElement classA = class_(name: 'A');
-    InterfaceType typeA = interfaceType(classA);
-    // ignore: deprecated_member_use_from_same_package
-    expect(typeA.isSupertypeOf(typeA), isTrue);
-  }
-
   void test_lookUpGetter_implemented() {
     //
     // class A { g {} }
@@ -3099,7 +1971,6 @@
     MethodElementImpl methodM =
         ElementFactory.methodElement(methodName, typeE, [typeE]);
     A.methods = <MethodElement>[methodM];
-    methodM.type = new FunctionTypeImpl(methodM);
 
     var F = typeParameter('F');
     var B = class_(
@@ -3117,8 +1988,8 @@
     // B<I>
     //
     InterfaceType typeI = interfaceType(class_(name: 'I'));
-    InterfaceTypeImpl typeBI = new InterfaceTypeImpl(B);
-    typeBI.typeArguments = <DartType>[typeI];
+    InterfaceTypeImpl typeBI =
+        new InterfaceTypeImpl.explicit(B, <DartType>[typeI]);
     MethodElement method = typeBI.lookUpMethod(methodName, library);
     expect(method, isNotNull);
     FunctionType methodType = method.type;
@@ -3261,16 +2132,7 @@
     expect(type.resolveToBound(null), same(type));
   }
 
-  void test_setTypeArguments() {
-    InterfaceTypeImpl type = interfaceType(ElementFactory.classElement2('A'));
-    List<DartType> typeArguments = <DartType>[
-      interfaceType(class_(name: 'B')),
-      interfaceType(class_(name: 'C'))
-    ];
-    type.typeArguments = typeArguments;
-    expect(type.typeArguments, typeArguments);
-  }
-
+  @deprecated
   void test_substitute_exception() {
     try {
       var classA = class_(name: 'A');
@@ -3284,16 +2146,17 @@
     }
   }
 
+  @deprecated
   void test_substitute_notEqual() {
     // The [test_substitute_equals] above has a slightly higher level
     // implementation.
     var classA = class_(name: 'A');
     TypeParameterElementImpl parameterElement =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    InterfaceTypeImpl type = new InterfaceTypeImpl(classA);
     TypeParameterTypeImpl parameter =
         new TypeParameterTypeImpl(parameterElement);
-    type.typeArguments = <DartType>[parameter];
+    InterfaceTypeImpl type =
+        new InterfaceTypeImpl.explicit(classA, <DartType>[parameter]);
     InterfaceType argumentType = interfaceType(class_(name: 'B'));
     TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F")));
@@ -3434,106 +2297,6 @@
     expect(type.element, element);
   }
 
-  void test_isMoreSpecificThan_typeArguments_dynamic() {
-    TypeParameterElementImpl element =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    // E << dynamic
-    expect(type.isMoreSpecificThan(DynamicTypeImpl.instance), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_object() {
-    TypeParameterElementImpl element =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    // E << Object
-    expect(type.isMoreSpecificThan(typeProvider.objectType), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_recursive() {
-    ClassElementImpl classS = class_(name: 'A');
-    TypeParameterElementImpl typeParameterU =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("U"));
-    TypeParameterTypeImpl typeParameterTypeU =
-        new TypeParameterTypeImpl(typeParameterU);
-    TypeParameterElementImpl typeParameterT =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("T"));
-    TypeParameterTypeImpl typeParameterTypeT =
-        new TypeParameterTypeImpl(typeParameterT);
-    typeParameterT.bound = typeParameterTypeU;
-    typeParameterU.bound = typeParameterTypeU;
-    // <T extends U> and <U extends T>
-    // T << S
-    expect(
-        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isFalse);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_self() {
-    TypeParameterElementImpl element =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
-    TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
-    // E << E
-    expect(type.isMoreSpecificThan(type), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_transitivity_interfaceTypes() {
-    //  class A {}
-    //  class B extends A {}
-    //
-    ClassElement classA = class_(name: 'A');
-    ClassElement classB = ElementFactory.classElement(
-      "B",
-      classA.instantiate(
-        typeArguments: [],
-        nullabilitySuffix: NullabilitySuffix.star,
-      ),
-    );
-    InterfaceType typeA = classA.instantiate(
-      typeArguments: [],
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-    InterfaceType typeB = interfaceType(classB);
-    TypeParameterElementImpl typeParameterT =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("T"));
-    typeParameterT.bound = typeB;
-    TypeParameterTypeImpl typeParameterTypeT =
-        new TypeParameterTypeImpl(typeParameterT);
-    // <T extends B>
-    // T << A
-    expect(typeParameterTypeT.isMoreSpecificThan(typeA), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_transitivity_typeParameters() {
-    ClassElementImpl classS = class_(name: 'A');
-    TypeParameterElementImpl typeParameterU =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("U"));
-    typeParameterU.bound = interfaceType(classS);
-    TypeParameterTypeImpl typeParameterTypeU =
-        new TypeParameterTypeImpl(typeParameterU);
-    TypeParameterElementImpl typeParameterT =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("T"));
-    typeParameterT.bound = typeParameterTypeU;
-    TypeParameterTypeImpl typeParameterTypeT =
-        new TypeParameterTypeImpl(typeParameterT);
-    // <T extends U> and <U extends S>
-    // T << S
-    expect(
-        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isTrue);
-  }
-
-  void test_isMoreSpecificThan_typeArguments_upperBound() {
-    ClassElementImpl classS = class_(name: 'A');
-    TypeParameterElementImpl typeParameterT =
-        new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("T"));
-    typeParameterT.bound = interfaceType(classS);
-    TypeParameterTypeImpl typeParameterTypeT =
-        new TypeParameterTypeImpl(typeParameterT);
-    // <T extends S>
-    // T << S
-    expect(
-        typeParameterTypeT.isMoreSpecificThan(interfaceType(classS)), isTrue);
-  }
-
   void test_resolveToBound_bound() {
     ClassElementImpl classS = class_(name: 'A');
     TypeParameterElementImpl element =
@@ -3646,6 +2409,7 @@
         same(VoidTypeImpl.instance));
   }
 
+  @deprecated
   void test_substitute_equal() {
     TypeParameterElementImpl element =
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
@@ -3657,6 +2421,7 @@
         same(argument));
   }
 
+  @deprecated
   void test_substitute_notEqual() {
     TypeParameterTypeImpl type = new TypeParameterTypeImpl(
         new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E")));
@@ -3676,51 +2441,6 @@
    */
   DartType _voidType = VoidTypeImpl.instance;
 
-  void test_isMoreSpecificThan_void_A() {
-    ClassElement classA = class_(name: 'A');
-    expect(
-      // ignore: deprecated_member_use_from_same_package
-      _voidType.isMoreSpecificThan(
-        classA.instantiate(
-          typeArguments: [],
-          nullabilitySuffix: NullabilitySuffix.star,
-        ),
-      ),
-      isFalse,
-    );
-  }
-
-  void test_isMoreSpecificThan_void_dynamic() {
-    // ignore: deprecated_member_use_from_same_package
-    expect(_voidType.isMoreSpecificThan(DynamicTypeImpl.instance), isTrue);
-  }
-
-  void test_isMoreSpecificThan_void_void() {
-    // ignore: deprecated_member_use_from_same_package
-    expect(_voidType.isMoreSpecificThan(_voidType), isTrue);
-  }
-
-  void test_isSubtypeOf_void_A() {
-    ClassElement classA = class_(name: 'A');
-    expect(
-      _voidType.isSubtypeOf(
-        classA.instantiate(
-          typeArguments: [],
-          nullabilitySuffix: NullabilitySuffix.star,
-        ),
-      ),
-      isFalse,
-    );
-  }
-
-  void test_isSubtypeOf_void_dynamic() {
-    expect(_voidType.isSubtypeOf(DynamicTypeImpl.instance), isTrue);
-  }
-
-  void test_isSubtypeOf_void_void() {
-    expect(_voidType.isSubtypeOf(_voidType), isTrue);
-  }
-
   void test_isVoid() {
     expect(_voidType.isVoid, isTrue);
   }
@@ -3730,12 +2450,3 @@
     expect(_voidType.resolveToBound(null), same(_voidType));
   }
 }
-
-class _FunctionTypeImplTest_isSubtypeOf_baseCase_classFunction
-    extends InterfaceTypeImpl {
-  _FunctionTypeImplTest_isSubtypeOf_baseCase_classFunction(ClassElement arg0)
-      : super(arg0);
-
-  @override
-  bool get isDartCoreFunction => true;
-}
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 23e92cc..3af77e7 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -35,10 +35,6 @@
 
 @reflectiveTest
 class FunctionTypeTest with ElementsTypesMixin {
-  static const bug_33294_fixed = false;
-  static const bug_33301_fixed = false;
-  static const bug_33302_fixed = false;
-
   final TypeProvider typeProvider = TestTypeProvider();
 
   InterfaceType get intType => typeProvider.intType;
@@ -69,7 +65,6 @@
     expect(f.name, name, reason: 'name');
     // ParameterizedType properties
     expect(f.typeArguments, typeArguments, reason: 'typeArguments');
-    expect(f.typeParameters, typeParameters, reason: 'typeParameters');
     // FunctionType properties
     expect(f.namedParameterTypes, namedParameterTypes,
         reason: 'namedParameterTypes');
@@ -117,16 +112,18 @@
       );
 
   test_synthetic() {
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f, element: isNull);
   }
 
   test_synthetic_instantiate() {
     // T Function<T>(T x)
     var t = typeParameter('T');
-    var x = requiredParameter('x', type: typeParameterType(t));
-    FunctionType f =
-        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], [x]);
+    var x = requiredParameter(name: 'x', type: typeParameterType(t));
+    FunctionType f = new FunctionTypeImpl.synthetic(
+        typeParameterType(t), [t], [x],
+        nullabilitySuffix: NullabilitySuffix.star);
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -140,21 +137,24 @@
   test_synthetic_instantiate_argument_length_mismatch() {
     // dynamic Function<T>()
     var t = typeParameter('T');
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [t], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [t], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     expect(() => f.instantiate([]), throwsA(new TypeMatcher<ArgumentError>()));
   }
 
   test_synthetic_instantiate_no_type_formals() {
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     expect(f.instantiate([]), same(f));
   }
 
   test_synthetic_instantiate_share_parameters() {
     // T Function<T>(int x)
     var t = typeParameter('T');
-    var x = requiredParameter('x', type: intType);
-    FunctionType f =
-        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], [x]);
+    var x = requiredParameter(name: 'x', type: intType);
+    FunctionType f = new FunctionTypeImpl.synthetic(
+        typeParameterType(t), [t], [x],
+        nullabilitySuffix: NullabilitySuffix.star);
     FunctionType instantiated = f.instantiate([objectType]);
     basicChecks(instantiated,
         element: isNull,
@@ -166,8 +166,9 @@
   }
 
   test_synthetic_namedParameter() {
-    var p = namedParameter('x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+    var p = namedParameter(name: 'x', type: objectType);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function({x: Object})',
@@ -179,8 +180,9 @@
   }
 
   test_synthetic_normalParameter() {
-    var p = requiredParameter('x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+    var p = requiredParameter(name: 'x', type: objectType);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function(Object)',
@@ -193,8 +195,9 @@
   }
 
   test_synthetic_optionalParameter() {
-    var p = positionalParameter('x', type: objectType);
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+    var p = positionalParameter(name: 'x', type: objectType);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f,
         element: isNull,
         displayName: 'dynamic Function([Object])',
@@ -207,21 +210,24 @@
   }
 
   test_synthetic_returnType() {
-    FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f,
         element: isNull,
         displayName: 'Object Function()',
         returnType: same(objectType));
   }
 
+  @deprecated
   test_synthetic_substitute() {
     // Map<T, U> Function<U extends T>(T x, U y)
     var t = typeParameter('T');
     var u = typeParameter('U', bound: typeParameterType(t));
-    var x = requiredParameter('x', type: typeParameterType(t));
-    var y = requiredParameter('y', type: typeParameterType(u));
+    var x = requiredParameter(name: 'x', type: typeParameterType(t));
+    var y = requiredParameter(name: 'y', type: typeParameterType(u));
     FunctionType f = new FunctionTypeImpl.synthetic(
-        mapOf(typeParameterType(t), typeParameterType(u)), [u], [x, y]);
+        mapOf(typeParameterType(t), typeParameterType(u)), [u], [x, y],
+        nullabilitySuffix: NullabilitySuffix.star);
     FunctionType substituted =
         f.substitute2([objectType], [typeParameterType(t)]);
     var uSubstituted = substituted.typeFormals[0];
@@ -238,20 +244,24 @@
         parameters: hasLength(2));
   }
 
+  @deprecated
   test_synthetic_substitute_argument_length_mismatch() {
     // dynamic Function()
     var t = typeParameter('T');
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     expect(() => f.substitute2([], [typeParameterType(t)]),
         throwsA(new TypeMatcher<ArgumentError>()));
   }
 
+  @deprecated
   test_synthetic_substitute_unchanged() {
     // dynamic Function<U>(U x)
     var t = typeParameter('T');
     var u = typeParameter('U');
-    var x = requiredParameter('x', type: typeParameterType(u));
-    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [u], [x]);
+    var x = requiredParameter(name: 'x', type: typeParameterType(u));
+    FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [u], [x],
+        nullabilitySuffix: NullabilitySuffix.star);
     FunctionType substituted =
         f.substitute2([objectType], [typeParameterType(t)]);
     expect(substituted, same(f));
@@ -259,410 +269,15 @@
 
   test_synthetic_typeFormals() {
     var t = typeParameter('T');
-    FunctionType f =
-        new FunctionTypeImpl.synthetic(typeParameterType(t), [t], []);
+    FunctionType f = new FunctionTypeImpl.synthetic(
+        typeParameterType(t), [t], [],
+        nullabilitySuffix: NullabilitySuffix.star);
     basicChecks(f,
         element: isNull,
         displayName: 'T Function<T>()',
         returnType: typeParameterType(t),
         typeFormals: [same(t)]);
   }
-
-  test_unnamedConstructor() {
-    var e = new MockFunctionTypedElement();
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f, element: same(e));
-  }
-
-  test_unnamedConstructor_instantiate_argument_length_mismatch() {
-    var t = typeParameter('T');
-    var e = new MockFunctionTypedElement(typeParameters: [t]);
-    FunctionType f = new FunctionTypeImpl(e);
-    expect(() => f.instantiate([]), throwsA(new TypeMatcher<ArgumentError>()));
-  }
-
-  test_unnamedConstructor_instantiate_noTypeParameters() {
-    var e = new MockFunctionTypedElement();
-    FunctionType f = new FunctionTypeImpl(e);
-    expect(f.instantiate([]), same(f));
-  }
-
-  test_unnamedConstructor_instantiate_parameterType_simple() {
-    var t = typeParameter('T');
-    var p = requiredParameter('x', type: typeParameterType(t));
-    var e = new MockFunctionTypedElement(typeParameters: [t], parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    var instantiated = f.instantiate([objectType]);
-    basicChecks(instantiated,
-        element: same(e),
-        displayName: 'dynamic Function(Object)',
-        typeArguments: hasLength(1),
-        typeParameters: [same(t)],
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(objectType)],
-        parameters: hasLength(1));
-    expect(instantiated.typeArguments[0], same(objectType));
-    expect(instantiated.parameters[0].name, 'x');
-    expect(instantiated.parameters[0].type, same(objectType));
-  }
-
-  test_unnamedConstructor_instantiate_returnType_simple() {
-    var t = typeParameter('T');
-    var e = new MockFunctionTypedElement(
-        typeParameters: [t], returnType: typeParameterType(t));
-    FunctionType f = new FunctionTypeImpl(e);
-    var instantiated = f.instantiate([objectType]);
-    basicChecks(instantiated,
-        element: same(e),
-        displayName: 'Object Function()',
-        typeArguments: hasLength(1),
-        typeParameters: [same(t)],
-        returnType: same(objectType));
-    expect(instantiated.typeArguments[0], same(objectType));
-  }
-
-  test_unnamedConstructor_namedParameter() {
-    var p = namedParameter('x', type: dynamicType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function({x: dynamic})',
-        namedParameterTypes: {'x': same(dynamicType)},
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_namedParameter_object() {
-    var p = namedParameter('x', type: objectType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function({x: Object})',
-        namedParameterTypes: {'x': same(objectType)},
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_nonTypedef_noTypeArguments() {
-    var e = new MockFunctionTypedElement();
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f, element: same(e));
-  }
-
-  test_unnamedConstructor_nonTypedef_withTypeArguments() {
-    var t = typeParameter('T');
-    var e = method('e', typeParameterType(t));
-    class_(name: 'C', typeParameters: [t], methods: [e]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        typeArguments: [typeParameterType(t)],
-        typeParameters: [same(t)],
-        displayName: 'T Function()',
-        returnType: typeParameterType(t));
-  }
-
-  test_unnamedConstructor_normalParameter() {
-    var p = requiredParameter('x', type: dynamicType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function(dynamic)',
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(dynamicType)],
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_normalParameter_object() {
-    var p = requiredParameter('x', type: objectType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function(Object)',
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(objectType)],
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_optionalParameter() {
-    var p = positionalParameter('x', type: dynamicType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function([dynamic])',
-        optionalParameterNames: ['x'],
-        optionalParameterTypes: [same(dynamicType)],
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_optionalParameter_object() {
-    var p = positionalParameter('x', type: objectType);
-    var e = new MockFunctionTypedElement(parameters: [p]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function([Object])',
-        optionalParameterNames: ['x'],
-        optionalParameterTypes: [same(objectType)],
-        parameters: [same(p)]);
-  }
-
-  test_unnamedConstructor_returnType() {
-    var e = new MockFunctionTypedElement(returnType: objectType);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        returnType: same(objectType),
-        displayName: 'Object Function()');
-  }
-
-  test_unnamedConstructor_returnType_null() {
-    var e = new MockFunctionTypedElement.withNullReturn();
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        returnType: same(dynamicType),
-        displayName: 'dynamic Function()');
-  }
-
-  test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
-    var t = typeParameter('T');
-    var e = method('e', dynamicType, isStatic: true);
-    class_(name: 'C', typeParameters: [t], methods: [e]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f, element: same(e));
-  }
-
-  test_unnamedConstructor_substitute_argument_length_mismatch() {
-    // abstract class C<T> {
-    //   dynamic f();
-    // }
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var e = new MockFunctionTypedElement(enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    expect(() => f.substitute2([], [typeParameterType(t)]),
-        throwsA(new TypeMatcher<ArgumentError>()));
-  }
-
-  test_unnamedConstructor_substitute_bound_recursive() {
-    // abstract class C<T> {
-    //   Map<S, V> f<S extends T, T extends U, V extends T>();
-    // }
-    var s = typeParameter('S');
-    var t = typeParameter('T');
-    var u = typeParameter('U');
-    var v = typeParameter('V');
-    s.bound = typeParameterType(t);
-    t.bound = typeParameterType(u);
-    v.bound = typeParameterType(t);
-    var c = class_(name: 'C', typeParameters: [u]);
-    var e = new MockFunctionTypedElement(
-        returnType: mapOf(typeParameterType(s), typeParameterType(v)),
-        typeParameters: [s, t, v],
-        enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [typeParameterType(u)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: isNotNull,
-        returnType: isNotNull,
-        typeFormals: hasLength(3),
-        typeParameters: [same(u)],
-        typeArguments: [same(objectType)]);
-    expect(substituted.displayName,
-        'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
-    var s2 = substituted.typeFormals[0];
-    var t2 = substituted.typeFormals[1];
-    var v2 = substituted.typeFormals[2];
-    expect(s2.name, 'S');
-    expect(t2.name, 'T');
-    expect(v2.name, 'V');
-    expect(s2.bound, typeParameterType(t2));
-    expect(t2.bound, same(objectType));
-    expect(v2.bound, typeParameterType(t2));
-    if (bug_33301_fixed) {
-      expect(substituted.returnType,
-          mapOf(typeParameterType(s2), typeParameterType(v2)));
-    } else {
-      expect(substituted.returnType,
-          mapOf(typeParameterType(s), typeParameterType(v)));
-    }
-  }
-
-  test_unnamedConstructor_substitute_bound_recursive_parameter() {
-    // abstract class C<T> {
-    //   void f<S extends T, T extends U, V extends T>(S x, V y);
-    // }
-    var s = typeParameter('S');
-    var t = typeParameter('T');
-    var u = typeParameter('U');
-    var v = typeParameter('V');
-    s.bound = typeParameterType(t);
-    t.bound = typeParameterType(u);
-    v.bound = typeParameterType(t);
-    var c = class_(name: 'C', typeParameters: [u]);
-    var x = requiredParameter('x', type: typeParameterType(s));
-    var y = requiredParameter('y', type: typeParameterType(v));
-    var e = new MockFunctionTypedElement(
-        returnType: voidType,
-        typeParameters: [s, t, v],
-        enclosingElement: c,
-        parameters: [x, y]);
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [typeParameterType(u)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: isNotNull,
-        returnType: same(voidType),
-        normalParameterNames: ['x', 'y'],
-        normalParameterTypes: hasLength(2),
-        parameters: hasLength(2),
-        typeFormals: hasLength(3),
-        typeParameters: [same(u)],
-        typeArguments: [same(objectType)]);
-    expect(substituted.displayName,
-        'void Function<S extends T,T extends Object,V extends T>(S, V)');
-    var s2 = substituted.typeFormals[0];
-    var t2 = substituted.typeFormals[1];
-    var v2 = substituted.typeFormals[2];
-    expect(s2.name, 'S');
-    expect(t2.name, 'T');
-    expect(v2.name, 'V');
-    expect(s2.bound, typeParameterType(t2));
-    expect(t2.bound, same(objectType));
-    expect(v2.bound, typeParameterType(t2));
-    if (bug_33301_fixed) {
-      expect(substituted.normalParameterTypes,
-          [same(typeParameterType(s2)), same(typeParameterType(v2))]);
-    } else {
-      expect(substituted.normalParameterTypes,
-          [typeParameterType(s), typeParameterType(v)]);
-    }
-  }
-
-  test_unnamedConstructor_substitute_bound_simple() {
-    // abstract class C<T> {
-    //   U f<U extends T>();
-    // }
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var u = typeParameter('U', bound: typeParameterType(t));
-    var e = new MockFunctionTypedElement(
-        typeParameters: [u],
-        returnType: typeParameterType(u),
-        enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: 'U Function<U extends Object>()',
-        typeArguments: [same(objectType)],
-        typeParameters: [same(t)],
-        returnType: isNotNull,
-        typeFormals: hasLength(1));
-    expect(substituted.typeFormals[0].name, 'U');
-    expect(substituted.typeFormals[0].bound, same(objectType));
-    expect((substituted.returnType as TypeParameterTypeImpl).element,
-        same(getBaseElement(substituted.typeFormals[0])));
-  }
-
-  test_unnamedConstructor_substitute_noop() {
-    var t = typeParameter('T');
-    var e = new MockFunctionTypedElement(returnType: typeParameterType(t));
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted =
-        f.substitute2([typeParameterType(t)], [typeParameterType(t)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: 'T Function()',
-        returnType: typeParameterType(t));
-    // TODO(paulberry): test substitute length mismatch
-  }
-
-  test_unnamedConstructor_substitute_parameterType_simple() {
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var p = requiredParameter('x', type: typeParameterType(t));
-    var e = new MockFunctionTypedElement(parameters: [p], enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: 'dynamic Function(Object)',
-        normalParameterNames: ['x'],
-        normalParameterTypes: [same(objectType)],
-        parameters: hasLength(1),
-        typeArguments: [same(objectType)],
-        typeParameters: [same(t)]);
-    expect(substituted.parameters[0].name, 'x');
-    expect(substituted.parameters[0].type, same(objectType));
-  }
-
-  test_unnamedConstructor_substitute_returnType_simple() {
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var e = new MockFunctionTypedElement(
-        returnType: typeParameterType(t), enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    var substituted = f.substitute2([objectType], [typeParameterType(t)]);
-    basicChecks(substituted,
-        element: same(e),
-        displayName: 'Object Function()',
-        returnType: same(objectType),
-        typeArguments: [same(objectType)],
-        typeParameters: [same(t)]);
-  }
-
-  test_unnamedConstructor_typeParameter() {
-    var t = typeParameter('T');
-    var e = new MockFunctionTypedElement(typeParameters: [t]);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'dynamic Function<T>()',
-        typeFormals: [same(t)]);
-    // TODO(paulberry): test pruning of bounds
-  }
-
-  test_unnamedConstructor_typeParameter_with_bound() {
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var u = typeParameter('U', bound: typeParameterType(t));
-    var e = new MockFunctionTypedElement(
-        typeParameters: [u],
-        returnType: typeParameterType(u),
-        enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'U Function<U extends T>()',
-        typeArguments: [typeParameterType(t)],
-        typeParameters: [same(t)],
-        returnType: typeParameterType(u),
-        typeFormals: hasLength(1));
-    expect(f.typeFormals[0].name, 'U');
-    expect(f.typeFormals[0].bound, typeParameterType(t));
-  }
-
-  test_unnamedConstructor_with_enclosing_type_parameters() {
-    // Test a weird behavior: substitutions are recorded in typeArguments and
-    // typeParameters.
-    var t = typeParameter('T');
-    var c = class_(name: 'C', typeParameters: [t]);
-    var e = new MockFunctionTypedElement(
-        returnType: typeParameterType(t), enclosingElement: c);
-    FunctionType f = new FunctionTypeImpl(e);
-    basicChecks(f,
-        element: same(e),
-        displayName: 'T Function()',
-        returnType: typeParameterType(t),
-        typeArguments: [typeParameterType(t)],
-        typeParameters: [same(t)]);
-  }
 }
 
 class MockCompilationUnitElement implements CompilationUnitElement {
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
deleted file mode 100644
index b2da098..0000000
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ /dev/null
@@ -1,1125 +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:analyzer/dart/element/nullability_suffix.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
-import 'package:meta/meta.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../resolution/driver_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(InheritanceManager2Test);
-  });
-}
-
-@reflectiveTest
-class InheritanceManager2Test extends DriverResolutionTest {
-  InheritanceManager2 manager;
-
-  @override
-  Future<void> resolveTestFile() async {
-    await super.resolveTestFile();
-    manager = new InheritanceManager2(
-      result.unit.declaredElement.context.typeSystem,
-    );
-  }
-
-  test_getInherited_closestSuper() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  void foo() {}
-}
-
-class X extends B {
-  void foo() {}
-}
-''');
-    _assertGetInherited(
-      className: 'X',
-      name: 'foo',
-      expected: 'B.foo: void Function()',
-    );
-  }
-
-  test_getInherited_interfaces() async {
-    await resolveTestCode('''
-abstract class I {
-  void foo();
-}
-
-abstrac class J {
-  void foo();
-}
-
-class X implements I, J {
-  void foo() {}
-}
-''');
-    _assertGetInherited(
-      className: 'X',
-      name: 'foo',
-      expected: 'J.foo: void Function()',
-    );
-  }
-
-  test_getInherited_mixin() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-mixin M {
-  void foo() {}
-}
-
-class X extends A with M {
-  void foo() {}
-}
-''');
-    _assertGetInherited(
-      className: 'X',
-      name: 'foo',
-      expected: 'M.foo: void Function()',
-    );
-  }
-
-  test_getInherited_preferImplemented() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class I {
-  void foo() {}
-}
-
-class X extends A implements I {
-  void foo() {}
-}
-''');
-    _assertGetInherited(
-      className: 'X',
-      name: 'foo',
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getInheritedConcreteMap_accessor_extends() async {
-    await resolveTestCode('''
-class A {
-  int get foo => 0;
-}
-
-class B extends A {}
-''');
-    _assertInheritedConcreteMap('B', r'''
-A.foo: int Function()
-''');
-  }
-
-  test_getInheritedConcreteMap_accessor_implements() async {
-    await resolveTestCode('''
-class A {
-  int get foo => 0;
-}
-
-abstract class B implements A {}
-''');
-    _assertInheritedConcreteMap('B', '');
-  }
-
-  test_getInheritedConcreteMap_accessor_with() async {
-    await resolveTestCode('''
-mixin A {
-  int get foo => 0;
-}
-
-class B extends Object with A {}
-''');
-    _assertInheritedConcreteMap('B', r'''
-A.foo: int Function()
-''');
-  }
-
-  test_getInheritedConcreteMap_implicitExtends() async {
-    await resolveTestCode('''
-class A {}
-''');
-    _assertInheritedConcreteMap('A', '');
-  }
-
-  test_getInheritedConcreteMap_method_extends() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {}
-''');
-    _assertInheritedConcreteMap('B', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedConcreteMap_method_extends_abstract() async {
-    await resolveTestCode('''
-abstract class A {
-  void foo();
-}
-
-class B extends A {}
-''');
-    _assertInheritedConcreteMap('B', '');
-  }
-
-  test_getInheritedConcreteMap_method_extends_invalidForImplements() async {
-    await resolveTestCode('''
-abstract class I {
-  void foo(int x, {int y});
-  void bar(String s);
-}
-
-class A {
-  void foo(int x) {}
-}
-
-class C extends A implements I {}
-''');
-    _assertInheritedConcreteMap('C', r'''
-A.foo: void Function(int)
-''');
-  }
-
-  test_getInheritedConcreteMap_method_implements() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-abstract class B implements A {}
-''');
-    _assertInheritedConcreteMap('B', '');
-  }
-
-  test_getInheritedConcreteMap_method_with() async {
-    await resolveTestCode('''
-mixin A {
-  void foo() {}
-}
-
-class B extends Object with A {}
-''');
-    _assertInheritedConcreteMap('B', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedConcreteMap_method_with2() async {
-    await resolveTestCode('''
-mixin A {
-  void foo() {}
-}
-
-mixin B {
-  void bar() {}
-}
-
-class C extends Object with A, B {}
-''');
-    _assertInheritedConcreteMap('C', r'''
-A.foo: void Function()
-B.bar: void Function()
-''');
-  }
-
-  test_getInheritedMap_accessor_extends() async {
-    await resolveTestCode('''
-class A {
-  int get foo => 0;
-}
-
-class B extends A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-''');
-  }
-
-  test_getInheritedMap_accessor_implements() async {
-    await resolveTestCode('''
-class A {
-  int get foo => 0;
-}
-
-abstract class B implements A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-''');
-  }
-
-  test_getInheritedMap_accessor_with() async {
-    await resolveTestCode('''
-mixin A {
-  int get foo => 0;
-}
-
-class B extends Object with A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-''');
-  }
-
-  test_getInheritedMap_closestSuper() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  void foo() {}
-}
-
-class X extends B {}
-''');
-    _assertInheritedMap('X', r'''
-B.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_field_extends() async {
-    await resolveTestCode('''
-class A {
-  int foo;
-}
-
-class B extends A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-A.foo=: void Function(int)
-''');
-  }
-
-  test_getInheritedMap_field_implements() async {
-    await resolveTestCode('''
-class A {
-  int foo;
-}
-
-abstract class B implements A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-A.foo=: void Function(int)
-''');
-  }
-
-  test_getInheritedMap_field_with() async {
-    await resolveTestCode('''
-mixin A {
-  int foo;
-}
-
-class B extends Object with A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: int Function()
-A.foo=: void Function(int)
-''');
-  }
-
-  test_getInheritedMap_implicitExtendsObject() async {
-    await resolveTestCode('''
-class A {}
-''');
-    _assertInheritedMap('A', '');
-  }
-
-  test_getInheritedMap_method_extends() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_method_implements() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-abstract class B implements A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_method_with() async {
-    await resolveTestCode('''
-mixin A {
-  void foo() {}
-}
-
-class B extends Object with A {}
-''');
-    _assertInheritedMap('B', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_preferImplemented() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class I {
-  void foo() {}
-}
-
-class X extends A implements I {
-  void foo() {}
-}
-''');
-    _assertInheritedMap('X', r'''
-A.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_union_conflict() async {
-    await resolveTestCode('''
-abstract class I {
-  int foo();
-  void bar();
-}
-
-abstract class J {
-  double foo();
-  void bar();
-}
-
-abstract class A implements I, J {}
-''');
-    _assertInheritedMap('A', r'''
-J.bar: void Function()
-''');
-  }
-
-  test_getInheritedMap_union_differentNames() async {
-    await resolveTestCode('''
-abstract class I {
-  int foo();
-}
-
-abstract class J {
-  double bar();
-}
-
-abstract class A implements I, J {}
-''');
-    _assertInheritedMap('A', r'''
-I.foo: int Function()
-J.bar: double Function()
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_2_getters() async {
-    await resolveTestCode('''
-abstract class I {
-  int get foo;
-}
-
-abstract class J {
-  int get foo;
-}
-
-abstract class A implements I, J {}
-''');
-    _assertInheritedMap('A', r'''
-J.foo: int Function()
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_2_methods() async {
-    await resolveTestCode('''
-abstract class I {
-  void foo();
-}
-
-abstract class J {
-  void foo();
-}
-
-abstract class A implements I, J {}
-''');
-    _assertInheritedMap('A', r'''
-J.foo: void Function()
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_2_setters() async {
-    await resolveTestCode('''
-abstract class I {
-  void set foo(num _);
-}
-
-abstract class J {
-  void set foo(int _);
-}
-
-abstract class A implements I, J {}
-abstract class B implements J, I {}
-''');
-    _assertInheritedMap('A', r'''
-I.foo=: void Function(num)
-''');
-
-    _assertInheritedMap('B', r'''
-I.foo=: void Function(num)
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_3_getters() async {
-    await resolveTestCode('''
-class A {}
-class B extends A {}
-class C extends B {}
-
-abstract class I1 {
-  A get foo;
-}
-
-abstract class I2 {
-  B get foo;
-}
-
-abstract class I3 {
-  C get foo;
-}
-
-abstract class D implements I1, I2, I3 {}
-abstract class E implements I3, I2, I1 {}
-''');
-    _assertInheritedMap('D', r'''
-I3.foo: C Function()
-''');
-
-    _assertInheritedMap('E', r'''
-I3.foo: C Function()
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_3_methods() async {
-    await resolveTestCode('''
-class A {}
-class B extends A {}
-class C extends B {}
-
-abstract class I1 {
-  void foo(A _);
-}
-
-abstract class I2 {
-  void foo(B _);
-}
-
-abstract class I3 {
-  void foo(C _);
-}
-
-abstract class D implements I1, I2, I3 {}
-abstract class E implements I3, I2, I1 {}
-''');
-    _assertInheritedMap('D', r'''
-I1.foo: void Function(A)
-''');
-  }
-
-  test_getInheritedMap_union_multipleSubtypes_3_setters() async {
-    await resolveTestCode('''
-class A {}
-class B extends A {}
-class C extends B {}
-
-abstract class I1 {
-  set foo(A _);
-}
-
-abstract class I2 {
-  set foo(B _);
-}
-
-abstract class I3 {
-  set foo(C _);
-}
-
-abstract class D implements I1, I2, I3 {}
-abstract class E implements I3, I2, I1 {}
-''');
-    _assertInheritedMap('D', r'''
-I1.foo=: void Function(A)
-''');
-
-    _assertInheritedMap('E', r'''
-I1.foo=: void Function(A)
-''');
-  }
-
-  test_getInheritedMap_union_oneSubtype_2_methods() async {
-    await resolveTestCode('''
-abstract class I1 {
-  int foo();
-}
-
-abstract class I2 {
-  int foo([int _]);
-}
-
-abstract class A implements I1, I2 {}
-abstract class B implements I2, I1 {}
-''');
-    _assertInheritedMap('A', r'''
-I2.foo: int Function([int])
-''');
-
-    _assertInheritedMap('B', r'''
-I2.foo: int Function([int])
-''');
-  }
-
-  test_getInheritedMap_union_oneSubtype_3_methods() async {
-    await resolveTestCode('''
-abstract class I1 {
-  int foo();
-}
-
-abstract class I2 {
-  int foo([int _]);
-}
-
-abstract class I3 {
-  int foo([int _, int __]);
-}
-
-abstract class A implements I1, I2, I3 {}
-abstract class B implements I3, I2, I1 {}
-''');
-    _assertInheritedMap('A', r'''
-I3.foo: int Function([int, int])
-''');
-
-    _assertInheritedMap('B', r'''
-I3.foo: int Function([int, int])
-''');
-  }
-
-  test_getMember() async {
-    await resolveTestCode('''
-abstract class I1 {
-  void f(int i);
-}
-
-abstract class I2 {
-  void f(Object o);
-}
-
-abstract class C implements I1, I2 {}
-''');
-    _assertGetMember(
-      className: 'C',
-      name: 'f',
-      expected: 'I2.f: void Function(Object)',
-    );
-  }
-
-  test_getMember_concrete() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-''');
-    _assertGetMember(
-      className: 'A',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_abstract() async {
-    await resolveTestCode('''
-abstract class A {
-  void foo();
-}
-''');
-    _assertGetMember(
-      className: 'A',
-      name: 'foo',
-      concrete: true,
-    );
-  }
-
-  test_getMember_concrete_fromMixedClass() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class X with A {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_fromMixedClass2() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B = Object with A;
-
-class X with B {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_fromMixedClass_skipObject() async {
-    await resolveTestCode('''
-class A {
-  String toString() => 'A';
-}
-
-class B {}
-
-class X extends A with B {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'toString',
-      concrete: true,
-      expected: 'A.toString: String Function()',
-    );
-  }
-
-  test_getMember_concrete_fromMixin() async {
-    await resolveTestCode('''
-mixin M {
-  void foo() {}
-}
-
-class X with M {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      concrete: true,
-      expected: 'M.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_fromSuper() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {}
-
-abstract class C extends B {}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-
-    _assertGetMember(
-      className: 'C',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_missing() async {
-    await resolveTestCode('''
-abstract class A {}
-''');
-    _assertGetMember(
-      className: 'A',
-      name: 'foo',
-      concrete: true,
-    );
-  }
-
-  test_getMember_concrete_noSuchMethod() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B implements A {
-  noSuchMethod(_) {}
-}
-
-abstract class C extends B {}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-
-    _assertGetMember(
-      className: 'C',
-      name: 'foo',
-      concrete: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_concrete_noSuchMethod_mixin() async {
-    await resolveTestCode('''
-class A {
-  void foo();
-
-  noSuchMethod(_) {}
-}
-
-abstract class B extends Object with A {}
-''');
-// noSuchMethod forwarders are not mixed-in.
-    // https://github.com/dart-lang/sdk/issues/33553#issuecomment-424638320
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      concrete: true,
-    );
-  }
-
-  test_getMember_concrete_noSuchMethod_moreSpecificSignature() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B implements A {
-  noSuchMethod(_) {}
-}
-
-class C extends B {
-  void foo([int a]);
-}
-''');
-    _assertGetMember(
-      className: 'C',
-      name: 'foo',
-      concrete: true,
-      expected: 'C.foo: void Function([int])',
-    );
-  }
-
-  test_getMember_preferLatest_mixin() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-mixin M1 {
-  void foo() {}
-}
-
-mixin M2 {
-  void foo() {}
-}
-
-abstract class I {
-  void foo();
-}
-
-class X extends A with M1, M2 implements I {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      expected: 'M2.foo: void Function()',
-    );
-  }
-
-  test_getMember_preferLatest_superclass() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  void foo() {}
-}
-
-abstract class I {
-  void foo();
-}
-
-class X extends B implements I {}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      expected: 'B.foo: void Function()',
-    );
-  }
-
-  test_getMember_preferLatest_this() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-abstract class I {
-  void foo();
-}
-
-class X extends A implements I {
-  void foo() {}
-}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      expected: 'X.foo: void Function()',
-    );
-  }
-
-  test_getMember_super_abstract() async {
-    await resolveTestCode('''
-abstract class A {
-  void foo();
-}
-
-class B extends A {
-  noSuchMethod(_) {}
-}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      forSuper: true,
-    );
-  }
-
-  test_getMember_super_forMixin_interface() async {
-    await resolveTestCode('''
-abstract class A {
-  void foo();
-}
-
-mixin M implements A {}
-''');
-    _assertGetMember(
-      className: 'M',
-      name: 'foo',
-      forSuper: true,
-    );
-  }
-
-  test_getMember_super_forMixin_superclassConstraint() async {
-    await resolveTestCode('''
-abstract class A {
-  void foo();
-}
-
-mixin M on A {}
-''');
-    _assertGetMember(
-      className: 'M',
-      name: 'foo',
-      forSuper: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_super_fromMixin() async {
-    await resolveTestCode('''
-mixin M {
-  void foo() {}
-}
-
-class X extends Object with M {
-  void foo() {}
-}
-''');
-    _assertGetMember(
-      className: 'X',
-      name: 'foo',
-      forSuper: true,
-      expected: 'M.foo: void Function()',
-    );
-  }
-
-  test_getMember_super_fromSuper() async {
-    await resolveTestCode('''
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  void foo() {}
-}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      forSuper: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  test_getMember_super_missing() async {
-    await resolveTestCode('''
-class A {}
-
-class B extends A {}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      forSuper: true,
-    );
-  }
-
-  test_getMember_super_noSuchMember() async {
-    await resolveTestCode('''
-class A {
-  void foo();
-  noSuchMethod(_) {}
-}
-
-class B extends A {
-  void foo() {}
-}
-''');
-    _assertGetMember(
-      className: 'B',
-      name: 'foo',
-      forSuper: true,
-      expected: 'A.foo: void Function()',
-    );
-  }
-
-  void _assertGetInherited({
-    @required String className,
-    @required String name,
-    String expected,
-  }) {
-    var interfaceType = _classInterfaceType(className);
-
-    var memberType = manager.getInherited(
-      interfaceType,
-      new Name(null, name),
-    );
-
-    _assertMemberType(memberType, expected);
-  }
-
-  void _assertGetMember({
-    @required String className,
-    @required String name,
-    String expected,
-    bool concrete = false,
-    bool forSuper = false,
-  }) {
-    var interfaceType = _classInterfaceType(className);
-
-    var memberType = manager.getMember(
-      interfaceType,
-      new Name(null, name),
-      concrete: concrete,
-      forSuper: forSuper,
-    );
-
-    _assertMemberType(memberType, expected);
-  }
-
-  void _assertInheritedConcreteMap(String className, String expected) {
-    var type = _classInterfaceType(className);
-    var map = manager.getInheritedConcreteMap(type);
-    _assertNameToFunctionTypeMap(map, expected);
-  }
-
-  void _assertInheritedMap(String className, String expected) {
-    var type = _classInterfaceType(className);
-    var map = manager.getInheritedMap(type);
-    _assertNameToFunctionTypeMap(map, expected);
-  }
-
-  void _assertMemberType(FunctionType type, String expected) {
-    if (expected != null) {
-      var element = type.element;
-      var enclosingElement = element.enclosingElement;
-      var actual = '${enclosingElement.name}.${element.name}: $type';
-      expect(actual, expected);
-    } else {
-      expect(type, isNull);
-    }
-  }
-
-  void _assertNameToFunctionTypeMap(
-      Map<Name, FunctionType> map, String expected) {
-    var lines = <String>[];
-    for (var name in map.keys) {
-      var type = map[name];
-      var element = type.element;
-
-      var enclosingElement = element.enclosingElement;
-      if (enclosingElement.name == 'Object') continue;
-
-      lines.add('${enclosingElement.name}.${element.name}: $type');
-    }
-
-    lines.sort();
-    var actual = lines.isNotEmpty ? lines.join('\n') + '\n' : '';
-
-    if (actual != expected) {
-      print(actual);
-    }
-    expect(actual, expected);
-  }
-
-  InterfaceType _classInterfaceType(String className) {
-    var element = findElement.classOrMixin(className);
-    return element.instantiate(
-      typeArguments: const [],
-      nullabilitySuffix: NullabilitySuffix.star,
-    );
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index f8901a3..9d113c6 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -969,6 +969,18 @@
     );
   }
 
+  test_getMember_super_forObject() async {
+    await resolveTestCode('''
+class A {}
+''');
+    var member = manager.getMember(
+      typeProvider.objectType,
+      Name(null, 'hashCode'),
+      forSuper: true,
+    );
+    expect(member, isNull);
+  }
+
   test_getMember_super_fromMixin() async {
     await resolveTestCode('''
 mixin M {
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
new file mode 100644
index 0000000..4def2d5
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -0,0 +1,5602 @@
+// 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/dart/analysis/features.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/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import '../../../generated/test_analysis_context.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SubtypeTest);
+    defineReflectiveTests(NonNullableSubtypingCompoundTest);
+    defineReflectiveTests(SubtypingCompoundTest);
+  });
+}
+
+@reflectiveTest
+class NonNullableSubtypingCompoundTest extends _SubtypingCompoundTestBase {
+  @override
+  FeatureSet get testFeatureSet {
+    return FeatureSet.forTesting(
+      additionalFeatures: [Feature.non_nullable],
+    );
+  }
+
+  test_dynamic() {
+    var equivalents = <DartType>[
+      voidNone,
+      objectQuestion,
+      objectStar,
+    ];
+
+    var subtypes = <DartType>[
+      bottomNone,
+      nullNone,
+      objectNone,
+    ];
+
+    _checkGroups(
+      dynamicNone,
+      equivalents: equivalents,
+      subtypes: subtypes,
+    );
+  }
+
+  test_futureOr_topTypes() {
+    var futureOrObject = futureOrNone(objectNone);
+    var futureOrObjectStar = futureOrNone(objectStar);
+    var futureOrObjectQuestion = futureOrNone(objectQuestion);
+
+    var futureOrStarObject = futureOrStar(objectNone);
+    var futureOrStarObjectStar = futureOrStar(objectStar);
+    var futureOrStarObjectQuestion = futureOrStar(objectQuestion);
+
+    var futureOrQuestionObject = futureOrQuestion(objectNone);
+    var futureOrQuestionObjectStar = futureOrQuestion(objectStar);
+    var futureOrQuestionObjectQuestion = futureOrQuestion(objectQuestion);
+
+    //FutureOr<Object> <: FutureOr*<Object?>
+    _checkGroups(
+      futureOrObject,
+      equivalents: [
+        objectStar,
+        futureOrObjectStar,
+        futureOrStarObject,
+        futureOrStarObjectStar,
+        objectNone,
+      ],
+      subtypes: [],
+      supertypes: [
+        objectQuestion,
+        futureOrQuestionObject,
+        futureOrObjectQuestion,
+        futureOrQuestionObject,
+        futureOrQuestionObjectStar,
+        futureOrStarObjectQuestion,
+        futureOrQuestionObjectQuestion,
+      ],
+    );
+  }
+
+  test_intNone() {
+    var equivalents = <DartType>[
+      intNone,
+      intStar,
+    ];
+
+    var subtypes = <DartType>[
+      bottomNone,
+    ];
+
+    var supertypes = <DartType>[
+      intQuestion,
+      objectNone,
+      objectQuestion,
+    ];
+
+    var unrelated = <DartType>[
+      doubleNone,
+      nullNone,
+      nullStar,
+      nullQuestion,
+      bottomQuestion,
+    ];
+
+    _checkGroups(
+      intNone,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+      subtypes: subtypes,
+    );
+  }
+
+  test_intQuestion() {
+    var equivalents = <DartType>[
+      intQuestion,
+      intStar,
+    ];
+
+    var subtypes = <DartType>[
+      intNone,
+      nullNone,
+      nullQuestion,
+      nullStar,
+      bottomNone,
+      bottomQuestion,
+      bottomStar,
+    ];
+
+    var supertypes = <DartType>[
+      numQuestion,
+      numStar,
+      objectQuestion,
+      objectStar,
+    ];
+
+    var unrelated = <DartType>[
+      doubleNone,
+      numNone,
+      objectNone,
+    ];
+
+    _checkGroups(
+      intQuestion,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+      subtypes: subtypes,
+    );
+  }
+
+  test_intStar() {
+    var equivalents = <DartType>[
+      intNone,
+      intQuestion,
+      intStar,
+    ];
+
+    var subtypes = <DartType>[
+      nullNone,
+      nullStar,
+      nullQuestion,
+      bottomNone,
+      bottomStar,
+      bottomQuestion,
+    ];
+
+    var supertypes = <DartType>[
+      numNone,
+      numQuestion,
+      numStar,
+      objectNone,
+      objectQuestion,
+    ];
+
+    var unrelated = <DartType>[
+      doubleStar,
+    ];
+
+    _checkGroups(
+      intStar,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+      subtypes: subtypes,
+    );
+  }
+
+  test_null() {
+    var equivalents = <DartType>[
+      nullNone,
+      nullQuestion,
+      nullStar,
+      bottomQuestion,
+    ];
+
+    var supertypes = <DartType>[
+      intQuestion,
+      intStar,
+      objectQuestion,
+      objectStar,
+      dynamicNone,
+      voidNone,
+    ];
+
+    var subtypes = <DartType>[
+      bottomNone,
+    ];
+
+    var unrelated = <DartType>[
+      doubleNone,
+      intNone,
+      numNone,
+      objectNone,
+    ];
+
+    for (final formOfNull in equivalents) {
+      _checkGroups(
+        formOfNull,
+        equivalents: equivalents,
+        supertypes: supertypes,
+        unrelated: unrelated,
+        subtypes: subtypes,
+      );
+    }
+  }
+
+  test_object() {
+    var equivalents = <DartType>[
+      objectStar,
+    ];
+
+    var supertypes = <DartType>[
+      objectQuestion,
+      dynamicType,
+      voidNone,
+    ];
+
+    var subtypes = <DartType>[
+      bottomNone,
+    ];
+
+    var unrelated = <DartType>[
+      doubleQuestion,
+      numQuestion,
+      intQuestion,
+      nullNone,
+    ];
+
+    _checkGroups(
+      objectNone,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+      subtypes: subtypes,
+    );
+  }
+}
+
+@reflectiveTest
+class SubtypeTest extends _SubtypingTestBase {
+  Map<String, DartType> _types = {};
+
+  void assertExpectedString(TypeImpl type, String expectedString) {
+    if (expectedString != null) {
+      var typeStr = _typeStr(type);
+
+      var typeParameterCollector = _TypeParameterCollector();
+      DartTypeVisitor.visit(type, typeParameterCollector);
+      for (var typeParameter in typeParameterCollector.typeParameters) {
+        if (typeParameter is TypeParameterMember) {
+          var boundTypeImpl = typeParameter.bound as TypeImpl;
+          var boundTypeStr = boundTypeImpl.toString(withNullability: true);
+          typeStr += ', ${typeParameter.name} & ' + boundTypeStr;
+        }
+      }
+
+      expect(typeStr, expectedString);
+    }
+  }
+
+  InterfaceType comparableQuestion(DartType type) {
+    return comparableElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType comparableStar(DartType type) {
+    return comparableElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  void isNotSubtype(
+    DartType T0,
+    DartType T1, {
+    String strT0,
+    String strT1,
+  }) {
+    assertExpectedString(T0, strT0);
+    assertExpectedString(T1, strT1);
+    expect(typeSystem.isSubtypeOf(T0, T1), isFalse);
+  }
+
+  void isNotSubtype2(
+    String strT0,
+    String strT1,
+  ) {
+    var T0 = _getTypeByStr(strT0);
+    var T1 = _getTypeByStr(strT1);
+    expect(typeSystem.isSubtypeOf(T0, T1), isFalse);
+  }
+
+  void isNotSubtype3({
+    String strT0,
+    String strT1,
+  }) {
+    isNotSubtype2(strT0, strT1);
+  }
+
+  void isSubtype(
+    DartType T0,
+    DartType T1, {
+    String strT0,
+    String strT1,
+  }) {
+    assertExpectedString(T0, strT0);
+    assertExpectedString(T1, strT1);
+    expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
+  }
+
+  void isSubtype2(
+    String strT0,
+    String strT1,
+  ) {
+    var T0 = _getTypeByStr(strT0);
+    var T1 = _getTypeByStr(strT1);
+    expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
+  }
+
+  void isSubtype3({
+    String strT0,
+    String strT1,
+  }) {
+    isSubtype2(strT0, strT1);
+  }
+
+  InterfaceType iterableStar(DartType type) {
+    return typeProvider.iterableElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType listNone(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType listQuestion(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType listStar(DartType type) {
+    return typeProvider.listElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  TypeParameterMember promoteTypeParameter(
+    TypeParameterElement element,
+    DartType bound,
+  ) {
+    assert(element is! TypeParameterMember);
+    return TypeParameterMember(element, null, bound);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    _defineTypes();
+  }
+
+  test_bottom_01() {
+    isSubtype(bottomNone, numNone, strT0: 'Never', strT1: 'num');
+  }
+
+  test_bottom_02() {
+    isSubtype(bottomNone, numStar, strT0: 'Never', strT1: 'num*');
+  }
+
+  test_bottom_03() {
+    isSubtype(bottomNone, numQuestion, strT0: 'Never', strT1: 'num?');
+  }
+
+  test_bottom_04() {
+    isSubtype(bottomNone, nullQuestion, strT0: 'Never', strT1: 'Null?');
+  }
+
+  test_bottom_05() {
+    isSubtype(bottomNone, bottomNone, strT0: 'Never', strT1: 'Never');
+  }
+
+  test_bottom_06() {
+    isSubtype(bottomNone, neverNone, strT0: 'Never', strT1: 'Never');
+  }
+
+  test_functionType_01() {
+    var E0 = typeParameter('E0');
+    var E1 = typeParameter('E1', bound: numStar);
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: numStar),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0 Function<E0>(E0, num*)*',
+      strT1: 'E1* Function<E1 extends num*>(E1*, E1*)*',
+    );
+  }
+
+  test_functionType_02() {
+    var E0 = typeParameter('E0', bound: numStar);
+    var E1 = typeParameter('E1', bound: intStar);
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function<E0 extends num*>(E0*)*',
+      strT1: 'int* Function<E1 extends int*>(E1*)*',
+    );
+  }
+
+  test_functionType_03() {
+    var E0 = typeParameter('E0', bound: numStar);
+    var E1 = typeParameter('E1', bound: intStar);
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0* Function<E0 extends num*>(E0*)*',
+      strT1: 'E1* Function<E1 extends int*>(E1*)*',
+    );
+  }
+
+  test_functionType_04() {
+    var E0 = typeParameter('E0', bound: numStar);
+    var E1 = typeParameter('E1', bound: intStar);
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0* Function<E0 extends num*>(int*)*',
+      strT1: 'E1* Function<E1 extends int*>(int*)*',
+    );
+  }
+
+  test_functionType_05() {
+    var E0 = typeParameter('E0', bound: numStar);
+    var E1 = typeParameter('E1', bound: numStar);
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'E0* Function<E0 extends num*>(E0*)*',
+      strT1: 'num* Function<E1 extends num*>(E1*)*',
+    );
+  }
+
+  test_functionType_06() {
+    var E0 = typeParameter('E0', bound: intStar);
+    var E1 = typeParameter('E1', bound: intStar);
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'E0* Function<E0 extends int*>(E0*)*',
+      strT1: 'num* Function<E1 extends int*>(E1*)*',
+    );
+  }
+
+  test_functionType_07() {
+    var E0 = typeParameter('E0', bound: intStar);
+    var E1 = typeParameter('E1', bound: intStar);
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'E0* Function<E0 extends int*>(E0*)*',
+      strT1: 'int* Function<E1 extends int*>(E1*)*',
+    );
+  }
+
+  test_functionType_08() {
+    var E0 = typeParameter('E0');
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function<E0>(int*)*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_functionType_09() {
+    var E0 = typeParameter('E0');
+    var F0 = typeParameter('F0');
+    var E1 = typeParameter('E1');
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0, F0],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function<E0,F0>(int*)*',
+      strT1: 'int* Function<E1>(int*)*',
+    );
+  }
+
+  test_functionType_10() {
+    var E0 = typeParameter('E0');
+    E0.bound = listStar(
+      typeParameterTypeStar(E0),
+    );
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0* Function<E0 extends List<E0*>*>(E0*)*',
+      strT1: 'E1* Function<E1 extends List<E1*>*>(E1*)*',
+    );
+  }
+
+  test_functionType_11() {
+    var E0 = typeParameter('E0');
+    E0.bound = iterableStar(
+      typeParameterTypeStar(E0),
+    );
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E0)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0* Function<E0 extends Iterable<E0*>*>(E0*)*',
+      strT1: 'E1* Function<E1 extends List<E1*>*>(E1*)*',
+    );
+  }
+
+  test_functionType_12() {
+    var E0 = typeParameter('E0');
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: listStar(objectStar)),
+        ],
+        returnType: typeParameterTypeStar(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'E0* Function<E0>(E0, List<Object*>*)*',
+      strT1: 'E1* Function<E1 extends List<E1*>*>(E1*, E1*)*',
+    );
+  }
+
+  test_functionType_13() {
+    var E0 = typeParameter('E0');
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: listStar(objectStar)),
+        ],
+        returnType: listStar(
+          typeParameterTypeNone(E0),
+        ),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'List<E0>* Function<E0>(E0, List<Object*>*)*',
+      strT1: 'E1* Function<E1 extends List<E1*>*>(E1*, E1*)*',
+    );
+  }
+
+  test_functionType_14() {
+    var E0 = typeParameter('E0');
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: listStar(objectStar)),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: typeParameterTypeStar(E1),
+      ),
+      strT0: 'int* Function<E0>(E0, List<Object*>*)*',
+      strT1: 'E1* Function<E1 extends List<E1*>*>(E1*, E1*)*',
+    );
+  }
+
+  test_functionType_15() {
+    var E0 = typeParameter('E0');
+
+    var E1 = typeParameter('E1');
+    E1.bound = listStar(
+      typeParameterTypeStar(E1),
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: listStar(objectStar)),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeStar(E1)),
+          requiredParameter(type: typeParameterTypeStar(E1)),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'E0 Function<E0>(E0, List<Object*>*)*',
+      strT1: 'void Function<E1 extends List<E1*>*>(E1*, E1*)*',
+    );
+  }
+
+  test_functionType_16() {
+    isSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionStar,
+      strT0: 'int* Function()*',
+      strT1: 'Function*',
+    );
+  }
+
+  test_functionType_17() {
+    isNotSubtype(
+      functionStar,
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      strT0: 'Function*',
+      strT1: 'int* Function()*',
+    );
+  }
+
+  test_functionType_18() {
+    isSubtype(
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      strT0: 'dynamic Function()*',
+      strT1: 'dynamic Function()*',
+    );
+  }
+
+  test_functionType_19() {
+    isSubtype(
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'dynamic Function()*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_functionType_20() {
+    isSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      strT0: 'void Function()*',
+      strT1: 'dynamic Function()*',
+    );
+  }
+
+  test_functionType_21() {
+    isSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_functionType_22() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      strT0: 'void Function()*',
+      strT1: 'int* Function()*',
+    );
+  }
+
+  test_functionType_23() {
+    isSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'void Function()*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_functionType_24() {
+    isSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'int* Function()*',
+    );
+  }
+
+  test_functionType_25() {
+    isSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        returnType: objectStar,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'Object* Function()*',
+    );
+  }
+
+  test_functionType_26() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        returnType: doubleStar,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'double* Function()*',
+    );
+  }
+
+  test_functionType_27() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_28() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'void Function()*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_functionType_29() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function()*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_30() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function(int*)*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_functionType_31() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: objectStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: objectStar,
+      ),
+      strT0: 'int* Function(Object*)*',
+      strT1: 'Object* Function(int*)*',
+    );
+  }
+
+  test_functionType_32() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: doubleStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function(int*)*',
+      strT1: 'int* Function(double*)*',
+    );
+  }
+
+  test_functionType_33() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function()*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_functionType_34() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function(int*)*',
+      strT1: 'int* Function(int*, int*)*',
+    );
+  }
+
+  test_functionType_35() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'int* Function(int*, int*)*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_functionType_36() {
+    var f = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            returnType: voidNone,
+          ),
+        ),
+      ],
+      returnType: voidNone,
+    );
+    var g = functionTypeStar(
+      parameters: [
+        requiredParameter(
+          type: functionTypeStar(
+            parameters: [
+              requiredParameter(type: intStar),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ],
+      returnType: voidNone,
+    );
+
+    isNotSubtype(
+      f,
+      g,
+      strT0: 'void Function(void Function()*)*',
+      strT1: 'void Function(void Function(int*)*)*',
+    );
+
+    isNotSubtype(
+      g,
+      f,
+      strT0: 'void Function(void Function(int*)*)*',
+      strT1: 'void Function(void Function()*)*',
+    );
+  }
+
+  test_functionType_37() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_functionType_38() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_39() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function(int*)*',
+      strT1: 'void Function([int*])*',
+    );
+  }
+
+  test_functionType_40() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function([int*])*',
+    );
+  }
+
+  test_functionType_41() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: objectStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([Object*])*',
+      strT1: 'void Function([int*])*',
+    );
+  }
+
+  test_functionType_42() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: objectStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function([Object*])*',
+    );
+  }
+
+  test_functionType_43() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function(int*, [int*])*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_44() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function(int*, [int*])*',
+      strT1: 'void Function(int*, [int*])*',
+    );
+  }
+
+  test_functionType_45() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*, int*])*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_46() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*, int*])*',
+      strT1: 'void Function(int*, [int*])*',
+    );
+  }
+
+  test_functionType_47() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*, int*])*',
+      strT1: 'void Function(int*, [int*, int*])*',
+    );
+  }
+
+  test_functionType_48() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*, int*, int*])*',
+      strT1: 'void Function(int*, [int*, int*])*',
+    );
+  }
+
+  test_functionType_49() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: doubleStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function(double*)*',
+    );
+  }
+
+  test_functionType_50() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*])*',
+      strT1: 'void Function([int*, int*])*',
+    );
+  }
+
+  test_functionType_51() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([int*, int*])*',
+      strT1: 'void Function([int*])*',
+    );
+  }
+
+  test_functionType_52() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: objectStar),
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          positionalParameter(type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function([Object*, int*])*',
+      strT1: 'void Function([int*])*',
+    );
+  }
+
+  test_functionType_53() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_functionType_54() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function(int*)*',
+    );
+  }
+
+  test_functionType_55() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function(int*)*',
+      strT1: 'void Function({a: int*})*',
+    );
+  }
+
+  test_functionType_56() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function({a: int*})*',
+    );
+  }
+
+  test_functionType_57() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'b', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function({b: int*})*',
+    );
+  }
+
+  test_functionType_58() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: objectStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: Object*})*',
+      strT1: 'void Function({a: int*})*',
+    );
+  }
+
+  test_functionType_59() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: objectStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function({a: Object*})*',
+    );
+  }
+
+  test_functionType_60() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function(int*, {a: int*})*',
+      strT1: 'void Function(int*, {a: int*})*',
+    );
+  }
+
+  test_functionType_61() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: doubleStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function({a: double*})*',
+    );
+  }
+
+  test_functionType_62() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*})*',
+      strT1: 'void Function({a: int*, b: int*})*',
+    );
+  }
+
+  test_functionType_63() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*, b: int*})*',
+      strT1: 'void Function({a: int*})*',
+    );
+  }
+
+  test_functionType_64() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*, b: int*, c: int*})*',
+      strT1: 'void Function({a: int*, c: int*})*',
+    );
+  }
+
+  test_functionType_65() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'c', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({c: int*, b: int*, a: int*})*',
+      strT1: 'void Function({a: int*, c: int*})*',
+    );
+  }
+
+  test_functionType_66() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*, b: int*, c: int*})*',
+      strT1: 'void Function({b: int*, c: int*})*',
+    );
+  }
+
+  test_functionType_67() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'c', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({c: int*, b: int*, a: int*})*',
+      strT1: 'void Function({b: int*, c: int*})*',
+    );
+  }
+
+  test_functionType_68() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'a', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({a: int*, b: int*, c: int*})*',
+      strT1: 'void Function({c: int*})*',
+    );
+  }
+
+  test_functionType_69() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'c', type: intStar),
+          namedParameter(name: 'b', type: intStar),
+          namedParameter(name: 'a', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'c', type: intStar),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function({c: int*, b: int*, a: int*})*',
+      strT1: 'void Function({c: int*})*',
+    );
+  }
+
+  test_functionType_70() {
+    isSubtype(
+      functionTypeNone(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      objectNone,
+      strT0: 'num* Function(int*)',
+      strT1: 'Object',
+    );
+  }
+
+  test_functionType_71() {
+    isSubtype(
+      functionTypeStar(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      objectNone,
+      strT0: 'num* Function(int*)*',
+      strT1: 'Object',
+    );
+  }
+
+  test_functionType_72() {
+    isNotSubtype(
+      functionTypeQuestion(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      objectNone,
+      strT0: 'num* Function(int*)?',
+      strT1: 'Object',
+    );
+  }
+
+  test_functionType_generic_nested() {
+    var E0 = typeParameter('E0');
+    var F0 = typeParameter('F0');
+    var E1 = typeParameter('E1');
+    var F1 = typeParameter('F1');
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(E0)),
+          ],
+          returnType: typeParameterTypeNone(E0),
+        ),
+      ),
+      functionTypeStar(
+        typeFormals: [F1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(F1)),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(F1)),
+          ],
+          returnType: typeParameterTypeNone(F1),
+        ),
+      ),
+      strT0: 'E0 Function(E0)* Function<E0>(E0)*',
+      strT1: 'F1 Function(F1)* Function<F1>(F1)*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(
+            type: functionTypeStar(
+              parameters: [
+                requiredParameter(type: intStar),
+                requiredParameter(type: typeParameterTypeNone(E0)),
+              ],
+              returnType: typeParameterTypeNone(E0),
+            ),
+          ),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+          requiredParameter(
+            type: functionTypeStar(
+              parameters: [
+                requiredParameter(type: numStar),
+                requiredParameter(type: typeParameterTypeNone(E1)),
+              ],
+              returnType: typeParameterTypeNone(E1),
+            ),
+          ),
+        ],
+        returnType: typeParameterTypeNone(E1),
+      ),
+      strT0: 'E0 Function<E0>(E0, E0 Function(int*, E0)*)*',
+      strT1: 'E1 Function<E1>(E1, E1 Function(num*, E1)*)*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0, F0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(F0)),
+          ],
+          returnType: typeParameterTypeNone(E0),
+        ),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+        ],
+        returnType: functionTypeStar(
+          typeFormals: [F1],
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(F1)),
+          ],
+          returnType: typeParameterTypeNone(E1),
+        ),
+      ),
+      strT0: 'E0 Function(F0)* Function<E0,F0>(E0)*',
+      strT1: 'E1 Function<F1>(F1)* Function<E1>(E1)*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0, F0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(F0)),
+          ],
+          returnType: typeParameterTypeNone(E0),
+        ),
+      ),
+      functionTypeStar(
+        typeFormals: [F1, E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: typeParameterTypeNone(F1)),
+          ],
+          returnType: typeParameterTypeNone(E1),
+        ),
+      ),
+      strT0: 'E0 Function(F0)* Function<E0,F0>(E0)*',
+      strT1: 'E1 Function(F1)* Function<F1,E1>(E1)*',
+    );
+  }
+
+  test_functionType_generic_required() {
+    var E0 = typeParameter('E');
+    var E1 = typeParameter('E');
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function<E>(E)*',
+      strT1: 'num* Function<E>(E)*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: typeParameterTypeNone(E1),
+      ),
+      strT0: 'E Function<E>(num*)*',
+      strT1: 'E Function<E>(int*)*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: numStar),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+          requiredParameter(type: intStar),
+        ],
+        returnType: typeParameterTypeNone(E1),
+      ),
+      strT0: 'E Function<E>(E, num*)*',
+      strT1: 'E Function<E>(E, int*)*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        typeFormals: [E0],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E0)),
+          requiredParameter(type: numStar),
+        ],
+        returnType: typeParameterTypeNone(E0),
+      ),
+      functionTypeStar(
+        typeFormals: [E1],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(E1)),
+          requiredParameter(type: typeParameterTypeNone(E1)),
+        ],
+        returnType: typeParameterTypeNone(E1),
+      ),
+      strT0: 'E Function<E>(E, num*)*',
+      strT1: 'E Function<E>(E, E)*',
+    );
+  }
+
+  test_functionType_notGeneric_functionReturnType() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: numStar),
+          ],
+          returnType: numStar,
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: intStar),
+          ],
+          returnType: numStar,
+        ),
+      ),
+      strT0: 'num* Function(num*)* Function(num*)*',
+      strT1: 'num* Function(int*)* Function(num*)*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: intStar),
+          ],
+          returnType: intStar,
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: functionTypeStar(
+          parameters: [
+            requiredParameter(type: numStar),
+          ],
+          returnType: numStar,
+        ),
+      ),
+      strT0: 'int* Function(int*)* Function(int*)*',
+      strT1: 'num* Function(num*)* Function(num*)*',
+    );
+  }
+
+  test_functionType_notGeneric_named() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: intStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'num* Function({x: num*})*',
+      strT1: 'num* Function({x: int*})*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+          namedParameter(name: 'x', type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+          namedParameter(name: 'x', type: intStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'num* Function(num*, {x: num*})*',
+      strT1: 'num* Function(int*, {x: int*})*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: numStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function({x: num*})*',
+      strT1: 'num* Function({x: num*})*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          namedParameter(name: 'x', type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function({x: int*})*',
+      strT1: 'num* Function({x: num*})*',
+    );
+  }
+
+  test_functionType_notGeneric_required() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'num* Function(num*)*',
+      strT1: 'num* Function(int*)*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function(num*)*',
+      strT1: 'num* Function(num*)*',
+    );
+
+    isSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function(num*)*',
+      strT1: 'num* Function(int*)*',
+    );
+
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: numStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'int* Function(int*)*',
+      strT1: 'num* Function(num*)*',
+    );
+
+    isSubtype(
+      nullQuestion,
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: numStar,
+      ),
+      strT0: 'Null?',
+      strT1: 'num* Function(int*)*',
+    );
+  }
+
+  test_futureOr_01() {
+    isSubtype(
+      intStar,
+      futureOrStar(intStar),
+      strT0: 'int*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_02() {
+    isSubtype(
+      intStar,
+      futureOrStar(numStar),
+      strT0: 'int*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_03() {
+    isSubtype(
+      futureStar(intStar),
+      futureOrStar(intStar),
+      strT0: 'Future<int*>*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_04() {
+    isSubtype(
+      futureStar(intStar),
+      futureOrStar(numStar),
+      strT0: 'Future<int*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_05() {
+    isSubtype(
+      futureStar(intStar),
+      futureOrStar(objectStar),
+      strT0: 'Future<int*>*',
+      strT1: 'FutureOr<Object*>*',
+    );
+  }
+
+  test_futureOr_06() {
+    isSubtype(
+      futureOrStar(intStar),
+      futureOrStar(intStar),
+      strT0: 'FutureOr<int*>*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_07() {
+    isSubtype(
+      futureOrStar(intStar),
+      futureOrStar(numStar),
+      strT0: 'FutureOr<int*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_08() {
+    isSubtype(
+      futureOrStar(intStar),
+      objectStar,
+      strT0: 'FutureOr<int*>*',
+      strT1: 'Object*',
+    );
+  }
+
+  test_futureOr_09() {
+    isNotSubtype(
+      intStar,
+      futureOrStar(doubleStar),
+      strT0: 'int*',
+      strT1: 'FutureOr<double*>*',
+    );
+  }
+
+  test_futureOr_10() {
+    isNotSubtype(
+      futureOrStar(doubleStar),
+      intStar,
+      strT0: 'FutureOr<double*>*',
+      strT1: 'int*',
+    );
+  }
+
+  test_futureOr_11() {
+    isNotSubtype(
+      futureOrStar(intStar),
+      futureStar(numStar),
+      strT0: 'FutureOr<int*>*',
+      strT1: 'Future<num*>*',
+    );
+  }
+
+  test_futureOr_12() {
+    isNotSubtype(
+      futureOrStar(intStar),
+      numStar,
+      strT0: 'FutureOr<int*>*',
+      strT1: 'num*',
+    );
+  }
+
+  test_futureOr_13() {
+    isSubtype(
+      nullQuestion,
+      futureOrStar(intStar),
+      strT0: 'Null?',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_14() {
+    isSubtype(
+      nullQuestion,
+      futureStar(intStar),
+      strT0: 'Null?',
+      strT1: 'Future<int*>*',
+    );
+  }
+
+  test_futureOr_15() {
+    isSubtype(
+      dynamicNone,
+      futureOrStar(dynamicNone),
+      strT0: 'dynamic',
+      strT1: 'FutureOr<dynamic>*',
+    );
+  }
+
+  test_futureOr_16() {
+    isNotSubtype(
+      dynamicNone,
+      futureOrStar(stringStar),
+      strT0: 'dynamic',
+      strT1: 'FutureOr<String*>*',
+    );
+  }
+
+  test_futureOr_17() {
+    isSubtype(
+      voidNone,
+      futureOrStar(voidNone),
+      strT0: 'void',
+      strT1: 'FutureOr<void>*',
+    );
+  }
+
+  test_futureOr_18() {
+    isNotSubtype(
+      voidNone,
+      futureOrStar(stringStar),
+      strT0: 'void',
+      strT1: 'FutureOr<String*>*',
+    );
+  }
+
+  test_futureOr_19() {
+    var E = typeParameter('E');
+
+    isSubtype(
+      typeParameterTypeNone(E),
+      futureOrStar(
+        typeParameterTypeNone(E),
+      ),
+      strT0: 'E',
+      strT1: 'FutureOr<E>*',
+    );
+  }
+
+  test_futureOr_20() {
+    var E = typeParameter('E');
+
+    isNotSubtype(
+      typeParameterTypeNone(E),
+      futureOrStar(stringStar),
+      strT0: 'E',
+      strT1: 'FutureOr<String*>*',
+    );
+  }
+
+  test_futureOr_21() {
+    isSubtype(
+      functionTypeStar(
+        parameters: [],
+        returnType: stringStar,
+      ),
+      futureOrStar(
+        functionTypeStar(
+          parameters: [],
+          returnType: voidNone,
+        ),
+      ),
+      strT0: 'String* Function()*',
+      strT1: 'FutureOr<void Function()*>*',
+    );
+  }
+
+  test_futureOr_22() {
+    isNotSubtype(
+      functionTypeStar(
+        parameters: [],
+        returnType: voidNone,
+      ),
+      futureOrStar(
+        functionTypeStar(
+          parameters: [],
+          returnType: stringStar,
+        ),
+      ),
+      strT0: 'void Function()*',
+      strT1: 'FutureOr<String* Function()*>*',
+    );
+  }
+
+  test_futureOr_23() {
+    isNotSubtype(
+      futureOrStar(numStar),
+      futureOrStar(intStar),
+      strT0: 'FutureOr<num*>*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_24() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, intStar);
+
+    isSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(numStar),
+      strT0: 'T, T & int*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_25() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, futureStar(numStar));
+
+    isSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(numStar),
+      strT0: 'T, T & Future<num*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_26() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, futureStar(intStar));
+
+    isSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(numStar),
+      strT0: 'T, T & Future<int*>*',
+      strT1: 'FutureOr<num*>*',
+    );
+  }
+
+  test_futureOr_27() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, numStar);
+
+    isNotSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(intStar),
+      strT0: 'T, T & num*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_28() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, futureStar(numStar));
+
+    isNotSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(intStar),
+      strT0: 'T, T & Future<num*>*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_29() {
+    var T = typeParameter('T');
+    var Tp = promoteTypeParameter(T, futureOrStar(numStar));
+
+    isNotSubtype(
+      typeParameterTypeNone(Tp),
+      futureOrStar(intStar),
+      strT0: 'T, T & FutureOr<num*>*',
+      strT1: 'FutureOr<int*>*',
+    );
+  }
+
+  test_futureOr_30() {
+    isSubtype(
+      futureOrStar(objectStar),
+      futureOrStar(
+        futureOrStar(objectStar),
+      ),
+      strT0: 'FutureOr<Object*>*',
+      strT1: 'FutureOr<FutureOr<Object*>*>*',
+    );
+  }
+
+  test_interfaceType_01() {
+    isSubtype(intStar, intStar, strT0: 'int*', strT1: 'int*');
+  }
+
+  test_interfaceType_02() {
+    isSubtype(intStar, numStar, strT0: 'int*', strT1: 'num*');
+  }
+
+  test_interfaceType_03() {
+    isSubtype(
+      intStar,
+      comparableStar(numStar),
+      strT0: 'int*',
+      strT1: 'Comparable<num*>*',
+    );
+  }
+
+  test_interfaceType_04() {
+    isSubtype(intStar, objectStar, strT0: 'int*', strT1: 'Object*');
+  }
+
+  test_interfaceType_05() {
+    isSubtype(doubleStar, numStar, strT0: 'double*', strT1: 'num*');
+  }
+
+  test_interfaceType_06() {
+    isNotSubtype(intStar, doubleStar, strT0: 'int*', strT1: 'double*');
+  }
+
+  test_interfaceType_07() {
+    isNotSubtype(
+      intStar,
+      comparableStar(intStar),
+      strT0: 'int*',
+      strT1: 'Comparable<int*>*',
+    );
+  }
+
+  test_interfaceType_08() {
+    isNotSubtype(
+      intStar,
+      iterableStar(intStar),
+      strT0: 'int*',
+      strT1: 'Iterable<int*>*',
+    );
+  }
+
+  test_interfaceType_09() {
+    isNotSubtype(
+      comparableStar(intStar),
+      iterableStar(intStar),
+      strT0: 'Comparable<int*>*',
+      strT1: 'Iterable<int*>*',
+    );
+  }
+
+  test_interfaceType_10() {
+    isSubtype(
+      listStar(intStar),
+      listStar(intStar),
+      strT0: 'List<int*>*',
+      strT1: 'List<int*>*',
+    );
+  }
+
+  test_interfaceType_11() {
+    isSubtype(
+      listStar(intStar),
+      iterableStar(intStar),
+      strT0: 'List<int*>*',
+      strT1: 'Iterable<int*>*',
+    );
+  }
+
+  test_interfaceType_12() {
+    isSubtype(
+      listStar(intStar),
+      listStar(numStar),
+      strT0: 'List<int*>*',
+      strT1: 'List<num*>*',
+    );
+  }
+
+  test_interfaceType_13() {
+    isSubtype(
+      listStar(intStar),
+      iterableStar(numStar),
+      strT0: 'List<int*>*',
+      strT1: 'Iterable<num*>*',
+    );
+  }
+
+  test_interfaceType_14() {
+    isSubtype(
+      listStar(intStar),
+      listStar(objectStar),
+      strT0: 'List<int*>*',
+      strT1: 'List<Object*>*',
+    );
+  }
+
+  test_interfaceType_15() {
+    isSubtype(
+      listStar(intStar),
+      iterableStar(objectStar),
+      strT0: 'List<int*>*',
+      strT1: 'Iterable<Object*>*',
+    );
+  }
+
+  test_interfaceType_16() {
+    isSubtype(
+      listStar(intStar),
+      objectStar,
+      strT0: 'List<int*>*',
+      strT1: 'Object*',
+    );
+  }
+
+  test_interfaceType_17() {
+    isSubtype(
+      listStar(intStar),
+      listStar(
+        comparableStar(objectStar),
+      ),
+      strT0: 'List<int*>*',
+      strT1: 'List<Comparable<Object*>*>*',
+    );
+  }
+
+  test_interfaceType_18() {
+    isSubtype(
+      listStar(intStar),
+      listStar(
+        comparableStar(numStar),
+      ),
+      strT0: 'List<int*>*',
+      strT1: 'List<Comparable<num*>*>*',
+    );
+  }
+
+  test_interfaceType_19() {
+    isSubtype(
+      listStar(intStar),
+      listStar(
+        comparableStar(
+          comparableStar(numStar),
+        ),
+      ),
+      strT0: 'List<int*>*',
+      strT1: 'List<Comparable<Comparable<num*>*>*>*',
+    );
+  }
+
+  test_interfaceType_20() {
+    isNotSubtype(
+      listStar(intStar),
+      listStar(doubleStar),
+      strT0: 'List<int*>*',
+      strT1: 'List<double*>*',
+    );
+  }
+
+  test_interfaceType_21() {
+    isNotSubtype(
+      listStar(intStar),
+      iterableStar(doubleStar),
+      strT0: 'List<int*>*',
+      strT1: 'Iterable<double*>*',
+    );
+  }
+
+  test_interfaceType_22() {
+    isNotSubtype(
+      listStar(intStar),
+      comparableStar(intStar),
+      strT0: 'List<int*>*',
+      strT1: 'Comparable<int*>*',
+    );
+  }
+
+  test_interfaceType_23() {
+    isNotSubtype(
+      listStar(intStar),
+      listStar(
+        comparableStar(intStar),
+      ),
+      strT0: 'List<int*>*',
+      strT1: 'List<Comparable<int*>*>*',
+    );
+  }
+
+  test_interfaceType_24() {
+    isNotSubtype(
+      listStar(intStar),
+      listStar(
+        comparableStar(
+          comparableStar(intStar),
+        ),
+      ),
+      strT0: 'List<int*>*',
+      strT1: 'List<Comparable<Comparable<int*>*>*>*',
+    );
+  }
+
+  test_interfaceType_25_interfaces() {
+    var A = class_(name: 'A');
+    var I = class_(name: 'I');
+
+    A.interfaces = [
+      I.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: NullabilitySuffix.none,
+      ),
+    ];
+
+    var A_none = A.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    var I_none = I.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_none, I_none, strT0: 'A', strT1: 'I');
+    isNotSubtype(I_none, A_none, strT0: 'I', strT1: 'A');
+  }
+
+  test_interfaceType_26_mixins() {
+    var A = class_(name: 'A');
+    var M = class_(name: 'M');
+
+    A.mixins = [
+      M.instantiate(
+        typeArguments: const [],
+        nullabilitySuffix: NullabilitySuffix.none,
+      ),
+    ];
+
+    var A_none = A.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+    var M_none = M.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+
+    isSubtype(A_none, M_none, strT0: 'A', strT1: 'M');
+    isNotSubtype(M_none, A_none, strT0: 'M', strT1: 'A');
+  }
+
+  test_interfaceType_27() {
+    isSubtype(numNone, objectNone, strT0: 'num', strT1: 'Object');
+  }
+
+  test_interfaceType_28() {
+    isSubtype(numStar, objectNone, strT0: 'num*', strT1: 'Object');
+  }
+
+  test_interfaceType_39() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isSubtype(
+      listNone(
+        typeParameterTypeNone(
+          promoteTypeParameter(T, intNone),
+        ),
+      ),
+      listNone(
+        typeParameterTypeNone(T),
+      ),
+      strT0: 'List<T>, T & int',
+      strT1: 'List<T>',
+    );
+  }
+
+  test_interfaceType_40() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isSubtype(
+      listNone(
+        typeParameterTypeNone(
+          promoteTypeParameter(T, intQuestion),
+        ),
+      ),
+      listNone(
+        typeParameterTypeNone(T),
+      ),
+      strT0: 'List<T>, T & int?',
+      strT1: 'List<T>',
+    );
+  }
+
+  test_multi_function_nonGeneric_oneArgument() {
+    isSubtype2('num* Function(num*)*', 'num* Function(int*)*');
+    isSubtype2('int* Function(num*)*', 'num* Function(num*)*');
+    isSubtype2('int* Function(num*)*', 'num* Function(int*)*');
+    isNotSubtype2('int* Function(int*)*', 'num* Function(num*)*');
+    isSubtype2('Null?', 'num* Function(int*)*');
+    isSubtype2('Null?', 'num* Function(int*)?');
+    isSubtype2('Never', 'num* Function(int*)');
+    isSubtype2('Never', 'num* Function(int*)*');
+    isSubtype2('Never', 'num* Function(int*)?');
+    isSubtype2('num* Function(num*)*', 'Object');
+    isSubtype2('num* Function(num*)', 'Object');
+    isNotSubtype2('num* Function(num*)?', 'Object');
+    isNotSubtype2('Null?', 'num* Function(int*)');
+    isNotSubtype2('num* Function(int*)', 'Never');
+  }
+
+  test_multi_function_nonGeneric_zeroArguments() {
+    isSubtype2('int* Function()', 'Function');
+    isSubtype2('int* Function()', 'Function*');
+    isSubtype2('int* Function()', 'Function?');
+
+    isSubtype2('int* Function()*', 'Function');
+    isSubtype2('int* Function()*', 'Function*');
+    isSubtype2('int* Function()*', 'Function?');
+
+    isNotSubtype2('int* Function()?', 'Function');
+    isSubtype2('int* Function()?', 'Function*');
+    isSubtype2('int* Function()?', 'Function?');
+
+    isSubtype2('int* Function()', 'Object');
+    isSubtype2('int* Function()', 'Object*');
+    isSubtype2('int* Function()', 'Object?');
+
+    isSubtype2('int* Function()*', 'Object');
+    isSubtype2('int* Function()*', 'Object*');
+    isSubtype2('int* Function()*', 'Object?');
+
+    isNotSubtype2('int* Function()?', 'Object');
+    isSubtype2('int* Function()?', 'Object*');
+    isSubtype2('int* Function()?', 'Object?');
+  }
+
+  test_multi_futureOr() {
+    isSubtype2('FutureOr<int>', 'Object');
+    isSubtype2('FutureOr<int>', 'Object*');
+    isSubtype2('FutureOr<int>', 'Object?');
+
+    isSubtype2('FutureOr<int>*', 'Object');
+    isSubtype2('FutureOr<int>*', 'Object*');
+    isSubtype2('FutureOr<int>*', 'Object?');
+
+    isNotSubtype2('FutureOr<int>?', 'Object');
+    isSubtype2('FutureOr<int>?', 'Object*');
+    isSubtype2('FutureOr<int>?', 'Object?');
+
+    isSubtype2('FutureOr<int*>', 'Object');
+    isSubtype2('FutureOr<int*>', 'Object*');
+    isSubtype2('FutureOr<int*>', 'Object?');
+
+    isNotSubtype2('FutureOr<int?>', 'Object');
+    isSubtype2('FutureOr<int?>', 'Object*');
+    isSubtype2('FutureOr<int?>', 'Object?');
+
+    isSubtype2('FutureOr<Future<Object>>', 'Future<Object>');
+    isNotSubtype2('FutureOr<Future<Object>>?', 'Future<Object>');
+    isNotSubtype2('FutureOr<Future<Object>?>', 'Future<Object>');
+    isNotSubtype2('FutureOr<Future<Object>?>?', 'Future<Object>');
+
+    isSubtype2('FutureOr<num>', 'Object');
+    isSubtype2('FutureOr<num>*', 'Object');
+    isNotSubtype2('FutureOr<num>?', 'Object');
+  }
+
+  test_multi_list_subTypes_superTypes() {
+    isSubtype2('List<int*>*', 'List<int*>*');
+    isSubtype2('List<int*>*', 'Iterable<int*>*');
+    isSubtype2('List<int*>*', 'List<num*>*');
+    isSubtype2('List<int*>*', 'Iterable<num*>*');
+    isSubtype2('List<int*>*', 'List<Object*>*');
+    isSubtype2('List<int*>*', 'Iterable<Object*>*');
+    isSubtype2('List<int*>*', 'Object*');
+    isSubtype2('List<int*>*', 'List<Comparable<Object*>*>*');
+    isSubtype2('List<int*>*', 'List<Comparable<num*>*>*');
+    isSubtype2('List<int*>*', 'List<Comparable<Comparable<num*>*>*>*');
+    isSubtype2('List<int*>', 'Object');
+    isSubtype2('List<int*>*', 'Object');
+    isSubtype2('Null?', 'List<int*>*');
+    isSubtype2('Null?', 'List<int*>?');
+    isSubtype2('Never', 'List<int*>');
+    isSubtype2('Never', 'List<int*>*');
+    isSubtype2('Never', 'List<int*>?');
+
+    isSubtype2('List<int>', 'List<int>');
+    isSubtype2('List<int>', 'List<int>*');
+    isSubtype2('List<int>', 'List<int>?');
+    isSubtype2('List<int>*', 'List<int>');
+    isSubtype2('List<int>*', 'List<int>*');
+    isSubtype2('List<int>*', 'List<int>?');
+    isNotSubtype2('List<int>?', 'List<int>');
+    isSubtype2('List<int>?', 'List<int>*');
+    isSubtype2('List<int>?', 'List<int>?');
+
+    isSubtype2('List<int>', 'List<int*>');
+    isSubtype2('List<int>', 'List<int?>');
+    isSubtype2('List<int*>', 'List<int>');
+    isSubtype2('List<int*>', 'List<int*>');
+    isSubtype2('List<int*>', 'List<int?>');
+    isNotSubtype2('List<int?>', 'List<int>');
+    isSubtype2('List<int?>', 'List<int*>');
+    isSubtype2('List<int?>', 'List<int?>');
+  }
+
+  test_multi_never() {
+    isSubtype2('Never', 'FutureOr<num>');
+    isSubtype2('Never', 'FutureOr<num*>');
+    isSubtype2('Never', 'FutureOr<num>*');
+    isSubtype2('Never', 'FutureOr<num?>');
+    isSubtype2('Never', 'FutureOr<num>?');
+    isNotSubtype2('FutureOr<num>', 'Never');
+  }
+
+  test_multi_num_subTypes_superTypes() {
+    isSubtype2('int*', 'num*');
+    isSubtype2('int*', 'Comparable<num*>*');
+    isSubtype2('int*', 'Comparable<Object*>*');
+    isSubtype2('int*', 'Object*');
+    isSubtype2('double*', 'num*');
+    isSubtype2('num', 'Object');
+    isSubtype2('num*', 'Object');
+    isSubtype2('Null?', 'num*');
+    isSubtype2('Null?', 'num?');
+    isSubtype2('Never', 'num');
+    isSubtype2('Never', 'num*');
+    isSubtype2('Never', 'num?');
+    isSubtype2('bottom', 'num');
+    isSubtype2('bottom', 'num*');
+    isSubtype2('bottom', 'num?');
+
+    isNotSubtype2('int*', 'double*');
+    isNotSubtype2('int*', 'Comparable<int*>*');
+    isNotSubtype2('int*', 'Iterable<int*>*');
+    isNotSubtype2('Comparable<int*>*', 'Iterable<int*>*');
+    isNotSubtype2('num?', 'Object');
+    isNotSubtype2('Null?', 'num');
+    isNotSubtype2('num', 'Never');
+  }
+
+  test_multi_object_topAndBottom() {
+    isSubtype2('bottom', 'Object');
+    isSubtype2('Never', 'Object');
+    isSubtype2('Object', 'dynamic');
+    isSubtype2('Object', 'void');
+    isSubtype2('Object', 'Object?');
+    isSubtype2('Object', 'Object*');
+    isSubtype2('Object*', 'Object');
+
+    isNotSubtype2('Object', 'bottom');
+    isNotSubtype2('Object', 'Null?');
+    isNotSubtype2('Object', 'Never');
+    isNotSubtype2('dynamic', 'Object');
+    isNotSubtype2('void', 'Object');
+    isNotSubtype2('Object?', 'Object');
+  }
+
+  test_multi_special() {
+    isNotSubtype2('dynamic', 'int');
+    isNotSubtype2('dynamic', 'int*');
+    isNotSubtype2('dynamic', 'int?');
+
+    isNotSubtype2('void', 'int');
+    isNotSubtype2('void', 'int*');
+    isNotSubtype2('void', 'int?');
+
+    isNotSubtype2('Object', 'int');
+    isNotSubtype2('Object', 'int*');
+    isNotSubtype2('Object', 'int?');
+
+    isNotSubtype2('Object*', 'int');
+    isNotSubtype2('Object*', 'int*');
+    isNotSubtype2('Object*', 'int?');
+
+    isNotSubtype2('Object?', 'int');
+    isNotSubtype2('Object?', 'int*');
+    isNotSubtype2('Object?', 'int?');
+
+    isNotSubtype2('int* Function()*', 'int*');
+  }
+
+  test_multi_topAndBottom() {
+    isSubtype2('Null?', 'Null?');
+    isNotSubtype2('Null?', 'bottom');
+    isNotSubtype2('Null?', 'Never');
+    isSubtype2('bottom', 'Null?');
+    isSubtype2('bottom', 'bottom');
+    isSubtype2('bottom', 'Never');
+    isSubtype2('Never', 'Null?');
+//    isNotSubtype2('Never', 'bottom');
+    isSubtype2('Never', 'Never');
+
+    isSubtype2('Null?', 'Never?');
+    isSubtype2('Never?', 'Null?');
+    isSubtype2('Never', 'Never?');
+    isNotSubtype2('Never?', 'Never');
+
+    isSubtype2('Object*', 'Object*');
+    isSubtype2('Object*', 'dynamic');
+    isSubtype2('Object*', 'void');
+    isSubtype2('Object*', 'Object?');
+    isSubtype2('dynamic', 'Object*');
+    isSubtype2('dynamic', 'dynamic');
+    isSubtype2('dynamic', 'void');
+    isSubtype2('dynamic', 'Object?');
+    isSubtype2('void', 'Object*');
+    isSubtype2('void', 'dynamic');
+    isSubtype2('void', 'void');
+    isSubtype2('void', 'Object?');
+    isSubtype2('Object?', 'Object*');
+    isSubtype2('Object?', 'dynamic');
+    isSubtype2('Object?', 'void');
+    isSubtype2('Object?', 'Object?');
+
+    isSubtype2('Never', 'Object?');
+    isSubtype2('Never', 'Object*');
+    isSubtype2('Never', 'dynamic');
+    isSubtype2('Never', 'void');
+    isSubtype2('bottom', 'Object?');
+    isSubtype2('bottom', 'Object*');
+    isSubtype2('bottom', 'dynamic');
+    isSubtype2('bottom', 'void');
+    isSubtype2('Null?', 'Object?');
+    isSubtype2('Null?', 'Object*');
+    isSubtype2('Null?', 'dynamic');
+    isSubtype2('Null?', 'void');
+
+    isNotSubtype2('Object?', 'Never');
+    isNotSubtype2('Object?', 'bottom');
+    isNotSubtype2('Object?', 'Null?');
+    isNotSubtype2('Object*', 'Never');
+    isNotSubtype2('Object*', 'bottom');
+    isNotSubtype2('Object*', 'Null?');
+    isNotSubtype2('dynamic', 'Never');
+    isNotSubtype2('dynamic', 'bottom');
+    isNotSubtype2('dynamic', 'Null?');
+    isNotSubtype2('void', 'Never');
+    isNotSubtype2('void', 'bottom');
+    isNotSubtype2('void', 'Null?');
+  }
+
+  test_never_01() {
+    isSubtype(
+      neverNone,
+      neverNone,
+      strT0: 'Never',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_02() {
+    isSubtype(neverNone, numNone, strT0: 'Never', strT1: 'num');
+  }
+
+  test_never_03() {
+    isSubtype(neverNone, numStar, strT0: 'Never', strT1: 'num*');
+  }
+
+  test_never_04() {
+    isSubtype(neverNone, numQuestion, strT0: 'Never', strT1: 'num?');
+  }
+
+  test_never_05() {
+    isNotSubtype(numNone, neverNone, strT0: 'num', strT1: 'Never');
+  }
+
+  test_never_06() {
+    isSubtype(
+      neverNone,
+      listNone(intStar),
+      strT0: 'Never',
+      strT1: 'List<int*>',
+    );
+  }
+
+  test_never_09() {
+    isNotSubtype(
+      numNone,
+      neverNone,
+      strT0: 'num',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_15() {
+    var T = typeParameter('T', bound: objectStar);
+
+    isSubtype(
+      neverNone,
+      typeParameterTypeStar(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'Never',
+      strT1: 'T*, T & num*',
+    );
+  }
+
+  test_never_16() {
+    var T = typeParameter('T', bound: objectStar);
+
+    isNotSubtype(
+      typeParameterTypeStar(
+        promoteTypeParameter(T, numStar),
+      ),
+      neverNone,
+      strT0: 'T*, T & num*',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_17() {
+    var T = typeParameter('T', bound: neverNone);
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      neverNone,
+      strT0: 'T',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_18() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, neverNone),
+      ),
+      neverNone,
+      strT0: 'T, T & Never',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_19() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isSubtype(
+      neverNone,
+      typeParameterTypeQuestion(T),
+      strT0: 'Never',
+      strT1: 'T?',
+    );
+  }
+
+  test_never_20() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isSubtype(
+      neverNone,
+      typeParameterTypeQuestion(T),
+      strT0: 'Never',
+      strT1: 'T?',
+    );
+  }
+
+  test_never_21() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isSubtype(
+      neverNone,
+      typeParameterTypeNone(T),
+      strT0: 'Never',
+      strT1: 'T',
+    );
+  }
+
+  test_never_22() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isSubtype(
+      neverNone,
+      typeParameterTypeNone(T),
+      strT0: 'Never',
+      strT1: 'T',
+    );
+  }
+
+  test_never_23() {
+    var T = typeParameter('T', bound: neverNone);
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      neverNone,
+      strT0: 'T',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_24() {
+    var T = typeParameter('T', bound: neverQuestion);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      neverNone,
+      strT0: 'T',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_25() {
+    var T = typeParameter('T', bound: neverNone);
+
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      neverNone,
+      strT0: 'T?',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_26() {
+    var T = typeParameter('T', bound: neverQuestion);
+
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      neverNone,
+      strT0: 'T?',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_27() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      neverNone,
+      strT0: 'T',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_28() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      neverNone,
+      strT0: 'T',
+      strT1: 'Never',
+    );
+  }
+
+  test_never_29() {
+    isSubtype(bottomNone, nullQuestion, strT0: 'Never', strT1: 'Null?');
+  }
+
+  test_null_01() {
+    isNotSubtype(
+      nullQuestion,
+      neverNone,
+      strT0: 'Null?',
+      strT1: 'Never',
+    );
+  }
+
+  test_null_02() {
+    isSubtype(
+      nullQuestion,
+      objectStar,
+      strT0: 'Null?',
+      strT1: 'Object*',
+    );
+  }
+
+  test_null_03() {
+    isSubtype(
+      nullQuestion,
+      voidNone,
+      strT0: 'Null?',
+      strT1: 'void',
+    );
+  }
+
+  test_null_04() {
+    isSubtype(
+      nullQuestion,
+      dynamicNone,
+      strT0: 'Null?',
+      strT1: 'dynamic',
+    );
+  }
+
+  test_null_05() {
+    isSubtype(
+      nullQuestion,
+      doubleStar,
+      strT0: 'Null?',
+      strT1: 'double*',
+    );
+  }
+
+  test_null_06() {
+    isSubtype(
+      nullQuestion,
+      doubleQuestion,
+      strT0: 'Null?',
+      strT1: 'double?',
+    );
+  }
+
+  test_null_07() {
+    isSubtype(
+      nullQuestion,
+      comparableStar(objectStar),
+      strT0: 'Null?',
+      strT1: 'Comparable<Object*>*',
+    );
+  }
+
+  test_null_08() {
+    var T = typeParameter('T', bound: objectStar);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(T),
+      strT0: 'Null?',
+      strT1: 'T',
+    );
+  }
+
+  test_null_09() {
+    isSubtype(
+      nullQuestion,
+      nullQuestion,
+      strT0: 'Null?',
+      strT1: 'Null?',
+    );
+  }
+
+  test_null_10() {
+    isNotSubtype(
+      nullQuestion,
+      listNone(intStar),
+      strT0: 'Null?',
+      strT1: 'List<int*>',
+    );
+  }
+
+  test_null_13() {
+    isNotSubtype(
+      nullQuestion,
+      functionTypeNone(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      strT0: 'Null?',
+      strT1: 'num* Function(int*)',
+    );
+  }
+
+  test_null_14() {
+    isSubtype(
+      nullQuestion,
+      functionTypeStar(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      strT0: 'Null?',
+      strT1: 'num* Function(int*)*',
+    );
+  }
+
+  test_null_15() {
+    isSubtype(
+      nullQuestion,
+      functionTypeQuestion(
+        returnType: numStar,
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+      ),
+      strT0: 'Null?',
+      strT1: 'num* Function(int*)?',
+    );
+  }
+
+  test_null_16() {
+    var T = typeParameter('T', bound: objectStar);
+
+    isSubtype(
+      nullQuestion,
+      typeParameterTypeStar(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'Null?',
+      strT1: 'T*, T & num*',
+    );
+  }
+
+  test_null_17() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numNone),
+      ),
+      strT0: 'Null?',
+      strT1: 'T, T & num',
+    );
+  }
+
+  test_null_18() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numQuestion),
+      ),
+      strT0: 'Null?',
+      strT1: 'T, T & num?',
+    );
+  }
+
+  test_null_19() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numNone),
+      ),
+      strT0: 'Null?',
+      strT1: 'T, T & num',
+    );
+  }
+
+  test_null_20() {
+    var T = typeParameter('T', bound: objectQuestion);
+    var S = typeParameter('S', bound: typeParameterTypeNone(T));
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          typeParameterTypeNone(S),
+        ),
+      ),
+      strT0: 'Null?',
+      strT1: 'T, T & S',
+    );
+  }
+
+  test_null_21() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isSubtype(
+      nullQuestion,
+      typeParameterTypeQuestion(T),
+      strT0: 'Null?',
+      strT1: 'T?',
+    );
+  }
+
+  test_null_22() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isSubtype(
+      nullQuestion,
+      typeParameterTypeQuestion(T),
+      strT0: 'Null?',
+      strT1: 'T?',
+    );
+  }
+
+  test_null_23() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(T),
+      strT0: 'Null?',
+      strT1: 'T',
+    );
+  }
+
+  test_null_24() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(T),
+      strT0: 'Null?',
+      strT1: 'T',
+    );
+  }
+
+  test_null_25() {
+    var T = typeParameter('T', bound: nullQuestion);
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      nullQuestion,
+      strT0: 'T',
+      strT1: 'Null?',
+    );
+  }
+
+  test_null_26() {
+    var T = typeParameter('T', bound: nullQuestion);
+
+    isSubtype(
+      typeParameterTypeQuestion(T),
+      nullQuestion,
+      strT0: 'T?',
+      strT1: 'Null?',
+    );
+  }
+
+  test_null_27() {
+    var T = typeParameter('T', bound: objectNone);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      nullQuestion,
+      strT0: 'T',
+      strT1: 'Null?',
+    );
+  }
+
+  test_null_28() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      nullQuestion,
+      strT0: 'T',
+      strT1: 'Null?',
+    );
+  }
+
+  test_null_29() {
+    isSubtype(
+      nullQuestion,
+      comparableQuestion(objectStar),
+      strT0: 'Null?',
+      strT1: 'Comparable<Object*>?',
+    );
+  }
+
+  test_null_30() {
+    isNotSubtype(nullQuestion, objectNone, strT0: 'Null?', strT1: 'Object');
+  }
+
+  test_nullabilitySuffix_01() {
+    isSubtype(intNone, intNone, strT0: 'int', strT1: 'int');
+    isSubtype(intNone, intQuestion, strT0: 'int', strT1: 'int?');
+    isSubtype(intNone, intStar, strT0: 'int', strT1: 'int*');
+
+    isNotSubtype(intQuestion, intNone, strT0: 'int?', strT1: 'int');
+    isSubtype(intQuestion, intQuestion, strT0: 'int?', strT1: 'int?');
+    isSubtype(intQuestion, intStar, strT0: 'int?', strT1: 'int*');
+
+    isSubtype(intStar, intNone, strT0: 'int*', strT1: 'int');
+    isSubtype(intStar, intQuestion, strT0: 'int*', strT1: 'int?');
+    isSubtype(intStar, intStar, strT0: 'int*', strT1: 'int*');
+  }
+
+  test_nullabilitySuffix_05() {
+    isSubtype(
+      functionTypeNone(
+        parameters: [
+          requiredParameter(type: intNone),
+        ],
+        returnType: voidNone,
+      ),
+      objectNone,
+      strT0: 'void Function(int)',
+      strT1: 'Object',
+    );
+  }
+
+  test_nullabilitySuffix_11() {
+    isSubtype(
+      intQuestion,
+      intQuestion,
+      strT0: 'int?',
+      strT1: 'int?',
+    );
+  }
+
+  test_nullabilitySuffix_12() {
+    isSubtype(
+      intStar,
+      intStar,
+      strT0: 'int*',
+      strT1: 'int*',
+    );
+  }
+
+  test_nullabilitySuffix_13() {
+    var f = functionTypeQuestion(
+      parameters: [
+        requiredParameter(type: intNone),
+      ],
+      returnType: intNone,
+    );
+    isSubtype(
+      f,
+      f,
+      strT0: 'int Function(int)?',
+      strT1: 'int Function(int)?',
+    );
+  }
+
+  test_nullabilitySuffix_14() {
+    var f = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intNone),
+      ],
+      returnType: intNone,
+    );
+    isSubtype(
+      f,
+      f,
+      strT0: 'int Function(int)*',
+      strT1: 'int Function(int)*',
+    );
+  }
+
+  test_nullabilitySuffix_15() {
+    var f = functionTypeNone(
+      parameters: [
+        requiredParameter(type: intNone),
+        requiredParameter(type: intStar),
+        requiredParameter(type: intQuestion),
+      ],
+      returnType: intQuestion,
+    );
+    isSubtype(
+      f,
+      f,
+      strT0: 'int? Function(int, int*, int?)',
+      strT1: 'int? Function(int, int*, int?)',
+    );
+  }
+
+  test_nullabilitySuffix_16() {
+    var type = listQuestion(intNone);
+    isSubtype(
+      type,
+      type,
+      strT0: 'List<int>?',
+      strT1: 'List<int>?',
+    );
+  }
+
+  test_nullabilitySuffix_17() {
+    var type = listQuestion(intQuestion);
+    isSubtype(
+      type,
+      type,
+      strT0: 'List<int?>?',
+      strT1: 'List<int?>?',
+    );
+  }
+
+  test_nullabilitySuffix_18() {
+    var T = typeParameter('T', bound: objectStar);
+    var type = typeParameterTypeNone(
+      promoteTypeParameter(T, intQuestion),
+    );
+    isSubtype(
+      type,
+      type,
+      strT0: 'T, T & int?',
+      strT1: 'T, T & int?',
+    );
+  }
+
+  test_nullabilitySuffix_19() {
+    var T = typeParameter('T', bound: objectNone);
+    var type = typeParameterTypeQuestion(
+      promoteTypeParameter(T, intQuestion),
+    );
+    isSubtype(
+      type,
+      type,
+      strT0: 'T?, T & int?',
+      strT1: 'T?, T & int?',
+    );
+  }
+
+  test_special_01() {
+    isNotSubtype(
+      dynamicNone,
+      intStar,
+      strT0: 'dynamic',
+      strT1: 'int*',
+    );
+  }
+
+  test_special_02() {
+    isNotSubtype(
+      voidNone,
+      intStar,
+      strT0: 'void',
+      strT1: 'int*',
+    );
+  }
+
+  test_special_03() {
+    isNotSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      intStar,
+      strT0: 'int* Function()*',
+      strT1: 'int*',
+    );
+  }
+
+  test_special_04() {
+    isNotSubtype(
+      intStar,
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      strT0: 'int*',
+      strT1: 'int* Function()*',
+    );
+  }
+
+  test_special_06() {
+    isSubtype(
+      functionTypeStar(
+        returnType: intStar,
+      ),
+      objectStar,
+      strT0: 'int* Function()*',
+      strT1: 'Object*',
+    );
+  }
+
+  test_special_07() {
+    isSubtype(
+      objectStar,
+      objectStar,
+      strT0: 'Object*',
+      strT1: 'Object*',
+    );
+  }
+
+  test_special_08() {
+    isSubtype(
+      objectStar,
+      dynamicNone,
+      strT0: 'Object*',
+      strT1: 'dynamic',
+    );
+  }
+
+  test_special_09() {
+    isSubtype(
+      objectStar,
+      voidNone,
+      strT0: 'Object*',
+      strT1: 'void',
+    );
+  }
+
+  test_special_10() {
+    isSubtype(
+      dynamicNone,
+      objectStar,
+      strT0: 'dynamic',
+      strT1: 'Object*',
+    );
+  }
+
+  test_special_11() {
+    isSubtype(
+      dynamicNone,
+      dynamicNone,
+      strT0: 'dynamic',
+      strT1: 'dynamic',
+    );
+  }
+
+  test_special_12() {
+    isSubtype(
+      dynamicNone,
+      voidNone,
+      strT0: 'dynamic',
+      strT1: 'void',
+    );
+  }
+
+  test_special_13() {
+    isSubtype(
+      voidNone,
+      objectStar,
+      strT0: 'void',
+      strT1: 'Object*',
+    );
+  }
+
+  test_special_14() {
+    isSubtype(
+      voidNone,
+      dynamicNone,
+      strT0: 'void',
+      strT1: 'dynamic',
+    );
+  }
+
+  test_special_15() {
+    isSubtype(
+      voidNone,
+      voidNone,
+      strT0: 'void',
+      strT1: 'void',
+    );
+  }
+
+  test_top_01() {
+    var S = typeParameter('S', bound: objectStar);
+    var T = typeParameter('T', bound: voidNone);
+    var U = typeParameter('U', bound: dynamicNone);
+    var V = typeParameter('V', bound: objectStar);
+
+    isSubtype(
+      functionTypeStar(
+        typeFormals: [S, T],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(S)),
+          requiredParameter(type: typeParameterTypeNone(T)),
+        ],
+        returnType: voidNone,
+      ),
+      functionTypeStar(
+        typeFormals: [U, V],
+        parameters: [
+          requiredParameter(type: typeParameterTypeNone(U)),
+          requiredParameter(type: typeParameterTypeNone(V)),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function<S extends Object*,T extends void>(S, T)*',
+      strT1: 'void Function<U extends dynamic,V extends Object*>(U, V)*',
+    );
+  }
+
+  test_top_02() {
+    var T0 = typeParameter('T0', bound: dynamicNone);
+    var T1 = typeParameter('T1', bound: objectStar);
+
+    var f = functionTypeStar(
+      typeFormals: [T0],
+      returnType: typeParameterTypeNone(T0),
+    );
+
+    var g = functionTypeStar(
+      typeFormals: [T1],
+      returnType: typeParameterTypeStar(T1),
+    );
+
+    isSubtype(
+      f,
+      g,
+      strT0: 'T0 Function<T0 extends dynamic>()*',
+      strT1: 'T1* Function<T1 extends Object*>()*',
+    );
+
+    isSubtype(
+      g,
+      f,
+      strT0: 'T1* Function<T1 extends Object*>()*',
+      strT1: 'T0 Function<T0 extends dynamic>()*',
+    );
+  }
+
+  test_top_03() {
+    var T0 = typeParameter('T0', bound: dynamicNone);
+    var T1 = typeParameter('T1', bound: objectStar);
+    var T2 = typeParameter('T2', bound: voidNone);
+
+    var h = functionTypeStar(
+      typeFormals: [T0],
+      returnType: typeParameterTypeStar(T0),
+    );
+
+    var i = functionTypeStar(
+      typeFormals: [T1],
+      returnType: typeParameterTypeStar(T1),
+    );
+
+    var j = functionTypeStar(
+      typeFormals: [T2],
+      returnType: typeParameterTypeStar(T2),
+    );
+
+    isSubtype(h, i);
+    isSubtype(h, j);
+    isSubtype(i, h);
+    isSubtype(i, j);
+    isSubtype(j, h);
+    isSubtype(h, i);
+  }
+
+  test_top_04() {
+    isNotSubtype(
+      dynamicNone,
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      strT0: 'dynamic',
+      strT1: 'dynamic Function()*',
+    );
+  }
+
+  test_top_05() {
+    isNotSubtype(
+      futureOrStar(
+        functionTypeStar(
+          returnType: voidNone,
+        ),
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'FutureOr<void Function()*>*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_top_06() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'T, T & void Function()*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_top_07() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        returnType: dynamicNone,
+      ),
+      strT0: 'T, T & void Function()*',
+      strT1: 'dynamic Function()*',
+    );
+  }
+
+  test_top_08() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        returnType: objectStar,
+      ),
+      strT0: 'T, T & void Function()*',
+      strT1: 'Object* Function()*',
+    );
+  }
+
+  test_top_09() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: voidNone),
+        ],
+        returnType: voidNone,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'void Function(void)*',
+    );
+  }
+
+  test_top_10() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: dynamicNone),
+        ],
+        returnType: dynamicNone,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'dynamic Function(dynamic)*',
+    );
+  }
+
+  test_top_11() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: objectStar),
+        ],
+        returnType: objectStar,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'Object* Function(Object*)*',
+    );
+  }
+
+  test_top_12() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: iterableStar(intStar)),
+        ],
+        returnType: dynamicNone,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'dynamic Function(Iterable<int*>*)*',
+    );
+  }
+
+  test_top_13() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: objectStar,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'Object* Function(int*)*',
+    );
+  }
+
+  test_top_14() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            parameters: [
+              requiredParameter(type: voidNone),
+            ],
+            returnType: voidNone,
+          ),
+        ),
+      ),
+      functionTypeStar(
+        parameters: [
+          requiredParameter(type: intStar),
+        ],
+        returnType: intStar,
+      ),
+      strT0: 'T, T & void Function(void)*',
+      strT1: 'int* Function(int*)*',
+    );
+  }
+
+  test_top_15() {
+    var T = typeParameter(
+      'T',
+      bound: functionTypeStar(
+        returnType: voidNone,
+      ),
+    );
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'T*',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_top_16() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'T',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_top_17() {
+    isNotSubtype(
+      voidNone,
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      strT0: 'void',
+      strT1: 'void Function()*',
+    );
+  }
+
+  test_top_18() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      dynamicNone,
+      typeParameterTypeNone(T),
+      strT0: 'dynamic',
+      strT1: 'T',
+    );
+  }
+
+  test_top_19() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      iterableStar(
+        typeParameterTypeNone(T),
+      ),
+      typeParameterTypeNone(T),
+      strT0: 'Iterable<T>*',
+      strT1: 'T',
+    );
+  }
+
+  test_top_21() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      functionTypeStar(
+        returnType: voidNone,
+      ),
+      typeParameterTypeNone(T),
+      strT0: 'void Function()*',
+      strT1: 'T',
+    );
+  }
+
+  test_top_22() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      futureOrStar(
+        typeParameterTypeNone(T),
+      ),
+      typeParameterTypeNone(T),
+      strT0: 'FutureOr<T>*',
+      strT1: 'T',
+    );
+  }
+
+  test_top_23() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      voidNone,
+      typeParameterTypeNone(T),
+      strT0: 'void',
+      strT1: 'T',
+    );
+  }
+
+  test_top_24() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      voidNone,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, voidNone),
+      ),
+      strT0: 'void',
+      strT1: 'T, T & void',
+    );
+  }
+
+  test_top_25() {
+    var T = typeParameter('T', bound: voidNone);
+
+    isNotSubtype(
+      voidNone,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, voidNone),
+      ),
+      strT0: 'void',
+      strT1: 'T, T & void',
+    );
+  }
+
+  test_typeParameter_01() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      strT0: 'T, T & int*',
+      strT1: 'T, T & int*',
+    );
+  }
+
+  test_typeParameter_02() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'T, T & int*',
+      strT1: 'T, T & num*',
+    );
+  }
+
+  test_typeParameter_03() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'T, T & num*',
+      strT1: 'T, T & num*',
+    );
+  }
+
+  test_typeParameter_04() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      strT0: 'T, T & num*',
+      strT1: 'T, T & int*',
+    );
+  }
+
+  test_typeParameter_05() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      nullQuestion,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'Null?',
+      strT1: 'T, T & num*',
+    );
+  }
+
+  test_typeParameter_06() {
+    var T = typeParameter('T', bound: intStar);
+
+    isSubtype(
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      typeParameterTypeStar(T),
+      strT0: 'T*, T & int*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_07() {
+    var T = typeParameter('T', bound: numStar);
+
+    isSubtype(
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      typeParameterTypeStar(T),
+      strT0: 'T*, T & int*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_08() {
+    var T = typeParameter('T', bound: numStar);
+
+    isSubtype(
+      typeParameterTypeStar(
+        promoteTypeParameter(T, numStar),
+      ),
+      typeParameterTypeStar(T),
+      strT0: 'T*, T & num*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_09() {
+    var T = typeParameter('T', bound: intStar);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      strT0: 'T*',
+      strT1: 'T*, T & int*',
+    );
+  }
+
+  test_typeParameter_10() {
+    var T = typeParameter('T', bound: intStar);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'T*',
+      strT1: 'T*, T & num*',
+    );
+  }
+
+  test_typeParameter_11() {
+    var T = typeParameter('T', bound: numStar);
+
+    isNotSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(
+        promoteTypeParameter(T, intStar),
+      ),
+      strT0: 'T*',
+      strT1: 'T*, T & int*',
+    );
+  }
+
+  test_typeParameter_12() {
+    var T = typeParameter('T', bound: numStar);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(T),
+      strT0: 'T*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_13() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(T),
+      strT0: 'T',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_14() {
+    var S = typeParameter('S');
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(S),
+      typeParameterTypeNone(T),
+      strT0: 'S',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_15() {
+    var T = typeParameter('T', bound: objectStar);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(T),
+      strT0: 'T*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_16() {
+    var S = typeParameter('S', bound: objectStar);
+    var T = typeParameter('T', bound: objectStar);
+
+    isNotSubtype(
+      typeParameterTypeNone(S),
+      typeParameterTypeNone(T),
+      strT0: 'S',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_17() {
+    var T = typeParameter('T', bound: dynamicNone);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      typeParameterTypeStar(T),
+      strT0: 'T*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_18() {
+    var S = typeParameter('S', bound: dynamicNone);
+    var T = typeParameter('T', bound: dynamicNone);
+
+    isNotSubtype(
+      typeParameterTypeNone(S),
+      typeParameterTypeNone(T),
+      strT0: 'S',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_19() {
+    var S = typeParameter('S');
+    var T = typeParameter('T', bound: typeParameterTypeNone(S));
+
+    isNotSubtype(
+      typeParameterTypeNone(S),
+      typeParameterTypeNone(T),
+      strT0: 'S',
+      strT1: 'T',
+    );
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      typeParameterTypeNone(S),
+      strT0: 'T',
+      strT1: 'S',
+    );
+  }
+
+  test_typeParameter_20() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      intStar,
+      strT0: 'T, T & int*',
+      strT1: 'int*',
+    );
+  }
+
+  test_typeParameter_21() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, intStar),
+      ),
+      numStar,
+      strT0: 'T, T & int*',
+      strT1: 'num*',
+    );
+  }
+
+  test_typeParameter_22() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      numStar,
+      strT0: 'T, T & num*',
+      strT1: 'num*',
+    );
+  }
+
+  test_typeParameter_23() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      intStar,
+      strT0: 'T, T & num*',
+      strT1: 'int*',
+    );
+  }
+
+  test_typeParameter_24() {
+    var S = typeParameter('S');
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(S, numStar),
+      ),
+      typeParameterTypeNone(T),
+      strT0: 'S, S & num*',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_25() {
+    var S = typeParameter('S');
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeNone(
+        promoteTypeParameter(S, numStar),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'S, S & num*',
+      strT1: 'T, T & num*',
+    );
+  }
+
+  test_typeParameter_26() {
+    var S = typeParameter('S', bound: intStar);
+
+    isSubtype(
+      typeParameterTypeStar(S),
+      intStar,
+      strT0: 'S*',
+      strT1: 'int*',
+    );
+  }
+
+  test_typeParameter_27() {
+    var S = typeParameter('S', bound: intStar);
+
+    isSubtype(
+      typeParameterTypeStar(S),
+      numStar,
+      strT0: 'S*',
+      strT1: 'num*',
+    );
+  }
+
+  test_typeParameter_28() {
+    var S = typeParameter('S', bound: numStar);
+
+    isSubtype(
+      typeParameterTypeStar(S),
+      numStar,
+      strT0: 'S*',
+      strT1: 'num*',
+    );
+  }
+
+  test_typeParameter_29() {
+    var S = typeParameter('S', bound: numStar);
+
+    isNotSubtype(
+      typeParameterTypeStar(S),
+      intStar,
+      strT0: 'S*',
+      strT1: 'int*',
+    );
+  }
+
+  test_typeParameter_30() {
+    var S = typeParameter('S', bound: numStar);
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeStar(S),
+      typeParameterTypeNone(T),
+      strT0: 'S*',
+      strT1: 'T',
+    );
+  }
+
+  test_typeParameter_31() {
+    var S = typeParameter('S', bound: numStar);
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      typeParameterTypeStar(S),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, numStar),
+      ),
+      strT0: 'S*',
+      strT1: 'T, T & num*',
+    );
+  }
+
+  test_typeParameter_32() {
+    var T = typeParameter('T', bound: dynamicNone);
+
+    isNotSubtype(
+      dynamicNone,
+      typeParameterTypeNone(
+        promoteTypeParameter(T, dynamicNone),
+      ),
+      strT0: 'dynamic',
+      strT1: 'T, T & dynamic',
+    );
+  }
+
+  test_typeParameter_33() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      functionTypeStar(
+        returnType: typeParameterTypeNone(T),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(
+          T,
+          functionTypeStar(
+            returnType: typeParameterTypeNone(T),
+          ),
+        ),
+      ),
+      strT0: 'T Function()*',
+      strT1: 'T, T & T Function()*',
+    );
+  }
+
+  test_typeParameter_34() {
+    var T = typeParameter('T');
+
+    isNotSubtype(
+      futureOrStar(
+        typeParameterTypeNone(
+          promoteTypeParameter(T, stringStar),
+        ),
+      ),
+      typeParameterTypeNone(
+        promoteTypeParameter(T, stringStar),
+      ),
+      strT0: 'FutureOr<T>*, T & String*',
+      strT1: 'T, T & String*',
+    );
+  }
+
+  test_typeParameter_35() {
+    var T = typeParameter('T');
+
+    isSubtype(
+      nullStar,
+      typeParameterTypeStar(T),
+      strT0: 'Null*',
+      strT1: 'T*',
+    );
+  }
+
+  test_typeParameter_36() {
+    var T = typeParameter('T', bound: numNone);
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      numNone,
+      strT0: 'T',
+      strT1: 'num',
+    );
+  }
+
+  test_typeParameter_37() {
+    var T = typeParameter('T', bound: objectQuestion);
+
+    var type = typeParameterTypeNone(
+      promoteTypeParameter(T, numQuestion),
+    );
+
+    isNotSubtype(type, numNone, strT0: 'T, T & num?', strT1: 'num');
+    isSubtype(type, numQuestion, strT0: 'T, T & num?', strT1: 'num?');
+    isSubtype(type, numStar, strT0: 'T, T & num?', strT1: 'num*');
+  }
+
+  test_typeParameter_38() {
+    var T = typeParameter('T', bound: numStar);
+
+    isSubtype(
+      typeParameterTypeStar(T),
+      objectNone,
+      strT0: 'T*',
+      strT1: 'Object',
+    );
+  }
+
+  test_typeParameter_39() {
+    var T = typeParameter('T', bound: numNone);
+
+    isSubtype(
+      typeParameterTypeNone(T),
+      objectNone,
+      strT0: 'T',
+      strT1: 'Object',
+    );
+  }
+
+  test_typeParameter_40() {
+    var T = typeParameter('T', bound: numNone);
+
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      objectNone,
+      strT0: 'T?',
+      strT1: 'Object',
+    );
+  }
+
+  test_typeParameter_41() {
+    var T = typeParameter('T', bound: numQuestion);
+
+    isNotSubtype(
+      typeParameterTypeNone(T),
+      objectNone,
+      strT0: 'T',
+      strT1: 'Object',
+    );
+  }
+
+  test_typeParameter_42() {
+    var T = typeParameter('T', bound: numQuestion);
+
+    isNotSubtype(
+      typeParameterTypeQuestion(T),
+      objectNone,
+      strT0: 'T?',
+      strT1: 'Object',
+    );
+  }
+
+  TypeParameterTypeImpl typeParameterTypeNone(TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.none);
+  }
+
+  TypeParameterTypeImpl typeParameterTypeQuestion(
+      TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.question);
+  }
+
+  TypeParameterTypeImpl typeParameterTypeStar(TypeParameterElement element) {
+    return element.instantiate(nullabilitySuffix: NullabilitySuffix.star);
+  }
+
+  void _defineType(String str, DartType type) {
+    for (var key in _types.keys) {
+      if (key == 'Never' || _typeStr(type) == 'Never') {
+        // We have aliases for Never.
+      } else {
+        var value = _types[key];
+        if (key == str) {
+          fail('Duplicate type: $str;  existing: $value;  new: $type');
+        }
+        if (_typeStr(value) == _typeStr(type)) {
+          fail('Duplicate type: $str');
+        }
+      }
+    }
+    _types[str] = type;
+  }
+
+  void _defineTypes() {
+    _defineType('bottom', bottomNone);
+    _defineType('dynamic', dynamicNone);
+    _defineType('void', voidNone);
+    _defineType('Never', neverNone);
+    _defineType('Never?', neverQuestion);
+    _defineType('Null?', nullQuestion);
+
+    _defineType('Object', objectNone);
+    _defineType('Object*', objectStar);
+    _defineType('Object?', objectQuestion);
+
+    _defineType('Comparable<Object*>*', comparableStar(objectStar));
+    _defineType('Comparable<num*>*', comparableStar(numStar));
+    _defineType('Comparable<int*>*', comparableStar(intStar));
+
+    _defineType('num', numNone);
+    _defineType('num*', numStar);
+    _defineType('num?', numQuestion);
+
+    _defineType('int', intNone);
+    _defineType('int*', intStar);
+    _defineType('int?', intQuestion);
+
+    _defineType('double', doubleNone);
+    _defineType('double*', doubleStar);
+    _defineType('double?', doubleQuestion);
+
+    _defineType('List<Object*>*', listStar(objectStar));
+    _defineType('List<num*>*', listStar(numStar));
+    _defineType('List<int>', listNone(intNone));
+    _defineType('List<int>*', listStar(intNone));
+    _defineType('List<int>?', listQuestion(intNone));
+    _defineType('List<int*>', listNone(intStar));
+    _defineType('List<int*>*', listStar(intStar));
+    _defineType('List<int*>?', listQuestion(intStar));
+    _defineType('List<int?>', listNone(intQuestion));
+
+    _defineType(
+      'List<Comparable<Object*>*>*',
+      listStar(
+        comparableStar(objectStar),
+      ),
+    );
+    _defineType(
+      'List<Comparable<num*>*>*',
+      listStar(
+        comparableStar(numStar),
+      ),
+    );
+    _defineType(
+      'List<Comparable<Comparable<num*>*>*>*',
+      listStar(
+        comparableStar(
+          comparableStar(numStar),
+        ),
+      ),
+    );
+
+    _defineType('Iterable<Object*>*', iterableStar(objectStar));
+    _defineType('Iterable<int*>*', iterableStar(intStar));
+    _defineType('Iterable<num*>*', iterableStar(numStar));
+
+    _defineType('Function', functionNone);
+    _defineType('Function*', functionStar);
+    _defineType('Function?', functionQuestion);
+
+    _defineType('FutureOr<int>', futureOrNone(intNone));
+    _defineType('FutureOr<int>*', futureOrStar(intNone));
+    _defineType('FutureOr<int>?', futureOrQuestion(intNone));
+
+    _defineType('FutureOr<int*>', futureOrNone(intStar));
+    _defineType('FutureOr<int?>', futureOrNone(intQuestion));
+
+    _defineType('FutureOr<num>', futureOrNone(numNone));
+    _defineType('FutureOr<num>*', futureOrStar(numNone));
+    _defineType('FutureOr<num>?', futureOrQuestion(numNone));
+
+    _defineType('FutureOr<num*>', futureOrNone(numStar));
+    _defineType('FutureOr<num?>', futureOrNone(numQuestion));
+
+    _defineType('Future<Object>', futureNone(objectNone));
+    _defineType(
+      'FutureOr<Future<Object>>',
+      futureOrNone(
+        futureNone(objectNone),
+      ),
+    );
+    _defineType(
+      'FutureOr<Future<Object>>?',
+      futureOrQuestion(
+        futureNone(objectNone),
+      ),
+    );
+    _defineType(
+      'FutureOr<Future<Object>?>',
+      futureOrNone(
+        futureQuestion(objectNone),
+      ),
+    );
+    _defineType(
+      'FutureOr<Future<Object>?>?',
+      futureOrQuestion(
+        futureQuestion(objectNone),
+      ),
+    );
+
+    _defineType(
+      'int* Function()',
+      functionTypeNone(
+        returnType: intStar,
+      ),
+    );
+    _defineType(
+      'int* Function()*',
+      functionTypeStar(
+        returnType: intStar,
+      ),
+    );
+    _defineType(
+      'int* Function()?',
+      functionTypeQuestion(
+        returnType: intStar,
+      ),
+    );
+
+    _defineType(
+      'num* Function(num*)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: numStar)],
+        returnType: numStar,
+      ),
+    );
+    _defineType(
+      'num* Function(num*)*',
+      functionTypeStar(
+        parameters: [requiredParameter(type: numStar)],
+        returnType: numStar,
+      ),
+    );
+    _defineType(
+      'num* Function(num*)?',
+      functionTypeQuestion(
+        parameters: [requiredParameter(type: numStar)],
+        returnType: numStar,
+      ),
+    );
+
+    _defineType(
+      'int* Function(num*)*',
+      functionTypeStar(
+        parameters: [requiredParameter(type: numStar)],
+        returnType: intStar,
+      ),
+    );
+
+    _defineType(
+      'num* Function(int*)',
+      functionTypeNone(
+        parameters: [requiredParameter(type: intStar)],
+        returnType: numStar,
+      ),
+    );
+    _defineType(
+      'num* Function(int*)*',
+      functionTypeStar(
+        parameters: [requiredParameter(type: intStar)],
+        returnType: numStar,
+      ),
+    );
+    _defineType(
+      'num* Function(int*)?',
+      functionTypeQuestion(
+        parameters: [requiredParameter(type: intStar)],
+        returnType: numStar,
+      ),
+    );
+
+    _defineType(
+      'int* Function(int*)*',
+      functionTypeStar(
+        parameters: [requiredParameter(type: intStar)],
+        returnType: intStar,
+      ),
+    );
+  }
+
+  DartType _getTypeByStr(String str) {
+    var type = _types[str];
+    expect(type, isNotNull, reason: 'No DartType for: $str');
+    return type;
+  }
+
+  static String _typeStr(DartType type) {
+    return (type as TypeImpl).toString(withNullability: true);
+  }
+}
+
+@reflectiveTest
+class SubtypingCompoundTest extends _SubtypingCompoundTestBase {
+  test_bottom_isBottom() {
+    var equivalents = <DartType>[bottomStar];
+
+    var supertypes = <DartType>[
+      dynamicNone,
+      objectStar,
+      intStar,
+      doubleStar,
+      numStar,
+      stringStar,
+      functionStar,
+    ];
+
+    _checkGroups(
+      bottomStar,
+      equivalents: equivalents,
+      supertypes: supertypes,
+    );
+  }
+
+  test_double() {
+    var equivalents = <DartType>[doubleStar];
+    var supertypes = <DartType>[numStar];
+    var unrelated = <DartType>[intStar];
+    _checkGroups(
+      doubleStar,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+    );
+  }
+
+  test_dynamic_isTop() {
+    var equivalents = <DartType>[
+      dynamicNone,
+      objectStar,
+      voidNone,
+    ];
+
+    var subtypes = <DartType>[
+      intStar,
+      doubleStar,
+      numStar,
+      stringStar,
+      functionStar,
+      bottomStar,
+    ];
+
+    _checkGroups(
+      dynamicType,
+      equivalents: equivalents,
+      subtypes: subtypes,
+    );
+  }
+
+  test_int() {
+    var equivalents = <DartType>[intStar];
+    var supertypes = <DartType>[numStar];
+    var unrelated = <DartType>[doubleStar];
+    _checkGroups(
+      intStar,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+    );
+  }
+
+  test_num() {
+    var equivalents = <DartType>[numStar];
+    var supertypes = <DartType>[objectStar];
+    var unrelated = <DartType>[stringStar];
+    var subtypes = <DartType>[intStar, doubleStar];
+    _checkGroups(
+      numStar,
+      equivalents: equivalents,
+      supertypes: supertypes,
+      unrelated: unrelated,
+      subtypes: subtypes,
+    );
+  }
+
+  test_void_isTop() {
+    var equivalents = <DartType>[
+      dynamicNone,
+      objectStar,
+      voidNone,
+    ];
+
+    var subtypes = <DartType>[
+      intStar,
+      doubleStar,
+      numStar,
+      stringStar,
+      functionStar,
+      bottomStar,
+    ];
+
+    _checkGroups(
+      voidNone,
+      equivalents: equivalents,
+      subtypes: subtypes,
+    );
+  }
+}
+
+class _SubtypingCompoundTestBase extends _SubtypingTestBase {
+  void _checkEquivalent(DartType type1, DartType type2) {
+    _checkIsSubtypeOf(type1, type2);
+    _checkIsSubtypeOf(type2, type1);
+  }
+
+  void _checkGroups(DartType t1,
+      {List<DartType> equivalents,
+      List<DartType> unrelated,
+      List<DartType> subtypes,
+      List<DartType> supertypes}) {
+    if (equivalents != null) {
+      for (DartType t2 in equivalents) {
+        _checkEquivalent(t1, t2);
+      }
+    }
+    if (unrelated != null) {
+      for (DartType t2 in unrelated) {
+        _checkUnrelated(t1, t2);
+      }
+    }
+    if (subtypes != null) {
+      for (DartType t2 in subtypes) {
+        _checkIsStrictSubtypeOf(t2, t1);
+      }
+    }
+    if (supertypes != null) {
+      for (DartType t2 in supertypes) {
+        _checkIsStrictSubtypeOf(t1, t2);
+      }
+    }
+  }
+
+  void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
+    var strType1 = _typeStr(type1);
+    var strType2 = _typeStr(type2);
+    expect(typeSystem.isSubtypeOf(type1, type2), false,
+        reason: '$strType1 was not supposed to be a subtype of $strType2');
+  }
+
+  void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
+    _checkIsSubtypeOf(type1, type2);
+    _checkIsNotSubtypeOf(type2, type1);
+  }
+
+  void _checkIsSubtypeOf(DartType type1, DartType type2) {
+    var strType1 = _typeStr(type1);
+    var strType2 = _typeStr(type2);
+    expect(typeSystem.isSubtypeOf(type1, type2), true,
+        reason: '$strType1 is not a subtype of $strType2');
+  }
+
+  void _checkUnrelated(DartType type1, DartType type2) {
+    _checkIsNotSubtypeOf(type1, type2);
+    _checkIsNotSubtypeOf(type2, type1);
+  }
+
+  static String _typeStr(DartType type) {
+    return (type as TypeImpl).toString(withNullability: true);
+  }
+}
+
+@reflectiveTest
+class _SubtypingTestBase with ElementsTypesMixin {
+  TypeProvider typeProvider;
+
+  Dart2TypeSystem typeSystem;
+
+  ClassElement _comparableElement;
+
+  BottomTypeImpl get bottomNone => BottomTypeImpl.instance;
+
+  BottomTypeImpl get bottomQuestion => BottomTypeImpl.instanceNullable;
+
+  BottomTypeImpl get bottomStar => BottomTypeImpl.instanceLegacy;
+
+  ClassElement get comparableElement {
+    return _comparableElement ??=
+        typeProvider.intType.element.library.getType('Comparable');
+  }
+
+  InterfaceType get doubleNone {
+    var element = typeProvider.doubleType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get doubleQuestion {
+    var element = typeProvider.doubleType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get doubleStar {
+    var element = typeProvider.doubleType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  DartType get dynamicNone => typeProvider.dynamicType;
+
+  InterfaceType get functionNone {
+    var element = typeProvider.functionType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get functionQuestion {
+    var element = typeProvider.functionType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get functionStar {
+    var element = typeProvider.functionType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get intNone {
+    var element = typeProvider.intType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get intQuestion {
+    var element = typeProvider.intType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get intStar {
+    var element = typeProvider.intType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  BottomTypeImpl get neverNone => BottomTypeImpl.instance;
+
+  BottomTypeImpl get neverQuestion => BottomTypeImpl.instanceNullable;
+
+  InterfaceType get nullNone {
+    var element = typeProvider.nullType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get nullQuestion {
+    var element = typeProvider.nullType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get nullStar {
+    var element = typeProvider.nullType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get numNone {
+    var element = typeProvider.numType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get numQuestion {
+    var element = typeProvider.numType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get numStar {
+    var element = typeProvider.numType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get objectNone {
+    var element = typeProvider.objectType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceType get objectQuestion {
+    var element = typeProvider.objectType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceType get objectStar {
+    var element = typeProvider.objectType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceType get stringStar {
+    var element = typeProvider.stringType.element;
+    return element.instantiate(
+      typeArguments: const [],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  FeatureSet get testFeatureSet {
+    return FeatureSet.forTesting();
+  }
+
+  VoidType get voidNone => typeProvider.voidType;
+
+  InterfaceTypeImpl futureNone(DartType type) {
+    return typeProvider.futureElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceTypeImpl futureOrNone(DartType type) {
+    return typeProvider.futureOrElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
+  }
+
+  InterfaceTypeImpl futureOrQuestion(DartType type) {
+    return typeProvider.futureOrElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceTypeImpl futureOrStar(DartType type) {
+    return typeProvider.futureOrElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  InterfaceTypeImpl futureQuestion(DartType type) {
+    return typeProvider.futureElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
+  }
+
+  InterfaceTypeImpl futureStar(DartType type) {
+    return typeProvider.futureElement.instantiate(
+      typeArguments: [type],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
+  }
+
+  void setUp() {
+    var analysisContext = TestAnalysisContext(
+      featureSet: testFeatureSet,
+    );
+    typeProvider = analysisContext.typeProvider;
+    typeSystem = analysisContext.typeSystem;
+  }
+}
+
+class _TypeParameterCollector extends DartTypeVisitor<void> {
+  final Set<TypeParameterElement> typeParameters = Set();
+
+  @override
+  void defaultDartType(DartType type) {
+    throw UnimplementedError('(${type.runtimeType}) $type');
+  }
+
+  @override
+  void visitBottomType(BottomTypeImpl type) {}
+
+  @override
+  void visitDynamicType(DynamicTypeImpl type) {}
+
+  @override
+  void visitFunctionType(FunctionType type) {
+    for (var typeParameter in type.typeFormals) {
+      var bound = typeParameter.bound;
+      if (bound != null) {
+        DartTypeVisitor.visit(bound, this);
+      }
+    }
+    for (var parameter in type.parameters) {
+      DartTypeVisitor.visit(parameter.type, this);
+    }
+    DartTypeVisitor.visit(type.returnType, this);
+  }
+
+  @override
+  void visitInterfaceType(InterfaceType type) {
+    for (var typeArgument in type.typeArguments) {
+      DartTypeVisitor.visit(typeArgument, this);
+    }
+  }
+
+  @override
+  void visitTypeParameterType(TypeParameterType type) {
+    typeParameters.add(type.element);
+  }
+
+  @override
+  void visitVoidType(VoidType type) {}
+}
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index ffecc6d..f24eff5 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -6,9 +6,9 @@
 
 import 'element_test.dart' as element;
 import 'function_type_test.dart' as function_type;
-import 'inheritance_manager2_test.dart' as inheritance_manager2;
 import 'inheritance_manager3_test.dart' as inheritance_manager3;
 import 'least_upper_bound_helper_test.dart' as least_upper_bound_helper;
+import 'subtype_test.dart' as subtype;
 import 'type_algebra_test.dart' as type_algebra;
 
 /// Utility for manually running all tests.
@@ -16,9 +16,9 @@
   defineReflectiveSuite(() {
     element.main();
     function_type.main();
-    inheritance_manager2.main();
     inheritance_manager3.main();
     least_upper_bound_helper.main();
+    subtype.main();
     type_algebra.main();
   }, name: 'element');
 }
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index c364469..a1c1663 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -5,6 +5,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/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
@@ -91,9 +92,11 @@
   test_function() async {
     // T Function(T)
     var T = typeParameter('T');
-    var type = functionType(
-      required: [typeParameterType(T)],
-      returns: typeParameterType(T),
+    var type = functionTypeStar(
+      parameters: [
+        requiredParameter(type: typeParameterType(T)),
+      ],
+      returnType: typeParameterType(T),
     );
 
     var result = Substitution.fromUpperAndLowerBounds(
@@ -117,7 +120,12 @@
   }
 
   test_function_noSubstitutions() async {
-    var type = functionType(required: [intType], returns: boolType);
+    var type = functionTypeStar(
+      parameters: [
+        requiredParameter(type: intType),
+      ],
+      returnType: boolType,
+    );
 
     var T = typeParameter('T');
     _assertIdenticalType(type, {T: intType});
@@ -127,12 +135,12 @@
     // typedef F<T, U> = T Function(U u, bool);
     var T = typeParameter('T');
     var U = typeParameter('U');
-    var type = functionType(
-      required: [
-        typeParameterType(U),
-        boolType,
+    var type = functionTypeStar(
+      parameters: [
+        requiredParameter(type: typeParameterType(U)),
+        requiredParameter(type: boolType),
       ],
-      returns: typeParameterType(T),
+      returnType: typeParameterType(T),
     );
 
     assertElementTypeString(type, 'T Function(U, bool)');
@@ -152,12 +160,12 @@
     // typedef F<T> = T Function<U extends T>(U);
     var T = typeParameter('T');
     var U = typeParameter('U', bound: typeParameterType(T));
-    var type = functionType(
+    var type = functionTypeStar(
       typeFormals: [U],
-      required: [
-        typeParameterType(U),
+      parameters: [
+        requiredParameter(type: typeParameterType(U)),
       ],
-      returns: typeParameterType(T),
+      returnType: typeParameterType(T),
     );
 
     assertElementTypeString(type, 'T Function<U extends T>(U)');
@@ -185,9 +193,9 @@
       typeParameterType(U),
       typeParameterType(V),
     ]);
-    var type = functionType(
+    var type = functionTypeStar(
       typeFormals: [T, U],
-      returns: boolType,
+      returnType: boolType,
     );
 
     assertElementTypeString(
@@ -259,6 +267,49 @@
     _assertIdenticalType(type, {U: doubleType});
   }
 
+  test_typeParameter_nullability() async {
+    var typeProvider = TestTypeProvider();
+
+    var intElement = typeProvider.intType.element;
+
+    var intQuestion = InterfaceTypeImpl.explicit(intElement, [],
+        nullabilitySuffix: NullabilitySuffix.question);
+    var intStar = InterfaceTypeImpl.explicit(intElement, [],
+        nullabilitySuffix: NullabilitySuffix.star);
+    var intNone = InterfaceTypeImpl.explicit(intElement, [],
+        nullabilitySuffix: NullabilitySuffix.star);
+
+    var tElement = TypeParameterElementImpl('T', -1);
+
+    void check(
+      NullabilitySuffix typeParameterNullability,
+      InterfaceTypeImpl typeArgument,
+      InterfaceTypeImpl expectedType,
+    ) {
+      var result = Substitution.fromMap(
+        {tElement: typeArgument},
+      ).substituteType(
+        TypeParameterTypeImpl(
+          tElement,
+          nullabilitySuffix: typeParameterNullability,
+        ),
+      );
+      expect(result, expectedType);
+    }
+
+    check(NullabilitySuffix.none, intNone, intNone);
+    check(NullabilitySuffix.none, intStar, intStar);
+    check(NullabilitySuffix.none, intQuestion, intQuestion);
+
+    check(NullabilitySuffix.star, intNone, intStar);
+    check(NullabilitySuffix.star, intStar, intStar);
+    check(NullabilitySuffix.star, intQuestion, intQuestion);
+
+    check(NullabilitySuffix.question, intNone, intQuestion);
+    check(NullabilitySuffix.question, intStar, intQuestion);
+    check(NullabilitySuffix.question, intQuestion, intQuestion);
+  }
+
   test_unknownInferredType() async {
     var T = typeParameter('T');
     _assertIdenticalType(UnknownInferredType.instance, {T: intType});
@@ -290,9 +341,12 @@
     var A = class_(name: 'A', typeParameters: [T]);
 
     var U = typeParameter('U');
-    var type = interfaceType(A,
-        typeArguments: [typeParameterType(U)],
-        nullabilitySuffix: NullabilitySuffix.none);
+    var type = A.instantiate(
+      typeArguments: [
+        U.instantiate(nullabilitySuffix: NullabilitySuffix.none),
+      ],
+      nullabilitySuffix: NullabilitySuffix.none,
+    );
     _assertSubstitution(type, {U: intType}, 'A<int>');
   }
 
@@ -302,9 +356,12 @@
     var A = class_(name: 'A', typeParameters: [T]);
 
     var U = typeParameter('U');
-    var type = interfaceType(A,
-        typeArguments: [typeParameterType(U)],
-        nullabilitySuffix: NullabilitySuffix.question);
+    var type = A.instantiate(
+      typeArguments: [
+        U.instantiate(nullabilitySuffix: NullabilitySuffix.none),
+      ],
+      nullabilitySuffix: NullabilitySuffix.question,
+    );
     _assertSubstitution(type, {U: intType}, 'A<int>?');
   }
 
@@ -314,9 +371,12 @@
     var A = class_(name: 'A', typeParameters: [T]);
 
     var U = typeParameter('U');
-    var type = interfaceType(A,
-        typeArguments: [typeParameterType(U)],
-        nullabilitySuffix: NullabilitySuffix.star);
+    var type = A.instantiate(
+      typeArguments: [
+        U.instantiate(nullabilitySuffix: NullabilitySuffix.none),
+      ],
+      nullabilitySuffix: NullabilitySuffix.star,
+    );
     _assertSubstitution(type, {U: intType}, 'A<int>*');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index ea4bd89..9c4678d 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -408,8 +408,7 @@
 
     var cRef = left.prefix;
     assertElement(cRef, findElement.class_('C'));
-    // TODO(scheglov) Why not `Type`? Should it even have a type?
-    assertType(cRef, 'C');
+    assertTypeNull(cRef);
 
     var fRef = left.identifier;
     assertElement(fRef, findElement.setter('f'));
@@ -862,7 +861,7 @@
     var bDeclaration = findNode.variableDeclaration('b =');
     TopLevelVariableElement bElement = bDeclaration.declaredElement;
     assertElement(bDeclaration.name, findElement.topVar('b'));
-    assertType(bDeclaration.name, 'bool');
+    assertTypeNull(bDeclaration.name);
     expect(bElement.type.toString(), 'bool');
 
     SimpleIdentifier aRef = bDeclaration.initializer;
@@ -880,7 +879,7 @@
     var bDeclaration = findNode.variableDeclaration('b =');
     TopLevelVariableElement bElement = bDeclaration.declaredElement;
     assertElement(bDeclaration.name, bElement);
-    assertType(bDeclaration.name, 'bool');
+    assertTypeNull(bDeclaration.name);
     expect(bElement.type.toString(), 'bool');
 
     SimpleIdentifier aRef = bDeclaration.initializer;
diff --git a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
index 96a7512..00fd73a 100644
--- a/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/extension_method_test.dart
@@ -16,6 +16,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ExtensionMethodsDeclarationTest);
+    defineReflectiveTests(ExtensionMethodsDeclarationWithNnbdTest);
     defineReflectiveTests(ExtensionMethodsExtendedTypeTest);
     defineReflectiveTests(ExtensionMethodsExternalReferenceTest);
     defineReflectiveTests(ExtensionMethodsInternalReferenceTest);
@@ -105,6 +106,39 @@
 ''');
   }
 
+  test_this_type_interface() async {
+    await assertNoErrorsInCode('''
+extension E on int {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'int');
+  }
+
+  test_this_type_typeParameter() async {
+    await assertNoErrorsInCode('''
+extension E<T> on T {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'T');
+  }
+
+  test_this_type_typeParameter_withBound() async {
+    await assertNoErrorsInCode('''
+extension E<T extends Object> on T {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'T');
+  }
+
   test_visibility_hidden() async {
     newFile('/test/lib/lib.dart', content: '''
 class C {}
@@ -280,6 +314,52 @@
   }
 }
 
+/// Tests that show that extension declarations and the members inside them are
+/// resolved correctly.
+@reflectiveTest
+class ExtensionMethodsDeclarationWithNnbdTest extends BaseExtensionMethodsTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = new FeatureSet.forTesting(
+        sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  test_this_type_interface() async {
+    await assertNoErrorsInCode('''
+extension E on int {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'int');
+  }
+
+  test_this_type_typeParameter() async {
+    await assertNoErrorsInCode('''
+extension E<T> on T {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'T');
+  }
+
+  test_this_type_typeParameter_withBound() async {
+    await assertNoErrorsInCode('''
+extension E<T extends Object> on T {
+  void foo() {
+    this;
+  }
+}
+''');
+    assertType(findNode.this_('this;'), 'T');
+  }
+}
+
 /// Tests that show that extension declarations support all of the possible
 /// types in the `on` clause.
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/local_function_test.dart b/pkg/analyzer/test/src/dart/resolution/local_function_test.dart
new file mode 100644
index 0000000..1fb626f
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/local_function_test.dart
@@ -0,0 +1,62 @@
+// 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 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(LocalFunctionResolutionTest);
+  });
+}
+
+@reflectiveTest
+class LocalFunctionResolutionTest extends DriverResolutionTest {
+  test_element_block() async {
+    await assertNoErrorsInCode(r'''
+f() {
+  g() {}
+  g();
+}
+''');
+    var element = findElement.localFunction('g');
+    expect(element.name, 'g');
+    expect(element.nameOffset, 8);
+
+    assertElement(findNode.methodInvocation('g();'), element);
+  }
+
+  test_element_switchCase() async {
+    await assertNoErrorsInCode(r'''
+f(int a) {
+  switch (a) {
+    case 1:
+      g() {}
+      g();
+      break;
+  }
+}
+''');
+    var element = findElement.localFunction('g');
+    expect(element.name, 'g');
+    expect(element.nameOffset, 44);
+
+    assertElement(findNode.methodInvocation('g();'), element);
+  }
+
+  test_element_ifStatement() async {
+    await assertNoErrorsInCode(r'''
+f() {
+  if (1 > 2)
+    g() {}
+}
+''');
+    var node = findNode.functionDeclaration('g() {}');
+    var element = node.declaredElement;
+    expect(element.name, 'g');
+    expect(element.nameOffset, 23);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
index 929f0533..56968e2 100644
--- a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
@@ -18,7 +18,7 @@
 
 @reflectiveTest
 class LocalVariableResolutionTest extends DriverResolutionTest {
-  test_element() async {
+  test_element_block() async {
     await assertNoErrorsInCode(r'''
 void f() {
   int x = 0;
@@ -32,6 +32,21 @@
     expect(x.isStatic, isFalse);
   }
 
+  test_element_ifStatement() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  if (1 > 2)
+    int x = 0;
+}
+''');
+
+    var x = findElement.localVar('x');
+    expect(x.isConst, isFalse);
+    expect(x.isFinal, isFalse);
+    expect(x.isLate, isFalse);
+    expect(x.isStatic, isFalse);
+  }
+
   test_element_const() async {
     await assertNoErrorsInCode(r'''
 void f() {
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index abf7f9d..e25faed 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -42,7 +42,7 @@
           type: TypeName
             name: SimpleIdentifier
               staticElement: self::@class::A
-              staticType: A
+              staticType: null
               token: A
             type: A
         staticElement: self::@class::A::@constructor::•
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 8ce09b5..942563e 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -1265,17 +1265,6 @@
     ]);
   }
 
-  test_isMoreSpecificThan() async {
-    await assertNoErrorsInCode(r'''
-mixin M {}
-''');
-
-    var element = findElement.mixin('M');
-    var type = interfaceType(element);
-    // ignore: deprecated_member_use_from_same_package
-    expect(type.isMoreSpecificThan(intType), isFalse);
-  }
-
   test_lookUpMemberInInterfaces_Object() async {
     await assertNoErrorsInCode(r'''
 class Foo {}
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 2c38049..3190200 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -56,6 +56,20 @@
     assertType(findNode.typeName('C;'), 'C');
   }
 
+  test_field_functionTypeAlias() async {
+    await assertNoErrorsInCode('''
+typedef F = T Function<T>(int, T);
+
+class C {
+  F? f;
+}
+''');
+    assertElementTypeString(
+      findElement.field('f').type,
+      'T Function<T>(int, T)?',
+    );
+  }
+
   test_local_getterNullAwareAccess_interfaceType() async {
     await resolveTestCode(r'''
 main() {
@@ -173,7 +187,6 @@
     assertType(findNode.typeName('T? y'), 'T?');
   }
 
-  @failingTest
   test_local_variable_genericFunctionType() async {
     await resolveTestCode('''
 main() {
@@ -184,7 +197,7 @@
 
     assertType(
       findNode.genericFunctionType('Function('),
-      '(bool!, String?) → int??',
+      'int? Function(bool, String?)?',
     );
   }
 
@@ -238,6 +251,19 @@
     assertType(findNode.typeName('A {} // 2'), 'A');
   }
 
+  test_nonNullPromotion_typeParameter() async {
+    await assertNoErrorsInCode(r'''
+class C<T> {
+  void foo(T? t) {
+    T temp = t!;
+  }
+  T bar(T? t) {
+    return t!;
+  }
+}
+''');
+  }
+
   test_null_assertion_operator_changes_null_to_never() async {
     await resolveTestCode('''
 main() {
@@ -260,9 +286,26 @@
     assertType(findNode.postfix('x!'), 'Object');
   }
 
-  @FailingTest(
-    reason: 'The question token is not added to FieldFormalParameter yet',
-  )
+  test_parameter_functionTyped() async {
+    await assertNoErrorsInCode('''
+void f1(void p1()) {}
+void f2(void p2()?) {}
+void f3({void p3()?}) {}
+''');
+    assertElementTypeString(
+      findElement.parameter('p1').type,
+      'void Function()',
+    );
+    assertElementTypeString(
+      findElement.parameter('p2').type,
+      'void Function()?',
+    );
+    assertElementTypeString(
+      findElement.parameter('p3').type,
+      'void Function()?',
+    );
+  }
+
   test_parameter_functionTyped_fieldFormal() async {
     await assertNoErrorsInCode('''
 class A {
@@ -288,26 +331,6 @@
     );
   }
 
-  test_parameter_functionTyped() async {
-    await assertNoErrorsInCode('''
-void f1(void p1()) {}
-void f2(void p2()?) {}
-void f3({void p3()?}) {}
-''');
-    assertElementTypeString(
-      findElement.parameter('p1').type,
-      'void Function()',
-    );
-    assertElementTypeString(
-      findElement.parameter('p2').type,
-      'void Function()?',
-    );
-    assertElementTypeString(
-      findElement.parameter('p3').type,
-      'void Function()?',
-    );
-  }
-
   test_parameter_functionTyped_local() async {
     await assertNoErrorsInCode('''
 f() {
@@ -330,7 +353,6 @@
     );
   }
 
-  @failingTest
   test_parameter_genericFunctionType() async {
     await resolveTestCode('''
 main(int? Function(bool, String?)? a) {
@@ -340,7 +362,7 @@
 
     assertType(
       findNode.genericFunctionType('Function('),
-      '(bool!, String?) → int??',
+      'int? Function(bool, String?)?',
     );
   }
 
@@ -458,7 +480,6 @@
     assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
   }
 
-  @failingTest
   test_typedef_function() async {
     await resolveTestCode('''
 typedef F<T> = int? Function(bool, T, T?);
@@ -471,7 +492,7 @@
 
     assertType(
       findNode.typeName('F<String>'),
-      'int? Function(bool!, String!, String?)?',
+      'int? Function(bool, String, String?)?',
     );
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 80bb8fb..fa9767e 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -29,6 +29,7 @@
     as instance_member_inference_class;
 import 'instance_member_inference_mixin_test.dart'
     as instance_member_inference_mixin;
+import 'local_function_test.dart' as local_function;
 import 'local_variable_test.dart' as local_variable;
 import 'metadata_test.dart' as metadata;
 import 'method_invocation_test.dart' as method_invocation;
@@ -64,6 +65,7 @@
     instance_creation.main();
     instance_member_inference_class.main();
     instance_member_inference_mixin.main();
+    local_function.main();
     local_variable.main();
     metadata.main();
     method_invocation.main();
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
index ed4f95f..cb605a0 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
@@ -26,7 +26,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_list_awaitForIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -39,7 +38,6 @@
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
-  @failingTest
   test_list_awaitForIn_int_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -51,7 +49,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
-  @failingTest
   test_list_for_downward() async {
     await resolveTestCode('''
 void f() {
@@ -63,7 +60,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_list_forIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() {
@@ -76,7 +72,6 @@
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
-  @failingTest
   test_list_forIn_int_downward() async {
     await resolveTestCode('''
 void f() {
@@ -89,7 +84,6 @@
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
-  @failingTest
   test_map_awaitForIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -102,7 +96,6 @@
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
-  @failingTest
   test_map_awaitForIn_int_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -114,7 +107,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
-  @failingTest
   test_map_for_downward() async {
     await resolveTestCode('''
 void f() {
@@ -126,7 +118,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_map_forIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() {
@@ -139,7 +130,6 @@
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
-  @failingTest
   test_map_forIn_int_downward() async {
     await resolveTestCode('''
 void f() {
@@ -152,7 +142,6 @@
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
-  @failingTest
   test_set_awaitForIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -165,7 +154,6 @@
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
-  @failingTest
   test_set_awaitForIn_int_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -177,7 +165,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
-  @failingTest
   test_set_for_downward() async {
     await resolveTestCode('''
 void f() {
@@ -189,7 +176,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_set_forIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() {
@@ -202,7 +188,6 @@
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
-  @failingTest
   test_set_forIn_int_downward() async {
     await resolveTestCode('''
 void f() {
@@ -226,7 +211,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_list_downward() async {
     await resolveTestCode('''
 void f() {
@@ -238,7 +222,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_map_downward() async {
     await resolveTestCode('''
 void f() {
@@ -250,7 +233,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_set_downward() async {
     await resolveTestCode('''
 void f() {
@@ -273,7 +255,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_list_downward() async {
     await resolveTestCode('''
 void f() {
@@ -286,7 +267,6 @@
         findNode.methodInvocation('a('), 'Iterable<int> Function()');
   }
 
-  @failingTest
   test_map_downward() async {
     await resolveTestCode('''
 void f() {
@@ -299,7 +279,6 @@
         findNode.methodInvocation('a('), 'Map<String, int> Function()');
   }
 
-  @failingTest
   test_set_downward() async {
     await resolveTestCode('''
 void f() {
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index 9ed2abc..b14de64 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapLiteralTest);
+    defineReflectiveTests(MapLiteralWithNnbdTest);
   });
 }
 
@@ -322,3 +325,37 @@
     assertType(setOrMapLiteral('{'), 'Map<num, String>');
   }
 }
+
+@reflectiveTest
+class MapLiteralWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
+
+  test_context_noTypeArgs_noEntries() async {
+    await resolveTestCode('''
+Map<String, String> a = {};
+''');
+    assertType(setOrMapLiteral('{'), 'Map<String, String>');
+  }
+
+  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
+    await resolveTestCode('''
+class C<T extends Object?> {
+  Map<String, T> a = {}; // 1
+  Map<String, T>? b = {}; // 2
+  Map<String, T?> c = {}; // 3
+  Map<String, T?>? d = {}; // 4
+}
+''');
+    assertType(setOrMapLiteral('{}; // 1'), 'Map<String, T>');
+    assertType(setOrMapLiteral('{}; // 2'), 'Map<String, T>');
+    assertType(setOrMapLiteral('{}; // 3'), 'Map<String, T?>');
+    assertType(setOrMapLiteral('{}; // 4'), 'Map<String, T?>');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
index a880513..642a09d 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/set_literal_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetLiteralTest);
+    defineReflectiveTests(SetLiteralWithNnbdTest);
   });
 }
 
@@ -261,3 +264,37 @@
     assertType(setLiteral('{'), 'Set<num>');
   }
 }
+
+@reflectiveTest
+class SetLiteralWithNnbdTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions =>
+      AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+  @override
+  bool get typeToStringWithNullability => true;
+
+  AstNode setOrMapLiteral(String search) => findNode.setOrMapLiteral(search);
+
+  test_context_noTypeArgs_noEntries() async {
+    await resolveTestCode('''
+Set<String> a = {};
+''');
+    assertType(setOrMapLiteral('{'), 'Set<String>');
+  }
+
+  test_context_noTypeArgs_noEntries_typeParameterNullable() async {
+    await resolveTestCode('''
+class C<T extends Object?> {
+  Set<T> a = {}; // 1
+  Set<T>? b = {}; // 2
+  Set<T?> c = {}; // 3
+  Set<T?>? d = {}; // 4
+}
+''');
+    assertType(setOrMapLiteral('{}; // 1'), 'Set<T>');
+    assertType(setOrMapLiteral('{}; // 2'), 'Set<T>');
+    assertType(setOrMapLiteral('{}; // 3'), 'Set<T?>');
+    assertType(setOrMapLiteral('{}; // 4'), 'Set<T?>');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
index cab7d7b..583b9fb 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
@@ -28,7 +28,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_downward() async {
     await resolveTestCode('''
 void f() {
@@ -50,7 +49,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_downward() async {
     await resolveTestCode('''
 void f() {
@@ -72,7 +70,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_awaitForIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -84,7 +81,6 @@
         findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
   }
 
-  @failingTest
   test_awaitForIn_int_downward() async {
     await resolveTestCode('''
 void f() async {
@@ -95,7 +91,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
   }
 
-  @failingTest
   test_for_downward() async {
     await resolveTestCode('''
 void f() {
@@ -106,7 +101,6 @@
     assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
   }
 
-  @failingTest
   test_forIn_dynamic_downward() async {
     await resolveTestCode('''
 void f() {
@@ -118,7 +112,6 @@
         findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
   }
 
-  @failingTest
   test_forIn_int_downward() async {
     await resolveTestCode('''
 void f() {
@@ -141,7 +134,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_downward() async {
     await resolveTestCode('''
 void f() {
@@ -163,7 +155,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_downward() async {
     await resolveTestCode('''
 void f() {
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
index 60e9a36..8d00d68 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
@@ -24,7 +24,6 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  @failingTest
   test_downward() async {
     await resolveTestCode('''
 void f() {
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 97b6c70..f5ac0c5 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -134,6 +134,28 @@
     ]);
   }
 
+  test_for_element_type_inferred_from_rewritten_node() async {
+    // See https://github.com/dart-lang/sdk/issues/39171
+    await assertNoErrorsInCode('''
+void f<T>(Iterable<T> Function() g, int Function(T) h) {
+  [for (var x in g()) if (x is String) h(x)];
+}
+''');
+  }
+
+  test_for_statement_type_inferred_from_rewritten_node() async {
+    // See https://github.com/dart-lang/sdk/issues/39171
+    await assertNoErrorsInCode('''
+void f<T>(Iterable<T> Function() g, void Function(T) h) {
+  for (var x in g()) {
+    if (x is String) {
+      h(x);
+    }
+  }
+}
+''');
+  }
+
   test_functionExpressionInvocation_required() async {
     await assertErrorsInCode('''
 main() {
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
index c47a2fd..5e19d96 100644
--- a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -39,6 +39,12 @@
     ]);
   }
 
+  test_notDefaultConstructor() async {
+    await assertNoErrorsInCode('''
+var x = List<int>.unmodifiable([]);
+''');
+  }
+
   test_nullableType() async {
     await assertNoErrorsInCode('''
 var l = new List<String?>(3);
diff --git a/pkg/analyzer/test/src/diagnostics/extension_override_argument_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/extension_override_argument_not_assignable_test.dart
index a0e9709..cb87bf4 100644
--- a/pkg/analyzer/test/src/diagnostics/extension_override_argument_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extension_override_argument_not_assignable_test.dart
@@ -11,13 +11,13 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ExtensionDeclaresAbstractMethodTest);
-    defineReflectiveTests(ExtensionDeclaresAbstractMethodWithNNBDTest);
+    defineReflectiveTests(ExtensionOverrideArgumentNotAssignableTest);
+    defineReflectiveTests(ExtensionOverrideArgumentNotAssignableWithNNBDTest);
   });
 }
 
 @reflectiveTest
-class ExtensionDeclaresAbstractMethodTest extends DriverResolutionTest {
+class ExtensionOverrideArgumentNotAssignableTest extends DriverResolutionTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
     ..contextFeatures = new FeatureSet.forTesting(
@@ -68,7 +68,8 @@
 }
 
 @reflectiveTest
-class ExtensionDeclaresAbstractMethodWithNNBDTest extends DriverResolutionTest {
+class ExtensionOverrideArgumentNotAssignableWithNNBDTest
+    extends DriverResolutionTest {
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
     ..contextFeatures = new FeatureSet.forTesting(
diff --git a/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
index 8dc2f67..8d86a32 100644
--- a/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,12 +12,33 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ImplicitThisReferenceInInitializerTest);
+    defineReflectiveTests(ImplicitThisReferenceInInitializerWithNnbdTest);
   });
 }
 
 @reflectiveTest
 class ImplicitThisReferenceInInitializerTest extends DriverResolutionTest {
-  test_implicitThisReferenceInInitializer_constructorName() async {
+  test_class_field_commentReference_prefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int a = 0;
+  /// foo [a.isEven] bar
+  int x = 1;
+}
+''');
+  }
+
+  test_class_field_commentReference_simpleIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int a = 0;
+  /// foo [a] bar
+  int x = 1;
+}
+''');
+  }
+
+  test_constructorName() async {
     await assertNoErrorsInCode(r'''
 class A {
   A.named() {}
@@ -27,7 +50,7 @@
 ''');
   }
 
-  test_implicitThisReferenceInInitializer_field() async {
+  test_field() async {
     await assertErrorsInCode(r'''
 class A {
   var v;
@@ -39,7 +62,7 @@
     ]);
   }
 
-  test_implicitThisReferenceInInitializer_field2() async {
+  test_field2() async {
     await assertErrorsInCode(r'''
 class A {
   final x = 0;
@@ -51,7 +74,7 @@
     ]);
   }
 
-  test_implicitThisReferenceInInitializer_invocation() async {
+  test_invocation() async {
     await assertErrorsInCode(r'''
 class A {
   var v;
@@ -63,7 +86,7 @@
     ]);
   }
 
-  test_implicitThisReferenceInInitializer_invocationInStatic() async {
+  test_invocationInStatic() async {
     await assertErrorsInCode(r'''
 class A {
   static var F = m();
@@ -74,137 +97,6 @@
     ]);
   }
 
-  test_implicitThisReferenceInInitializer_prefixedIdentifier() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var f;
-}
-class B {
-  var v;
-  B(A a) : v = a.f;
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_qualifiedMethodInvocation() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  f() {}
-}
-class B {
-  var v;
-  B() : v = new A().f();
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_qualifiedPropertyAccess() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var f;
-}
-class B {
-  var v;
-  B() : v = new A().f;
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_redirectingConstructorInvocation() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p) {}
-  A.named() : this(f);
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 39, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_staticField_thisClass() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-  static var f;
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_staticGetter() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-  static get f => 42;
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_staticMethod() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f();
-  static f() => 42;
-}
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_superConstructorInvocation() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p) {}
-}
-class B extends A {
-  B() : super(f);
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 56, 1),
-    ]);
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelField() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-}
-var f = 42;
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelFunction() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f();
-}
-f() => 42;
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_topLevelGetter() async {
-    await assertNoErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-}
-get f => 42;
-''');
-  }
-
-  test_implicitThisReferenceInInitializer_typeParameter() async {
-    await assertNoErrorsInCode(r'''
-class A<T> {
-  var v;
-  A(p) : v = (p is T);
-}
-''');
-  }
-
   test_isInInstanceVariableInitializer_restored() async {
     // If ErrorVerifier._isInInstanceVariableInitializer is not properly
     // restored on exit from visitVariableDeclaration, the error at (1)
@@ -226,4 +118,189 @@
       error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 89, 4),
     ]);
   }
+
+  test_prefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var f;
+}
+class B {
+  var v;
+  B(A a) : v = a.f;
+}
+''');
+  }
+
+  test_qualifiedMethodInvocation() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  f() {}
+}
+class B {
+  var v;
+  B() : v = new A().f();
+}
+''');
+  }
+
+  test_qualifiedPropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var f;
+}
+class B {
+  var v;
+  B() : v = new A().f;
+}
+''');
+  }
+
+  test_redirectingConstructorInvocation() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p) {}
+  A.named() : this(f);
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 39, 1),
+    ]);
+  }
+
+  test_staticField_thisClass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  static var f;
+}
+''');
+  }
+
+  test_staticGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  static get f => 42;
+}
+''');
+  }
+
+  test_staticMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f();
+  static f() => 42;
+}
+''');
+  }
+
+  test_superConstructorInvocation() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p) {}
+}
+class B extends A {
+  B() : super(f);
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 56, 1),
+    ]);
+  }
+
+  test_topLevelField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+}
+var f = 42;
+''');
+  }
+
+  test_topLevelFunction() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f();
+}
+f() => 42;
+''');
+  }
+
+  test_topLevelGetter() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+}
+get f => 42;
+''');
+  }
+
+  test_typeParameter() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  var v;
+  A(p) : v = (p is T);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ImplicitThisReferenceInInitializerWithNnbdTest
+    extends ImplicitThisReferenceInInitializerTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  test_class_field_late_invokeInstanceMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  late int x = foo();
+  int foo() => 0;
+}
+''');
+  }
+
+  test_class_field_late_invokeStaticMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  late int x = foo();
+  static int foo() => 0;
+}
+''');
+  }
+
+  test_class_field_late_readInstanceField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int a = 0;
+  late int x = a;
+}
+''');
+  }
+
+  test_class_field_late_readStaticField() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static int a = 0;
+  late int x = a;
+}
+''');
+  }
+
+  test_mixin_field_late_readInstanceField() async {
+    await assertNoErrorsInCode(r'''
+mixin M {
+  int a = 0;
+  late int x = a;
+}
+''');
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_non_virtual_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_non_virtual_annotation_test.dart
new file mode 100644
index 0000000..246c649
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_non_virtual_annotation_test.dart
@@ -0,0 +1,282 @@
+// 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:analyzer/src/test_utilities/package_mixin.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidNonVirtualAnnotationTest);
+  });
+}
+
+@reflectiveTest
+class InvalidNonVirtualAnnotationTest extends DriverResolutionTest
+    with PackageMixin {
+  setUp() {
+    super.setUp();
+    addMetaPackage();
+  }
+
+  test_class() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+class C {}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_class_abstract_member() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+abstract class C {
+  @nonVirtual
+  void m();
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 55, 11),
+    ]);
+  }
+
+  test_class_getter() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int get g => 0;
+}
+''');
+  }
+
+  test_class_instance_field() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int f;
+}
+''');
+  }
+
+  test_class_instance_member() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  void m() {
+  }
+}
+''');
+  }
+
+  test_class_setter() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  set s(int v) {}
+}
+''');
+  }
+
+  test_class_static_field() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+   @nonVirtual
+   static int f;
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 47, 11),
+    ]);
+  }
+
+  test_class_static_method() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+   @nonVirtual
+   static void m() {}
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 47, 11),
+    ]);
+  }
+
+  test_enum() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+enum E {
+  a, b, c
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_enum_constant() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+enum E {
+  @nonVirtual
+  a,
+  b, c
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 45, 11),
+    ]);
+  }
+
+  test_extension() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+extension E on Object {}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_extension_member() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+extension E on Object {
+   @nonVirtual
+   void m() {}
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 61, 11),
+    ]);
+  }
+
+  test_import() async {
+    await assertErrorsInCode(r'''
+@nonVirtual
+import 'package:meta/meta.dart';
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 0, 11),
+    ]);
+  }
+
+  test_mixin() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+mixin M {}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_mixin_instance_member() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+mixin M {
+  @nonVirtual
+  void m() {}
+}
+''');
+  }
+
+  test_mixin_static_field() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+mixin M {
+  @nonVirtual
+  static int f;
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 46, 11),
+    ]);
+  }
+
+  test_mixin_static_method() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+mixin M {
+  @nonVirtual
+  static void m() {}
+}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 46, 11),
+    ]);
+  }
+
+  test_top_level_function() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+m() {}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_top_level_getter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+int get g =>  0;
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_top_level_setter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+set s(int v) {}
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_top_level_var() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+int x;
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+
+  test_typedef() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@nonVirtual
+typedef bool predicate(Object o);
+''', [
+      error(HintCode.INVALID_NON_VIRTUAL_ANNOTATION, 34, 11),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_of_non_virtual_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_of_non_virtual_member_test.dart
new file mode 100644
index 0000000..de618de
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_of_non_virtual_member_test.dart
@@ -0,0 +1,253 @@
+// 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:analyzer/src/test_utilities/package_mixin.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidOverrideOfNonVirtualMemberTest);
+  });
+}
+
+@reflectiveTest
+class InvalidOverrideOfNonVirtualMemberTest extends DriverResolutionTest
+    with PackageMixin {
+  setUp() {
+    super.setUp();
+    addMetaPackage();
+  }
+
+  test_class_field() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int g = 0;
+}
+
+class B extends C  {
+  @override
+  int g = 0;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 113, 1),
+    ]);
+  }
+
+  test_class_field_2() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int g = 0;
+}
+
+class B extends C  {
+  int g = 0, h = 1;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 101, 1),
+    ]);
+  }
+
+  test_class_field_overriddenByGetter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int g = 0;
+}
+
+class B extends C  {
+  @override
+  int get g => 0;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 117, 1),
+    ]);
+  }
+
+  test_class_field_overriddenBySetter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int g = 0;
+}
+
+class B extends C  {
+  @override
+  set g(int v) {}
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 113, 1),
+    ]);
+  }
+
+  test_class_getter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int get g => 0;
+}
+
+class B extends C  {
+  @override
+  int get g => 0;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 122, 1),
+    ]);
+  }
+
+  test_class_getter_overriddenByField() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int get g => 0;
+}
+
+class B extends C  {
+  @override
+  int g = 0;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 118, 1),
+    ]);
+  }
+
+  test_class_implements_getter() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  int get g => 0;
+}
+
+class B implements C  {
+  @override
+  int get g => 0; //OK
+}
+''');
+  }
+
+  test_class_implements_method() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  void f() {}
+}
+
+class B implements C  {
+  @override
+  void f() {} //OK
+}
+''');
+  }
+
+  test_class_method() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  void f() {}
+}
+
+class B extends C  {
+  @override
+  void f() {}
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 115, 1),
+    ]);
+  }
+
+  test_class_setter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  set g(int v) {}
+}
+
+class B extends C  {
+  @override
+  set g(int v) {}
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 118, 1),
+    ]);
+  }
+
+  test_class_setter_overriddenByField() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+class C {
+  @nonVirtual
+  set g(int v) {}
+}
+
+class B extends C  {
+  @override
+  int g = 0;
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 118, 1),
+    ]);
+  }
+
+  test_mixin_method() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+mixin M {
+  @nonVirtual
+  void f() {}
+}
+
+class B with M {
+  @override
+  void f() {}
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 111, 1),
+    ]);
+  }
+
+  test_mixin_setter() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+mixin M {
+  @nonVirtual
+  set g(int v) {}
+}
+
+class B with M {
+  @override
+  set g(int v) {}
+}
+''', [
+      error(HintCode.INVALID_OVERRIDE_OF_NON_VIRTUAL_MEMBER, 114, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_null_value_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_null_value_test.dart
index 6bbcb48..aa815e1 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_use_of_null_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_null_value_test.dart
@@ -40,14 +40,12 @@
   }
 
   test_cascade() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 m() {
   Null x;
   x..toString;
 }
-''', [
-      error(StaticWarningCode.INVALID_USE_OF_NULL_VALUE, 18, 1),
-    ]);
+''');
   }
 
   test_eq() async {
diff --git a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
index 679f2ce..4574d92 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
@@ -74,6 +74,16 @@
 ''');
   }
 
+  test_class_nullable_named_optional_noDefault_fieldFormal() async {
+    await assertNoErrorsInCode('''
+typedef F = T Function<T>(T);
+class C {
+  F? f;
+  C({this.f});
+}
+''');
+  }
+
   test_class_nullable_named_required() async {
     await assertNoErrorsInCode('''
 void f({required int? a}) {}
@@ -119,6 +129,178 @@
 ''');
   }
 
+  test_futureOr_nonNullable_nonNullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int> a = 0}) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nonNullable_named_optional_noDefault() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int> a}) {}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 43, 1),
+    ]);
+  }
+
+  test_futureOr_nonNullable_nonNullable_named_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({required FutureOr<int> a}) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nonNullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int> a = 0]) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nonNullable_positional_optional_noDefault() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int> a]) {}
+''', [
+      error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 43, 1),
+    ]);
+  }
+
+  test_futureOr_nonNullable_nonNullable_positional_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f(FutureOr<int> a) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int>? a = 0}) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int>? a}) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_named_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({required FutureOr<int>? a}) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int>? a = 0]) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int>? a]) {}
+''');
+  }
+
+  test_futureOr_nonNullable_nullable_positional_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f(FutureOr<int>? a) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int?> a = 0}) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int?> a}) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_named_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({required FutureOr<int?> a}) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int?> a = 0]) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int?> a]) {}
+''');
+  }
+
+  test_futureOr_nullable_nonNullable_positional_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f(FutureOr<int?> a) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_named_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int?>? a = 0}) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_named_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({FutureOr<int?>? a}) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_named_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f({required FutureOr<int?>? a}) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_positional_optional_default() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int?>? a = 0]) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_positional_optional_noDefault() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f([FutureOr<int?>? a]) {}
+''');
+  }
+
+  test_futureOr_nullable_nullable_positional_required() async {
+    await assertNoErrorsInCode('''
+import 'dart:async';
+void f(FutureOr<int?>? a) {}
+''');
+  }
+
   test_genericFunctionType() async {
     await assertNoErrorsInCode('''
 void Function({String s})? log;
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
index 56a4de8..666d6a1 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -36,7 +36,7 @@
 import 'dart:async';
 Future<int> f() async {}
 ''', [
-      error(HintCode.MISSING_RETURN, 21, 11),
+      error(HintCode.MISSING_RETURN, 33, 1),
     ]);
   }
 
@@ -81,7 +81,7 @@
     await assertErrorsInCode(r'''
 int f() {}
 ''', [
-      error(HintCode.MISSING_RETURN, 0, 3),
+      error(HintCode.MISSING_RETURN, 4, 1),
     ]);
   }
 
@@ -166,7 +166,21 @@
   int m() {}
 }
 ''', [
-      error(HintCode.MISSING_RETURN, 12, 3),
+      error(HintCode.MISSING_RETURN, 16, 1),
+    ]);
+  }
+
+  test_method_annotation() async {
+    await assertErrorsInCode(r'''
+abstract class A {
+  int m();
+}
+@override
+class B extends A {
+  m() {}
+}
+''', [
+      error(HintCode.MISSING_RETURN, 64, 1),
     ]);
   }
 
@@ -186,7 +200,7 @@
   FutureOr<int> m() {}
 }
 ''', [
-      error(HintCode.MISSING_RETURN, 33, 13),
+      error(HintCode.MISSING_RETURN, 47, 1),
     ]);
   }
 
@@ -199,7 +213,7 @@
   m() {}
 }
 ''', [
-      error(HintCode.MISSING_RETURN, 54, 6),
+      error(HintCode.MISSING_RETURN, 54, 1),
     ]);
   }
 
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
new file mode 100644
index 0000000..6c1287c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/must_be_a_native_function_type_test.dart
@@ -0,0 +1,58 @@
+// 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/dart/error/ffi_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MustBeANativeFunctionTypeTest);
+  });
+}
+
+@reflectiveTest
+class MustBeANativeFunctionTypeTest extends DriverResolutionTest {
+  test_fromFunction() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+int f(int i) => i * 2;
+class C<T extends Function> {
+  void g() {
+    Pointer.fromFunction<T>(f);
+  }
+}
+''', [
+      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 89, 26),
+    ]);
+  }
+
+  test_lookupFunction() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+typedef S = int Function(int);
+typedef F = String Function(String);
+void f(DynamicLibrary lib) {
+  lib.lookupFunction<S, F>('g');
+}
+''', [
+      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 137, 1),
+    ]);
+  }
+
+  test_lookupFunction_T() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+typedef F = int Function(int);
+class C<T extends Function> {
+  void f(DynamicLibrary lib, NativeFunction x) {
+    lib.lookupFunction<T, F>('g');
+  }
+}
+''', [
+      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 152, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_a_subtype_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_a_subtype_test.dart
index f9e9334..244a8c6 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_a_subtype_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_a_subtype_test.dart
@@ -15,21 +15,6 @@
 
 @reflectiveTest
 class MustBeASubtypeTest extends DriverResolutionTest {
-  test_asFunction() async {
-    await assertErrorsInCode(r'''
-import 'dart:ffi';
-typedef TPrime = int Function(int);
-typedef F = String Function(String);
-class C {
-  void f(Pointer<NativeFunction<TPrime>> p) {
-    p.asFunction<F>();
-  }
-}
-''', [
-      error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 165, 1),
-    ]);
-  }
-
   test_fromFunction_firstArgument() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
@@ -78,16 +63,17 @@
 ''');
   }
 
-  test_lookupFunction() async {
+  test_lookupFunction_F() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
-typedef S = int Function(int);
-typedef F = String Function(String);
-void f(DynamicLibrary lib) {
-  lib.lookupFunction<S, F>('g');
+typedef T = Int8 Function(Int8);
+class C<F extends int Function(int)> {
+  void f(DynamicLibrary lib, NativeFunction x) {
+    lib.lookupFunction<T, F>('g');
+  }
 }
 ''', [
-      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 137, 1),
+      error(FfiCode.MUST_BE_A_SUBTYPE, 166, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
index 4b5275e..5754334 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_test.dart
@@ -28,46 +28,4 @@
       error(FfiCode.NON_CONSTANT_TYPE_ARGUMENT, 147, 1),
     ]);
   }
-
-  test_fromFunction() async {
-    await assertErrorsInCode(r'''
-import 'dart:ffi';
-int f(int i) => i * 2;
-class C<T extends Function> {
-  void g() {
-    Pointer.fromFunction<T>(f);
-  }
-}
-''', [
-      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 89, 26),
-    ]);
-  }
-
-  test_lookupFunction_F() async {
-    await assertErrorsInCode(r'''
-import 'dart:ffi';
-typedef T = Int8 Function(Int8);
-class C<F extends int Function(int)> {
-  void f(DynamicLibrary lib, NativeFunction x) {
-    lib.lookupFunction<T, F>('g');
-  }
-}
-''', [
-      error(FfiCode.MUST_BE_A_SUBTYPE, 166, 1),
-    ]);
-  }
-
-  test_lookupFunction_T() async {
-    await assertErrorsInCode(r'''
-import 'dart:ffi';
-typedef F = int Function(int);
-class C<T extends Function> {
-  void f(DynamicLibrary lib, NativeFunction x) {
-    lib.lookupFunction<T, F>('g');
-  }
-}
-''', [
-      error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 152, 1),
-    ]);
-  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_to_pointer_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_to_pointer_test.dart
deleted file mode 100644
index a0aee94..0000000
--- a/pkg/analyzer/test/src/diagnostics/non_constant_type_argument_to_pointer_test.dart
+++ /dev/null
@@ -1,31 +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/dart/error/ffi_code.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/driver_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(NonConstantTypeArgumentToPointerTest);
-  });
-}
-
-@reflectiveTest
-class NonConstantTypeArgumentToPointerTest extends DriverResolutionTest {
-  test_asFunction_F() async {
-    await assertErrorsInCode(r'''
-import 'dart:ffi';
-typedef R = int Function(int);
-class C<T extends Function> {
-  void f(Pointer<NativeFunction<T>> p) {
-    p.asFunction<R>();
-  }
-}
-''', [
-      error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 138, 1),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/non_native_function_type_argument_to_pointer_test.dart b/pkg/analyzer/test/src/diagnostics/non_native_function_type_argument_to_pointer_test.dart
index ac8e808..0928850 100644
--- a/pkg/analyzer/test/src/diagnostics/non_native_function_type_argument_to_pointer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_native_function_type_argument_to_pointer_test.dart
@@ -15,7 +15,7 @@
 
 @reflectiveTest
 class NonNativeFunctionTypeArgumentToPointerTest extends DriverResolutionTest {
-  test_asFunction() async {
+  test_asFunction_1() async {
     await assertErrorsInCode(r'''
 import 'dart:ffi';
 typedef R = Int8 Function(Int8);
@@ -28,4 +28,33 @@
       error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 109, 1),
     ]);
   }
+
+  test_asFunction_2() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+typedef TPrime = int Function(int);
+typedef F = String Function(String);
+class C {
+  void f(Pointer<NativeFunction<TPrime>> p) {
+    p.asFunction<F>();
+  }
+}
+''', [
+      error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 165, 1),
+    ]);
+  }
+
+  test_asFunction_F() async {
+    await assertErrorsInCode(r'''
+import 'dart:ffi';
+typedef R = int Function(int);
+class C<T extends Function> {
+  void f(Pointer<NativeFunction<T>> p) {
+    p.asFunction<R>();
+  }
+}
+''', [
+      error(FfiCode.NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER, 138, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/not_a_type_test.dart b/pkg/analyzer/test/src/diagnostics/not_a_type_test.dart
index 7eb1b7d..d6af0b2 100644
--- a/pkg/analyzer/test/src/diagnostics/not_a_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_a_type_test.dart
@@ -42,6 +42,8 @@
 extension E on int {}
 E a;
 ''', [error(StaticWarningCode.NOT_A_TYPE, 22, 1)]);
-    assertTypeDynamic(findNode.simple('E a;'));
+    var typeName = findNode.typeName('E a;');
+    assertElementTypeDynamic(typeName.type);
+    assertTypeNull(typeName.name);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/redirect_to_non_const_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/redirect_to_non_const_constructor_test.dart
new file mode 100644
index 0000000..490adef
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/redirect_to_non_const_constructor_test.dart
@@ -0,0 +1,80 @@
+// 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/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RedirectToNonConstConstructorTest);
+  });
+}
+
+@reflectiveTest
+class RedirectToNonConstConstructorTest extends DriverResolutionTest {
+  test_constRedirector_cannotResolveRedirectee() async {
+    // No crash when redirectee cannot be resolved.
+    await assertErrorsInCode(r'''
+class A {
+  const factory A.b() = A.a;
+}
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_MISSING_CONSTRUCTOR, 34, 3),
+    ]);
+  }
+
+  test_constRedirector_constRedirectee() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  const A.a();
+  const factory A.b() = A.a;
+}
+''');
+  }
+
+  test_constRedirector_constRedirectee_viaInitializer() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  const A.a();
+  const A.b() : this.a();
+}
+''');
+  }
+
+  test_constRedirector_nonConstRedirectee() async {
+    await assertErrorsInCode(r'''
+class A {
+  A.a();
+  const factory A.b() = A.a;
+}
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, 43, 3),
+    ]);
+  }
+
+  test_constRedirector_nonConstRedirectee_viaInitializer() async {
+    await assertErrorsInCode(r'''
+class A {
+  A.a();
+  const A.b() : this.a();
+}
+''', [
+      error(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONSTRUCTOR, 40, 1),
+    ]);
+  }
+
+  test_constRedirector_viaInitializer_cannotResolveRedirectee() async {
+    // No crash when redirectee cannot be resolved.
+    await assertErrorsInCode(r'''
+class A {
+  const A.b() : this.a();
+}
+''', [
+      error(CompileTimeErrorCode.REDIRECT_GENERATIVE_TO_MISSING_CONSTRUCTOR, 26,
+          8),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index a46bc359..f7fe172 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -134,12 +134,16 @@
 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_literal_annotation_test.dart' as invalid_literal_annotation;
+import 'invalid_non_virtual_annotation_test.dart'
+    as invalid_non_virtual_annotation;
 import 'invalid_optional_parameter_type_test.dart'
     as invalid_optional_parameter_type;
 import 'invalid_override_different_default_values_named_test.dart'
     as invalid_override_different_default_values_named;
 import 'invalid_override_different_default_values_positional_test.dart'
     as invalid_override_different_default_values_positional;
+import 'invalid_override_of_non_virtual_member_test.dart'
+    as invalid_override_of_non_virtual_member;
 import 'invalid_override_test.dart' as invalid_override;
 import 'invalid_reference_to_this_test.dart' as invalid_reference_to_this;
 import 'invalid_required_named_param_test.dart' as invalid_required_named_param;
@@ -191,6 +195,8 @@
 import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
 import 'mixin_super_class_constraint_non_interface_test.dart'
     as mixin_super_class_constraint_non_interface;
+import 'must_be_a_native_function_type_test.dart'
+    as must_be_a_native_function_type;
 import 'must_be_a_subtype_test.dart' as must_be_a_subtype;
 import 'must_be_immutable_test.dart' as must_be_immutable;
 import 'must_call_super_test.dart' as must_call_super;
@@ -217,8 +223,6 @@
 import 'non_constant_map_value_test.dart' as non_constant_map_value;
 import 'non_constant_set_element_test.dart' as non_constant_set_element;
 import 'non_constant_type_argument_test.dart' as non_constant_type_argument;
-import 'non_constant_type_argument_to_pointer_test.dart'
-    as non_constant_type_argument_to_pointer;
 import 'non_native_function_type_argument_to_pointer_test.dart'
     as non_native_function_type_argument_to_pointer;
 import 'non_null_opt_out_test.dart' as non_null_opt_out;
@@ -267,6 +271,8 @@
 import 'redirect_to_missing_constructor_test.dart'
     as redirect_to_missing_constructor;
 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 '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;
@@ -447,9 +453,11 @@
     invalid_field_type_in_struct.main();
     invalid_immutable_annotation.main();
     invalid_literal_annotation.main();
+    invalid_non_virtual_annotation.main();
     invalid_optional_parameter_type.main();
     invalid_override_different_default_values_named.main();
     invalid_override_different_default_values_positional.main();
+    invalid_override_of_non_virtual_member.main();
     invalid_override.main();
     invalid_reference_to_this.main();
     invalid_required_named_param.main();
@@ -486,6 +494,7 @@
     mixin_of_non_class.main();
     mixin_on_sealed_class.main();
     mixin_super_class_constraint_non_interface.main();
+    must_be_a_native_function_type.main();
     must_be_a_subtype.main();
     must_be_immutable.main();
     must_call_super.main();
@@ -506,7 +515,6 @@
     non_constant_map_value_from_deferred_library.main();
     non_constant_set_element.main();
     non_constant_type_argument.main();
-    non_constant_type_argument_to_pointer.main();
     non_native_function_type_argument_to_pointer.main();
     non_null_opt_out.main();
     non_type_in_catch_clause.main();
@@ -538,6 +546,7 @@
     redirect_to_invalid_return_type.main();
     redirect_to_missing_constructor.main();
     redirect_to_non_class.main();
+    redirect_to_non_const_constructor.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/unchecked_use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
index 249a0f4..cc17c45 100644
--- a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -215,7 +215,47 @@
 ''');
   }
 
-  test_cascade_nullable() async {
+  test_cascade_nullable_indexed_assignment() async {
+    await assertErrorsInCode(r'''
+m() {
+  List<int>? x;
+  x..[0] = 1;
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+    ]);
+  }
+
+  test_cascade_nullable_indexed_assignment_null_aware() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  List<int>? x;
+  x?..[0] = 1;
+}
+''');
+  }
+
+  test_cascade_nullable_method_invocation() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x..abs();
+}
+''', [
+      error(StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 18, 1),
+    ]);
+  }
+
+  test_cascade_nullable_method_invocation_null_aware() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x?..abs();
+}
+''');
+  }
+
+  test_cascade_nullable_property_access() async {
     await assertErrorsInCode(r'''
 m() {
   int? x;
@@ -226,6 +266,15 @@
     ]);
   }
 
+  test_cascade_nullable_property_access_null_aware() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x?..isEven;
+}
+''');
+  }
+
   test_eqEq_nullable() async {
     await assertNoErrorsInCode(r'''
 m() {
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart
index 36fe2ea..b2c5f28 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_extension_operator_test.dart
@@ -197,4 +197,26 @@
 }
 ''');
   }
+
+  test_prefix_minus_defined() async {
+    await assertNoErrorsInCode('''
+extension E on String {
+  String operator -() => substring(1);
+}
+f() {
+  -E('a');
+}
+''');
+  }
+
+  test_prefix_minus_undefined() async {
+    await assertErrorsInCode('''
+extension E on String {}
+f() {
+  -E('a');
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR, 33, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
index 727f808..dd021db 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UnnecessaryTypeCheckFalseTest);
+    defineReflectiveTests(UnnecessaryTypeCheckFalseWithNnbdTest);
   });
 }
 
@@ -17,31 +20,57 @@
 class UnnecessaryTypeCheckFalseTest extends DriverResolutionTest {
   test_null_not_Null() async {
     await assertErrorsInCode(r'''
-bool b = null is! Null;
+var b = null is! Null;
 ''', [
-      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 9, 13),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 8, 13),
     ]);
   }
 
   test_type_not_dynamic() async {
     await assertErrorsInCode(r'''
-m(i) {
-  bool b = i is! dynamic;
+void f<T>(T a) {
+  a is! dynamic;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
-      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 18, 13),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 19, 13),
     ]);
   }
 
   test_type_not_object() async {
     await assertErrorsInCode(r'''
-m(i) {
-  bool b = i is! Object;
+void f<T>(T a) {
+  a is! Object;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
-      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 18, 12),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 19, 12),
+    ]);
+  }
+}
+
+@reflectiveTest
+class UnnecessaryTypeCheckFalseWithNnbdTest
+    extends UnnecessaryTypeCheckFalseTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  test_type_not_object() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T a) {
+  a is! Object;
+}
+''');
+  }
+
+  test_type_not_objectQuestion() async {
+    await assertErrorsInCode(r'''
+void f<T>(T a) {
+  a is! Object?;
+}
+''', [
+      error(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, 19, 13),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
index daae87f..9a2d852 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
@@ -2,7 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UnnecessaryTypeCheckTrueTest);
+    defineReflectiveTests(UnnecessaryTypeCheckTrueWithNnbdTest);
   });
 }
 
@@ -17,31 +20,57 @@
 class UnnecessaryTypeCheckTrueTest extends DriverResolutionTest {
   test_null_is_Null() async {
     await assertErrorsInCode(r'''
-bool b = null is Null;
+var b = null is Null;
 ''', [
-      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 9, 12),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 8, 12),
     ]);
   }
 
   test_type_is_dynamic() async {
     await assertErrorsInCode(r'''
-m(i) {
-  bool b = i is dynamic;
+void f<T>(T a) {
+  a is dynamic;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
-      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 18, 12),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 19, 12),
     ]);
   }
 
   test_type_is_object() async {
     await assertErrorsInCode(r'''
-m(i) {
-  bool b = i is Object;
+void f<T>(T a) {
+  a is Object;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
-      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 18, 11),
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 19, 11),
+    ]);
+  }
+}
+
+@reflectiveTest
+class UnnecessaryTypeCheckTrueWithNnbdTest
+    extends UnnecessaryTypeCheckTrueTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..contextFeatures = FeatureSet.forTesting(
+        sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  test_type_is_object() async {
+    await assertNoErrorsInCode(r'''
+void f<T>(T a) {
+  a is Object;
+}
+''');
+  }
+
+  test_type_is_objectQuestion() async {
+    await assertErrorsInCode(r'''
+void f<T>(T a) {
+  a is Object?;
+}
+''', [
+      error(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, 19, 12),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
index 52917c9..99fd027 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
@@ -709,4 +709,20 @@
       error(StaticWarningCode.USE_OF_VOID_RESULT, 96, 4),
     ]);
   }
+
+  test_void() async {
+    await assertErrorsInCode('''
+extension E on String {
+  int get g => 0;
+}
+
+void f() {}
+
+main() {
+  E(f()).g;
+}
+''', [
+      error(StaticWarningCode.USE_OF_VOID_RESULT, 71, 3),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/fasta/token_utils_test.dart b/pkg/analyzer/test/src/fasta/token_utils_test.dart
index 40e05d0..5f138e8 100644
--- a/pkg/analyzer/test/src/fasta/token_utils_test.dart
+++ b/pkg/analyzer/test/src/fasta/token_utils_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/fasta/token_utils.dart';
-import 'package:front_end/src/fasta/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/analyzer/test/src/lint/config_test.dart b/pkg/analyzer/test/src/lint/config_test.dart
index bd39e89..082b835 100644
--- a/pkg/analyzer/test/src/lint/config_test.dart
+++ b/pkg/analyzer/test/src/lint/config_test.dart
@@ -122,9 +122,9 @@
               (RuleConfig rc1, RuleConfig rc2) => rc1.name.compareTo(rc2.name));
           expect(ruleConfigs, hasLength(2));
           expect(ruleConfigs[0].name, 'camel_case_types');
-          expect(config.ruleConfigs[0].args['enabled'], isFalse);
+          expect(ruleConfigs[0].args['enabled'], isTrue);
           expect(ruleConfigs[1].name, 'unnecessary_getters');
-          expect(config.ruleConfigs[1].args['enabled'], isTrue);
+          expect(ruleConfigs[1].args['enabled'], isFalse);
         });
       });
     });
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 06b49c5..8e48671 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:test/test.dart';
@@ -25,6 +26,15 @@
   Future<void> resolve(String content) async {
     await resolveTestCode(content);
     var contextUnit = LinterContextUnit(result.content, result.unit);
+
+    final libraryPath = result.libraryElement.source.fullName;
+    final builder = new ContextBuilder(
+        resourceProvider, null /* sdkManager */, null /* contentCache */);
+    // todo (pq): get workspace from analysis context
+    final workspace =
+        ContextBuilder.createWorkspace(resourceProvider, libraryPath, builder);
+    final workspacePackage = workspace.findPackageFor(libraryPath);
+
     context = new LinterContextImpl(
       [contextUnit],
       contextUnit,
@@ -33,6 +43,8 @@
       result.typeSystem,
       InheritanceManager3(result.typeSystem),
       analysisOptions,
+      // todo (pq): test package or consider passing in null
+      workspacePackage,
     );
   }
 }
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 4e70ff2..0a3945b 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -2962,6 +2962,42 @@
     }
   }
 
+  test_simple_dependenciesFromKnownFiles() async {
+    var a = convertPath('/home/test/bin/a.dart');
+    var b = convertPath('/home/test/bin/b.dart');
+    var c = convertPath('/home/test/bin/c.dart');
+
+    newFile(a, content: 'class A {}');
+    newFile(b, content: 'class B {}');
+    newFile(c, content: 'class C {}');
+    testAnalysisContext.currentSession.getFile(a);
+    testAnalysisContext.currentSession.getFile(b);
+    testAnalysisContext.currentSession.getFile(c);
+
+    var context = tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+    tracker.pullKnownFiles();
+
+    var libraries = context.getLibraries(b);
+    _assertHasLibraries(
+      libraries.sdk,
+      uriList: ['dart:core', 'dart:async'],
+    );
+    _assertHasLibraries(
+      libraries.dependencies,
+      uriList: [],
+      only: true,
+    );
+    _assertHasLibraries(
+      libraries.context,
+      uriList: [
+        toUriStr(a),
+        toUriStr(c),
+      ],
+      only: true,
+    );
+  }
+
   static void _assertHasLibraries(List<Library> libraries,
       {@required List<String> uriList, bool only = false}) {
     var actualUriList = libraries.map((lib) => lib.uriStr).toList();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 4418dfc..1ab09c0 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -442,14 +442,6 @@
       } else {
         buffer.write('<null>');
       }
-    } else {
-      buffer.write('typedef ');
-      writeType2(e.returnType);
-
-      writeName(e);
-
-      writeTypeParameterElements(e.typeParameters);
-      writeParameterElements(e.parameters);
     }
 
     buffer.writeln(';');
@@ -1042,8 +1034,6 @@
       if (type.element.typeParameters.isNotEmpty) {
         writeList('<', '>', type.typeArguments, ', ', writeType);
       }
-    } else if (type is CircularFunctionTypeImpl) {
-      buffer.write('...');
     } else if (type is FunctionType) {
       writeType2(type.returnType);
       buffer.write('Function');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 223e3b7..4f81d47 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -7589,6 +7589,21 @@
 ''');
   }
 
+  test_instantiateToBounds_genericFunctionAsBound() async {
+    var library = await checkLibrary('''
+class A<T> {}
+class B<T extends int Function(), U extends A<T>> {}
+B b;
+''');
+    checkElementText(library, r'''
+class A<T> {
+}
+notSimplyBounded class B<T extends int Function(), U extends A<T>> {
+}
+B<int Function(), A<int Function()>> b;
+''');
+  }
+
   test_instantiateToBounds_genericTypeAlias_simple() async {
     var library = await checkLibrary('''
 typedef F<T extends num> = S Function<S>(T p);
@@ -10048,6 +10063,7 @@
         annotateNullability: true);
   }
 
+  @deprecated
   test_type_param_generic_function_type_nullability_legacy() async {
     featureSet = disableNnbd;
     var library = await checkLibrary('''
@@ -10065,6 +10081,7 @@
     expect((t.type as TypeImpl).nullabilitySuffix, NullabilitySuffix.star);
   }
 
+  @deprecated
   test_type_param_generic_function_type_nullability_migrated() async {
     featureSet = enableNnbd;
     var library = await checkLibrary('''
@@ -10495,8 +10512,8 @@
 F f;
 ''');
     checkElementText(library, r'''
-typedef F = <null>;
-dynamic f;
+typedef F = dynamic Function();
+dynamic Function() f;
 ''');
   }
 
@@ -11254,7 +11271,7 @@
         type: TypeName
           name: SimpleIdentifier
             staticElement: self::@class::A
-            staticType: A<dynamic>
+            staticType: null
             token: A
           type: A<int>
       staticElement: ConstructorMember
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index 5a7066d..da2d4ac 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -575,7 +575,7 @@
     {
       var node = findNode.simple('w in');
       VariableElement element = node.staticElement;
-      expect(node.staticType, typeProvider.dynamicType);
+      expect(node.staticType, isNull);
       expect(element.type, typeProvider.dynamicType);
 
       var invocation = findNode.methodInvocation('f()) {} // 1');
@@ -585,7 +585,7 @@
     {
       var node = findNode.simple('x in');
       VariableElement element = node.staticElement;
-      expect(node.staticType, typeProvider.numType);
+      expect(node.staticType, isNull);
       expect(element.type, typeProvider.numType);
     }
 
@@ -593,7 +593,7 @@
       var node = findNode.simple('y in');
       VariableElement element = node.staticElement;
 
-      expect(node.staticType, typeProvider.numType);
+      expect(node.staticType, isNull);
       expect(element.type, typeProvider.numType);
 
       var invocation = findNode.methodInvocation('f()) {} // 3');
@@ -684,7 +684,7 @@
     await resolveTestCode(code);
     var xNode = findNode.simple('x) {}');
     VariableElement xElement = xNode.staticElement;
-    expect(xNode.staticType, typeProvider.objectType);
+    expect(xNode.staticType, isNull);
     expect(xElement.type, typeProvider.objectType);
   }
 
diff --git a/pkg/analyzer/test/src/workspace/basic_test.dart b/pkg/analyzer/test/src/workspace/basic_test.dart
index cdd5e28..a4d4752 100644
--- a/pkg/analyzer/test/src/workspace/basic_test.dart
+++ b/pkg/analyzer/test/src/workspace/basic_test.dart
@@ -12,24 +12,6 @@
 
 import '../../generated/test_support.dart';
 
-class MockContextBuilder implements ContextBuilder {
-  Map<String, Packages> packagesMapMap = <String, Packages>{};
-  Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
-      <Packages, Map<String, List<Folder>>>{};
-
-  Map<String, List<Folder>> convertPackagesToMap(Packages packages) =>
-      packagesToMapMap[packages];
-
-  Packages createPackageMap(String rootDirectoryPath) =>
-      packagesMapMap[rootDirectoryPath];
-
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
-class MockPackages implements Packages {
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
-
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(BasicWorkspaceTest);
@@ -38,34 +20,6 @@
 }
 
 @reflectiveTest
-class BasicWorkspaceTest with ResourceProviderMixin {
-  setUp() {
-    newFolder('/workspace');
-  }
-
-  void test_find_fail_notAbsolute() {
-    expect(
-        () => BasicWorkspace.find(resourceProvider, convertPath('not_absolute'),
-            new MockContextBuilder()),
-        throwsA(TypeMatcher<ArgumentError>()));
-  }
-
-  void test_find_directory() {
-    BasicWorkspace workspace = BasicWorkspace.find(
-        resourceProvider, convertPath('/workspace'), new MockContextBuilder());
-    expect(workspace.root, convertPath('/workspace'));
-  }
-
-  void test_find_file() {
-    BasicWorkspace workspace = BasicWorkspace.find(
-        resourceProvider,
-        convertPath('/workspace/project/lib/lib1.dart'),
-        new MockContextBuilder());
-    expect(workspace.root, convertPath('/workspace/project/lib'));
-  }
-}
-
-@reflectiveTest
 class BasicWorkspacePackageTest with ResourceProviderMixin {
   BasicWorkspace workspace;
 
@@ -81,24 +35,6 @@
         resourceProvider, convertPath('/workspace'), contextBuilder);
   }
 
-  void test_findPackageFor_unrelatedFile() {
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace2/project/lib/file.dart'));
-    expect(package, isNull);
-  }
-
-  void test_findPackageFor_includedFile() {
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
-    expect(package, isNotNull);
-    expect(package.root, convertPath('/workspace'));
-    expect(package.workspace, equals(workspace));
-  }
-
   void test_contains_differentWorkspace() {
     newFile('/workspace2/project/lib/file.dart');
 
@@ -128,4 +64,68 @@
             TestSource(convertPath('/workspace/project/test/test.dart'))),
         isTrue);
   }
+
+  void test_findPackageFor_includedFile() {
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/workspace'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_unrelatedFile() {
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace2/project/lib/file.dart'));
+    expect(package, isNull);
+  }
+}
+
+@reflectiveTest
+class BasicWorkspaceTest with ResourceProviderMixin {
+  setUp() {
+    newFolder('/workspace');
+  }
+
+  void test_find_directory() {
+    BasicWorkspace workspace = BasicWorkspace.find(
+        resourceProvider, convertPath('/workspace'), new MockContextBuilder());
+    expect(workspace.root, convertPath('/workspace'));
+  }
+
+  void test_find_fail_notAbsolute() {
+    expect(
+        () => BasicWorkspace.find(resourceProvider, convertPath('not_absolute'),
+            new MockContextBuilder()),
+        throwsA(TypeMatcher<ArgumentError>()));
+  }
+
+  void test_find_file() {
+    BasicWorkspace workspace = BasicWorkspace.find(
+        resourceProvider,
+        convertPath('/workspace/project/lib/lib1.dart'),
+        new MockContextBuilder());
+    expect(workspace.root, convertPath('/workspace/project/lib'));
+  }
+}
+
+class MockContextBuilder implements ContextBuilder {
+  Map<String, Packages> packagesMapMap = <String, Packages>{};
+  Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
+      <Packages, Map<String, List<Folder>>>{};
+
+  Map<String, List<Folder>> convertPackagesToMap(Packages packages) =>
+      packagesToMapMap[packages];
+
+  Packages createPackageMap(String rootDirectoryPath) =>
+      packagesMapMap[rootDirectoryPath];
+
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockPackages implements Packages {
+  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/analyzer/test/src/workspace/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart
index aab84ef..f2080c5 100644
--- a/pkg/analyzer/test/src/workspace/bazel_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -6,6 +6,7 @@
 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:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -486,7 +487,153 @@
 }
 
 @reflectiveTest
+class BazelWorkspacePackageTest with ResourceProviderMixin {
+  BazelWorkspace workspace;
+  BazelWorkspacePackage package;
+
+  void test_contains_differentPackage_summarySource() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+    var source = InSummarySource(
+        Uri.parse('package:some.other.code/file.dart'), '' /* summaryPath */);
+    expect(package.contains(source), isFalse);
+  }
+
+  void test_contains_differentPackageInWorkspace() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+
+    // A file that is _not_ in this package is not required to have a BUILD
+    // file above it, for simplicity and reduced I/O.
+    expect(
+        package
+            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
+        isFalse);
+  }
+
+  void test_contains_differentWorkspace() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
+        isFalse);
+  }
+
+  void test_contains_samePackage() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+    final targetFile = newFile('/ws/some/code/lib/code2.dart');
+    final targetFile2 = newFile('/ws/some/code/lib/src/code3.dart');
+    final targetBinFile = newFile('/ws/some/code/bin/code.dart');
+    final targetTestFile = newFile('/ws/some/code/test/code_test.dart');
+
+    expect(package.contains(TestSource(targetFile.path)), isTrue);
+    expect(package.contains(TestSource(targetFile2.path)), isTrue);
+    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
+    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
+  }
+
+  void test_contains_samePackage_summarySource() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+    newFile('/ws/some/code/lib/code2.dart');
+    newFile('/ws/some/code/lib/src/code3.dart');
+    final file2Source = InSummarySource(
+        Uri.parse('package:some.code/code2.dart'), '' /* summaryPath */);
+    final file3Source = InSummarySource(
+        Uri.parse('package:some.code/src/code2.dart'), '' /* summaryPath */);
+
+    expect(package.contains(file2Source), isTrue);
+    expect(package.contains(file3Source), isTrue);
+  }
+
+  void test_contains_subPackage() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+    newFile('/ws/some/code/testing/BUILD');
+    newFile('/ws/some/code/testing/lib/testing.dart');
+
+    expect(
+        package.contains(
+            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
+        isFalse);
+  }
+
+  void test_findPackageFor_buildFileExists() {
+    _setUpPackage('/ws/some/code', workspaceRoot: '/ws');
+
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/ws/some/code'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_missingMarkerFiles() {
+    _addResources([
+      '/ws/WORKSPACE',
+      '/ws/bazel-genfiles',
+    ]);
+    workspace =
+        BazelWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+    final targetFile = newFile('/ws/some/code/lib/code.dart');
+
+    package = workspace.findPackageFor(targetFile.path);
+    expect(package, isNull);
+  }
+
+  void test_findPackageFor_packagesFileInBinExists() {
+    _addResources([
+      '/ws/blaze-out/host/bin/some/code/code.packages',
+      '/ws/some/code/lib/code.dart',
+    ]);
+    workspace =
+        BazelWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+
+    package = workspace.findPackageFor('/ws/some/code/lib/code.dart');
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/ws/some/code'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_packagesFileInBinExists_subPackage() {
+    _addResources([
+      '/ws/blaze-out/host/bin/some/code/code.packages',
+      '/ws/blaze-out/host/bin/some/code/testing/testing.packages',
+      '/ws/some/code/lib/code.dart',
+      '/ws/some/code/testing/lib/testing.dart',
+    ]);
+    workspace = BazelWorkspace.find(
+        resourceProvider, convertPath('/ws/some/code/testing'));
+
+    package =
+        workspace.findPackageFor('/ws/some/code/testing/lib/testing.dart');
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/ws/some/code/testing'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  /// Create new files and directories from [paths].
+  void _addResources(List<String> paths) {
+    for (String path in paths) {
+      if (path.endsWith('/')) {
+        newFolder(path.substring(0, path.length - 1));
+      } else {
+        newFile(path);
+      }
+    }
+  }
+
+  /// Set up files for [package] rooted at [root] and [workspace] rooted at
+  /// [workspaceRoot].
+  void _setUpPackage(String root, {@required String workspaceRoot}) {
+    _addResources([
+      '$workspaceRoot/WORKSPACE',
+      '$workspaceRoot/bazel-genfiles/',
+      '$root/BUILD',
+      '$root/lib/code.dart',
+    ]);
+    workspace =
+        BazelWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+    package = workspace.findPackageFor('$root/lib/code.dart');
+  }
+}
+
+@reflectiveTest
 class BazelWorkspaceTest with ResourceProviderMixin {
+  BazelWorkspace workspace;
+
   void test_find_fail_notAbsolute() {
     expect(
         () =>
@@ -494,10 +641,39 @@
         throwsA(const TypeMatcher<ArgumentError>()));
   }
 
+  void test_find_hasBlazeBinFolderInOutFolder() {
+    _addResources([
+      '/workspace/blaze-out/host/bin/',
+      '/workspace/my/module/',
+    ]);
+    BazelWorkspace workspace = BazelWorkspace.find(
+        resourceProvider, convertPath('/workspace/my/module'));
+    expect(workspace.root, convertPath('/workspace'));
+    expect(workspace.readonly, isNull);
+    expect(workspace.bin, convertPath('/workspace/blaze-out/host/bin'));
+    expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
+  }
+
+  void test_find_hasBlazeOutFolder_missingBinFolder() {
+    _addResources([
+      '/workspace/blaze-genfiles/',
+      '/workspace/blaze-out/',
+      '/workspace/my/module/',
+    ]);
+    BazelWorkspace workspace = BazelWorkspace.find(
+        resourceProvider, convertPath('/workspace/my/module'));
+    expect(workspace.root, convertPath('/workspace'));
+    expect(workspace.readonly, isNull);
+    expect(workspace.bin, convertPath('/workspace/blaze-bin'));
+    expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
+  }
+
   void test_find_hasReadonlyFolder() {
-    newFolder('/Users/user/test/READONLY/prime');
-    newFolder('/Users/user/test/prime');
-    newFolder('/Users/user/test/prime/bazel-genfiles');
+    _addResources([
+      '/Users/user/test/READONLY/prime/',
+      '/Users/user/test/prime/',
+      '/Users/user/test/prime/bazel-genfiles/',
+    ]);
     BazelWorkspace workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/Users/user/test/prime/my/module'));
     expect(workspace.root, convertPath('/Users/user/test/prime'));
@@ -508,9 +684,11 @@
   }
 
   void test_find_hasReadonlyFolder_bad_actuallyHasWorkspaceFile() {
-    newFolder('/Users/user/test/READONLY');
-    newFile('/Users/user/test/prime/WORKSPACE');
-    newFolder('/Users/user/test/prime/bazel-genfiles');
+    _addResources([
+      '/Users/user/test/READONLY/',
+      '/Users/user/test/prime/WORKSPACE',
+      '/Users/user/test/prime/bazel-genfiles/',
+    ]);
     BazelWorkspace workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/Users/user/test/prime/my/module'));
     expect(workspace.root, convertPath('/Users/user/test/prime'));
@@ -521,9 +699,11 @@
   }
 
   void test_find_hasReadonlyFolder_blaze() {
-    newFolder('/Users/user/test/READONLY/prime');
-    newFolder('/Users/user/test/prime');
-    newFolder('/Users/user/test/prime/blaze-genfiles');
+    _addResources([
+      '/Users/user/test/READONLY/prime/',
+      '/Users/user/test/prime/',
+      '/Users/user/test/prime/blaze-genfiles/',
+    ]);
     BazelWorkspace workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/Users/user/test/prime/my/module'));
     expect(workspace.root, convertPath('/Users/user/test/prime'));
@@ -534,8 +714,10 @@
   }
 
   void test_find_hasWorkspaceFile() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-genfiles');
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-genfiles/',
+    ]);
     BazelWorkspace workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/workspace/my/module'));
     expect(workspace.root, convertPath('/workspace'));
@@ -545,8 +727,10 @@
   }
 
   void test_find_hasWorkspaceFile_forModuleInWorkspace() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-genfiles');
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-genfiles/',
+    ]);
     BazelWorkspace workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/workspace/my/module'));
     expect(workspace.root, convertPath('/workspace'));
@@ -556,8 +740,10 @@
   }
 
   void test_find_hasWorkspaceFile_forWorkspace() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/bazel-genfiles');
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-genfiles/',
+    ]);
     BazelWorkspace workspace =
         BazelWorkspace.find(resourceProvider, convertPath('/workspace'));
     expect(workspace.root, convertPath('/workspace'));
@@ -567,8 +753,10 @@
   }
 
   void test_find_hasWorkspaceFile_forWorkspace_blaze() {
-    newFile('/workspace/WORKSPACE');
-    newFolder('/workspace/blaze-genfiles');
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/blaze-genfiles/',
+    ]);
     BazelWorkspace workspace =
         BazelWorkspace.find(resourceProvider, convertPath('/workspace'));
     expect(workspace.root, convertPath('/workspace'));
@@ -601,183 +789,75 @@
   }
 
   void test_findFile_hasReadonlyFolder() {
-    newFolder('/Users/user/test/READONLY/prime');
-    newFolder('/Users/user/test/prime');
-    newFile('/Users/user/test/prime/my/module/test1.dart');
-    newFile('/Users/user/test/prime/my/module/test2.dart');
-    newFile('/Users/user/test/prime/my/module/test3.dart');
-    newFile('/Users/user/test/prime/bazel-bin/my/module/test2.dart');
-    newFile('/Users/user/test/prime/bazel-genfiles/my/module/test3.dart');
-    newFile('/Users/user/test/READONLY/prime/other/module/test4.dart');
-    BazelWorkspace workspace = BazelWorkspace.find(
+    _addResources([
+      '/Users/user/test/READONLY/prime/',
+      '/Users/user/test/prime/',
+      '/Users/user/test/prime/my/module/test1.dart',
+      '/Users/user/test/prime/my/module/test2.dart',
+      '/Users/user/test/prime/my/module/test3.dart',
+      '/Users/user/test/prime/bazel-bin/my/module/test2.dart',
+      '/Users/user/test/prime/bazel-genfiles/my/module/test3.dart',
+      '/Users/user/test/READONLY/prime/other/module/test4.dart',
+    ]);
+    workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/Users/user/test/prime/my/module'));
-    expect(
-        workspace
-            .findFile(
-                convertPath('/Users/user/test/prime/my/module/test1.dart'))
-            .path,
-        convertPath('/Users/user/test/prime/my/module/test1.dart'));
-    expect(
-        workspace
-            .findFile(
-                convertPath('/Users/user/test/prime/my/module/test2.dart'))
-            .path,
-        convertPath('/Users/user/test/prime/bazel-bin/my/module/test2.dart'));
-    expect(
-        workspace
-            .findFile(
-                convertPath('/Users/user/test/prime/my/module/test3.dart'))
-            .path,
-        convertPath(
-            '/Users/user/test/prime/bazel-genfiles/my/module/test3.dart'));
-    expect(
-        workspace
-            .findFile(
-                convertPath('/Users/user/test/prime/other/module/test4.dart'))
-            .path,
-        convertPath('/Users/user/test/READONLY/prime/other/module/test4.dart'));
+    _expectFindFile('/Users/user/test/prime/my/module/test1.dart',
+        equals: '/Users/user/test/prime/my/module/test1.dart');
+    _expectFindFile('/Users/user/test/prime/my/module/test2.dart',
+        equals: '/Users/user/test/prime/bazel-bin/my/module/test2.dart');
+    _expectFindFile('/Users/user/test/prime/my/module/test3.dart',
+        equals: '/Users/user/test/prime/bazel-genfiles/my/module/test3.dart');
+    _expectFindFile('/Users/user/test/prime/other/module/test4.dart',
+        equals: '/Users/user/test/READONLY/prime/other/module/test4.dart');
   }
 
   void test_findFile_main_overrides_readonly() {
-    newFolder('/Users/user/test/READONLY/prime');
-    newFolder('/Users/user/test/prime');
-    newFolder('/Users/user/test/prime/bazel-genfiles');
-    newFile('/Users/user/test/prime/my/module/test.dart');
-    newFile('/Users/user/test/READONLY/prime/my/module/test.dart');
-    BazelWorkspace workspace = BazelWorkspace.find(
+    _addResources([
+      '/Users/user/test/READONLY/prime/',
+      '/Users/user/test/prime/',
+      '/Users/user/test/prime/bazel-genfiles/',
+      '/Users/user/test/prime/my/module/test.dart',
+      '/Users/user/test/READONLY/prime/my/module/test.dart',
+    ]);
+    workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/Users/user/test/prime/my/module'));
-    expect(
-        workspace
-            .findFile(convertPath('/Users/user/test/prime/my/module/test.dart'))
-            .path,
-        convertPath('/Users/user/test/prime/my/module/test.dart'));
+    _expectFindFile('/Users/user/test/prime/my/module/test.dart',
+        equals: '/Users/user/test/prime/my/module/test.dart');
   }
 
   void test_findFile_noReadOnly() {
-    newFile('/workspace/WORKSPACE');
-    newFile('/workspace/my/module/test1.dart');
-    newFile('/workspace/my/module/test2.dart');
-    newFile('/workspace/my/module/test3.dart');
-    newFile('/workspace/bazel-bin/my/module/test2.dart');
-    newFile('/workspace/bazel-genfiles/my/module/test3.dart');
-    BazelWorkspace workspace = BazelWorkspace.find(
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/my/module/test1.dart',
+      '/workspace/my/module/test2.dart',
+      '/workspace/my/module/test3.dart',
+      '/workspace/bazel-bin/my/module/test2.dart',
+      '/workspace/bazel-genfiles/my/module/test3.dart',
+    ]);
+    workspace = BazelWorkspace.find(
         resourceProvider, convertPath('/workspace/my/module'));
-    expect(
-        workspace.findFile(convertPath('/workspace/my/module/test1.dart')).path,
-        convertPath('/workspace/my/module/test1.dart'));
-    expect(
-        workspace.findFile(convertPath('/workspace/my/module/test2.dart')).path,
-        convertPath('/workspace/bazel-bin/my/module/test2.dart'));
-    expect(
-        workspace.findFile(convertPath('/workspace/my/module/test3.dart')).path,
-        convertPath('/workspace/bazel-genfiles/my/module/test3.dart'));
-  }
-}
-
-@reflectiveTest
-class BazelWorkspacePackageTest with ResourceProviderMixin {
-  BazelWorkspace workspace;
-
-  void setUp() {
-    newFile('/ws/WORKSPACE');
-    newFolder('/ws/bazel-genfiles');
-    workspace =
-        BazelWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+    _expectFindFile('/workspace/my/module/test1.dart',
+        equals: '/workspace/my/module/test1.dart');
+    _expectFindFile('/workspace/my/module/test2.dart',
+        equals: '/workspace/bazel-bin/my/module/test2.dart');
+    _expectFindFile('/workspace/my/module/test3.dart',
+        equals: '/workspace/bazel-genfiles/my/module/test3.dart');
   }
 
-  void test_findPackageFor_missingBuildFile() {
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package, isNull);
+  /// Create new files and directories from [paths].
+  void _addResources(List<String> paths) {
+    for (String path in paths) {
+      if (path.endsWith('/')) {
+        newFolder(path.substring(0, path.length - 1));
+      } else {
+        newFile(path);
+      }
+    }
   }
 
-  void test_findPackageFor_buildFileExists() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package, isNotNull);
-    expect(package.root, convertPath('/ws/some/code'));
-    expect(package.workspace, equals(workspace));
-  }
-
-  void test_contains_differentWorkspace() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
-        isFalse);
-  }
-
-  void test_contains_differentPackageInWorkspace() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    // A file that is _not_ in this package is not required to have a BUILD
-    // file above it, for simplicity and reduced I/O.
-    expect(
-        package
-            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
-        isFalse);
-  }
-
-  void test_contains_samePackage() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-    final targetFile2 = newFile('/ws/some/code/lib/code2.dart');
-    final targetFile3 = newFile('/ws/some/code/lib/src/code3.dart');
-    final targetBinFile = newFile('/ws/some/code/bin/code.dart');
-    final targetTestFile = newFile('/ws/some/code/test/code_test.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(TestSource(targetFile2.path)), isTrue);
-    expect(package.contains(TestSource(targetFile3.path)), isTrue);
-    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
-    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
-  }
-
-  void test_contains_subPackage() {
-    newFile('/ws/some/code/BUILD');
-    newFile('/ws/some/code/lib/code.dart');
-    newFile('/ws/some/code/testing/BUILD');
-    newFile('/ws/some/code/testing/lib/testing.dart');
-
-    var package =
-        workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
-    expect(
-        package.contains(
-            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
-        isFalse);
-  }
-
-  void test_contains_differentPackage_summarySource() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    var source = InSummarySource(
-        Uri.parse('package:some.other.code/file.dart'), '' /* summaryPath */);
-    expect(package.contains(source), isFalse);
-  }
-
-  void test_contains_samePackage_summarySource() {
-    newFile('/ws/some/code/BUILD');
-    final targetFile = newFile('/ws/some/code/lib/code.dart');
-    newFile('/ws/some/code/lib/code2.dart');
-    newFile('/ws/some/code/lib/src/code3.dart');
-
-    final file2Source = InSummarySource(
-        Uri.parse('package:some.code/code2.dart'), '' /* summaryPath */);
-    final file3Source = InSummarySource(
-        Uri.parse('package:some.code/src/code2.dart'), '' /* summaryPath */);
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(file2Source), isTrue);
-    expect(package.contains(file3Source), isTrue);
-  }
+  /// Expect that [BazelWorkspace.findFile], given [path], returns [equals].
+  void _expectFindFile(String path, {@required String equals}) =>
+      expect(workspace.findFile(convertPath(path)).path, convertPath(equals));
 }
 
 class _MockSource implements Source {
diff --git a/pkg/analyzer/test/src/workspace/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart
index 6349e70..b3348de 100644
--- a/pkg/analyzer/test/src/workspace/gn_test.dart
+++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -17,6 +17,93 @@
 }
 
 @reflectiveTest
+class GnWorkspacePackageTest with ResourceProviderMixin {
+  void test_contains_differentPackageInWorkspace() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/BUILD.gn');
+    var targetFile = newFile('/ws/some/code/lib/code.dart');
+
+    var package = workspace.findPackageFor(targetFile.path);
+    // A file that is _not_ in this package is not required to have a BUILD.gn
+    // file above it, for simplicity and reduced I/O.
+    expect(
+        package
+            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
+        isFalse);
+  }
+
+  void test_contains_differentWorkspace() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/BUILD.gn');
+    var targetFile = newFile('/ws/some/code/lib/code.dart');
+
+    var package = workspace.findPackageFor(targetFile.path);
+    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
+        isFalse);
+  }
+
+  void test_contains_samePackage() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/BUILD.gn');
+    var targetFile = newFile('/ws/some/code/lib/code.dart');
+    var targetFile2 = newFile('/ws/some/code/lib/code2.dart');
+    var targetFile3 = newFile('/ws/some/code/lib/src/code3.dart');
+    var targetBinFile = newFile('/ws/some/code/bin/code.dart');
+    var targetTestFile = newFile('/ws/some/code/test/code_test.dart');
+
+    var package = workspace.findPackageFor(targetFile.path);
+    expect(package.contains(TestSource(targetFile2.path)), isTrue);
+    expect(package.contains(TestSource(targetFile3.path)), isTrue);
+    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
+    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
+  }
+
+  void test_contains_subPackage() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/BUILD.gn');
+    newFile('/ws/some/code/lib/code.dart');
+    newFile('/ws/some/code/testing/BUILD.gn');
+    newFile('/ws/some/code/testing/lib/testing.dart');
+
+    var package =
+        workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
+    expect(
+        package.contains(
+            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
+        isFalse);
+  }
+
+  void test_findPackageFor_buildFileExists() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/BUILD.gn');
+    var targetFile = newFile('/ws/some/code/lib/code.dart');
+
+    var package = workspace.findPackageFor(targetFile.path);
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/ws/some/code'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_missingBuildFile() {
+    GnWorkspace workspace = _buildStandardGnWorkspace();
+    newFile('/ws/some/code/lib/code.dart');
+
+    var package =
+        workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
+    expect(package, isNull);
+  }
+
+  GnWorkspace _buildStandardGnWorkspace() {
+    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');
+    newFolder('/ws/some/code');
+    return GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+  }
+}
+
+@reflectiveTest
 class GnWorkspaceTest with ResourceProviderMixin {
   void test_find_noJiriRoot() {
     newFolder('/workspace');
@@ -170,90 +257,3 @@
     expect(workspace.packageMap['rettulf'][0].path, packageTwoLocation);
   }
 }
-
-@reflectiveTest
-class GnWorkspacePackageTest with ResourceProviderMixin {
-  GnWorkspace _buildStandardGnWorkspace() {
-    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');
-    newFolder('/ws/some/code');
-    return GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
-  }
-
-  void test_findPackageFor_missingBuildFile() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/lib/code.dart');
-
-    var package =
-        workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
-    expect(package, isNull);
-  }
-
-  void test_findPackageFor_buildFileExists() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/BUILD.gn');
-    var targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package, isNotNull);
-    expect(package.root, convertPath('/ws/some/code'));
-    expect(package.workspace, equals(workspace));
-  }
-
-  void test_contains_differentWorkspace() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/BUILD.gn');
-    var targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(TestSource(convertPath('/ws2/some/file.dart'))),
-        isFalse);
-  }
-
-  void test_contains_differentPackageInWorkspace() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/BUILD.gn');
-    var targetFile = newFile('/ws/some/code/lib/code.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    // A file that is _not_ in this package is not required to have a BUILD.gn
-    // file above it, for simplicity and reduced I/O.
-    expect(
-        package
-            .contains(TestSource(convertPath('/ws/some/other/code/file.dart'))),
-        isFalse);
-  }
-
-  void test_contains_samePackage() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/BUILD.gn');
-    var targetFile = newFile('/ws/some/code/lib/code.dart');
-    var targetFile2 = newFile('/ws/some/code/lib/code2.dart');
-    var targetFile3 = newFile('/ws/some/code/lib/src/code3.dart');
-    var targetBinFile = newFile('/ws/some/code/bin/code.dart');
-    var targetTestFile = newFile('/ws/some/code/test/code_test.dart');
-
-    var package = workspace.findPackageFor(targetFile.path);
-    expect(package.contains(TestSource(targetFile2.path)), isTrue);
-    expect(package.contains(TestSource(targetFile3.path)), isTrue);
-    expect(package.contains(TestSource(targetBinFile.path)), isTrue);
-    expect(package.contains(TestSource(targetTestFile.path)), isTrue);
-  }
-
-  void test_contains_subPackage() {
-    GnWorkspace workspace = _buildStandardGnWorkspace();
-    newFile('/ws/some/code/BUILD.gn');
-    newFile('/ws/some/code/lib/code.dart');
-    newFile('/ws/some/code/testing/BUILD.gn');
-    newFile('/ws/some/code/testing/lib/testing.dart');
-
-    var package =
-        workspace.findPackageFor(convertPath('/ws/some/code/lib/code.dart'));
-    expect(
-        package.contains(
-            TestSource(convertPath('/ws/some/code/testing/lib/testing.dart'))),
-        isFalse);
-  }
-}
diff --git a/pkg/analyzer/test/src/workspace/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart
index ef5bd9f..6045fb1 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -2,10 +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/src/summary/package_bundle_reader.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart';
 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/package_build.dart';
 import 'package:package_config/packages.dart';
@@ -246,20 +246,6 @@
         isFalse);
   }
 
-  void test_contains_sameWorkspace() {
-    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
-    newFile('/workspace/project/lib/file2.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
-    var file2Path = convertPath('/workspace/project/lib/file2.dart');
-    expect(package.contains(TestSource(file2Path)), isTrue);
-    var binPath = convertPath('/workspace/project/bin/bin.dart');
-    expect(package.contains(TestSource(binPath)), isTrue);
-    var testPath = convertPath('/workspace/project/test/test.dart');
-    expect(package.contains(TestSource(testPath)), isTrue);
-  }
-
   void test_contains_packageUris() {
     PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
     newFile('/workspace/project/lib/file2.dart');
@@ -280,6 +266,20 @@
     expect(package.contains(file2Source), isFalse);
   }
 
+  void test_contains_sameWorkspace() {
+    PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
+    newFile('/workspace/project/lib/file2.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/code.dart'));
+    var file2Path = convertPath('/workspace/project/lib/file2.dart');
+    expect(package.contains(TestSource(file2Path)), isTrue);
+    var binPath = convertPath('/workspace/project/bin/bin.dart');
+    expect(package.contains(TestSource(binPath)), isTrue);
+    var testPath = convertPath('/workspace/project/test/test.dart');
+    expect(package.contains(TestSource(testPath)), isTrue);
+  }
+
   void test_findPackageFor_includedFile() {
     PackageBuildWorkspace workspace = _createPackageBuildWorkspace();
     newFile('/workspace/project/lib/file.dart');
diff --git a/pkg/analyzer/test/src/workspace/pub_test.dart b/pkg/analyzer/test/src/workspace/pub_test.dart
index 7e18297..7d7e987 100644
--- a/pkg/analyzer/test/src/workspace/pub_test.dart
+++ b/pkg/analyzer/test/src/workspace/pub_test.dart
@@ -53,24 +53,6 @@
         resourceProvider, convertPath('/workspace'), contextBuilder);
   }
 
-  void test_findPackageFor_unrelatedFile() {
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace2/project/lib/file.dart'));
-    expect(package, isNull);
-  }
-
-  void test_findPackageFor_includedFile() {
-    newFile('/workspace/project/lib/file.dart');
-
-    var package = workspace
-        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
-    expect(package, isNotNull);
-    expect(package.root, convertPath('/workspace'));
-    expect(package.workspace, equals(workspace));
-  }
-
   void test_contains_differentWorkspace() {
     newFile('/workspace2/project/lib/file.dart');
 
@@ -100,23 +82,28 @@
             TestSource(convertPath('/workspace/project/test/test.dart'))),
         isTrue);
   }
+
+  void test_findPackageFor_includedFile() {
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace/project/lib/file.dart'));
+    expect(package, isNotNull);
+    expect(package.root, convertPath('/workspace'));
+    expect(package.workspace, equals(workspace));
+  }
+
+  void test_findPackageFor_unrelatedFile() {
+    newFile('/workspace/project/lib/file.dart');
+
+    var package = workspace
+        .findPackageFor(convertPath('/workspace2/project/lib/file.dart'));
+    expect(package, isNull);
+  }
 }
 
 @reflectiveTest
 class PubWorkspaceTest with ResourceProviderMixin {
-  void test_find_fail_notAbsolute() {
-    expect(
-        () => PubWorkspace.find(resourceProvider, convertPath('not_absolute'),
-            new MockContextBuilder()),
-        throwsA(TypeMatcher<ArgumentError>()));
-  }
-
-  void test_find_missingPubspec() {
-    PubWorkspace workspace = PubWorkspace.find(resourceProvider,
-        convertPath('/workspace/lib/lib1.dart'), new MockContextBuilder());
-    expect(workspace, isNull);
-  }
-
   void test_find_directory() {
     newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
     PubWorkspace workspace = PubWorkspace.find(
@@ -124,10 +111,23 @@
     expect(workspace.root, convertPath('/workspace'));
   }
 
+  void test_find_fail_notAbsolute() {
+    expect(
+        () => PubWorkspace.find(resourceProvider, convertPath('not_absolute'),
+            new MockContextBuilder()),
+        throwsA(TypeMatcher<ArgumentError>()));
+  }
+
   void test_find_file() {
     newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
     PubWorkspace workspace = PubWorkspace.find(resourceProvider,
         convertPath('/workspace/lib/lib1.dart'), new MockContextBuilder());
     expect(workspace.root, convertPath('/workspace'));
   }
+
+  void test_find_missingPubspec() {
+    PubWorkspace workspace = PubWorkspace.find(resourceProvider,
+        convertPath('/workspace/lib/lib1.dart'), new MockContextBuilder());
+    expect(workspace, isNull);
+  }
 }
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index 28fa311..2ea4044 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -5,6 +5,10 @@
 // TODO(paulberry,johnniwinther): Use the code for extraction of test data from
 // annotated code from CFE.
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
+import 'package:_fe_analyzer_shared/src/testing/id.dart'
+    show ActualData, Id, IdValue, MemberId, NodeId;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart' hide Annotation;
@@ -20,10 +24,6 @@
 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:front_end/src/testing/annotated_code_helper.dart';
-import 'package:front_end/src/testing/id.dart'
-    show ActualData, Id, IdValue, MemberId, NodeId;
-import 'package:front_end/src/testing/id_testing.dart';
 
 /// Test configuration used for testing the analyzer with constant evaluation.
 final TestConfig analyzerConstantUpdate2018Config = TestConfig(
@@ -181,18 +181,47 @@
     if (id is NodeId) {
       return id.value;
     } else if (id is MemberId) {
-      if (id.className != null) {
-        throw UnimplementedError('TODO(paulberry): handle class members');
-      }
+      var className = id.className;
       var name = id.memberName;
       var unit =
           parseString(content: code[uri].sourceCode, throwIfDiagnostics: false)
               .unit;
+      if (className != null) {
+        for (var declaration in unit.declarations) {
+          if (declaration is ClassDeclaration &&
+              declaration.name.name == className) {
+            for (var member in declaration.members) {
+              if (member is ConstructorDeclaration) {
+                if (member.name.name == name) {
+                  return member.offset;
+                }
+              } else if (member is FieldDeclaration) {
+                for (var variable in member.fields.variables) {
+                  if (variable.name.name == name) {
+                    return variable.offset;
+                  }
+                }
+              } else if (member is MethodDeclaration) {
+                if (member.name.name == name) {
+                  return member.offset;
+                }
+              }
+            }
+          }
+        }
+        throw StateError('Member not found: $className.$name');
+      }
       for (var declaration in unit.declarations) {
         if (declaration is FunctionDeclaration) {
           if (declaration.name.name == name) {
             return declaration.offset;
           }
+        } else if (declaration is TopLevelVariableDeclaration) {
+          for (var variable in declaration.variables.variables) {
+            if (variable.name.name == name) {
+              return variable.offset;
+            }
+          }
         }
       }
       throw StateError('Member not found: $name');
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 2fafd4d..3df5e19 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -510,6 +510,8 @@
 
 _'{0}' is deprecated and shouldn't be used._
 
+_'{0}' is deprecated and shouldn't be used. {1}._
+
 #### Description
 
 The analyzer produces this diagnostic when a deprecated library or class
@@ -535,6 +537,8 @@
 
 _'{0}' is deprecated and shouldn't be used._
 
+_'{0}' is deprecated and shouldn't be used. {1}._
+
 #### Description
 
 The analyzer produces this diagnostic when a deprecated library member or
@@ -1416,7 +1420,7 @@
 The following code produces this diagnostic:
 
 {% prettify dart %}
-[!int!] f(int x) {
+int [!f!](int x) {
   if (x < 0) {
     return 0;
   }
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index c5f56bf..580c05d 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -83,15 +83,73 @@
   }
 }
 
+/// An information holder containing information about a diagnostic that was
+/// extracted from the instance creation expression.
+class DiagnosticInformation {
+  /// The name of the diagnostic.
+  final String name;
+
+  /// The messages associated with the diagnostic.
+  List<String> messages;
+
+  /// The lines of documentation associated with the diagnostic.
+  List<String> documentation;
+
+  /// Initialize a newly created information holder with the given [name] and
+  /// [message].
+  DiagnosticInformation(this.name, String message) : messages = [message];
+
+  /// Return `true` if this diagnostic has documentation.
+  bool get hasDocumentation => documentation != null;
+
+  /// Return the full documentation for this diagnostic.
+  void writeOn(StringSink sink) {
+    messages.sort();
+    sink.writeln('### ${name.toLowerCase()}');
+    for (String message in messages) {
+      sink.writeln();
+      for (String line in _split('_${_escape(message)}_')) {
+        sink.writeln(line);
+      }
+    }
+    sink.writeln();
+    for (String line in documentation) {
+      sink.writeln(line);
+    }
+  }
+
+  /// Return a version of the [text] in which characters that have special
+  /// meaning in markdown have been escaped.
+  String _escape(String text) {
+    return text.replaceAll('_', '\\_');
+  }
+
+  /// Split the [message] into multiple lines, each of which is less than 80
+  /// characters long.
+  List<String> _split(String message) {
+    // This uses a brute force approach because we don't expect to have messages
+    // that need to be split more than once.
+    int length = message.length;
+    if (length <= 80) {
+      return [message];
+    }
+    int endIndex = message.lastIndexOf(' ', 80);
+    if (endIndex < 0) {
+      return [message];
+    }
+    return [message.substring(0, endIndex), message.substring(endIndex + 1)];
+  }
+}
+
 /// A class used to generate diagnostic documentation.
 class DocumentationGenerator {
   /// The absolute paths of the files containing the declarations of the error
   /// codes.
   final List<CodePath> codePaths;
 
-  /// A map from the name of a diagnostic code to the lines of the documentation
-  /// for that code.
-  Map<String, List<String>> docsByCode = {};
+  /// A map from the name of a diagnostic to the information about that
+  /// diagnostic.
+  Map<String, DiagnosticInformation> infoByName = {};
 
   /// Initialize a newly created documentation generator.
   DocumentationGenerator(this.codePaths) {
@@ -141,6 +199,34 @@
     }
   }
 
+  /// Extract information about a diagnostic from the [expression], or `null` if
+  /// the expression does not appear to be creating an error code. If the
+  /// expression is the name of a generated code, then the [generatedResult]
+  /// should have the unit in which the information can be found.
+  DiagnosticInformation _extractDiagnosticInformation(
+      Expression expression, ParsedUnitResult generatedResult) {
+    if (expression is InstanceCreationExpression) {
+      NodeList<Expression> arguments = expression.argumentList.arguments;
+      String name = _extractName(arguments);
+      String message = _extractMessage(arguments);
+      DiagnosticInformation info = infoByName[name];
+      if (info == null) {
+        info = DiagnosticInformation(name, message);
+        infoByName[name] = info;
+      } else {
+        info.messages.add(message);
+      }
+      return info;
+    } else if (expression is SimpleIdentifier && generatedResult != null) {
+      VariableDeclaration variable =
+          _findVariable(expression.name, generatedResult.unit);
+      if (variable != null) {
+        return _extractDiagnosticInformation(variable.initializer, null);
+      }
+    }
+    return null;
+  }
+
   /// Extract documentation from the given [field] declaration.
   List<String> _extractDoc(FieldDeclaration field) {
     Token comments = field.firstTokenAfterCommentAndMetadata.precedingComments;
@@ -187,26 +273,24 @@
   void _extractDocs(ParsedUnitResult result, ParsedUnitResult generatedResult) {
     CompilationUnit unit = result.unit;
     for (CompilationUnitMember declaration in unit.declarations) {
-      if (declaration is ClassDeclaration) {
+      if (declaration is ClassDeclaration &&
+          declaration.name.name != 'StrongModeCode') {
         for (ClassMember member in declaration.members) {
-          if (member is FieldDeclaration) {
-            List<String> docs = _extractDoc(member);
-            if (docs != null) {
-              VariableDeclaration variable = member.fields.variables[0];
-              String variableName = variable.name.name;
-              if (docsByCode.containsKey(variableName)) {
-                throw StateError('Duplicate diagnostic code');
+          if (member is FieldDeclaration &&
+              member.isStatic &&
+              !_isDeprecated(member)) {
+            VariableDeclaration variable = member.fields.variables[0];
+            DiagnosticInformation info = _extractDiagnosticInformation(
+                variable.initializer, generatedResult);
+            if (info != null) {
+              List<String> docs = _extractDoc(member);
+              if (docs != null) {
+                if (info.documentation != null) {
+                  throw StateError(
+                      'Documentation defined multiple times for ${info.name}');
+                }
+                info.documentation = docs;
               }
-              String message =
-                  _extractMessage(variable.initializer, generatedResult);
-              docs = [
-                '### ${variableName.toLowerCase()}',
-                '',
-                ..._split('_${_escape(message)}_'),
-                '',
-                ...docs,
-              ];
-              docsByCode[variableName] = docs;
             }
           }
         }
@@ -214,23 +298,29 @@
     }
   }
 
-  /// Extract the message from the [expression]. If the expression is the name
-  /// of a generated code, then the [generatedResult] should have the unit in
-  /// which the message can be found.
-  String _extractMessage(
-      Expression expression, ParsedUnitResult generatedResult) {
-    if (expression is InstanceCreationExpression) {
-      return (expression.argumentList.arguments[1] as StringLiteral)
-          .stringValue;
-    } else if (expression is SimpleIdentifier && generatedResult != null) {
-      VariableDeclaration variable =
-          _findVariable(expression.name, generatedResult.unit);
-      if (variable != null) {
-        return _extractMessage(variable.initializer, null);
-      }
+  /// Return the message extracted from the list of [arguments].
+  String _extractMessage(NodeList<Expression> arguments) {
+    int positionalCount =
+        arguments.where((expression) => expression is! NamedExpression).length;
+    if (positionalCount == 2) {
+      return _extractString(arguments[1]);
+    } else if (positionalCount == 3) {
+      return _extractString(arguments[2]);
+    } else {
+      throw StateError(
+          'Invalid number of positional arguments: $positionalCount');
     }
-    throw StateError(
-        'Cannot extract a message from a ${expression.runtimeType}');
+  }
+
+  /// Return the name extracted from the list of [arguments].
+  String _extractName(NodeList<Expression> arguments) =>
+      _extractString(arguments[0]);
+
+  String _extractString(Expression expression) {
+    if (expression is StringLiteral) {
+      return expression.stringValue;
+    }
+    throw StateError('Cannot extract string from $expression');
   }
 
   /// Return the declaration of the top-level variable with the [name] in the
@@ -248,6 +338,10 @@
     return null;
   }
 
+  /// Return `true` if the [field] is marked as being deprecated.
+  bool _isDeprecated(FieldDeclaration field) =>
+      field.metadata.any((annotation) => annotation.name.name == 'Deprecated');
+
   /// Use the analysis context [collection] to parse the file at the given
   /// [path] and return the result.
   ParsedUnitResult _parse(AnalysisContextCollection collection, String path) {
@@ -262,22 +356,6 @@
     return result;
   }
 
-  /// Split the [message] into multiple lines, each of which is less than 80
-  /// characters long.
-  List<String> _split(String message) {
-    // This uses a brute force approach because we don't expect to have messages
-    // that need to be split more than once.
-    int length = message.length;
-    if (length <= 80) {
-      return [message];
-    }
-    int endIndex = message.lastIndexOf(' ', 80);
-    if (endIndex < 0) {
-      return [message];
-    }
-    return [message.substring(0, endIndex), message.substring(endIndex + 1)];
-  }
-
   /// Write the documentation for all of the diagnostics.
   void _writeDiagnostics(StringSink sink) {
     sink.write('''
@@ -288,13 +366,13 @@
 doesn't conform to the language specification or
 that might work in unexpected ways.
 ''');
-    List<String> errorCodes = docsByCode.keys.toList();
+    List<String> errorCodes = infoByName.keys.toList();
     errorCodes.sort();
     for (String errorCode in errorCodes) {
-      List<String> docs = docsByCode[errorCode];
-      sink.writeln();
-      for (String line in docs) {
-        sink.writeln(line);
+      DiagnosticInformation info = infoByName[errorCode];
+      if (info.hasDocumentation) {
+        sink.writeln();
+        info.writeOn(sink);
       }
     }
   }
diff --git a/pkg/analyzer/tool/experiments/generate.dart b/pkg/analyzer/tool/experiments/generate.dart
index ac968f5..188115e 100644
--- a/pkg/analyzer/tool/experiments/generate.dart
+++ b/pkg/analyzer/tool/experiments/generate.dart
@@ -4,8 +4,9 @@
  */
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
+    show $MINUS, $_;
 import 'package:analysis_tool/tools.dart';
-import 'package:front_end/src/fasta/scanner/characters.dart' show $MINUS, $_;
 import 'package:path/path.dart';
 import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
 
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index 1a20e92..176b649 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -14,10 +14,10 @@
  */
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
 import 'package:analysis_tool/tools.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:front_end/src/fasta/scanner.dart';
 import 'package:path/path.dart';
 import 'package:yaml/yaml.dart' show loadYaml;
 
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index dd44327..842e513 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -18,9 +18,9 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 import 'package:analysis_tool/tools.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/scanner/token.dart' show Token;
 
 import 'idl_model.dart' as idl_model;
 import 'mini_ast.dart';
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 57c11bd..5d333e2 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -2,12 +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.
 
-import 'package:front_end/src/fasta/messages.dart' show LocatedMessage, Message;
-import 'package:front_end/src/fasta/parser.dart';
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    show LocatedMessage, Message;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/problems.dart'
     show internalProblem, unsupported;
 import 'package:front_end/src/fasta/source/stack_listener.dart';
-import 'package:front_end/src/scanner/token.dart';
 
 /// "Mini AST" representation of a declaration which can accept annotations.
 class AnnotatedNode {
diff --git a/pkg/analyzer/tool/test_log_parser/test_log_parser.dart b/pkg/analyzer/tool/test_log_parser/test_log_parser.dart
index 851201c..fc4c0d9 100644
--- a/pkg/analyzer/tool/test_log_parser/test_log_parser.dart
+++ b/pkg/analyzer/tool/test_log_parser/test_log_parser.dart
@@ -139,10 +139,6 @@
             traceLine.contains('DeclarationResolver.applyParameters') ||
             traceLine.contains('ResolutionStorer._store')) {
           return stackTrace[i + 1];
-        } else if (traceLine.contains('_FunctionTypeImplLazy.substitute2') ||
-            traceLine.contains('ElementImpl.encloseElement') ||
-            traceLine.contains('ResolutionStorer._validateLocation')) {
-          return stackTrace[i + 2];
         }
         return traceLine;
       }
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index c5e1bc2..e6a08d1 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -8,7 +8,7 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/exception/exception.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -260,21 +260,24 @@
   }
 }
 
-/// This [Logger] prints out information comments to [outSink] and error messages
-/// to [errorSink].
-class StdLogger extends Logger {
-  StdLogger();
+/// This [InstrumentationService] prints out information comments to [outSink]
+/// and error messages to [errorSink].
+class StdInstrumentation extends InstrumentationService {
+  StdInstrumentation() : super(null);
 
   @override
-  void logError(String message, [CaughtException exception]) {
+  void logError(String message) {
     errorSink.writeln(message);
-    if (exception != null) {
-      errorSink.writeln(exception);
-    }
   }
 
   @override
-  void logInformation(String message, [CaughtException exception]) {
+  void logException(dynamic exception, [StackTrace stackTrace]) {
+    errorSink.writeln(exception);
+    errorSink.writeln(stackTrace);
+  }
+
+  @override
+  void logInfo(String message, [exception]) {
     outSink.writeln(message);
     if (exception != null) {
       outSink.writeln(exception);
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 2927eae..8c70966 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -426,8 +426,8 @@
         sdk = summarySdk;
         sdkBundle = summarySdk.bundle;
       } else {
-        FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(resourceProvider,
-            resourceProvider.getFolder(options.dartSdkPath), true);
+        FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(
+            resourceProvider, resourceProvider.getFolder(options.dartSdkPath));
         dartSdk.analysisOptions =
             createAnalysisOptionsForCommandLineOptions(options, rootPath);
         dartSdk.useSummary = !options.buildSummaryOnly;
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 9252730..02197e3 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -613,7 +613,7 @@
 
     // Set up logging.
     if (options.log) {
-      AnalysisEngine.instance.logger = new StdLogger();
+      AnalysisEngine.instance.instrumentationService = new StdInstrumentation();
     }
 
     // Save stats from previous context before clobbering it.
@@ -770,7 +770,7 @@
       } else {
         String dartSdkPath = options.dartSdkPath;
         FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(
-            resourceProvider, resourceProvider.getFolder(dartSdkPath), true);
+            resourceProvider, resourceProvider.getFolder(dartSdkPath));
         dartSdk.useSummary = useSummaries &&
             options.sourceFiles.every((String sourcePath) {
               sourcePath = path.absolute(sourcePath);
diff --git a/pkg/analyzer_fe_comparison/lib/src/kernel.dart b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
index b5df74b..c8fe0be 100644
--- a/pkg/analyzer_fe_comparison/lib/src/kernel.dart
+++ b/pkg/analyzer_fe_comparison/lib/src/kernel.dart
@@ -4,11 +4,11 @@
 
 import 'dart:async';
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, DiagnosticMessageHandler, getMessageHeaderText;
 import 'package:analyzer_fe_comparison/src/comparison_node.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions;
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler, getMessageHeaderText;
 import 'package:front_end/src/api_prototype/kernel_generator.dart';
 import 'package:front_end/src/api_prototype/standard_file_system.dart';
 import 'package:kernel/ast.dart';
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 228f53d..6b0880f 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/suggestion_builder.dart
@@ -150,7 +150,7 @@
       DartType type = element.type;
       return type != null ? type.displayName : 'dynamic';
     } else if (element is FunctionTypeAliasElement) {
-      return element.returnType.toString();
+      return element.function.returnType.toString();
     } else {
       return null;
     }
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index 0763e54..a4e973e 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -241,7 +241,7 @@
       }
       parameters = element.parameters;
     } else if (element is analyzer.FunctionTypeAliasElement) {
-      parameters = element.parameters;
+      parameters = element.function.parameters;
     } else {
       return null;
     }
@@ -283,7 +283,7 @@
       analyzer.DartType type = element.type;
       return type != null ? type.displayName : 'dynamic';
     } else if (element is analyzer.FunctionTypeAliasElement) {
-      return element.returnType.toString();
+      return element.function.returnType.toString();
     }
     return null;
   }
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index 10d21a7..0c69701 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
-import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -128,7 +127,6 @@
 
   void tearDown() {
     AnalysisEngine.instance.clearCaches();
-    AnalysisEngine.instance.logger = null;
   }
 
   void _addTestPackageDependency(String name, String rootPath) {
@@ -163,29 +161,6 @@
 }
 
 /**
- * Instances of the class [PrintLogger] print all of the errors.
- */
-class PrintLogger implements Logger {
-  static final Logger instance = new PrintLogger();
-
-  @override
-  void logError(String message, [CaughtException exception]) {
-    print(message);
-    if (exception != null) {
-      print(exception);
-    }
-  }
-
-  @override
-  void logInformation(String message, [CaughtException exception]) {
-    print(message);
-    if (exception != null) {
-      print(exception);
-    }
-  }
-}
-
-/**
  * Wraps the given [_ElementVisitorFunction] into an instance of
  * [engine.GeneralizingElementVisitor].
  */
diff --git a/pkg/async_helper/lib/async_helper.dart b/pkg/async_helper/lib/async_helper.dart
index 509af15..ddab13d 100644
--- a/pkg/async_helper/lib/async_helper.dart
+++ b/pkg/async_helper/lib/async_helper.dart
@@ -90,6 +90,8 @@
   return f().then(asyncSuccess);
 }
 
+bool _pass(dynamic object) => true;
+
 /// Calls [f] and verifies that it throws a `T`.
 ///
 /// The optional [check] function can provide additional validation that the
@@ -103,7 +105,7 @@
 /// exception is not caught by [asyncExpectThrows]. The test is still considered
 /// failing.
 void asyncExpectThrows<T>(Future<void> f(),
-    [bool check(T error), String reason]) {
+    [bool check(T error) = _pass, String reason = ""]) {
   var type = "";
   if (T != dynamic && T != Object) type = "<$T>";
   var header = "asyncExpectThrows$type(${reason ?? ''}):";
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index adb9abc..386f4ed 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -503,11 +503,14 @@
   FunctionEntity get rtiEvalMethod;
   FunctionEntity get rtiBindMethod;
   FunctionEntity get rtiAddRulesMethod;
+  FunctionEntity get rtiAddErasedTypesMethod;
 
   FunctionEntity get generalIsTestImplementation;
   FunctionEntity get generalAsCheckImplementation;
   FunctionEntity get generalTypeCheckImplementation;
 
+  FunctionEntity get specializedIsTop;
+  FunctionEntity get specializedAsTop;
   FunctionEntity get specializedIsBool;
   FunctionEntity get specializedAsBoolNullable;
   FunctionEntity get specializedCheckBoolNullable;
@@ -1935,6 +1938,11 @@
   FunctionEntity get rtiAddRulesMethod =>
       _rtiAddRulesMethod ??= _findClassMember(_rtiUniverseClass, 'addRules');
 
+  FunctionEntity _rtiAddErasedTypesMethod;
+  @override
+  FunctionEntity get rtiAddErasedTypesMethod => _rtiAddErasedTypesMethod ??=
+      _findClassMember(_rtiUniverseClass, 'addErasedTypes');
+
   FunctionEntity _generalIsTestImplementation;
   @override
   FunctionEntity get generalIsTestImplementation =>
@@ -1954,6 +1962,12 @@
           _findRtiFunction('_generalTypeCheckImplementation');
 
   @override
+  FunctionEntity get specializedIsTop => _findRtiFunction('_isTop');
+
+  @override
+  FunctionEntity get specializedAsTop => _findRtiFunction('_asTop');
+
+  @override
   FunctionEntity get specializedIsBool => _findRtiFunction('_isBool');
 
   @override
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index f34388f..186623f 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -1656,6 +1656,11 @@
   }
 
   @override
+  void visitErasedType(ErasedType type, Null argument) {
+    // Nothing to add.
+  }
+
+  @override
   void visitAnyType(AnyType type, Null argument) {
     // Nothing to add.
   }
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index df92e42..5445a80 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -44,6 +44,9 @@
   /// Is `true` if this type is the dynamic type.
   bool get isDynamic => false;
 
+  /// Is `true` if this type is an erased type.
+  bool get isErased => false;
+
   /// Is `true` if this type is the any type.
   bool get isAny => false;
 
@@ -393,7 +396,9 @@
 }
 
 class VoidType extends DartType {
-  const VoidType();
+  const VoidType._();
+
+  factory VoidType() => const VoidType._();
 
   @override
   bool get isVoid => true;
@@ -412,7 +417,9 @@
 }
 
 class DynamicType extends DartType {
-  const DynamicType();
+  const DynamicType._();
+
+  factory DynamicType() => const DynamicType._();
 
   @override
   bool get isDynamic => true;
@@ -433,6 +440,29 @@
   }
 }
 
+class ErasedType extends DartType {
+  const ErasedType._();
+
+  factory ErasedType() => const ErasedType._();
+
+  @override
+  bool get treatAsDynamic => true;
+
+  @override
+  bool get isErased => true;
+
+  @override
+  R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
+      visitor.visitErasedType(this, argument);
+
+  @override
+  int get hashCode => 119;
+
+  @override
+  bool _equals(DartType other, _Assumptions assumptions) =>
+      identical(this, other);
+}
+
 /// Represents a type which is simultaneously top and bottom.
 ///
 /// This is not a standard Dart type, but an extension of the standard Dart type
@@ -445,7 +475,9 @@
 /// * Representing types appearing as generic method bounds which contain type
 /// variables. (See issue 33422.)
 class AnyType extends DartType {
-  const AnyType();
+  const AnyType._();
+
+  factory AnyType() => const AnyType._();
 
   @override
   bool get isAny => true;
@@ -659,6 +691,8 @@
 
   R visitDynamicType(covariant DynamicType type, A argument) => null;
 
+  R visitErasedType(covariant ErasedType type, A argument) => null;
+
   R visitAnyType(covariant AnyType type, A argument) => null;
 
   R visitFutureOrType(covariant FutureOrType type, A argument) => null;
@@ -695,6 +729,10 @@
       visitType(type, argument);
 
   @override
+  R visitErasedType(covariant ErasedType type, A argument) =>
+      visitType(type, argument);
+
+  @override
   R visitAnyType(covariant AnyType type, A argument) =>
       visitType(type, argument);
 
@@ -888,6 +926,9 @@
   DartType visitDynamicType(covariant DynamicType type, A argument) => type;
 
   @override
+  DartType visitErasedType(covariant ErasedType type, A argument) => type;
+
+  @override
   DartType visitAnyType(covariant AnyType type, A argument) => type;
 
   @override
@@ -959,6 +1000,7 @@
   bool handleInterfaceType(InterfaceType type) => false;
   bool handleTypedefType(TypedefType type) => false;
   bool handleDynamicType(DynamicType type) => false;
+  bool handleErasedType(ErasedType type) => false;
   bool handleAnyType(AnyType type) => false;
   bool handleFutureOrType(FutureOrType type) => false;
 
@@ -1021,6 +1063,10 @@
       handleDynamicType(type);
 
   @override
+  bool visitErasedType(ErasedType type, List<FunctionTypeVariable> bindings) =>
+      handleErasedType(type);
+
+  @override
   bool visitAnyType(AnyType type, List<FunctionTypeVariable> bindings) =>
       handleAnyType(type);
 
@@ -1159,6 +1205,11 @@
   }
 
   @override
+  void visitErasedType(covariant ErasedType type, _) {
+    _identifier('erased');
+  }
+
+  @override
   void visitAnyType(covariant AnyType type, _) {
     _identifier('any');
   }
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 95f3c9c..4c49acb 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1691,7 +1691,7 @@
       TypeInformation mask;
       DartType type = node.guard != null
           ? _elementMap.getDartType(node.guard)
-          : const DynamicType();
+          : DynamicType();
       if (type.isInterfaceType) {
         InterfaceType interfaceType = type;
         mask = _types.nonNullSubtype(interfaceType.element);
@@ -1700,7 +1700,7 @@
       }
       Local local = _localsMap.getLocalVariable(exception);
       _state.updateLocal(
-          _inferrer, _capturedAndBoxed, local, mask, node, const DynamicType(),
+          _inferrer, _capturedAndBoxed, local, mask, node, DynamicType(),
           isNullable: false /* `throw null` produces a NullThrownError */);
     }
     ir.VariableDeclaration stackTrace = node.stackTrace;
@@ -1710,7 +1710,7 @@
       // Note: stack trace may be null if users omit a stack in
       // `completer.completeError`.
       _state.updateLocal(_inferrer, _capturedAndBoxed, local,
-          _types.dynamicType, node, const DynamicType());
+          _types.dynamicType, node, DynamicType());
     }
     visit(node.body);
     return null;
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index cb1c2a4..84d3e5c 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -714,9 +714,15 @@
           node, CodePositionKind.START, SourcePositionKind.START);
     } else if (access is js.Fun ||
         access is js.New ||
-        access is js.NamedFunction) {
-      // function(){}()  new Function("...")()   function foo(){}()
-      //             ^                      ^                    ^
+        access is js.NamedFunction ||
+        (access is js.Parentheses &&
+            (access.enclosed is js.Fun ||
+                access.enclosed is js.New ||
+                access.enclosed is js.NamedFunction))) {
+      // function(){}()     new Function("...")()     function foo(){}()
+      //             ^                         ^                      ^
+      // (function(){})()   (new Function("..."))()   (function foo(){})()
+      //               ^                         ^                      ^
       return new CallPosition(
           node.target, CodePositionKind.END, SourcePositionKind.INNER);
     } else if (access is js.Binary || access is js.Call) {
diff --git a/pkg/compiler/lib/src/ir/closure.dart b/pkg/compiler/lib/src/ir/closure.dart
index a1c9773..336b148 100644
--- a/pkg/compiler/lib/src/ir/closure.dart
+++ b/pkg/compiler/lib/src/ir/closure.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/text/ast_to_text.dart' as ir show debugNodeToString;
 
 /// Collection of scope data collected for a single member.
 class ClosureScopeModel {
@@ -414,4 +415,7 @@
   String toString() =>
       'TypeVariableTypeWithContext(type=$type,context=$context,'
       'kind=$kind,typeDeclaration=$typeDeclaration)';
+
+  @override
+  String leakingDebugToString() => ir.debugNodeToString(this);
 }
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 9850a1a..1f92dffc 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -193,6 +193,9 @@
   bool visitBottomType(ir.BottomType node) => false;
 
   @override
+  bool visitNeverType(ir.NeverType node) => false;
+
+  @override
   bool visitVoidType(ir.VoidType node) => false;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index b41805a..ffd71e5 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -595,7 +595,7 @@
     if (node.parameter.parent is ir.Typedef) {
       // Typedefs are only used in type literals so we never need their type
       // variables.
-      return const DynamicType();
+      return DynamicType();
     }
     return new TypeVariableType(elementMap.getTypeVariable(node.parameter));
   }
@@ -647,19 +647,19 @@
 
   @override
   DartType visitVoidType(ir.VoidType node) {
-    return const VoidType();
+    return VoidType();
   }
 
   @override
   DartType visitDynamicType(ir.DynamicType node) {
-    return const DynamicType();
+    return DynamicType();
   }
 
   @override
   DartType visitInvalidType(ir.InvalidType node) {
     // Root uses such a `o is Unresolved` and `o as Unresolved` must be special
     // cased in the builder, nested invalid types are treated as `dynamic`.
-    return const DynamicType();
+    return DynamicType();
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index c755f95..e4c6473 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -814,6 +814,9 @@
         _commonElements.specializedIsString,
         _commonElements.specializedAsStringNullable,
         _commonElements.specializedCheckStringNullable,
+        _commonElements.specializedIsTop,
+        _commonElements.specializedAsTop,
+        // no specializedCheckTop
       ], globalClasses: [
         _commonElements.closureClass, // instanceOrFunctionType uses this.
       ], globalUses: [])
@@ -822,7 +825,10 @@
 
   BackendImpact _rtiAddRules;
 
-  BackendImpact get rtiAddRules => _rtiAddRules ??= BackendImpact(
-      globalUses: [_commonElements.rtiAddRulesMethod],
-      otherImpacts: [_needsString('Needed to encode the new RTI ruleset.')]);
+  BackendImpact get rtiAddRules => _rtiAddRules ??= BackendImpact(globalUses: [
+        _commonElements.rtiAddRulesMethod,
+        _commonElements.rtiAddErasedTypesMethod
+      ], otherImpacts: [
+        _needsString('Needed to encode the new RTI ruleset.')
+      ]);
 }
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index 62e9fa0..f7d02de 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -126,6 +126,8 @@
       WorldImpactBuilderImpl newRtiImpact = new WorldImpactBuilderImpl();
       newRtiImpact.registerStaticUse(StaticUse.staticInvoke(
           _commonElements.rtiAddRulesMethod, CallStructure.TWO_ARGS));
+      newRtiImpact.registerStaticUse(StaticUse.staticInvoke(
+          _commonElements.rtiAddErasedTypesMethod, CallStructure.TWO_ARGS));
       enqueuer.applyImpact(newRtiImpact);
       _isNewRtiUsed = true;
     }
diff --git a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
index 549909d..435d29e 100644
--- a/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/js_interop_analysis.dart
@@ -45,9 +45,9 @@
   // range of positional arguments that need to be supported by JavaScript
   // function types.
   return new FunctionType(
-      const DynamicType(),
+      DynamicType(),
       const <DartType>[],
-      new List<DartType>.filled(16, const DynamicType()),
+      new List<DartType>.filled(16, DynamicType()),
       const <String>[],
       const <DartType>[],
       const <FunctionTypeVariable>[]);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 8284882..b486e74 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -133,6 +133,8 @@
 
   /// Compute the required type checks and substitutions for the given
   /// instantiated and checked classes.
+  // TODO(fishythefish): Unify type checks and substitutions once old RTI is
+  // removed.
   TypeChecks _computeChecks(Map<ClassEntity, ClassUse> classUseMap) {
     // Run through the combination of instantiated and checked
     // arguments and record all combination where the element of a checked
@@ -297,9 +299,17 @@
               } else {
                 // We need a non-trivial substitution function for
                 // [checkedClass].
-                checks.add(new TypeCheck(
-                    checkedClass, computeSubstitution(cls, checkedClass),
-                    needsIs: false));
+                Substitution substitution =
+                    computeSubstitution(cls, checkedClass);
+                checks.add(
+                    new TypeCheck(checkedClass, substitution, needsIs: false));
+
+                assert(substitution != null);
+                for (DartType argument in substitution.arguments) {
+                  if (argument is InterfaceType) {
+                    computeChecks(argument.element);
+                  }
+                }
               }
             }
           } else {
@@ -312,9 +322,17 @@
             } else {
               // We need a non-trivial substitution function for
               // [checkedClass].
-              checks.add(new TypeCheck(
-                  checkedClass, computeSubstitution(cls, checkedClass),
-                  needsIs: needsIs));
+              Substitution substitution =
+                  computeSubstitution(cls, checkedClass);
+              checks.add(
+                  new TypeCheck(checkedClass, substitution, needsIs: needsIs));
+
+              assert(substitution != null);
+              for (DartType argument in substitution.arguments) {
+                if (argument is InterfaceType) {
+                  computeChecks(argument.element);
+                }
+              }
             }
           }
         }
@@ -1018,6 +1036,11 @@
   }
 
   @override
+  jsAst.Expression visitErasedType(ErasedType type, ModularEmitter emitter) {
+    throw UnsupportedError('Legacy RTI does not support erased types');
+  }
+
+  @override
   jsAst.Expression visitAnyType(AnyType type, ModularEmitter emitter) =>
       getJsInteropTypeArgumentValue();
 
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
index 62ae8ed..92a3b0a 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -36,13 +36,6 @@
 
   jsAst.Literal encodeGroundRecipe(ModularEmitter emitter, TypeRecipe recipe);
 
-  /// Return the recipe with type variables replaced with <any>. This is a hack
-  /// until DartType contains <any> and the parameter stub emitter is replaced
-  /// with an SSA path.
-  // TODO(37715): Remove this.
-  jsAst.Literal encodeRecipeWithVariablesReplaceByAny(
-      ModularEmitter emitter, DartType dartType);
-
   /// Returns a [jsAst.Literal] representing [supertypeArgument] to be evaluated
   /// against a [FullTypeEnvironmentStructure] representing [declaringType]. Any
   /// [TypeVariableType]s appearing in [supertypeArgument] which are declared by
@@ -86,15 +79,6 @@
   }
 
   @override
-  jsAst.Literal encodeRecipeWithVariablesReplaceByAny(
-      ModularEmitter emitter, DartType dartType) {
-    return _RecipeGenerator(this, emitter, null, TypeExpressionRecipe(dartType),
-            hackTypeVariablesToAny: true)
-        .run()
-        .recipe;
-  }
-
-  @override
   jsAst.Literal encodeMetadataRecipe(ModularEmitter emitter,
       InterfaceType declaringType, DartType supertypeArgument) {
     return _RecipeGenerator(
@@ -132,7 +116,6 @@
   final TypeEnvironmentStructure _environment;
   final TypeRecipe _recipe;
   final bool metadata;
-  final bool hackTypeVariablesToAny;
 
   final List<FunctionTypeVariable> functionTypeVariables = [];
   final Set<TypeVariableType> typeVariables = {};
@@ -143,7 +126,7 @@
 
   _RecipeGenerator(
       this._encoder, this._emitter, this._environment, this._recipe,
-      {this.metadata = false, this.hackTypeVariablesToAny = false});
+      {this.metadata = false});
 
   JClosedWorld get _closedWorld => _encoder._closedWorld;
   NativeBasicData get _nativeData => _encoder._nativeData;
@@ -244,12 +227,6 @@
 
   @override
   void visitTypeVariableType(TypeVariableType type, _) {
-    if (hackTypeVariablesToAny) {
-      // Emit 'any' type.
-      _emitExtensionOp(Recipe.pushAnyExtension);
-      return;
-    }
-
     TypeEnvironmentStructure environment = _environment;
     if (environment is SingletonTypeEnvironmentStructure) {
       if (type == environment.variable) {
@@ -291,6 +268,11 @@
   }
 
   @override
+  void visitErasedType(ErasedType type, _) {
+    _emitCode(Recipe.pushErased);
+  }
+
+  @override
   void visitAnyType(AnyType type, _) {
     _emitExtensionOp(Recipe.pushAnyExtension);
   }
@@ -483,13 +465,14 @@
   Set<InterfaceType> _supertypes = {};
   Map<TypeVariableType, DartType> _typeVariables = {};
 
+  bool get isEmpty => _supertypes.isEmpty && _typeVariables.isEmpty;
+  bool get isNotEmpty => _supertypes.isNotEmpty || _typeVariables.isNotEmpty;
+
   void addAll(Iterable<InterfaceType> supertypes,
       Map<TypeVariableType, DartType> typeVariables) {
     _supertypes.addAll(supertypes);
     _typeVariables.addAll(typeVariables);
   }
-
-  bool get isEmpty => _supertypes.isEmpty && _typeVariables.isEmpty;
 }
 
 class Ruleset {
@@ -499,6 +482,9 @@
   Ruleset(this._redirections, this._entries);
   Ruleset.empty() : this({}, {});
 
+  bool get isEmpty => _redirections.isEmpty && _entries.isEmpty;
+  bool get isNotEmpty => _redirections.isNotEmpty || _entries.isNotEmpty;
+
   void addRedirection(ClassEntity targetClass, ClassEntity redirection) {
     _redirections[targetClass] = redirection;
   }
@@ -613,4 +599,22 @@
           InterfaceType targetType, DartType supertypeArgument) =>
       _recipeEncoder.encodeMetadataRecipe(
           _emitter, targetType, supertypeArgument);
+
+  jsAst.StringConcatenation encodeErasedTypes(
+          Map<ClassEntity, int> erasedTypes) =>
+      js.concatenateStrings([
+        _quote,
+        _leftBrace,
+        ...js.joinLiterals(erasedTypes.entries.map(encodeErasedType), _comma),
+        _rightBrace,
+        _quote,
+      ]);
+
+  jsAst.StringConcatenation encodeErasedType(
+          MapEntry<ClassEntity, int> entry) =>
+      js.concatenateStrings([
+        js.quoteName(_emitter.typeAccessNewRti(entry.key)),
+        _colon,
+        js.number(entry.value),
+      ]);
 }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 75742c5..9c9fd78 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -653,7 +653,7 @@
   /// Serializes this [RuntimeTypesNeed] to [sink].
   void writeToDataSink(DataSink sink);
 
-  /// Returns `true` if [cls] needs type arguments at runtime type.
+  /// Returns `true` if [cls] needs type arguments at runtime.
   ///
   /// This is for instance the case for generic classes used in a type test:
   ///
@@ -665,6 +665,10 @@
   ///
   bool classNeedsTypeArguments(ClassEntity cls);
 
+  /// Returns `true` if [cls] is a generic class which does not need type
+  /// arguments at runtime.
+  bool classHasErasedTypeArguments(ClassEntity cls);
+
   /// Returns `true` if [method] needs type arguments at runtime type.
   ///
   /// This is for instance the case for generic methods that use type tests:
@@ -729,6 +733,9 @@
       _elementEnvironment.isGenericClass(cls);
 
   @override
+  bool classHasErasedTypeArguments(ClassEntity cls) => false;
+
+  @override
   bool methodNeedsSignature(FunctionEntity method) => true;
 
   @override
@@ -821,6 +828,13 @@
   }
 
   @override
+  bool classHasErasedTypeArguments(ClassEntity cls) {
+    assert(checkClass(cls));
+    if (!_elementEnvironment.isGenericClass(cls)) return false;
+    return !classesNeedingTypeArguments.contains(cls);
+  }
+
+  @override
   bool methodNeedsSignature(FunctionEntity function) {
     return methodsNeedingSignature.contains(function);
   }
diff --git a/pkg/compiler/lib/src/js_backend/type_reference.dart b/pkg/compiler/lib/src/js_backend/type_reference.dart
index 4323e64..2b7f88e 100644
--- a/pkg/compiler/lib/src/js_backend/type_reference.dart
+++ b/pkg/compiler/lib/src/js_backend/type_reference.dart
@@ -91,10 +91,16 @@
   /// [typeRecipe] is a recipe for a ground type or type environment.
   final TypeRecipe typeRecipe;
 
+  // TODO(sra): Refine the concept of reference context and replace the
+  // 'forConstant' and 'forLazyInitializer' flags.
+
   // `true` if TypeReference is in code that initializes constant value.
-  // TODO(sra): Refine the concept of reference context.
   bool forConstant = false;
 
+  // `true` if TypeReference is in code for a lazy initializer of a static
+  // variable.
+  bool forLazyInitializer = false;
+
   js.Expression _value;
 
   @override
@@ -106,13 +112,15 @@
   factory TypeReference.readFromDataSource(DataSource source) {
     source.begin(tag);
     TypeRecipe recipe = source.readTypeRecipe();
+    bool forLazyInitializer = source.readBool();
     source.end(tag);
-    return TypeReference(recipe);
+    return TypeReference(recipe)..forLazyInitializer = forLazyInitializer;
   }
 
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeTypeRecipe(typeRecipe);
+    sink.writeBool(forLazyInitializer);
     sink.end(tag);
   }
 
@@ -240,7 +248,9 @@
   void _registerTypeReference(TypeReference node) {
     TypeRecipe recipe = node.typeRecipe;
     _ReferenceSet refs = _referencesByRecipe[recipe] ??= _ReferenceSet(recipe);
-    refs.count += 1;
+    refs.count++;
+    if (node.forConstant) refs.countInConstant++;
+    if (node.forLazyInitializer) refs.countInLazyInitializer++;
     refs._references.add(node);
   }
 
@@ -289,8 +299,11 @@
     }
     var initializer = js.ObjectInitializer(properties, isOneLiner: false);
 
-    _resource.value = js.js(r'var # = #',
-        [js.VariableDeclaration(typesHolderLocalName), initializer]);
+    var function = js.js(r'function rtii(){return #}', initializer);
+    _resource.value = js.js(r'var # = #()', [
+      js.VariableDeclaration(typesHolderLocalName),
+      js.Parentheses(function)
+    ]);
   }
 
   // This is a top-level local name in the generated JavaScript top-level
@@ -299,19 +312,45 @@
   static const typesHolderLocalName = r'type$';
 
   void _allocateNames() {
-    // Step 1. Filter out generate-at-use cases and allocate unique
-    // characteristic names to the rest.
+    // Filter out generate-at-use cases and allocate unique names to the rest.
     List<_ReferenceSet> referencesInTable = [];
     Set<String> usedNames = {};
     for (_ReferenceSet referenceSet in _referencesByRecipe.values) {
-      // TODO(sra): Use more refined idea of context, e.g. single-use recipes in
-      // lazy initializers or 'throw' expressions.
+      // - If a type is used only once from a constant then the findType can be
+      // a subexpression of constant since it will be evaluated exactly once and
+      // need not be stored anywhere else.
+      if (referenceSet.count == 1 && referenceSet.countInConstant == 1) {
+        continue;
+      }
 
-      // If a type is used only once from a constant then the findType can be a
-      // subexpression of constant since it will be evaluated only once and need
-      // not be stored anywhere else.
-      if (referenceSet.count == 1 &&
-          referenceSet._references.single.forConstant) continue;
+      // - Lazy initializers are usually evaluated on demand and only once, so
+      // it is worth deferrering evaluating the type references until the lazy
+      // initializer is executed, provided it does not increase program
+      // size too much.
+      //
+      // Assuming minification in a large program, the size for precomputed is
+      //
+      //     abc:f("TTT"),/*once*/ +  type$.abc/*N times*/
+      //
+      // i.e. 13 + 5N. The size for repeated generate-at-use is
+      //
+      //      H.lookupType("TTT") /*N times*/
+      //
+      // i.e. 10N. Repeated is smaller when 10N < 13+5N, or N < 2.6. Since we
+      // get a startup benefit of not evaluating the type recipe, lets round
+      // up. Note that we don't know the size of the recipe ("TTT" assumes an
+      // infrequently referenced non-generic interface type), but if the recipe
+      // is larger, it is in a string so the program has the same number of
+      // tokens and the extra bytes will be parsed efficiently.
+      const int maxRepeatedLookups = 3;
+
+      if (referenceSet.countInLazyInitializer == referenceSet.count &&
+          referenceSet.count <= maxRepeatedLookups) {
+        continue;
+      }
+
+      // TODO(sra): There are other contexts that would be beneficial, e.g. a
+      // type reference occuring only in a throw expression.
 
       String suggestedName = _RecipeToIdentifier().run(referenceSet.recipe);
       if (usedNames.contains(suggestedName)) {
@@ -421,6 +460,11 @@
   // JavaScript ASTs.
   int count = 0;
 
+  // Number tree-scan occurrences in a constant initializer.
+  int countInConstant = 0;
+  // Number tree-scan occurrences in a static lazy initializer.
+  int countInLazyInitializer = 0;
+
   // It is possible for the JavaScript AST to be a DAG, so collect
   // [TypeReference]s as set so we don't try to update one twice.
   final Set<TypeReference> _references = Set.identity();
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index 15eeb44..f1200d2 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -225,6 +225,8 @@
   int visitDynamicType(covariant DynamicType type, _) => 5;
   @override
   int visitAnyType(covariant AnyType type, _) => 7;
+  @override
+  int visitErasedType(covariant ErasedType type, _) => 8;
 }
 
 class _DartTypeOrdering extends DartTypeVisitor<int, DartType> {
@@ -295,6 +297,11 @@
   }
 
   @override
+  int visitErasedType(covariant ErasedType type, covariant ErasedType other) {
+    throw UnsupportedError('Unreachable');
+  }
+
+  @override
   int visitAnyType(covariant AnyType type, covariant AnyType other) {
     throw UnsupportedError('Unreachable');
   }
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 98412ea..482d49e 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -250,7 +250,7 @@
     type.forEachTypeVariable(variables.add);
     assert(variables.isNotEmpty);
     return type.subst(
-        List.filled(variables.length, const AnyType()), variables.toList());
+        List.filled(variables.length, AnyType()), variables.toList());
   }
 
   // We fill the lists depending on possible/invoked selectors. For example,
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 91d8954..cfd16dc 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
@@ -987,6 +987,23 @@
   }
 
   js.Expression _generateFunctionType(ClassEntity /*?*/ enclosingClass,
+          FunctionType type, OutputUnit outputUnit) =>
+      _options.experimentNewRti
+          ? _generateFunctionTypeNewRti(enclosingClass, type, outputUnit)
+          : _generateFunctionTypeLegacy(enclosingClass, type, outputUnit);
+
+  js.Expression _generateFunctionTypeLegacy(ClassEntity /*?*/ enclosingClass,
+      FunctionType type, OutputUnit outputUnit) {
+    if (type.containsTypeVariables) {
+      js.Expression thisAccess = js.js(r'this.$receiver');
+      return _rtiEncoder.getSignatureEncoding(
+          _namer, _task.emitter, type, thisAccess);
+    } else {
+      return _task.metadataCollector.reifyType(type, outputUnit);
+    }
+  }
+
+  js.Expression _generateFunctionTypeNewRti(ClassEntity /*?*/ enclosingClass,
       FunctionType type, OutputUnit outputUnit) {
     InterfaceType enclosingType;
     if (enclosingClass != null && type.containsTypeVariables) {
@@ -995,24 +1012,18 @@
         // Erase type arguments.
         List<DartType> typeArguments = enclosingType.typeArguments;
         type = type.subst(
-            List<DartType>.filled(typeArguments.length, const DynamicType()),
+            List<DartType>.filled(typeArguments.length, ErasedType()),
             typeArguments);
       }
     }
 
     if (type.containsTypeVariables) {
-      if (_options.experimentNewRti) {
-        RecipeEncoding encoding = _rtiRecipeEncoder.encodeRecipe(
-            _task.emitter,
-            FullTypeEnvironmentStructure(classType: enclosingType),
-            TypeExpressionRecipe(type));
-        _lateNamedTypeVariablesNewRti.addAll(encoding.typeVariables);
-        return encoding.recipe;
-      } else {
-        js.Expression thisAccess = js.js(r'this.$receiver');
-        return _rtiEncoder.getSignatureEncoding(
-            _namer, _task.emitter, type, thisAccess);
-      }
+      RecipeEncoding encoding = _rtiRecipeEncoder.encodeRecipe(
+          _task.emitter,
+          FullTypeEnvironmentStructure(classType: enclosingType),
+          TypeExpressionRecipe(type));
+      _lateNamedTypeVariablesNewRti.addAll(encoding.typeVariables);
+      return encoding.recipe;
     } else {
       return _task.metadataCollector.reifyType(type, outputUnit);
     }
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index aaea216..fcc0a7e 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -335,6 +335,9 @@
   bool visitDynamicType(DynamicType type, OutputUnit argument) => true;
 
   @override
+  bool visitErasedType(ErasedType type, OutputUnit argument) => true;
+
+  @override
   bool visitAnyType(AnyType type, OutputUnit argument) => true;
 
   @override
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 a18606f..fbee515 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
@@ -599,6 +599,7 @@
   JElementEnvironment get _elementEnvironment =>
       _closedWorld.elementEnvironment;
   NativeData get _nativeData => _closedWorld.nativeData;
+  RuntimeTypesNeed get _rtiNeed => _closedWorld.rtiNeed;
 
   js.Name _call0Name, _call1Name, _call2Name;
   js.Name get call0Name =>
@@ -1961,20 +1962,29 @@
     return js.Block(statements);
   }
 
-  js.Statement emitTypeRules(Fragment fragment) {
-    if (!_options.experimentNewRti) return js.EmptyStatement();
+  js.Block emitTypeRules(Fragment fragment) {
+    if (!_options.experimentNewRti) return js.Block.empty();
 
+    List<js.Statement> statements = [];
     bool addJsObjectRedirections = false;
     ClassEntity jsObjectClass = _commonElements.jsJavaScriptObjectClass;
     InterfaceType jsObjectType = _elementEnvironment.getThisType(jsObjectClass);
 
     Ruleset ruleset = Ruleset.empty();
+    Map<ClassEntity, int> erasedTypes = {};
     Iterable<Class> classes =
         fragment.libraries.expand((Library library) => library.classes);
     classes.forEach((Class cls) {
+      ClassEntity element = cls.element;
+      InterfaceType targetType = _elementEnvironment.getThisType(element);
+
+      // TODO(fishythefish): Prune uninstantiated classes.
+      if (_rtiNeed.classHasErasedTypeArguments(element)) {
+        erasedTypes[element] = targetType.typeArguments.length;
+      }
+
       if (cls.classChecksNewRti == null) return;
-      InterfaceType targetType = _elementEnvironment.getThisType(cls.element);
-      bool isInterop = _nativeData.isJsInteropClass(cls.element);
+      bool isInterop = _nativeData.isJsInteropClass(element);
 
       Iterable<TypeCheck> checks = cls.classChecksNewRti.checks;
       Iterable<InterfaceType> supertypes = isInterop
@@ -2009,12 +2019,26 @@
       });
     }
 
-    FunctionEntity method = _closedWorld.commonElements.rtiAddRulesMethod;
-    return js.js.statement('#(init.#,JSON.parse(#));', [
-      _emitter.staticFunctionAccess(method),
-      RTI_UNIVERSE,
-      _rulesetEncoder.encodeRuleset(ruleset),
-    ]);
+    if (ruleset.isNotEmpty) {
+      FunctionEntity addRules = _closedWorld.commonElements.rtiAddRulesMethod;
+      statements.add(js.js.statement('#(init.#,JSON.parse(#));', [
+        _emitter.staticFunctionAccess(addRules),
+        RTI_UNIVERSE,
+        _rulesetEncoder.encodeRuleset(ruleset),
+      ]));
+    }
+
+    if (erasedTypes.isNotEmpty) {
+      FunctionEntity addErasedTypes =
+          _closedWorld.commonElements.rtiAddErasedTypesMethod;
+      statements.add(js.js.statement('#(init.#,JSON.parse(#));', [
+        _emitter.staticFunctionAccess(addErasedTypes),
+        RTI_UNIVERSE,
+        _rulesetEncoder.encodeErasedTypes(erasedTypes),
+      ]));
+    }
+
+    return js.Block(statements);
   }
 
   /// Returns an expression that creates the initial Rti Universe.
@@ -2028,6 +2052,7 @@
 
     initField(RtiUniverseFieldNames.evalCache, 'new Map()');
     initField(RtiUniverseFieldNames.typeRules, '{}');
+    initField(RtiUniverseFieldNames.erasedTypes, '{}');
     initField(RtiUniverseFieldNames.sharedEmptyArray, '[]');
 
     return js.ObjectInitializer(universeFields);
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 c353cef..4443bbc 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
@@ -54,6 +54,7 @@
 import '../../js_backend/runtime_types_codegen.dart';
 import '../../js_backend/runtime_types_new.dart'
     show RecipeEncoder, RecipeEncoderImpl, Ruleset, RulesetEncoder;
+import '../../js_backend/runtime_types_resolution.dart' show RuntimeTypesNeed;
 import '../../js_backend/type_reference.dart'
     show
         TypeReferenceFinalizer,
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 6b99f16..70d2510a 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -193,7 +193,7 @@
               new TypedefType(
                   newTypedef,
                   new List<DartType>.filled(
-                      data.node.typeParameters.length, const DynamicType()),
+                      data.node.typeParameters.length, DynamicType()),
                   getDartType(data.node.type))));
       assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
     }
@@ -709,7 +709,7 @@
         data.rawType = new InterfaceType(
             cls,
             new List<DartType>.filled(
-                node.typeParameters.length, const DynamicType()));
+                node.typeParameters.length, DynamicType()));
       }
     }
   }
@@ -722,8 +722,8 @@
         _ensureThisAndRawType(cls, data);
         data.jsInteropType = data.thisType;
       } else {
-        data.jsInteropType = InterfaceType(cls,
-            List<DartType>.filled(node.typeParameters.length, const AnyType()));
+        data.jsInteropType = InterfaceType(
+            cls, List<DartType>.filled(node.typeParameters.length, AnyType()));
       }
     }
   }
@@ -909,7 +909,7 @@
     if (node.parent is ir.Constructor) {
       // The return type on generative constructors is `void`, but we need
       // `dynamic` type to match the element model.
-      returnType = const DynamicType();
+      returnType = DynamicType();
     } else {
       returnType = getDartType(node.returnType);
     }
@@ -2180,7 +2180,7 @@
   JsElementEnvironment(this.elementMap);
 
   @override
-  DartType get dynamicType => const DynamicType();
+  DartType get dynamicType => DynamicType();
 
   @override
   LibraryEntity get mainLibrary => elementMap._mainLibrary;
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 1c8687b..fd739cc 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -761,12 +761,15 @@
 
   @override
   DartType visitDynamicType(DynamicType type, _EntityConverter converter) {
-    return const DynamicType();
+    return DynamicType();
   }
 
   @override
-  DartType visitAnyType(AnyType type, _EntityConverter converter) =>
-      const AnyType();
+  DartType visitErasedType(ErasedType type, _EntityConverter converter) =>
+      ErasedType();
+
+  @override
+  DartType visitAnyType(AnyType type, _EntityConverter converter) => AnyType();
 
   @override
   DartType visitInterfaceType(InterfaceType type, _EntityConverter converter) {
@@ -827,7 +830,7 @@
 
   @override
   DartType visitVoidType(VoidType type, _EntityConverter converter) {
-    return const VoidType();
+    return VoidType();
   }
 
   @override
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 4c899d4..66e263e 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -280,7 +280,7 @@
         data.rawType = new InterfaceType(
             cls,
             new List<DartType>.filled(
-                node.typeParameters.length, const DynamicType()));
+                node.typeParameters.length, DynamicType()));
       }
     }
   }
@@ -293,8 +293,8 @@
         _ensureThisAndRawType(cls, data);
         data.jsInteropType = data.thisType;
       } else {
-        data.jsInteropType = InterfaceType(cls,
-            List<DartType>.filled(node.typeParameters.length, const AnyType()));
+        data.jsInteropType = InterfaceType(
+            cls, List<DartType>.filled(node.typeParameters.length, AnyType()));
       }
     }
   }
@@ -483,7 +483,7 @@
     if (node.parent is ir.Constructor) {
       // The return type on generative constructors is `void`, but we need
       // `dynamic` type to match the element model.
-      returnType = const DynamicType();
+      returnType = DynamicType();
     } else {
       returnType = getDartType(node.returnType);
     }
@@ -1186,8 +1186,7 @@
     IndexedTypedef typedef = createTypedef(library, node.name);
     TypedefType typedefType = new TypedefType(
         typedef,
-        new List<DartType>.filled(
-            node.typeParameters.length, const DynamicType()),
+        new List<DartType>.filled(node.typeParameters.length, DynamicType()),
         getDartType(node.type));
     return typedefs.register(
         typedef, new KTypedefData(node, typedef, typedefType));
@@ -1647,7 +1646,7 @@
   KernelElementEnvironment(this.elementMap);
 
   @override
-  DartType get dynamicType => const DynamicType();
+  DartType get dynamicType => DynamicType();
 
   @override
   LibraryEntity get mainLibrary => elementMap._mainLibrary;
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 5bb7e12..b97e294 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -714,7 +714,7 @@
       String typeString, TypeLookup lookupType) {
     if (typeString == '=Object') return SpecialType.JsObject;
     if (typeString == 'dynamic') {
-      return const DynamicType();
+      return DynamicType();
     }
     int index = typeString.indexOf('<');
     var type = lookupType(typeString, required: index == -1);
@@ -727,7 +727,7 @@
         return type;
       }
     }
-    return const DynamicType();
+    return DynamicType();
   }
 }
 
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index b9fc97b..63ac858 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -188,7 +188,7 @@
       case DartTypeKind.none:
         return null;
       case DartTypeKind.voidType:
-        return const VoidType();
+        return VoidType();
       case DartTypeKind.typeVariable:
         return new TypeVariableType(readTypeVariable());
       case DartTypeKind.functionTypeVariable:
@@ -235,9 +235,11 @@
         DartType unaliased = _readDartType(functionTypeVariables);
         return new TypedefType(typedef, typeArguments, unaliased);
       case DartTypeKind.dynamicType:
-        return const DynamicType();
+        return DynamicType();
+      case DartTypeKind.erasedType:
+        return ErasedType();
       case DartTypeKind.anyType:
-        return const AnyType();
+        return AnyType();
       case DartTypeKind.futureOr:
         DartType typeArgument = _readDartType(functionTypeVariables);
         return new FutureOrType(typeArgument);
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 1d13e87..13b0a7f 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -96,6 +96,7 @@
   interfaceType,
   typedef,
   dynamicType,
+  erasedType,
   anyType,
   futureOr,
 }
@@ -140,7 +141,7 @@
     int index = functionTypeVariables.indexOf(type);
     if (index == -1) {
       // TODO(johnniwinther): Avoid free variables.
-      _sink._writeDartType(const DynamicType(), functionTypeVariables);
+      _sink._writeDartType(DynamicType(), functionTypeVariables);
     } else {
       _sink.writeEnum(DartTypeKind.functionTypeVariable);
       _sink.writeInt(index);
@@ -191,6 +192,12 @@
   }
 
   @override
+  void visitErasedType(covariant ErasedType type,
+      List<FunctionTypeVariable> functionTypeVariables) {
+    _sink.writeEnum(DartTypeKind.erasedType);
+  }
+
+  @override
   void visitAnyType(covariant AnyType type,
       List<FunctionTypeVariable> functionTypeVariables) {
     _sink.writeEnum(DartTypeKind.anyType);
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 3e9e4fc..00f98df 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -150,7 +150,6 @@
   final List<KernelInliningState> _inliningStack = <KernelInliningState>[];
   Local _returnLocal;
   DartType _returnType;
-  bool _inLazyInitializerExpression = false;
 
   StackFrame _currentFrame;
 
@@ -586,7 +585,7 @@
   }
 
   void _buildField(ir.Field node) {
-    _inLazyInitializerExpression = node.isStatic;
+    graph.isLazyInitializer = node.isStatic;
     FieldEntity field = _elementMap.getMember(node);
     _openFunction(field, checks: TargetChecks.none);
     if (node.isInstanceMember &&
@@ -1709,11 +1708,9 @@
     String loadId = closedWorld.outputUnitData.getImportDeferName(
         _elementMap.getSpannable(targetElement, checkLoad), import);
     HInstruction prefixConstant = graph.addConstantString(loadId, closedWorld);
-    HInstruction uriConstant =
-        graph.addConstantString('${import.uri}', closedWorld);
     _pushStaticInvocation(
         _commonElements.checkDeferredIsLoaded,
-        [prefixConstant, uriConstant],
+        [prefixConstant],
         _typeInferenceMap
             .getReturnTypeOf(_commonElements.checkDeferredIsLoaded),
         const <DartType>[],
@@ -4696,7 +4693,7 @@
     // TODO(sra): This should be JSArray<any>, created via
     // _elementEnvironment.getJsInteropType(_elementEnvironment.jsArrayClass);
     InterfaceType interopType =
-        InterfaceType(_commonElements.jsArrayClass, [const DynamicType()]);
+        InterfaceType(_commonElements.jsArrayClass, [DynamicType()]);
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildCall(invocation, invocation);
     HInstruction rti =
@@ -4995,8 +4992,8 @@
     // Native behavior effects here are similar to native/behavior.dart.
     // The return type is dynamic if we don't trust js-interop type
     // declarations.
-    nativeBehavior.typesReturned.add(
-        options.trustJSInteropTypeAnnotations ? type : const DynamicType());
+    nativeBehavior.typesReturned
+        .add(options.trustJSInteropTypeAnnotations ? type : DynamicType());
 
     // The allocation effects include the declared type if it is native (which
     // includes js interop types).
@@ -5805,7 +5802,7 @@
       }
 
       // Do not inline code that is rarely executed unless it reduces size.
-      if (_inExpressionOfThrow || _inLazyInitializerExpression) {
+      if (_inExpressionOfThrow || graph.isLazyInitializer) {
         return reductiveHeuristic(inlineData);
       }
 
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 90ffef5..7779388 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -112,7 +112,7 @@
       SourceInformation sourceInformation = sourceInformationStrategy
           .createBuilderForContext(field)
           .buildDeclaration(field);
-      SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
+      SsaCodeGenerator codeGenerator = SsaCodeGenerator(
           this,
           _options,
           emitter,
@@ -142,7 +142,7 @@
       if (method.asyncMarker != AsyncMarker.SYNC) {
         registry.registerAsyncMarker(method.asyncMarker);
       }
-      SsaCodeGenerator codeGenerator = new SsaCodeGenerator(
+      SsaCodeGenerator codeGenerator = SsaCodeGenerator(
           this,
           _options,
           emitter,
@@ -3405,7 +3405,9 @@
     // 'findType' will be called somewhere to initialize the type reference.
     _registry.registerStaticUse(StaticUse.staticInvoke(
         _commonElements.findType, CallStructure.ONE_ARG));
-    push(TypeReference(node.typeExpression));
+    TypeReference reference = TypeReference(node.typeExpression);
+    reference.forLazyInitializer = currentGraph.isLazyInitializer;
+    push(reference);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 068ae28..783485b 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -233,6 +233,7 @@
   HParameterValue explicitReceiverParameter;
   bool isRecursiveMethod = false;
   bool calledInLoop = false;
+  bool isLazyInitializer = false;
 
   final List<HBasicBlock> blocks = <HBasicBlock>[];
 
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index 700018b..121aad1 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -105,10 +105,6 @@
         negatable: false, help: 'Enable assert statements.')
     ..addFlag('help',
         abbr: 'h', negatable: false, help: 'Display this help message.')
-    ..addOption('output', abbr: 'o', valueHelp: 'path', help: '''
-Set the output filename. <path> can be relative or absolute.
-E.g.: dart2native main.dart -o ../bin/my_app.exe
-''')
     ..addOption(
       'output-kind',
       abbr: 'k',
@@ -120,6 +116,10 @@
       defaultsTo: 'exe',
       valueHelp: 'aot|exe',
     )
+    ..addOption('output', abbr: 'o', valueHelp: 'path', help: '''
+Set the output filename. <path> can be relative or absolute.
+E.g.: dart2native main.dart -o ../bin/my_app.exe
+''')
     ..addOption('packages', abbr: 'p', valueHelp: 'path', help: '''
 Get package locations from the specified file instead of .packages. <path> can be relative or absolute.
 E.g.: dart2native --packages=/tmp/pkgs main.dart
diff --git a/pkg/dartfix/CHANGELOG.md b/pkg/dartfix/CHANGELOG.md
index 153554b..3a8048b 100644
--- a/pkg/dartfix/CHANGELOG.md
+++ b/pkg/dartfix/CHANGELOG.md
@@ -1,6 +1,13 @@
 # 0.1.5
-* add command line options for selecting/excluding fixes to apply
-* add experimental NNBD migration support
+* Add command line options for selecting/excluding fixes to apply (`--fix`,
+  `--excludeFix`, and `--required`). Call with `--help` for more details.
+* Add a `--color` option for printing messages with ANSI colors. This defaults
+  to true if the terminal supports ANSI colors.
+* Add a `--pedantic` option for specifying fixes relating to the [pedantic]
+  lints.
+* Add experimental non-nullable migration support.
+
+[pedantic]: https://pub.dev/packages/pedantic
 
 # 0.1.4
  * update protocol version constraints
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index 02bcf3a..32e9b91 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -99,11 +99,13 @@
           defaultsTo: false,
           negatable: false)
       ..addOption(_serverSnapshot,
-          help: 'Path to the analysis server snapshot file.', valueHelp: 'path')
+          help: 'Path to the analysis server snapshot file.',
+          valueHelp: 'path',
+          hide: true)
       ..addFlag(_verboseOption,
           abbr: 'v',
-          defaultsTo: false,
           help: 'Verbose output.',
+          defaultsTo: false,
           negatable: false)
       ..addFlag(_colorOption,
           help: 'Use ansi colors when printing messages.',
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
index 124c866..b895769 100644
--- a/pkg/dartfix/pubspec.yaml
+++ b/pkg/dartfix/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dartfix
-version: 0.1.5-dev
+version: 0.1.5
 author: Dart Team <misc@dartlang.org>
 description:
   A tool for migrating Dart source to newer versions of the Dart SDK
@@ -13,9 +13,9 @@
   dartfix:
 
 dependencies:
-  # pin to an exact version of analysis_server_client because the edit.dartfix protocol
-  # is experimental and will continue to evolve
-  analysis_server_client: 1.1.3
+  # Pin to an exact version of analysis_server_client because the edit.dartfix
+  # protocol is experimental and will continue to evolve.
+  analysis_server_client: 1.1.2
   args: ^1.4.0
   cli_util: ^0.1.3
   path: ^1.6.0
diff --git a/pkg/dev_compiler/lib/dev_compiler.dart b/pkg/dev_compiler/lib/dev_compiler.dart
index 7859a56..e0f2bba 100644
--- a/pkg/dev_compiler/lib/dev_compiler.dart
+++ b/pkg/dev_compiler/lib/dev_compiler.dart
@@ -5,3 +5,7 @@
 // The dev_compiler does not have a publishable public API, instead this is
 // intended for other consumers within the Dart SDK.
 export 'src/kernel/target.dart' show DevCompilerTarget;
+export 'src/kernel/compiler.dart' show ProgramCompiler;
+export 'src/kernel/command.dart' show jsProgramToCode;
+export 'src/compiler/shared_command.dart' show SharedCompilerOptions;
+export 'src/compiler/module_builder.dart' show ModuleFormat;
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 198ea15..075aaae 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -5879,7 +5879,8 @@
       var finder = YieldFinder();
       body.accept(finder);
       if (finder.hasYield) {
-        var genFn = js_ast.Fun([], body, isGenerator: true);
+        js_ast.Expression genFn = js_ast.Fun([], body, isGenerator: true);
+        if (usesThisOrSuper(genFn)) genFn = js.call('#.bind(this)', genFn);
         var asyncLibrary = emitLibraryName(types.futureElement.library);
         return js_ast.Yield(js.call(
             '#.async(#, #)', [asyncLibrary, _emitType(yieldType), genFn]));
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index c100c2f..ee256ec 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -58,7 +58,7 @@
       );
     } else if (element is GenericTypeAliasElement) {
       var typeArguments = rules.instantiateTypeFormalsToBounds2(element);
-      return element.instantiate2(
+      return element.instantiate(
         typeArguments: typeArguments,
         nullabilitySuffix: NullabilitySuffix.star,
       );
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index be32b50..74d485c 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -346,8 +346,8 @@
     var scheme = uri.scheme;
     if (scheme == 'dart' || scheme == 'package' || scheme == multiRootScheme) {
       if (scheme == multiRootScheme) {
-        var multiRootPath = '$multiRootOutputPath${uri.path}';
-        multiRootPath = p.relative(multiRootPath, from: sourceMapDir);
+        var multiRootPath = "${multiRootOutputPath ?? ''}${uri.path}";
+        multiRootPath = p.url.relative(multiRootPath, from: sourceMapDir);
         return multiRootPath;
       }
       return sourcePath;
@@ -361,7 +361,7 @@
     if (match != null) return match;
 
     // Fall back to a relative path against the source map itself.
-    sourcePath = p.relative(sourcePath, from: sourceMapDir);
+    sourcePath = p.url.relative(sourcePath, from: sourceMapDir);
 
     // Convert from relative local path to relative URI.
     return p.toUri(sourcePath).path;
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 4a2f6e6..775fbbb 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -235,8 +235,16 @@
   /// distinct symbols will be used, so each library will have distinct private
   /// member names, that won't collide at runtime, as required by the Dart
   /// language spec.
+  ///
+  /// If an [id] is provided, try to use that.
+  ///
+  /// TODO(vsm): Clean up id generation logic.  This method is used to both
+  /// define new symbols and to reference existing ones.  If it's called
+  /// multiple times with same [library] and [name], we'll allocate redundant
+  /// top-level variables (see callers to this method).
   @protected
-  js_ast.TemporaryId emitPrivateNameSymbol(Library library, String name) {
+  js_ast.TemporaryId emitPrivateNameSymbol(Library library, String name,
+      [js_ast.TemporaryId id]) {
     /// Initializes the JS `Symbol` for the private member [name] in [library].
     ///
     /// If the library is in the current JS module ([_libraries] contains it),
@@ -253,7 +261,7 @@
     js_ast.TemporaryId initPrivateNameSymbol() {
       var idName = name.endsWith('=') ? name.replaceAll('=', '_') : name;
       idName = idName.replaceAll('.', '_');
-      var id = js_ast.TemporaryId(idName);
+      id ??= js_ast.TemporaryId(idName);
       moduleItems.add(js.statement('const # = #.privateName(#, #)',
           [id, runtimeModule, emitLibraryName(library), js.string(name)]));
       return id;
@@ -270,8 +278,9 @@
   /// overridden within the same library.
   @protected
   js_ast.TemporaryId emitClassPrivateNameSymbol(
-      Library library, String className, String memberName) {
-    return emitPrivateNameSymbol(library, '$className.$memberName');
+      Library library, String className, String memberName,
+      [js_ast.TemporaryId id]) {
+    return emitPrivateNameSymbol(library, '$className.$memberName', id);
   }
 
   /// Emits an expression to set the property [nameExpr] on the class [className],
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index d2020b3..3493030 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -216,8 +216,9 @@
   final NullableInference _nullableInference;
 
   factory ProgramCompiler(Component component, ClassHierarchy hierarchy,
-      SharedCompilerOptions options) {
-    var coreTypes = CoreTypes(component);
+      SharedCompilerOptions options,
+      {CoreTypes coreTypes}) {
+    coreTypes ??= CoreTypes(component);
     var types = TypeSchemaEnvironment(coreTypes, hierarchy);
     var constants = DevCompilerConstants();
     var nativeTypes = NativeTypeSet(coreTypes, constants);
@@ -589,6 +590,19 @@
     assert(formals.isNotEmpty);
     var name = getTopLevelName(c);
     var jsFormals = _emitTypeFormals(formals);
+
+    // Checks for explicitly set variance to avoid emitting legacy covariance
+    // Variance annotations are not necessary when variance experiment flag is
+    // not enabled or when no type parameters have explicitly defined
+    // variances.
+    var hasOnlyLegacyCovariance = formals.every((t) => t.isLegacyCovariant);
+    if (!hasOnlyLegacyCovariance) {
+      var varianceList = formals.map(_emitVariance);
+      var varianceStatement = runtimeStatement(
+          'setGenericArgVariances(#, [#])', [className, varianceList]);
+      body = js_ast.Statement.from([body, varianceStatement]);
+    }
+
     var typeConstructor = js.call('(#) => { #; #; return #; }', [
       jsFormals,
       _typeTable.discharge(formals),
@@ -609,6 +623,20 @@
         [genericName, genericCall, _emitTopLevelName(c), genericName]);
   }
 
+  js_ast.Expression _emitVariance(TypeParameter typeParameter) {
+    switch (typeParameter.variance) {
+      case Variance.contravariant:
+        return runtimeCall('Variance.contravariant');
+      case Variance.invariant:
+        return runtimeCall('Variance.invariant');
+      case Variance.unrelated:
+        return runtimeCall('Variance.unrelated');
+      case Variance.covariant:
+      default:
+        return runtimeCall('Variance.covariant');
+    }
+  }
+
   js_ast.Statement _emitClassStatement(Class c, js_ast.Expression className,
       js_ast.Expression heritage, List<js_ast.Method> methods) {
     if (c.typeParameters.isNotEmpty) {
@@ -2573,6 +2601,9 @@
   js_ast.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
 
   @override
+  js_ast.Expression visitNeverType(NeverType type) => runtimeCall('Never');
+
+  @override
   js_ast.Expression visitInterfaceType(InterfaceType type) {
     var c = type.classNode;
     _declareBeforeUse(c);
@@ -2645,22 +2676,29 @@
         ?.skip(type.requiredParameterCount)
         ?.toList();
 
-    var namedTypes = type.namedParameters;
-    var rt = _emitType(type.returnType);
-    var ra = _emitTypeNames(requiredTypes, requiredParams, member);
+    var namedTypes = <NamedType>[];
+    var requiredNamedTypes = <NamedType>[];
+    type.namedParameters.forEach((param) => param.isRequired
+        ? requiredNamedTypes.add(param)
+        : namedTypes.add(param));
+    var allNamedTypes = type.namedParameters;
+
+    var returnType = _emitType(type.returnType);
+    var requiredArgs = _emitTypeNames(requiredTypes, requiredParams, member);
 
     List<js_ast.Expression> typeParts;
-    if (namedTypes.isNotEmpty) {
+    if (allNamedTypes.isNotEmpty) {
       assert(optionalTypes.isEmpty);
-      // TODO(vsm): Pass in annotations here as well.
-      var na = _emitTypeProperties(namedTypes);
-      typeParts = [rt, ra, na];
+      // TODO(vsm): The old pageloader may require annotations here.
+      var namedArgs = _emitTypeProperties(namedTypes);
+      var requiredNamedArgs = _emitTypeProperties(requiredNamedTypes);
+      typeParts = [returnType, requiredArgs, namedArgs, requiredNamedArgs];
     } else if (optionalTypes.isNotEmpty) {
-      assert(namedTypes.isEmpty);
-      var oa = _emitTypeNames(optionalTypes, optionalParams, member);
-      typeParts = [rt, ra, oa];
+      assert(allNamedTypes.isEmpty);
+      var optionalArgs = _emitTypeNames(optionalTypes, optionalParams, member);
+      typeParts = [returnType, requiredArgs, optionalArgs];
     } else {
-      typeParts = [rt, ra];
+      typeParts = [returnType, requiredArgs];
     }
 
     var typeFormals = type.typeParameters;
@@ -2769,12 +2807,16 @@
     return result;
   }
 
+  /// Emits named parameters in the form '{name: type}'.
   js_ast.ObjectInitializer _emitTypeProperties(Iterable<NamedType> types) {
     return js_ast.ObjectInitializer(types
         .map((t) => js_ast.Property(propertyName(t.name), _emitType(t.type)))
         .toList());
   }
 
+  /// Emits a list of types and their metadata annotations to code.
+  ///
+  /// Annotatable contexts include typedefs and method/function declarations.
   js_ast.ArrayInitializer _emitTypeNames(List<DartType> types,
       List<VariableDeclaration> parameters, Member member) {
     var result = <js_ast.Expression>[];
@@ -2835,9 +2877,17 @@
 
   void _emitVirtualFieldSymbols(Class c, List<js_ast.Statement> body) {
     _classProperties.virtualFields.forEach((field, virtualField) {
-      var symbol = emitClassPrivateNameSymbol(
-          c.enclosingLibrary, getLocalClassName(c), field.name.name);
-      body.add(js.statement('const # = #;', [virtualField, symbol]));
+      // 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.name, virtualField);
+      if (symbol != virtualField) {
+        body.add(js.statement('const # = #;', [virtualField, symbol]));
+      }
     });
   }
 
@@ -4934,7 +4984,9 @@
 
   @override
   js_ast.Expression visitNullCheck(NullCheck node) {
-    throw UnimplementedError('Unimplemented null check expression: $node');
+    var expr = node.operand;
+    // If the expression is non-nullable already, this is a no-op.
+    return isNullable(expr) ? notNull(expr) : _visitExpression(expr);
   }
 
   @override
@@ -5266,7 +5318,8 @@
     var finder = YieldFinder();
     jsBlock.accept(finder);
     if (finder.hasYield) {
-      var genFn = js_ast.Fun([], jsBlock, isGenerator: true);
+      js_ast.Expression genFn = js_ast.Fun([], jsBlock, isGenerator: true);
+      if (usesThisOrSuper(genFn)) genFn = js.call('#.bind(this)', genFn);
       var asyncLibrary = emitLibraryName(_coreTypes.asyncLibrary);
       var returnType = _emitType(node.getStaticType(_types));
       var asyncCall =
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 3bd4a1f..960e92a 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -59,6 +59,23 @@
         'dart:web_sql'
       ];
 
+  // The libraries required to be indexed via CoreTypes.
+  @override
+  List<String> get extraIndexedLibraries => const [
+        'dart:async',
+        'dart:collection',
+        'dart:html',
+        'dart:indexed_db',
+        'dart:math',
+        'dart:svg',
+        'dart:web_audio',
+        'dart:web_gl',
+        'dart:web_sql',
+        'dart:_interceptors',
+        'dart:_js_helper',
+        'dart:_native_typed_data',
+      ];
+
   @override
   bool mayDefineRestrictedType(Uri uri) =>
       uri.scheme == 'dart' &&
diff --git a/pkg/dev_compiler/test/modular_suite_nnbd.dart b/pkg/dev_compiler/test/modular_suite_nnbd.dart
new file mode 100644
index 0000000..a40d89a
--- /dev/null
+++ b/pkg/dev_compiler/test/modular_suite_nnbd.dart
@@ -0,0 +1,353 @@
+// 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.
+
+/// Test the modular compilation pipeline of ddc.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+
+Uri sdkRoot = Platform.script.resolve("../../../");
+Options _options;
+String _dartdevcScript;
+String _kernelWorkerScript;
+main(List<String> args) async {
+  _options = Options.parse(args);
+  await _resolveScripts();
+  await runSuite(
+      sdkRoot.resolve('tests/compiler/dartdevc/modular/'),
+      'tests/compiler/dartdevc/modular/',
+      _options,
+      IOPipeline([
+        SourceToSummaryDillStep(),
+        DDKStep(),
+        RunD8(),
+      ], cacheSharedModules: true));
+}
+
+const dillId = DataId("dill");
+const jsId = DataId("js");
+const txtId = DataId("txt");
+
+class SourceToSummaryDillStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [dillId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: source-to-dill on $module");
+
+    // We use non file-URI schemes for representing source locations in a
+    // root-agnostic way. This allows us to refer to file across modules and
+    // across steps without exposing the underlying temporary folders that are
+    // created by the framework. In build systems like bazel this is especially
+    // important because each step may be run on a different machine.
+    //
+    // Files in packages are defined in terms of `package:` URIs, while
+    // non-package URIs are defined using the `dart-dev-app` scheme.
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
+    String sourceToImportUri(Uri relativeUri) =>
+        _sourceToImportUri(module, rootScheme, relativeUri);
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    await _createPackagesFile(module, root, transitiveDependencies);
+
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      sources = ['dart:core'];
+      extraArgs = [
+        '--libraries-file',
+        '$rootScheme:///sdk_nnbd/lib/libraries_nnbd_mix_hack.json'
+      ];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      sources = module.sources.map(sourceToImportUri).toList();
+      extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+    }
+
+    Module sdkModule =
+        module.isSdk ? module : module.dependencies.firstWhere((m) => m.isSdk);
+
+    List<String> args = [
+      _kernelWorkerScript,
+      '--summary-only',
+      '--target',
+      'ddc',
+      '--multi-root',
+      '$root',
+      '--multi-root-scheme',
+      rootScheme,
+      ...extraArgs,
+      '--output',
+      '${toUri(module, dillId)}',
+      if (!module.isSdk) ...[
+        '--dart-sdk-summary',
+        '${toUri(sdkModule, dillId)}',
+        '--exclude-non-sources',
+      ],
+      ...(transitiveDependencies
+          .where((m) => !m.isSdk)
+          .expand((m) => ['--input-summary', '${toUri(m, dillId)}'])),
+      ...(sources.expand((String uri) => ['--source', uri])),
+      ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+    ];
+
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: source-to-dill on $module");
+  }
+}
+
+class DDKStep implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [jsId];
+
+  @override
+  bool get needsSources => true;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [dillId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [dillId];
+
+  @override
+  bool get onlyOnMain => false;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: ddk on $module");
+
+    Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+    await _createPackagesFile(module, root, transitiveDependencies);
+
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
+    List<String> sources;
+    List<String> extraArgs;
+    if (module.isSdk) {
+      sources = ['dart:core'];
+      // extraArgs = [];
+      extraArgs = [
+        '--compile-sdk',
+        '--libraries-file',
+        '$rootScheme:///sdk_nnbd/lib/libraries_nnbd_mix_hack.json'
+      ];
+      assert(transitiveDependencies.isEmpty);
+    } else {
+      Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
+      sources = module.sources
+          .map((relativeUri) =>
+              _sourceToImportUri(module, rootScheme, relativeUri))
+          .toList();
+      extraArgs = [
+        '--dart-sdk-summary',
+        '${toUri(sdkModule, dillId)}',
+        '--packages',
+        '.packages',
+      ];
+    }
+
+    Uri output = toUri(module, jsId);
+
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      _dartdevcScript,
+      '--kernel',
+      '--summarize-text',
+      '--modules=es6',
+      '--no-summarize',
+      '--no-source-map',
+      '--multi-root-scheme',
+      rootScheme,
+      ...sources,
+      ...extraArgs,
+      for (String flag in flags) '--enable-experiment=$flag',
+      ...(transitiveDependencies
+          .where((m) => !m.isSdk)
+          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+      '-o',
+      '$output',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: ddk on $module");
+  }
+}
+
+class RunD8 implements IOModularStep {
+  @override
+  List<DataId> get resultData => const [txtId];
+
+  @override
+  bool get needsSources => false;
+
+  @override
+  List<DataId> get dependencyDataNeeded => const [jsId];
+
+  @override
+  List<DataId> get moduleDataNeeded => const [jsId];
+
+  @override
+  bool get onlyOnMain => true;
+
+  @override
+  Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+      List<String> flags) async {
+    if (_options.verbose) print("\nstep: d8 on $module");
+
+    // Rename sdk.js to dart_sdk.js (the alternative, but more hermetic solution
+    // would be to rename the import on all other .js files, but seems
+    // overkill/unnecessary.
+    if (await File.fromUri(root.resolve('dart_sdk.js')).exists()) {
+      throw 'error: dart_sdk.js already exists.';
+    }
+
+    await File.fromUri(root.resolve('sdk.js'))
+        .copy(root.resolve('dart_sdk.js').toFilePath());
+    var runjs = '''
+    import { dart, _isolate_helper } from 'dart_sdk.js';
+    import { main } from 'main.js';
+    _isolate_helper.startRootIsolate(() => {}, []);
+    main.main();
+    ''';
+
+    var wrapper =
+        root.resolveUri(toUri(module, jsId)).toFilePath() + ".wrapper.js";
+    await File(wrapper).writeAsString(runjs);
+    List<String> d8Args = ['--module', wrapper];
+    var result = await _runProcess(
+        sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+    _checkExitCode(result, this, module);
+
+    await File.fromUri(root.resolveUri(toUri(module, txtId)))
+        .writeAsString(result.stdout as String);
+  }
+
+  @override
+  void notifyCached(Module module) {
+    if (_options.verbose) print("\ncached step: d8 on $module");
+  }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+  if (result.exitCode != 0 || _options.verbose) {
+    stdout.write(result.stdout);
+    stderr.write(result.stderr);
+  }
+  if (result.exitCode != 0) {
+    throw "${step.runtimeType} failed on $module:\n\n"
+        "stdout:\n${result.stdout}\n\n"
+        "stderr:\n${result.stderr}";
+  }
+}
+
+Future<ProcessResult> _runProcess(
+    String command, List<String> arguments, String workingDirectory) {
+  if (_options.verbose) {
+    print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+  }
+  return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+  if (Platform.isWindows) {
+    return 'third_party/d8/windows/d8.exe';
+  } else if (Platform.isLinux) {
+    return 'third_party/d8/linux/d8';
+  } else if (Platform.isMacOS) {
+    return 'third_party/d8/macos/d8';
+  }
+  throw UnsupportedError('Unsupported platform.');
+}
+
+Future<void> _createPackagesFile(
+    Module module, Uri root, Set<Module> transitiveDependencies) async {
+  // We create a .packages file which defines the location of this module if
+  // it is a package.  The CFE requires that if a `package:` URI of a
+  // dependency is used in an import, then we need that package entry in the
+  // .packages file. However, after it checks that the definition exists, the
+  // CFE will not actually use the resolved URI if a library for the import
+  // URI is already found in one of the provided .dill files of the
+  // dependencies. For that reason, and to ensure that a step only has access
+  // to the files provided in a module, we generate a .packages with invalid
+  // folders for other packages.
+  // TODO(sigmund): follow up with the CFE to see if we can remove the need
+  // for the .packages entry altogether if they won't need to read the
+  // sources.
+  var packagesContents = StringBuffer();
+  if (module.isPackage) {
+    packagesContents.write('${module.name}:${module.packageBase}\n');
+  }
+  for (Module dependency in transitiveDependencies) {
+    if (dependency.isPackage) {
+      packagesContents.write('${dependency.name}:unused\n');
+    }
+  }
+
+  await File.fromUri(root.resolve('.packages'))
+      .writeAsString('$packagesContents');
+}
+
+String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
+  if (module.isPackage) {
+    var basePath = module.packageBase.path;
+    var packageRelativePath = basePath == "./"
+        ? relativeUri.path
+        : relativeUri.path.substring(basePath.length);
+    return 'package:${module.name}/$packageRelativePath';
+  } else {
+    return '$rootScheme:/$relativeUri';
+  }
+}
+
+Future<void> _resolveScripts() async {
+  Future<String> resolve(
+      String sdkSourcePath, String relativeSnapshotPath) async {
+    String result = sdkRoot.resolve(sdkSourcePath).toFilePath();
+    if (_options.useSdk) {
+      String snapshot = Uri.file(Platform.resolvedExecutable)
+          .resolve(relativeSnapshotPath)
+          .toFilePath();
+      if (await File(snapshot).exists()) {
+        return snapshot;
+      }
+    }
+    return result;
+  }
+
+  _dartdevcScript = await resolve(
+      'pkg/dev_compiler/bin/dartdevc.dart', 'snapshots/dartdevc.dart.snapshot');
+  _kernelWorkerScript = await resolve('utils/bazel/kernel_worker.dart',
+      'snapshots/kernel_worker.dart.snapshot');
+}
diff --git a/pkg/dev_compiler/test/sourcemap/common.dart b/pkg/dev_compiler/test/sourcemap/common.dart
index b8890ba..c5c7ff5 100644
--- a/pkg/dev_compiler/test/sourcemap/common.dart
+++ b/pkg/dev_compiler/test/sourcemap/common.dart
@@ -6,8 +6,8 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:path/path.dart' as p;
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 import 'package:sourcemap_testing/src/stepping_helper.dart';
 import 'package:testing/testing.dart';
 
diff --git a/pkg/dev_compiler/test/sourcemap/ddc_common.dart b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
index c96ca2d..00330de 100644
--- a/pkg/dev_compiler/test/sourcemap/ddc_common.dart
+++ b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
@@ -7,8 +7,8 @@
 import 'dart:io';
 import 'dart:mirrors' show currentMirrorSystem;
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:front_end/src/api_unstable/ddc.dart' as fe;
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 import 'package:path/path.dart' as p;
 import 'package:sourcemap_testing/src/stacktrace_helper.dart';
 import 'package:sourcemap_testing/src/stepping_helper.dart';
diff --git a/pkg/dev_compiler/tool/build_pkgs.dart b/pkg/dev_compiler/tool/build_pkgs.dart
index 5e8fc50..5152573 100755
--- a/pkg/dev_compiler/tool/build_pkgs.dart
+++ b/pkg/dev_compiler/tool/build_pkgs.dart
@@ -23,6 +23,13 @@
 /// packages will be placed in a "pkg" subdirectory of this.
 String outputDirectory;
 
+/// List of language experiments to enable when building.
+List<String> experiments;
+
+/// Whether to force the analyzer backend to generate code even if there are
+/// errors.
+bool unsafeForceCompile;
+
 /// Compiles the packages that the DDC tests use to JS into the given output
 /// directory.
 ///
@@ -46,6 +53,10 @@
       abbr: "o", help: "Directory to write output to.");
   argParser.addFlag("travis",
       help: "Build the additional packages tested on Travis.");
+  argParser.addMultiOption("enable-experiment",
+      help: "Enable experimental language features.");
+  argParser.addFlag("unsafe-force-compile",
+      help: "Generate output even if compile errors are reported.");
 
   ArgResults argResults;
   try {
@@ -63,6 +74,8 @@
   analyzerSummary = argResults["analyzer-sdk"] as String;
   kernelSummary = argResults["kernel-sdk"] as String;
   outputDirectory = argResults["output"] as String;
+  experiments = argResults["enable-experiment"] as List<String>;
+  unsafeForceCompile = argResults["unsafe-force-compile"] as bool;
 
   // Build leaf packages. These have no other package dependencies.
 
@@ -126,21 +139,18 @@
   makeArgs({bool kernel = false}) {
     var pkgDirectory = p.join(outputDirectory, kernel ? 'pkg_kernel' : 'pkg');
     Directory(pkgDirectory).createSync(recursive: true);
-    var args = <String>[];
-    if (kernel) args.add('-k');
 
-    args.addAll([
+    return [
+      if (kernel) '-k',
+      if (experiments.isNotEmpty)
+        '--enable-experiment=${experiments.join(",")}',
+      if (unsafeForceCompile && !kernel) '--unsafe-force-compile',
       '--dart-sdk-summary=${kernel ? kernelSummary : analyzerSummary}',
       '-o${pkgDirectory}/$module.js',
-      'package:$module/$module.dart'
-    ]);
-    for (var lib in libs) {
-      args.add('package:$module/$lib.dart');
-    }
-    for (var dep in deps) {
-      args.add('-s${pkgDirectory}/$dep.${kernel ? "dill" : "sum"}');
-    }
-    return args;
+      'package:$module/$module.dart',
+      for (var lib in libs) 'package:$module/$lib.dart',
+      for (var dep in deps) '-s${pkgDirectory}/$dep.${kernel ? "dill" : "sum"}',
+    ];
   }
 
   if (analyzerSummary != null) {
diff --git a/pkg/dev_compiler/tool/ddc b/pkg/dev_compiler/tool/ddc
index 493f531..4fff33d 100755
--- a/pkg/dev_compiler/tool/ddc
+++ b/pkg/dev_compiler/tool/ddc
@@ -30,8 +30,7 @@
   DIRS=$( ls "$OUT_DIR" )
   # list of possible configurations in decreasing desirability
   CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
+    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64")
   DART_CONFIGURATION="None"
   for CONFIG in ${CONFIGS[*]}
   do
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index db3ca57..493dc1b 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -9,6 +9,8 @@
 import 'dart:io';
 import 'dart:math' as math;
 
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -35,8 +37,16 @@
   }
 
   var sdk = 'sdk';
+  var useNnbd = false;
   if (argv.length > 3) {
     sdk = argv[3];
+
+    // TODO(38701): While the core libraries have been forked for NNBD, use the
+    // SDK directory name to determine whether to enable the NNBD experiment
+    // when parsing the lib sources. Once the libraries have been unforked, we
+    // should unconditionally enable the experiment flag since then the
+    // canonical SDK libs will use NNBD syntax.
+    useNnbd = sdk.contains("nnbd");
   }
 
   var selfModifyTime = File(self).lastModifiedSync().millisecondsSinceEpoch;
@@ -63,7 +73,7 @@
       File(p.join(repoDir, 'tools', 'VERSION')).readAsStringSync());
 
   // Parse libraries.dart
-  var sdkLibraries = _getSdkLibraries(libContents);
+  var sdkLibraries = _getSdkLibraries(libContents, useNnbd: useNnbd);
 
   // Enumerate core libraries and apply patches
   for (SdkLibrary library in sdkLibraries) {
@@ -91,7 +101,8 @@
       int inputModifyTime = math.max(selfModifyTime,
           libraryFile.lastModifiedSync().millisecondsSinceEpoch);
       var partFiles = <File>[];
-      for (var part in parseString(content: libraryContents).unit.directives) {
+      for (var part
+          in _parseString(libraryContents, useNnbd: useNnbd).unit.directives) {
         if (part is PartDirective) {
           var partPath = part.uri.stringValue;
           outPaths.add(p.join(p.dirname(libraryOut), partPath));
@@ -136,7 +147,7 @@
         contents.addAll(partFiles.map((f) => f.readAsStringSync()));
         if (patchExists) {
           var patchContents = patchFile.readAsStringSync();
-          contents = _patchLibrary(contents, patchContents);
+          contents = _patchLibrary(contents, patchContents, useNnbd: useNnbd);
         }
 
         if (contents != null) {
@@ -178,18 +189,19 @@
 /// in the Dart language. Since this feature is only for the convenience of
 /// writing the dart:* libraries, and not a tool given to Dart developers, it
 /// seems like a non-ideal situation. Instead we keep the preprocessing simple.
-List<String> _patchLibrary(List<String> partsContents, String patchContents) {
+List<String> _patchLibrary(List<String> partsContents, String patchContents,
+    {bool useNnbd = false}) {
   var results = <StringEditBuffer>[];
 
   // Parse the patch first. We'll need to extract bits of this as we go through
   // the other files.
-  var patchFinder = PatchFinder.parseAndVisit(patchContents);
+  var patchFinder = PatchFinder.parseAndVisit(patchContents, useNnbd: useNnbd);
 
   // Merge `external` declarations with the corresponding `@patch` code.
   bool failed = false;
   for (var partContent in partsContents) {
     var partEdits = StringEditBuffer(partContent);
-    var partUnit = parseString(content: partContent).unit;
+    var partUnit = _parseString(partContent, useNnbd: useNnbd).unit;
     var patcher = PatchApplier(partEdits, patchFinder);
     partUnit.accept(patcher);
     if (!failed) failed = patcher.patchWasMissing;
@@ -314,9 +326,9 @@
   final mergeMembers = <String, List<ClassMember>>{};
   final mergeDeclarations = <CompilationUnitMember>[];
 
-  PatchFinder.parseAndVisit(String contents)
+  PatchFinder.parseAndVisit(String contents, {bool useNnbd})
       : contents = contents,
-        unit = parseString(content: contents).unit {
+        unit = _parseString(contents, useNnbd: useNnbd).unit {
     visitCompilationUnit(unit);
   }
 
@@ -478,11 +490,16 @@
   }
 }
 
-List<SdkLibrary> _getSdkLibraries(String contents) {
+List<SdkLibrary> _getSdkLibraries(String contents, {bool useNnbd}) {
   // TODO(jmesserly): fix SdkLibrariesReader_LibraryBuilder in Analyzer.
   // It doesn't understand optional new/const in Dart 2. For now, we keep
   // redundant `const` in tool/input_sdk/libraries.dart as a workaround.
   var libraryBuilder = SdkLibrariesReader_LibraryBuilder();
-  parseString(content: contents).unit.accept(libraryBuilder);
+  _parseString(contents, useNnbd: useNnbd).unit.accept(libraryBuilder);
   return libraryBuilder.librariesMap.sdkLibraries;
 }
+
+ParseStringResult _parseString(String source, {bool useNnbd}) {
+  var features = FeatureSet.fromEnableFlags([if (useNnbd) "non-nullable"]);
+  return parseString(content: source, featureSet: features);
+}
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 9d1d5ea..18f3e8f 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -629,7 +629,7 @@
   static void notType<T>(dynamic object, [String reason = ""]) {
     if (object is! T) return;
     String msg = _getMessage(reason);
-    _fail("Expect.type($object is! $T$msg) fails"
+    _fail("Expect.type($object is! $T$msg) fails "
         "on ${Error.safeToString(object)}");
   }
 
diff --git a/pkg/front_end/analysis_options_no_lints.yaml b/pkg/front_end/analysis_options_no_lints.yaml
index b2e05b8..c24332a 100644
--- a/pkg/front_end/analysis_options_no_lints.yaml
+++ b/pkg/front_end/analysis_options_no_lints.yaml
@@ -6,10 +6,6 @@
   exclude:
     - test/analyser_ignored/**
     - test/extensions/data/**
-    - test/flow_analysis/definite_assignment/data/**
-    - test/flow_analysis/nullability/data/**
-    - test/flow_analysis/reachability/data/**
-    - test/flow_analysis/type_promotion/data/**
     - parser_testcases/**
     - testcases/**
     - test/id_testing/data/**
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 60ea195..441ccc1 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -4,12 +4,13 @@
 
 library front_end.compiler_options;
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessageHandler;
+
 import 'package:kernel/ast.dart' as kernel show Library;
 
 import 'package:kernel/target/targets.dart' show Target;
 
-import 'diagnostic_message.dart' show DiagnosticMessageHandler;
-
 import 'experimental_flags.dart'
     show
         defaultExperimentalFlags,
@@ -21,7 +22,8 @@
 
 import 'standard_file_system.dart' show StandardFileSystem;
 
-export 'diagnostic_message.dart' show DiagnosticMessage;
+export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage;
 
 /// Front-end options relevant to compiler back ends.
 ///
diff --git a/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart b/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart
deleted file mode 100644
index 47c30f0..0000000
--- a/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart
+++ /dev/null
@@ -1,81 +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.
-
-library front_end.diagnostic_message;
-
-import '../fasta/fasta_codes.dart'
-    show Code, DiagnosticMessageFromJson, FormattedMessage;
-
-import '../fasta/severity.dart' show Severity;
-
-/// The type of a diagnostic message callback. For example:
-///
-///    void handler(DiagnosticMessage message) {
-///      if (enableTerminalColors) { // See [terminal_color_support.dart].
-///        message.ansiFormatted.forEach(stderr.writeln);
-///      } else {
-///        message.plainTextFormatted.forEach(stderr.writeln);
-///      }
-///    }
-typedef DiagnosticMessageHandler = void Function(DiagnosticMessage);
-
-/// Represents a diagnostic message that can be reported from a tool, for
-/// example, a compiler.
-///
-/// The word *diagnostic* is used loosely here, as a tool may also use this for
-/// reporting any kind of message, including non-diagnostic messages such as
-/// licensing, informal, or logging information. This allows a well-behaved
-/// tool to never directly write to stdout or stderr.
-abstract class DiagnosticMessage {
-  DiagnosticMessage._(); // Prevent subclassing.
-
-  Iterable<String> get ansiFormatted;
-
-  Iterable<String> get plainTextFormatted;
-
-  Severity get severity;
-}
-
-/// This method is subject to change.
-Uri getMessageUri(DiagnosticMessage message) {
-  return message is FormattedMessage
-      ? message.uri
-      : message is DiagnosticMessageFromJson ? message.uri : null;
-}
-
-/// This method is subject to change.
-int getMessageCharOffset(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.charOffset : null;
-}
-
-/// This method is subject to change.
-int getMessageLength(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.length : null;
-}
-
-/// This method is subject to change.
-Code getMessageCodeObject(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.code : null;
-}
-
-/// This method is subject to change.
-String getMessageHeaderText(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.message : null;
-}
-
-/// This method is subject to change.
-int getMessageCode(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.code.index : -1;
-}
-
-/// This method is subject to change.
-Map<String, dynamic> getMessageArguments(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.arguments : null;
-}
-
-/// This method is subject to change.
-Iterable<DiagnosticMessage> getMessageRelatedInformation(
-    DiagnosticMessage message) {
-  return message is FormattedMessage ? message.relatedInformation : null;
-}
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 26b7a35..2f5193b 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
@@ -4,6 +4,9 @@
 
 import 'dart:async' show Future;
 
+import 'package:_fe_analyzer_shared/src/scanner/string_scanner.dart'
+    show StringScanner;
+
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -19,8 +22,6 @@
 
 import '../fasta/incremental_serializer.dart' show IncrementalSerializer;
 
-import '../fasta/scanner/string_scanner.dart' show StringScanner;
-
 import 'compiler_options.dart' show CompilerOptions;
 
 export '../fasta/incremental_serializer.dart' show IncrementalSerializer;
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 7c5e1b5..ebb705a 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
@@ -7,6 +7,11 @@
 
 import 'dart:async' show Future;
 
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    show messageMissingMain, noLength;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart' show Component;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -17,10 +22,6 @@
 
 import '../fasta/compiler_context.dart' show CompilerContext;
 
-import '../fasta/fasta_codes.dart' show messageMissingMain, noLength;
-
-import '../fasta/severity.dart' show Severity;
-
 import '../kernel_generator_impl.dart'
     show generateKernel, generateKernelInternal;
 
@@ -53,7 +54,7 @@
 
 Future<CompilerResult> kernelForProgramInternal(
     Uri source, CompilerOptions options,
-    {bool retainDataForTesting: false}) async {
+    {bool retainDataForTesting: false, bool requireMain: true}) async {
   ProcessedOptions pOptions =
       new ProcessedOptions(options: options, inputs: [source]);
   return await CompilerContext.runWithOptions(pOptions, (context) async {
@@ -63,7 +64,7 @@
     Component component = result?.component;
     if (component == null) return null;
 
-    if (component.mainMethod == null) {
+    if (requireMain && component.mainMethod == null) {
       context.options.report(
           messageMissingMain.withLocation(source, -1, noLength),
           Severity.error);
diff --git a/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart b/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
index 17dcc08..ab69e10 100644
--- a/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
+++ b/pkg/front_end/lib/src/api_prototype/terminal_color_support.dart
@@ -8,9 +8,11 @@
 
 import 'dart:io' show Platform, Process, ProcessResult, stderr, stdout;
 
-import '../fasta/colors.dart' show ALL_CODES, TERMINAL_CAPABILITIES;
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage;
 
-import 'diagnostic_message.dart' show DiagnosticMessage;
+import 'package:_fe_analyzer_shared/src/util/colors.dart'
+    show ALL_CODES, TERMINAL_CAPABILITIES;
 
 /// True if we should enable colors in output.
 ///
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 57080d9..2e14914 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -7,6 +7,9 @@
 
 import 'dart:async' show Future;
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessageHandler;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 
 import 'package:kernel/kernel.dart' show Component, Library;
@@ -16,8 +19,6 @@
 import '../api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags;
 
-import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
-
 import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
 import '../api_prototype/file_system.dart' show FileSystem;
@@ -33,11 +34,14 @@
 import 'modular_incremental_compilation.dart' as modular
     show initializeIncrementalCompiler;
 
+export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage;
+
+export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 export '../api_prototype/compiler_options.dart'
     show parseExperimentalFlags, parseExperimentalArguments;
 
-export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
-
 export '../api_prototype/experimental_flags.dart'
     show ExperimentalFlag, parseExperimentalFlag;
 
@@ -48,8 +52,6 @@
 
 export '../fasta/kernel/utils.dart' show serializeComponent;
 
-export '../fasta/severity.dart' show Severity;
-
 export 'compiler_state.dart' show InitializedCompilerState;
 
 /// Initializes the compiler for a modular build.
@@ -68,6 +70,7 @@
     FileSystem fileSystem,
     Iterable<String> experiments,
     bool outlineOnly,
+    Map<String, String> environmentDefines,
     {bool trackNeededDillLibraries: false}) async {
   List<Component> outputLoadedInputSummaries =
       new List<Component>(summaryInputs.length);
@@ -88,7 +91,8 @@
       experimentalFlags: experimentalFlags,
       outlineOnly: outlineOnly,
       omitPlatform: true,
-      trackNeededDillLibraries: trackNeededDillLibraries);
+      trackNeededDillLibraries: trackNeededDillLibraries,
+      environmentDefines: environmentDefines);
 }
 
 Future<InitializedCompilerState> initializeCompiler(
@@ -100,7 +104,8 @@
     List<Uri> linkedInputs,
     Target target,
     FileSystem fileSystem,
-    Iterable<String> experiments) async {
+    Iterable<String> experiments,
+    Map<String, String> environmentDefines) async {
   // TODO(sigmund): use incremental compiler when it supports our use case.
   // Note: it is common for the summary worker to invoke the compiler with the
   // same input summary URIs, but with different contents, so we'd need to be
@@ -114,7 +119,7 @@
     ..linkedDependencies = linkedInputs
     ..target = target
     ..fileSystem = fileSystem
-    ..environmentDefines = const {}
+    ..environmentDefines = environmentDefines
     ..experimentalFlags = parseExperimentalFlags(
         parseExperimentalArguments(experiments),
         onError: (e) => throw e);
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index fd6e8f0..668533014 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -4,6 +4,17 @@
 
 import 'dart:async' show Future;
 
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    show messageMissingMain;
+
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessageHandler;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show ErrorToken, StringToken, Token;
+
 import 'package:kernel/kernel.dart' show Component, Statement;
 
 import 'package:kernel/ast.dart' as ir;
@@ -12,8 +23,6 @@
 
 import '../api_prototype/compiler_options.dart' show CompilerOptions;
 
-import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
-
 import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
 import '../api_prototype/file_system.dart' show FileSystem;
@@ -26,24 +35,18 @@
 
 import '../fasta/compiler_context.dart' show CompilerContext;
 
-import '../fasta/fasta_codes.dart' show messageMissingMain;
-
-import '../fasta/severity.dart' show Severity;
-
 import '../kernel_generator_impl.dart' show generateKernelInternal;
 
-import '../fasta/scanner.dart' show ErrorToken, StringToken, Token;
-
 import '../fasta/kernel/redirecting_factory_body.dart' as redirecting;
 
 import 'compiler_state.dart' show InitializedCompilerState;
 
 import 'util.dart' show equalLists, equalMaps;
 
-export '../api_prototype/compiler_options.dart'
-    show CompilerOptions, parseExperimentalFlags, parseExperimentalArguments;
+export 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    show LocatedMessage;
 
-export '../api_prototype/diagnostic_message.dart'
+export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show
         DiagnosticMessage,
         getMessageCharOffset,
@@ -52,28 +55,15 @@
         getMessageRelatedInformation,
         getMessageUri;
 
-export '../api_prototype/experimental_flags.dart'
-    show defaultExperimentalFlags, ExperimentalFlag;
+export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
-export '../api_prototype/file_system.dart'
-    show FileSystem, FileSystemEntity, FileSystemException;
+export 'package:_fe_analyzer_shared/src/parser/async_modifier.dart'
+    show AsyncModifier;
 
-export '../api_prototype/kernel_generator.dart' show kernelForProgram;
+export 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show isUserDefinableOperator, isMinusOperator;
 
-export '../api_prototype/standard_file_system.dart' show DataFileSystemEntity;
-
-export '../compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-
-export '../fasta/fasta_codes.dart' show LocatedMessage;
-
-export '../fasta/operator.dart' show operatorFromString;
-
-export '../fasta/parser/async_modifier.dart' show AsyncModifier;
-
-export '../fasta/scanner.dart' show isUserDefinableOperator, isMinusOperator;
-
-export '../fasta/scanner/characters.dart'
+export 'package:_fe_analyzer_shared/src/scanner/characters.dart'
     show
         $$,
         $0,
@@ -95,13 +85,31 @@
         $s,
         $z;
 
-export '../fasta/severity.dart' show Severity;
+export 'package:_fe_analyzer_shared/src/util/link.dart' show Link, LinkBuilder;
 
-export '../fasta/util/link.dart' show Link, LinkBuilder;
+export 'package:_fe_analyzer_shared/src/util/link_implementation.dart'
+    show LinkEntry;
 
-export '../fasta/util/link_implementation.dart' show LinkEntry;
+export 'package:_fe_analyzer_shared/src/util/relativize.dart'
+    show relativizeUri;
 
-export '../fasta/util/relativize.dart' show relativizeUri;
+export '../api_prototype/compiler_options.dart'
+    show CompilerOptions, parseExperimentalFlags, parseExperimentalArguments;
+
+export '../api_prototype/experimental_flags.dart'
+    show defaultExperimentalFlags, ExperimentalFlag;
+
+export '../api_prototype/file_system.dart'
+    show FileSystem, FileSystemEntity, FileSystemException;
+
+export '../api_prototype/kernel_generator.dart' show kernelForProgram;
+
+export '../api_prototype/standard_file_system.dart' show DataFileSystemEntity;
+
+export '../compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+export '../fasta/operator.dart' show operatorFromString;
 
 export 'compiler_state.dart' show InitializedCompilerState;
 
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 0a5122b..9560262 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -4,6 +4,9 @@
 
 import 'dart:async' show Future;
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessageHandler;
+
 import 'package:kernel/class_hierarchy.dart';
 
 import 'package:kernel/kernel.dart' show Component;
@@ -12,8 +15,6 @@
 
 import '../api_prototype/compiler_options.dart' show CompilerOptions;
 
-import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
-
 import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
 import '../api_prototype/file_system.dart' show FileSystem;
@@ -33,11 +34,14 @@
 
 import 'util.dart' show equalLists, equalMaps;
 
+export 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage;
+
+export 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 export '../api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags, parseExperimentalArguments;
 
-export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
-
 export '../api_prototype/experimental_flags.dart'
     show ExperimentalFlag, parseExperimentalFlag;
 
@@ -59,8 +63,6 @@
 export '../fasta/kernel/redirecting_factory_body.dart'
     show RedirectingFactoryBody;
 
-export '../fasta/severity.dart' show Severity;
-
 export '../fasta/type_inference/type_schema_environment.dart'
     show TypeSchemaEnvironment;
 
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 5244f74..d7a4797 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
@@ -54,190 +54,216 @@
     bool outlineOnly,
     bool omitPlatform: false,
     bool trackNeededDillLibraries: false}) async {
-  final List<int> sdkDigest = workerInputDigests[sdkSummary];
-  if (sdkDigest == null) {
-    throw new StateError("Expected to get digest for $sdkSummary");
-  }
-
-  Map<Uri, WorkerInputComponent> workerInputCache =
-      oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
-  Map<Uri, Uri> workerInputCacheLibs =
-      oldState?.workerInputCacheLibs ?? new Map<Uri, Uri>();
-
-  WorkerInputComponent cachedSdkInput = workerInputCache[sdkSummary];
-
-  IncrementalCompiler incrementalCompiler;
-  CompilerOptions options;
-  ProcessedOptions processedOpts;
-
-  if (oldState == null ||
-      oldState.incrementalCompiler == null ||
-      oldState.options.compileSdk != compileSdk ||
-      oldState.incrementalCompiler.outlineOnly != outlineOnly ||
-      !equalMaps(oldState.options.experimentalFlags, experimentalFlags) ||
-      !equalMaps(oldState.options.environmentDefines, environmentDefines) ||
-      !equalSets(oldState.tags, tags) ||
-      cachedSdkInput == null ||
-      !digestsEqual(cachedSdkInput.digest, sdkDigest)) {
-    // No - or immediately not correct - previous state.
-    // We'll load a new sdk, anything loaded already will have a wrong root.
-    workerInputCache.clear();
-    workerInputCacheLibs.clear();
-
-    // The sdk was either not cached or it has changed.
-    options = new CompilerOptions()
-      ..compileSdk = compileSdk
-      ..sdkRoot = sdkRoot
-      ..sdkSummary = sdkSummary
-      ..packagesFileUri = packagesFile
-      ..librariesSpecificationUri = librariesSpecificationUri
-      ..target = target
-      ..fileSystem = fileSystem
-      ..omitPlatform = omitPlatform
-      ..environmentDefines = environmentDefines
-      ..experimentalFlags = experimentalFlags;
-
-    processedOpts = new ProcessedOptions(options: options);
-    cachedSdkInput = new WorkerInputComponent(
-        sdkDigest, await processedOpts.loadSdkSummary(null));
-    workerInputCache[sdkSummary] = cachedSdkInput;
-    for (Library lib in cachedSdkInput.component.libraries) {
-      if (workerInputCacheLibs.containsKey(lib.importUri)) {
-        throw new StateError("Duplicate sources in sdk.");
+  bool isRetry = false;
+  while (true) {
+    try {
+      final List<int> sdkDigest = workerInputDigests[sdkSummary];
+      if (sdkDigest == null) {
+        throw new StateError("Expected to get digest for $sdkSummary");
       }
-      workerInputCacheLibs[lib.importUri] = sdkSummary;
-    }
 
-    incrementalCompiler = new IncrementalCompiler.fromComponent(
-        new CompilerContext(processedOpts),
-        cachedSdkInput.component,
-        outlineOnly);
-    incrementalCompiler.trackNeededDillLibraries = trackNeededDillLibraries;
-  } else {
-    options = oldState.options;
-    processedOpts = oldState.processedOpts;
-    Component sdkComponent = cachedSdkInput.component;
-    // Reset the state of the component.
-    for (Library lib in sdkComponent.libraries) {
-      lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
-    }
+      Map<Uri, WorkerInputComponent> workerInputCache =
+          oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
+      Map<Uri, Uri> workerInputCacheLibs =
+          oldState?.workerInputCacheLibs ?? new Map<Uri, Uri>();
 
-    // Make sure the canonical name root knows about the sdk - otherwise we
-    // won't be able to link to it when loading more outlines.
-    sdkComponent.adoptChildren();
+      WorkerInputComponent cachedSdkInput = workerInputCache[sdkSummary];
 
-    // TODO(jensj): This is - at least currently - necessary,
-    // although it's not entirely obvious why.
-    // It likely has to do with several outlines containing the same libraries.
-    // Once that stops (and we check for it) we can probably remove this,
-    // and instead only do it when about to reuse an outline in the
-    // 'inputSummaries.add(component);' line further down.
-    for (WorkerInputComponent cachedInput in workerInputCache.values) {
-      cachedInput.component.adoptChildren();
-    }
+      IncrementalCompiler incrementalCompiler;
+      CompilerOptions options;
+      ProcessedOptions processedOpts;
 
-    // Reuse the incremental compiler, but reset as needed.
-    incrementalCompiler = oldState.incrementalCompiler;
-    incrementalCompiler.invalidateAllSources();
-    incrementalCompiler.trackNeededDillLibraries = trackNeededDillLibraries;
-    options.packagesFileUri = packagesFile;
-    options.fileSystem = fileSystem;
-    processedOpts.clearFileSystemCache();
-  }
+      if (oldState == null ||
+          oldState.incrementalCompiler == null ||
+          oldState.options.compileSdk != compileSdk ||
+          oldState.incrementalCompiler.outlineOnly != outlineOnly ||
+          !equalMaps(oldState.options.experimentalFlags, experimentalFlags) ||
+          !equalMaps(oldState.options.environmentDefines, environmentDefines) ||
+          !equalSets(oldState.tags, tags) ||
+          cachedSdkInput == null ||
+          !digestsEqual(cachedSdkInput.digest, sdkDigest)) {
+        // No - or immediately not correct - previous state.
+        // We'll load a new sdk, anything loaded already will have a wrong root.
+        workerInputCache.clear();
+        workerInputCacheLibs.clear();
 
-  // Then read all the input summary components.
-  CanonicalName nameRoot = cachedSdkInput.component.root;
-  Map<Uri, Uri> libraryToInputDill;
-  if (trackNeededDillLibraries) {
-    libraryToInputDill = new Map<Uri, Uri>();
-  }
-  List<int> loadFromDillIndexes = new List<int>();
+        // The sdk was either not cached or it has changed.
+        options = new CompilerOptions()
+          ..compileSdk = compileSdk
+          ..sdkRoot = sdkRoot
+          ..sdkSummary = sdkSummary
+          ..packagesFileUri = packagesFile
+          ..librariesSpecificationUri = librariesSpecificationUri
+          ..target = target
+          ..fileSystem = fileSystem
+          ..omitPlatform = omitPlatform
+          ..environmentDefines = environmentDefines
+          ..experimentalFlags = experimentalFlags;
 
-  // Notice that the ordering of the input summaries matter, so we need to
-  // keep them in order.
-  if (outputLoadedInputSummaries.length != inputSummaries.length) {
-    throw new ArgumentError("Invalid length.");
-  }
-  Set<Uri> inputSummariesSet = new Set<Uri>();
-  for (int i = 0; i < inputSummaries.length; i++) {
-    Uri summaryUri = inputSummaries[i];
-    inputSummariesSet.add(summaryUri);
-    WorkerInputComponent cachedInput = workerInputCache[summaryUri];
-    List<int> digest = workerInputDigests[summaryUri];
-    if (digest == null) {
-      throw new StateError("Expected to get digest for $summaryUri");
-    }
-    if (cachedInput == null ||
-        cachedInput.component.root != nameRoot ||
-        !digestsEqual(digest, cachedInput.digest)) {
-      // Remove any old libraries from workerInputCacheLibs.
-      Component component = cachedInput?.component;
-      if (component != null) {
-        for (Library lib in component.libraries) {
-          workerInputCacheLibs.remove(lib.importUri);
+        processedOpts = new ProcessedOptions(options: options);
+        cachedSdkInput = new WorkerInputComponent(
+            sdkDigest, await processedOpts.loadSdkSummary(null));
+        workerInputCache[sdkSummary] = cachedSdkInput;
+        for (Library lib in cachedSdkInput.component.libraries) {
+          if (workerInputCacheLibs.containsKey(lib.importUri)) {
+            throw new StateError("Duplicate sources in sdk.");
+          }
+          workerInputCacheLibs[lib.importUri] = sdkSummary;
         }
-      }
 
-      loadFromDillIndexes.add(i);
-    } else {
-      // Need to reset cached components so they are usable again.
-      Component component = cachedInput.component;
-      for (Library lib in component.libraries) {
-        lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
-        if (trackNeededDillLibraries) {
-          libraryToInputDill[lib.importUri] = summaryUri;
+        incrementalCompiler = new IncrementalCompiler.fromComponent(
+            new CompilerContext(processedOpts),
+            cachedSdkInput.component,
+            outlineOnly);
+        incrementalCompiler.trackNeededDillLibraries = trackNeededDillLibraries;
+      } else {
+        options = oldState.options;
+        processedOpts = oldState.processedOpts;
+        Component sdkComponent = cachedSdkInput.component;
+        // Reset the state of the component.
+        for (Library lib in sdkComponent.libraries) {
+          lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
         }
+
+        // Make sure the canonical name root knows about the sdk - otherwise we
+        // won't be able to link to it when loading more outlines.
+        sdkComponent.adoptChildren();
+
+        // TODO(jensj): This is - at least currently - necessary,
+        // although it's not entirely obvious why.
+        // It likely has to do with several outlines containing the same
+        // libraries. Once that stops (and we check for it) we can probably
+        // remove this, and instead only do it when about to reuse an outline
+        // in the 'inputSummaries.add(component);' line further down.
+        for (WorkerInputComponent cachedInput in workerInputCache.values) {
+          cachedInput.component.adoptChildren();
+        }
+
+        // Reuse the incremental compiler, but reset as needed.
+        incrementalCompiler = oldState.incrementalCompiler;
+        incrementalCompiler.invalidateAllSources();
+        incrementalCompiler.trackNeededDillLibraries = trackNeededDillLibraries;
+        options.packagesFileUri = packagesFile;
+        options.fileSystem = fileSystem;
+        processedOpts.clearFileSystemCache();
       }
-      component.computeCanonicalNames(); // this isn't needed, is it?
-      outputLoadedInputSummaries[i] = component;
-    }
-  }
 
-  for (int i = 0; i < loadFromDillIndexes.length; i++) {
-    int index = loadFromDillIndexes[i];
-    Uri summaryUri = inputSummaries[index];
-    List<int> digest = workerInputDigests[summaryUri];
-    if (digest == null) {
-      throw new StateError("Expected to get digest for $summaryUri");
-    }
+      // Then read all the input summary components.
+      CanonicalName nameRoot = cachedSdkInput.component.root;
+      Map<Uri, Uri> libraryToInputDill;
+      if (trackNeededDillLibraries) {
+        libraryToInputDill = new Map<Uri, Uri>();
+      }
+      List<int> loadFromDillIndexes = new List<int>();
 
-    List<int> bytes = await fileSystem.entityForUri(summaryUri).readAsBytes();
-    WorkerInputComponent cachedInput = new WorkerInputComponent(
-        digest,
-        await processedOpts.loadComponent(bytes, nameRoot,
-            alwaysCreateNewNamedNodes: true));
-    workerInputCache[summaryUri] = cachedInput;
-    outputLoadedInputSummaries[index] = cachedInput.component;
-    for (Library lib in cachedInput.component.libraries) {
-      if (workerInputCacheLibs.containsKey(lib.importUri)) {
-        Uri fromSummary = workerInputCacheLibs[lib.importUri];
-        if (inputSummariesSet.contains(fromSummary)) {
-          throw new StateError(
-              "Asked to load several summaries that contain the same library.");
+      // Notice that the ordering of the input summaries matter, so we need to
+      // keep them in order.
+      if (outputLoadedInputSummaries.length != inputSummaries.length) {
+        throw new ArgumentError("Invalid length.");
+      }
+      Set<Uri> inputSummariesSet = new Set<Uri>();
+      for (int i = 0; i < inputSummaries.length; i++) {
+        Uri summaryUri = inputSummaries[i];
+        inputSummariesSet.add(summaryUri);
+        WorkerInputComponent cachedInput = workerInputCache[summaryUri];
+        List<int> digest = workerInputDigests[summaryUri];
+        if (digest == null) {
+          throw new StateError("Expected to get digest for $summaryUri");
+        }
+        if (cachedInput == null ||
+            cachedInput.component.root != nameRoot ||
+            !digestsEqual(digest, cachedInput.digest)) {
+          // Remove any old libraries from workerInputCacheLibs.
+          Component component = cachedInput?.component;
+          if (component != null) {
+            for (Library lib in component.libraries) {
+              workerInputCacheLibs.remove(lib.importUri);
+            }
+          }
+
+          loadFromDillIndexes.add(i);
         } else {
-          // Library contained in old cached component. Flush that cache.
-          Component component = workerInputCache.remove(fromSummary).component;
+          // Need to reset cached components so they are usable again.
+          Component component = cachedInput.component;
           for (Library lib in component.libraries) {
-            workerInputCacheLibs.remove(lib.importUri);
+            lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
+            if (trackNeededDillLibraries) {
+              libraryToInputDill[lib.importUri] = summaryUri;
+            }
+          }
+          component.computeCanonicalNames(); // this isn't needed, is it?
+          outputLoadedInputSummaries[i] = component;
+        }
+      }
+
+      for (int i = 0; i < loadFromDillIndexes.length; i++) {
+        int index = loadFromDillIndexes[i];
+        Uri summaryUri = inputSummaries[index];
+        List<int> digest = workerInputDigests[summaryUri];
+        if (digest == null) {
+          throw new StateError("Expected to get digest for $summaryUri");
+        }
+
+        List<int> bytes =
+            await fileSystem.entityForUri(summaryUri).readAsBytes();
+        WorkerInputComponent cachedInput = new WorkerInputComponent(
+            digest,
+            await processedOpts.loadComponent(bytes, nameRoot,
+                alwaysCreateNewNamedNodes: true));
+        workerInputCache[summaryUri] = cachedInput;
+        outputLoadedInputSummaries[index] = cachedInput.component;
+        for (Library lib in cachedInput.component.libraries) {
+          if (workerInputCacheLibs.containsKey(lib.importUri)) {
+            Uri fromSummary = workerInputCacheLibs[lib.importUri];
+            if (inputSummariesSet.contains(fromSummary)) {
+              throw new StateError(
+                  "Asked to load several summaries that contain the same "
+                  "library.");
+            } else {
+              // Library contained in old cached component. Flush that cache.
+              Component component =
+                  workerInputCache.remove(fromSummary).component;
+              for (Library lib in component.libraries) {
+                workerInputCacheLibs.remove(lib.importUri);
+              }
+            }
+          } else {
+            workerInputCacheLibs[lib.importUri] = summaryUri;
+          }
+
+          if (trackNeededDillLibraries) {
+            libraryToInputDill[lib.importUri] = summaryUri;
           }
         }
-      } else {
-        workerInputCacheLibs[lib.importUri] = summaryUri;
       }
 
-      if (trackNeededDillLibraries) {
-        libraryToInputDill[lib.importUri] = summaryUri;
-      }
+      incrementalCompiler
+          .setModulesToLoadOnNextComputeDelta(outputLoadedInputSummaries);
+
+      return new InitializedCompilerState(options, processedOpts,
+          workerInputCache: workerInputCache,
+          workerInputCacheLibs: workerInputCacheLibs,
+          incrementalCompiler: incrementalCompiler,
+          tags: tags,
+          libraryToInputDill: libraryToInputDill);
+    } catch (e, s) {
+      if (isRetry) rethrow;
+      print('''
+Failed to initialize incremental compiler, throwing away old state.
+
+This is likely a result of https://github.com/dart-lang/sdk/issues/38102, if
+you are consistently seeing this problem please see that issue.
+
+The specific exception that was encountered was:
+
+$e
+$s
+''');
+      isRetry = true;
+      oldState = null;
+      // Artificial delay to attempt to increase the odds of recovery from
+      // timing related issues.
+      await new Future.delayed(const Duration(milliseconds: 50));
     }
   }
-
-  incrementalCompiler
-      .setModulesToLoadOnNextComputeDelta(outputLoadedInputSummaries);
-
-  return new InitializedCompilerState(options, processedOpts,
-      workerInputCache: workerInputCache,
-      workerInputCacheLibs: workerInputCacheLibs,
-      incrementalCompiler: incrementalCompiler,
-      tags: tags,
-      libraryToInputDill: libraryToInputDill);
 }
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 6da41e1..c6e6a46 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -2,12 +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.
 
+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;
 
-export '../api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler, getMessageUri;
-
 export '../api_prototype/experimental_flags.dart'
     show defaultExperimentalFlags, ExperimentalFlag;
 
@@ -65,5 +67,3 @@
         serializeProcedure;
 
 export '../fasta/resolve_input_uri.dart' show resolveInputUri;
-
-export '../fasta/severity.dart' show Severity;
diff --git a/pkg/front_end/lib/src/base/libraries_specification.dart b/pkg/front_end/lib/src/base/libraries_specification.dart
index 2907e69..9dc212a 100644
--- a/pkg/front_end/lib/src/base/libraries_specification.dart
+++ b/pkg/front_end/lib/src/base/libraries_specification.dart
@@ -90,8 +90,8 @@
 // TODO(sigmund): move this file to a shared package.
 import 'dart:convert' show jsonDecode, jsonEncode;
 
-import '../fasta/util/relativize.dart' show relativizeUri;
-import '../fasta/resolve_input_uri.dart' show isWindows;
+import 'package:_fe_analyzer_shared/src/util/relativize.dart'
+    show relativizeUri, isWindows;
 
 /// Contents from a single library specification file.
 ///
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 413f0b2..d4777b0 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -8,6 +8,8 @@
 
 import 'dart:typed_data' show Uint8List;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:kernel/kernel.dart' show CanonicalName, Component, Location;
@@ -61,8 +63,6 @@
 
 import '../fasta/problems.dart' show DebugAbort, unimplemented;
 
-import '../fasta/severity.dart' show Severity;
-
 import '../fasta/ticker.dart' show Ticker;
 
 import '../fasta/uri_translator.dart' show UriTranslator;
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index 53e5418..b297897 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -6,9 +6,6 @@
 
 import '../problems.dart' show unsupported;
 
-/// Dummy class to help deprecate [Builder.target].
-abstract class UnrelatedTarget {}
-
 abstract class Builder {
   /// Used when multiple things with the same name are declared within the same
   /// parent. Only used for top-level and class-member declarations, not for
@@ -21,8 +18,6 @@
 
   int get charOffset;
 
-  get target;
-
   Builder get origin;
 
   String get fullNameForErrors;
@@ -217,9 +212,6 @@
   BuilderImpl();
 
   @override
-  get target => unsupported("${runtimeType}.target", charOffset, fileUri);
-
-  @override
   Builder get origin => this;
 
   bool get hasProblem => false;
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 262efcd..e47b4a1 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -32,6 +32,7 @@
         TypeParameter,
         TypeParameterType,
         VariableDeclaration,
+        Variance,
         VoidType;
 
 import 'package:kernel/ast.dart' show FunctionType, TypeParameterType;
@@ -43,7 +44,11 @@
 import 'package:kernel/core_types.dart' show CoreTypes;
 
 import 'package:kernel/src/bounds_checks.dart'
-    show TypeArgumentIssue, findTypeArgumentIssues, getGenericTypeName;
+    show
+        TypeArgumentIssue,
+        computeVariance,
+        findTypeArgumentIssues,
+        getGenericTypeName;
 import 'package:kernel/text/text_serialization_verifier.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
@@ -80,6 +85,8 @@
         templateIncorrectTypeArgumentInSupertypeInferred,
         templateInterfaceCheck,
         templateInternalProblemNotFoundIn,
+        templateInvalidTypeVariableVariancePosition,
+        templateInvalidTypeVariableVariancePositionInReturnType,
         templateMixinApplicationIncompatibleSupertype,
         templateNamedMixinOverride,
         templateOverriddenMethodCause,
@@ -107,7 +114,7 @@
 import '../names.dart' show noSuchMethodName;
 
 import '../problems.dart'
-    show internalProblem, unexpected, unhandled, unimplemented, unsupported;
+    show internalProblem, unexpected, unhandled, unimplemented;
 
 import '../scope.dart';
 
@@ -196,10 +203,6 @@
   /// For a patch class the origin class is returned.
   Class get cls;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  UnrelatedTarget get target;
-
   @override
   ClassBuilder get origin;
 
@@ -228,7 +231,7 @@
   void checkBoundsInSupertype(
       Supertype supertype, TypeEnvironment typeEnvironment);
 
-  void checkBoundsInOutline(TypeEnvironment typeEnvironment);
+  void checkTypesInOutline(TypeEnvironment typeEnvironment);
 
   void addRedirectingConstructor(
       ProcedureBuilder constructorBuilder, SourceLibraryBuilder library);
@@ -578,9 +581,9 @@
   @override
   Builder lookupLocalMember(String name,
       {bool setter: false, bool required: false}) {
-    Builder builder = setter ? scope.setters[name] : scope.local[name];
+    Builder builder = scope.lookupLocalMember(name, setter: setter);
     if (builder == null && isPatch) {
-      builder = setter ? origin.scope.setters[name] : origin.scope.local[name];
+      builder = origin.scope.lookupLocalMember(name, setter: setter);
     }
     if (required && builder == null) {
       internalProblem(
@@ -605,15 +608,6 @@
   InterfaceType _nullableRawType;
   InterfaceType _nonNullableRawType;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  @override
-  UnrelatedTarget get target => unsupported(
-      "ClassBuilder.target is deprecated. "
-      "Use ClassBuilder.cls instead.",
-      charOffset,
-      fileUri);
-
   @override
   ClassBuilder get origin => actualOrigin ?? this;
 
@@ -656,7 +650,7 @@
         return nullableRawType;
       case Nullability.nonNullable:
         return nonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         return unhandled("$nullability", "rawType", noOffset, noUri);
     }
@@ -858,7 +852,7 @@
   }
 
   @override
-  void checkBoundsInOutline(TypeEnvironment typeEnvironment) {
+  void checkTypesInOutline(TypeEnvironment typeEnvironment) {
     SourceLibraryBuilder library = this.library;
 
     // Check in bounds of own type variables.
@@ -912,9 +906,11 @@
 
     // Check in members.
     for (Field field in cls.fields) {
+      checkVarianceInField(field, typeEnvironment, cls.typeParameters);
       library.checkBoundsInField(field, typeEnvironment);
     }
     for (Procedure procedure in cls.procedures) {
+      checkVarianceInFunction(procedure, typeEnvironment, cls.typeParameters);
       library.checkBoundsInFunctionNode(
           procedure.function, typeEnvironment, fileUri);
     }
@@ -932,6 +928,96 @@
     }
   }
 
+  void checkVarianceInField(Field field, TypeEnvironment typeEnvironment,
+      List<TypeParameter> typeParameters) {
+    for (TypeParameter typeParameter in typeParameters) {
+      int fieldVariance = computeVariance(typeParameter, field.type);
+      if (field.hasImplicitGetter) {
+        reportVariancePositionIfInvalid(
+            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
+      }
+      if (field.hasImplicitSetter && !field.isCovariant) {
+        fieldVariance = Variance.combine(Variance.contravariant, fieldVariance);
+        reportVariancePositionIfInvalid(
+            fieldVariance, typeParameter, field.fileUri, field.fileOffset);
+      }
+    }
+  }
+
+  void checkVarianceInFunction(Procedure procedure,
+      TypeEnvironment typeEnvironment, List<TypeParameter> typeParameters) {
+    List<TypeParameter> functionTypeParameters =
+        procedure.function.typeParameters;
+    List<VariableDeclaration> positionalParameters =
+        procedure.function.positionalParameters;
+    List<VariableDeclaration> namedParameters =
+        procedure.function.namedParameters;
+    DartType returnType = procedure.function.returnType;
+
+    if (functionTypeParameters != null) {
+      for (TypeParameter functionParameter in functionTypeParameters) {
+        for (TypeParameter typeParameter in typeParameters) {
+          int typeVariance = Variance.combine(Variance.invariant,
+              computeVariance(typeParameter, functionParameter.bound));
+          reportVariancePositionIfInvalid(typeVariance, typeParameter, fileUri,
+              functionParameter.fileOffset);
+        }
+      }
+    }
+    if (positionalParameters != null) {
+      for (VariableDeclaration formal in positionalParameters) {
+        if (!formal.isCovariant) {
+          for (TypeParameter typeParameter in typeParameters) {
+            int formalVariance = Variance.combine(Variance.contravariant,
+                computeVariance(typeParameter, formal.type));
+            reportVariancePositionIfInvalid(
+                formalVariance, typeParameter, fileUri, formal.fileOffset);
+          }
+        }
+      }
+    }
+    if (namedParameters != null) {
+      for (VariableDeclaration named in namedParameters) {
+        for (TypeParameter typeParameter in typeParameters) {
+          int namedVariance = Variance.combine(Variance.contravariant,
+              computeVariance(typeParameter, named.type));
+          reportVariancePositionIfInvalid(
+              namedVariance, typeParameter, fileUri, named.fileOffset);
+        }
+      }
+    }
+    if (returnType != null) {
+      for (TypeParameter typeParameter in typeParameters) {
+        int returnTypeVariance = computeVariance(typeParameter, returnType);
+        reportVariancePositionIfInvalid(returnTypeVariance, typeParameter,
+            fileUri, procedure.function.fileOffset,
+            isReturnType: true);
+      }
+    }
+  }
+
+  void reportVariancePositionIfInvalid(
+      int variance, TypeParameter typeParameter, Uri fileUri, int fileOffset,
+      {bool isReturnType: false}) {
+    SourceLibraryBuilder library = this.library;
+    if (!typeParameter.isLegacyCovariant &&
+        !Variance.greaterThanOrEqual(variance, typeParameter.variance)) {
+      Message message;
+      if (isReturnType) {
+        message = templateInvalidTypeVariableVariancePositionInReturnType
+            .withArguments(Variance.keywordString(typeParameter.variance),
+                typeParameter.name, Variance.keywordString(variance));
+      } else {
+        message = templateInvalidTypeVariableVariancePosition.withArguments(
+            Variance.keywordString(typeParameter.variance),
+            typeParameter.name,
+            Variance.keywordString(variance));
+      }
+      library.reportTypeArgumentIssue(
+          message, fileUri, fileOffset, typeParameter);
+    }
+  }
+
   @override
   void addRedirectingConstructor(
       ProcedureBuilder constructorBuilder, SourceLibraryBuilder library) {
@@ -947,16 +1033,20 @@
     // [constructor.target].
     //
     // TODO(ahe): Add a kernel node to represent redirecting factory bodies.
+    const String redirectingName = "_redirecting#";
     DillMemberBuilder constructorsField =
-        origin.scope.local.putIfAbsent("_redirecting#", () {
+        origin.scope.lookupLocalMember(redirectingName, setter: false);
+    if (constructorsField == null) {
       ListLiteral literal = new ListLiteral(<Expression>[]);
-      Name name = new Name("_redirecting#", library.library);
+      Name name = new Name(redirectingName, library.library);
       Field field = new Field(name,
           isStatic: true, initializer: literal, fileUri: cls.fileUri)
         ..fileOffset = cls.fileOffset;
       cls.addMember(field);
-      return new DillMemberBuilder(field, this);
-    });
+      constructorsField = new DillMemberBuilder(field, this);
+      origin.scope
+          .addLocalMember(redirectingName, constructorsField, setter: false);
+    }
     Field field = constructorsField.member;
     ListLiteral literal = field.initializer;
     literal.expressions
@@ -1759,14 +1849,15 @@
         patchForTesting = patch;
       }
       // TODO(ahe): Complain if `patch.supertype` isn't null.
-      scope.local.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.local[name];
+      scope.forEachLocalMember((String name, Builder member) {
+        Builder memberPatch =
+            patch.scope.lookupLocalMember(name, setter: false);
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
       });
-      scope.setters.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.setters[name];
+      scope.forEachLocalSetter((String name, Builder member) {
+        Builder memberPatch = patch.scope.lookupLocalMember(name, setter: true);
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
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 bec90c2..07565c4 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -4,12 +4,10 @@
 
 import 'dart:core' hide MapEntry;
 
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
 import 'package:kernel/ast.dart' hide Variance;
 
-import '../../base/common.dart';
-
-import '../../scanner/token.dart' show Token;
-
 import '../constant_context.dart' show ConstantContext;
 
 import '../kernel/body_builder.dart' show BodyBuilder;
@@ -105,9 +103,6 @@
   ConstructorBuilder actualOrigin;
 
   @override
-  ConstructorBuilder patchForTesting;
-
-  @override
   Constructor get actualConstructor => _constructor;
 
   ConstructorBuilderImpl(
@@ -134,6 +129,9 @@
   ConstructorBuilder get origin => actualOrigin ?? this;
 
   @override
+  ConstructorBuilder get patchForTesting => dataForTesting?.patchForTesting;
+
+  @override
   bool get isDeclarationInstanceMember => false;
 
   @override
@@ -309,9 +307,7 @@
     if (patch is ConstructorBuilderImpl) {
       if (checkPatch(patch)) {
         patch.actualOrigin = this;
-        if (retainDataForTesting) {
-          patchForTesting = patch;
-        }
+        dataForTesting?.patchForTesting = patch;
       }
     } else {
       reportPatchMismatch(patch);
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 3e7daab..f1dfab0 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -26,11 +26,6 @@
   /// Return the [Extension] built by this builder.
   Extension get extension;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  @override
-  UnrelatedTarget get target;
-
   void buildOutlineExpressions(LibraryBuilder library);
 
   /// Looks up extension member by [name] taking privacy into account.
@@ -76,15 +71,6 @@
     return declaration;
   }
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  @override
-  UnrelatedTarget get target => unsupported(
-      "ExtensionBuilder.target is deprecated. "
-      "Use ExtensionBuilder.extension instead.",
-      charOffset,
-      fileUri);
-
   @override
   DartType buildType(LibraryBuilder library,
       NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
@@ -108,7 +94,7 @@
   Builder lookupLocalMember(String name,
       {bool setter: false, bool required: false}) {
     // TODO(johnniwinther): Support patching on extensions.
-    Builder builder = setter ? scope.setters[name] : scope.local[name];
+    Builder builder = scope.lookupLocalMember(name, setter: setter);
     if (required && builder == null) {
       internalProblem(
           templateInternalProblemNotFoundIn.withArguments(
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 23825f5..75a5060 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -4,16 +4,9 @@
 
 library fasta.field_builder;
 
-import 'package:kernel/ast.dart'
-    show
-        Class,
-        DartType,
-        Expression,
-        Field,
-        InvalidType,
-        Member,
-        Name,
-        NullLiteral;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import 'package:kernel/ast.dart' hide MapEntry, Variance;
 
 import '../constant_context.dart' show ConstantContext;
 
@@ -30,8 +23,6 @@
 
 import '../problems.dart' show internalProblem;
 
-import '../scanner.dart' show Token;
-
 import '../scope.dart' show Scope;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -135,6 +126,18 @@
     return type == null && (hasInitializer || isClassInstanceMember);
   }
 
+  @override
+  bool get isAssignable {
+    if (isConst) return false;
+    if (isFinal) {
+      if (isLate) {
+        return !hasInitializer;
+      }
+      return false;
+    }
+    return true;
+  }
+
   Field build(SourceLibraryBuilder libraryBuilder) {
     field
       ..isCovariant = isCovariant
@@ -207,10 +210,8 @@
               library, classBuilder, this, scope, fileUri);
       bodyBuilder.constantContext =
           isConst ? ConstantContext.inferred : ConstantContext.required;
-      initializer = bodyBuilder.parseFieldInitializer(constInitializerToken)
-        ..parent = field;
-      bodyBuilder.typeInferrer
-          ?.inferFieldInitializer(bodyBuilder, field.type, field.initializer);
+      initializer = bodyBuilder.typeInferrer?.inferFieldInitializer(bodyBuilder,
+          field.type, bodyBuilder.parseFieldInitializer(constInitializerToken));
       if (library.loader is SourceLoader) {
         SourceLoader loader = library.loader;
         loader.transformPostInference(field, bodyBuilder.transformSetLiterals,
@@ -246,8 +247,8 @@
     }
     type.isStarted = true;
     TypeInferrerImpl typeInferrer = library.loader.typeInferenceEngine
-        .createTopLevelTypeInferrer(
-            fileUri, field.enclosingClass?.thisType, library);
+        .createTopLevelTypeInferrer(fileUri, field.enclosingClass?.thisType,
+            library, dataForTesting?.inferenceData);
     BodyBuilder bodyBuilder =
         library.loader.createBodyBuilderForField(this, typeInferrer);
     bodyBuilder.constantContext =
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 3937dcc..b85d421 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
@@ -4,22 +4,23 @@
 
 library fasta.formal_parameter_builder;
 
-import 'package:kernel/ast.dart' show VariableDeclaration;
-
-import '../parser.dart' show FormalParameterKind;
-
-import '../parser/formal_parameter_kind.dart'
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'
     show
         isMandatoryFormalParameterKind,
         isOptionalNamedFormalParameterKind,
         isOptionalPositionalFormalParameterKind;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show FormalParameterKind;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import 'package:kernel/ast.dart' show Expression, VariableDeclaration;
+
 import '../constant_context.dart' show ConstantContext;
 
 import '../modifier.dart';
 
-import '../scanner.dart' show Token;
-
 import '../scope.dart' show Scope;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -38,10 +39,12 @@
 import 'metadata_builder.dart';
 import 'modifier_builder.dart';
 import 'type_builder.dart';
+import 'variable_builder.dart';
 
 /// A builder for a formal parameter, i.e. a parameter on a method or
 /// constructor.
-class FormalParameterBuilder extends ModifierBuilderImpl {
+class FormalParameterBuilder extends ModifierBuilderImpl
+    implements VariableBuilder {
   /// List of metadata builders for the metadata declared on this parameter.
   final List<MetadataBuilder> metadata;
 
@@ -93,11 +96,14 @@
 
   bool get isCovariant => (modifiers & covariantMask) != 0;
 
+  // An initializing formal parameter might be final without its
+  // VariableDeclaration being final. See
+  // [ProcedureBuilder.computeFormalParameterInitializerScope]..
+  bool get isAssignable => variable.isAssignable && !isInitializingFormal;
+
   @override
   String get fullNameForErrors => name;
 
-  VariableDeclaration get target => variable;
-
   VariableDeclaration build(
       SourceLibraryBuilder library, int functionNestingLevel) {
     if (variable == null) {
@@ -168,10 +174,11 @@
           .createBodyBuilderForOutlineExpression(
               library, classBuilder, this, scope, fileUri);
       bodyBuilder.constantContext = ConstantContext.required;
-      variable.initializer = bodyBuilder.parseFieldInitializer(initializerToken)
-        ..parent = variable;
-      bodyBuilder.typeInferrer?.inferParameterInitializer(
-          bodyBuilder, variable.initializer, variable.type);
+      Expression initializer =
+          bodyBuilder.parseFieldInitializer(initializerToken);
+      initializer = bodyBuilder.typeInferrer
+          ?.inferParameterInitializer(bodyBuilder, initializer, variable.type);
+      variable.initializer = initializer..parent = variable;
       if (library.loader is SourceLoader) {
         SourceLoader loader = library.loader;
         loader.transformPostInference(variable,
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 19ae53c..2ddba04 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -216,6 +216,9 @@
   bool get isExternal => (modifiers & externalMask) != 0;
 
   @override
+  bool get isAssignable => false;
+
+  @override
   Scope computeFormalParameterScope(Scope parent) {
     if (formals == null) return parent;
     Map<String, Builder> local = <String, Builder>{};
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 f42b8d4..6788b1d 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
@@ -26,9 +26,6 @@
       {this.context, this.suppressMessage: true})
       : super(null, 0, name, null, message.charOffset, message.uri);
 
-  @override
-  InvalidType get target => const InvalidType();
-
   DartType buildType(LibraryBuilder library,
       NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
     return buildTypesWithBuiltArguments(library, null, null);
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 6d6db2a..bd32d32 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -4,6 +4,8 @@
 
 library fasta.library_builder;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart' show Library, Nullability;
 
 import '../combinator.dart' show Combinator;
@@ -23,8 +25,6 @@
         templateInternalProblemNotFoundIn,
         templateInternalProblemPrivateConstructorAccess;
 
-import '../severity.dart' show Severity;
-
 import '../scope.dart';
 
 import 'builder.dart';
@@ -52,11 +52,6 @@
 
   bool mayImplementRestrictedTypes;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  @override
-  UnrelatedTarget get target;
-
   /// Set the language version to a specific non-null major and minor version.
   ///
   /// If the language version has previously been explicitly set set (i.e. with
@@ -142,6 +137,12 @@
 
   int finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType);
 
+  /// Computes variances of type parameters on typedefs.
+  ///
+  /// The variance property of type parameters on typedefs is computed from the
+  /// use of the parameters in the right-hand side of the typedef definition.
+  int computeVariances() => 0;
+
   /// This method instantiates type parameters to their bounds in some cases
   /// where they were omitted by the programmer and not provided by the type
   /// inference.  The method returns the number of distinct type variables
@@ -153,6 +154,8 @@
 
   void addSyntheticDeclarationOfDynamic();
 
+  void addSyntheticDeclarationOfNever();
+
   /// Lookups the member [name] declared in this library.
   ///
   /// If [required] is `true` and no member is found an internal problem is
@@ -216,15 +219,6 @@
   @override
   bool get isSynthetic => false;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  @override
-  UnrelatedTarget get target => unsupported(
-      "LibraryBuilder.target is deprecated. "
-      "Use LibraryBuilder.library instead.",
-      charOffset,
-      fileUri);
-
   /// Set the language version to a specific non-null major and minor version.
   ///
   /// If the language version has previously been explicitly set set (i.e. with
@@ -297,20 +291,20 @@
   bool addToExportScope(String name, Builder member, [int charOffset = -1]) {
     if (name.startsWith("_")) return false;
     if (member is PrefixBuilder) return false;
-    Map<String, Builder> map =
-        member.isSetter ? exportScope.setters : exportScope.local;
-    Builder existing = map[name];
-    if (existing == member) return false;
-    if (existing != null) {
+    Builder existing =
+        exportScope.lookupLocalMember(name, setter: member.isSetter);
+    if (existing == member) {
+      return false;
+    } else if (existing != null) {
       Builder result = computeAmbiguousDeclaration(
           name, existing, member, charOffset,
           isExport: true);
-      map[name] = result;
+      exportScope.addLocalMember(name, result, setter: member.isSetter);
       return result != existing;
     } else {
-      map[name] = member;
+      exportScope.addLocalMember(name, member, setter: member.isSetter);
+      return true;
     }
-    return true;
   }
 
   @override
@@ -364,6 +358,9 @@
   int finishTypeVariables(ClassBuilder object, TypeBuilder dynamicType) => 0;
 
   @override
+  int computeVariances() => 0;
+
+  @override
   int computeDefaultTypes(TypeBuilder dynamicType, TypeBuilder bottomType,
       ClassBuilder objectClass) {
     return 0;
@@ -371,14 +368,17 @@
 
   @override
   void becomeCoreLibrary() {
-    if (scope.local["dynamic"] == null) {
+    if (scope.lookupLocalMember("dynamic", setter: false) == null) {
       addSyntheticDeclarationOfDynamic();
     }
+    if (scope.lookupLocalMember("Never", setter: false) == null) {
+      addSyntheticDeclarationOfNever();
+    }
   }
 
   @override
   Builder lookupLocalMember(String name, {bool required: false}) {
-    Builder builder = scope.local[name];
+    Builder builder = scope.lookupLocalMember(name, setter: false);
     if (required && builder == null) {
       internalProblem(
           templateInternalProblemNotFoundIn.withArguments(
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 b17b175..c4475da 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -8,7 +8,12 @@
 
 import 'package:kernel/ast.dart';
 
+import '../../base/common.dart';
+
+import '../kernel/class_hierarchy_builder.dart';
 import '../problems.dart' show unsupported;
+import '../type_inference/type_inference_engine.dart'
+    show InferenceDataForTesting;
 
 import 'builder.dart';
 import 'class_builder.dart';
@@ -17,8 +22,6 @@
 import 'library_builder.dart';
 import 'modifier_builder.dart';
 
-import '../kernel/class_hierarchy_builder.dart';
-
 abstract class MemberBuilder implements ModifierBuilder, ClassMember {
   void set parent(Builder value);
 
@@ -27,9 +30,6 @@
   /// The [Member] built by this builder;
   Member get member;
 
-  // TODO(johnniwinther): Deprecate this.
-  Member get target;
-
   // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
   Member get extensionTearOff;
 
@@ -57,7 +57,12 @@
   @override
   String get name;
 
-  MemberBuilderImpl(this.parent, int charOffset) : super(parent, charOffset);
+  MemberDataForTesting dataForTesting;
+
+  MemberBuilderImpl(this.parent, int charOffset)
+      : dataForTesting =
+            retainDataForTesting ? new MemberDataForTesting() : null,
+        super(parent, charOffset);
 
   @override
   bool get isDeclarationInstanceMember => isDeclarationMember && !isStatic;
@@ -99,10 +104,6 @@
     }
   }
 
-  // TODO(johnniwinther): Deprecate this.
-  @override
-  Member get target => member;
-
   // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
   @override
   Member get extensionTearOff =>
@@ -133,3 +134,9 @@
   @override
   ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
 }
+
+class MemberDataForTesting {
+  final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
+
+  MemberBuilder patchForTesting;
+}
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 2853615..80978bb 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -4,12 +4,12 @@
 
 library fasta.metadata_builder;
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
 import 'package:kernel/ast.dart' show Annotatable, Class, Library;
 
 import '../kernel/body_builder.dart' show BodyBuilder;
 
-import '../scanner.dart' show Token;
-
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import '../scope.dart' show Scope;
@@ -43,7 +43,7 @@
       parent.addAnnotation(
           bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
     }
-    bodyBuilder.inferAnnotations(parent.annotations);
+    bodyBuilder.inferAnnotations(parent, parent.annotations);
     bodyBuilder.resolveRedirectingFactoryTargets();
   }
 }
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 02402c3..a653514 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
@@ -4,6 +4,8 @@
 
 library fasta.named_type_builder;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart' show DartType, Supertype;
 
 import '../fasta_codes.dart'
@@ -28,9 +30,8 @@
 
 import '../scope.dart';
 
-import '../severity.dart' show Severity;
-
 import 'builder.dart';
+import 'builtin_type_builder.dart';
 import 'class_builder.dart';
 import 'invalid_type_declaration_builder.dart';
 import 'library_builder.dart';
@@ -284,7 +285,11 @@
     }
     NamedTypeBuilder newType =
         new NamedTypeBuilder(name, nullabilityBuilder, clonedArguments);
-    newTypes.add(newType);
+    if (declaration is BuiltinTypeBuilder) {
+      newType.declaration = declaration;
+    } else {
+      newTypes.add(newType);
+    }
     return newType;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart
new file mode 100644
index 0000000..b9ed5f6
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/never_type_builder.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.
+
+library fasta.never_type_builder;
+
+import 'package:kernel/ast.dart' show DartType, Nullability;
+
+import 'builtin_type_builder.dart';
+import 'library_builder.dart';
+import 'nullability_builder.dart';
+import 'type_builder.dart';
+
+class NeverTypeBuilder extends BuiltinTypeBuilder {
+  NeverTypeBuilder(
+      DartType type, LibraryBuilder compilationUnit, int charOffset)
+      : super("Never", type, compilationUnit, charOffset);
+
+  String get debugName => "NeverTypeBuilder";
+
+  DartType buildType(LibraryBuilder library,
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+    return type.withNullability(nullabilityBuilder.build(library));
+  }
+
+  DartType buildTypesWithBuiltArguments(LibraryBuilder library,
+      Nullability nullability, List<DartType> arguments) {
+    return type.withNullability(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 1fece4a..54a2786 100644
--- a/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
@@ -41,7 +41,7 @@
         return const NullabilityBuilder.nullable();
       case Nullability.legacy:
       case Nullability.nonNullable:
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         return const NullabilityBuilder.omitted();
     }
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 ffb90bd..16686fb 100644
--- a/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/prefix_builder.dart
@@ -47,16 +47,17 @@
   }
 
   void addToExportScope(String name, Builder member, int charOffset) {
-    Map<String, Builder> map =
-        member.isSetter ? exportScope.setters : exportScope.local;
-    Builder existing = map[name];
+    Builder existing =
+        exportScope.lookupLocalMember(name, setter: member.isSetter);
+    Builder result;
     if (existing != null) {
-      map[name] = parent.computeAmbiguousDeclaration(
+      result = parent.computeAmbiguousDeclaration(
           name, existing, member, charOffset,
           isExport: true);
     } else {
-      map[name] = member;
+      result = member;
     }
+    exportScope.addLocalMember(name, result, setter: member.isSetter);
   }
 
   @override
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 22efa9d..4823b32 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -9,8 +9,6 @@
 
 import 'package:kernel/type_algebra.dart';
 
-import '../../base/common.dart';
-
 import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
 import '../loader.dart' show Loader;
@@ -66,9 +64,6 @@
   final ProcedureKind kind;
 
   @override
-  ProcedureBuilder patchForTesting;
-
-  @override
   AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
 
   @override
@@ -118,6 +113,9 @@
   ProcedureBuilder get origin => actualOrigin ?? this;
 
   @override
+  ProcedureBuilder get patchForTesting => dataForTesting?.patchForTesting;
+
+  @override
   AsyncMarker get asyncModifier => actualAsyncModifier;
 
   @override
@@ -399,9 +397,7 @@
     if (patch is ProcedureBuilderImpl) {
       if (checkPatch(patch)) {
         patch.actualOrigin = this;
-        if (retainDataForTesting) {
-          patchForTesting = patch;
-        }
+        dataForTesting?.patchForTesting = patch;
       }
     } else {
       reportPatchMismatch(patch);
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 ec076a7..c284797 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
@@ -21,11 +21,10 @@
 import '../fasta_codes.dart'
     show noLength, templateCyclicTypedef, templateTypeArgumentMismatch;
 
-import '../problems.dart' show unhandled, unsupported;
+import '../problems.dart' show unhandled;
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import 'builder.dart';
 import 'formal_parameter_builder.dart';
 import 'function_type_builder.dart';
 import 'library_builder.dart';
@@ -56,14 +55,6 @@
               ..fileOffset = charOffset),
         super(metadata, 0, name, parent, charOffset);
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // use until Builder.target is fully retired.
-  UnrelatedTarget get target => unsupported(
-      "TypeAliasBuilder.target is deprecated. "
-      "Use TypeAliasBuilder.typedef instead.",
-      charOffset,
-      fileUri);
-
   String get debugName => "TypeAliasBuilder";
 
   LibraryBuilder get parent => super.parent;
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 f018dfe..eda4189 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
@@ -5,7 +5,7 @@
 library fasta.type_variable_builder;
 
 import 'package:kernel/ast.dart'
-    show DartType, Nullability, TypeParameter, TypeParameterType, Variance;
+    show DartType, Nullability, TypeParameter, TypeParameterType;
 
 import '../fasta_codes.dart'
     show
@@ -13,11 +13,8 @@
         templateInternalProblemUnfinishedTypeVariable,
         templateTypeArgumentsOnTypeVariable;
 
-import '../problems.dart' show unsupported;
-
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import 'builder.dart';
 import 'class_builder.dart';
 import 'library_builder.dart';
 import 'named_type_builder.dart';
@@ -38,9 +35,7 @@
 
   TypeVariableBuilder(
       String name, SourceLibraryBuilder compilationUnit, int charOffset,
-      {this.bound,
-      this.isExtensionTypeParameter: false,
-      int variableVariance: Variance.covariant})
+      {this.bound, this.isExtensionTypeParameter: false, int variableVariance})
       : actualParameter = new TypeParameter(name, null)
           ..fileOffset = charOffset
           ..variance = variableVariance,
@@ -74,14 +69,6 @@
   /// The [TypeParameter] built by this builder.
   TypeParameter get parameter => origin.actualParameter;
 
-  // Deliberately unrelated return type to statically detect more accidental
-  // uses until Builder.target is fully retired.
-  UnrelatedTarget get target => unsupported(
-      "TypeVariableBuilder.target is deprecated. "
-      "Use TypeVariableBuilder.parameter instead.",
-      charOffset,
-      fileUri);
-
   int get variance => parameter.variance;
 
   void set variance(int value) {
@@ -201,7 +188,7 @@
           if (current.parameter.bound is TypeParameterType) {
             next = current.parameter.bound;
             if (next.typeParameterTypeNullability == marker) {
-              next.typeParameterTypeNullability = Nullability.neither;
+              next.typeParameterTypeNullability = Nullability.undetermined;
               libraryBuilder.addProblem(
                   templateCycleInTypeVariables.withArguments(
                       next.parameter.name, current.parameter.name),
diff --git a/pkg/front_end/lib/src/fasta/builder/variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/variable_builder.dart
new file mode 100644
index 0000000..cc006cb
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/variable_builder.dart
@@ -0,0 +1,15 @@
+// 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.
+
+library fasta.kernel_variable_builder;
+
+import 'package:kernel/ast.dart' show VariableDeclaration;
+
+import '../builder/builder.dart';
+
+abstract class VariableBuilder implements Builder {
+  VariableDeclaration get variable;
+
+  bool get isAssignable;
+}
diff --git a/pkg/front_end/lib/src/fasta/colors.dart b/pkg/front_end/lib/src/fasta/colors.dart
deleted file mode 100644
index c8b4812..0000000
--- a/pkg/front_end/lib/src/fasta/colors.dart
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// TODO(ahe): Originally copied from sdk/pkg/compiler/lib/src/colors.dart,
-// merge these two packages.
-library colors;
-
-import 'dart:convert' show jsonEncode;
-
-import 'dart:io' show Platform, Process, ProcessResult, stderr, stdout;
-
-import 'compiler_context.dart' show CompilerContext;
-
-/// ANSI/xterm termcap for setting default colors. Output from Unix
-/// command-line program `tput op`.
-const String DEFAULT_COLOR = "\x1b[39;49m";
-
-/// ANSI/xterm termcap for setting black text color. Output from Unix
-/// command-line program `tput setaf 0`.
-const String BLACK_COLOR = "\x1b[30m";
-
-/// ANSI/xterm termcap for setting red text color. Output from Unix
-/// command-line program `tput setaf 1`.
-const String RED_COLOR = "\x1b[31m";
-
-/// ANSI/xterm termcap for setting green text color. Output from Unix
-/// command-line program `tput setaf 2`.
-const String GREEN_COLOR = "\x1b[32m";
-
-/// ANSI/xterm termcap for setting yellow text color. Output from Unix
-/// command-line program `tput setaf 3`.
-const String YELLOW_COLOR = "\x1b[33m";
-
-/// ANSI/xterm termcap for setting blue text color. Output from Unix
-/// command-line program `tput setaf 4`.
-const String BLUE_COLOR = "\x1b[34m";
-
-/// ANSI/xterm termcap for setting magenta text color. Output from Unix
-/// command-line program `tput setaf 5`.
-const String MAGENTA_COLOR = "\x1b[35m";
-
-/// ANSI/xterm termcap for setting cyan text color. Output from Unix
-/// command-line program `tput setaf 6`.
-const String CYAN_COLOR = "\x1b[36m";
-
-/// ANSI/xterm termcap for setting white text color. Output from Unix
-/// command-line program `tput setaf 7`.
-const String WHITE_COLOR = "\x1b[37m";
-
-/// All the above codes. This is used to compare the above codes to the
-/// terminal's. Printing this string should have the same effect as just
-/// printing [DEFAULT_COLOR].
-const String ALL_CODES = BLACK_COLOR +
-    RED_COLOR +
-    GREEN_COLOR +
-    YELLOW_COLOR +
-    BLUE_COLOR +
-    MAGENTA_COLOR +
-    CYAN_COLOR +
-    WHITE_COLOR +
-    DEFAULT_COLOR;
-
-const String TERMINAL_CAPABILITIES = """
-colors
-setaf 0
-setaf 1
-setaf 2
-setaf 3
-setaf 4
-setaf 5
-setaf 6
-setaf 7
-op
-""";
-
-String wrap(String string, String color) {
-  return CompilerContext.enableColors
-      ? "${color}$string${DEFAULT_COLOR}"
-      : string;
-}
-
-String black(String string) => wrap(string, BLACK_COLOR);
-String red(String string) => wrap(string, RED_COLOR);
-String green(String string) => wrap(string, GREEN_COLOR);
-String yellow(String string) => wrap(string, YELLOW_COLOR);
-String blue(String string) => wrap(string, BLUE_COLOR);
-String magenta(String string) => wrap(string, MAGENTA_COLOR);
-String cyan(String string) => wrap(string, CYAN_COLOR);
-String white(String string) => wrap(string, WHITE_COLOR);
-
-/// Returns whether [sink] supports ANSI escapes or `null` if it could not be
-/// determined.
-bool _supportsAnsiEscapes(sink) {
-  try {
-    // ignore: undefined_getter
-    return sink.supportsAnsiEscapes;
-  } on NoSuchMethodError {
-    // Ignored: We're running on an older version of the Dart VM which doesn't
-    // implement `supportsAnsiEscapes`.
-    return null;
-  }
-}
-
-/// True if we should enable colors in output.
-///
-/// We enable colors when both `stdout` and `stderr` support ANSI escapes.
-///
-/// On non-Windows platforms, this functions checks the terminal capabilities,
-/// on Windows we only enable colors if the VM getters are present and returned
-/// `true`.
-///
-/// Note: do not call this method directly, as it is expensive to
-/// compute. Instead, use [CompilerContext.enableColors].
-bool computeEnableColors(CompilerContext context) {
-  // TODO(ahe): Remove this method.
-
-  bool stderrSupportsColors = _supportsAnsiEscapes(stdout);
-  bool stdoutSupportsColors = _supportsAnsiEscapes(stderr);
-
-  if (stdoutSupportsColors == false) {
-    if (context.options.verbose) {
-      print("Not enabling colors, stdout does not support ANSI colors.");
-    }
-    return false;
-  }
-  if (stderrSupportsColors == false) {
-    if (context.options.verbose) {
-      print("Not enabling colors, stderr does not support ANSI colors.");
-    }
-    return false;
-  }
-
-  if (Platform.isWindows) {
-    if (stderrSupportsColors != true || stdoutSupportsColors != true) {
-      // In this case, either [stdout] or [stderr] did not support the
-      // property `supportsAnsiEscapes`. Since we do not have another way
-      // to determine support for colors, we disable them.
-      if (context.options.verbose) {
-        print("Not enabling colors as ANSI is not supported.");
-      }
-      return false;
-    }
-    if (context.options.verbose) {
-      print("Enabling colors as OS is Windows.");
-    }
-    return true;
-  }
-
-  // We have to check if the terminal actually supports colors. Currently,
-  // to avoid linking the Dart VM with ncurses, ANSI escape support is reduced
-  // to `Platform.environment['TERM'].contains("xterm")`.
-
-  // The `-S` option of `tput` allows us to query multiple capabilities at
-  // once.
-  ProcessResult result = Process.runSync(
-      "/bin/sh", ["-c", "printf '%s' '$TERMINAL_CAPABILITIES' | tput -S"]);
-
-  if (result.exitCode != 0) {
-    if (context.options.verbose) {
-      print("Not enabling colors, running tput failed.");
-    }
-    return false;
-  }
-
-  List<String> lines = result.stdout.split("\n");
-
-  if (lines.length != 2) {
-    if (context.options.verbose) {
-      print("Not enabling colors, unexpected output from tput: "
-          "${jsonEncode(result.stdout)}.");
-    }
-    return false;
-  }
-
-  String numberOfColors = lines[0];
-  if ((int.tryParse(numberOfColors) ?? -1) < 8) {
-    if (context.options.verbose) {
-      print("Not enabling colors, less than 8 colors supported: "
-          "${jsonEncode(numberOfColors)}.");
-    }
-    return false;
-  }
-
-  String allCodes = lines[1].trim();
-  if (ALL_CODES != allCodes) {
-    if (context.options.verbose) {
-      print("Not enabling colors, color codes don't match: "
-          "${jsonEncode(ALL_CODES)} != ${jsonEncode(allCodes)}.");
-    }
-    return false;
-  }
-
-  if (context.options.verbose) {
-    print("Enabling colors.");
-  }
-  return true;
-}
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 87e21e6..137ecd1 100644
--- a/pkg/front_end/lib/src/fasta/command_line_reporting.dart
+++ b/pkg/front_end/lib/src/fasta/command_line_reporting.dart
@@ -12,12 +12,22 @@
 
 import 'dart:typed_data' show Uint8List;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart'
+    show Severity, severityPrefixes;
+
+import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
+    show $CARET, $SPACE, $TAB;
+
+import 'package:_fe_analyzer_shared/src/util/colors.dart'
+    show enableColors, green, magenta, red;
+
+import 'package:_fe_analyzer_shared/src/util/relativize.dart'
+    show isWindows, relativizeUri;
+
 import 'package:kernel/ast.dart' show Location, TreeNode;
 
 import '../compute_platform_binaries_location.dart' show translateSdk;
 
-import 'colors.dart' show green, magenta, red;
-
 import 'compiler_context.dart' show CompilerContext;
 
 import 'crash.dart' show Crash, safeToString;
@@ -28,14 +38,6 @@
 
 import 'problems.dart' show unhandled;
 
-import 'resolve_input_uri.dart' show isWindows;
-
-import 'severity.dart' show Severity, severityPrefixes;
-
-import 'scanner/characters.dart' show $CARET, $SPACE, $TAB;
-
-import 'util/relativize.dart' show relativizeUri;
-
 const bool hideWarnings = false;
 
 /// Formats [message] as a string that is suitable for output from a
@@ -55,7 +57,7 @@
     if (message.tip != null) {
       messageText += "\n${message.tip}";
     }
-    if (CompilerContext.enableColors) {
+    if (enableColors) {
       switch (severity) {
         case Severity.error:
         case Severity.internalProblem:
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 98d4be9..820b4b2 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -6,23 +6,24 @@
 
 import 'dart:async' show Future, Zone, runZoned;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
+
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
+    show StringToken;
+
 import 'package:kernel/ast.dart' show Source;
 
 import '../api_prototype/file_system.dart' show FileSystem;
 
 import '../base/processed_options.dart' show ProcessedOptions;
 
-import 'scanner/token.dart' show StringToken;
-
 import 'command_line_reporting.dart' as command_line_reporting;
 
-import 'colors.dart' show computeEnableColors;
-
 import 'fasta_codes.dart'
     show LocatedMessage, Message, messageInternalProblemMissingContext;
 
-import 'severity.dart' show Severity;
-
 final Object compilerContextKey = new Object();
 
 /// Shared context used throughout the compiler.
@@ -52,16 +53,14 @@
 
   FileSystem get fileSystem => options.fileSystem;
 
-  bool enableColorsCached = null;
-
   Uri cachedSdkRoot = null;
 
   bool compilingPlatform = false;
 
-  CompilerContext(this.options);
-
-  void disableColors() {
-    enableColorsCached = false;
+  CompilerContext(this.options) {
+    if (options.verbose) {
+      colors.printEnableColorsReason = print;
+    }
   }
 
   /// Report [message], for example, by printing it.
@@ -142,10 +141,6 @@
     return new CompilerContext(new ProcessedOptions()).runInContext<T>(action);
   }
 
-  static bool get enableColors {
-    return current.enableColorsCached ??= computeEnableColors(current);
-  }
-
   void clear() {
     StringToken.canonicalizer.clear();
     errors.clear();
diff --git a/pkg/front_end/lib/src/fasta/diagnostics.md b/pkg/front_end/lib/src/fasta/diagnostics.md
index 1305e52..4307597 100644
--- a/pkg/front_end/lib/src/fasta/diagnostics.md
+++ b/pkg/front_end/lib/src/fasta/diagnostics.md
@@ -9,7 +9,7 @@
   -- you also update these references to it:
   --  * pkg/compiler/lib/src/diagnostics/messages.dart
   --  * pkg/dart_messages/lib/shared_messages.dart
-  --  * pkg/front_end/lib/src/base/errors.dart
+  --  * pkg/_fe_analyzer_shared/lib/src/base/errors.dart
   --  * https://github.com/dart-lang/linter/
   -->
 
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 12637f1..3992966 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
@@ -57,4 +57,7 @@
     }
     return null;
   }
+
+  @override
+  bool get isAssignable => member is Field && member.hasSetter;
 }
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 d13f4d3..5296ed7 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
@@ -18,6 +18,8 @@
         ListLiteral,
         Member,
         NamedNode,
+        NeverType,
+        Nullability,
         Procedure,
         Reference,
         StaticGet,
@@ -27,6 +29,7 @@
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/dynamic_type_builder.dart';
+import '../builder/never_type_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
@@ -56,32 +59,17 @@
 
 import 'dill_type_alias_builder.dart' show DillTypeAliasBuilder;
 
-class LazyLibraryScope extends Scope {
+class LazyLibraryScope extends LazyScope {
   DillLibraryBuilder libraryBuilder;
 
-  LazyLibraryScope(Map<String, Builder> local, Map<String, Builder> setters,
-      Scope parent, String debugName, {bool isModifiable: true})
-      : super(
-            local: local,
-            setters: setters,
-            parent: parent,
-            debugName: debugName,
-            isModifiable: isModifiable);
-
   LazyLibraryScope.top({bool isModifiable: false})
-      : this(<String, Builder>{}, <String, Builder>{}, null, "top",
+      : super(<String, Builder>{}, <String, MemberBuilder>{}, null, "top",
             isModifiable: isModifiable);
 
-  Map<String, Builder> get local {
+  @override
+  void ensureScope() {
     if (libraryBuilder == null) throw new StateError("No library builder.");
     libraryBuilder.ensureLoaded();
-    return super.local;
-  }
-
-  Map<String, Builder> get setters {
-    if (libraryBuilder == null) throw new StateError("No library builder.");
-    libraryBuilder.ensureLoaded();
-    return super.setters;
   }
 }
 
@@ -158,6 +146,14 @@
         "dynamic", new DynamicTypeBuilder(const DynamicType(), this, -1), -1);
   }
 
+  void addSyntheticDeclarationOfNever() {
+    addBuilder(
+        "Never",
+        new NeverTypeBuilder(
+            const NeverType(Nullability.nonNullable), this, -1),
+        -1);
+  }
+
   void addClass(Class cls) {
     DillClassBuilder classBulder = new DillClassBuilder(cls, this);
     addBuilder(cls.name, classBulder, cls.fileOffset);
@@ -312,10 +308,11 @@
       }
       Builder declaration;
       if (isSetter) {
-        declaration = library.exportScope.setters[name];
+        declaration = library.exportScope.lookupLocalMember(name, setter: true);
         exportScopeBuilder.addSetter(name, declaration);
       } else {
-        declaration = library.exportScope.local[name];
+        declaration =
+            library.exportScope.lookupLocalMember(name, setter: false);
         exportScopeBuilder.addMember(name, declaration);
       }
       if (declaration == null) {
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 a6ac789..4e3f3ef 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
@@ -60,6 +60,9 @@
   }
 
   bool get isField => member is Field;
+
+  @override
+  bool get isAssignable => member is Field && member.hasSetter;
 }
 
 int computeModifiers(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes.dart b/pkg/front_end/lib/src/fasta/fasta_codes.dart
index 99f52bd..1d65728 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes.dart
@@ -4,271 +4,15 @@
 
 library fasta.codes;
 
-import 'dart:convert' show JsonEncoder, json;
+import 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    hide demangleMixinApplicationName;
 
 import 'package:kernel/ast.dart'
     show Constant, DartType, demangleMixinApplicationName;
 
-import '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
-
-import '../scanner/token.dart' show Token;
-
 import 'kernel/type_labeler.dart';
 
-import 'severity.dart' show Severity;
+export 'package:_fe_analyzer_shared/src/messages/codes.dart'
+    hide demangleMixinApplicationName;
 
-import 'resolve_input_uri.dart' show isWindows;
-
-import 'util/relativize.dart' as util show relativizeUri;
-
-part 'fasta_codes_generated.dart';
-
-const int noLength = 1;
-
-class Code<T> {
-  final String name;
-
-  /// The unique positive integer associated with this code,
-  /// or `-1` if none. This index is used when translating
-  /// this error to its corresponding Analyzer error.
-  final int index;
-
-  final Template<T> template;
-
-  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;
-
-  String toString() => name;
-}
-
-class Message {
-  final Code<dynamic> code;
-
-  final String message;
-
-  final String tip;
-
-  final Map<String, dynamic> arguments;
-
-  const Message(this.code, {this.message, this.tip, this.arguments});
-
-  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
-    return new LocatedMessage(uri, charOffset, length, this);
-  }
-
-  LocatedMessage withoutLocation() {
-    return new LocatedMessage(null, -1, noLength, this);
-  }
-
-  String toString() {
-    return "Message[$code, $message, $tip, $arguments]";
-  }
-}
-
-class MessageCode extends Code<Null> implements Message {
-  final String message;
-
-  final String tip;
-
-  const MessageCode(String name,
-      {int index,
-      List<String> analyzerCodes,
-      Severity severity: Severity.error,
-      this.message,
-      this.tip})
-      : super(name, null,
-            index: index, analyzerCodes: analyzerCodes, severity: severity);
-
-  Map<String, dynamic> get arguments => const <String, dynamic>{};
-
-  Code<dynamic> get code => this;
-
-  @override
-  LocatedMessage withLocation(Uri uri, int charOffset, int length) {
-    return new LocatedMessage(uri, charOffset, length, this);
-  }
-
-  LocatedMessage withoutLocation() {
-    return new LocatedMessage(null, -1, noLength, this);
-  }
-}
-
-class Template<T> {
-  final String messageTemplate;
-
-  final String tipTemplate;
-
-  final T withArguments;
-
-  const Template({this.messageTemplate, this.tipTemplate, this.withArguments});
-}
-
-class LocatedMessage implements Comparable<LocatedMessage> {
-  final Uri uri;
-
-  final int charOffset;
-
-  final int length;
-
-  final Message messageObject;
-
-  const LocatedMessage(
-      this.uri, this.charOffset, this.length, this.messageObject);
-
-  Code<dynamic> get code => messageObject.code;
-
-  String get message => messageObject.message;
-
-  String get tip => messageObject.tip;
-
-  Map<String, dynamic> get arguments => messageObject.arguments;
-
-  int compareTo(LocatedMessage other) {
-    int result = "${uri}".compareTo("${other.uri}");
-    if (result != 0) return result;
-    result = charOffset.compareTo(other.charOffset);
-    if (result != 0) return result;
-    return message.compareTo(message);
-  }
-
-  FormattedMessage withFormatting(String formatted, int line, int column,
-      Severity severity, List<FormattedMessage> relatedInformation) {
-    return new FormattedMessage(
-        this, formatted, line, column, severity, relatedInformation);
-  }
-}
-
-class FormattedMessage implements DiagnosticMessage {
-  final LocatedMessage locatedMessage;
-
-  final String formatted;
-
-  final int line;
-
-  final int column;
-
-  @override
-  final Severity severity;
-
-  final List<FormattedMessage> relatedInformation;
-
-  const FormattedMessage(this.locatedMessage, this.formatted, this.line,
-      this.column, this.severity, this.relatedInformation);
-
-  Code<dynamic> get code => locatedMessage.code;
-
-  String get message => locatedMessage.message;
-
-  String get tip => locatedMessage.tip;
-
-  Map<String, dynamic> get arguments => locatedMessage.arguments;
-
-  Uri get uri => locatedMessage.uri;
-
-  int get charOffset => locatedMessage.charOffset;
-
-  int get length => locatedMessage.length;
-
-  @override
-  Iterable<String> get ansiFormatted sync* {
-    yield formatted;
-    if (relatedInformation != null) {
-      for (FormattedMessage m in relatedInformation) {
-        yield m.formatted;
-      }
-    }
-  }
-
-  @override
-  Iterable<String> get plainTextFormatted {
-    // TODO(ahe): Implement this correctly.
-    return ansiFormatted;
-  }
-
-  Map<String, Object> toJson() {
-    // This should be kept in sync with package:kernel/problems.md
-    return <String, Object>{
-      "ansiFormatted": ansiFormatted.toList(),
-      "plainTextFormatted": plainTextFormatted.toList(),
-      "severity": severity.index,
-      "uri": uri.toString(),
-    };
-  }
-
-  String toJsonString() {
-    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
-    return encoder.convert(this);
-  }
-}
-
-class DiagnosticMessageFromJson implements DiagnosticMessage {
-  @override
-  final Iterable<String> ansiFormatted;
-
-  @override
-  final Iterable<String> plainTextFormatted;
-
-  @override
-  final Severity severity;
-
-  final Uri uri;
-
-  DiagnosticMessageFromJson(
-      this.ansiFormatted, this.plainTextFormatted, this.severity, this.uri);
-
-  factory DiagnosticMessageFromJson.fromJson(String jsonString) {
-    Map<String, Object> decoded = json.decode(jsonString);
-    List<String> ansiFormatted =
-        new List<String>.from(decoded["ansiFormatted"]);
-    List<String> plainTextFormatted =
-        new List<String>.from(decoded["plainTextFormatted"]);
-    Severity severity = Severity.values[decoded["severity"]];
-    Uri uri = Uri.parse(decoded["uri"]);
-
-    return new DiagnosticMessageFromJson(
-        ansiFormatted, plainTextFormatted, severity, uri);
-  }
-
-  Map<String, Object> toJson() {
-    // This should be kept in sync with package:kernel/problems.md
-    return <String, Object>{
-      "ansiFormatted": ansiFormatted.toList(),
-      "plainTextFormatted": plainTextFormatted.toList(),
-      "severity": severity.index,
-      "uri": uri.toString(),
-    };
-  }
-
-  String toJsonString() {
-    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
-    return encoder.convert(this);
-  }
-}
-
-String relativizeUri(Uri uri) {
-  // We have this method here for two reasons:
-  //
-  // 1. It allows us to implement #uri message argument without using it
-  // (otherwise, we might get an `UNUSED_IMPORT` warning).
-  //
-  // 2. We can change `base` argument here if needed.
-  return uri == null ? null : util.relativizeUri(Uri.base, uri, isWindows);
-}
-
-typedef SummaryTemplate = Message Function(int, int, num, num, num);
-
-String itemizeNames(List<String> names) {
-  StringBuffer buffer = new StringBuffer();
-  for (int i = 0; i < names.length - 1; i++) {
-    buffer.write(" - ");
-    buffer.writeln(names[i]);
-  }
-  buffer.write(" - ");
-  buffer.write(names.last);
-  return "$buffer";
-}
+part 'fasta_codes_cfe_generated.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
new file mode 100644
index 0000000..d9a60cb
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -0,0 +1,2189 @@
+// 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.
+
+// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
+//
+// Instead modify 'pkg/front_end/messages.yaml' and run
+// 'pkg/front_end/tool/fasta generate-messages' to update.
+
+// ignore_for_file: lines_longer_than_80_chars
+
+part of fasta.codes;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, DartType _type, DartType _type2)>
+    templateAmbiguousSupertypes = const Template<
+            Message Function(String name, DartType _type, DartType _type2)>(
+        messageTemplate:
+            r"""'#name' can't implement both '#type' and '#type2'""",
+        withArguments: _withArgumentsAmbiguousSupertypes);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+    codeAmbiguousSupertypes =
+    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+        "AmbiguousSupertypes", templateAmbiguousSupertypes,
+        analyzerCodes: <String>["AMBIGUOUS_SUPERTYPES"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsAmbiguousSupertypes(
+    String name, DartType _type, DartType _type2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeAmbiguousSupertypes,
+      message: """'${name}' can't implement both '${type}' and '${type2}'""" +
+          labeler.originMessages,
+      arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateArgumentTypeNotAssignable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The argument type '#type' can't be assigned to the parameter type '#type2'.""",
+    withArguments: _withArgumentsArgumentTypeNotAssignable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeArgumentTypeNotAssignable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "ArgumentTypeNotAssignable", templateArgumentTypeNotAssignable,
+        analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsArgumentTypeNotAssignable(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeArgumentTypeNotAssignable,
+      message:
+          """The argument type '${type}' can't be assigned to the parameter type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant
+            _constant)> templateConstEvalDuplicateElement = const Template<
+        Message Function(Constant _constant)>(
+    messageTemplate:
+        r"""The element '#constant' conflicts with another existing element in the set.""",
+    withArguments: _withArgumentsConstEvalDuplicateElement);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)> codeConstEvalDuplicateElement =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalDuplicateElement", templateConstEvalDuplicateElement,
+        analyzerCodes: <String>["EQUAL_ELEMENTS_IN_CONST_SET"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalDuplicateElement(Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalDuplicateElement,
+      message:
+          """The element '${constant}' conflicts with another existing element in the set.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant
+            _constant)> templateConstEvalDuplicateKey = const Template<
+        Message Function(Constant _constant)>(
+    messageTemplate:
+        r"""The key '#constant' conflicts with another existing key in the map.""",
+    withArguments: _withArgumentsConstEvalDuplicateKey);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)> codeConstEvalDuplicateKey =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalDuplicateKey", templateConstEvalDuplicateKey,
+        analyzerCodes: <String>["EQUAL_KEYS_IN_CONST_MAP"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalDuplicateKey(Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalDuplicateKey,
+      message:
+          """The key '${constant}' conflicts with another existing key in the map.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant
+            _constant)> templateConstEvalElementImplementsEqual = const Template<
+        Message Function(Constant _constant)>(
+    messageTemplate:
+        r"""The element '#constant' does not have a primitive operator '=='.""",
+    withArguments: _withArgumentsConstEvalElementImplementsEqual);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)>
+    codeConstEvalElementImplementsEqual =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalElementImplementsEqual",
+        templateConstEvalElementImplementsEqual,
+        analyzerCodes: <String>["CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalElementImplementsEqual(Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalElementImplementsEqual,
+      message:
+          """The element '${constant}' does not have a primitive operator '=='.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateConstEvalFreeTypeParameter = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""The type '#type' is not a constant because it depends on a type parameter, only instantiated types are allowed.""",
+    withArguments: _withArgumentsConstEvalFreeTypeParameter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeConstEvalFreeTypeParameter =
+    const Code<Message Function(DartType _type)>(
+  "ConstEvalFreeTypeParameter",
+  templateConstEvalFreeTypeParameter,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalFreeTypeParameter(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeConstEvalFreeTypeParameter,
+      message:
+          """The type '${type}' is not a constant because it depends on a type parameter, only instantiated types are allowed.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        Constant _constant,
+        DartType _type,
+        DartType
+            _type2)> templateConstEvalInvalidBinaryOperandType = const Template<
+        Message Function(String string, Constant _constant, DartType _type,
+            DartType _type2)>(
+    messageTemplate:
+        r"""Binary operator '#string' on '#constant' requires operand of type '#type', but was of type '#type2'.""",
+    withArguments: _withArgumentsConstEvalInvalidBinaryOperandType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+    Message Function(String string, Constant _constant, DartType _type,
+        DartType _type2)> codeConstEvalInvalidBinaryOperandType = const Code<
+    Message Function(
+        String string, Constant _constant, DartType _type, DartType _type2)>(
+  "ConstEvalInvalidBinaryOperandType",
+  templateConstEvalInvalidBinaryOperandType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidBinaryOperandType(
+    String string, Constant _constant, DartType _type, DartType _type2) {
+  if (string.isEmpty) throw 'No string provided';
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String constant = constantParts.join();
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeConstEvalInvalidBinaryOperandType,
+      message:
+          """Binary operator '${string}' on '${constant}' requires operand of type '${type}', but was of type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'string': string,
+        'constant': _constant,
+        'type': _type,
+        'type2': _type2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant _constant,
+        DartType
+            _type)> templateConstEvalInvalidEqualsOperandType = const Template<
+        Message Function(Constant _constant, DartType _type)>(
+    messageTemplate:
+        r"""Binary operator '==' requires receiver constant '#constant' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type '#type'.""",
+    withArguments: _withArgumentsConstEvalInvalidEqualsOperandType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant, DartType _type)>
+    codeConstEvalInvalidEqualsOperandType =
+    const Code<Message Function(Constant _constant, DartType _type)>(
+  "ConstEvalInvalidEqualsOperandType",
+  templateConstEvalInvalidEqualsOperandType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidEqualsOperandType(
+    Constant _constant, DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  List<Object> typeParts = labeler.labelType(_type);
+  String constant = constantParts.join();
+  String type = typeParts.join();
+  return new Message(codeConstEvalInvalidEqualsOperandType,
+      message:
+          """Binary operator '==' requires receiver constant '${constant}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type '${type}'.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant, 'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        Constant
+            _constant)> templateConstEvalInvalidMethodInvocation = const Template<
+        Message Function(String string, Constant _constant)>(
+    messageTemplate:
+        r"""The method '#string' can't be invoked on '#constant' in a constant expression.""",
+    withArguments: _withArgumentsConstEvalInvalidMethodInvocation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, Constant _constant)>
+    codeConstEvalInvalidMethodInvocation =
+    const Code<Message Function(String string, Constant _constant)>(
+        "ConstEvalInvalidMethodInvocation",
+        templateConstEvalInvalidMethodInvocation,
+        analyzerCodes: <String>["UNDEFINED_OPERATOR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidMethodInvocation(
+    String string, Constant _constant) {
+  if (string.isEmpty) throw 'No string provided';
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalInvalidMethodInvocation,
+      message:
+          """The method '${string}' can't be invoked on '${constant}' in a constant expression.""" +
+              labeler.originMessages,
+      arguments: {'string': string, 'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        Constant
+            _constant)> templateConstEvalInvalidPropertyGet = const Template<
+        Message Function(String string, Constant _constant)>(
+    messageTemplate:
+        r"""The property '#string' can't be accessed on '#constant' in a constant expression.""",
+    withArguments: _withArgumentsConstEvalInvalidPropertyGet);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, Constant _constant)>
+    codeConstEvalInvalidPropertyGet =
+    const Code<Message Function(String string, Constant _constant)>(
+        "ConstEvalInvalidPropertyGet", templateConstEvalInvalidPropertyGet,
+        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidPropertyGet(
+    String string, Constant _constant) {
+  if (string.isEmpty) throw 'No string provided';
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalInvalidPropertyGet,
+      message:
+          """The property '${string}' can't be accessed on '${constant}' in a constant expression.""" +
+              labeler.originMessages,
+      arguments: {'string': string, 'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Constant _constant)>
+    templateConstEvalInvalidStringInterpolationOperand =
+    const Template<Message Function(Constant _constant)>(
+        messageTemplate:
+            r"""The constant value '#constant' can't be used as part of a string interpolation in a constant expression.
+Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""",
+        withArguments:
+            _withArgumentsConstEvalInvalidStringInterpolationOperand);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)>
+    codeConstEvalInvalidStringInterpolationOperand =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalInvalidStringInterpolationOperand",
+        templateConstEvalInvalidStringInterpolationOperand,
+        analyzerCodes: <String>["CONST_EVAL_TYPE_BOOL_NUM_STRING"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidStringInterpolationOperand(
+    Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalInvalidStringInterpolationOperand,
+      message:
+          """The constant value '${constant}' can't be used as part of a string interpolation in a constant expression.
+Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant
+            _constant)> templateConstEvalInvalidSymbolName = const Template<
+        Message Function(Constant _constant)>(
+    messageTemplate:
+        r"""The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '#constant'.""",
+    withArguments: _withArgumentsConstEvalInvalidSymbolName);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)>
+    codeConstEvalInvalidSymbolName =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalInvalidSymbolName", templateConstEvalInvalidSymbolName,
+        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidSymbolName(Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalInvalidSymbolName,
+      message:
+          """The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '${constant}'.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Constant _constant,
+        DartType _type,
+        DartType
+            _type2)> templateConstEvalInvalidType = const Template<
+        Message Function(Constant _constant, DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Expected constant '#constant' to be of type '#type', but was of type '#type2'.""",
+    withArguments: _withArgumentsConstEvalInvalidType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(Constant _constant, DartType _type, DartType _type2)>
+    codeConstEvalInvalidType = const Code<
+        Message Function(Constant _constant, DartType _type, DartType _type2)>(
+  "ConstEvalInvalidType",
+  templateConstEvalInvalidType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalInvalidType(
+    Constant _constant, DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String constant = constantParts.join();
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeConstEvalInvalidType,
+      message:
+          """Expected constant '${constant}' to be of type '${type}', but was of type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(Constant _constant)>
+    templateConstEvalKeyImplementsEqual =
+    const Template<Message Function(Constant _constant)>(
+        messageTemplate:
+            r"""The key '#constant' does not have a primitive operator '=='.""",
+        withArguments: _withArgumentsConstEvalKeyImplementsEqual);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Constant _constant)>
+    codeConstEvalKeyImplementsEqual =
+    const Code<Message Function(Constant _constant)>(
+        "ConstEvalKeyImplementsEqual", templateConstEvalKeyImplementsEqual,
+        analyzerCodes: <String>[
+      "CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstEvalKeyImplementsEqual(Constant _constant) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> constantParts = labeler.labelConstant(_constant);
+  String constant = constantParts.join();
+  return new Message(codeConstEvalKeyImplementsEqual,
+      message:
+          """The key '${constant}' does not have a primitive operator '=='.""" +
+              labeler.originMessages,
+      arguments: {'constant': _constant});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        String
+            name)> templateDeferredTypeAnnotation = const Template<
+        Message Function(DartType _type, String name)>(
+    messageTemplate:
+        r"""The type '#type' is deferred loaded via prefix '#name' and can't be used as a type annotation.""",
+    tipTemplate:
+        r"""Try removing 'deferred' from the import of '#name' or use a supertype of '#type' that isn't deferred.""",
+    withArguments: _withArgumentsDeferredTypeAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, String name)>
+    codeDeferredTypeAnnotation =
+    const Code<Message Function(DartType _type, String name)>(
+        "DeferredTypeAnnotation", templateDeferredTypeAnnotation,
+        analyzerCodes: <String>["TYPE_ANNOTATION_DEFERRED_CLASS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsDeferredTypeAnnotation(DartType _type, String name) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  String type = typeParts.join();
+  return new Message(codeDeferredTypeAnnotation,
+      message:
+          """The type '${type}' is deferred loaded via prefix '${name}' and can't be used as a type annotation.""" +
+              labeler.originMessages,
+      tip: """Try removing 'deferred' from the import of '${name}' or use a supertype of '${type}' that isn't deferred.""",
+      arguments: {'type': _type, 'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, DartType _type2)>
+    templateFfiDartTypeMismatch =
+    const Template<Message Function(DartType _type, DartType _type2)>(
+        messageTemplate: r"""Expected '#type' to be a subtype of '#type2'.""",
+        withArguments: _withArgumentsFfiDartTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeFfiDartTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+  "FfiDartTypeMismatch",
+  templateFfiDartTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiDartTypeMismatch(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeFfiDartTypeMismatch,
+      message: """Expected '${type}' to be a subtype of '${type2}'.""" +
+          labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateFfiExpectedExceptionalReturn = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Expected an exceptional return value for a native callback returning '#type'.""",
+    withArguments: _withArgumentsFfiExpectedExceptionalReturn);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeFfiExpectedExceptionalReturn =
+    const Code<Message Function(DartType _type)>(
+  "FfiExpectedExceptionalReturn",
+  templateFfiExpectedExceptionalReturn,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiExpectedExceptionalReturn(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeFfiExpectedExceptionalReturn,
+      message:
+          """Expected an exceptional return value for a native callback returning '${type}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateFfiExpectedNoExceptionalReturn = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Exceptional return value cannot be provided for a native callback returning '#type'.""",
+    withArguments: _withArgumentsFfiExpectedNoExceptionalReturn);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)>
+    codeFfiExpectedNoExceptionalReturn =
+    const Code<Message Function(DartType _type)>(
+  "FfiExpectedNoExceptionalReturn",
+  templateFfiExpectedNoExceptionalReturn,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiExpectedNoExceptionalReturn(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeFfiExpectedNoExceptionalReturn,
+      message:
+          """Exceptional return value cannot be provided for a native callback returning '${type}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(DartType _type)> templateFfiTypeInvalid = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Expected type '#type' to be a valid and instantiated subtype of 'NativeType'.""",
+    withArguments: _withArgumentsFfiTypeInvalid);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeFfiTypeInvalid =
+    const Code<Message Function(DartType _type)>(
+  "FfiTypeInvalid",
+  templateFfiTypeInvalid,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiTypeInvalid(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeFfiTypeInvalid,
+      message:
+          """Expected type '${type}' to be a valid and instantiated subtype of 'NativeType'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        DartType
+            _type3)> templateFfiTypeMismatch = const Template<
+        Message Function(DartType _type, DartType _type2, DartType _type3)>(
+    messageTemplate:
+        r"""Expected type '#type' to be '#type2', which is the Dart type corresponding to '#type3'.""",
+    withArguments: _withArgumentsFfiTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2, DartType _type3)>
+    codeFfiTypeMismatch = const Code<
+        Message Function(DartType _type, DartType _type2, DartType _type3)>(
+  "FfiTypeMismatch",
+  templateFfiTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiTypeMismatch(
+    DartType _type, DartType _type2, DartType _type3) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  List<Object> type3Parts = labeler.labelType(_type3);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  String type3 = type3Parts.join();
+  return new Message(codeFfiTypeMismatch,
+      message:
+          """Expected type '${type}' to be '${type2}', which is the Dart type corresponding to '${type3}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2, 'type3': _type3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateForInLoopElementTypeNotAssignable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""A value of type '#type' can't be assigned to a variable of type '#type2'.""",
+    tipTemplate: r"""Try changing the type of the variable.""",
+    withArguments: _withArgumentsForInLoopElementTypeNotAssignable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeForInLoopElementTypeNotAssignable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "ForInLoopElementTypeNotAssignable",
+        templateForInLoopElementTypeNotAssignable,
+        analyzerCodes: <String>["FOR_IN_OF_INVALID_ELEMENT_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsForInLoopElementTypeNotAssignable(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeForInLoopElementTypeNotAssignable,
+      message:
+          """A value of type '${type}' can't be assigned to a variable of type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Try changing the type of the variable.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateForInLoopTypeNotIterable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The type '#type' used in the 'for' loop must implement '#type2'.""",
+    withArguments: _withArgumentsForInLoopTypeNotIterable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeForInLoopTypeNotIterable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "ForInLoopTypeNotIterable", templateForInLoopTypeNotIterable,
+        analyzerCodes: <String>["FOR_IN_OF_INVALID_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsForInLoopTypeNotIterable(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeForInLoopTypeNotIterable,
+      message:
+          """The type '${type}' used in the 'for' loop must implement '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type)>
+    templateGenericFunctionTypeInferredAsActualTypeArgument =
+    const Template<Message Function(DartType _type)>(
+        messageTemplate:
+            r"""Generic function type '#type' inferred as a type argument.""",
+        tipTemplate:
+            r"""Try providing a non-generic function type explicitly.""",
+        withArguments:
+            _withArgumentsGenericFunctionTypeInferredAsActualTypeArgument);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)>
+    codeGenericFunctionTypeInferredAsActualTypeArgument =
+    const Code<Message Function(DartType _type)>(
+        "GenericFunctionTypeInferredAsActualTypeArgument",
+        templateGenericFunctionTypeInferredAsActualTypeArgument,
+        analyzerCodes: <String>["GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsGenericFunctionTypeInferredAsActualTypeArgument(
+    DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeGenericFunctionTypeInferredAsActualTypeArgument,
+      message:
+          """Generic function type '${type}' inferred as a type argument.""" +
+              labeler.originMessages,
+      tip: """Try providing a non-generic function type explicitly.""",
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type)> templateIllegalRecursiveType =
+    const Template<Message Function(DartType _type)>(
+        messageTemplate: r"""Illegal recursive type '#type'.""",
+        withArguments: _withArgumentsIllegalRecursiveType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeIllegalRecursiveType =
+    const Code<Message Function(DartType _type)>(
+  "IllegalRecursiveType",
+  templateIllegalRecursiveType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIllegalRecursiveType(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeIllegalRecursiveType,
+      message: """Illegal recursive type '${type}'.""" + labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateImplicitCallOfNonMethod = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Cannot invoke an instance of '#type' because it declares 'call' to be something other than a method.""",
+    tipTemplate:
+        r"""Try changing 'call' to a method or explicitly invoke 'call'.""",
+    withArguments: _withArgumentsImplicitCallOfNonMethod);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeImplicitCallOfNonMethod =
+    const Code<Message Function(DartType _type)>(
+        "ImplicitCallOfNonMethod", templateImplicitCallOfNonMethod,
+        analyzerCodes: <String>["IMPLICIT_CALL_OF_NON_METHOD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsImplicitCallOfNonMethod(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeImplicitCallOfNonMethod,
+      message:
+          """Cannot invoke an instance of '${type}' because it declares 'call' to be something other than a method.""" +
+              labeler.originMessages,
+      tip: """Try changing 'call' to a method or explicitly invoke 'call'.""",
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateIncompatibleRedirecteeFunctionType = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The constructor function type '#type' isn't a subtype of '#type2'.""",
+    withArguments: _withArgumentsIncompatibleRedirecteeFunctionType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeIncompatibleRedirecteeFunctionType =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "IncompatibleRedirecteeFunctionType",
+        templateIncompatibleRedirecteeFunctionType,
+        analyzerCodes: <String>["REDIRECT_TO_INVALID_TYPE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncompatibleRedirecteeFunctionType(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncompatibleRedirecteeFunctionType,
+      message:
+          """The constructor function type '${type}' isn't a subtype of '${type2}'.""" +
+              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,
+        String name,
+        String
+            name2)> templateIncorrectTypeArgument = const Template<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>(
+    messageTemplate:
+        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2'.""",
+    tipTemplate:
+        r"""Try changing type arguments so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgument);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>
+    codeIncorrectTypeArgument = const Code<
+            Message Function(
+                DartType _type, DartType _type2, String name, String name2)>(
+        "IncorrectTypeArgument", templateIncorrectTypeArgument,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgument(
+    DartType _type, DartType _type2, String name, String name2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncorrectTypeArgument,
+      message:
+          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}'.""" +
+              labeler.originMessages,
+      tip: """Try changing type arguments so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        String
+            name2)> templateIncorrectTypeArgumentInReturnType = const Template<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>(
+    messageTemplate:
+        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the return type.""",
+    tipTemplate:
+        r"""Try changing type arguments so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentInReturnType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>
+    codeIncorrectTypeArgumentInReturnType = const Code<
+            Message Function(
+                DartType _type, DartType _type2, String name, String name2)>(
+        "IncorrectTypeArgumentInReturnType",
+        templateIncorrectTypeArgumentInReturnType,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInReturnType(
+    DartType _type, DartType _type2, String name, String name2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncorrectTypeArgumentInReturnType,
+      message:
+          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the return type.""" +
+              labeler.originMessages,
+      tip: """Try changing type arguments so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        String name2,
+        String name3,
+        String
+            name4)> templateIncorrectTypeArgumentInSupertype = const Template<
+        Message Function(DartType _type, DartType _type2, String name,
+            String name2, String name3, String name4)>(
+    messageTemplate:
+        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the supertype '#name3' of class '#name4'.""",
+    tipTemplate:
+        r"""Try changing type arguments so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentInSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, DartType _type2, String name,
+            String name2, String name3, String name4)>
+    codeIncorrectTypeArgumentInSupertype = const Code<
+            Message Function(DartType _type, DartType _type2, String name,
+                String name2, String name3, String name4)>(
+        "IncorrectTypeArgumentInSupertype",
+        templateIncorrectTypeArgumentInSupertype,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInSupertype(DartType _type,
+    DartType _type2, String name, String name2, String name3, String name4) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  if (name4.isEmpty) throw 'No name provided';
+  name4 = demangleMixinApplicationName(name4);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncorrectTypeArgumentInSupertype,
+      message:
+          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the supertype '${name3}' of class '${name4}'.""" +
+              labeler.originMessages,
+      tip:
+          """Try changing type arguments so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'name2': name2,
+        'name3': name3,
+        'name4': name4
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        String name2,
+        String name3,
+        String
+            name4)> templateIncorrectTypeArgumentInSupertypeInferred = const Template<
+        Message Function(
+            DartType _type,
+            DartType _type2,
+            String name,
+            String name2,
+            String name3,
+            String
+                name4)>(
+    messageTemplate:
+        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the supertype '#name3' of class '#name4'.""",
+    tipTemplate:
+        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentInSupertypeInferred);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, DartType _type2, String name,
+            String name2, String name3, String name4)>
+    codeIncorrectTypeArgumentInSupertypeInferred = const Code<
+            Message Function(DartType _type, DartType _type2, String name,
+                String name2, String name3, String name4)>(
+        "IncorrectTypeArgumentInSupertypeInferred",
+        templateIncorrectTypeArgumentInSupertypeInferred,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInSupertypeInferred(DartType _type,
+    DartType _type2, String name, String name2, String name3, String name4) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  if (name4.isEmpty) throw 'No name provided';
+  name4 = demangleMixinApplicationName(name4);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncorrectTypeArgumentInSupertypeInferred,
+      message:
+          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the supertype '${name3}' of class '${name4}'.""" +
+              labeler.originMessages,
+      tip:
+          """Try specifying type arguments explicitly so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'name2': name2,
+        'name3': name3,
+        'name4': name4
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        String
+            name2)> templateIncorrectTypeArgumentInferred = const Template<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>(
+    messageTemplate:
+        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2'.""",
+    tipTemplate:
+        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentInferred);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, String name, String name2)>
+    codeIncorrectTypeArgumentInferred = const Code<
+            Message Function(
+                DartType _type, DartType _type2, String name, String name2)>(
+        "IncorrectTypeArgumentInferred", templateIncorrectTypeArgumentInferred,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentInferred(
+    DartType _type, DartType _type2, String name, String name2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIncorrectTypeArgumentInferred,
+      message:
+          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}'.""" +
+              labeler.originMessages,
+      tip: """Try specifying type arguments explicitly so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        DartType _type3,
+        String
+            name2)> templateIncorrectTypeArgumentQualified = const Template<
+        Message Function(
+            DartType _type,
+            DartType _type2,
+            String name,
+            DartType _type3,
+            String
+                name2)>(
+    messageTemplate:
+        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3.#name2'.""",
+    tipTemplate:
+        r"""Try changing type arguments so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentQualified);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, DartType _type2, String name,
+            DartType _type3, String name2)> codeIncorrectTypeArgumentQualified =
+    const Code<
+            Message Function(DartType _type, DartType _type2, String name,
+                DartType _type3, String name2)>(
+        "IncorrectTypeArgumentQualified",
+        templateIncorrectTypeArgumentQualified,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentQualified(DartType _type,
+    DartType _type2, String name, DartType _type3, String name2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type3Parts = labeler.labelType(_type3);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  String type3 = type3Parts.join();
+  return new Message(codeIncorrectTypeArgumentQualified,
+      message:
+          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}.${name2}'.""" +
+              labeler.originMessages,
+      tip: """Try changing type arguments so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'type3': _type3,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType _type2,
+        String name,
+        DartType _type3,
+        String
+            name2)> templateIncorrectTypeArgumentQualifiedInferred = const Template<
+        Message Function(DartType _type, DartType _type2, String name,
+            DartType _type3, String name2)>(
+    messageTemplate:
+        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3.#name2'.""",
+    tipTemplate:
+        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
+    withArguments: _withArgumentsIncorrectTypeArgumentQualifiedInferred);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, DartType _type2, String name,
+            DartType _type3, String name2)>
+    codeIncorrectTypeArgumentQualifiedInferred = const Code<
+            Message Function(DartType _type, DartType _type2, String name,
+                DartType _type3, String name2)>(
+        "IncorrectTypeArgumentQualifiedInferred",
+        templateIncorrectTypeArgumentQualifiedInferred,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIncorrectTypeArgumentQualifiedInferred(DartType _type,
+    DartType _type2, String name, DartType _type3, String name2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type3Parts = labeler.labelType(_type3);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  String type3 = type3Parts.join();
+  return new Message(codeIncorrectTypeArgumentQualifiedInferred,
+      message:
+          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}.${name2}'.""" +
+              labeler.originMessages,
+      tip: """Try specifying type arguments explicitly so that they conform to the bounds.""",
+      arguments: {
+        'type': _type,
+        'type2': _type2,
+        'name': name,
+        'type3': _type3,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType
+            _type2)> templateInitializingFormalTypeMismatch = const Template<
+        Message Function(String name, DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The type of parameter '#name', '#type' is not a subtype of the corresponding field's type, '#type2'.""",
+    tipTemplate:
+        r"""Try changing the type of parameter '#name' to a subtype of '#type2'.""",
+    withArguments: _withArgumentsInitializingFormalTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+    codeInitializingFormalTypeMismatch =
+    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+        "InitializingFormalTypeMismatch",
+        templateInitializingFormalTypeMismatch,
+        analyzerCodes: <String>["INVALID_PARAMETER_DECLARATION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInitializingFormalTypeMismatch(
+    String name, DartType _type, DartType _type2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInitializingFormalTypeMismatch,
+      message:
+          """The type of parameter '${name}', '${type}' is not a subtype of the corresponding field's type, '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Try changing the type of parameter '${name}' to a subtype of '${type2}'.""",
+      arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType
+            _type2)> templateIntersectionTypeAsTypeArgument = const Template<
+        Message Function(String name, DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Can't infer a type for '#name', it can be either '#type' or '#type2'.""",
+    tipTemplate:
+        r"""Try adding a type argument selecting one of the options.""",
+    withArguments: _withArgumentsIntersectionTypeAsTypeArgument);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type, DartType _type2)>
+    codeIntersectionTypeAsTypeArgument =
+    const Code<Message Function(String name, DartType _type, DartType _type2)>(
+  "IntersectionTypeAsTypeArgument",
+  templateIntersectionTypeAsTypeArgument,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsIntersectionTypeAsTypeArgument(
+    String name, DartType _type, DartType _type2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeIntersectionTypeAsTypeArgument,
+      message:
+          """Can't infer a type for '${name}', it can be either '${type}' or '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Try adding a type argument selecting one of the options.""",
+      arguments: {'name': name, 'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidAssignment = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""A value of type '#type' can't be assigned to a variable of type '#type2'.""",
+    withArguments: _withArgumentsInvalidAssignment);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidAssignment =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidAssignment", templateInvalidAssignment,
+        analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidAssignment(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidAssignment,
+      message:
+          """A value of type '${type}' can't be assigned to a variable of type '${type2}'.""" +
+              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)> templateInvalidCastFunctionExpr = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The function expression type '#type' isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the function expression or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastFunctionExpr);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastFunctionExpr =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastFunctionExpr", templateInvalidCastFunctionExpr,
+        analyzerCodes: <String>["INVALID_CAST_FUNCTION_EXPR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastFunctionExpr(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastFunctionExpr,
+      message:
+          """The function expression type '${type}' isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the function expression or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastLiteralList = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The list literal type '#type' isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the list literal or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastLiteralList);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastLiteralList =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastLiteralList", templateInvalidCastLiteralList,
+        analyzerCodes: <String>["INVALID_CAST_LITERAL_LIST"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastLiteralList(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastLiteralList,
+      message:
+          """The list literal type '${type}' isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the list literal or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastLiteralMap = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The map literal type '#type' isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the map literal or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastLiteralMap);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastLiteralMap =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastLiteralMap", templateInvalidCastLiteralMap,
+        analyzerCodes: <String>["INVALID_CAST_LITERAL_MAP"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastLiteralMap(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastLiteralMap,
+      message:
+          """The map literal type '${type}' isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the map literal or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastLiteralSet = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The set literal type '#type' isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the set literal or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastLiteralSet);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastLiteralSet =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastLiteralSet", templateInvalidCastLiteralSet,
+        analyzerCodes: <String>["INVALID_CAST_LITERAL_SET"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastLiteralSet(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastLiteralSet,
+      message:
+          """The set literal type '${type}' isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the set literal or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastLocalFunction = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The local function has type '#type' that isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the function or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastLocalFunction);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastLocalFunction =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastLocalFunction", templateInvalidCastLocalFunction,
+        analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastLocalFunction(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastLocalFunction,
+      message:
+          """The local function has type '${type}' that isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the function or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastNewExpr = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The constructor returns type '#type' that isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the object being constructed or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastNewExpr);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastNewExpr =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastNewExpr", templateInvalidCastNewExpr,
+        analyzerCodes: <String>["INVALID_CAST_NEW_EXPR"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastNewExpr(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastNewExpr,
+      message:
+          """The constructor returns type '${type}' that isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the object being constructed or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastStaticMethod = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The static method has type '#type' that isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the method or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastStaticMethod);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastStaticMethod =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastStaticMethod", templateInvalidCastStaticMethod,
+        analyzerCodes: <String>["INVALID_CAST_METHOD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastStaticMethod(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastStaticMethod,
+      message:
+          """The static method has type '${type}' that isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the method or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateInvalidCastTopLevelFunction = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The top level function has type '#type' that isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the function or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastTopLevelFunction);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastTopLevelFunction =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastTopLevelFunction", templateInvalidCastTopLevelFunction,
+        analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastTopLevelFunction(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastTopLevelFunction,
+      message:
+          """The top level function has type '${type}' that isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the function or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, DartType _type2, DartType _type3)>
+    templateMixinApplicationIncompatibleSupertype = const Template<
+            Message Function(DartType _type, DartType _type2, DartType _type3)>(
+        messageTemplate:
+            r"""'#type' doesn't implement '#type2' so it can't be used with '#type3'.""",
+        withArguments: _withArgumentsMixinApplicationIncompatibleSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2, DartType _type3)>
+    codeMixinApplicationIncompatibleSupertype = const Code<
+            Message Function(DartType _type, DartType _type2, DartType _type3)>(
+        "MixinApplicationIncompatibleSupertype",
+        templateMixinApplicationIncompatibleSupertype,
+        analyzerCodes: <String>["MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMixinApplicationIncompatibleSupertype(
+    DartType _type, DartType _type2, DartType _type3) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  List<Object> type3Parts = labeler.labelType(_type3);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  String type3 = type3Parts.join();
+  return new Message(codeMixinApplicationIncompatibleSupertype,
+      message:
+          """'${type}' doesn't implement '${type2}' so it can't be used with '${type3}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2, 'type3': _type3});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String name2,
+        DartType
+            _type)> templateMixinInferenceNoMatchingClass = const Template<
+        Message Function(String name, String name2, DartType _type)>(
+    messageTemplate:
+        r"""Type parameters could not be inferred for the mixin '#name' because '#name2' does not implement the mixin's supertype constraint '#type'.""",
+    withArguments: _withArgumentsMixinInferenceNoMatchingClass);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2, DartType _type)>
+    codeMixinInferenceNoMatchingClass =
+    const Code<Message Function(String name, String name2, DartType _type)>(
+        "MixinInferenceNoMatchingClass", templateMixinInferenceNoMatchingClass,
+        analyzerCodes: <String>["MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMixinInferenceNoMatchingClass(
+    String name, String name2, DartType _type) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeMixinInferenceNoMatchingClass,
+      message:
+          """Type parameters could not be inferred for the mixin '${name}' because '${name2}' does not implement the mixin's supertype constraint '${type}'.""" +
+              labeler.originMessages,
+      arguments: {'name': name, 'name2': name2, 'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        String name2,
+        DartType _type,
+        DartType _type2,
+        String
+            name3)> templateOverrideTypeMismatchParameter = const Template<
+        Message Function(
+            String name,
+            String name2,
+            DartType _type,
+            DartType _type2,
+            String
+                name3)>(
+    messageTemplate:
+        r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'.""",
+    tipTemplate:
+        r"""Change to a supertype of '#type2', or, for a covariant parameter, a subtype.""",
+    withArguments: _withArgumentsOverrideTypeMismatchParameter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(String name, String name2, DartType _type,
+            DartType _type2, String name3)> codeOverrideTypeMismatchParameter =
+    const Code<
+            Message Function(String name, String name2, DartType _type,
+                DartType _type2, String name3)>(
+        "OverrideTypeMismatchParameter", templateOverrideTypeMismatchParameter,
+        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideTypeMismatchParameter(
+    String name, String name2, DartType _type, DartType _type2, String name3) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name3.isEmpty) throw 'No name provided';
+  name3 = demangleMixinApplicationName(name3);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeOverrideTypeMismatchParameter,
+      message:
+          """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden method, '${name3}'.""" +
+              labeler.originMessages,
+      tip: """Change to a supertype of '${type2}', or, for a covariant parameter, a subtype.""",
+      arguments: {
+        'name': name,
+        'name2': name2,
+        'type': _type,
+        'type2': _type2,
+        'name3': name3
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType _type2,
+        String
+            name2)> templateOverrideTypeMismatchReturnType = const Template<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>(
+    messageTemplate:
+        r"""The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'.""",
+    tipTemplate: r"""Change to a subtype of '#type2'.""",
+    withArguments: _withArgumentsOverrideTypeMismatchReturnType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>
+    codeOverrideTypeMismatchReturnType = const Code<
+            Message Function(
+                String name, DartType _type, DartType _type2, String name2)>(
+        "OverrideTypeMismatchReturnType",
+        templateOverrideTypeMismatchReturnType,
+        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideTypeMismatchReturnType(
+    String name, DartType _type, DartType _type2, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeOverrideTypeMismatchReturnType,
+      message:
+          """The return type of the method '${name}' is '${type}', which does not match the return type, '${type2}', of the overridden method, '${name2}'.""" +
+              labeler.originMessages,
+      tip: """Change to a subtype of '${type2}'.""",
+      arguments: {
+        'name': name,
+        'type': _type,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType _type,
+        DartType _type2,
+        String
+            name2)> templateOverrideTypeMismatchSetter = const Template<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>(
+    messageTemplate:
+        r"""The field '#name' has type '#type', which does not match the corresponding type, '#type2', in the overridden setter, '#name2'.""",
+    withArguments: _withArgumentsOverrideTypeMismatchSetter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            String name, DartType _type, DartType _type2, String name2)>
+    codeOverrideTypeMismatchSetter = const Code<
+            Message Function(
+                String name, DartType _type, DartType _type2, String name2)>(
+        "OverrideTypeMismatchSetter", templateOverrideTypeMismatchSetter,
+        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsOverrideTypeMismatchSetter(
+    String name, DartType _type, DartType _type2, String name2) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeOverrideTypeMismatchSetter,
+      message:
+          """The field '${name}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden setter, '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'name': name,
+        'type': _type,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(DartType _type, DartType _type2)>
+    templateRedirectingFactoryIncompatibleTypeArgument =
+    const Template<Message Function(DartType _type, DartType _type2)>(
+        messageTemplate: r"""The type '#type' doesn't extend '#type2'.""",
+        tipTemplate: r"""Try using a different type as argument.""",
+        withArguments:
+            _withArgumentsRedirectingFactoryIncompatibleTypeArgument);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeRedirectingFactoryIncompatibleTypeArgument =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "RedirectingFactoryIncompatibleTypeArgument",
+        templateRedirectingFactoryIncompatibleTypeArgument,
+        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsRedirectingFactoryIncompatibleTypeArgument(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeRedirectingFactoryIncompatibleTypeArgument,
+      message: """The type '${type}' doesn't extend '${type2}'.""" +
+          labeler.originMessages,
+      tip: """Try using a different type as argument.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateSpreadElementTypeMismatch = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Can't assign spread elements of type '#type' to collection elements of type '#type2'.""",
+    withArguments: _withArgumentsSpreadElementTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSpreadElementTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SpreadElementTypeMismatch", templateSpreadElementTypeMismatch,
+        analyzerCodes: <String>["LIST_ELEMENT_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadElementTypeMismatch(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSpreadElementTypeMismatch,
+      message:
+          """Can't assign spread elements of type '${type}' to collection elements of type '${type2}'.""" +
+              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)> templateSpreadMapEntryElementKeyTypeMismatch = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'.""",
+    withArguments: _withArgumentsSpreadMapEntryElementKeyTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSpreadMapEntryElementKeyTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SpreadMapEntryElementKeyTypeMismatch",
+        templateSpreadMapEntryElementKeyTypeMismatch,
+        analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementKeyTypeMismatch(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSpreadMapEntryElementKeyTypeMismatch,
+      message:
+          """Can't assign spread entry keys of type '${type}' to map entry keys of type '${type2}'.""" +
+              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)>
+    templateSpreadMapEntryElementValueTypeMismatch =
+    const Template<Message Function(DartType _type, DartType _type2)>(
+        messageTemplate:
+            r"""Can't assign spread entry values of type '#type' to map entry values of type '#type2'.""",
+        withArguments: _withArgumentsSpreadMapEntryElementValueTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSpreadMapEntryElementValueTypeMismatch =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SpreadMapEntryElementValueTypeMismatch",
+        templateSpreadMapEntryElementValueTypeMismatch,
+        analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryElementValueTypeMismatch(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSpreadMapEntryElementValueTypeMismatch,
+      message:
+          """Can't assign spread entry values of type '${type}' to map entry values of type '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateSpreadMapEntryTypeMismatch = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Unexpected type '#type' of a map spread entry.  Expected 'dynamic' or a Map.""",
+    withArguments: _withArgumentsSpreadMapEntryTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeSpreadMapEntryTypeMismatch =
+    const Code<Message Function(DartType _type)>(
+  "SpreadMapEntryTypeMismatch",
+  templateSpreadMapEntryTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadMapEntryTypeMismatch(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeSpreadMapEntryTypeMismatch,
+      message:
+          """Unexpected type '${type}' of a map spread entry.  Expected 'dynamic' or a Map.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType
+            _type)> templateSpreadTypeMismatch = const Template<
+        Message Function(DartType _type)>(
+    messageTemplate:
+        r"""Unexpected type '#type' of a spread.  Expected 'dynamic' or an Iterable.""",
+    withArguments: _withArgumentsSpreadTypeMismatch);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type)> codeSpreadTypeMismatch =
+    const Code<Message Function(DartType _type)>(
+  "SpreadTypeMismatch",
+  templateSpreadTypeMismatch,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSpreadTypeMismatch(DartType _type) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeSpreadTypeMismatch,
+      message:
+          """Unexpected type '${type}' of a spread.  Expected 'dynamic' or an Iterable.""" +
+              labeler.originMessages,
+      arguments: {'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
+            _type2)> templateSwitchExpressionNotAssignable = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""Type '#type' of the switch expression isn't assignable to the type '#type2' of this case expression.""",
+    withArguments: _withArgumentsSwitchExpressionNotAssignable);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeSwitchExpressionNotAssignable =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "SwitchExpressionNotAssignable", templateSwitchExpressionNotAssignable,
+        analyzerCodes: <String>["SWITCH_EXPRESSION_NOT_ASSIGNABLE"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsSwitchExpressionNotAssignable(
+    DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeSwitchExpressionNotAssignable,
+      message:
+          """Type '${type}' of the switch expression isn't assignable to the type '${type2}' of this case expression.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType
+            _type)> templateUndefinedGetter = const Template<
+        Message Function(String name, DartType _type)>(
+    messageTemplate:
+        r"""The getter '#name' isn't defined for the class '#type'.""",
+    tipTemplate:
+        r"""Try correcting the name to the name of an existing getter, or defining a getter or field named '#name'.""",
+    withArguments: _withArgumentsUndefinedGetter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type)> codeUndefinedGetter =
+    const Code<Message Function(String name, DartType _type)>(
+        "UndefinedGetter", templateUndefinedGetter,
+        analyzerCodes: <String>["UNDEFINED_GETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUndefinedGetter(String name, DartType _type) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeUndefinedGetter,
+      message:
+          """The getter '${name}' isn't defined for the class '${type}'.""" +
+              labeler.originMessages,
+      tip:
+          """Try correcting the name to the name of an existing getter, or defining a getter or field named '${name}'.""",
+      arguments: {'name': name, 'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType
+            _type)> templateUndefinedMethod = const Template<
+        Message Function(String name, DartType _type)>(
+    messageTemplate:
+        r"""The method '#name' isn't defined for the class '#type'.""",
+    tipTemplate:
+        r"""Try correcting the name to the name of an existing method, or defining a method named '#name'.""",
+    withArguments: _withArgumentsUndefinedMethod);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type)> codeUndefinedMethod =
+    const Code<Message Function(String name, DartType _type)>(
+        "UndefinedMethod", templateUndefinedMethod,
+        analyzerCodes: <String>["UNDEFINED_METHOD"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUndefinedMethod(String name, DartType _type) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeUndefinedMethod,
+      message:
+          """The method '${name}' isn't defined for the class '${type}'.""" +
+              labeler.originMessages,
+      tip:
+          """Try correcting the name to the name of an existing method, or defining a method named '${name}'.""",
+      arguments: {'name': name, 'type': _type});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String name,
+        DartType
+            _type)> templateUndefinedSetter = const Template<
+        Message Function(String name, DartType _type)>(
+    messageTemplate:
+        r"""The setter '#name' isn't defined for the class '#type'.""",
+    tipTemplate:
+        r"""Try correcting the name to the name of an existing setter, or defining a setter or field named '#name'.""",
+    withArguments: _withArgumentsUndefinedSetter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, DartType _type)> codeUndefinedSetter =
+    const Code<Message Function(String name, DartType _type)>(
+        "UndefinedSetter", templateUndefinedSetter,
+        analyzerCodes: <String>["UNDEFINED_SETTER"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsUndefinedSetter(String name, DartType _type) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  String type = typeParts.join();
+  return new Message(codeUndefinedSetter,
+      message:
+          """The setter '${name}' isn't defined for the class '${type}'.""" +
+              labeler.originMessages,
+      tip:
+          """Try correcting the name to the name of an existing setter, or defining a setter or field named '${name}'.""",
+      arguments: {'name': name, 'type': _type});
+}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
deleted file mode 100644
index 1ad47c1..0000000
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ /dev/null
@@ -1,10216 +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.
-
-// NOTE: THIS FILE IS GENERATED. DO NOT EDIT.
-//
-// Instead modify 'pkg/front_end/messages.yaml' and run
-// 'pkg/front_end/tool/fasta generate-messages' to update.
-
-// ignore_for_file: lines_longer_than_80_chars
-
-part of fasta.codes;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateAbstractClassInstantiation =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""The class '#name' is abstract and can't be instantiated.""",
-        withArguments: _withArgumentsAbstractClassInstantiation);
-
-// 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,
-        analyzerCodes: <String>["NEW_WITH_ABSTRACT_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsAbstractClassInstantiation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeAbstractClassInstantiation,
-      message: """The class '${name}' is abstract and can't be instantiated.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAbstractClassMember = messageAbstractClassMember;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAbstractClassMember = const MessageCode(
-    "AbstractClassMember",
-    index: 51,
-    message: r"""Members of classes can't be declared to be 'abstract'.""",
-    tip:
-        r"""Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAbstractNotSync = messageAbstractNotSync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAbstractNotSync = const MessageCode("AbstractNotSync",
-    analyzerCodes: <String>["NON_SYNC_ABSTRACT_METHOD"],
-    message: r"""Abstract methods can't use 'async', 'async*', or 'sync*'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateAbstractRedirectedClassInstantiation = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Factory redirects to class '#name', which is abstract and can't be instantiated.""",
-    withArguments: _withArgumentsAbstractRedirectedClassInstantiation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    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.
-Message _withArgumentsAbstractRedirectedClassInstantiation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeAbstractRedirectedClassInstantiation,
-      message:
-          """Factory redirects to class '${name}', which is abstract and can't be instantiated.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateAccessError =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Access error: '#name'.""",
-        withArguments: _withArgumentsAccessError);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsAccessError(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeAccessError,
-      message: """Access error: '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, DartType _type, DartType _type2)>
-    templateAmbiguousSupertypes = const Template<
-            Message Function(String name, DartType _type, DartType _type2)>(
-        messageTemplate:
-            r"""'#name' can't implement both '#type' and '#type2'""",
-        withArguments: _withArgumentsAmbiguousSupertypes);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
-    codeAmbiguousSupertypes =
-    const Code<Message Function(String name, DartType _type, DartType _type2)>(
-        "AmbiguousSupertypes", templateAmbiguousSupertypes,
-        analyzerCodes: <String>["AMBIGUOUS_SUPERTYPES"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsAmbiguousSupertypes(
-    String name, DartType _type, DartType _type2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeAmbiguousSupertypes,
-      message: """'${name}' can't implement both '${type}' and '${type2}'""" +
-          labeler.originMessages,
-      arguments: {'name': name, 'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAnonymousBreakTargetOutsideFunction =
-    messageAnonymousBreakTargetOutsideFunction;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAnonymousBreakTargetOutsideFunction =
-    const MessageCode("AnonymousBreakTargetOutsideFunction",
-        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"],
-        message: r"""Can't break to a target in a different function.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAnonymousContinueTargetOutsideFunction =
-    messageAnonymousContinueTargetOutsideFunction;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAnonymousContinueTargetOutsideFunction =
-    const MessageCode("AnonymousContinueTargetOutsideFunction",
-        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"],
-        message: r"""Can't continue at a target in a different function.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateArgumentTypeNotAssignable = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The argument type '#type' can't be assigned to the parameter type '#type2'.""",
-    withArguments: _withArgumentsArgumentTypeNotAssignable);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeArgumentTypeNotAssignable =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "ArgumentTypeNotAssignable", templateArgumentTypeNotAssignable,
-        analyzerCodes: <String>["ARGUMENT_TYPE_NOT_ASSIGNABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsArgumentTypeNotAssignable(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeArgumentTypeNotAssignable,
-      message:
-          """The argument type '${type}' can't be assigned to the parameter type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int
-            codePoint)> templateAsciiControlCharacter = const Template<
-        Message Function(int codePoint)>(
-    messageTemplate:
-        r"""The control character #unicode can only be used in strings and comments.""",
-    withArguments: _withArgumentsAsciiControlCharacter);
-
-// 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,
-        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsAsciiControlCharacter(int codePoint) {
-  String unicode =
-      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
-  return new Message(codeAsciiControlCharacter,
-      message:
-          """The control character ${unicode} can only be used in strings and comments.""",
-      arguments: {'codePoint': codePoint});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAssertAsExpression = messageAssertAsExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAssertAsExpression = const MessageCode(
-    "AssertAsExpression",
-    message: r"""`assert` can't be used as an expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAssertExtraneousArgument = messageAssertExtraneousArgument;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAssertExtraneousArgument = const MessageCode(
-    "AssertExtraneousArgument",
-    message: r"""`assert` can't have more than two arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAwaitAsIdentifier = const MessageCode(
-    "AwaitAsIdentifier",
-    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
-    message:
-        r"""'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAwaitForNotAsync = messageAwaitForNotAsync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAwaitForNotAsync = const MessageCode(
-    "AwaitForNotAsync",
-    analyzerCodes: <String>["ASYNC_FOR_IN_WRONG_CONTEXT"],
-    message:
-        r"""The asynchronous for-in can only be used in functions marked with 'async' or 'async*'.""",
-    tip:
-        r"""Try marking the function body with either 'async' or 'async*', or removing the 'await' before the for loop.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAwaitNotAsync = messageAwaitNotAsync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAwaitNotAsync = const MessageCode("AwaitNotAsync",
-    analyzerCodes: <String>["AWAIT_IN_WRONG_CONTEXT"],
-    message: r"""'await' can only be used in 'async' or 'async*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String name2)>
-    templateBadTypeVariableInSupertype =
-    const Template<Message Function(String name, String name2)>(
-        messageTemplate:
-            r"""Found unsupported uses of '#name' in supertype '#name2'.""",
-        withArguments: _withArgumentsBadTypeVariableInSupertype);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeBadTypeVariableInSupertype =
-    const Code<Message Function(String name, String name2)>(
-  "BadTypeVariableInSupertype",
-  templateBadTypeVariableInSupertype,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsBadTypeVariableInSupertype(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeBadTypeVariableInSupertype,
-      message:
-          """Found unsupported uses of '${name}' in supertype '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateBoundIssueViaCycleNonSimplicity = const Template<
-        Message Function(String name,
-            String name2)>(
-    messageTemplate:
-        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '#name2'.""",
-    tipTemplate:
-        r"""Try providing type arguments to '#name2' here or to some other raw types in the bounds along the reference chain.""",
-    withArguments: _withArgumentsBoundIssueViaCycleNonSimplicity);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    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.
-Message _withArgumentsBoundIssueViaCycleNonSimplicity(
-    String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeBoundIssueViaCycleNonSimplicity,
-      message:
-          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through '${name2}'.""",
-      tip: """Try providing type arguments to '${name2}' here or to some other raw types in the bounds along the reference chain.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateBoundIssueViaLoopNonSimplicity = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Generic type '#name' can't be used without type arguments in the bounds of its own type variables.""",
-    tipTemplate: r"""Try providing type arguments to '#name' here.""",
-    withArguments: _withArgumentsBoundIssueViaLoopNonSimplicity);
-
-// 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.
-Message _withArgumentsBoundIssueViaLoopNonSimplicity(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeBoundIssueViaLoopNonSimplicity,
-      message:
-          """Generic type '${name}' can't be used without type arguments in the bounds of its own type variables.""",
-      tip: """Try providing type arguments to '${name}' here.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateBoundIssueViaRawTypeWithNonSimpleBounds =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Generic type '#name' can't be used without type arguments in a type variable bound.""",
-        tipTemplate: r"""Try providing type arguments to '#name' here.""",
-        withArguments: _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    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.
-Message _withArgumentsBoundIssueViaRawTypeWithNonSimpleBounds(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeBoundIssueViaRawTypeWithNonSimpleBounds,
-      message:
-          """Generic type '${name}' can't be used without type arguments in a type variable bound.""",
-      tip: """Try providing type arguments to '${name}' here.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeBreakOutsideOfLoop = messageBreakOutsideOfLoop;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageBreakOutsideOfLoop = const MessageCode(
-    "BreakOutsideOfLoop",
-    index: 52,
-    message:
-        r"""A break statement can't be used outside of a loop or switch statement.""",
-    tip: r"""Try removing the break statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateBreakTargetOutsideFunction =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Can't break to '#name' in a different function.""",
-        withArguments: _withArgumentsBreakTargetOutsideFunction);
-
-// 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,
-        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsBreakTargetOutsideFunction(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeBreakTargetOutsideFunction,
-      message: """Can't break to '${name}' in a different function.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateBuiltInIdentifierAsType =
-    const Template<Message Function(Token token)>(
-        messageTemplate:
-            r"""The built-in identifier '#lexeme' can't be used as a type.""",
-        withArguments: _withArgumentsBuiltInIdentifierAsType);
-
-// 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,
-        analyzerCodes: <String>["BUILT_IN_IDENTIFIER_AS_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsBuiltInIdentifierAsType(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeBuiltInIdentifierAsType,
-      message:
-          """The built-in identifier '${lexeme}' can't be used as a type.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)>
-    templateBuiltInIdentifierInDeclaration =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Can't use '#lexeme' as a name here.""",
-        withArguments: _withArgumentsBuiltInIdentifierInDeclaration);
-
-// 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.
-Message _withArgumentsBuiltInIdentifierInDeclaration(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeBuiltInIdentifierInDeclaration,
-      message: """Can't use '${lexeme}' as a name here.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeBytecodeLimitExceededTooManyArguments =
-    messageBytecodeLimitExceededTooManyArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageBytecodeLimitExceededTooManyArguments =
-    const MessageCode("BytecodeLimitExceededTooManyArguments",
-        message: r"""Dart bytecode limit exceeded: too many arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCandidateFound = messageCandidateFound;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCandidateFound = const MessageCode("CandidateFound",
-    severity: Severity.context,
-    message: r"""Found this candidate, but the arguments don't match.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateCandidateFoundIsDefaultConstructor =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""The class '#name' has a constructor that takes no arguments.""",
-        withArguments: _withArgumentsCandidateFoundIsDefaultConstructor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeCandidateFoundIsDefaultConstructor =
-    const Code<Message Function(String name)>(
-        "CandidateFoundIsDefaultConstructor",
-        templateCandidateFoundIsDefaultConstructor,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCandidateFoundIsDefaultConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCandidateFoundIsDefaultConstructor,
-      message:
-          """The class '${name}' has a constructor that takes no arguments.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCannotAssignToParenthesizedExpression =
-    messageCannotAssignToParenthesizedExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCannotAssignToParenthesizedExpression =
-    const MessageCode("CannotAssignToParenthesizedExpression",
-        analyzerCodes: <String>["ASSIGNMENT_TO_PARENTHESIZED_EXPRESSION"],
-        message: r"""Can't assign to a parenthesized expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCannotAssignToSuper = messageCannotAssignToSuper;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCannotAssignToSuper = const MessageCode(
-    "CannotAssignToSuper",
-    analyzerCodes: <String>["NOT_AN_LVALUE"],
-    message: r"""Can't assign to super.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateCannotReadSdkSpecification =
-    const Template<Message Function(String string)>(
-        messageTemplate:
-            r"""Unable to read the 'libraries.json' specification file:
-  #string.""",
-        withArguments: _withArgumentsCannotReadSdkSpecification);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsCannotReadSdkSpecification(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeCannotReadSdkSpecification,
-      message: """Unable to read the 'libraries.json' specification file:
-  ${string}.""", arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantDisambiguateAmbiguousInformation =
-    messageCantDisambiguateAmbiguousInformation;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantDisambiguateAmbiguousInformation = const MessageCode(
-    "CantDisambiguateAmbiguousInformation",
-    message:
-        r"""Both Iterable and Map spread elements encountered in ambiguous literal.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantDisambiguateNotEnoughInformation =
-    messageCantDisambiguateNotEnoughInformation;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantDisambiguateNotEnoughInformation = const MessageCode(
-    "CantDisambiguateNotEnoughInformation",
-    message:
-        r"""Not enough type information to disambiguate between literal set and literal map.""",
-    tip:
-        r"""Try providing type arguments for the literal explicitly to disambiguate it.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantInferPackagesFromManyInputs =
-    messageCantInferPackagesFromManyInputs;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantInferPackagesFromManyInputs = const MessageCode(
-    "CantInferPackagesFromManyInputs",
-    message:
-        r"""Can't infer a .packages file when compiling multiple inputs.""",
-    tip: r"""Try specifying the file explicitly with the --packages option.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantInferPackagesFromPackageUri =
-    messageCantInferPackagesFromPackageUri;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantInferPackagesFromPackageUri = const MessageCode(
-    "CantInferPackagesFromPackageUri",
-    message: r"""Can't infer a .packages file from an input 'package:*' URI.""",
-    tip: r"""Try specifying the file explicitly with the --packages option.""");
-
-// 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 inherited 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 inherited 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
-            string)> templateCantInferTypeDueToCircularity = const Template<
-        Message Function(String string)>(
-    messageTemplate:
-        r"""Can't infer the type of '#string': circularity found during type inference.""",
-    tipTemplate: r"""Specify the type explicitly.""",
-    withArguments: _withArgumentsCantInferTypeDueToCircularity);
-
-// 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,
-        analyzerCodes: <String>["RECURSIVE_COMPILE_TIME_CONSTANT"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCantInferTypeDueToCircularity(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeCantInferTypeDueToCircularity,
-      message:
-          """Can't infer the type of '${string}': circularity found during type inference.""",
-      tip: """Specify the type explicitly.""",
-      arguments: {'string': string});
-}
-
-// 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 inherited 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 inherited 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(Uri uri_, String string)> templateCantReadFile =
-    const Template<Message Function(Uri uri_, String string)>(
-        messageTemplate: r"""Error when reading '#uri': #string""",
-        withArguments: _withArgumentsCantReadFile);
-
-// 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,
-        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_);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeCantReadFile,
-      message: """Error when reading '${uri}': ${string}""",
-      arguments: {'uri': uri_, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)>
-    templateCantUseControlFlowOrSpreadAsConstant =
-    const Template<Message Function(Token token)>(
-        messageTemplate:
-            r"""'#lexeme' is not supported in constant expressions.""",
-        withArguments: _withArgumentsCantUseControlFlowOrSpreadAsConstant);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)>
-    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.
-Message _withArgumentsCantUseControlFlowOrSpreadAsConstant(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeCantUseControlFlowOrSpreadAsConstant,
-      message: """'${lexeme}' is not supported in constant expressions.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Token
-            token)> templateCantUseDeferredPrefixAsConstant = const Template<
-        Message Function(Token token)>(
-    messageTemplate:
-        r"""'#lexeme' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
-    tipTemplate:
-        r"""Try moving the constant from the deferred library, or removing 'deferred' from the import.
-""",
-    withArguments: _withArgumentsCantUseDeferredPrefixAsConstant);
-
-// 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.
-Message _withArgumentsCantUseDeferredPrefixAsConstant(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeCantUseDeferredPrefixAsConstant,
-      message:
-          """'${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});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantUsePrefixAsExpression =
-    messageCantUsePrefixAsExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantUsePrefixAsExpression = const MessageCode(
-    "CantUsePrefixAsExpression",
-    analyzerCodes: <String>["PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT"],
-    message: r"""A prefix can't be used as an expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantUsePrefixWithNullAware =
-    messageCantUsePrefixWithNullAware;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantUsePrefixWithNullAware = const MessageCode(
-    "CantUsePrefixWithNullAware",
-    analyzerCodes: <String>["PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT"],
-    message: r"""A prefix can't be used with null-aware operators.""",
-    tip: r"""Try replacing '?.' with '.'""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCatchSyntax = messageCatchSyntax;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCatchSyntax = const MessageCode("CatchSyntax",
-    index: 84,
-    message:
-        r"""'catch' must be followed by '(identifier)' or '(identifier, identifier)'.""",
-    tip:
-        r"""No types are needed, the first is given by 'on', the second is always 'StackTrace'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCatchSyntaxExtraParameters =
-    messageCatchSyntaxExtraParameters;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCatchSyntaxExtraParameters = const MessageCode(
-    "CatchSyntaxExtraParameters",
-    index: 83,
-    message:
-        r"""'catch' must be followed by '(identifier)' or '(identifier, identifier)'.""",
-    tip:
-        r"""No types are needed, the first is given by 'on', the second is always 'StackTrace'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeClassInClass = messageClassInClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageClassInClass = const MessageCode("ClassInClass",
-    index: 53,
-    message: r"""Classes can't be declared inside other classes.""",
-    tip: r"""Try moving the class to the top-level.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeColonInPlaceOfIn = messageColonInPlaceOfIn;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageColonInPlaceOfIn = const MessageCode(
-    "ColonInPlaceOfIn",
-    index: 54,
-    message: r"""For-in loops use 'in' rather than a colon.""",
-    tip: r"""Try replacing the colon with the keyword 'in'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateCombinedMemberSignatureFailed = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""Class '#name' inherits multiple members named '#name2' with incompatible signatures.""",
-    tipTemplate: r"""Try adding a declaration of '#name2' to '#name'.""",
-    withArguments: _withArgumentsCombinedMemberSignatureFailed);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeCombinedMemberSignatureFailed =
-    const Code<Message Function(String name, String name2)>(
-        "CombinedMemberSignatureFailed", templateCombinedMemberSignatureFailed,
-        analyzerCodes: <String>["INCONSISTENT_INHERITANCE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCombinedMemberSignatureFailed(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeCombinedMemberSignatureFailed,
-      message:
-          """Class '${name}' inherits multiple members named '${name2}' with incompatible signatures.""",
-      tip: """Try adding a declaration of '${name2}' to '${name}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String
-            string2)> templateConflictingModifiers = const Template<
-        Message Function(String string, String string2)>(
-    messageTemplate:
-        r"""Members can't be declared to be both '#string' and '#string2'.""",
-    tipTemplate: r"""Try removing one of the keywords.""",
-    withArguments: _withArgumentsConflictingModifiers);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeConflictingModifiers =
-    const Code<Message Function(String string, String string2)>(
-        "ConflictingModifiers", templateConflictingModifiers,
-        index: 59);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConflictingModifiers(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeConflictingModifiers,
-      message:
-          """Members can't be declared to be both '${string}' and '${string2}'.""",
-      tip: """Try removing one of the keywords.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateConflictsWithConstructor =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Conflicts with constructor '#name'.""",
-        withArguments: _withArgumentsConflictsWithConstructor);
-
-// 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,
-        analyzerCodes: <String>["CONFLICTS_WITH_CONSTRUCTOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConflictsWithConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConflictsWithConstructor,
-      message: """Conflicts with constructor '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateConflictsWithFactory =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Conflicts with factory '#name'.""",
-        withArguments: _withArgumentsConflictsWithFactory);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsConflictsWithFactory(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConflictsWithFactory,
-      message: """Conflicts with factory '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateConflictsWithMember =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Conflicts with member '#name'.""",
-        withArguments: _withArgumentsConflictsWithMember);
-
-// 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,
-        analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConflictsWithMember(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConflictsWithMember,
-      message: """Conflicts with member '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateConflictsWithSetter =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Conflicts with setter '#name'.""",
-        withArguments: _withArgumentsConflictsWithSetter);
-
-// 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,
-        analyzerCodes: <String>["CONFLICTS_WITH_MEMBER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConflictsWithSetter(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConflictsWithSetter,
-      message: """Conflicts with setter '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateConflictsWithTypeVariable =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Conflicts with type variable '#name'.""",
-        withArguments: _withArgumentsConflictsWithTypeVariable);
-
-// 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,
-        analyzerCodes: <String>["CONFLICTING_TYPE_VARIABLE_AND_MEMBER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConflictsWithTypeVariable(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConflictsWithTypeVariable,
-      message: """Conflicts with type variable '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConflictsWithTypeVariableCause =
-    messageConflictsWithTypeVariableCause;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConflictsWithTypeVariableCause = const MessageCode(
-    "ConflictsWithTypeVariableCause",
-    severity: Severity.context,
-    message: r"""This is the type variable.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstAndFinal = messageConstAndFinal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstAndFinal = const MessageCode("ConstAndFinal",
-    index: 58,
-    message: r"""Members can't be declared to be both 'const' and 'final'.""",
-    tip: r"""Try removing either the 'const' or 'final' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstClass = messageConstClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstClass = const MessageCode("ConstClass",
-    index: 60,
-    message: r"""Classes can't be declared to be 'const'.""",
-    tip:
-        r"""Try removing the 'const' keyword. If you're trying to indicate that instances of the class can be constants, place the 'const' keyword on  the class' constructor(s).""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstConstructorNonFinalField =
-    messageConstConstructorNonFinalField;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorNonFinalField = const MessageCode(
-    "ConstConstructorNonFinalField",
-    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD"],
-    message: r"""Constructor is marked 'const' so all fields must be final.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstConstructorNonFinalFieldCause =
-    messageConstConstructorNonFinalFieldCause;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorNonFinalFieldCause = const MessageCode(
-    "ConstConstructorNonFinalFieldCause",
-    severity: Severity.context,
-    message: r"""Field isn't final, but constructor is 'const'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstConstructorRedirectionToNonConst =
-    messageConstConstructorRedirectionToNonConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorRedirectionToNonConst =
-    const MessageCode("ConstConstructorRedirectionToNonConst",
-        message:
-            r"""A constant constructor can't call a non-constant constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstConstructorWithBody = messageConstConstructorWithBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorWithBody = const MessageCode(
-    "ConstConstructorWithBody",
-    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_BODY"],
-    message: r"""A const constructor can't have a body.""",
-    tip: r"""Try removing either the 'const' keyword or the body.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstConstructorWithNonConstSuper =
-    messageConstConstructorWithNonConstSuper;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorWithNonConstSuper = const MessageCode(
-    "ConstConstructorWithNonConstSuper",
-    analyzerCodes: <String>["CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER"],
-    message:
-        r"""A constant constructor can't call a non-constant super constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalCircularity = messageConstEvalCircularity;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalCircularity = const MessageCode(
-    "ConstEvalCircularity",
-    analyzerCodes: <String>["RECURSIVE_COMPILE_TIME_CONSTANT"],
-    message: r"""Constant expression depends on itself.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalContext = messageConstEvalContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalContext =
-    const MessageCode("ConstEvalContext", message: r"""While analyzing:""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateConstEvalDeferredLibrary = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""'#name' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
-    tipTemplate:
-        r"""Try moving the constant from the deferred library, or removing 'deferred' from the import.
-""",
-    withArguments: _withArgumentsConstEvalDeferredLibrary);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeConstEvalDeferredLibrary =
-    const Code<Message Function(String name)>(
-        "ConstEvalDeferredLibrary", templateConstEvalDeferredLibrary,
-        analyzerCodes: <String>[
-      "NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY"
-    ]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalDeferredLibrary(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConstEvalDeferredLibrary,
-      message:
-          """'${name}' 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: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant
-            _constant)> templateConstEvalDuplicateElement = const Template<
-        Message Function(Constant _constant)>(
-    messageTemplate:
-        r"""The element '#constant' conflicts with another existing element in the set.""",
-    withArguments: _withArgumentsConstEvalDuplicateElement);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)> codeConstEvalDuplicateElement =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalDuplicateElement", templateConstEvalDuplicateElement,
-        analyzerCodes: <String>["EQUAL_ELEMENTS_IN_CONST_SET"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalDuplicateElement(Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalDuplicateElement,
-      message:
-          """The element '${constant}' conflicts with another existing element in the set.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant
-            _constant)> templateConstEvalDuplicateKey = const Template<
-        Message Function(Constant _constant)>(
-    messageTemplate:
-        r"""The key '#constant' conflicts with another existing key in the map.""",
-    withArguments: _withArgumentsConstEvalDuplicateKey);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)> codeConstEvalDuplicateKey =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalDuplicateKey", templateConstEvalDuplicateKey,
-        analyzerCodes: <String>["EQUAL_KEYS_IN_CONST_MAP"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalDuplicateKey(Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalDuplicateKey,
-      message:
-          """The key '${constant}' conflicts with another existing key in the map.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant
-            _constant)> templateConstEvalElementImplementsEqual = const Template<
-        Message Function(Constant _constant)>(
-    messageTemplate:
-        r"""The element '#constant' does not have a primitive operator '=='.""",
-    withArguments: _withArgumentsConstEvalElementImplementsEqual);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)>
-    codeConstEvalElementImplementsEqual =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalElementImplementsEqual",
-        templateConstEvalElementImplementsEqual,
-        analyzerCodes: <String>["CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalElementImplementsEqual(Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalElementImplementsEqual,
-      message:
-          """The element '${constant}' does not have a primitive operator '=='.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalFailedAssertion = messageConstEvalFailedAssertion;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalFailedAssertion = const MessageCode(
-    "ConstEvalFailedAssertion",
-    analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"],
-    message: r"""This assertion failed.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateConstEvalFailedAssertionWithMessage =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""This assertion failed with message: #string""",
-        withArguments: _withArgumentsConstEvalFailedAssertionWithMessage);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
-    codeConstEvalFailedAssertionWithMessage =
-    const Code<Message Function(String string)>(
-        "ConstEvalFailedAssertionWithMessage",
-        templateConstEvalFailedAssertionWithMessage,
-        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalFailedAssertionWithMessage(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeConstEvalFailedAssertionWithMessage,
-      message: """This assertion failed with message: ${string}""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateConstEvalFreeTypeParameter = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""The type '#type' is not a constant because it depends on a type parameter, only instantiated types are allowed.""",
-    withArguments: _withArgumentsConstEvalFreeTypeParameter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeConstEvalFreeTypeParameter =
-    const Code<Message Function(DartType _type)>(
-  "ConstEvalFreeTypeParameter",
-  templateConstEvalFreeTypeParameter,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalFreeTypeParameter(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeConstEvalFreeTypeParameter,
-      message:
-          """The type '${type}' is not a constant because it depends on a type parameter, only instantiated types are allowed.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        Constant _constant,
-        DartType _type,
-        DartType
-            _type2)> templateConstEvalInvalidBinaryOperandType = const Template<
-        Message Function(String string, Constant _constant, DartType _type,
-            DartType _type2)>(
-    messageTemplate:
-        r"""Binary operator '#string' on '#constant' requires operand of type '#type', but was of type '#type2'.""",
-    withArguments: _withArgumentsConstEvalInvalidBinaryOperandType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-    Message Function(String string, Constant _constant, DartType _type,
-        DartType _type2)> codeConstEvalInvalidBinaryOperandType = const Code<
-    Message Function(
-        String string, Constant _constant, DartType _type, DartType _type2)>(
-  "ConstEvalInvalidBinaryOperandType",
-  templateConstEvalInvalidBinaryOperandType,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidBinaryOperandType(
-    String string, Constant _constant, DartType _type, DartType _type2) {
-  if (string.isEmpty) throw 'No string provided';
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String constant = constantParts.join();
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeConstEvalInvalidBinaryOperandType,
-      message:
-          """Binary operator '${string}' on '${constant}' requires operand of type '${type}', but was of type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {
-        'string': string,
-        'constant': _constant,
-        'type': _type,
-        'type2': _type2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant _constant,
-        DartType
-            _type)> templateConstEvalInvalidEqualsOperandType = const Template<
-        Message Function(Constant _constant, DartType _type)>(
-    messageTemplate:
-        r"""Binary operator '==' requires receiver constant '#constant' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type '#type'.""",
-    withArguments: _withArgumentsConstEvalInvalidEqualsOperandType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant, DartType _type)>
-    codeConstEvalInvalidEqualsOperandType =
-    const Code<Message Function(Constant _constant, DartType _type)>(
-  "ConstEvalInvalidEqualsOperandType",
-  templateConstEvalInvalidEqualsOperandType,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidEqualsOperandType(
-    Constant _constant, DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  List<Object> typeParts = labeler.labelType(_type);
-  String constant = constantParts.join();
-  String type = typeParts.join();
-  return new Message(codeConstEvalInvalidEqualsOperandType,
-      message:
-          """Binary operator '==' requires receiver constant '${constant}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type '${type}'.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant, 'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        Constant
-            _constant)> templateConstEvalInvalidMethodInvocation = const Template<
-        Message Function(String string, Constant _constant)>(
-    messageTemplate:
-        r"""The method '#string' can't be invoked on '#constant' in a constant expression.""",
-    withArguments: _withArgumentsConstEvalInvalidMethodInvocation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, Constant _constant)>
-    codeConstEvalInvalidMethodInvocation =
-    const Code<Message Function(String string, Constant _constant)>(
-        "ConstEvalInvalidMethodInvocation",
-        templateConstEvalInvalidMethodInvocation,
-        analyzerCodes: <String>["UNDEFINED_OPERATOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidMethodInvocation(
-    String string, Constant _constant) {
-  if (string.isEmpty) throw 'No string provided';
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalInvalidMethodInvocation,
-      message:
-          """The method '${string}' can't be invoked on '${constant}' in a constant expression.""" +
-              labeler.originMessages,
-      arguments: {'string': string, 'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        Constant
-            _constant)> templateConstEvalInvalidPropertyGet = const Template<
-        Message Function(String string, Constant _constant)>(
-    messageTemplate:
-        r"""The property '#string' can't be accessed on '#constant' in a constant expression.""",
-    withArguments: _withArgumentsConstEvalInvalidPropertyGet);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, Constant _constant)>
-    codeConstEvalInvalidPropertyGet =
-    const Code<Message Function(String string, Constant _constant)>(
-        "ConstEvalInvalidPropertyGet", templateConstEvalInvalidPropertyGet,
-        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidPropertyGet(
-    String string, Constant _constant) {
-  if (string.isEmpty) throw 'No string provided';
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalInvalidPropertyGet,
-      message:
-          """The property '${string}' can't be accessed on '${constant}' in a constant expression.""" +
-              labeler.originMessages,
-      arguments: {'string': string, 'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateConstEvalInvalidStaticInvocation = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""The invocation of '#name' is not allowed in a constant expression.""",
-    withArguments: _withArgumentsConstEvalInvalidStaticInvocation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeConstEvalInvalidStaticInvocation =
-    const Code<Message Function(String name)>(
-        "ConstEvalInvalidStaticInvocation",
-        templateConstEvalInvalidStaticInvocation,
-        analyzerCodes: <String>["CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidStaticInvocation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConstEvalInvalidStaticInvocation,
-      message:
-          """The invocation of '${name}' is not allowed in a constant expression.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Constant _constant)>
-    templateConstEvalInvalidStringInterpolationOperand =
-    const Template<Message Function(Constant _constant)>(
-        messageTemplate:
-            r"""The constant value '#constant' can't be used as part of a string interpolation in a constant expression.
-Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""",
-        withArguments:
-            _withArgumentsConstEvalInvalidStringInterpolationOperand);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)>
-    codeConstEvalInvalidStringInterpolationOperand =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalInvalidStringInterpolationOperand",
-        templateConstEvalInvalidStringInterpolationOperand,
-        analyzerCodes: <String>["CONST_EVAL_TYPE_BOOL_NUM_STRING"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidStringInterpolationOperand(
-    Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalInvalidStringInterpolationOperand,
-      message:
-          """The constant value '${constant}' can't be used as part of a string interpolation in a constant expression.
-Only values of type 'null', 'bool', 'int', 'double', or 'String' can be used.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant
-            _constant)> templateConstEvalInvalidSymbolName = const Template<
-        Message Function(Constant _constant)>(
-    messageTemplate:
-        r"""The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '#constant'.""",
-    withArguments: _withArgumentsConstEvalInvalidSymbolName);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)>
-    codeConstEvalInvalidSymbolName =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalInvalidSymbolName", templateConstEvalInvalidSymbolName,
-        analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidSymbolName(Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalInvalidSymbolName,
-      message:
-          """The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '${constant}'.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Constant _constant,
-        DartType _type,
-        DartType
-            _type2)> templateConstEvalInvalidType = const Template<
-        Message Function(Constant _constant, DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""Expected constant '#constant' to be of type '#type', but was of type '#type2'.""",
-    withArguments: _withArgumentsConstEvalInvalidType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(Constant _constant, DartType _type, DartType _type2)>
-    codeConstEvalInvalidType = const Code<
-        Message Function(Constant _constant, DartType _type, DartType _type2)>(
-  "ConstEvalInvalidType",
-  templateConstEvalInvalidType,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidType(
-    Constant _constant, DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String constant = constantParts.join();
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeConstEvalInvalidType,
-      message:
-          """Expected constant '${constant}' to be of type '${type}', but was of type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant, 'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Constant _constant)>
-    templateConstEvalKeyImplementsEqual =
-    const Template<Message Function(Constant _constant)>(
-        messageTemplate:
-            r"""The key '#constant' does not have a primitive operator '=='.""",
-        withArguments: _withArgumentsConstEvalKeyImplementsEqual);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Constant _constant)>
-    codeConstEvalKeyImplementsEqual =
-    const Code<Message Function(Constant _constant)>(
-        "ConstEvalKeyImplementsEqual", templateConstEvalKeyImplementsEqual,
-        analyzerCodes: <String>[
-      "CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS"
-    ]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalKeyImplementsEqual(Constant _constant) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> constantParts = labeler.labelConstant(_constant);
-  String constant = constantParts.join();
-  return new Message(codeConstEvalKeyImplementsEqual,
-      message:
-          """The key '${constant}' does not have a primitive operator '=='.""" +
-              labeler.originMessages,
-      arguments: {'constant': _constant});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String string2,
-        String
-            string3)> templateConstEvalNegativeShift = const Template<
-        Message Function(String string, String string2, String string3)>(
-    messageTemplate:
-        r"""Binary operator '#string' on '#string2' requires non-negative operand, but was '#string3'.""",
-    withArguments: _withArgumentsConstEvalNegativeShift);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2, String string3)>
-    codeConstEvalNegativeShift =
-    const Code<Message Function(String string, String string2, String string3)>(
-  "ConstEvalNegativeShift",
-  templateConstEvalNegativeShift,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalNegativeShift(
-    String string, String string2, String string3) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  if (string3.isEmpty) throw 'No string provided';
-  return new Message(codeConstEvalNegativeShift,
-      message:
-          """Binary operator '${string}' on '${string2}' requires non-negative operand, but was '${string3}'.""",
-      arguments: {'string': string, 'string2': string2, 'string3': string3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            string)> templateConstEvalNonConstantVariableGet = const Template<
-        Message Function(String string)>(
-    messageTemplate:
-        r"""The variable '#string' is not a constant, only constant expressions are allowed.""",
-    withArguments: _withArgumentsConstEvalNonConstantVariableGet);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
-    codeConstEvalNonConstantVariableGet =
-    const Code<Message Function(String string)>(
-        "ConstEvalNonConstantVariableGet",
-        templateConstEvalNonConstantVariableGet,
-        analyzerCodes: <String>["NON_CONSTANT_VALUE_IN_INITIALIZER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalNonConstantVariableGet(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeConstEvalNonConstantVariableGet,
-      message:
-          """The variable '${string}' is not a constant, only constant expressions are allowed.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalNotListOrSetInSpread =
-    messageConstEvalNotListOrSetInSpread;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalNotListOrSetInSpread = const MessageCode(
-    "ConstEvalNotListOrSetInSpread",
-    analyzerCodes: <String>["CONST_SPREAD_EXPECTED_LIST_OR_SET"],
-    message:
-        r"""Only lists and sets can be used in spreads in constant lists and sets.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalNotMapInSpread = messageConstEvalNotMapInSpread;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalNotMapInSpread = const MessageCode(
-    "ConstEvalNotMapInSpread",
-    analyzerCodes: <String>["CONST_SPREAD_EXPECTED_MAP"],
-    message: r"""Only maps can be used in spreads in constant maps.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalNullValue = messageConstEvalNullValue;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalNullValue = const MessageCode(
-    "ConstEvalNullValue",
-    analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"],
-    message: r"""Null value during constant evaluation.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalStartingPoint = messageConstEvalStartingPoint;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalStartingPoint = const MessageCode(
-    "ConstEvalStartingPoint",
-    message: r"""Constant evaluation error:""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstEvalUnevaluated = messageConstEvalUnevaluated;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstEvalUnevaluated = const MessageCode(
-    "ConstEvalUnevaluated",
-    message: r"""Could not evaluate constant expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String
-            string2)> templateConstEvalZeroDivisor = const Template<
-        Message Function(String string, String string2)>(
-    messageTemplate:
-        r"""Binary operator '#string' on '#string2' requires non-zero divisor, but divisor was '0'.""",
-    withArguments: _withArgumentsConstEvalZeroDivisor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeConstEvalZeroDivisor =
-    const Code<Message Function(String string, String string2)>(
-        "ConstEvalZeroDivisor", templateConstEvalZeroDivisor,
-        analyzerCodes: <String>["CONST_EVAL_THROWS_IDBZE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalZeroDivisor(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeConstEvalZeroDivisor,
-      message:
-          """Binary operator '${string}' on '${string2}' requires non-zero divisor, but divisor was '0'.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstFactory = messageConstFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstFactory = const MessageCode("ConstFactory",
-    index: 62,
-    message:
-        r"""Only redirecting factory constructors can be declared to be 'const'.""",
-    tip:
-        r"""Try removing the 'const' keyword, or replacing the body with '=' followed by a valid target.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstFactoryRedirectionToNonConst =
-    messageConstFactoryRedirectionToNonConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstFactoryRedirectionToNonConst = const MessageCode(
-    "ConstFactoryRedirectionToNonConst",
-    analyzerCodes: <String>["REDIRECT_TO_NON_CONST_CONSTRUCTOR"],
-    message:
-        r"""Constant factory constructor can't delegate to a non-constant constructor.""",
-    tip:
-        r"""Try redirecting to a different constructor or marking the target constructor 'const'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateConstFieldWithoutInitializer = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""The const variable '#name' must be initialized.""",
-    tipTemplate:
-        r"""Try adding an initializer ('= expression') to the declaration.""",
-    withArguments: _withArgumentsConstFieldWithoutInitializer);
-
-// 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,
-        analyzerCodes: <String>["CONST_NOT_INITIALIZED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstFieldWithoutInitializer(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConstFieldWithoutInitializer,
-      message: """The const variable '${name}' must be initialized.""",
-      tip: """Try adding an initializer ('= expression') to the declaration.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstInstanceField = messageConstInstanceField;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstInstanceField = const MessageCode(
-    "ConstInstanceField",
-    analyzerCodes: <String>["CONST_INSTANCE_FIELD"],
-    message: r"""Only static fields can be declared as const.""",
-    tip:
-        r"""Try using 'final' instead of 'const', or adding the keyword 'static'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstMethod = messageConstMethod;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstMethod = const MessageCode("ConstMethod",
-    index: 63,
-    message:
-        r"""Getters, setters and methods can't be declared to be 'const'.""",
-    tip: r"""Try removing the 'const' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorCyclic = messageConstructorCyclic;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorCyclic = const MessageCode(
-    "ConstructorCyclic",
-    analyzerCodes: <String>["RECURSIVE_CONSTRUCTOR_REDIRECT"],
-    message: r"""Redirecting constructors can't be cyclic.""",
-    tip:
-        r"""Try to have all constructors eventually redirect to a non-redirecting constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateConstructorNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Couldn't find constructor '#name'.""",
-        withArguments: _withArgumentsConstructorNotFound);
-
-// 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,
-        analyzerCodes: <String>["CONSTRUCTOR_NOT_FOUND"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstructorNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConstructorNotFound,
-      message: """Couldn't find constructor '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorNotSync = messageConstructorNotSync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorNotSync = const MessageCode(
-    "ConstructorNotSync",
-    analyzerCodes: <String>["NON_SYNC_CONSTRUCTOR"],
-    message:
-        r"""Constructor bodies can't use 'async', 'async*', or 'sync*'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorWithReturnType =
-    messageConstructorWithReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorWithReturnType = const MessageCode(
-    "ConstructorWithReturnType",
-    index: 55,
-    message: r"""Constructors can't have a return type.""",
-    tip: r"""Try removing the return type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorWithTypeArguments =
-    messageConstructorWithTypeArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorWithTypeArguments = const MessageCode(
-    "ConstructorWithTypeArguments",
-    analyzerCodes: <String>["WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR"],
-    message:
-        r"""A constructor invocation can't have type arguments on the constructor name.""",
-    tip: r"""Try to place the type arguments on the class name.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorWithTypeParameters =
-    messageConstructorWithTypeParameters;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorWithTypeParameters = const MessageCode(
-    "ConstructorWithTypeParameters",
-    analyzerCodes: <String>["TYPE_PARAMETER_ON_CONSTRUCTOR"],
-    message: r"""Constructors can't have type parameters.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstructorWithWrongName = messageConstructorWithWrongName;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstructorWithWrongName = const MessageCode(
-    "ConstructorWithWrongName",
-    analyzerCodes: <String>["INVALID_CONSTRUCTOR_NAME"],
-    message:
-        r"""The name of a constructor must match the name of the enclosing class.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateConstructorWithWrongNameContext =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""The name of the enclosing class is '#name'.""",
-        withArguments: _withArgumentsConstructorWithWrongNameContext);
-
-// 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.
-Message _withArgumentsConstructorWithWrongNameContext(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeConstructorWithWrongNameContext,
-      message: """The name of the enclosing class is '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeContinueLabelNotTarget = messageContinueLabelNotTarget;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageContinueLabelNotTarget = const MessageCode(
-    "ContinueLabelNotTarget",
-    analyzerCodes: <String>["LABEL_UNDEFINED"],
-    message: r"""Target of continue must be a label.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeContinueOutsideOfLoop = messageContinueOutsideOfLoop;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageContinueOutsideOfLoop = const MessageCode(
-    "ContinueOutsideOfLoop",
-    index: 2,
-    message:
-        r"""A continue statement can't be used outside of a loop or switch statement.""",
-    tip: r"""Try removing the continue statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateContinueTargetOutsideFunction =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't continue at '#name' in a different function.""",
-        withArguments: _withArgumentsContinueTargetOutsideFunction);
-
-// 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,
-        analyzerCodes: <String>["LABEL_IN_OUTER_SCOPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsContinueTargetOutsideFunction(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeContinueTargetOutsideFunction,
-      message: """Can't continue at '${name}' in a different function.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeContinueWithoutLabelInCase =
-    messageContinueWithoutLabelInCase;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageContinueWithoutLabelInCase = const MessageCode(
-    "ContinueWithoutLabelInCase",
-    index: 64,
-    message:
-        r"""A continue statement in a switch statement must have a label as a target.""",
-    tip:
-        r"""Try adding a label associated with one of the case clauses to the continue statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2)>
-    templateCouldNotParseUri =
-    const Template<Message Function(String string, String string2)>(
-        messageTemplate: r"""Couldn't parse URI '#string':
-  #string2.""", withArguments: _withArgumentsCouldNotParseUri);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeCouldNotParseUri =
-    const Code<Message Function(String string, String string2)>(
-  "CouldNotParseUri",
-  templateCouldNotParseUri,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCouldNotParseUri(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeCouldNotParseUri,
-      message: """Couldn't parse URI '${string}':
-  ${string2}.""", arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantAndStatic = messageCovariantAndStatic;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantAndStatic = const MessageCode(
-    "CovariantAndStatic",
-    index: 66,
-    message:
-        r"""Members can't be declared to be both 'covariant' and 'static'.""",
-    tip: r"""Try removing either the 'covariant' or 'static' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantMember = messageCovariantMember;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantMember = const MessageCode("CovariantMember",
-    index: 67,
-    message:
-        r"""Getters, setters and methods can't be declared to be 'covariant'.""",
-    tip: r"""Try removing the 'covariant' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            string)> templateCycleInTypeVariables = const Template<
-        Message Function(String name, String string)>(
-    messageTemplate: r"""Type '#name' is a bound of itself via '#string'.""",
-    tipTemplate:
-        r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
-    withArguments: _withArgumentsCycleInTypeVariables);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String string)>
-    codeCycleInTypeVariables =
-    const Code<Message Function(String name, String string)>(
-        "CycleInTypeVariables", templateCycleInTypeVariables,
-        analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCycleInTypeVariables(String name, String string) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeCycleInTypeVariables,
-      message: """Type '${name}' is a bound of itself via '${string}'.""",
-      tip:
-          """Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
-      arguments: {'name': name, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateCyclicClassHierarchy =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is a supertype of itself.""",
-        withArguments: _withArgumentsCyclicClassHierarchy);
-
-// 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,
-        analyzerCodes: <String>["RECURSIVE_INTERFACE_INHERITANCE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCyclicClassHierarchy(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCyclicClassHierarchy,
-      message: """'${name}' is a supertype of itself.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateCyclicRedirectingFactoryConstructors =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Cyclic definition of factory '#name'.""",
-        withArguments: _withArgumentsCyclicRedirectingFactoryConstructors);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    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.
-Message _withArgumentsCyclicRedirectingFactoryConstructors(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCyclicRedirectingFactoryConstructors,
-      message: """Cyclic definition of factory '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateCyclicTypedef =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""The typedef '#name' has a reference to itself.""",
-        withArguments: _withArgumentsCyclicTypedef);
-
-// 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,
-        analyzerCodes: <String>["TYPE_ALIAS_CANNOT_REFERENCE_ITSELF"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsCyclicTypedef(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeCyclicTypedef,
-      message: """The typedef '${name}' has a reference to itself.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String string)>
-    templateDebugTrace =
-    const Template<Message Function(String name, String string)>(
-        messageTemplate: r"""Fatal '#name' at:
-#string""", withArguments: _withArgumentsDebugTrace);
-
-// 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,
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDebugTrace(String name, String string) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeDebugTrace, message: """Fatal '${name}' at:
-${string}""", arguments: {'name': name, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDeclaredMemberConflictsWithInheritedMember =
-    messageDeclaredMemberConflictsWithInheritedMember;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDeclaredMemberConflictsWithInheritedMember =
-    const MessageCode("DeclaredMemberConflictsWithInheritedMember",
-        analyzerCodes: <String>["DECLARED_MEMBER_CONFLICTS_WITH_INHERITED"],
-        message:
-            r"""Can't declare a member that conflicts with an inherited one.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDeclaredMemberConflictsWithInheritedMemberCause =
-    messageDeclaredMemberConflictsWithInheritedMemberCause;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDeclaredMemberConflictsWithInheritedMemberCause =
-    const MessageCode("DeclaredMemberConflictsWithInheritedMemberCause",
-        severity: Severity.context,
-        message: r"""This is the inherited member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDefaultValueInRedirectingFactoryConstructor =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't have a default value here because any default values of '#name' would be used instead.""",
-        tipTemplate: r"""Try removing the default value.""",
-        withArguments:
-            _withArgumentsDefaultValueInRedirectingFactoryConstructor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeDefaultValueInRedirectingFactoryConstructor =
-    const Code<Message Function(String name)>(
-        "DefaultValueInRedirectingFactoryConstructor",
-        templateDefaultValueInRedirectingFactoryConstructor,
-        analyzerCodes: <String>[
-      "DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR"
-    ]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDefaultValueInRedirectingFactoryConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDefaultValueInRedirectingFactoryConstructor,
-      message:
-          """Can't have a default value here because any default values of '${name}' would be used instead.""",
-      tip: """Try removing the default value.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDeferredAfterPrefix = messageDeferredAfterPrefix;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDeferredAfterPrefix = const MessageCode(
-    "DeferredAfterPrefix",
-    index: 68,
-    message:
-        r"""The deferred keyword should come immediately before the prefix ('as' clause).""",
-    tip: r"""Try moving the deferred keyword before the prefix.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateDeferredPrefixDuplicated = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Can't use the name '#name' for a deferred library, as the name is used elsewhere.""",
-    withArguments: _withArgumentsDeferredPrefixDuplicated);
-
-// 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,
-        analyzerCodes: <String>["SHARED_DEFERRED_PREFIX"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDeferredPrefixDuplicated(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDeferredPrefixDuplicated,
-      message:
-          """Can't use the name '${name}' for a deferred library, as the name is used elsewhere.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDeferredPrefixDuplicatedCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is used here.""",
-        withArguments: _withArgumentsDeferredPrefixDuplicatedCause);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDeferredPrefixDuplicatedCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDeferredPrefixDuplicatedCause,
-      message: """'${name}' is used here.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        String
-            name)> templateDeferredTypeAnnotation = const Template<
-        Message Function(DartType _type, String name)>(
-    messageTemplate:
-        r"""The type '#type' is deferred loaded via prefix '#name' and can't be used as a type annotation.""",
-    tipTemplate:
-        r"""Try removing 'deferred' from the import of '#name' or use a supertype of '#type' that isn't deferred.""",
-    withArguments: _withArgumentsDeferredTypeAnnotation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, String name)>
-    codeDeferredTypeAnnotation =
-    const Code<Message Function(DartType _type, String name)>(
-        "DeferredTypeAnnotation", templateDeferredTypeAnnotation,
-        analyzerCodes: <String>["TYPE_ANNOTATION_DEFERRED_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDeferredTypeAnnotation(DartType _type, String name) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String type = typeParts.join();
-  return new Message(codeDeferredTypeAnnotation,
-      message:
-          """The type '${type}' is deferred loaded via prefix '${name}' and can't be used as a type annotation.""" +
-              labeler.originMessages,
-      tip: """Try removing 'deferred' from the import of '${name}' or use a supertype of '${type}' that isn't deferred.""",
-      arguments: {'type': _type, 'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-        Message Function(
-            int count, int count2, num _num1, num _num2, num _num3)>
-    templateDillOutlineSummary = const Template<
-            Message Function(
-                int count, int count2, num _num1, num _num2, num _num3)>(
-        messageTemplate:
-            r"""Indexed #count libraries (#count2 bytes) in #num1%.3ms, that is,
-#num2%12.3 bytes/ms, and
-#num3%12.3 ms/libraries.""",
-        withArguments: _withArgumentsDillOutlineSummary);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-    Message Function(int count, int count2, num _num1, num _num2,
-        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) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  if (_num1 == null) throw 'No number provided';
-  String num1 = _num1.toStringAsFixed(3);
-  if (_num2 == null) throw 'No number provided';
-  String num2 = _num2.toStringAsFixed(3).padLeft(12);
-  if (_num3 == null) throw 'No number provided';
-  String num3 = _num3.toStringAsFixed(3).padLeft(12);
-  return new Message(codeDillOutlineSummary,
-      message:
-          """Indexed ${count} libraries (${count2} bytes) in ${num1}ms, that is,
-${num2} bytes/ms, and
-${num3} ms/libraries.""",
-      arguments: {
-        'count': count,
-        'count2': count2,
-        'num1': _num1,
-        'num2': _num2,
-        'num3': _num3
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateDirectCycleInTypeVariables = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""Type '#name' can't use itself as a bound.""",
-    tipTemplate:
-        r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
-    withArguments: _withArgumentsDirectCycleInTypeVariables);
-
-// 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,
-        analyzerCodes: <String>["TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDirectCycleInTypeVariables(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDirectCycleInTypeVariables,
-      message: """Type '${name}' can't use itself as a bound.""",
-      tip:
-          """Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDirectiveAfterDeclaration =
-    messageDirectiveAfterDeclaration;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDirectiveAfterDeclaration = const MessageCode(
-    "DirectiveAfterDeclaration",
-    index: 69,
-    message: r"""Directives must appear before any declarations.""",
-    tip: r"""Try moving the directive before any declarations.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDuplicateDeferred = messageDuplicateDeferred;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDuplicateDeferred = const MessageCode(
-    "DuplicateDeferred",
-    index: 71,
-    message: r"""An import directive can only have one 'deferred' keyword.""",
-    tip: r"""Try removing all but one 'deferred' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicateLabelInSwitchStatement =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""The label '#name' was already used in this switch statement.""",
-        tipTemplate: r"""Try choosing a different name for this label.""",
-        withArguments: _withArgumentsDuplicateLabelInSwitchStatement);
-
-// 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.
-Message _withArgumentsDuplicateLabelInSwitchStatement(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicateLabelInSwitchStatement,
-      message:
-          """The label '${name}' was already used in this switch statement.""",
-      tip: """Try choosing a different name for this label.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDuplicatePrefix = messageDuplicatePrefix;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDuplicatePrefix = const MessageCode("DuplicatePrefix",
-    index: 73,
-    message: r"""An import directive can only have one prefix ('as' clause).""",
-    tip: r"""Try removing all but one prefix.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedDeclaration =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is already declared in this scope.""",
-        withArguments: _withArgumentsDuplicatedDeclaration);
-
-// 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,
-        analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedDeclaration(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedDeclaration,
-      message: """'${name}' is already declared in this scope.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicatedDeclarationCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Previous declaration of '#name'.""",
-        withArguments: _withArgumentsDuplicatedDeclarationCause);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedDeclarationCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedDeclarationCause,
-      message: """Previous declaration of '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateDuplicatedDeclarationSyntheticCause = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Previous declaration of '#name' is implied by this definition.""",
-    withArguments: _withArgumentsDuplicatedDeclarationSyntheticCause);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeDuplicatedDeclarationSyntheticCause =
-    const Code<Message Function(String name)>(
-        "DuplicatedDeclarationSyntheticCause",
-        templateDuplicatedDeclarationSyntheticCause,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedDeclarationSyntheticCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedDeclarationSyntheticCause,
-      message:
-          """Previous declaration of '${name}' is implied by this definition.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedDeclarationUse =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't use '#name' because it is declared more than once.""",
-        withArguments: _withArgumentsDuplicatedDeclarationUse);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsDuplicatedDeclarationUse(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedDeclarationUse,
-      message: """Can't use '${name}' because it is declared more than once.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateDuplicatedExport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""'#name' is exported from both '#uri' and '#uri2'.""",
-        withArguments: _withArgumentsDuplicatedExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeDuplicatedExport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedExport", templateDuplicatedExport,
-        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_);
-  return new Message(codeDuplicatedExport,
-      message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateDuplicatedExportInType =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""'#name' is exported from both '#uri' and '#uri2'.""",
-        withArguments: _withArgumentsDuplicatedExportInType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    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_);
-  return new Message(codeDuplicatedExportInType,
-      message: """'${name}' is exported from both '${uri}' and '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateDuplicatedImport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""'#name' is imported from both '#uri' and '#uri2'.""",
-        withArguments: _withArgumentsDuplicatedImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeDuplicatedImport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedImport", templateDuplicatedImport,
-        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_);
-  return new Message(codeDuplicatedImport,
-      message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateDuplicatedImportInType =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""'#name' is imported from both '#uri' and '#uri2'.""",
-        withArguments: _withArgumentsDuplicatedImportInType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeDuplicatedImportInType =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "DuplicatedImportInType", templateDuplicatedImportInType,
-        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_);
-  return new Message(codeDuplicatedImportInType,
-      message: """'${name}' is imported from both '${uri}' and '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedLibraryExport =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""A library with name '#name' is exported more than once.""",
-        withArguments: _withArgumentsDuplicatedLibraryExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeDuplicatedLibraryExport =
-    const Code<Message Function(String name)>(
-        "DuplicatedLibraryExport", templateDuplicatedLibraryExport,
-        analyzerCodes: <String>["EXPORT_DUPLICATED_LIBRARY_NAMED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedLibraryExport(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedLibraryExport,
-      message: """A library with name '${name}' is exported more than once.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicatedLibraryExportContext =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is also exported here.""",
-        withArguments: _withArgumentsDuplicatedLibraryExportContext);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeDuplicatedLibraryExportContext =
-    const Code<Message Function(String name)>("DuplicatedLibraryExportContext",
-        templateDuplicatedLibraryExportContext,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedLibraryExportContext(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedLibraryExportContext,
-      message: """'${name}' is also exported here.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedLibraryImport =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""A library with name '#name' is imported more than once.""",
-        withArguments: _withArgumentsDuplicatedLibraryImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeDuplicatedLibraryImport =
-    const Code<Message Function(String name)>(
-        "DuplicatedLibraryImport", templateDuplicatedLibraryImport,
-        analyzerCodes: <String>["IMPORT_DUPLICATED_LIBRARY_NAMED"],
-        severity: Severity.warning);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedLibraryImport(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedLibraryImport,
-      message: """A library with name '${name}' is imported more than once.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicatedLibraryImportContext =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is also imported here.""",
-        withArguments: _withArgumentsDuplicatedLibraryImportContext);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeDuplicatedLibraryImportContext =
-    const Code<Message Function(String name)>("DuplicatedLibraryImportContext",
-        templateDuplicatedLibraryImportContext,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedLibraryImportContext(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedLibraryImportContext,
-      message: """'${name}' is also imported here.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateDuplicatedModifier =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""The modifier '#lexeme' was already specified.""",
-        tipTemplate:
-            r"""Try removing all but one occurrence of the modifier.""",
-        withArguments: _withArgumentsDuplicatedModifier);
-
-// 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);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedModifier(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeDuplicatedModifier,
-      message: """The modifier '${lexeme}' was already specified.""",
-      tip: """Try removing all but one occurrence of the modifier.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateDuplicatedNamePreviouslyUsed = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Can't declare '#name' because it was already used in this scope.""",
-    withArguments: _withArgumentsDuplicatedNamePreviouslyUsed);
-
-// 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,
-        analyzerCodes: <String>["REFERENCED_BEFORE_DECLARATION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedNamePreviouslyUsed(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedNamePreviouslyUsed,
-      message:
-          """Can't declare '${name}' because it was already used in this scope.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicatedNamePreviouslyUsedCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Previous use of '#name'.""",
-        withArguments: _withArgumentsDuplicatedNamePreviouslyUsedCause);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeDuplicatedNamePreviouslyUsedCause =
-    const Code<Message Function(String name)>(
-        "DuplicatedNamePreviouslyUsedCause",
-        templateDuplicatedNamePreviouslyUsedCause,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedNamePreviouslyUsedCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedNamePreviouslyUsedCause,
-      message: """Previous use of '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedNamedArgument =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Duplicated named argument '#name'.""",
-        withArguments: _withArgumentsDuplicatedNamedArgument);
-
-// 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,
-        analyzerCodes: <String>["DUPLICATE_NAMED_ARGUMENT"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedNamedArgument(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedNamedArgument,
-      message: """Duplicated named argument '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateDuplicatedParameterName =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Duplicated parameter name '#name'.""",
-        withArguments: _withArgumentsDuplicatedParameterName);
-
-// 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,
-        analyzerCodes: <String>["DUPLICATE_DEFINITION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedParameterName(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedParameterName,
-      message: """Duplicated parameter name '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateDuplicatedParameterNameCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Other parameter named '#name'.""",
-        withArguments: _withArgumentsDuplicatedParameterNameCause);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsDuplicatedParameterNameCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeDuplicatedParameterNameCause,
-      message: """Other parameter named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEmptyNamedParameterList = messageEmptyNamedParameterList;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEmptyNamedParameterList = const MessageCode(
-    "EmptyNamedParameterList",
-    analyzerCodes: <String>["MISSING_IDENTIFIER"],
-    message: r"""Named parameter lists cannot be empty.""",
-    tip: r"""Try adding a named parameter to the list.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEmptyOptionalParameterList =
-    messageEmptyOptionalParameterList;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEmptyOptionalParameterList = const MessageCode(
-    "EmptyOptionalParameterList",
-    analyzerCodes: <String>["MISSING_IDENTIFIER"],
-    message: r"""Optional parameter lists cannot be empty.""",
-    tip: r"""Try adding an optional parameter to the list.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEncoding = messageEncoding;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEncoding = const MessageCode("Encoding",
-    message: r"""Unable to decode bytes as UTF-8.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateEnumConstantSameNameAsEnclosing = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Name of enum constant '#name' can't be the same as the enum's own name.""",
-    withArguments: _withArgumentsEnumConstantSameNameAsEnclosing);
-
-// 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.
-Message _withArgumentsEnumConstantSameNameAsEnclosing(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeEnumConstantSameNameAsEnclosing,
-      message:
-          """Name of enum constant '${name}' can't be the same as the enum's own name.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEnumDeclarationEmpty = messageEnumDeclarationEmpty;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEnumDeclarationEmpty = const MessageCode(
-    "EnumDeclarationEmpty",
-    analyzerCodes: <String>["EMPTY_ENUM_BODY"],
-    message: r"""An enum declaration can't be empty.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEnumInClass = messageEnumInClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEnumInClass = const MessageCode("EnumInClass",
-    index: 74,
-    message: r"""Enums can't be declared inside classes.""",
-    tip: r"""Try moving the enum to the top-level.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEnumInstantiation = messageEnumInstantiation;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEnumInstantiation = const MessageCode(
-    "EnumInstantiation",
-    analyzerCodes: <String>["INSTANTIATE_ENUM"],
-    message: r"""Enums can't be instantiated.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeEqualityCannotBeEqualityOperand =
-    messageEqualityCannotBeEqualityOperand;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageEqualityCannotBeEqualityOperand = const MessageCode(
-    "EqualityCannotBeEqualityOperand",
-    index: 1,
-    message:
-        r"""A comparison expression can't be an operand of another comparison expression.""",
-    tip: r"""Try putting parentheses around one of the comparisons.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateExpectedAfterButGot =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Expected '#string' after this.""",
-        withArguments: _withArgumentsExpectedAfterButGot);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_TOKEN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedAfterButGot(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExpectedAfterButGot,
-      message: """Expected '${string}' after this.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedAnInitializer = messageExpectedAnInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedAnInitializer = const MessageCode(
-    "ExpectedAnInitializer",
-    index: 36,
-    message: r"""Expected an initializer.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedBlock = messageExpectedBlock;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedBlock = const MessageCode("ExpectedBlock",
-    analyzerCodes: <String>["EXPECTED_TOKEN"],
-    message: r"""Expected a block.""",
-    tip: r"""Try adding {}.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedBlockToSkip = messageExpectedBlockToSkip;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedBlockToSkip = const MessageCode(
-    "ExpectedBlockToSkip",
-    analyzerCodes: <String>["MISSING_FUNCTION_BODY"],
-    message: r"""Expected a function body or '=>'.""",
-    tip: r"""Try adding {}.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedBody = messageExpectedBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedBody = const MessageCode("ExpectedBody",
-    analyzerCodes: <String>["MISSING_FUNCTION_BODY"],
-    message: r"""Expected a function body or '=>'.""",
-    tip: r"""Try adding {}.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateExpectedButGot =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Expected '#string' before this.""",
-        withArguments: _withArgumentsExpectedButGot);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_TOKEN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedButGot(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExpectedButGot,
-      message: """Expected '${string}' before this.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassMember =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected a class member, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedClassMember);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_CLASS_MEMBER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassMember(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedClassMember,
-      message: """Expected a class member, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateExpectedClassOrMixinBody =
-    const Template<Message Function(String string)>(
-        messageTemplate:
-            r"""A #string must have a body, even if it is empty.""",
-        tipTemplate: r"""Try adding an empty body.""",
-        withArguments: _withArgumentsExpectedClassOrMixinBody);
-
-// 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,
-        index: 8);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassOrMixinBody(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExpectedClassOrMixinBody,
-      message: """A ${string} must have a body, even if it is empty.""",
-      tip: """Try adding an empty body.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedDeclaration =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected a declaration, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedDeclaration);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_EXECUTABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedDeclaration(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedDeclaration,
-      message: """Expected a declaration, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedElseOrComma = messageExpectedElseOrComma;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedElseOrComma = const MessageCode(
-    "ExpectedElseOrComma",
-    index: 46,
-    message: r"""Expected 'else' or comma.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Token token)> templateExpectedEnumBody = const Template<
-        Message Function(Token token)>(
-    messageTemplate: r"""Expected a enum body, but got '#lexeme'.""",
-    tipTemplate:
-        r"""An enum definition must have a body with at least one constant name.""",
-    withArguments: _withArgumentsExpectedEnumBody);
-
-// 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,
-        analyzerCodes: <String>["MISSING_ENUM_BODY"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedEnumBody(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedEnumBody,
-      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});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedFunctionBody =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected a function body, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedFunctionBody);
-
-// 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,
-        analyzerCodes: <String>["MISSING_FUNCTION_BODY"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedFunctionBody(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedFunctionBody,
-      message: """Expected a function body, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedHexDigit = messageExpectedHexDigit;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedHexDigit = const MessageCode(
-    "ExpectedHexDigit",
-    analyzerCodes: <String>["MISSING_HEX_DIGIT"],
-    message: r"""A hex digit (0-9 or A-F) must follow '0x'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedIdentifier =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected an identifier, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedIdentifier);
-
-// 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,
-        analyzerCodes: <String>["MISSING_IDENTIFIER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedIdentifier(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedIdentifier,
-      message: """Expected an identifier, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateExpectedInstead =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Expected '#string' instead of this.""",
-        withArguments: _withArgumentsExpectedInstead);
-
-// 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);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedInstead(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExpectedInstead,
-      message: """Expected '${string}' instead of this.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedNamedArgument = messageExpectedNamedArgument;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedNamedArgument = const MessageCode(
-    "ExpectedNamedArgument",
-    analyzerCodes: <String>["EXTRA_POSITIONAL_ARGUMENTS"],
-    message: r"""Expected named argument.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedOneExpression = messageExpectedOneExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedOneExpression = const MessageCode(
-    "ExpectedOneExpression",
-    message: r"""Expected one expression, but found additional input.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedOpenParens = messageExpectedOpenParens;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedOpenParens =
-    const MessageCode("ExpectedOpenParens", message: r"""Expected '('.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedStatement = messageExpectedStatement;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedStatement = const MessageCode(
-    "ExpectedStatement",
-    index: 29,
-    message: r"""Expected a statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedString =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected a String, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedString);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_STRING_LITERAL"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedString(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedString,
-      message: """Expected a String, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateExpectedToken =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Expected to find '#string'.""",
-        withArguments: _withArgumentsExpectedToken);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_TOKEN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedToken(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExpectedToken,
-      message: """Expected to find '${string}'.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedType =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Expected a type, but got '#lexeme'.""",
-        withArguments: _withArgumentsExpectedType);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_TYPE_NAME"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedType(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExpectedType,
-      message: """Expected a type, but got '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpectedUri = messageExpectedUri;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpectedUri =
-    const MessageCode("ExpectedUri", message: r"""Expected a URI.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            string)> templateExperimentNotEnabled = const Template<
-        Message Function(String string)>(
-    messageTemplate:
-        r"""This requires the '#string' experiment to be enabled.""",
-    tipTemplate:
-        r"""Try enabling this experiment by adding it to the command line when compiling and running.""",
-    withArguments: _withArgumentsExperimentNotEnabled);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)> codeExperimentNotEnabled =
-    const Code<Message Function(String string)>(
-        "ExperimentNotEnabled", templateExperimentNotEnabled,
-        index: 48);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExperimentNotEnabled(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeExperimentNotEnabled,
-      message: """This requires the '${string}' experiment to be enabled.""",
-      tip:
-          """Try enabling this experiment by adding it to the command line when compiling and running.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExplicitExtensionArgumentMismatch =
-    messageExplicitExtensionArgumentMismatch;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExplicitExtensionArgumentMismatch = const MessageCode(
-    "ExplicitExtensionArgumentMismatch",
-    message:
-        r"""Explicit extension application requires exactly 1 positional argument.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExplicitExtensionAsExpression =
-    messageExplicitExtensionAsExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExplicitExtensionAsExpression = const MessageCode(
-    "ExplicitExtensionAsExpression",
-    message:
-        r"""Explicit extension application cannot be used as an expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExplicitExtensionAsLvalue =
-    messageExplicitExtensionAsLvalue;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExplicitExtensionAsLvalue = const MessageCode(
-    "ExplicitExtensionAsLvalue",
-    message:
-        r"""Explicit extension application cannot be a target for assignment.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        int
-            count)> templateExplicitExtensionTypeArgumentMismatch = const Template<
-        Message Function(String name, int count)>(
-    messageTemplate:
-        r"""Explicit extension application of extension '#name' takes '#count' type argument(s).""",
-    withArguments: _withArgumentsExplicitExtensionTypeArgumentMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, int count)>
-    codeExplicitExtensionTypeArgumentMismatch =
-    const Code<Message Function(String name, int count)>(
-  "ExplicitExtensionTypeArgumentMismatch",
-  templateExplicitExtensionTypeArgumentMismatch,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExplicitExtensionTypeArgumentMismatch(
-    String name, int count) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (count == null) throw 'No count provided';
-  return new Message(codeExplicitExtensionTypeArgumentMismatch,
-      message:
-          """Explicit extension application of extension '${name}' takes '${count}' type argument(s).""",
-      arguments: {'name': name, 'count': count});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExportAfterPart = messageExportAfterPart;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExportAfterPart = const MessageCode("ExportAfterPart",
-    index: 75,
-    message: r"""Export directives must precede part directives.""",
-    tip: r"""Try moving the export directives before the part directives.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateExportHidesExport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""Export of '#name' (from '#uri') hides export from '#uri2'.""",
-        withArguments: _withArgumentsExportHidesExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeExportHidesExport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ExportHidesExport", templateExportHidesExport,
-        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_);
-  return new Message(codeExportHidesExport,
-      message:
-          """Export of '${name}' (from '${uri}') hides export from '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExpressionNotMetadata = messageExpressionNotMetadata;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExpressionNotMetadata = const MessageCode(
-    "ExpressionNotMetadata",
-    message:
-        r"""This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateExtendingEnum =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""'#name' is an enum and can't be extended or implemented.""",
-        withArguments: _withArgumentsExtendingEnum);
-
-// 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,
-        analyzerCodes: <String>["EXTENDS_ENUM"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExtendingEnum(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeExtendingEnum,
-      message: """'${name}' is an enum and can't be extended or implemented.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateExtendingRestricted =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""'#name' is restricted and can't be extended or implemented.""",
-        withArguments: _withArgumentsExtendingRestricted);
-
-// 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,
-        analyzerCodes: <String>["EXTENDS_DISALLOWED_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExtendingRestricted(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeExtendingRestricted,
-      message:
-          """'${name}' is restricted and can't be extended or implemented.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExtensionDeclaresAbstractMember =
-    messageExtensionDeclaresAbstractMember;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExtensionDeclaresAbstractMember = const MessageCode(
-    "ExtensionDeclaresAbstractMember",
-    index: 94,
-    message: r"""Extensions can't declare abstract members.""",
-    tip: r"""Try providing an implementation for the member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExtensionDeclaresConstructor =
-    messageExtensionDeclaresConstructor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExtensionDeclaresConstructor = const MessageCode(
-    "ExtensionDeclaresConstructor",
-    index: 92,
-    message: r"""Extensions can't declare constructors.""",
-    tip: r"""Try removing the constructor declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExtensionDeclaresInstanceField =
-    messageExtensionDeclaresInstanceField;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExtensionDeclaresInstanceField = const MessageCode(
-    "ExtensionDeclaresInstanceField",
-    index: 93,
-    message: r"""Extensions can't declare instance fields""",
-    tip: r"""Try removing the field declaration or making it a static field""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateExtensionMemberConflictsWithObjectMember =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""This extension member conflicts with Object member '#name'.""",
-        withArguments: _withArgumentsExtensionMemberConflictsWithObjectMember);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeExtensionMemberConflictsWithObjectMember =
-    const Code<Message Function(String name)>(
-  "ExtensionMemberConflictsWithObjectMember",
-  templateExtensionMemberConflictsWithObjectMember,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExtensionMemberConflictsWithObjectMember(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeExtensionMemberConflictsWithObjectMember,
-      message:
-          """This extension member conflicts with Object member '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalClass = messageExternalClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalClass = const MessageCode("ExternalClass",
-    index: 3,
-    message: r"""Classes can't be declared to be 'external'.""",
-    tip: r"""Try removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalConstructorWithBody =
-    messageExternalConstructorWithBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalConstructorWithBody = const MessageCode(
-    "ExternalConstructorWithBody",
-    index: 87,
-    message: r"""External constructors can't have a body.""",
-    tip:
-        r"""Try removing the body of the constructor, or removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalConstructorWithFieldInitializers =
-    messageExternalConstructorWithFieldInitializers;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalConstructorWithFieldInitializers =
-    const MessageCode("ExternalConstructorWithFieldInitializers",
-        analyzerCodes: <String>["EXTERNAL_CONSTRUCTOR_WITH_FIELD_INITIALIZERS"],
-        message: r"""An external constructor can't initialize fields.""",
-        tip:
-            r"""Try removing the field initializers, or removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalEnum = messageExternalEnum;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalEnum = const MessageCode("ExternalEnum",
-    index: 5,
-    message: r"""Enums can't be declared to be 'external'.""",
-    tip: r"""Try removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalFactoryRedirection =
-    messageExternalFactoryRedirection;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalFactoryRedirection = const MessageCode(
-    "ExternalFactoryRedirection",
-    index: 85,
-    message: r"""A redirecting factory can't be external.""",
-    tip: r"""Try removing the 'external' modifier.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalFactoryWithBody = messageExternalFactoryWithBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalFactoryWithBody = const MessageCode(
-    "ExternalFactoryWithBody",
-    index: 86,
-    message: r"""External factories can't have a body.""",
-    tip:
-        r"""Try removing the body of the factory, or removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalField = messageExternalField;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalField = const MessageCode("ExternalField",
-    index: 50,
-    message: r"""Fields can't be declared to be 'external'.""",
-    tip:
-        r"""Try removing the keyword 'external', or replacing the field by an external getter and/or setter.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalMethodWithBody = messageExternalMethodWithBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalMethodWithBody = const MessageCode(
-    "ExternalMethodWithBody",
-    index: 49,
-    message: r"""An external or native method can't have a body.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalTypedef = messageExternalTypedef;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalTypedef = const MessageCode("ExternalTypedef",
-    index: 76,
-    message: r"""Typedefs can't be declared to be 'external'.""",
-    tip: r"""Try removing the keyword 'external'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExtraneousModifier =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Can't have modifier '#lexeme' here.""",
-        tipTemplate: r"""Try removing '#lexeme'.""",
-        withArguments: _withArgumentsExtraneousModifier);
-
-// 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);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExtraneousModifier(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExtraneousModifier,
-      message: """Can't have modifier '${lexeme}' here.""",
-      tip: """Try removing '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)>
-    templateExtraneousModifierInExtension =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Can't have modifier '#lexeme' in an extension.""",
-        tipTemplate: r"""Try removing '#lexeme'.""",
-        withArguments: _withArgumentsExtraneousModifierInExtension);
-
-// 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,
-        index: 98);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExtraneousModifierInExtension(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeExtraneousModifierInExtension,
-      message: """Can't have modifier '${lexeme}' in an extension.""",
-      tip: """Try removing '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFactoryNotSync = messageFactoryNotSync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFactoryNotSync = const MessageCode("FactoryNotSync",
-    analyzerCodes: <String>["NON_SYNC_FACTORY"],
-    message: r"""Factory bodies can't use 'async', 'async*', or 'sync*'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFactoryTopLevelDeclaration =
-    messageFactoryTopLevelDeclaration;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFactoryTopLevelDeclaration = const MessageCode(
-    "FactoryTopLevelDeclaration",
-    index: 78,
-    message: r"""Top-level declarations can't be declared to be 'factory'.""",
-    tip: r"""Try removing the keyword 'factory'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateFastaCLIArgumentRequired =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Expected value after '#name'.""",
-        withArguments: _withArgumentsFastaCLIArgumentRequired);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsFastaCLIArgumentRequired(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFastaCLIArgumentRequired,
-      message: """Expected value after '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFastaUsageLong = messageFastaUsageLong;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFastaUsageLong =
-    const MessageCode("FastaUsageLong", message: r"""Supported options:
-
-  -o <file>, --output=<file>
-    Generate the output into <file>.
-
-  -h, /h, /?, --help
-    Display this message (add -v for information about all options).
-
-  -v, --verbose
-    Display verbose information.
-
-  -Dname
-  -Dname=value
-    Define an environment variable in the compile-time environment.
-
-  --no-defines
-    Ignore all -D options and leave environment constants unevaluated.
-
-  --
-    Stop option parsing, the rest of the command line is assumed to be
-    file names or arguments to the Dart program.
-
-  --packages=<file>
-    Use package resolution configuration <file>, which should contain a mapping
-    of package names to paths.
-
-  --platform=<file>
-    Read the SDK platform from <file>, which should be in Dill/Kernel IR format
-    and contain the Dart SDK.
-
-  --target=dart2js|dart2js_server|dart_runner|dartdevc|flutter|flutter_runner|none|vm
-    Specify the target configuration.
-
-  --enable-asserts
-    Check asserts in initializers during constant evaluation.
-
-  --verify
-    Check that the generated output is free of various problems. This is mostly
-    useful for developers of this compiler or Kernel transformations.
-
-  --dump-ir
-    Print compiled libraries in Kernel source notation.
-
-  --omit-platform
-    Exclude the platform from the serialized dill file.
-
-  --bytecode
-    Generate bytecode. Supported only for SDK platform compilation.
-
-  --exclude-source
-    Do not include source code in the dill file.
-
-  --compile-sdk=<sdk>
-    Compile the SDK from scratch instead of reading it from a .dill file
-    (see --platform).
-
-  --sdk=<sdk>
-    Location of the SDK sources for use when compiling additional platform
-    libraries.
-
-  --supermixin
-    Ignored for now.
-
-  --single-root-scheme=String
-  --single-root-base=<dir>
-    Specify a custom URI scheme and a location on disk where such URIs are
-    mapped to.
-
-    When specified, the compiler can be invoked with inputs using the custom
-    URI scheme. The compiler can ignore the exact location of files on disk
-    and as a result to produce output that is independent of the absolute
-    location of files on disk. This is mostly useful for integrating with
-    build systems.
-
-  --fatal=errors
-  --fatal=warnings
-    Makes messages of the given kinds fatal, that is, immediately stop the
-    compiler with a non-zero exit-code. In --verbose mode, also display an
-    internal stack trace from the compiler. Multiple kinds can be separated by
-    commas, for example, --fatal=errors,warnings.
-
-  --fatal-skip=<number>
-  --fatal-skip=trace
-    Skip this many messages that would otherwise be fatal before aborting the
-    compilation. Default is 0, which stops at the first message. Specify
-    'trace' to print a stack trace for every message without stopping.
-
-  --enable-experiment=<flag>
-    Enable or disable an experimental flag, used to guard features currently
-    in development. Prefix an experiment name with 'no-' to disable it.
-    Multiple experiments can be separated by commas.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFastaUsageShort = messageFastaUsageShort;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFastaUsageShort =
-    const MessageCode("FastaUsageShort", message: r"""Frequently used options:
-
-  -o <file> Generate the output into <file>.
-  -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(DartType _type, DartType _type2)>
-    templateFfiDartTypeMismatch =
-    const Template<Message Function(DartType _type, DartType _type2)>(
-        messageTemplate: r"""Expected '#type' to be a subtype of '#type2'.""",
-        withArguments: _withArgumentsFfiDartTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeFfiDartTypeMismatch =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-  "FfiDartTypeMismatch",
-  templateFfiDartTypeMismatch,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiDartTypeMismatch(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeFfiDartTypeMismatch,
-      message: """Expected '${type}' to be a subtype of '${type2}'.""" +
-          labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// 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.
-const MessageCode messageFfiExceptionalReturnNull = const MessageCode(
-    "FfiExceptionalReturnNull",
-    message: r"""Exceptional return value must not be null.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFfiExpectedConstant = messageFfiExpectedConstant;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFfiExpectedConstant = const MessageCode(
-    "FfiExpectedConstant",
-    message: r"""Exceptional return value must be a constant.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateFfiExpectedExceptionalReturn = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Expected an exceptional return value for a native callback returning '#type'.""",
-    withArguments: _withArgumentsFfiExpectedExceptionalReturn);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeFfiExpectedExceptionalReturn =
-    const Code<Message Function(DartType _type)>(
-  "FfiExpectedExceptionalReturn",
-  templateFfiExpectedExceptionalReturn,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiExpectedExceptionalReturn(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeFfiExpectedExceptionalReturn,
-      message:
-          """Expected an exceptional return value for a native callback returning '${type}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateFfiExpectedNoExceptionalReturn = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Exceptional return value cannot be provided for a native callback returning '#type'.""",
-    withArguments: _withArgumentsFfiExpectedNoExceptionalReturn);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)>
-    codeFfiExpectedNoExceptionalReturn =
-    const Code<Message Function(DartType _type)>(
-  "FfiExpectedNoExceptionalReturn",
-  templateFfiExpectedNoExceptionalReturn,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiExpectedNoExceptionalReturn(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeFfiExpectedNoExceptionalReturn,
-      message:
-          """Exceptional return value cannot be provided for a native callback returning '${type}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateFfiExtendsOrImplementsSealedClass =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Class '#name' cannot be extended or implemented.""",
-        withArguments: _withArgumentsFfiExtendsOrImplementsSealedClass);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeFfiExtendsOrImplementsSealedClass =
-    const Code<Message Function(String name)>(
-  "FfiExtendsOrImplementsSealedClass",
-  templateFfiExtendsOrImplementsSealedClass,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiExtendsOrImplementsSealedClass(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiExtendsOrImplementsSealedClass,
-      message: """Class '${name}' cannot be extended or implemented.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(String name)> templateFfiFieldAnnotation = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Field '#name' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
-    withArguments: _withArgumentsFfiFieldAnnotation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsFfiFieldAnnotation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiFieldAnnotation,
-      message:
-          """Field '${name}' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs cannot have regular Dart fields.""",
-      arguments: {'name': name});
-}
-
-// 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.""",
-    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.
-Message _withArgumentsFfiFieldInitializer(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiFieldInitializer,
-      message:
-          """Field '${name}' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateFfiFieldNoAnnotation = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""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.""",
-    withArguments: _withArgumentsFfiFieldNoAnnotation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsFfiFieldNoAnnotation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiFieldNoAnnotation,
-      message:
-          """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.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(String name)> templateFfiNotStatic = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""",
-    withArguments: _withArgumentsFfiNotStatic);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsFfiNotStatic(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiNotStatic,
-      message:
-          """${name} expects a static function as parameter. dart:ffi only supports calling static Dart functions from native code.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateFfiStructGeneric =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Struct '#name' should not be generic.""",
-        withArguments: _withArgumentsFfiStructGeneric);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsFfiStructGeneric(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFfiStructGeneric,
-      message: """Struct '${name}' should not be generic.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(DartType _type)> templateFfiTypeInvalid = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Expected type '#type' to be a valid and instantiated subtype of 'NativeType'.""",
-    withArguments: _withArgumentsFfiTypeInvalid);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeFfiTypeInvalid =
-    const Code<Message Function(DartType _type)>(
-  "FfiTypeInvalid",
-  templateFfiTypeInvalid,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiTypeInvalid(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeFfiTypeInvalid,
-      message:
-          """Expected type '${type}' to be a valid and instantiated subtype of 'NativeType'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        DartType
-            _type3)> templateFfiTypeMismatch = const Template<
-        Message Function(DartType _type, DartType _type2, DartType _type3)>(
-    messageTemplate:
-        r"""Expected type '#type' to be '#type2', which is the Dart type corresponding to '#type3'.""",
-    withArguments: _withArgumentsFfiTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2, DartType _type3)>
-    codeFfiTypeMismatch = const Code<
-        Message Function(DartType _type, DartType _type2, DartType _type3)>(
-  "FfiTypeMismatch",
-  templateFfiTypeMismatch,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiTypeMismatch(
-    DartType _type, DartType _type2, DartType _type3) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  List<Object> type3Parts = labeler.labelType(_type3);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  String type3 = type3Parts.join();
-  return new Message(codeFfiTypeMismatch,
-      message:
-          """Expected type '${type}' to be '${type2}', which is the Dart type corresponding to '${type3}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2, 'type3': _type3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFieldInitializedOutsideDeclaringClass =
-    messageFieldInitializedOutsideDeclaringClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFieldInitializedOutsideDeclaringClass = const MessageCode(
-    "FieldInitializedOutsideDeclaringClass",
-    index: 88,
-    message: r"""A field can only be initialized in its declaring class""",
-    tip:
-        r"""Try passing a value into the superclass constructor, or moving the initialization into the constructor body.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFieldInitializerOutsideConstructor =
-    messageFieldInitializerOutsideConstructor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFieldInitializerOutsideConstructor = const MessageCode(
-    "FieldInitializerOutsideConstructor",
-    index: 79,
-    message: r"""Field formal parameters can only be used in a constructor.""",
-    tip: r"""Try removing 'this.'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFinalAndCovariant = messageFinalAndCovariant;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFinalAndCovariant = const MessageCode(
-    "FinalAndCovariant",
-    index: 80,
-    message:
-        r"""Members can't be declared to be both 'final' and 'covariant'.""",
-    tip: r"""Try removing either the 'final' or 'covariant' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFinalAndVar = messageFinalAndVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFinalAndVar = const MessageCode("FinalAndVar",
-    index: 81,
-    message: r"""Members can't be declared to be both 'final' and 'var'.""",
-    tip: r"""Try removing the keyword 'var'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateFinalFieldNotInitialized = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""Final field '#name' is not initialized.""",
-    tipTemplate:
-        r"""Try to initialize the field in the declaration or in every constructor.""",
-    withArguments: _withArgumentsFinalFieldNotInitialized);
-
-// 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,
-        analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFinalFieldNotInitialized(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFinalFieldNotInitialized,
-      message: """Final field '${name}' is not initialized.""",
-      tip:
-          """Try to initialize the field in the declaration or in every constructor.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateFinalFieldNotInitializedByConstructor = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Final field '#name' is not initialized by this constructor.""",
-    tipTemplate:
-        r"""Try to initialize the field using an initializing formal or a field initializer.""",
-    withArguments: _withArgumentsFinalFieldNotInitializedByConstructor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    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.
-Message _withArgumentsFinalFieldNotInitializedByConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFinalFieldNotInitializedByConstructor,
-      message:
-          """Final field '${name}' is not initialized by this constructor.""",
-      tip:
-          """Try to initialize the field using an initializing formal or a field initializer.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateFinalFieldWithoutInitializer = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""The final variable '#name' must be initialized.""",
-    tipTemplate:
-        r"""Try adding an initializer ('= expression') to the declaration.""",
-    withArguments: _withArgumentsFinalFieldWithoutInitializer);
-
-// 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,
-        analyzerCodes: <String>["FINAL_NOT_INITIALIZED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFinalFieldWithoutInitializer(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFinalFieldWithoutInitializer,
-      message: """The final variable '${name}' must be initialized.""",
-      tip: """Try adding an initializer ('= expression') to the declaration.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateFinalInstanceVariableAlreadyInitialized =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""'#name' is a final instance variable that has already been initialized.""",
-        withArguments: _withArgumentsFinalInstanceVariableAlreadyInitialized);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeFinalInstanceVariableAlreadyInitialized =
-    const Code<Message Function(String name)>(
-        "FinalInstanceVariableAlreadyInitialized",
-        templateFinalInstanceVariableAlreadyInitialized,
-        analyzerCodes: <String>["FINAL_INITIALIZED_MULTIPLE_TIMES"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFinalInstanceVariableAlreadyInitialized(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFinalInstanceVariableAlreadyInitialized,
-      message:
-          """'${name}' is a final instance variable that has already been initialized.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateFinalInstanceVariableAlreadyInitializedCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' was initialized here.""",
-        withArguments:
-            _withArgumentsFinalInstanceVariableAlreadyInitializedCause);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeFinalInstanceVariableAlreadyInitializedCause =
-    const Code<Message Function(String name)>(
-        "FinalInstanceVariableAlreadyInitializedCause",
-        templateFinalInstanceVariableAlreadyInitializedCause,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFinalInstanceVariableAlreadyInitializedCause(
-    String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeFinalInstanceVariableAlreadyInitializedCause,
-      message: """'${name}' was initialized here.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateForInLoopElementTypeNotAssignable = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""A value of type '#type' can't be assigned to a variable of type '#type2'.""",
-    tipTemplate: r"""Try changing the type of the variable.""",
-    withArguments: _withArgumentsForInLoopElementTypeNotAssignable);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeForInLoopElementTypeNotAssignable =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "ForInLoopElementTypeNotAssignable",
-        templateForInLoopElementTypeNotAssignable,
-        analyzerCodes: <String>["FOR_IN_OF_INVALID_ELEMENT_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsForInLoopElementTypeNotAssignable(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeForInLoopElementTypeNotAssignable,
-      message:
-          """A value of type '${type}' can't be assigned to a variable of type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Try changing the type of the variable.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeForInLoopExactlyOneVariable =
-    messageForInLoopExactlyOneVariable;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageForInLoopExactlyOneVariable = const MessageCode(
-    "ForInLoopExactlyOneVariable",
-    message: r"""A for-in loop can't have more than one loop variable.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeForInLoopNotAssignable = messageForInLoopNotAssignable;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageForInLoopNotAssignable = const MessageCode(
-    "ForInLoopNotAssignable",
-    message:
-        r"""Can't assign to this, so it can't be used in a for-in loop.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateForInLoopTypeNotIterable = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The type '#type' used in the 'for' loop must implement '#type2'.""",
-    withArguments: _withArgumentsForInLoopTypeNotIterable);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeForInLoopTypeNotIterable =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "ForInLoopTypeNotIterable", templateForInLoopTypeNotIterable,
-        analyzerCodes: <String>["FOR_IN_OF_INVALID_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsForInLoopTypeNotIterable(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeForInLoopTypeNotIterable,
-      message:
-          """The type '${type}' used in the 'for' loop must implement '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeForInLoopWithConstVariable =
-    messageForInLoopWithConstVariable;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageForInLoopWithConstVariable = const MessageCode(
-    "ForInLoopWithConstVariable",
-    analyzerCodes: <String>["FOR_IN_WITH_CONST_VARIABLE"],
-    message: r"""A for-in loop-variable can't be 'const'.""",
-    tip: r"""Try removing the 'const' modifier.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFunctionTypeDefaultValue = messageFunctionTypeDefaultValue;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFunctionTypeDefaultValue = const MessageCode(
-    "FunctionTypeDefaultValue",
-    analyzerCodes: <String>["DEFAULT_VALUE_IN_FUNCTION_TYPE"],
-    message: r"""Can't have a default value in a function type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeFunctionTypedParameterVar =
-    messageFunctionTypedParameterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageFunctionTypedParameterVar = const MessageCode(
-    "FunctionTypedParameterVar",
-    analyzerCodes: <String>["FUNCTION_TYPED_PARAMETER_VAR"],
-    message:
-        r"""Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type.""",
-    tip: r"""Try replacing the keyword with a return type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageGeneratorReturnsValue = const MessageCode(
-    "GeneratorReturnsValue",
-    analyzerCodes: <String>["RETURN_IN_GENERATOR"],
-    message: r"""'sync*' and 'async*' can't return a value.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeGenericFunctionTypeInBound =
-    messageGenericFunctionTypeInBound;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageGenericFunctionTypeInBound = const MessageCode(
-    "GenericFunctionTypeInBound",
-    analyzerCodes: <String>["GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND"],
-    message:
-        r"""Type variables can't have generic function types in their bounds.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(DartType _type)>
-    templateGenericFunctionTypeInferredAsActualTypeArgument =
-    const Template<Message Function(DartType _type)>(
-        messageTemplate:
-            r"""Generic function type '#type' inferred as a type argument.""",
-        tipTemplate:
-            r"""Try providing a non-generic function type explicitly.""",
-        withArguments:
-            _withArgumentsGenericFunctionTypeInferredAsActualTypeArgument);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)>
-    codeGenericFunctionTypeInferredAsActualTypeArgument =
-    const Code<Message Function(DartType _type)>(
-        "GenericFunctionTypeInferredAsActualTypeArgument",
-        templateGenericFunctionTypeInferredAsActualTypeArgument,
-        analyzerCodes: <String>["GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsGenericFunctionTypeInferredAsActualTypeArgument(
-    DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeGenericFunctionTypeInferredAsActualTypeArgument,
-      message:
-          """Generic function type '${type}' inferred as a type argument.""" +
-              labeler.originMessages,
-      tip: """Try providing a non-generic function type explicitly.""",
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeGenericFunctionTypeUsedAsActualTypeArgument =
-    messageGenericFunctionTypeUsedAsActualTypeArgument;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageGenericFunctionTypeUsedAsActualTypeArgument =
-    const MessageCode("GenericFunctionTypeUsedAsActualTypeArgument",
-        analyzerCodes: <String>["GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT"],
-        message:
-            r"""A generic function type can't be used as a type argument.""",
-        tip: r"""Try using a non-generic function type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateGetterNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Getter not found: '#name'.""",
-        withArguments: _withArgumentsGetterNotFound);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_GETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsGetterNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeGetterNotFound,
-      message: """Getter not found: '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeGetterWithFormals = messageGetterWithFormals;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageGetterWithFormals = const MessageCode(
-    "GetterWithFormals",
-    analyzerCodes: <String>["GETTER_WITH_PARAMETERS"],
-    message: r"""A getter can't have formal parameters.""",
-    tip: r"""Try removing '(...)'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalAssignmentToNonAssignable =
-    messageIllegalAssignmentToNonAssignable;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalAssignmentToNonAssignable = const MessageCode(
-    "IllegalAssignmentToNonAssignable",
-    index: 45,
-    message: r"""Illegal assignment to non-assignable expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalAsyncGeneratorReturnType =
-    messageIllegalAsyncGeneratorReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalAsyncGeneratorReturnType = const MessageCode(
-    "IllegalAsyncGeneratorReturnType",
-    analyzerCodes: <String>["ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE"],
-    message:
-        r"""Functions marked 'async*' must have a return type assignable to 'Stream'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalAsyncGeneratorVoidReturnType =
-    messageIllegalAsyncGeneratorVoidReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalAsyncGeneratorVoidReturnType =
-    const MessageCode("IllegalAsyncGeneratorVoidReturnType",
-        message:
-            r"""Functions marked 'async*' can't have return type 'void'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalAsyncReturnType = messageIllegalAsyncReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalAsyncReturnType = const MessageCode(
-    "IllegalAsyncReturnType",
-    analyzerCodes: <String>["ILLEGAL_ASYNC_RETURN_TYPE"],
-    message:
-        r"""Functions marked 'async' must have a return type assignable to 'Future'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateIllegalMixin =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""The type '#name' can't be mixed in.""",
-        withArguments: _withArgumentsIllegalMixin);
-
-// 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,
-        analyzerCodes: <String>["ILLEGAL_MIXIN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIllegalMixin(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeIllegalMixin,
-      message: """The type '${name}' can't be mixed in.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateIllegalMixinDueToConstructors =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't use '#name' as a mixin because it has constructors.""",
-        withArguments: _withArgumentsIllegalMixinDueToConstructors);
-
-// 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,
-        analyzerCodes: <String>["MIXIN_DECLARES_CONSTRUCTOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIllegalMixinDueToConstructors(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeIllegalMixinDueToConstructors,
-      message:
-          """Can't use '${name}' as a mixin because it has constructors.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateIllegalMixinDueToConstructorsCause =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""This constructor prevents using '#name' as a mixin.""",
-        withArguments: _withArgumentsIllegalMixinDueToConstructorsCause);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeIllegalMixinDueToConstructorsCause =
-    const Code<Message Function(String name)>(
-        "IllegalMixinDueToConstructorsCause",
-        templateIllegalMixinDueToConstructorsCause,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIllegalMixinDueToConstructorsCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeIllegalMixinDueToConstructorsCause,
-      message: """This constructor prevents using '${name}' as a mixin.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(DartType _type)> templateIllegalRecursiveType =
-    const Template<Message Function(DartType _type)>(
-        messageTemplate: r"""Illegal recursive type '#type'.""",
-        withArguments: _withArgumentsIllegalRecursiveType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeIllegalRecursiveType =
-    const Code<Message Function(DartType _type)>(
-  "IllegalRecursiveType",
-  templateIllegalRecursiveType,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIllegalRecursiveType(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeIllegalRecursiveType,
-      message: """Illegal recursive type '${type}'.""" + labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalSyncGeneratorReturnType =
-    messageIllegalSyncGeneratorReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalSyncGeneratorReturnType = const MessageCode(
-    "IllegalSyncGeneratorReturnType",
-    analyzerCodes: <String>["ILLEGAL_SYNC_GENERATOR_RETURN_TYPE"],
-    message:
-        r"""Functions marked 'sync*' must have a return type assignable to 'Iterable'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIllegalSyncGeneratorVoidReturnType =
-    messageIllegalSyncGeneratorVoidReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIllegalSyncGeneratorVoidReturnType = const MessageCode(
-    "IllegalSyncGeneratorVoidReturnType",
-    message: r"""Functions marked 'sync*' can't have return type 'void'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeImplementsBeforeExtends = messageImplementsBeforeExtends;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageImplementsBeforeExtends = const MessageCode(
-    "ImplementsBeforeExtends",
-    index: 44,
-    message: r"""The extends clause must be before the implements clause.""",
-    tip: r"""Try moving the extends clause before the implements clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeImplementsBeforeOn = messageImplementsBeforeOn;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageImplementsBeforeOn = const MessageCode(
-    "ImplementsBeforeOn",
-    index: 43,
-    message: r"""The on clause must be before the implements clause.""",
-    tip: r"""Try moving the on clause before the implements clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeImplementsBeforeWith = messageImplementsBeforeWith;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageImplementsBeforeWith = const MessageCode(
-    "ImplementsBeforeWith",
-    index: 42,
-    message: r"""The with clause must be before the implements clause.""",
-    tip: r"""Try moving the with clause before the implements clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeImplementsFutureOr = messageImplementsFutureOr;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageImplementsFutureOr = const MessageCode(
-    "ImplementsFutureOr",
-    message: r"""'FutureOr' can't be used in an 'implements' clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, int count)>
-    templateImplementsRepeated =
-    const Template<Message Function(String name, int count)>(
-        messageTemplate: r"""'#name' can only be implemented once.""",
-        tipTemplate: r"""Try removing #count of the occurrences.""",
-        withArguments: _withArgumentsImplementsRepeated);
-
-// 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,
-        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);
-  if (count == null) throw 'No count provided';
-  return new Message(codeImplementsRepeated,
-      message: """'${name}' can only be implemented once.""",
-      tip: """Try removing ${count} of the occurrences.""",
-      arguments: {'name': name, 'count': count});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateImplementsSuperClass = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""'#name' can't be used in both 'extends' and 'implements' clauses.""",
-    tipTemplate: r"""Try removing one of the occurrences.""",
-    withArguments: _withArgumentsImplementsSuperClass);
-
-// 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,
-        analyzerCodes: <String>["IMPLEMENTS_SUPER_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsImplementsSuperClass(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeImplementsSuperClass,
-      message:
-          """'${name}' can't be used in both 'extends' and 'implements' clauses.""",
-      tip: """Try removing one of the occurrences.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateImplicitCallOfNonMethod = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Cannot invoke an instance of '#type' because it declares 'call' to be something other than a method.""",
-    tipTemplate:
-        r"""Try changing 'call' to a method or explicitly invoke 'call'.""",
-    withArguments: _withArgumentsImplicitCallOfNonMethod);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeImplicitCallOfNonMethod =
-    const Code<Message Function(DartType _type)>(
-        "ImplicitCallOfNonMethod", templateImplicitCallOfNonMethod,
-        analyzerCodes: <String>["IMPLICIT_CALL_OF_NON_METHOD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsImplicitCallOfNonMethod(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeImplicitCallOfNonMethod,
-      message:
-          """Cannot invoke an instance of '${type}' because it declares 'call' to be something other than a method.""" +
-              labeler.originMessages,
-      tip: """Try changing 'call' to a method or explicitly invoke 'call'.""",
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String name2,
-        String
-            name3)> templateImplicitMixinOverride = const Template<
-        Message Function(String name, String name2, String name3)>(
-    messageTemplate:
-        r"""Applying the mixin '#name' to '#name2' introduces an erroneous override of '#name3'.""",
-    withArguments: _withArgumentsImplicitMixinOverride);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2, String name3)>
-    codeImplicitMixinOverride =
-    const Code<Message Function(String name, String name2, String name3)>(
-  "ImplicitMixinOverride",
-  templateImplicitMixinOverride,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsImplicitMixinOverride(
-    String name, String name2, String name3) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  if (name3.isEmpty) throw 'No name provided';
-  name3 = demangleMixinApplicationName(name3);
-  return new Message(codeImplicitMixinOverride,
-      message:
-          """Applying the mixin '${name}' to '${name2}' introduces an erroneous override of '${name3}'.""",
-      arguments: {'name': name, 'name2': name2, 'name3': name3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeImportAfterPart = messageImportAfterPart;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageImportAfterPart = const MessageCode("ImportAfterPart",
-    index: 10,
-    message: r"""Import directives must precede part directives.""",
-    tip: r"""Try moving the import directives before the part directives.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateImportHidesImport =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate:
-            r"""Import of '#name' (from '#uri') hides import from '#uri2'.""",
-        withArguments: _withArgumentsImportHidesImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    codeImportHidesImport =
-    const Code<Message Function(String name, Uri uri_, Uri uri2_)>(
-        "ImportHidesImport", templateImportHidesImport,
-        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_);
-  return new Message(codeImportHidesImport,
-      message:
-          """Import of '${name}' (from '${uri}') hides import from '${uri2}'.""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateIncompatibleRedirecteeFunctionType = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The constructor function type '#type' isn't a subtype of '#type2'.""",
-    withArguments: _withArgumentsIncompatibleRedirecteeFunctionType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeIncompatibleRedirecteeFunctionType =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "IncompatibleRedirecteeFunctionType",
-        templateIncompatibleRedirecteeFunctionType,
-        analyzerCodes: <String>["REDIRECT_TO_INVALID_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncompatibleRedirecteeFunctionType(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncompatibleRedirecteeFunctionType,
-      message:
-          """The constructor function type '${type}' isn't a subtype of '${type2}'.""" +
-              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,
-        String name,
-        String
-            name2)> templateIncorrectTypeArgument = const Template<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>(
-    messageTemplate:
-        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2'.""",
-    tipTemplate:
-        r"""Try changing type arguments so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgument);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>
-    codeIncorrectTypeArgument = const Code<
-            Message Function(
-                DartType _type, DartType _type2, String name, String name2)>(
-        "IncorrectTypeArgument", templateIncorrectTypeArgument,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgument(
-    DartType _type, DartType _type2, String name, String name2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncorrectTypeArgument,
-      message:
-          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}'.""" +
-              labeler.originMessages,
-      tip: """Try changing type arguments so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        String
-            name2)> templateIncorrectTypeArgumentInReturnType = const Template<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>(
-    messageTemplate:
-        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the return type.""",
-    tipTemplate:
-        r"""Try changing type arguments so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentInReturnType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>
-    codeIncorrectTypeArgumentInReturnType = const Code<
-            Message Function(
-                DartType _type, DartType _type2, String name, String name2)>(
-        "IncorrectTypeArgumentInReturnType",
-        templateIncorrectTypeArgumentInReturnType,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentInReturnType(
-    DartType _type, DartType _type2, String name, String name2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncorrectTypeArgumentInReturnType,
-      message:
-          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the return type.""" +
-              labeler.originMessages,
-      tip: """Try changing type arguments so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        String name2,
-        String name3,
-        String
-            name4)> templateIncorrectTypeArgumentInSupertype = const Template<
-        Message Function(DartType _type, DartType _type2, String name,
-            String name2, String name3, String name4)>(
-    messageTemplate:
-        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the supertype '#name3' of class '#name4'.""",
-    tipTemplate:
-        r"""Try changing type arguments so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentInSupertype);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(DartType _type, DartType _type2, String name,
-            String name2, String name3, String name4)>
-    codeIncorrectTypeArgumentInSupertype = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                String name2, String name3, String name4)>(
-        "IncorrectTypeArgumentInSupertype",
-        templateIncorrectTypeArgumentInSupertype,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentInSupertype(DartType _type,
-    DartType _type2, String name, String name2, String name3, String name4) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  if (name3.isEmpty) throw 'No name provided';
-  name3 = demangleMixinApplicationName(name3);
-  if (name4.isEmpty) throw 'No name provided';
-  name4 = demangleMixinApplicationName(name4);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncorrectTypeArgumentInSupertype,
-      message:
-          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the supertype '${name3}' of class '${name4}'.""" +
-              labeler.originMessages,
-      tip:
-          """Try changing type arguments so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'name2': name2,
-        'name3': name3,
-        'name4': name4
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        String name2,
-        String name3,
-        String
-            name4)> templateIncorrectTypeArgumentInSupertypeInferred = const Template<
-        Message Function(
-            DartType _type,
-            DartType _type2,
-            String name,
-            String name2,
-            String name3,
-            String
-                name4)>(
-    messageTemplate:
-        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2' in the supertype '#name3' of class '#name4'.""",
-    tipTemplate:
-        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentInSupertypeInferred);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(DartType _type, DartType _type2, String name,
-            String name2, String name3, String name4)>
-    codeIncorrectTypeArgumentInSupertypeInferred = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                String name2, String name3, String name4)>(
-        "IncorrectTypeArgumentInSupertypeInferred",
-        templateIncorrectTypeArgumentInSupertypeInferred,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentInSupertypeInferred(DartType _type,
-    DartType _type2, String name, String name2, String name3, String name4) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  if (name3.isEmpty) throw 'No name provided';
-  name3 = demangleMixinApplicationName(name3);
-  if (name4.isEmpty) throw 'No name provided';
-  name4 = demangleMixinApplicationName(name4);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncorrectTypeArgumentInSupertypeInferred,
-      message:
-          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}' in the supertype '${name3}' of class '${name4}'.""" +
-              labeler.originMessages,
-      tip:
-          """Try specifying type arguments explicitly so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'name2': name2,
-        'name3': name3,
-        'name4': name4
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        String
-            name2)> templateIncorrectTypeArgumentInferred = const Template<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>(
-    messageTemplate:
-        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#name2'.""",
-    tipTemplate:
-        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentInferred);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            DartType _type, DartType _type2, String name, String name2)>
-    codeIncorrectTypeArgumentInferred = const Code<
-            Message Function(
-                DartType _type, DartType _type2, String name, String name2)>(
-        "IncorrectTypeArgumentInferred", templateIncorrectTypeArgumentInferred,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentInferred(
-    DartType _type, DartType _type2, String name, String name2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIncorrectTypeArgumentInferred,
-      message:
-          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${name2}'.""" +
-              labeler.originMessages,
-      tip: """Try specifying type arguments explicitly so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        DartType _type3,
-        String
-            name2)> templateIncorrectTypeArgumentQualified = const Template<
-        Message Function(
-            DartType _type,
-            DartType _type2,
-            String name,
-            DartType _type3,
-            String
-                name2)>(
-    messageTemplate:
-        r"""Type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3.#name2'.""",
-    tipTemplate:
-        r"""Try changing type arguments so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentQualified);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(DartType _type, DartType _type2, String name,
-            DartType _type3, String name2)> codeIncorrectTypeArgumentQualified =
-    const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                DartType _type3, String name2)>(
-        "IncorrectTypeArgumentQualified",
-        templateIncorrectTypeArgumentQualified,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentQualified(DartType _type,
-    DartType _type2, String name, DartType _type3, String name2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  List<Object> type3Parts = labeler.labelType(_type3);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  String type3 = type3Parts.join();
-  return new Message(codeIncorrectTypeArgumentQualified,
-      message:
-          """Type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}.${name2}'.""" +
-              labeler.originMessages,
-      tip: """Try changing type arguments so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'type3': _type3,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType _type2,
-        String name,
-        DartType _type3,
-        String
-            name2)> templateIncorrectTypeArgumentQualifiedInferred = const Template<
-        Message Function(DartType _type, DartType _type2, String name,
-            DartType _type3, String name2)>(
-    messageTemplate:
-        r"""Inferred type argument '#type' doesn't conform to the bound '#type2' of the type variable '#name' on '#type3.#name2'.""",
-    tipTemplate:
-        r"""Try specifying type arguments explicitly so that they conform to the bounds.""",
-    withArguments: _withArgumentsIncorrectTypeArgumentQualifiedInferred);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(DartType _type, DartType _type2, String name,
-            DartType _type3, String name2)>
-    codeIncorrectTypeArgumentQualifiedInferred = const Code<
-            Message Function(DartType _type, DartType _type2, String name,
-                DartType _type3, String name2)>(
-        "IncorrectTypeArgumentQualifiedInferred",
-        templateIncorrectTypeArgumentQualifiedInferred,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIncorrectTypeArgumentQualifiedInferred(DartType _type,
-    DartType _type2, String name, DartType _type3, String name2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  List<Object> type3Parts = labeler.labelType(_type3);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  String type3 = type3Parts.join();
-  return new Message(codeIncorrectTypeArgumentQualifiedInferred,
-      message:
-          """Inferred type argument '${type}' doesn't conform to the bound '${type2}' of the type variable '${name}' on '${type3}.${name2}'.""" +
-              labeler.originMessages,
-      tip: """Try specifying type arguments explicitly so that they conform to the bounds.""",
-      arguments: {
-        'type': _type,
-        'type2': _type2,
-        'name': name,
-        'type3': _type3,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeIncorrectTypeArgumentVariable =
-    messageIncorrectTypeArgumentVariable;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageIncorrectTypeArgumentVariable = const MessageCode(
-    "IncorrectTypeArgumentVariable",
-    severity: Severity.context,
-    message: r"""This is the type variable whose bound isn't conformed to.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateInferredPackageUri =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""Interpreting this as package URI, '#uri'.""",
-        withArguments: _withArgumentsInferredPackageUri);
-
-// 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,
-        severity: Severity.warning);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInferredPackageUri(Uri uri_) {
-  String uri = relativizeUri(uri_);
-  return new Message(codeInferredPackageUri,
-      message: """Interpreting this as package URI, '${uri}'.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInheritedMembersConflict = messageInheritedMembersConflict;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInheritedMembersConflict = const MessageCode(
-    "InheritedMembersConflict",
-    analyzerCodes: <String>["CONFLICTS_WITH_INHERITED_MEMBER"],
-    message: r"""Can't inherit members that conflict with each other.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInheritedMembersConflictCause1 =
-    messageInheritedMembersConflictCause1;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInheritedMembersConflictCause1 = const MessageCode(
-    "InheritedMembersConflictCause1",
-    severity: Severity.context,
-    message: r"""This is one inherited member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInheritedMembersConflictCause2 =
-    messageInheritedMembersConflictCause2;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInheritedMembersConflictCause2 = const MessageCode(
-    "InheritedMembersConflictCause2",
-    severity: Severity.context,
-    message: r"""This is the other inherited member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        Uri
-            uri_)> templateInitializeFromDillNotSelfContained = const Template<
-        Message Function(String string, Uri uri_)>(
-    messageTemplate:
-        r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
-If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
-Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
-    withArguments: _withArgumentsInitializeFromDillNotSelfContained);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, Uri uri_)>
-    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_);
-  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.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
-If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
-Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
-      arguments: {'string': string, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateInitializeFromDillNotSelfContainedNoDump =
-    const Template<Message Function(String string)>(
-        messageTemplate:
-            r"""Tried to initialize from a previous compilation (#string), but the file was not self-contained. This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
-        withArguments: _withArgumentsInitializeFromDillNotSelfContainedNoDump);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
-    codeInitializeFromDillNotSelfContainedNoDump =
-    const Code<Message Function(String string)>(
-        "InitializeFromDillNotSelfContainedNoDump",
-        templateInitializeFromDillNotSelfContainedNoDump,
-        severity: Severity.warning);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInitializeFromDillNotSelfContainedNoDump(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInitializeFromDillNotSelfContainedNoDump,
-      message:
-          """Tried to initialize from a previous compilation (${string}), but the file was not self-contained. This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String string2,
-        String string3,
-        Uri
-            uri_)> templateInitializeFromDillUnknownProblem = const Template<
-        Message Function(
-            String string, String string2, String string3, Uri uri_)>(
-    messageTemplate:
-        r"""Tried to initialize from a previous compilation (#string), but couldn't.
-Error message was '#string2'.
-Stacktrace included '#string3'.
-This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
-If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
-Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
-    withArguments: _withArgumentsInitializeFromDillUnknownProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            String string, String string2, String string3, Uri uri_)>
-    codeInitializeFromDillUnknownProblem = const Code<
-            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.
-Message _withArgumentsInitializeFromDillUnknownProblem(
-    String string, String string2, String string3, Uri uri_) {
-  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_);
-  return new Message(codeInitializeFromDillUnknownProblem,
-      message:
-          """Tried to initialize from a previous compilation (${string}), but couldn't.
-Error message was '${string2}'.
-Stacktrace included '${string3}'.
-This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
-If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
-Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
-      arguments: {
-        'string': string,
-        'string2': string2,
-        'string3': string3,
-        'uri': uri_
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2, String string3)>
-    templateInitializeFromDillUnknownProblemNoDump = const Template<
-            Message Function(String string, String string2, String string3)>(
-        messageTemplate:
-            r"""Tried to initialize from a previous compilation (#string), but couldn't.
-Error message was '#string2'.
-Stacktrace included '#string3'.
-This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
-        withArguments: _withArgumentsInitializeFromDillUnknownProblemNoDump);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2, String string3)>
-    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.
-Message _withArgumentsInitializeFromDillUnknownProblemNoDump(
-    String string, String string2, String string3) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  if (string3.isEmpty) throw 'No string provided';
-  return new Message(codeInitializeFromDillUnknownProblemNoDump,
-      message:
-          """Tried to initialize from a previous compilation (${string}), but couldn't.
-Error message was '${string2}'.
-Stacktrace included '${string3}'.
-This might be a bug.
-
-The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
-      arguments: {'string': string, 'string2': string2, 'string3': string3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInitializedVariableInForEach =
-    messageInitializedVariableInForEach;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInitializedVariableInForEach = const MessageCode(
-    "InitializedVariableInForEach",
-    index: 82,
-    message: r"""The loop variable in a for-each loop can't be initialized.""",
-    tip:
-        r"""Try removing the initializer, or using a different kind of loop.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateInitializerForStaticField =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' isn't an instance field of this class.""",
-        withArguments: _withArgumentsInitializerForStaticField);
-
-// 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,
-        analyzerCodes: <String>["INITIALIZER_FOR_STATIC_FIELD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInitializerForStaticField(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInitializerForStaticField,
-      message: """'${name}' isn't an instance field of this class.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateInitializerOutsideConstructor = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Only constructors can have initializers, and '#name' is not a constructor.""",
-    withArguments: _withArgumentsInitializerOutsideConstructor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeInitializerOutsideConstructor =
-    const Code<Message Function(String name)>(
-        "InitializerOutsideConstructor", templateInitializerOutsideConstructor,
-        analyzerCodes: <String>["INITIALIZER_OUTSIDE_CONSTRUCTOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInitializerOutsideConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInitializerOutsideConstructor,
-      message:
-          """Only constructors can have initializers, and '${name}' is not a constructor.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType _type,
-        DartType
-            _type2)> templateInitializingFormalTypeMismatch = const Template<
-        Message Function(String name, DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The type of parameter '#name', '#type' is not a subtype of the corresponding field's type, '#type2'.""",
-    tipTemplate:
-        r"""Try changing the type of parameter '#name' to a subtype of '#type2'.""",
-    withArguments: _withArgumentsInitializingFormalTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
-    codeInitializingFormalTypeMismatch =
-    const Code<Message Function(String name, DartType _type, DartType _type2)>(
-        "InitializingFormalTypeMismatch",
-        templateInitializingFormalTypeMismatch,
-        analyzerCodes: <String>["INVALID_PARAMETER_DECLARATION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInitializingFormalTypeMismatch(
-    String name, DartType _type, DartType _type2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInitializingFormalTypeMismatch,
-      message:
-          """The type of parameter '${name}', '${type}' is not a subtype of the corresponding field's type, '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Try changing the type of parameter '${name}' to a subtype of '${type2}'.""",
-      arguments: {'name': name, 'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInitializingFormalTypeMismatchField =
-    messageInitializingFormalTypeMismatchField;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInitializingFormalTypeMismatchField =
-    const MessageCode("InitializingFormalTypeMismatchField",
-        severity: Severity.context,
-        message: r"""The field that corresponds to the parameter.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateInputFileNotFound =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""Input file not found: #uri.""",
-        withArguments: _withArgumentsInputFileNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codeInputFileNotFound,
-      message: """Input file not found: ${uri}.""", arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            string)> templateIntegerLiteralIsOutOfRange = const Template<
-        Message Function(String string)>(
-    messageTemplate:
-        r"""The integer literal #string can't be represented in 64 bits.""",
-    tipTemplate:
-        r"""Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
-    withArguments: _withArgumentsIntegerLiteralIsOutOfRange);
-
-// 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,
-        analyzerCodes: <String>["INTEGER_LITERAL_OUT_OF_RANGE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIntegerLiteralIsOutOfRange(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeIntegerLiteralIsOutOfRange,
-      message:
-          """The integer literal ${string} can't be represented in 64 bits.""",
-      tip:
-          """Try using the BigInt class if you need an integer larger than 9,223,372,036,854,775,807 or less than -9,223,372,036,854,775,808.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateInterfaceCheck = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""The implementation of '#name' in the non-abstract class '#name2' does not conform to its interface.""",
-    withArguments: _withArgumentsInterfaceCheck);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsInterfaceCheck(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeInterfaceCheck,
-      message:
-          """The implementation of '${name}' in the non-abstract class '${name2}' does not conform to its interface.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemAlreadyInitialized =
-    messageInternalProblemAlreadyInitialized;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemAlreadyInitialized = const MessageCode(
-    "InternalProblemAlreadyInitialized",
-    severity: Severity.internalProblem,
-    message: r"""Attempt to set initializer on field without initializer.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemBodyOnAbstractMethod =
-    messageInternalProblemBodyOnAbstractMethod;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemBodyOnAbstractMethod =
-    const MessageCode("InternalProblemBodyOnAbstractMethod",
-        severity: Severity.internalProblem,
-        message: r"""Attempting to set body on abstract method.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templateInternalProblemConstructorNotFound =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate: r"""No constructor named '#name' in '#uri'.""",
-        withArguments: _withArgumentsInternalProblemConstructorNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    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.
-Message _withArgumentsInternalProblemConstructorNotFound(
-    String name, Uri uri_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  return new Message(codeInternalProblemConstructorNotFound,
-      message: """No constructor named '${name}' in '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateInternalProblemContextSeverity =
-    const Template<Message Function(String string)>(
-        messageTemplate:
-            r"""Non-context message has context severity: #string""",
-        withArguments: _withArgumentsInternalProblemContextSeverity);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsInternalProblemContextSeverity(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemContextSeverity,
-      message: """Non-context message has context severity: ${string}""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String string)>
-    templateInternalProblemDebugAbort =
-    const Template<Message Function(String name, String string)>(
-        messageTemplate: r"""Compilation aborted due to fatal '#name' at:
-#string""", withArguments: _withArgumentsInternalProblemDebugAbort);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String string)>
-    codeInternalProblemDebugAbort =
-    const Code<Message Function(String name, String string)>(
-        "InternalProblemDebugAbort", templateInternalProblemDebugAbort,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemDebugAbort(String name, String string) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemDebugAbort,
-      message: """Compilation aborted due to fatal '${name}' at:
-${string}""", arguments: {'name': name, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemExtendingUnmodifiableScope =
-    messageInternalProblemExtendingUnmodifiableScope;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemExtendingUnmodifiableScope =
-    const MessageCode("InternalProblemExtendingUnmodifiableScope",
-        severity: Severity.internalProblem,
-        message: r"""Can't extend an unmodifiable scope.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemLabelUsageInVariablesDeclaration =
-    messageInternalProblemLabelUsageInVariablesDeclaration;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemLabelUsageInVariablesDeclaration =
-    const MessageCode("InternalProblemLabelUsageInVariablesDeclaration",
-        severity: Severity.internalProblem,
-        message:
-            r"""Unexpected usage of label inside declaration of variables.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemMissingContext =
-    messageInternalProblemMissingContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemMissingContext = const MessageCode(
-    "InternalProblemMissingContext",
-    severity: Severity.internalProblem,
-    message: r"""Compiler cannot run without a compiler context.""",
-    tip:
-        r"""Are calls to the compiler wrapped in CompilerContext.runInContext?""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateInternalProblemNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Couldn't find '#name'.""",
-        withArguments: _withArgumentsInternalProblemNotFound);
-
-// 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,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInternalProblemNotFound,
-      message: """Couldn't find '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String name2)>
-    templateInternalProblemNotFoundIn =
-    const Template<Message Function(String name, String name2)>(
-        messageTemplate: r"""Couldn't find '#name' in '#name2'.""",
-        withArguments: _withArgumentsInternalProblemNotFoundIn);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeInternalProblemNotFoundIn =
-    const Code<Message Function(String name, String name2)>(
-        "InternalProblemNotFoundIn", templateInternalProblemNotFoundIn,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemNotFoundIn(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeInternalProblemNotFoundIn,
-      message: """Couldn't find '${name}' in '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemPreviousTokenNotFound =
-    messageInternalProblemPreviousTokenNotFound;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemPreviousTokenNotFound =
-    const MessageCode("InternalProblemPreviousTokenNotFound",
-        severity: Severity.internalProblem,
-        message: r"""Couldn't find previous token.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateInternalProblemPrivateConstructorAccess =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Can't access private constructor '#name'.""",
-        withArguments: _withArgumentsInternalProblemPrivateConstructorAccess);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeInternalProblemPrivateConstructorAccess =
-    const Code<Message Function(String name)>(
-        "InternalProblemPrivateConstructorAccess",
-        templateInternalProblemPrivateConstructorAccess,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemPrivateConstructorAccess(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInternalProblemPrivateConstructorAccess,
-      message: """Can't access private constructor '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInternalProblemProvidedBothCompileSdkAndSdkSummary =
-    messageInternalProblemProvidedBothCompileSdkAndSdkSummary;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInternalProblemProvidedBothCompileSdkAndSdkSummary =
-    const MessageCode("InternalProblemProvidedBothCompileSdkAndSdkSummary",
-        severity: Severity.internalProblem,
-        message:
-            r"""The compileSdk and sdkSummary options are mutually exclusive""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String string)>
-    templateInternalProblemStackNotEmpty =
-    const Template<Message Function(String name, String string)>(
-        messageTemplate: r"""#name.stack isn't empty:
-  #string""", withArguments: _withArgumentsInternalProblemStackNotEmpty);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String string)>
-    codeInternalProblemStackNotEmpty =
-    const Code<Message Function(String name, String string)>(
-        "InternalProblemStackNotEmpty", templateInternalProblemStackNotEmpty,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemStackNotEmpty(String name, String string) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemStackNotEmpty,
-      message: """${name}.stack isn't empty:
-  ${string}""", arguments: {'name': name, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2)>
-    templateInternalProblemUnexpected =
-    const Template<Message Function(String string, String string2)>(
-        messageTemplate: r"""Expected '#string', but got '#string2'.""",
-        withArguments: _withArgumentsInternalProblemUnexpected);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeInternalProblemUnexpected =
-    const Code<Message Function(String string, String string2)>(
-        "InternalProblemUnexpected", templateInternalProblemUnexpected,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemUnexpected(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemUnexpected,
-      message: """Expected '${string}', but got '${string2}'.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        Uri
-            uri_)> templateInternalProblemUnfinishedTypeVariable = const Template<
-        Message Function(String name, Uri uri_)>(
-    messageTemplate:
-        r"""Unfinished type variable '#name' found in non-source library '#uri'.""",
-    withArguments: _withArgumentsInternalProblemUnfinishedTypeVariable);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    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.
-Message _withArgumentsInternalProblemUnfinishedTypeVariable(
-    String name, Uri uri_) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  String uri = relativizeUri(uri_);
-  return new Message(codeInternalProblemUnfinishedTypeVariable,
-      message:
-          """Unfinished type variable '${name}' found in non-source library '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2)>
-    templateInternalProblemUnhandled =
-    const Template<Message Function(String string, String string2)>(
-        messageTemplate: r"""Unhandled #string in #string2.""",
-        withArguments: _withArgumentsInternalProblemUnhandled);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeInternalProblemUnhandled =
-    const Code<Message Function(String string, String string2)>(
-        "InternalProblemUnhandled", templateInternalProblemUnhandled,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemUnhandled(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemUnhandled,
-      message: """Unhandled ${string} in ${string2}.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateInternalProblemUnimplemented =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Unimplemented #string.""",
-        withArguments: _withArgumentsInternalProblemUnimplemented);
-
-// 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,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemUnimplemented(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemUnimplemented,
-      message: """Unimplemented ${string}.""", arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateInternalProblemUnsupported =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Unsupported operation: '#name'.""",
-        withArguments: _withArgumentsInternalProblemUnsupported);
-
-// 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,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemUnsupported(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInternalProblemUnsupported,
-      message: """Unsupported operation: '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)>
-    templateInternalProblemUriMissingScheme =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""The URI '#uri' has no scheme.""",
-        withArguments: _withArgumentsInternalProblemUriMissingScheme);
-
-// 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_);
-  return new Message(codeInternalProblemUriMissingScheme,
-      message: """The URI '${uri}' has no scheme.""", arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateInternalProblemVerificationError =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Verification of the generated program failed:
-#string""", withArguments: _withArgumentsInternalProblemVerificationError);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
-    codeInternalProblemVerificationError =
-    const Code<Message Function(String string)>(
-        "InternalProblemVerificationError",
-        templateInternalProblemVerificationError,
-        severity: Severity.internalProblem);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInternalProblemVerificationError(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInternalProblemVerificationError,
-      message: """Verification of the generated program failed:
-${string}""", arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInterpolationInUri = messageInterpolationInUri;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInterpolationInUri = const MessageCode(
-    "InterpolationInUri",
-    analyzerCodes: <String>["INVALID_LITERAL_IN_CONFIGURATION"],
-    message: r"""Can't use string interpolation in a URI.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType _type,
-        DartType
-            _type2)> templateIntersectionTypeAsTypeArgument = const Template<
-        Message Function(String name, DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""Can't infer a type for '#name', it can be either '#type' or '#type2'.""",
-    tipTemplate:
-        r"""Try adding a type argument selecting one of the options.""",
-    withArguments: _withArgumentsIntersectionTypeAsTypeArgument);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
-    codeIntersectionTypeAsTypeArgument =
-    const Code<Message Function(String name, DartType _type, DartType _type2)>(
-  "IntersectionTypeAsTypeArgument",
-  templateIntersectionTypeAsTypeArgument,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIntersectionTypeAsTypeArgument(
-    String name, DartType _type, DartType _type2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeIntersectionTypeAsTypeArgument,
-      message:
-          """Can't infer a type for '${name}', it can be either '${type}' or '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Try adding a type argument selecting one of the options.""",
-      arguments: {'name': name, 'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidAssignment = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""A value of type '#type' can't be assigned to a variable of type '#type2'.""",
-    withArguments: _withArgumentsInvalidAssignment);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidAssignment =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidAssignment", templateInvalidAssignment,
-        analyzerCodes: <String>["INVALID_ASSIGNMENT"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidAssignment(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidAssignment,
-      message:
-          """A value of type '${type}' can't be assigned to a variable of type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidAwaitFor = messageInvalidAwaitFor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidAwaitFor = const MessageCode("InvalidAwaitFor",
-    index: 9,
-    message:
-        r"""The keyword 'await' isn't allowed for a normal 'for' statement.""",
-    tip: r"""Try removing the keyword, or use a for-each statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateInvalidBreakTarget =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Can't break to '#name'.""",
-        withArguments: _withArgumentsInvalidBreakTarget);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsInvalidBreakTarget(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInvalidBreakTarget,
-      message: """Can't break to '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastFunctionExpr = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The function expression type '#type' isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the function expression or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastFunctionExpr);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastFunctionExpr =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastFunctionExpr", templateInvalidCastFunctionExpr,
-        analyzerCodes: <String>["INVALID_CAST_FUNCTION_EXPR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastFunctionExpr(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastFunctionExpr,
-      message:
-          """The function expression type '${type}' isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the function expression or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastLiteralList = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The list literal type '#type' isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the list literal or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastLiteralList);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastLiteralList =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastLiteralList", templateInvalidCastLiteralList,
-        analyzerCodes: <String>["INVALID_CAST_LITERAL_LIST"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastLiteralList(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastLiteralList,
-      message:
-          """The list literal type '${type}' isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the list literal or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastLiteralMap = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The map literal type '#type' isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the map literal or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastLiteralMap);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastLiteralMap =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastLiteralMap", templateInvalidCastLiteralMap,
-        analyzerCodes: <String>["INVALID_CAST_LITERAL_MAP"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastLiteralMap(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastLiteralMap,
-      message:
-          """The map literal type '${type}' isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the map literal or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastLiteralSet = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The set literal type '#type' isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the set literal or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastLiteralSet);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastLiteralSet =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastLiteralSet", templateInvalidCastLiteralSet,
-        analyzerCodes: <String>["INVALID_CAST_LITERAL_SET"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastLiteralSet(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastLiteralSet,
-      message:
-          """The set literal type '${type}' isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the set literal or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastLocalFunction = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The local function has type '#type' that isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the function or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastLocalFunction);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastLocalFunction =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastLocalFunction", templateInvalidCastLocalFunction,
-        analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastLocalFunction(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastLocalFunction,
-      message:
-          """The local function has type '${type}' that isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the function or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastNewExpr = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The constructor returns type '#type' that isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the object being constructed or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastNewExpr);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastNewExpr =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastNewExpr", templateInvalidCastNewExpr,
-        analyzerCodes: <String>["INVALID_CAST_NEW_EXPR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastNewExpr(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastNewExpr,
-      message:
-          """The constructor returns type '${type}' that isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the object being constructed or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastStaticMethod = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The static method has type '#type' that isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the method or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastStaticMethod);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastStaticMethod =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastStaticMethod", templateInvalidCastStaticMethod,
-        analyzerCodes: <String>["INVALID_CAST_METHOD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastStaticMethod(DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastStaticMethod,
-      message:
-          """The static method has type '${type}' that isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the method or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateInvalidCastTopLevelFunction = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""The top level function has type '#type' that isn't of expected type '#type2'.""",
-    tipTemplate:
-        r"""Change the type of the function or the context in which it is used.""",
-    withArguments: _withArgumentsInvalidCastTopLevelFunction);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeInvalidCastTopLevelFunction =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "InvalidCastTopLevelFunction", templateInvalidCastTopLevelFunction,
-        analyzerCodes: <String>["INVALID_CAST_FUNCTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvalidCastTopLevelFunction(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeInvalidCastTopLevelFunction,
-      message:
-          """The top level function has type '${type}' that isn't of expected type '${type2}'.""" +
-              labeler.originMessages,
-      tip: """Change the type of the function or the context in which it is used.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidCatchArguments = messageInvalidCatchArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidCatchArguments = const MessageCode(
-    "InvalidCatchArguments",
-    analyzerCodes: <String>["INVALID_CATCH_ARGUMENTS"],
-    message: r"""Invalid catch arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidCodePoint = messageInvalidCodePoint;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidCodePoint = const MessageCode(
-    "InvalidCodePoint",
-    analyzerCodes: <String>["INVALID_CODE_POINT"],
-    message:
-        r"""The escape sequence starting with '\u' isn't a valid code point.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateInvalidContinueTarget =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Can't continue at '#name'.""",
-        withArguments: _withArgumentsInvalidContinueTarget);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsInvalidContinueTarget(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInvalidContinueTarget,
-      message: """Can't continue at '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidHexEscape = messageInvalidHexEscape;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidHexEscape = const MessageCode(
-    "InvalidHexEscape",
-    index: 40,
-    message:
-        r"""An escape sequence starting with '\x' must be followed by 2 hexadecimal digits.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidInitializer = messageInvalidInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidInitializer = const MessageCode(
-    "InvalidInitializer",
-    index: 90,
-    message: r"""Not a valid initializer.""",
-    tip: r"""To initialize a field, use the syntax 'name = value'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidInlineFunctionType =
-    messageInvalidInlineFunctionType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidInlineFunctionType = const MessageCode(
-    "InvalidInlineFunctionType",
-    analyzerCodes: <String>["INVALID_INLINE_FUNCTION_TYPE"],
-    message:
-        r"""Inline function types cannot be used for parameters in a generic function type.""",
-    tip:
-        r"""Try changing the inline function type (as in 'int f()') to a prefixed function type using the `Function` keyword (as in 'int Function() f').""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateInvalidOperator =
-    const Template<Message Function(Token token)>(
-        messageTemplate:
-            r"""The string '#lexeme' isn't a user-definable operator.""",
-        withArguments: _withArgumentsInvalidOperator);
-
-// 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);
-
-// 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});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_, String string)>
-    templateInvalidPackageUri =
-    const Template<Message Function(Uri uri_, String string)>(
-        messageTemplate: r"""Invalid package URI '#uri':
-  #string.""", withArguments: _withArgumentsInvalidPackageUri);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeInvalidPackageUri,
-      message: """Invalid package URI '${uri}':
-  ${string}.""", arguments: {'uri': uri_, 'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidSuperInInitializer =
-    messageInvalidSuperInInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidSuperInInitializer = const MessageCode(
-    "InvalidSuperInInitializer",
-    index: 47,
-    message:
-        r"""Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidSyncModifier = messageInvalidSyncModifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidSyncModifier = const MessageCode(
-    "InvalidSyncModifier",
-    analyzerCodes: <String>["MISSING_STAR_AFTER_SYNC"],
-    message: r"""Invalid modifier 'sync'.""",
-    tip: r"""Try replacing 'sync' with 'sync*'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidThisInInitializer = messageInvalidThisInInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidThisInInitializer = const MessageCode(
-    "InvalidThisInInitializer",
-    index: 65,
-    message:
-        r"""Can only use 'this' in an initializer for field initialization (e.g. 'this.x = something') and constructor redirection (e.g. 'this()' or 'this.namedConstructor())""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidUnicodeEscape = messageInvalidUnicodeEscape;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidUnicodeEscape = const MessageCode(
-    "InvalidUnicodeEscape",
-    index: 38,
-    message:
-        r"""An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidUseOfNullAwareAccess =
-    messageInvalidUseOfNullAwareAccess;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidUseOfNullAwareAccess = const MessageCode(
-    "InvalidUseOfNullAwareAccess",
-    analyzerCodes: <String>["INVALID_USE_OF_NULL_AWARE_ACCESS"],
-    message: r"""Cannot use '?.' here.""",
-    tip: r"""Try using '.'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeInvalidVoid = messageInvalidVoid;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageInvalidVoid = const MessageCode("InvalidVoid",
-    analyzerCodes: <String>["EXPECTED_TYPE_NAME"],
-    message: r"""Type 'void' can't be used here.""",
-    tip:
-        r"""Try removing 'void' keyword or replace it with 'var', 'final', or a type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateInvokeNonFunction =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""'#name' isn't a function or method and can't be invoked.""",
-        withArguments: _withArgumentsInvokeNonFunction);
-
-// 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,
-        analyzerCodes: <String>["INVOCATION_OF_NON_FUNCTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsInvokeNonFunction(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeInvokeNonFunction,
-      message: """'${name}' isn't a function or method and can't be invoked.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(String name)> templateLabelNotFound = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""Can't find label '#name'.""",
-    tipTemplate:
-        r"""Try defining the label, or correcting the name to match an existing label.""",
-    withArguments: _withArgumentsLabelNotFound);
-
-// 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,
-        analyzerCodes: <String>["LABEL_UNDEFINED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsLabelNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeLabelNotFound,
-      message: """Can't find label '${name}'.""",
-      tip:
-          """Try defining the label, or correcting the name to match an existing label.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeLanguageVersionInvalidInDotPackages =
-    messageLanguageVersionInvalidInDotPackages;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageLanguageVersionInvalidInDotPackages = const MessageCode(
-    "LanguageVersionInvalidInDotPackages",
-    message:
-        r"""The language version is not specified correctly in the .packages file.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeLanguageVersionMismatchInPart =
-    messageLanguageVersionMismatchInPart;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageLanguageVersionMismatchInPart = const MessageCode(
-    "LanguageVersionMismatchInPart",
-    message:
-        r"""The language version override has to be the same in the library and its part(s).""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int count,
-        int
-            count2)> templateLanguageVersionTooHigh = const Template<
-        Message Function(int count, int count2)>(
-    messageTemplate:
-        r"""The specified language version is too high. The highest supported language version is #count.#count2.""",
-    withArguments: _withArgumentsLanguageVersionTooHigh);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  return new Message(codeLanguageVersionTooHigh,
-      message:
-          """The specified language version is too high. The highest supported language version is ${count}.${count2}.""",
-      arguments: {'count': count, 'count2': count2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeLibraryDirectiveNotFirst = messageLibraryDirectiveNotFirst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageLibraryDirectiveNotFirst = const MessageCode(
-    "LibraryDirectiveNotFirst",
-    index: 37,
-    message:
-        r"""The library directive must appear before all other directives.""",
-    tip: r"""Try moving the library directive before any other directives.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeListLiteralTooManyTypeArguments =
-    messageListLiteralTooManyTypeArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageListLiteralTooManyTypeArguments = const MessageCode(
-    "ListLiteralTooManyTypeArguments",
-    analyzerCodes: <String>["EXPECTED_ONE_LIST_TYPE_ARGUMENTS"],
-    message: r"""List literal requires exactly one type argument.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Uri uri_)> templateLoadLibraryHidesMember = const Template<
-        Message Function(Uri uri_)>(
-    messageTemplate:
-        r"""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.""",
-    tipTemplate: r"""Try to rename or hide the member.""",
-    withArguments: _withArgumentsLoadLibraryHidesMember);
-
-// 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,
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsLoadLibraryHidesMember(Uri 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.""",
-      tip: """Try to rename or hide the member.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeLoadLibraryTakesNoArguments =
-    messageLoadLibraryTakesNoArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageLoadLibraryTakesNoArguments = const MessageCode(
-    "LoadLibraryTakesNoArguments",
-    analyzerCodes: <String>["LOAD_LIBRARY_TAKES_NO_ARGUMENTS"],
-    message: r"""'loadLibrary' takes no arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templateLocalDefinitionHidesExport =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate:
-            r"""Local definition of '#name' hides export from '#uri'.""",
-        withArguments: _withArgumentsLocalDefinitionHidesExport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    codeLocalDefinitionHidesExport =
-    const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesExport", templateLocalDefinitionHidesExport,
-        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_);
-  return new Message(codeLocalDefinitionHidesExport,
-      message: """Local definition of '${name}' hides export from '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templateLocalDefinitionHidesImport =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate:
-            r"""Local definition of '#name' hides import from '#uri'.""",
-        withArguments: _withArgumentsLocalDefinitionHidesImport);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_)>
-    codeLocalDefinitionHidesImport =
-    const Code<Message Function(String name, Uri uri_)>(
-        "LocalDefinitionHidesImport", templateLocalDefinitionHidesImport,
-        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_);
-  return new Message(codeLocalDefinitionHidesImport,
-      message: """Local definition of '${name}' hides import from '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMapLiteralTypeArgumentMismatch =
-    messageMapLiteralTypeArgumentMismatch;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMapLiteralTypeArgumentMismatch = const MessageCode(
-    "MapLiteralTypeArgumentMismatch",
-    analyzerCodes: <String>["EXPECTED_TWO_MAP_TYPE_ARGUMENTS"],
-    message: r"""A map literal requires exactly two type arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMemberWithSameNameAsClass =
-    messageMemberWithSameNameAsClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMemberWithSameNameAsClass = const MessageCode(
-    "MemberWithSameNameAsClass",
-    message:
-        r"""A class member can't have the same name as the enclosing class.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMetadataTypeArguments = messageMetadataTypeArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMetadataTypeArguments = const MessageCode(
-    "MetadataTypeArguments",
-    index: 91,
-    message: r"""An annotation (metadata) can't use type arguments.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateMethodNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Method not found: '#name'.""",
-        withArguments: _withArgumentsMethodNotFound);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_METHOD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMethodNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeMethodNotFound,
-      message: """Method not found: '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingArgumentList = messageMissingArgumentList;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingArgumentList = const MessageCode(
-    "MissingArgumentList",
-    message: r"""Constructor invocations must have an argument list.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingAssignableSelector =
-    messageMissingAssignableSelector;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingAssignableSelector = const MessageCode(
-    "MissingAssignableSelector",
-    index: 35,
-    message: r"""Missing selector such as '.identifier' or '[0]'.""",
-    tip: r"""Try adding a selector.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingAssignmentInInitializer =
-    messageMissingAssignmentInInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingAssignmentInInitializer = const MessageCode(
-    "MissingAssignmentInInitializer",
-    index: 34,
-    message: r"""Expected an assignment after the field name.""",
-    tip: r"""To initialize a field, use the syntax 'name = value'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingConstFinalVarOrType =
-    messageMissingConstFinalVarOrType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingConstFinalVarOrType = const MessageCode(
-    "MissingConstFinalVarOrType",
-    index: 33,
-    message:
-        r"""Variables must be declared using the keywords 'const', 'final', 'var' or a type name.""",
-    tip:
-        r"""Try adding the name of the type of the variable or the keyword 'var'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingExplicitConst = messageMissingExplicitConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingExplicitConst = const MessageCode(
-    "MissingExplicitConst",
-    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
-    message: r"""Constant expression expected.""",
-    tip: r"""Try inserting 'const'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(int count)>
-    templateMissingExplicitTypeArguments =
-    const Template<Message Function(int count)>(
-        messageTemplate: r"""No type arguments provided, #count possible.""",
-        withArguments: _withArgumentsMissingExplicitTypeArguments);
-
-// 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,
-        severity: Severity.ignored);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMissingExplicitTypeArguments(int count) {
-  if (count == null) throw 'No count provided';
-  return new Message(codeMissingExplicitTypeArguments,
-      message: """No type arguments provided, ${count} possible.""",
-      arguments: {'count': count});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingExponent = messageMissingExponent;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingExponent = const MessageCode("MissingExponent",
-    analyzerCodes: <String>["MISSING_DIGIT"],
-    message:
-        r"""Numbers in exponential notation should always contain an exponent (an integer number with an optional sign).""",
-    tip:
-        r"""Make sure there is an exponent, and remove any whitespace before it.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingExpressionInThrow = messageMissingExpressionInThrow;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingExpressionInThrow = const MessageCode(
-    "MissingExpressionInThrow",
-    index: 32,
-    message: r"""Missing expression after 'throw'.""",
-    tip:
-        r"""Add an expression after 'throw' or use 'rethrow' to throw a caught exception""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingFunctionParameters =
-    messageMissingFunctionParameters;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingFunctionParameters = const MessageCode(
-    "MissingFunctionParameters",
-    analyzerCodes: <String>["MISSING_FUNCTION_PARAMETERS"],
-    message:
-        r"""A function declaration needs an explicit list of parameters.""",
-    tip: r"""Try adding a parameter list to the function declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateMissingImplementationCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' is defined here.""",
-        withArguments: _withArgumentsMissingImplementationCause);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMissingImplementationCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeMissingImplementationCause,
-      message: """'${name}' is defined here.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        List<String>
-            _names)> templateMissingImplementationNotAbstract = const Template<
-        Message Function(String name, List<String> _names)>(
-    messageTemplate:
-        r"""The non-abstract class '#name' is missing implementations for these members:
-#names""",
-    tipTemplate: r"""Try to either
- - provide an implementation,
- - inherit an implementation from a superclass or mixin,
- - mark the class as abstract, or
- - provide a 'noSuchMethod' implementation.
-""",
-    withArguments: _withArgumentsMissingImplementationNotAbstract);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, List<String> _names)>
-    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.
-Message _withArgumentsMissingImplementationNotAbstract(
-    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(codeMissingImplementationNotAbstract,
-      message:
-          """The non-abstract class '${name}' is missing implementations for these members:
-${names}""",
-      tip: """Try to either
- - provide an implementation,
- - inherit an implementation from a superclass or mixin,
- - mark the class as abstract, or
- - provide a 'noSuchMethod' implementation.
-""",
-      arguments: {'name': name, 'names': _names});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingInput = messageMissingInput;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingInput = const MessageCode("MissingInput",
-    message: r"""No input file provided to the compiler.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingMain = messageMissingMain;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingMain = const MessageCode("MissingMain",
-    message: r"""No 'main' method found.""",
-    tip: r"""Try adding a method named 'main' to your program.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingMethodParameters = messageMissingMethodParameters;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingMethodParameters = const MessageCode(
-    "MissingMethodParameters",
-    analyzerCodes: <String>["MISSING_METHOD_PARAMETERS"],
-    message: r"""A method declaration needs an explicit list of parameters.""",
-    tip: r"""Try adding a parameter list to the method declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingOperatorKeyword = messageMissingOperatorKeyword;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingOperatorKeyword = const MessageCode(
-    "MissingOperatorKeyword",
-    index: 31,
-    message:
-        r"""Operator declarations must be preceded by the keyword 'operator'.""",
-    tip: r"""Try adding the keyword 'operator'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Uri uri_)> templateMissingPartOf = const Template<
-        Message Function(Uri uri_)>(
-    messageTemplate:
-        r"""Can't use '#uri' as a part, because it has no 'part of' declaration.""",
-    withArguments: _withArgumentsMissingPartOf);
-
-// 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,
-        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_);
-  return new Message(codeMissingPartOf,
-      message:
-          """Can't use '${uri}' as a part, because it has no 'part of' declaration.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingPrefixInDeferredImport =
-    messageMissingPrefixInDeferredImport;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingPrefixInDeferredImport = const MessageCode(
-    "MissingPrefixInDeferredImport",
-    index: 30,
-    message: r"""Deferred imports should have a prefix.""",
-    tip: r"""Try adding a prefix to the import by adding an 'as' clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMissingTypedefParameters = messageMissingTypedefParameters;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMissingTypedefParameters = const MessageCode(
-    "MissingTypedefParameters",
-    analyzerCodes: <String>["MISSING_TYPEDEF_PARAMETERS"],
-    message: r"""A typedef needs an explicit list of parameters.""",
-    tip: r"""Try adding a parameter list to the typedef.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-        Message Function(DartType _type, DartType _type2, DartType _type3)>
-    templateMixinApplicationIncompatibleSupertype = const Template<
-            Message Function(DartType _type, DartType _type2, DartType _type3)>(
-        messageTemplate:
-            r"""'#type' doesn't implement '#type2' so it can't be used with '#type3'.""",
-        withArguments: _withArgumentsMixinApplicationIncompatibleSupertype);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2, DartType _type3)>
-    codeMixinApplicationIncompatibleSupertype = const Code<
-            Message Function(DartType _type, DartType _type2, DartType _type3)>(
-        "MixinApplicationIncompatibleSupertype",
-        templateMixinApplicationIncompatibleSupertype,
-        analyzerCodes: <String>["MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMixinApplicationIncompatibleSupertype(
-    DartType _type, DartType _type2, DartType _type3) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  List<Object> type3Parts = labeler.labelType(_type3);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  String type3 = type3Parts.join();
-  return new Message(codeMixinApplicationIncompatibleSupertype,
-      message:
-          """'${type}' doesn't implement '${type2}' so it can't be used with '${type3}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2, 'type3': _type3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMixinDeclaresConstructor = messageMixinDeclaresConstructor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMixinDeclaresConstructor = const MessageCode(
-    "MixinDeclaresConstructor",
-    index: 95,
-    message: r"""Mixins can't declare constructors.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String name2,
-        DartType
-            _type)> templateMixinInferenceNoMatchingClass = const Template<
-        Message Function(String name, String name2, DartType _type)>(
-    messageTemplate:
-        r"""Type parameters could not be inferred for the mixin '#name' because '#name2' does not implement the mixin's supertype constraint '#type'.""",
-    withArguments: _withArgumentsMixinInferenceNoMatchingClass);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2, DartType _type)>
-    codeMixinInferenceNoMatchingClass =
-    const Code<Message Function(String name, String name2, DartType _type)>(
-        "MixinInferenceNoMatchingClass", templateMixinInferenceNoMatchingClass,
-        analyzerCodes: <String>["MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsMixinInferenceNoMatchingClass(
-    String name, String name2, DartType _type) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeMixinInferenceNoMatchingClass,
-      message:
-          """Type parameters could not be inferred for the mixin '${name}' because '${name2}' does not implement the mixin's supertype constraint '${type}'.""" +
-              labeler.originMessages,
-      arguments: {'name': name, 'name2': name2, 'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String
-            string2)> templateModifierOutOfOrder = const Template<
-        Message Function(String string, String string2)>(
-    messageTemplate:
-        r"""The modifier '#string' should be before the modifier '#string2'.""",
-    tipTemplate: r"""Try re-ordering the modifiers.""",
-    withArguments: _withArgumentsModifierOutOfOrder);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeModifierOutOfOrder =
-    const Code<Message Function(String string, String string2)>(
-        "ModifierOutOfOrder", templateModifierOutOfOrder,
-        index: 56);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsModifierOutOfOrder(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeModifierOutOfOrder,
-      message:
-          """The modifier '${string}' should be before the modifier '${string2}'.""",
-      tip: """Try re-ordering the modifiers.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMoreThanOneSuperOrThisInitializer =
-    messageMoreThanOneSuperOrThisInitializer;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMoreThanOneSuperOrThisInitializer = const MessageCode(
-    "MoreThanOneSuperOrThisInitializer",
-    analyzerCodes: <String>["SUPER_IN_REDIRECTING_CONSTRUCTOR"],
-    message: r"""Can't have more than one 'super' or 'this' initializer.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleExtends = messageMultipleExtends;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleExtends = const MessageCode("MultipleExtends",
-    index: 28,
-    message: r"""Each class definition can have at most one extends clause.""",
-    tip:
-        r"""Try choosing one superclass and define your class to implement (or mix in) the others.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleImplements = messageMultipleImplements;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleImplements = const MessageCode(
-    "MultipleImplements",
-    analyzerCodes: <String>["MULTIPLE_IMPLEMENTS_CLAUSES"],
-    message:
-        r"""Each class definition can have at most one implements clause.""",
-    tip:
-        r"""Try combining all of the implements clauses into a single clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleLibraryDirectives =
-    messageMultipleLibraryDirectives;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleLibraryDirectives = const MessageCode(
-    "MultipleLibraryDirectives",
-    index: 27,
-    message: r"""Only one library directive may be declared in a file.""",
-    tip: r"""Try removing all but one of the library directives.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleOnClauses = messageMultipleOnClauses;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleOnClauses = const MessageCode(
-    "MultipleOnClauses",
-    index: 26,
-    message: r"""Each mixin definition can have at most one on clause.""",
-    tip: r"""Try combining all of the on clauses into a single clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleVarianceModifiers =
-    messageMultipleVarianceModifiers;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleVarianceModifiers = const MessageCode(
-    "MultipleVarianceModifiers",
-    index: 97,
-    message: r"""Each type parameter can have at most one variance modifier.""",
-    tip: r"""Use at most one of the 'in', 'out', or 'inout' modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeMultipleWith = messageMultipleWith;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageMultipleWith = const MessageCode("MultipleWith",
-    index: 24,
-    message: r"""Each class definition can have at most one with clause.""",
-    tip: r"""Try combining all of the with clauses into a single clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNamedFunctionExpression = messageNamedFunctionExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNamedFunctionExpression = const MessageCode(
-    "NamedFunctionExpression",
-    analyzerCodes: <String>["NAMED_FUNCTION_EXPRESSION"],
-    message: r"""A function expression can't have a name.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateNamedMixinOverride = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""The mixin application class '#name' introduces an erroneous override of '#name2'.""",
-    withArguments: _withArgumentsNamedMixinOverride);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsNamedMixinOverride(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeNamedMixinOverride,
-      message:
-          """The mixin application class '${name}' introduces an erroneous override of '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNativeClauseShouldBeAnnotation =
-    messageNativeClauseShouldBeAnnotation;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNativeClauseShouldBeAnnotation = const MessageCode(
-    "NativeClauseShouldBeAnnotation",
-    index: 23,
-    message: r"""Native clause in this form is deprecated.""",
-    tip:
-        r"""Try removing this native clause and adding @native() or @native('native-name') before the declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Token token)> templateNoFormals = const Template<
-        Message Function(Token token)>(
-    messageTemplate: r"""A function should have formal parameters.""",
-    tipTemplate:
-        r"""Try adding '()' after '#lexeme', or add 'get' before '#lexeme' to declare a getter.""",
-    withArguments: _withArgumentsNoFormals);
-
-// 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,
-        analyzerCodes: <String>["MISSING_FUNCTION_PARAMETERS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNoFormals(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeNoFormals,
-      message: """A function should have formal parameters.""",
-      tip:
-          """Try adding '()' after '${lexeme}', or add 'get' before '${lexeme}' to declare a getter.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateNoSuchNamedParameter =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""No named parameter with the name '#name'.""",
-        withArguments: _withArgumentsNoSuchNamedParameter);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_NAMED_PARAMETER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNoSuchNamedParameter(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNoSuchNamedParameter,
-      message: """No named parameter with the name '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNoUnnamedConstructorInObject =
-    messageNoUnnamedConstructorInObject;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNoUnnamedConstructorInObject = const MessageCode(
-    "NoUnnamedConstructorInObject",
-    message: r"""'Object' has no unnamed constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String character,
-        int
-            codePoint)> templateNonAsciiIdentifier = const Template<
-        Message Function(String character, int codePoint)>(
-    messageTemplate:
-        r"""The non-ASCII character '#character' (#unicode) can't be used in identifiers, only in strings and comments.""",
-    tipTemplate:
-        r"""Try using an US-ASCII letter, a digit, '_' (an underscore), or '$' (a dollar sign).""",
-    withArguments: _withArgumentsNonAsciiIdentifier);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String character, int codePoint)>
-    codeNonAsciiIdentifier =
-    const Code<Message Function(String character, int codePoint)>(
-        "NonAsciiIdentifier", templateNonAsciiIdentifier,
-        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonAsciiIdentifier(String character, int codePoint) {
-  if (character.runes.length != 1) throw "Not a character '${character}'";
-  String unicode =
-      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
-  return new Message(codeNonAsciiIdentifier,
-      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});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int
-            codePoint)> templateNonAsciiWhitespace = const Template<
-        Message Function(int codePoint)>(
-    messageTemplate:
-        r"""The non-ASCII space character #unicode can only be used in strings and comments.""",
-    withArguments: _withArgumentsNonAsciiWhitespace);
-
-// 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,
-        analyzerCodes: <String>["ILLEGAL_CHARACTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonAsciiWhitespace(int codePoint) {
-  String unicode =
-      "U+${codePoint.toRadixString(16).toUpperCase().padLeft(4, '0')}";
-  return new Message(codeNonAsciiWhitespace,
-      message:
-          """The non-ASCII space character ${unicode} can only be used in strings and comments.""",
-      arguments: {'codePoint': codePoint});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNonConstConstructor = messageNonConstConstructor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNonConstConstructor = const MessageCode(
-    "NonConstConstructor",
-    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
-    message:
-        r"""Cannot invoke a non-'const' constructor where a const expression is expected.""",
-    tip: r"""Try using a constructor or factory that is 'const'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNonConstFactory = messageNonConstFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNonConstFactory = const MessageCode("NonConstFactory",
-    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
-    message:
-        r"""Cannot invoke a non-'const' factory where a const expression is expected.""",
-    tip: r"""Try using a constructor or factory that is 'const'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNonInstanceTypeVariableUse =
-    messageNonInstanceTypeVariableUse;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNonInstanceTypeVariableUse = const MessageCode(
-    "NonInstanceTypeVariableUse",
-    analyzerCodes: <String>["TYPE_PARAMETER_REFERENCED_BY_STATIC"],
-    message: r"""Can only use type variables in instance methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNonNullAwareSpreadIsNull = messageNonNullAwareSpreadIsNull;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNonNullAwareSpreadIsNull = const MessageCode(
-    "NonNullAwareSpreadIsNull",
-    message: r"""Can't spread a value with static type Null.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNonPartOfDirectiveInPart = messageNonPartOfDirectiveInPart;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNonPartOfDirectiveInPart = const MessageCode(
-    "NonPartOfDirectiveInPart",
-    analyzerCodes: <String>["NON_PART_OF_DIRECTIVE_IN_PART"],
-    message: r"""The part-of directive must be the only directive in a part.""",
-    tip:
-        r"""Try removing the other directives, or moving them to the library for which this is a part.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateNonSimpleBoundViaReference =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Bound of this variable references raw type '#name'.""",
-        withArguments: _withArgumentsNonSimpleBoundViaReference);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonSimpleBoundViaReference(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNonSimpleBoundViaReference,
-      message: """Bound of this variable references raw type '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateNonSimpleBoundViaVariable = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Bound of this variable references variable '#name' from the same declaration.""",
-    withArguments: _withArgumentsNonSimpleBoundViaVariable);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonSimpleBoundViaVariable(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNonSimpleBoundViaVariable,
-      message:
-          """Bound of this variable references variable '${name}' from the same declaration.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNotAConstantExpression = messageNotAConstantExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNotAConstantExpression = const MessageCode(
-    "NotAConstantExpression",
-    analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"],
-    message: r"""Not a constant expression.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateNotAPrefixInTypeAnnotation = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""'#name.#name2' can't be used as a type because '#name' doesn't refer to an import prefix.""",
-    withArguments: _withArgumentsNotAPrefixInTypeAnnotation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeNotAPrefixInTypeAnnotation =
-    const Code<Message Function(String name, String name2)>(
-        "NotAPrefixInTypeAnnotation", templateNotAPrefixInTypeAnnotation,
-        analyzerCodes: <String>["NOT_A_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNotAPrefixInTypeAnnotation(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeNotAPrefixInTypeAnnotation,
-      message:
-          """'${name}.${name2}' can't be used as a type because '${name}' doesn't refer to an import prefix.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateNotAType =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""'#name' isn't a type.""",
-        withArguments: _withArgumentsNotAType);
-
-// 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,
-        analyzerCodes: <String>["NOT_A_TYPE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNotAType(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNotAType,
-      message: """'${name}' isn't a type.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNotATypeContext = messageNotATypeContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNotATypeContext = const MessageCode("NotATypeContext",
-    severity: Severity.context, message: r"""This isn't a type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNotAnLvalue = messageNotAnLvalue;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNotAnLvalue = const MessageCode("NotAnLvalue",
-    analyzerCodes: <String>["NOT_AN_LVALUE"],
-    message: r"""Can't assign to this.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateNotBinaryOperator =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""'#lexeme' isn't a binary operator.""",
-        withArguments: _withArgumentsNotBinaryOperator);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsNotBinaryOperator(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeNotBinaryOperator,
-      message: """'${lexeme}' isn't a binary operator.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateNotConstantExpression =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""#string is not a constant expression.""",
-        withArguments: _withArgumentsNotConstantExpression);
-
-// 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,
-        analyzerCodes: <String>["NOT_CONSTANT_EXPRESSION"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNotConstantExpression(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeNotConstantExpression,
-      message: """${string} is not a constant expression.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeNullAwareCascadeOutOfOrder =
-    messageNullAwareCascadeOutOfOrder;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageNullAwareCascadeOutOfOrder = const MessageCode(
-    "NullAwareCascadeOutOfOrder",
-    index: 96,
-    message:
-        r"""The '?..' cascade operator must be first in the cascade sequence.""",
-    tip:
-        r"""Try moving the '?..' operator to be the first cascade operator in the sequence.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeObjectExtends = messageObjectExtends;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageObjectExtends = const MessageCode("ObjectExtends",
-    message: r"""The class 'Object' can't have a superclass.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeObjectImplements = messageObjectImplements;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageObjectImplements = const MessageCode(
-    "ObjectImplements",
-    message: r"""The class 'Object' can't implement anything.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeObjectMixesIn = messageObjectMixesIn;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageObjectMixesIn = const MessageCode("ObjectMixesIn",
-    message: r"""The class 'Object' can't use mixins.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeOnlyTry = messageOnlyTry;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageOnlyTry = const MessageCode("OnlyTry",
-    index: 20,
-    message:
-        r"""A try block must be followed by an 'on', 'catch', or 'finally' clause.""",
-    tip:
-        r"""Try adding either a catch or finally clause, or remove the try statement.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateOperatorMinusParameterMismatch = const Template<
-        Message Function(String name)>(
-    messageTemplate: r"""Operator '#name' should have zero or one parameter.""",
-    tipTemplate:
-        r"""With zero parameters, it has the syntactic form '-a', formally known as 'unary-'. With one parameter, it has the syntactic form 'a - b', formally known as '-'.""",
-    withArguments: _withArgumentsOperatorMinusParameterMismatch);
-
-// 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"
-]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOperatorMinusParameterMismatch(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeOperatorMinusParameterMismatch,
-      message: """Operator '${name}' should have zero or one parameter.""",
-      tip:
-          """With zero parameters, it has the syntactic form '-a', formally known as 'unary-'. With one parameter, it has the syntactic form 'a - b', formally known as '-'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateOperatorParameterMismatch0 =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Operator '#name' shouldn't have any parameters.""",
-        withArguments: _withArgumentsOperatorParameterMismatch0);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsOperatorParameterMismatch0(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeOperatorParameterMismatch0,
-      message: """Operator '${name}' shouldn't have any parameters.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateOperatorParameterMismatch1 =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Operator '#name' should have exactly one parameter.""",
-        withArguments: _withArgumentsOperatorParameterMismatch1);
-
-// 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,
-        analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOperatorParameterMismatch1(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeOperatorParameterMismatch1,
-      message: """Operator '${name}' should have exactly one parameter.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateOperatorParameterMismatch2 =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Operator '#name' should have exactly two parameters.""",
-        withArguments: _withArgumentsOperatorParameterMismatch2);
-
-// 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,
-        analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOperatorParameterMismatch2(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeOperatorParameterMismatch2,
-      message: """Operator '${name}' should have exactly two parameters.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeOperatorWithOptionalFormals =
-    messageOperatorWithOptionalFormals;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageOperatorWithOptionalFormals = const MessageCode(
-    "OperatorWithOptionalFormals",
-    message: r"""An operator can't have optional parameters.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateOverriddenMethodCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""This is the overridden method ('#name').""",
-        withArguments: _withArgumentsOverriddenMethodCause);
-
-// 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,
-        severity: Severity.context);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverriddenMethodCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeOverriddenMethodCause,
-      message: """This is the overridden method ('${name}').""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateOverrideFewerNamedArguments = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""The method '#name' has fewer named arguments than those of overridden method '#name2'.""",
-    withArguments: _withArgumentsOverrideFewerNamedArguments);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeOverrideFewerNamedArguments =
-    const Code<Message Function(String name, String name2)>(
-        "OverrideFewerNamedArguments", templateOverrideFewerNamedArguments,
-        analyzerCodes: <String>["INVALID_OVERRIDE_NAMED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideFewerNamedArguments(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeOverrideFewerNamedArguments,
-      message:
-          """The method '${name}' has fewer named arguments than those of overridden method '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateOverrideFewerPositionalArguments = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""The method '#name' has fewer positional arguments than those of overridden method '#name2'.""",
-    withArguments: _withArgumentsOverrideFewerPositionalArguments);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    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.
-Message _withArgumentsOverrideFewerPositionalArguments(
-    String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeOverrideFewerPositionalArguments,
-      message:
-          """The method '${name}' has fewer positional arguments than those of overridden method '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String name2,
-        String
-            name3)> templateOverrideMismatchNamedParameter = const Template<
-        Message Function(String name, String name2, String name3)>(
-    messageTemplate:
-        r"""The method '#name' doesn't have the named parameter '#name2' of overridden method '#name3'.""",
-    withArguments: _withArgumentsOverrideMismatchNamedParameter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2, String name3)>
-    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.
-Message _withArgumentsOverrideMismatchNamedParameter(
-    String name, String name2, String name3) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  if (name3.isEmpty) throw 'No name provided';
-  name3 = demangleMixinApplicationName(name3);
-  return new Message(codeOverrideMismatchNamedParameter,
-      message:
-          """The method '${name}' doesn't have the named parameter '${name2}' of overridden method '${name3}'.""",
-      arguments: {'name': name, 'name2': name2, 'name3': name3});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateOverrideMoreRequiredArguments = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""The method '#name' has more required arguments than those of overridden method '#name2'.""",
-    withArguments: _withArgumentsOverrideMoreRequiredArguments);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeOverrideMoreRequiredArguments =
-    const Code<Message Function(String name, String name2)>(
-        "OverrideMoreRequiredArguments", templateOverrideMoreRequiredArguments,
-        analyzerCodes: <String>["INVALID_OVERRIDE_REQUIRED"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideMoreRequiredArguments(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeOverrideMoreRequiredArguments,
-      message:
-          """The method '${name}' has more required arguments than those of overridden method '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String name2,
-        DartType _type,
-        DartType _type2,
-        String
-            name3)> templateOverrideTypeMismatchParameter = const Template<
-        Message Function(
-            String name,
-            String name2,
-            DartType _type,
-            DartType _type2,
-            String
-                name3)>(
-    messageTemplate:
-        r"""The parameter '#name' of the method '#name2' has type '#type', which does not match the corresponding type, '#type2', in the overridden method, '#name3'.""",
-    tipTemplate:
-        r"""Change to a supertype of '#type2', or, for a covariant parameter, a subtype.""",
-    withArguments: _withArgumentsOverrideTypeMismatchParameter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(String name, String name2, DartType _type,
-            DartType _type2, String name3)> codeOverrideTypeMismatchParameter =
-    const Code<
-            Message Function(String name, String name2, DartType _type,
-                DartType _type2, String name3)>(
-        "OverrideTypeMismatchParameter", templateOverrideTypeMismatchParameter,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideTypeMismatchParameter(
-    String name, String name2, DartType _type, DartType _type2, String name3) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name3.isEmpty) throw 'No name provided';
-  name3 = demangleMixinApplicationName(name3);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeOverrideTypeMismatchParameter,
-      message:
-          """The parameter '${name}' of the method '${name2}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden method, '${name3}'.""" +
-              labeler.originMessages,
-      tip: """Change to a supertype of '${type2}', or, for a covariant parameter, a subtype.""",
-      arguments: {
-        'name': name,
-        'name2': name2,
-        'type': _type,
-        'type2': _type2,
-        'name3': name3
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType _type,
-        DartType _type2,
-        String
-            name2)> templateOverrideTypeMismatchReturnType = const Template<
-        Message Function(
-            String name, DartType _type, DartType _type2, String name2)>(
-    messageTemplate:
-        r"""The return type of the method '#name' is '#type', which does not match the return type, '#type2', of the overridden method, '#name2'.""",
-    tipTemplate: r"""Change to a subtype of '#type2'.""",
-    withArguments: _withArgumentsOverrideTypeMismatchReturnType);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            String name, DartType _type, DartType _type2, String name2)>
-    codeOverrideTypeMismatchReturnType = const Code<
-            Message Function(
-                String name, DartType _type, DartType _type2, String name2)>(
-        "OverrideTypeMismatchReturnType",
-        templateOverrideTypeMismatchReturnType,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideTypeMismatchReturnType(
-    String name, DartType _type, DartType _type2, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeOverrideTypeMismatchReturnType,
-      message:
-          """The return type of the method '${name}' is '${type}', which does not match the return type, '${type2}', of the overridden method, '${name2}'.""" +
-              labeler.originMessages,
-      tip: """Change to a subtype of '${type2}'.""",
-      arguments: {
-        'name': name,
-        'type': _type,
-        'type2': _type2,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType _type,
-        DartType _type2,
-        String
-            name2)> templateOverrideTypeMismatchSetter = const Template<
-        Message Function(
-            String name, DartType _type, DartType _type2, String name2)>(
-    messageTemplate:
-        r"""The field '#name' has type '#type', which does not match the corresponding type, '#type2', in the overridden setter, '#name2'.""",
-    withArguments: _withArgumentsOverrideTypeMismatchSetter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-        Message Function(
-            String name, DartType _type, DartType _type2, String name2)>
-    codeOverrideTypeMismatchSetter = const Code<
-            Message Function(
-                String name, DartType _type, DartType _type2, String name2)>(
-        "OverrideTypeMismatchSetter", templateOverrideTypeMismatchSetter,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideTypeMismatchSetter(
-    String name, DartType _type, DartType _type2, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeOverrideTypeMismatchSetter,
-      message:
-          """The field '${name}' has type '${type}', which does not match the corresponding type, '${type2}', in the overridden setter, '${name2}'.""" +
-              labeler.originMessages,
-      arguments: {
-        'name': name,
-        'type': _type,
-        'type2': _type2,
-        'name2': name2
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateOverrideTypeVariablesMismatch = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""Declared type variables of '#name' doesn't match those on overridden method '#name2'.""",
-    withArguments: _withArgumentsOverrideTypeVariablesMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    codeOverrideTypeVariablesMismatch =
-    const Code<Message Function(String name, String name2)>(
-        "OverrideTypeVariablesMismatch", templateOverrideTypeVariablesMismatch,
-        analyzerCodes: <String>["INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsOverrideTypeVariablesMismatch(String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeOverrideTypeVariablesMismatch,
-      message:
-          """Declared type variables of '${name}' doesn't match those on overridden method '${name2}'.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-        Message Function(String name, Uri uri_)> templatePackageNotFound =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate:
-            r"""Could not resolve the package '#name' in '#uri'.""",
-        withArguments: _withArgumentsPackageNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codePackageNotFound,
-      message: """Could not resolve the package '${name}' in '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templatePackagesFileFormat =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Problem in packages configuration file: #string""",
-        withArguments: _withArgumentsPackagesFileFormat);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsPackagesFileFormat(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codePackagesFileFormat,
-      message: """Problem in packages configuration file: ${string}""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartExport = messagePartExport;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartExport = const MessageCode("PartExport",
-    analyzerCodes: <String>["EXPORT_OF_NON_LIBRARY"],
-    message:
-        r"""Can't export this file because it contains a 'part of' declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartExportContext = messagePartExportContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartExportContext = const MessageCode(
-    "PartExportContext",
-    severity: Severity.context,
-    message: r"""This is the file that can't be exported.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartInPart = messagePartInPart;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartInPart = const MessageCode("PartInPart",
-    analyzerCodes: <String>["NON_PART_OF_DIRECTIVE_IN_PART"],
-    message: r"""A file that's a part of a library can't have parts itself.""",
-    tip: r"""Try moving the 'part' declaration to the containing library.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartInPartLibraryContext = messagePartInPartLibraryContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartInPartLibraryContext = const MessageCode(
-    "PartInPartLibraryContext",
-    severity: Severity.context,
-    message: r"""This is the containing library.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(Uri uri_)> templatePartOfInLibrary = const Template<
-        Message Function(Uri uri_)>(
-    messageTemplate:
-        r"""Can't import '#uri', because it has a 'part of' declaration.""",
-    tipTemplate:
-        r"""Try removing the 'part of' declaration, or using '#uri' as a part.""",
-    withArguments: _withArgumentsPartOfInLibrary);
-
-// 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,
-        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_);
-  return new Message(codePartOfInLibrary,
-      message:
-          """Can't import '${uri}', because it has a 'part of' declaration.""",
-      tip:
-          """Try removing the 'part of' declaration, or using '${uri}' as a part.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Uri uri_,
-        String name,
-        String
-            name2)> templatePartOfLibraryNameMismatch = const Template<
-        Message Function(Uri uri_, String name, String name2)>(
-    messageTemplate:
-        r"""Using '#uri' as part of '#name' but its 'part of' declaration says '#name2'.""",
-    withArguments: _withArgumentsPartOfLibraryNameMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Uri uri_, String name, String name2)>
-    codePartOfLibraryNameMismatch =
-    const Code<Message Function(Uri uri_, String name, String name2)>(
-        "PartOfLibraryNameMismatch", templatePartOfLibraryNameMismatch,
-        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_);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codePartOfLibraryNameMismatch,
-      message:
-          """Using '${uri}' as part of '${name}' but its 'part of' declaration says '${name2}'.""",
-      arguments: {'uri': uri_, 'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartOfSelf = messagePartOfSelf;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartOfSelf = const MessageCode("PartOfSelf",
-    analyzerCodes: <String>["PART_OF_NON_PART"],
-    message: r"""A file can't be a part of itself.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartOfTwice = messagePartOfTwice;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartOfTwice = const MessageCode("PartOfTwice",
-    index: 25,
-    message: r"""Only one part-of directive may be declared in a file.""",
-    tip: r"""Try removing all but one of the part-of directives.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartOfTwoLibraries = messagePartOfTwoLibraries;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartOfTwoLibraries = const MessageCode(
-    "PartOfTwoLibraries",
-    analyzerCodes: <String>["PART_OF_DIFFERENT_LIBRARY"],
-    message: r"""A file can't be part of more than one library.""",
-    tip:
-        r"""Try moving the shared declarations into the libraries, or into a new library.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartOfTwoLibrariesContext =
-    messagePartOfTwoLibrariesContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartOfTwoLibrariesContext = const MessageCode(
-    "PartOfTwoLibrariesContext",
-    severity: Severity.context,
-    message: r"""Used as a part in this library.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Uri uri_,
-        Uri uri2_,
-        Uri
-            uri3_)> templatePartOfUriMismatch = const Template<
-        Message Function(Uri uri_, Uri uri2_, Uri uri3_)>(
-    messageTemplate:
-        r"""Using '#uri' as part of '#uri2' but its 'part of' declaration says '#uri3'.""",
-    withArguments: _withArgumentsPartOfUriMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>
-    codePartOfUriMismatch =
-    const Code<Message Function(Uri uri_, Uri uri2_, Uri uri3_)>(
-        "PartOfUriMismatch", templatePartOfUriMismatch,
-        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_);
-  return new Message(codePartOfUriMismatch,
-      message:
-          """Using '${uri}' as part of '${uri2}' but its 'part of' declaration says '${uri3}'.""",
-      arguments: {'uri': uri_, 'uri2': uri2_, 'uri3': uri3_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Uri uri_,
-        Uri uri2_,
-        String
-            name)> templatePartOfUseUri = const Template<
-        Message Function(Uri uri_, Uri uri2_, String name)>(
-    messageTemplate:
-        r"""Using '#uri' as part of '#uri2' but its 'part of' declaration says '#name'.""",
-    tipTemplate:
-        r"""Try changing the 'part of' declaration to use a relative file name.""",
-    withArguments: _withArgumentsPartOfUseUri);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Uri uri_, Uri uri2_, String name)>
-    codePartOfUseUri =
-    const Code<Message Function(Uri uri_, Uri uri2_, String name)>(
-        "PartOfUseUri", templatePartOfUseUri,
-        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_);
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codePartOfUseUri,
-      message:
-          """Using '${uri}' as part of '${uri2}' but its 'part of' declaration says '${name}'.""",
-      tip: """Try changing the 'part of' declaration to use a relative file name.""",
-      arguments: {'uri': uri_, 'uri2': uri2_, 'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePartOrphan = messagePartOrphan;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePartOrphan = const MessageCode("PartOrphan",
-    message: r"""This part doesn't have a containing library.""",
-    tip: r"""Try removing the 'part of' declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templatePartTwice =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""Can't use '#uri' as a part more than once.""",
-        withArguments: _withArgumentsPartTwice);
-
-// 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,
-        analyzerCodes: <String>["DUPLICATE_PART"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsPartTwice(Uri uri_) {
-  String uri = relativizeUri(uri_);
-  return new Message(codePartTwice,
-      message: """Can't use '${uri}' as a part more than once.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePatchClassOrigin = messagePatchClassOrigin;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePatchClassOrigin = const MessageCode(
-    "PatchClassOrigin",
-    severity: Severity.context,
-    message: r"""This is the origin class.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePatchClassTypeVariablesMismatch =
-    messagePatchClassTypeVariablesMismatch;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePatchClassTypeVariablesMismatch = const MessageCode(
-    "PatchClassTypeVariablesMismatch",
-    message:
-        r"""A patch class must have the same number of type variables as its origin class.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePatchDeclarationMismatch = messagePatchDeclarationMismatch;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePatchDeclarationMismatch = const MessageCode(
-    "PatchDeclarationMismatch",
-    message: r"""This patch doesn't match origin declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePatchDeclarationOrigin = messagePatchDeclarationOrigin;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePatchDeclarationOrigin = const MessageCode(
-    "PatchDeclarationOrigin",
-    severity: Severity.context,
-    message: r"""This is the origin declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)>
-    templatePatchInjectionFailed =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate: r"""Can't inject '#name' into '#uri'.""",
-        tipTemplate: r"""Try adding '@patch'.""",
-        withArguments: _withArgumentsPatchInjectionFailed);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codePatchInjectionFailed,
-      message: """Can't inject '${name}' into '${uri}'.""",
-      tip: """Try adding '@patch'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePatchNonExternal = messagePatchNonExternal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePatchNonExternal = const MessageCode(
-    "PatchNonExternal",
-    message:
-        r"""Can't apply this patch as its origin declaration isn't external.""",
-    tip: r"""Try adding 'external' to the origin declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePlatformPrivateLibraryAccess =
-    messagePlatformPrivateLibraryAccess;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePlatformPrivateLibraryAccess = const MessageCode(
-    "PlatformPrivateLibraryAccess",
-    analyzerCodes: <String>["IMPORT_INTERNAL_LIBRARY"],
-    message: r"""Can't access platform private library.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePositionalAfterNamedArgument =
-    messagePositionalAfterNamedArgument;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePositionalAfterNamedArgument = const MessageCode(
-    "PositionalAfterNamedArgument",
-    analyzerCodes: <String>["POSITIONAL_AFTER_NAMED_ARGUMENT"],
-    message: r"""Place positional arguments before named arguments.""",
-    tip:
-        r"""Try moving the positional argument before the named arguments, or add a name to the argument.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePositionalParameterWithEquals =
-    messagePositionalParameterWithEquals;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePositionalParameterWithEquals = const MessageCode(
-    "PositionalParameterWithEquals",
-    analyzerCodes: <String>["WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER"],
-    message:
-        r"""Positional optional parameters can't use ':' to specify a default value.""",
-    tip: r"""Try replacing ':' with '='.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePrefixAfterCombinator = messagePrefixAfterCombinator;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePrefixAfterCombinator = const MessageCode(
-    "PrefixAfterCombinator",
-    index: 6,
-    message:
-        r"""The prefix ('as' clause) should come before any show/hide combinators.""",
-    tip: r"""Try moving the prefix before the combinators.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codePrivateNamedParameter = messagePrivateNamedParameter;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messagePrivateNamedParameter = const MessageCode(
-    "PrivateNamedParameter",
-    analyzerCodes: <String>["PRIVATE_OPTIONAL_PARAMETER"],
-    message: r"""An optional named parameter can't start with '_'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeRedirectingConstructorWithBody =
-    messageRedirectingConstructorWithBody;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageRedirectingConstructorWithBody = const MessageCode(
-    "RedirectingConstructorWithBody",
-    index: 22,
-    message: r"""Redirecting constructors can't have a body.""",
-    tip:
-        r"""Try removing the body, or not making this a redirecting constructor.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(DartType _type, DartType _type2)>
-    templateRedirectingFactoryIncompatibleTypeArgument =
-    const Template<Message Function(DartType _type, DartType _type2)>(
-        messageTemplate: r"""The type '#type' doesn't extend '#type2'.""",
-        tipTemplate: r"""Try using a different type as argument.""",
-        withArguments:
-            _withArgumentsRedirectingFactoryIncompatibleTypeArgument);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeRedirectingFactoryIncompatibleTypeArgument =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "RedirectingFactoryIncompatibleTypeArgument",
-        templateRedirectingFactoryIncompatibleTypeArgument,
-        analyzerCodes: <String>["TYPE_ARGUMENT_NOT_MATCHING_BOUNDS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsRedirectingFactoryIncompatibleTypeArgument(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeRedirectingFactoryIncompatibleTypeArgument,
-      message: """The type '${type}' doesn't extend '${type2}'.""" +
-          labeler.originMessages,
-      tip: """Try using a different type as argument.""",
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeRedirectionInNonFactory = messageRedirectionInNonFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageRedirectionInNonFactory = const MessageCode(
-    "RedirectionInNonFactory",
-    index: 21,
-    message: r"""Only factory constructor can specify '=' redirection.""",
-    tip:
-        r"""Try making this a factory constructor, or remove the redirection.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateRedirectionTargetNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Redirection constructor target not found: '#name'""",
-        withArguments: _withArgumentsRedirectionTargetNotFound);
-
-// 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,
-        analyzerCodes: <String>["REDIRECT_TO_MISSING_CONSTRUCTOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsRedirectionTargetNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeRedirectionTargetNotFound,
-      message: """Redirection constructor target not found: '${name}'""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeRequiredParameterWithDefault =
-    messageRequiredParameterWithDefault;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageRequiredParameterWithDefault = const MessageCode(
-    "RequiredParameterWithDefault",
-    analyzerCodes: <String>["NAMED_PARAMETER_OUTSIDE_GROUP"],
-    message: r"""Non-optional parameters can't have a default value.""",
-    tip:
-        r"""Try removing the default value or making the parameter optional.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeRethrowNotCatch = messageRethrowNotCatch;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageRethrowNotCatch = const MessageCode("RethrowNotCatch",
-    analyzerCodes: <String>["RETHROW_OUTSIDE_CATCH"],
-    message: r"""'rethrow' can only be used in catch clauses.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeReturnFromVoidFunction = messageReturnFromVoidFunction;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageReturnFromVoidFunction = const MessageCode(
-    "ReturnFromVoidFunction",
-    analyzerCodes: <String>["RETURN_OF_INVALID_TYPE"],
-    message: r"""Can't return a value from a void function.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeReturnTypeFunctionExpression =
-    messageReturnTypeFunctionExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageReturnTypeFunctionExpression = const MessageCode(
-    "ReturnTypeFunctionExpression",
-    message: r"""A function expression can't have a return type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeReturnWithoutExpression = messageReturnWithoutExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageReturnWithoutExpression = const MessageCode(
-    "ReturnWithoutExpression",
-    analyzerCodes: <String>["RETURN_WITHOUT_VALUE"],
-    severity: Severity.warning,
-    message: r"""Must explicitly return a value from a non-void function.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateSdkRootNotFound =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""SDK root directory not found: #uri.""",
-        withArguments: _withArgumentsSdkRootNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codeSdkRootNotFound,
-      message: """SDK root directory not found: ${uri}.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        Uri
-            uri_)> templateSdkSpecificationNotFound = const Template<
-        Message Function(Uri uri_)>(
-    messageTemplate: r"""SDK libraries specification not found: #uri.""",
-    tipTemplate:
-        r"""Normally, the specification is a file named 'libraries.json' in the Dart SDK install location.""",
-    withArguments: _withArgumentsSdkSpecificationNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codeSdkSpecificationNotFound,
-      message: """SDK libraries specification not found: ${uri}.""",
-      tip:
-          """Normally, the specification is a file named 'libraries.json' in the Dart SDK install location.""",
-      arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateSdkSummaryNotFound =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""SDK summary not found: #uri.""",
-        withArguments: _withArgumentsSdkSummaryNotFound);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codeSdkSummaryNotFound,
-      message: """SDK summary not found: ${uri}.""", arguments: {'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSetLiteralTooManyTypeArguments =
-    messageSetLiteralTooManyTypeArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSetLiteralTooManyTypeArguments = const MessageCode(
-    "SetLiteralTooManyTypeArguments",
-    message: r"""A set literal requires exactly one type argument.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSetOrMapLiteralTooManyTypeArguments =
-    messageSetOrMapLiteralTooManyTypeArguments;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSetOrMapLiteralTooManyTypeArguments = const MessageCode(
-    "SetOrMapLiteralTooManyTypeArguments",
-    message:
-        r"""A set or map literal requires exactly one or two type arguments, respectively.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSetterNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Setter not found: '#name'.""",
-        withArguments: _withArgumentsSetterNotFound);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_SETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSetterNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSetterNotFound,
-      message: """Setter not found: '${name}'.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSetterNotSync = messageSetterNotSync;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSetterNotSync = const MessageCode("SetterNotSync",
-    analyzerCodes: <String>["INVALID_MODIFIER_ON_SETTER"],
-    message: r"""Setters can't use 'async', 'async*', or 'sync*'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSetterWithWrongNumberOfFormals =
-    messageSetterWithWrongNumberOfFormals;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSetterWithWrongNumberOfFormals = const MessageCode(
-    "SetterWithWrongNumberOfFormals",
-    analyzerCodes: <String>["WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER"],
-    message: r"""A setter should have exactly one formal parameter.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int count,
-        int count2,
-        num _num1,
-        num _num2,
-        num
-            _num3)> templateSourceBodySummary = const Template<
-        Message Function(
-            int count, int count2, num _num1, num _num2, num _num3)>(
-    messageTemplate:
-        r"""Built bodies for #count compilation units (#count2 bytes) in #num1%.3ms, that is,
-#num2%12.3 bytes/ms, and
-#num3%12.3 ms/compilation unit.""",
-    withArguments: _withArgumentsSourceBodySummary);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-    Message Function(int count, int count2, num _num1, num _num2,
-        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) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  if (_num1 == null) throw 'No number provided';
-  String num1 = _num1.toStringAsFixed(3);
-  if (_num2 == null) throw 'No number provided';
-  String num2 = _num2.toStringAsFixed(3).padLeft(12);
-  if (_num3 == null) throw 'No number provided';
-  String num3 = _num3.toStringAsFixed(3).padLeft(12);
-  return new Message(codeSourceBodySummary,
-      message:
-          """Built bodies for ${count} compilation units (${count2} bytes) in ${num1}ms, that is,
-${num2} bytes/ms, and
-${num3} ms/compilation unit.""",
-      arguments: {
-        'count': count,
-        'count2': count2,
-        'num1': _num1,
-        'num2': _num2,
-        'num3': _num3
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int count,
-        int count2,
-        num _num1,
-        num _num2,
-        num
-            _num3)> templateSourceOutlineSummary = const Template<
-        Message Function(
-            int count, int count2, num _num1, num _num2, num _num3)>(
-    messageTemplate:
-        r"""Built outlines for #count compilation units (#count2 bytes) in #num1%.3ms, that is,
-#num2%12.3 bytes/ms, and
-#num3%12.3 ms/compilation unit.""",
-    withArguments: _withArgumentsSourceOutlineSummary);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<
-    Message Function(int count, int count2, num _num1, num _num2,
-        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) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  if (_num1 == null) throw 'No number provided';
-  String num1 = _num1.toStringAsFixed(3);
-  if (_num2 == null) throw 'No number provided';
-  String num2 = _num2.toStringAsFixed(3).padLeft(12);
-  if (_num3 == null) throw 'No number provided';
-  String num3 = _num3.toStringAsFixed(3).padLeft(12);
-  return new Message(codeSourceOutlineSummary,
-      message:
-          """Built outlines for ${count} compilation units (${count2} bytes) in ${num1}ms, that is,
-${num2} bytes/ms, and
-${num3} ms/compilation unit.""",
-      arguments: {
-        'count': count,
-        'count2': count2,
-        'num1': _num1,
-        'num2': _num2,
-        'num3': _num3
-      });
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSpreadElement = messageSpreadElement;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSpreadElement = const MessageCode("SpreadElement",
-    severity: Severity.context, message: r"""Iterable spread.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateSpreadElementTypeMismatch = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""Can't assign spread elements of type '#type' to collection elements of type '#type2'.""",
-    withArguments: _withArgumentsSpreadElementTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeSpreadElementTypeMismatch =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "SpreadElementTypeMismatch", templateSpreadElementTypeMismatch,
-        analyzerCodes: <String>["LIST_ELEMENT_TYPE_NOT_ASSIGNABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSpreadElementTypeMismatch(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeSpreadElementTypeMismatch,
-      message:
-          """Can't assign spread elements of type '${type}' to collection elements of type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSpreadMapElement = messageSpreadMapElement;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSpreadMapElement = const MessageCode(
-    "SpreadMapElement",
-    severity: Severity.context,
-    message: r"""Map spread.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateSpreadMapEntryElementKeyTypeMismatch = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""Can't assign spread entry keys of type '#type' to map entry keys of type '#type2'.""",
-    withArguments: _withArgumentsSpreadMapEntryElementKeyTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeSpreadMapEntryElementKeyTypeMismatch =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "SpreadMapEntryElementKeyTypeMismatch",
-        templateSpreadMapEntryElementKeyTypeMismatch,
-        analyzerCodes: <String>["MAP_KEY_TYPE_NOT_ASSIGNABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSpreadMapEntryElementKeyTypeMismatch(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeSpreadMapEntryElementKeyTypeMismatch,
-      message:
-          """Can't assign spread entry keys of type '${type}' to map entry keys of type '${type2}'.""" +
-              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)>
-    templateSpreadMapEntryElementValueTypeMismatch =
-    const Template<Message Function(DartType _type, DartType _type2)>(
-        messageTemplate:
-            r"""Can't assign spread entry values of type '#type' to map entry values of type '#type2'.""",
-        withArguments: _withArgumentsSpreadMapEntryElementValueTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeSpreadMapEntryElementValueTypeMismatch =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "SpreadMapEntryElementValueTypeMismatch",
-        templateSpreadMapEntryElementValueTypeMismatch,
-        analyzerCodes: <String>["MAP_VALUE_TYPE_NOT_ASSIGNABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSpreadMapEntryElementValueTypeMismatch(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeSpreadMapEntryElementValueTypeMismatch,
-      message:
-          """Can't assign spread entry values of type '${type}' to map entry values of type '${type2}'.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateSpreadMapEntryTypeMismatch = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Unexpected type '#type' of a map spread entry.  Expected 'dynamic' or a Map.""",
-    withArguments: _withArgumentsSpreadMapEntryTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeSpreadMapEntryTypeMismatch =
-    const Code<Message Function(DartType _type)>(
-  "SpreadMapEntryTypeMismatch",
-  templateSpreadMapEntryTypeMismatch,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSpreadMapEntryTypeMismatch(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeSpreadMapEntryTypeMismatch,
-      message:
-          """Unexpected type '${type}' of a map spread entry.  Expected 'dynamic' or a Map.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType
-            _type)> templateSpreadTypeMismatch = const Template<
-        Message Function(DartType _type)>(
-    messageTemplate:
-        r"""Unexpected type '#type' of a spread.  Expected 'dynamic' or an Iterable.""",
-    withArguments: _withArgumentsSpreadTypeMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type)> codeSpreadTypeMismatch =
-    const Code<Message Function(DartType _type)>(
-  "SpreadTypeMismatch",
-  templateSpreadTypeMismatch,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSpreadTypeMismatch(DartType _type) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeSpreadTypeMismatch,
-      message:
-          """Unexpected type '${type}' of a spread.  Expected 'dynamic' or an Iterable.""" +
-              labeler.originMessages,
-      arguments: {'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStackOverflow = messageStackOverflow;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStackOverflow = const MessageCode("StackOverflow",
-    index: 19,
-    message: r"""The file has too many nested expressions or statements.""",
-    tip: r"""Try simplifying the code.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAndInstanceConflict =
-    messageStaticAndInstanceConflict;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAndInstanceConflict = const MessageCode(
-    "StaticAndInstanceConflict",
-    analyzerCodes: <String>["CONFLICTING_STATIC_AND_INSTANCE"],
-    message: r"""This static member conflicts with an instance member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAndInstanceConflictCause =
-    messageStaticAndInstanceConflictCause;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAndInstanceConflictCause = const MessageCode(
-    "StaticAndInstanceConflictCause",
-    severity: Severity.context,
-    message: r"""This is the instance member.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticConstructor = messageStaticConstructor;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticConstructor = const MessageCode(
-    "StaticConstructor",
-    index: 4,
-    message: r"""Constructors can't be static.""",
-    tip: r"""Try removing the keyword 'static'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticOperator = messageStaticOperator;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticOperator = const MessageCode("StaticOperator",
-    index: 17,
-    message: r"""Operators can't be static.""",
-    tip: r"""Try removing the keyword 'static'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSuperAsExpression = messageSuperAsExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSuperAsExpression = const MessageCode(
-    "SuperAsExpression",
-    analyzerCodes: <String>["SUPER_AS_EXPRESSION"],
-    message: r"""Can't use 'super' as an expression.""",
-    tip:
-        r"""To delegate a constructor to a super constructor, put the super call as an initializer.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSuperAsIdentifier = messageSuperAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSuperAsIdentifier = const MessageCode(
-    "SuperAsIdentifier",
-    analyzerCodes: <String>["SUPER_AS_EXPRESSION"],
-    message: r"""Expected identifier, but got 'super'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSuperInitializerNotLast = messageSuperInitializerNotLast;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSuperInitializerNotLast = const MessageCode(
-    "SuperInitializerNotLast",
-    analyzerCodes: <String>["INVALID_SUPER_INVOCATION"],
-    message: r"""Can't have initializers after 'super'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSuperNullAware = messageSuperNullAware;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSuperNullAware = const MessageCode("SuperNullAware",
-    index: 18,
-    message:
-        r"""The operator '?.' cannot be used with 'super' because 'super' cannot be null.""",
-    tip: r"""Try replacing '?.' with '.'""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateSuperclassHasNoConstructor =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Superclass has no constructor named '#name'.""",
-        withArguments: _withArgumentsSuperclassHasNoConstructor);
-
-// 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,
-        analyzerCodes: <String>[
-      "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER",
-      "UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT"
-    ]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSuperclassHasNoConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassHasNoConstructor,
-      message: """Superclass has no constructor named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateSuperclassHasNoDefaultConstructor = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""The superclass, '#name', has no unnamed constructor that takes no arguments.""",
-    withArguments: _withArgumentsSuperclassHasNoDefaultConstructor);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    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.
-Message _withArgumentsSuperclassHasNoDefaultConstructor(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassHasNoDefaultConstructor,
-      message:
-          """The superclass, '${name}', has no unnamed constructor that takes no arguments.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSuperclassHasNoGetter =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Superclass has no getter named '#name'.""",
-        withArguments: _withArgumentsSuperclassHasNoGetter);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_SUPER_GETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSuperclassHasNoGetter(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassHasNoGetter,
-      message: """Superclass has no getter named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSuperclassHasNoMethod =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Superclass has no method named '#name'.""",
-        withArguments: _withArgumentsSuperclassHasNoMethod);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_SUPER_METHOD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSuperclassHasNoMethod(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassHasNoMethod,
-      message: """Superclass has no method named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSuperclassHasNoSetter =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Superclass has no setter named '#name'.""",
-        withArguments: _withArgumentsSuperclassHasNoSetter);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_SUPER_SETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSuperclassHasNoSetter(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassHasNoSetter,
-      message: """Superclass has no setter named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateSuperclassMethodArgumentMismatch = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""Superclass doesn't have a method named '#name' with matching arguments.""",
-    withArguments: _withArgumentsSuperclassMethodArgumentMismatch);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsSuperclassMethodArgumentMismatch(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSuperclassMethodArgumentMismatch,
-      message:
-          """Superclass doesn't have a method named '${name}' with matching arguments.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSupertypeIsFunction = messageSupertypeIsFunction;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSupertypeIsFunction = const MessageCode(
-    "SupertypeIsFunction",
-    message: r"""Can't use a function type as supertype.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSupertypeIsIllegal =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""The type '#name' can't be used as supertype.""",
-        withArguments: _withArgumentsSupertypeIsIllegal);
-
-// 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,
-        analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSupertypeIsIllegal(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSupertypeIsIllegal,
-      message: """The type '${name}' can't be used as supertype.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateSupertypeIsTypeVariable =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""The type variable '#name' can't be used as supertype.""",
-        withArguments: _withArgumentsSupertypeIsTypeVariable);
-
-// 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,
-        analyzerCodes: <String>["EXTENDS_NON_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSupertypeIsTypeVariable(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeSupertypeIsTypeVariable,
-      message: """The type variable '${name}' can't be used as supertype.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSwitchCaseFallThrough = messageSwitchCaseFallThrough;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSwitchCaseFallThrough = const MessageCode(
-    "SwitchCaseFallThrough",
-    analyzerCodes: <String>["CASE_BLOCK_NOT_TERMINATED"],
-    message: r"""Switch case may fall through to the next case.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        DartType _type,
-        DartType
-            _type2)> templateSwitchExpressionNotAssignable = const Template<
-        Message Function(DartType _type, DartType _type2)>(
-    messageTemplate:
-        r"""Type '#type' of the switch expression isn't assignable to the type '#type2' of this case expression.""",
-    withArguments: _withArgumentsSwitchExpressionNotAssignable);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(DartType _type, DartType _type2)>
-    codeSwitchExpressionNotAssignable =
-    const Code<Message Function(DartType _type, DartType _type2)>(
-        "SwitchExpressionNotAssignable", templateSwitchExpressionNotAssignable,
-        analyzerCodes: <String>["SWITCH_EXPRESSION_NOT_ASSIGNABLE"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsSwitchExpressionNotAssignable(
-    DartType _type, DartType _type2) {
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  List<Object> type2Parts = labeler.labelType(_type2);
-  String type = typeParts.join();
-  String type2 = type2Parts.join();
-  return new Message(codeSwitchExpressionNotAssignable,
-      message:
-          """Type '${type}' of the switch expression isn't assignable to the type '${type2}' of this case expression.""" +
-              labeler.originMessages,
-      arguments: {'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSwitchExpressionNotAssignableCause =
-    messageSwitchExpressionNotAssignableCause;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSwitchExpressionNotAssignableCause = const MessageCode(
-    "SwitchExpressionNotAssignableCause",
-    severity: Severity.context,
-    message: r"""The switch expression is here.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSwitchHasCaseAfterDefault =
-    messageSwitchHasCaseAfterDefault;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSwitchHasCaseAfterDefault = const MessageCode(
-    "SwitchHasCaseAfterDefault",
-    index: 16,
-    message:
-        r"""The default case should be the last case in a switch statement.""",
-    tip: r"""Try moving the default case after the other case clauses.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSwitchHasMultipleDefaults =
-    messageSwitchHasMultipleDefaults;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSwitchHasMultipleDefaults = const MessageCode(
-    "SwitchHasMultipleDefaults",
-    index: 15,
-    message: r"""The 'default' case can only be declared once.""",
-    tip: r"""Try removing all but one default case.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeSyntheticToken = messageSyntheticToken;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageSyntheticToken = const MessageCode("SyntheticToken",
-    message: r"""This couldn't be parsed.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateThisAccessInFieldInitializer =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't access 'this' in a field initializer to read '#name'.""",
-        withArguments: _withArgumentsThisAccessInFieldInitializer);
-
-// 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,
-        analyzerCodes: <String>["THIS_ACCESS_FROM_FIELD_INITIALIZER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsThisAccessInFieldInitializer(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeThisAccessInFieldInitializer,
-      message:
-          """Can't access 'this' in a field initializer to read '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeThisAsIdentifier = messageThisAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageThisAsIdentifier = const MessageCode(
-    "ThisAsIdentifier",
-    analyzerCodes: <String>["INVALID_REFERENCE_TO_THIS"],
-    message: r"""Expected identifier, but got 'this'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeThisInitializerNotAlone = messageThisInitializerNotAlone;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageThisInitializerNotAlone = const MessageCode(
-    "ThisInitializerNotAlone",
-    analyzerCodes: <String>["FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR"],
-    message: r"""Can't have other initializers together with 'this'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
-    templateThisOrSuperAccessInFieldInitializer =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""Can't access '#string' in a field initializer.""",
-        withArguments: _withArgumentsThisOrSuperAccessInFieldInitializer);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
-    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.
-Message _withArgumentsThisOrSuperAccessInFieldInitializer(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeThisOrSuperAccessInFieldInitializer,
-      message: """Can't access '${string}' in a field initializer.""",
-      arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int count,
-        int
-            count2)> templateTooFewArguments = const Template<
-        Message Function(int count, int count2)>(
-    messageTemplate:
-        r"""Too few positional arguments: #count required, #count2 given.""",
-    withArguments: _withArgumentsTooFewArguments);
-
-// 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,
-        analyzerCodes: <String>["NOT_ENOUGH_REQUIRED_ARGUMENTS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsTooFewArguments(int count, int count2) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  return new Message(codeTooFewArguments,
-      message:
-          """Too few positional arguments: ${count} required, ${count2} given.""",
-      arguments: {'count': count, 'count2': count2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        int count,
-        int
-            count2)> templateTooManyArguments = const Template<
-        Message Function(int count, int count2)>(
-    messageTemplate:
-        r"""Too many positional arguments: #count allowed, but #count2 found.""",
-    tipTemplate: r"""Try removing the extra positional arguments.""",
-    withArguments: _withArgumentsTooManyArguments);
-
-// 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,
-        analyzerCodes: <String>["EXTRA_POSITIONAL_ARGUMENTS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsTooManyArguments(int count, int count2) {
-  if (count == null) throw 'No count provided';
-  if (count2 == null) throw 'No count provided';
-  return new Message(codeTooManyArguments,
-      message:
-          """Too many positional arguments: ${count} allowed, but ${count2} found.""",
-      tip: """Try removing the extra positional arguments.""",
-      arguments: {'count': count, 'count2': count2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTopLevelOperator = messageTopLevelOperator;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTopLevelOperator = const MessageCode(
-    "TopLevelOperator",
-    index: 14,
-    message: r"""Operators must be declared within a class.""",
-    tip:
-        r"""Try removing the operator, moving it to a class, or converting it to be a function.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeAfterVar = messageTypeAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeAfterVar = const MessageCode("TypeAfterVar",
-    index: 89,
-    message:
-        r"""Variables can't be declared using both 'var' and a type name.""",
-    tip: r"""Try removing 'var.'""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(int count)> templateTypeArgumentMismatch =
-    const Template<Message Function(int count)>(
-        messageTemplate: r"""Expected #count type arguments.""",
-        withArguments: _withArgumentsTypeArgumentMismatch);
-
-// 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,
-        analyzerCodes: <String>["WRONG_NUMBER_OF_TYPE_ARGUMENTS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsTypeArgumentMismatch(int count) {
-  if (count == null) throw 'No count provided';
-  return new Message(codeTypeArgumentMismatch,
-      message: """Expected ${count} type arguments.""",
-      arguments: {'count': count});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateTypeArgumentsOnTypeVariable =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Can't use type arguments with type variable '#name'.""",
-        tipTemplate: r"""Try removing the type arguments.""",
-        withArguments: _withArgumentsTypeArgumentsOnTypeVariable);
-
-// 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,
-        index: 13);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsTypeArgumentsOnTypeVariable(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeTypeArgumentsOnTypeVariable,
-      message: """Can't use type arguments with type variable '${name}'.""",
-      tip: """Try removing the type arguments.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeBeforeFactory = messageTypeBeforeFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeBeforeFactory = const MessageCode(
-    "TypeBeforeFactory",
-    index: 57,
-    message: r"""Factory constructors cannot have a return type.""",
-    tip: r"""Try removing the type appearing before 'factory'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)> templateTypeNotFound =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""Type '#name' not found.""",
-        withArguments: _withArgumentsTypeNotFound);
-
-// 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,
-        analyzerCodes: <String>["UNDEFINED_CLASS"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsTypeNotFound(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeTypeNotFound,
-      message: """Type '${name}' not found.""", arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_)> templateTypeOrigin =
-    const Template<Message Function(String name, Uri uri_)>(
-        messageTemplate: r"""'#name' is from '#uri'.""",
-        withArguments: _withArgumentsTypeOrigin);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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_);
-  return new Message(codeTypeOrigin,
-      message: """'${name}' is from '${uri}'.""",
-      arguments: {'name': name, 'uri': uri_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, Uri uri_, Uri uri2_)>
-    templateTypeOriginWithFileUri =
-    const Template<Message Function(String name, Uri uri_, Uri uri2_)>(
-        messageTemplate: r"""'#name' is from '#uri' ('#uri2').""",
-        withArguments: _withArgumentsTypeOriginWithFileUri);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, Uri uri_, Uri uri2_)>
-    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_);
-  return new Message(codeTypeOriginWithFileUri,
-      message: """'${name}' is from '${uri}' ('${uri2}').""",
-      arguments: {'name': name, 'uri': uri_, 'uri2': uri2_});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeVariableDuplicatedName =
-    messageTypeVariableDuplicatedName;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeVariableDuplicatedName = const MessageCode(
-    "TypeVariableDuplicatedName",
-    analyzerCodes: <String>["DUPLICATE_DEFINITION"],
-    message: r"""A type variable can't have the same name as another.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateTypeVariableDuplicatedNameCause =
-    const Template<Message Function(String name)>(
-        messageTemplate: r"""The other type variable named '#name'.""",
-        withArguments: _withArgumentsTypeVariableDuplicatedNameCause);
-
-// 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.
-Message _withArgumentsTypeVariableDuplicatedNameCause(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeTypeVariableDuplicatedNameCause,
-      message: """The other type variable named '${name}'.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeVariableInConstantContext =
-    messageTypeVariableInConstantContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeVariableInConstantContext = const MessageCode(
-    "TypeVariableInConstantContext",
-    analyzerCodes: <String>["TYPE_PARAMETER_IN_CONST_EXPRESSION"],
-    message: r"""Type variables can't be used as constants.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeVariableInStaticContext =
-    messageTypeVariableInStaticContext;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeVariableInStaticContext = const MessageCode(
-    "TypeVariableInStaticContext",
-    analyzerCodes: <String>["TYPE_PARAMETER_REFERENCED_BY_STATIC"],
-    message: r"""Type variables can't be used in static members.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypeVariableSameNameAsEnclosing =
-    messageTypeVariableSameNameAsEnclosing;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypeVariableSameNameAsEnclosing = const MessageCode(
-    "TypeVariableSameNameAsEnclosing",
-    analyzerCodes: <String>["CONFLICTING_TYPE_VARIABLE_AND_CLASS"],
-    message:
-        r"""A type variable can't have the same name as its enclosing declaration.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypedefInClass = messageTypedefInClass;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypedefInClass = const MessageCode("TypedefInClass",
-    index: 7,
-    message: r"""Typedefs can't be declared inside classes.""",
-    tip: r"""Try moving the typedef to the top-level.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeTypedefNotFunction = messageTypedefNotFunction;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageTypedefNotFunction = const MessageCode(
-    "TypedefNotFunction",
-    analyzerCodes: <String>["INVALID_GENERIC_FUNCTION_TYPE"],
-    message: r"""Can't create typedef from non-function type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType
-            _type)> templateUndefinedGetter = const Template<
-        Message Function(String name, DartType _type)>(
-    messageTemplate:
-        r"""The getter '#name' isn't defined for the class '#type'.""",
-    tipTemplate:
-        r"""Try correcting the name to the name of an existing getter, or defining a getter or field named '#name'.""",
-    withArguments: _withArgumentsUndefinedGetter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type)> codeUndefinedGetter =
-    const Code<Message Function(String name, DartType _type)>(
-        "UndefinedGetter", templateUndefinedGetter,
-        analyzerCodes: <String>["UNDEFINED_GETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUndefinedGetter(String name, DartType _type) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeUndefinedGetter,
-      message:
-          """The getter '${name}' isn't defined for the class '${type}'.""" +
-              labeler.originMessages,
-      tip:
-          """Try correcting the name to the name of an existing getter, or defining a getter or field named '${name}'.""",
-      arguments: {'name': name, 'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType
-            _type)> templateUndefinedMethod = const Template<
-        Message Function(String name, DartType _type)>(
-    messageTemplate:
-        r"""The method '#name' isn't defined for the class '#type'.""",
-    tipTemplate:
-        r"""Try correcting the name to the name of an existing method, or defining a method named '#name'.""",
-    withArguments: _withArgumentsUndefinedMethod);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type)> codeUndefinedMethod =
-    const Code<Message Function(String name, DartType _type)>(
-        "UndefinedMethod", templateUndefinedMethod,
-        analyzerCodes: <String>["UNDEFINED_METHOD"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUndefinedMethod(String name, DartType _type) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeUndefinedMethod,
-      message:
-          """The method '${name}' isn't defined for the class '${type}'.""" +
-              labeler.originMessages,
-      tip:
-          """Try correcting the name to the name of an existing method, or defining a method named '${name}'.""",
-      arguments: {'name': name, 'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        DartType
-            _type)> templateUndefinedSetter = const Template<
-        Message Function(String name, DartType _type)>(
-    messageTemplate:
-        r"""The setter '#name' isn't defined for the class '#type'.""",
-    tipTemplate:
-        r"""Try correcting the name to the name of an existing setter, or defining a setter or field named '#name'.""",
-    withArguments: _withArgumentsUndefinedSetter);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type)> codeUndefinedSetter =
-    const Code<Message Function(String name, DartType _type)>(
-        "UndefinedSetter", templateUndefinedSetter,
-        analyzerCodes: <String>["UNDEFINED_SETTER"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUndefinedSetter(String name, DartType _type) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  TypeLabeler labeler = new TypeLabeler();
-  List<Object> typeParts = labeler.labelType(_type);
-  String type = typeParts.join();
-  return new Message(codeUndefinedSetter,
-      message:
-          """The setter '${name}' isn't defined for the class '${type}'.""" +
-              labeler.originMessages,
-      tip:
-          """Try correcting the name to the name of an existing setter, or defining a setter or field named '${name}'.""",
-      arguments: {'name': name, 'type': _type});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeUnexpectedDollarInString = messageUnexpectedDollarInString;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageUnexpectedDollarInString = const MessageCode(
-    "UnexpectedDollarInString",
-    analyzerCodes: <String>["UNEXPECTED_DOLLAR_IN_STRING"],
-    message:
-        r"""A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).""",
-    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)> templateUnexpectedToken =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""Unexpected token '#lexeme'.""",
-        withArguments: _withArgumentsUnexpectedToken);
-
-// 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,
-        analyzerCodes: <String>["UNEXPECTED_TOKEN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUnexpectedToken(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeUnexpectedToken,
-      message: """Unexpected token '${lexeme}'.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, Token token)>
-    templateUnmatchedToken =
-    const Template<Message Function(String string, Token token)>(
-        messageTemplate: r"""Can't find '#string' to match '#lexeme'.""",
-        withArguments: _withArgumentsUnmatchedToken);
-
-// 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,
-        analyzerCodes: <String>["EXPECTED_TOKEN"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUnmatchedToken(String string, Token token) {
-  if (string.isEmpty) throw 'No string provided';
-  String lexeme = token.lexeme;
-  return new Message(codeUnmatchedToken,
-      message: """Can't find '${string}' to match '${lexeme}'.""",
-      arguments: {'string': string, 'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String name,
-        String
-            name2)> templateUnresolvedPrefixInTypeAnnotation = const Template<
-        Message Function(String name, String name2)>(
-    messageTemplate:
-        r"""'#name.#name2' can't be used as a type because '#name' isn't defined.""",
-    withArguments: _withArgumentsUnresolvedPrefixInTypeAnnotation);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)>
-    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.
-Message _withArgumentsUnresolvedPrefixInTypeAnnotation(
-    String name, String name2) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  if (name2.isEmpty) throw 'No name provided';
-  name2 = demangleMixinApplicationName(name2);
-  return new Message(codeUnresolvedPrefixInTypeAnnotation,
-      message:
-          """'${name}.${name2}' can't be used as a type because '${name}' isn't defined.""",
-      arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)> templateUnspecified =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""#string""",
-        withArguments: _withArgumentsUnspecified);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-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.
-Message _withArgumentsUnspecified(String string) {
-  if (string.isEmpty) throw 'No string provided';
-  return new Message(codeUnspecified,
-      message: """${string}""", arguments: {'string': string});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateUnsupportedOperator =
-    const Template<Message Function(Token token)>(
-        messageTemplate: r"""The '#lexeme' operator is not supported.""",
-        withArguments: _withArgumentsUnsupportedOperator);
-
-// 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,
-        analyzerCodes: <String>["UNSUPPORTED_OPERATOR"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUnsupportedOperator(Token token) {
-  String lexeme = token.lexeme;
-  return new Message(codeUnsupportedOperator,
-      message: """The '${lexeme}' operator is not supported.""",
-      arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeUnsupportedPrefixPlus = messageUnsupportedPrefixPlus;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageUnsupportedPrefixPlus = const MessageCode(
-    "UnsupportedPrefixPlus",
-    analyzerCodes: <String>["MISSING_IDENTIFIER"],
-    message: r"""'+' is not a prefix operator.""",
-    tip: r"""Try removing '+'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeUnterminatedComment = messageUnterminatedComment;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageUnterminatedComment = const MessageCode(
-    "UnterminatedComment",
-    analyzerCodes: <String>["UNTERMINATED_MULTI_LINE_COMMENT"],
-    message: r"""Comment starting with '/*' must end with '*/'.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2)>
-    templateUnterminatedString =
-    const Template<Message Function(String string, String string2)>(
-        messageTemplate:
-            r"""String starting with #string must end with #string2.""",
-        withArguments: _withArgumentsUnterminatedString);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeUnterminatedString =
-    const Code<Message Function(String string, String string2)>(
-        "UnterminatedString", templateUnterminatedString,
-        analyzerCodes: <String>["UNTERMINATED_STRING_LITERAL"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsUnterminatedString(String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeUnterminatedString,
-      message: """String starting with ${string} must end with ${string2}.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeUnterminatedToken = messageUnterminatedToken;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageUnterminatedToken =
-    const MessageCode("UnterminatedToken", message: r"""Incomplete token.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Uri uri_)> templateUntranslatableUri =
-    const Template<Message Function(Uri uri_)>(
-        messageTemplate: r"""Not found: '#uri'""",
-        withArguments: _withArgumentsUntranslatableUri);
-
-// 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,
-        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_);
-  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 Code<Null> codeVarAsTypeName = messageVarAsTypeName;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageVarAsTypeName = const MessageCode("VarAsTypeName",
-    index: 61, message: r"""The keyword 'var' can't be used as a type name.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeVarReturnType = messageVarReturnType;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageVarReturnType = const MessageCode("VarReturnType",
-    index: 12,
-    message: r"""The return type can't be 'var'.""",
-    tip:
-        r"""Try removing the keyword 'var', or replacing it with the name of the return type.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeVoidExpression = messageVoidExpression;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageVoidExpression = const MessageCode("VoidExpression",
-    analyzerCodes: <String>["USE_OF_VOID_RESULT"],
-    message: r"""This expression has type 'void' and can't be used.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String string,
-        String
-            string2)> templateWebLiteralCannotBeRepresentedExactly = const Template<
-        Message Function(String string, String string2)>(
-    messageTemplate:
-        r"""The integer literal #string can't be represented exactly in JavaScript.""",
-    tipTemplate:
-        r"""Try changing the literal to something that can be represented in Javascript. In Javascript #string2 is the nearest value that can be represented exactly.""",
-    withArguments: _withArgumentsWebLiteralCannotBeRepresentedExactly);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
-    codeWebLiteralCannotBeRepresentedExactly =
-    const Code<Message Function(String string, String string2)>(
-  "WebLiteralCannotBeRepresentedExactly",
-  templateWebLiteralCannotBeRepresentedExactly,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsWebLiteralCannotBeRepresentedExactly(
-    String string, String string2) {
-  if (string.isEmpty) throw 'No string provided';
-  if (string2.isEmpty) throw 'No string provided';
-  return new Message(codeWebLiteralCannotBeRepresentedExactly,
-      message:
-          """The integer literal ${string} can't be represented exactly in JavaScript.""",
-      tip: """Try changing the literal to something that can be represented in Javascript. In Javascript ${string2} is the nearest value that can be represented exactly.""",
-      arguments: {'string': string, 'string2': string2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeWithBeforeExtends = messageWithBeforeExtends;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageWithBeforeExtends = const MessageCode(
-    "WithBeforeExtends",
-    index: 11,
-    message: r"""The extends clause must be before the with clause.""",
-    tip: r"""Try moving the extends clause before the with clause.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeYieldAsIdentifier = messageYieldAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageYieldAsIdentifier = const MessageCode(
-    "YieldAsIdentifier",
-    analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
-    message:
-        r"""'yield' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeYieldNotGenerator = messageYieldNotGenerator;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageYieldNotGenerator = const MessageCode(
-    "YieldNotGenerator",
-    analyzerCodes: <String>["YIELD_IN_NON_GENERATOR"],
-    message: r"""'yield' can only be used in 'sync*' or 'async*' methods.""");
diff --git a/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart b/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
deleted file mode 100644
index 7129694..0000000
--- a/pkg/front_end/lib/src/fasta/flow_analysis/flow_analysis.dart
+++ /dev/null
@@ -1,1715 +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:meta/meta.dart';
-
-/// [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
-/// should be used prior to running flow analysis, to compute the sets of
-/// variables to pass in to flow analysis.
-///
-/// This class is intended to be used in two phases.  In the first phase, the
-/// client should traverse the source code recursively, making calls to
-/// [beginNode] and [endNode] to indicate the constructs in which writes should
-/// be tracked, and calls to [write] to indicate when a write is encountered.
-/// The order of visiting is not important provided that nesting is respected.
-/// This phase is called the "pre-traversal" because it should happen prior to
-/// flow analysis.
-///
-/// Then, in the second phase, the client may make queries using
-/// [capturedAnywhere], [writtenInNode], and [capturedInNode].
-///
-/// 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> {
-  /// Mapping from a node to the set of local variables that are potentially
-  /// written to within that node.
-  final Map<Node, Set<Variable>> _writtenInNode = {};
-
-  /// Mapping from a node to the set of local variables for which a potential
-  /// write is captured by a local function or closure inside that node.
-  final Map<Node, Set<Variable>> _capturedInNode = {};
-
-  /// Set of local variables that are potentially written to anywhere in the
-  /// code being analyzed.
-  final Set<Variable> _writtenAnywhere = {};
-
-  /// Set of local variables for which a potential write is captured by a local
-  /// function or closure anywhere in the code being analyzed.
-  final Set<Variable> _capturedAnywhere = {};
-
-  /// Stack of sets accumulating variables that are potentially written to.
-  ///
-  /// A set is pushed onto the stack when a node is entered, and popped when
-  /// a node is left.
-  final List<Set<Variable>> _writtenStack = [new Set<Variable>.identity()];
-
-  /// Stack of sets accumulating variables that are declared.
-  ///
-  /// A set is pushed onto the stack when a node is entered, and popped when
-  /// a node is left.
-  final List<Set<Variable>> _declaredStack = [new Set<Variable>.identity()];
-
-  /// Stack of sets accumulating variables for which a potential write is
-  /// captured by a local function or closure.
-  ///
-  /// A set is pushed onto the stack when a node is entered, and popped when
-  /// a node is left.
-  final List<Set<Variable>> _capturedStack = [new Set<Variable>.identity()];
-
-  AssignedVariables();
-
-  /// Queries the set of variables for which a potential write is captured by a
-  /// local function or closure anywhere in the code being analyzed.
-  Set<Variable> get capturedAnywhere => _capturedAnywhere;
-
-  /// Queries the set of variables that are potentially written to anywhere in
-  /// the code being analyzed.
-  Set<Variable> get writtenAnywhere => _writtenAnywhere;
-
-  /// This method should be called during pre-traversal, to mark the start of a
-  /// loop statement, switch statement, try statement, loop collection element,
-  /// local function, or closure which might need to be queried later.
-  ///
-  /// [isClosure] should be true if the node is a local function or closure.
-  ///
-  /// The span between the call to [beginNode] and [endNode] should cover any
-  /// statements and expressions that might be crossed by a backwards jump.  So
-  /// for instance, in a "for" loop, the condition, updaters, and body should be
-  /// covered, but the initializers should not.  Similarly, in a switch
-  /// statement, the body of the switch statement should be covered, but the
-  /// switch expression should not.
-  void beginNode() {
-    _writtenStack.add(new Set<Variable>.identity());
-    _declaredStack.add(new Set<Variable>.identity());
-    _capturedStack.add(new Set<Variable>.identity());
-  }
-
-  /// Queries the set of variables for which a potential write is captured by a
-  /// local function or closure inside the [node].
-  Set<Variable> capturedInNode(Node node) {
-    return _capturedInNode[node] ??
-        (throw new StateError('No information for $node'));
-  }
-
-  /// This method should be called during pre-traversal, to indicate that the
-  /// declaration of a variable has been found.
-  ///
-  /// It is not required for the declaration to be seen prior to its use (this
-  /// is to allow for error recovery in the analyzer).
-  void declare(Variable variable) {
-    _declaredStack.last.add(variable);
-  }
-
-  /// This method should be called during pre-traversal, to mark the end of a
-  /// loop statement, switch statement, try statement, loop collection element,
-  /// local function, or closure which might need to be queried later.
-  ///
-  /// [isClosure] should be true if the node is a local function or closure.
-  ///
-  /// See [beginNode] for more details.
-  void endNode(Node node, {bool isClosure: false}) {
-    Set<Variable> declaredInThisNode = _declaredStack.removeLast();
-    Set<Variable> writtenInThisNode = _writtenStack.removeLast()
-      ..removeAll(declaredInThisNode);
-    Set<Variable> capturedInThisNode = _capturedStack.removeLast()
-      ..removeAll(declaredInThisNode);
-    _writtenInNode[node] = writtenInThisNode;
-    _capturedInNode[node] = capturedInThisNode;
-    _writtenStack.last.addAll(writtenInThisNode);
-    _capturedStack.last.addAll(capturedInThisNode);
-    if (isClosure) {
-      _capturedStack.last.addAll(writtenInThisNode);
-      _capturedAnywhere.addAll(writtenInThisNode);
-    }
-  }
-
-  /// Call this after visiting the code to be analyzed, to check invariants.
-  void finish() {
-    assert(() {
-      assert(_writtenStack.length == 1);
-      assert(_declaredStack.length == 1);
-      assert(_capturedStack.length == 1);
-      Set<Variable> writtenInThisNode = _writtenStack.last;
-      Set<Variable> declaredInThisNode = _declaredStack.last;
-      Set<Variable> capturedInThisNode = _capturedStack.last;
-      Set<Variable> undeclaredWrites =
-          writtenInThisNode.difference(declaredInThisNode);
-      assert(undeclaredWrites.isEmpty,
-          'Variables written to but not declared: $undeclaredWrites');
-      Set<Variable> undeclaredCaptures =
-          capturedInThisNode.difference(declaredInThisNode);
-      assert(undeclaredCaptures.isEmpty,
-          'Variables captured but not declared: $undeclaredCaptures');
-      return true;
-    }());
-  }
-
-  /// This method should be called during pre-traversal, to mark a write to a
-  /// variable.
-  void write(Variable variable) {
-    _writtenStack.last.add(variable);
-    _writtenAnywhere.add(variable);
-  }
-
-  /// Queries the set of variables that are potentially written to inside the
-  /// [node].
-  Set<Variable> writtenInNode(Node node) {
-    return _writtenInNode[node] ??
-        (throw new StateError('No information for $node'));
-  }
-}
-
-/// Implementation of flow analysis to be shared between the analyzer and the
-/// front end.
-///
-/// 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<Statement, Expression, Variable, Type> {
-  factory FlowAnalysis(
-      TypeOperations<Variable, Type> typeOperations,
-      Iterable<Variable> variablesWrittenAnywhere,
-      Iterable<Variable> variablesCapturedAnywhere) {
-    return new _FlowAnalysisImpl(typeOperations,
-        variablesWrittenAnywhere.toList(), variablesCapturedAnywhere.toList());
-  }
-
-  /// Return `true` if the current state is reachable.
-  bool get isReachable;
-
-  /// Call this method when visiting a boolean literal expression.
-  void booleanLiteral(Expression expression, bool value);
-
-  /// Call this method upon reaching the ":" part of a conditional expression
-  /// ("?:").  [thenExpression] should be the expression preceding the ":".
-  void conditional_elseBegin(Expression thenExpression);
-
-  /// Call this method when finishing the visit of a conditional expression
-  /// ("?:").  [elseExpression] should be the expression preceding the ":", and
-  /// [conditionalExpression] should be the whole conditional expression.
-  void conditional_end(
-      Expression conditionalExpression, Expression elseExpression);
-
-  /// Call this method upon reaching the "?" part of a conditional expression
-  /// ("?:").  [condition] should be the expression preceding the "?".
-  void conditional_thenBegin(Expression condition);
-
-  /// Call this method before visiting the body of a "do-while" statement.
-  /// [loopAssigned] should be the set of variables that are assigned in the
-  /// body of the loop (or the condition), and [loopCaptured] should be the set
-  /// of variables that are captured by closures within the body of the loop (or
-  /// the condition).
-  void doStatement_bodyBegin(Statement doStatement,
-      Iterable<Variable> loopAssigned, Iterable<Variable> loopCaptured);
-
-  /// Call this method after visiting the body of a "do-while" statement, and
-  /// before visiting its condition.
-  void doStatement_conditionBegin();
-
-  /// Call this method after visiting the condition of a "do-while" statement.
-  /// [condition] should be the condition of the loop.
-  void doStatement_end(Expression condition);
-
-  /// Call this method just after visiting a binary `==` or `!=` expression.
-  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
-      {bool notEqual = false});
-
-  /// Call this method just after visiting the left hand side of a binary `==`
-  /// or `!=` expression.
-  void equalityOp_rightBegin(Expression leftOperand);
-
-  /// This method should be called at the conclusion of flow analysis for a top
-  /// level function or method.  Performs assertion checks.
-  void finish();
-
-  /// Call this method just before visiting the body of a conventional "for"
-  /// statement or collection element.  See [for_conditionBegin] for details.
-  ///
-  /// If a "for" statement is being entered, [node] is an opaque representation
-  /// of the loop, for use as the target of future calls to [handleBreak] or
-  /// [handleContinue].  If a "for" collection element is being entered, [node]
-  /// should be `null`.
-  ///
-  /// [condition] is an opaque representation of the loop condition; it is
-  /// matched against expressions passed to previous calls to determine whether
-  /// 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);
-
-  /// Call this method just before visiting the condition of a conventional
-  /// "for" statement or collection element.
-  ///
-  /// Note that a conventional "for" statement is a statement of the form
-  /// `for (initializers; condition; updaters) body`.  Statements of the form
-  /// `for (variable in iterable) body` should use [forEach_bodyBegin].  Similar
-  /// for "for" collection elements.
-  ///
-  /// The order of visiting a "for" statement or collection element should be:
-  /// - Visit the initializers.
-  /// - Call [for_conditionBegin].
-  /// - Visit the condition.
-  /// - Call [for_bodyBegin].
-  /// - Visit the body.
-  /// - Call [for_updaterBegin].
-  /// - Visit the updaters.
-  /// - Call [for_end].
-  ///
-  /// [loopAssigned] should be the set of variables that are assigned anywhere
-  /// in the loop's condition, updaters, or body.
-  void for_conditionBegin(
-      Set<Variable> loopAssigned, Set<Variable> loopCaptured);
-
-  /// Call this method just after visiting the updaters of a conventional "for"
-  /// statement or collection element.  See [for_conditionBegin] for details.
-  void for_end();
-
-  /// Call this method just before visiting the updaters of a conventional "for"
-  /// statement or collection element.  See [for_conditionBegin] for details.
-  void for_updaterBegin();
-
-  /// Call this method just before visiting the body of a "for-in" statement or
-  /// collection element.
-  ///
-  /// The order of visiting a "for-in" statement or collection element should
-  /// be:
-  /// - Visit the iterable expression.
-  /// - Call [forEach_bodyBegin].
-  /// - Visit the body.
-  /// - Call [forEach_end].
-  ///
-  /// [loopAssigned] should be the set of variables that are assigned anywhere
-  /// in the loop's body.  [loopVariable] should be the loop variable, if it's a
-  /// local variable, or `null` otherwise.
-  void forEach_bodyBegin(Iterable<Variable> loopAssigned,
-      Iterable<Variable> loopCaptured, Variable loopVariable);
-
-  /// Call this method just before visiting the body of a "for-in" statement or
-  /// collection element.  See [forEach_bodyBegin] for details.
-  void forEach_end();
-
-  /// Call this method just before visiting the body of a function expression or
-  /// local function.
-  void functionExpression_begin(Iterable<Variable> writeCaptured);
-
-  /// Call this method just after visiting the body of a function expression or
-  /// local function.
-  void functionExpression_end();
-
-  /// Call this method when visiting a break statement.  [target] should be the
-  /// statement targeted by the break.
-  void handleBreak(Statement target);
-
-  /// Call this method when visiting a continue statement.  [target] should be
-  /// the statement targeted by the continue.
-  void handleContinue(Statement target);
-
-  /// Register the fact that the current state definitely exists, e.g. returns
-  /// from the body, throws an exception, etc.
-  void handleExit();
-
-  /// Call this method after visiting the RHS of an if-null ("??") expression.
-  void ifNullExpression_end();
-
-  /// Call this method after visiting the LHS of an if-null ("??") expression.
-  void ifNullExpression_rightBegin();
-
-  /// Call this method after visiting the "then" part of an if statement, and
-  /// before visiting the "else" part.
-  void ifStatement_elseBegin();
-
-  /// Call this method after visiting an if statement.
-  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.
-  ///
-  /// The order of visiting an if statement with no "else" part should be:
-  /// - Visit the condition
-  /// - Call [ifStatement_thenBegin]
-  /// - Visit the "then" statement
-  /// - Call [ifStatement_end], passing `false` for `hasElse`.
-  ///
-  /// The order of visiting an if statement with an "else" part should be:
-  /// - Visit the condition
-  /// - Call [ifStatement_thenBegin]
-  /// - Visit the "then" statement
-  /// - Call [ifStatement_elseBegin]
-  /// - Visit the "else" statement
-  /// - Call [ifStatement_end], passing `true` for `hasElse`.
-  void ifStatement_thenBegin(Expression condition);
-
-  /// Register an initialized declaration of the given [variable] in the current
-  /// state.  Should also be called for function parameters.
-  void initialize(Variable variable);
-
-  /// Return whether the [variable] is definitely assigned in the current state.
-  bool isAssigned(Variable variable);
-
-  /// Call this method after visiting the LHS of an "is" expression that checks
-  /// the type of a promotable variable.
-  /// [isExpression] should be the complete expression.  [variable] should be
-  /// the promotable variable.  [isNot] should be a boolean indicating whether
-  /// this is an "is" or an "is!" expression.  [type] should be the type being
-  /// checked.
-  void isExpression_end(
-      Expression isExpression, Variable variable, bool isNot, Type type);
-
-  /// Call this method after visiting the RHS of a logical binary operation
-  /// ("||" or "&&").
-  /// [wholeExpression] should be the whole logical binary expression.
-  /// [rightOperand] should be the RHS.  [isAnd] should indicate whether the
-  /// logical operator is "&&" or "||".
-  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
-      {@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});
-
-  /// Call this method after visiting a logical not ("!") expression.
-  /// [notExpression] should be the complete expression.  [operand] should be
-  /// the subexpression whose logical value is being negated.
-  void logicalNot_end(Expression notExpression, Expression operand);
-
-  /// Call this method just after visiting a non-null assertion (`x!`)
-  /// expression.
-  void nonNullAssert_end(Expression operand);
-
-  /// Call this method when encountering an expression that is a `null` literal.
-  void nullLiteral(Expression expression);
-
-  /// Call this method just after visiting a parenthesized expression.
-  ///
-  /// This is only necessary if the implementation uses a different [Expression]
-  /// object to represent a parenthesized expression and its contents.
-  void parenthesizedExpression(
-      Expression outerExpression, Expression innerExpression);
-
-  /// Retrieves the type that the [variable] is promoted to, if the [variable]
-  /// is currently promoted.  Otherwise returns `null`.
-  ///
-  /// For testing only.  Please use [variableRead] instead.
-  @visibleForTesting
-  Type promotedType(Variable variable);
-
-  /// Call this method just before visiting one of the cases in the body of a
-  /// switch statement.  See [switchStatement_expressionEnd] for details.
-  ///
-  /// [hasLabel] indicates whether the case has any labels.
-  ///
-  /// The [notPromoted] set contains all variables that are potentially assigned
-  /// within the body of the switch statement.
-  void switchStatement_beginCase(bool hasLabel, Iterable<Variable> notPromoted,
-      Iterable<Variable> captured);
-
-  /// Call this method just after visiting the body of a switch statement.  See
-  /// [switchStatement_expressionEnd] for details.
-  ///
-  /// [hasDefault] indicates whether the switch statement had a "default" case.
-  void switchStatement_end(bool hasDefault);
-
-  /// Call this method just after visiting the expression part of a switch
-  /// statement.
-  ///
-  /// The order of visiting a switch statement should be:
-  /// - Visit the switch expression.
-  /// - Call [switchStatement_expressionEnd].
-  /// - For each switch case (including the default case, if any):
-  ///   - Call [switchStatement_beginCase].
-  ///   - Visit the case.
-  /// - Call [switchStatement_end].
-  void switchStatement_expressionEnd(Statement switchStatement);
-
-  /// Call this method just before visiting the body of a "try/catch" statement.
-  ///
-  /// The order of visiting a "try/catch" statement should be:
-  /// - Call [tryCatchStatement_bodyBegin]
-  /// - Visit the try block
-  /// - Call [tryCatchStatement_bodyEnd]
-  /// - For each catch block:
-  ///   - Call [tryCatchStatement_catchBegin]
-  ///   - Call [initialize] for the exception and stack trace variables
-  ///   - Visit the catch block
-  ///   - Call [tryCatchStatement_catchEnd]
-  /// - Call [tryCatchStatement_end]
-  ///
-  /// The order of visiting a "try/catch/finally" statement should be:
-  /// - Call [tryFinallyStatement_bodyBegin]
-  /// - Call [tryCatchStatement_bodyBegin]
-  /// - Visit the try block
-  /// - Call [tryCatchStatement_bodyEnd]
-  /// - For each catch block:
-  ///   - Call [tryCatchStatement_catchBegin]
-  ///   - Call [initialize] for the exception and stack trace variables
-  ///   - Visit the catch block
-  ///   - Call [tryCatchStatement_catchEnd]
-  /// - Call [tryCatchStatement_end]
-  /// - Call [tryFinallyStatement_finallyBegin]
-  /// - Visit the finally block
-  /// - Call [tryFinallyStatement_end]
-  void tryCatchStatement_bodyBegin();
-
-  /// Call this method just after visiting the body of a "try/catch" statement.
-  /// See [tryCatchStatement_bodyBegin] for details.
-  ///
-  /// [assignedInBody] should be the set of variables assigned in the "try" part
-  /// of the statement.  [capturedInBody] should be the set of variables
-  /// captured by closures in the "try" part of the statement.
-  void tryCatchStatement_bodyEnd(
-      Iterable<Variable> assignedInBody, Iterable<Variable> capturedInBody);
-
-  /// Call this method just before visiting a catch clause of a "try/catch"
-  /// statement.  See [tryCatchStatement_bodyBegin] for details.
-  void tryCatchStatement_catchBegin();
-
-  /// Call this method just after visiting a catch clause of a "try/catch"
-  /// statement.  See [tryCatchStatement_bodyBegin] for details.
-  void tryCatchStatement_catchEnd();
-
-  /// Call this method just after visiting a "try/catch" statement.  See
-  /// [tryCatchStatement_bodyBegin] for details.
-  void tryCatchStatement_end();
-
-  /// Call this method just before visiting the body of a "try/finally"
-  /// statement.
-  ///
-  /// The order of visiting a "try/finally" statement should be:
-  /// - Call [tryFinallyStatement_bodyBegin]
-  /// - Visit the try block
-  /// - Call [tryFinallyStatement_finallyBegin]
-  /// - Visit the finally block
-  /// - Call [tryFinallyStatement_end]
-  ///
-  /// See [tryCatchStatement_bodyBegin] for the order of visiting a
-  /// "try/catch/finally" statement.
-  void tryFinallyStatement_bodyBegin();
-
-  /// Call this method just after visiting a "try/finally" statement.
-  /// See [tryFinallyStatement_bodyBegin] for details.
-  ///
-  /// [assignedInFinally] should be the set of variables assigned in the
-  /// "finally" part of the statement.
-  void tryFinallyStatement_end(Set<Variable> assignedInFinally);
-
-  /// Call this method just before visiting the finally block of a "try/finally"
-  /// statement.  See [tryFinallyStatement_bodyBegin] for details.
-  void tryFinallyStatement_finallyBegin(
-      Iterable<Variable> assignedInBody, Iterable<Variable> capturedInBody);
-
-  /// Call this method when encountering an expression that reads the value of
-  /// a variable.
-  ///
-  /// If the variable's type is currently promoted, the promoted type is
-  /// returned.  Otherwise `null` is returned.
-  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
-  /// be the condition part of the while statement.
-  void whileStatement_bodyBegin(Statement whileStatement, Expression condition);
-
-  /// Call this method before visiting the condition part of a "while"
-  /// statement.
-  /// [loopAssigned] should be the set of variables assigned in the body of the
-  /// loop (or in the condition).  [loopCaptured] should be the set of variables
-  /// captured by closures in the body of the loop (or in the condition).
-  void whileStatement_conditionBegin(
-      Iterable<Variable> loopAssigned, Iterable<Variable> loopCaptured);
-
-  /// Call this method after visiting a "while" statement.
-  void whileStatement_end();
-
-  /// Register write of the given [variable] in the current state.
-  void write(Variable variable);
-}
-
-/// An instance of the [FlowModel] class represents the information gathered by
-/// flow analysis at a single point in the control flow of the function or
-/// method being analyzed.
-///
-/// 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> {
-  /// Indicates whether this point in the control flow is reachable.
-  final bool reachable;
-
-  /// For each variable being tracked by flow analysis, the variable's model.
-  ///
-  /// Flow analysis has no awareness of scope, so variables that are out of
-  /// scope are retained in the map until such time as their declaration no
-  /// longer dominates the control flow.  So, for example, if a variable is
-  /// declared inside the `then` branch of an `if` statement, and the `else`
-  /// branch of the `if` statement ends in a `return` statement, then the
-  /// variable remains in the map after the `if` statement ends, even though the
-  /// variable is not in scope anymore.  This should not have any effect on
-  /// analysis results for error-free code, because it is an error to refer to a
-  /// variable that is no longer in scope.
-  final Map<Variable, VariableModel<Type> /*!*/ > variableInfo;
-
-  /// Variable model for variables that have never been seen before.
-  final VariableModel<Type> _freshVariableInfo;
-
-  /// Creates a state object with the given [reachable] status.  All variables
-  /// are assumed to be unpromoted and already assigned, so joining another
-  /// state with this one will have no effect on it.
-  FlowModel(bool reachable)
-      : this._(
-          reachable,
-          const {},
-        );
-
-  FlowModel._(this.reachable, this.variableInfo)
-      : _freshVariableInfo = new VariableModel.fresh() {
-    assert(() {
-      for (VariableModel<Type> value in variableInfo.values) {
-        assert(value != null);
-      }
-      return true;
-    }());
-  }
-
-  /// Gets the info for the given [variable], creating it if it doesn't exist.
-  VariableModel<Type> infoFor(Variable variable) =>
-      variableInfo[variable] ?? _freshVariableInfo;
-
-  /// Updates the state to indicate that the given [variable] has been
-  /// determined to contain a non-null value.
-  ///
-  /// TODO(paulberry): should this method mark the variable as definitely
-  /// assigned?  Does it matter?
-  FlowModel<Variable, Type> markNonNullable(
-      TypeOperations<Variable, Type> typeOperations, Variable variable) {
-    VariableModel<Type> info = infoFor(variable);
-    if (info.writeCaptured) return this;
-    Type previousType = info.promotedType;
-    previousType ??= typeOperations.variableType(variable);
-    Type type = typeOperations.promoteToNonNull(previousType);
-    if (typeOperations.isSameType(type, previousType)) return this;
-    return _updateVariableInfo(variable, info.withPromotedType(type));
-  }
-
-  /// Updates the state to indicate that the given [variable] has been
-  /// determined to satisfy the given [type], e.g. as a consequence of an `is`
-  /// expression as the condition of an `if` statement.
-  ///
-  /// Note that the state is only changed if [type] is a subtype of the
-  /// variable's previous (possibly promoted) type.
-  ///
-  /// TODO(paulberry): if the type is non-nullable, should this method mark the
-  /// variable as definitely assigned?  Does it matter?
-  FlowModel<Variable, Type> promote(
-    TypeOperations<Variable, Type> typeOperations,
-    Variable variable,
-    Type type,
-  ) {
-    VariableModel<Type> info = infoFor(variable);
-    if (info.writeCaptured) return this;
-    Type previousType = info.promotedType;
-    previousType ??= typeOperations.variableType(variable);
-
-    if (!typeOperations.isSubtypeOf(type, previousType) ||
-        typeOperations.isSameType(type, previousType)) {
-      return this;
-    }
-    return _updateVariableInfo(variable, info.withPromotedType(type));
-  }
-
-  /// Updates the state to indicate that the given [writtenVariables] are no
-  /// longer promoted; they are presumed to have their declared types.
-  ///
-  /// This is used at the top of loops to conservatively cancel the promotion of
-  /// variables that are modified within the loop, so that we correctly analyze
-  /// code like the following:
-  ///
-  ///     if (x is int) {
-  ///       x.isEven; // OK, promoted to int
-  ///       while (true) {
-  ///         x.isEven; // ERROR: promotion lost
-  ///         x = 'foo';
-  ///       }
-  ///     }
-  ///
-  /// Note that a more accurate analysis would be to iterate to a fixed point,
-  /// and only remove promotions if it can be shown that they aren't restored
-  /// later in the loop body.  If we switch to a fixed point analysis, we should
-  /// be able to remove this method.
-  FlowModel<Variable, Type> removePromotedAll(
-      Iterable<Variable> writtenVariables,
-      Iterable<Variable> capturedVariables) {
-    Map<Variable, VariableModel<Type>> newVariableInfo;
-    for (Variable variable in writtenVariables) {
-      VariableModel<Type> info = infoFor(variable);
-      if (info.promotedType != null) {
-        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
-            variableInfo))[variable] = info.withPromotedType(null);
-      }
-    }
-    for (Variable variable in capturedVariables) {
-      VariableModel<Type> info = variableInfo[variable];
-      if (info == null) {
-        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
-                variableInfo))[variable] =
-            new VariableModel<Type>(null, false, true);
-      } else if (!info.writeCaptured) {
-        (newVariableInfo ??= new Map<Variable, VariableModel<Type>>.from(
-            variableInfo))[variable] = info.writeCapture();
-      }
-    }
-    if (newVariableInfo == null) return this;
-    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
-  }
-
-  /// Updates the state to reflect a control path that is known to have
-  /// previously passed through some [other] state.
-  ///
-  /// Approximately, this method forms the union of the definite assignments and
-  /// promotions in `this` state and the [other] state.  More precisely:
-  ///
-  /// The control flow path is considered reachable if both this state and the
-  /// other state are reachable.  Variables are considered definitely assigned
-  /// if they were definitely assigned in either this state or the other state.
-  /// Variable type promotions are taken from this state, unless the promotion
-  /// in the other state is more specific, and the variable is "safe".  A
-  /// variable is considered safe if there is no chance that it was assigned
-  /// more recently than the "other" state.
-  ///
-  /// This is used after a `try/finally` statement to combine the promotions and
-  /// definite assignments that occurred in the `try` and `finally` blocks
-  /// (where `this` is the state from the `finally` block and `other` is the
-  /// state from the `try` block).  Variables that are assigned in the `finally`
-  /// block are considered "unsafe" because the assignment might have cancelled
-  /// the effect of any promotion that occurred inside the `try` block.
-  FlowModel<Variable, Type> restrict(
-      TypeOperations<Variable, Type> typeOperations,
-      FlowModel<Variable, Type> other,
-      Set<Variable> unsafe) {
-    bool newReachable = reachable && other.reachable;
-
-    Map<Variable, VariableModel<Type>> newVariableInfo =
-        <Variable, VariableModel<Type>>{};
-    bool variableInfoMatchesThis = true;
-    bool variableInfoMatchesOther = true;
-    for (MapEntry<Variable, VariableModel<Type>> entry
-        in variableInfo.entries) {
-      Variable variable = entry.key;
-      VariableModel<Type> thisModel = entry.value;
-      VariableModel<Type> otherModel = other.infoFor(variable);
-      VariableModel<Type> restricted = thisModel.restrict(
-          typeOperations, otherModel, unsafe.contains(variable));
-      if (!identical(restricted, _freshVariableInfo)) {
-        newVariableInfo[variable] = restricted;
-      }
-      if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
-      if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
-    }
-    for (MapEntry<Variable, VariableModel<Type>> entry
-        in other.variableInfo.entries) {
-      Variable variable = entry.key;
-      if (variableInfo.containsKey(variable)) continue;
-      VariableModel<Type> thisModel = _freshVariableInfo;
-      VariableModel<Type> otherModel = entry.value;
-      VariableModel<Type> restricted = thisModel.restrict(
-          typeOperations, otherModel, unsafe.contains(variable));
-      if (!identical(restricted, _freshVariableInfo)) {
-        newVariableInfo[variable] = restricted;
-      }
-      if (!identical(restricted, thisModel)) variableInfoMatchesThis = false;
-      if (!identical(restricted, otherModel)) variableInfoMatchesOther = false;
-    }
-    assert(variableInfoMatchesThis ==
-        _variableInfosEqual(newVariableInfo, variableInfo));
-    assert(variableInfoMatchesOther ==
-        _variableInfosEqual(newVariableInfo, other.variableInfo));
-    if (variableInfoMatchesThis) {
-      newVariableInfo = variableInfo;
-    } else if (variableInfoMatchesOther) {
-      newVariableInfo = other.variableInfo;
-    }
-
-    return _identicalOrNew(this, other, newReachable, newVariableInfo);
-  }
-
-  /// Updates the state to indicate whether the control flow path is
-  /// [reachable].
-  FlowModel<Variable, Type> setReachable(bool reachable) {
-    if (this.reachable == reachable) return this;
-
-    return new FlowModel<Variable, Type>._(reachable, variableInfo);
-  }
-
-  @override
-  String toString() => '($reachable, $variableInfo)';
-
-  /// 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.
-  ///
-  /// TODO(paulberry): allow for writes that preserve type promotions.
-  FlowModel<Variable, Type> write(Variable variable) {
-    VariableModel<Type> infoForVar = infoFor(variable);
-    VariableModel<Type> newInfoForVar = infoForVar.write();
-    if (identical(newInfoForVar, infoForVar)) return this;
-    return _updateVariableInfo(variable, newInfoForVar);
-  }
-
-  /// Returns a new [FlowModel] where the information for [variable] is replaced
-  /// with [model].
-  FlowModel<Variable, Type> _updateVariableInfo(
-      Variable variable, VariableModel<Type> model) {
-    Map<Variable, VariableModel<Type>> newVariableInfo =
-        new Map<Variable, VariableModel<Type>>.from(variableInfo);
-    newVariableInfo[variable] = model;
-    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
-  }
-
-  /// Forms a new state to reflect a control flow path that might have come from
-  /// either `this` or the [other] state.
-  ///
-  /// The control flow path is considered reachable if either of the input
-  /// states is reachable.  Variables are considered definitely assigned if they
-  /// were definitely assigned in both of the input states.  Variable promotions
-  /// 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>(
-    TypeOperations<Variable, Type> typeOperations,
-    FlowModel<Variable, Type> first,
-    FlowModel<Variable, Type> second,
-  ) {
-    if (first == null) return second;
-    if (second == null) return first;
-
-    if (first.reachable && !second.reachable) return first;
-    if (!first.reachable && second.reachable) return second;
-
-    bool newReachable = first.reachable || second.reachable;
-    Map<Variable, VariableModel<Type>> newVariableInfo =
-        FlowModel.joinVariableInfo(
-            typeOperations, first.variableInfo, second.variableInfo);
-
-    return FlowModel._identicalOrNew(
-        first, second, newReachable, newVariableInfo);
-  }
-
-  /// Joins two "variable info" maps.  See [join] for details.
-  @visibleForTesting
-  static Map<Variable, VariableModel<Type>> joinVariableInfo<Variable, Type>(
-    TypeOperations<Variable, Type> typeOperations,
-    Map<Variable, VariableModel<Type>> first,
-    Map<Variable, VariableModel<Type>> second,
-  ) {
-    if (identical(first, second)) return first;
-    if (first.isEmpty || second.isEmpty) return const {};
-
-    Map<Variable, VariableModel<Type>> result =
-        <Variable, VariableModel<Type>>{};
-    bool alwaysFirst = true;
-    bool alwaysSecond = true;
-    for (MapEntry<Variable, VariableModel<Type>> entry in first.entries) {
-      Variable variable = entry.key;
-      VariableModel<Type> secondModel = second[variable];
-      if (secondModel == null) {
-        alwaysFirst = false;
-      } else {
-        VariableModel<Type> joined =
-            VariableModel.join<Type>(typeOperations, entry.value, secondModel);
-        result[variable] = joined;
-        if (!identical(joined, entry.value)) alwaysFirst = false;
-        if (!identical(joined, secondModel)) alwaysSecond = false;
-      }
-    }
-
-    if (alwaysFirst) return first;
-    if (alwaysSecond && result.length == second.length) return second;
-    if (result.isEmpty) return const {};
-    return result;
-  }
-
-  /// 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,
-      bool newReachable,
-      Map<Variable, VariableModel<Type>> newVariableInfo) {
-    if (first.reachable == newReachable &&
-        identical(first.variableInfo, newVariableInfo)) {
-      return first;
-    }
-    if (second.reachable == newReachable &&
-        identical(second.variableInfo, newVariableInfo)) {
-      return second;
-    }
-
-    return new FlowModel<Variable, Type>._(newReachable, newVariableInfo);
-  }
-
-  /// Determines whether the given "variableInfo" maps are equivalent.
-  ///
-  /// The equivalence check is shallow; if two variables' models are not
-  /// identical, we return `false`.
-  static bool _variableInfosEqual<Variable, Type>(
-      Map<Variable, VariableModel<Type>> p1,
-      Map<Variable, VariableModel<Type>> p2) {
-    if (p1.length != p2.length) return false;
-    if (!p1.keys.toSet().containsAll(p2.keys)) return false;
-    for (MapEntry<Variable, VariableModel<Type>> entry in p1.entries) {
-      VariableModel<Type> p1Value = entry.value;
-      VariableModel<Type> p2Value = p2[entry.key];
-      if (!identical(p1Value, p2Value)) {
-        return false;
-      }
-    }
-    return true;
-  }
-}
-
-/// Operations on types, abstracted from concrete type interfaces.
-abstract class TypeOperations<Variable, Type> {
-  /// Returns `true` if [type1] and [type2] are the same type.
-  bool isSameType(Type type1, Type type2);
-
-  /// Return `true` if the [leftType] is a subtype of the [rightType].
-  bool isSubtypeOf(Type leftType, Type rightType);
-
-  /// Returns the non-null promoted version of [type].
-  ///
-  /// Note that some types don't have a non-nullable version (e.g.
-  /// `FutureOr<int?>`), so [type] may be returned even if it is nullable.
-  Type /*!*/ promoteToNonNull(Type type);
-
-  /// Return the static type of the given [variable].
-  Type variableType(Variable variable);
-}
-
-/// An instance of the [VariableModel] class represents the information gathered
-/// by flow analysis for a single variable at a single point in the control flow
-/// of the function or method being analyzed.
-///
-/// 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<Type> {
-  /// The type that the variable has been promoted to, or `null` if the variable
-  /// is not promoted.
-  final Type promotedType;
-
-  /// Indicates whether the variable has definitely been assigned.
-  final bool assigned;
-
-  /// Indicates whether the variable has been write captured.
-  final bool writeCaptured;
-
-  VariableModel(this.promotedType, this.assigned, this.writeCaptured) {
-    assert(!writeCaptured || promotedType == null,
-        "Write-captured variables can't be promoted");
-  }
-
-  /// Creates a [VariableModel] representing a variable that's never been seen
-  /// before.
-  VariableModel.fresh()
-      : promotedType = null,
-        assigned = false,
-        writeCaptured = false;
-
-  @override
-  bool operator ==(Object other) {
-    return other is VariableModel<Type> &&
-        this.promotedType == other.promotedType &&
-        this.assigned == other.assigned &&
-        this.writeCaptured == other.writeCaptured;
-  }
-
-  /// Returns an updated model reflect a control path that is known to have
-  /// previously passed through some [other] state.  See [FlowModel.restrict]
-  /// for details.
-  VariableModel<Type> restrict(TypeOperations<Object, Type> typeOperations,
-      VariableModel<Type> otherModel, bool unsafe) {
-    Type thisType = promotedType;
-    Type otherType = otherModel.promotedType;
-    bool newAssigned = assigned || otherModel.assigned;
-    bool newWriteCaptured = writeCaptured || otherModel.writeCaptured;
-    if (!unsafe) {
-      if (otherType != null &&
-          (thisType == null ||
-              typeOperations.isSubtypeOf(otherType, thisType))) {
-        return _identicalOrNew(
-            this, otherModel, otherType, newAssigned, newWriteCaptured);
-      }
-    }
-    return _identicalOrNew(
-        this, otherModel, thisType, newAssigned, newWriteCaptured);
-  }
-
-  @override
-  String toString() =>
-      'VariableModel($promotedType, $assigned, $writeCaptured)';
-
-  /// Returns a new [VariableModel] where the promoted type is replaced with
-  /// [promotedType].
-  VariableModel<Type> withPromotedType(Type promotedType) =>
-      new VariableModel<Type>(promotedType, assigned, writeCaptured);
-
-  /// Returns a new [VariableModel] reflecting the fact that the variable was
-  /// just written to.
-  VariableModel<Type> write() {
-    if (promotedType == null && assigned) return this;
-    return new VariableModel<Type>(null, true, writeCaptured);
-  }
-
-  /// Returns a new [VariableModel] reflecting the fact that the variable has
-  /// been write-captured.
-  VariableModel<Type> writeCapture() {
-    return new VariableModel<Type>(null, assigned, true);
-  }
-
-  /// Joins two variable models.  See [FlowModel.join] for details.
-  static VariableModel<Type> join<Type>(
-      TypeOperations<Object, Type> typeOperations,
-      VariableModel<Type> first,
-      VariableModel<Type> second) {
-    Type firstType = first.promotedType;
-    Type secondType = second.promotedType;
-    Type newPromotedType;
-    if (identical(firstType, secondType)) {
-      newPromotedType = firstType;
-    } else if (firstType == null || secondType == null) {
-      newPromotedType = null;
-    } else if (typeOperations.isSubtypeOf(firstType, secondType)) {
-      newPromotedType = secondType;
-    } else if (typeOperations.isSubtypeOf(secondType, firstType)) {
-      newPromotedType = firstType;
-    } else {
-      newPromotedType = null;
-    }
-    bool newAssigned = first.assigned && second.assigned;
-    bool newWriteCaptured = first.writeCaptured || second.writeCaptured;
-    return _identicalOrNew(
-        first, second, newPromotedType, newAssigned, newWriteCaptured);
-  }
-
-  /// 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<Type> _identicalOrNew<Type>(
-      VariableModel<Type> first,
-      VariableModel<Type> second,
-      Type newPromotedType,
-      bool newAssigned,
-      bool newWriteCaptured) {
-    if (identical(first.promotedType, newPromotedType) &&
-        first.assigned == newAssigned &&
-        first.writeCaptured == newWriteCaptured) {
-      return first;
-    } else if (identical(second.promotedType, newPromotedType) &&
-        second.assigned == newAssigned &&
-        second.writeCaptured == newWriteCaptured) {
-      return second;
-    } else {
-      return new VariableModel<Type>(
-          newPromotedType, newAssigned, newWriteCaptured);
-    }
-  }
-}
-
-/// [_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 {
-  /// Flow models associated with the condition being branched on.
-  final _ExpressionInfo<Variable, Type> _conditionInfo;
-
-  _BranchContext(this._conditionInfo);
-}
-
-/// [_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 {
-  /// Accumulated flow model for all `break` statements seen so far, or `null`
-  /// if no `break` statements have been seen yet.
-  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;
-}
-
-/// [_FlowContext] representing a conditional expression.
-class _ConditionalContext<Variable, Type>
-    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;
-
-  _ConditionalContext(_ExpressionInfo<Variable, Type> conditionInfo)
-      : super(conditionInfo);
-}
-
-/// A collection of flow models representing the possible outcomes of evaluating
-/// an expression that are relevant to flow analysis.
-class _ExpressionInfo<Variable, Type> {
-  /// The state after the expression evaluates, if we don't care what it
-  /// evaluates to.
-  final FlowModel<Variable, Type> _after;
-
-  /// The state after the expression evaluates, if it evaluates to `true`.
-  final FlowModel<Variable, Type> _ifTrue;
-
-  /// The state after the expression evaluates, if it evaluates to `false`.
-  final FlowModel<Variable, Type> _ifFalse;
-
-  _ExpressionInfo(this._after, this._ifTrue, this._ifFalse);
-}
-
-class _FlowAnalysisImpl<Statement, Expression, Variable, Type>
-    implements FlowAnalysis<Statement, Expression, Variable, Type> {
-  final List<Variable> _variablesWrittenAnywhere;
-
-  final List<Variable> _variablesCapturedAnywhere;
-
-  /// The [TypeOperations], used to access types, and check subtyping.
-  final TypeOperations<Variable, Type> typeOperations;
-
-  /// Stack of [_FlowContext] objects representing the statements and
-  /// expressions that are currently being visited.
-  final List<_FlowContext> _stack = [];
-
-  /// The mapping from [Statement]s that can act as targets for `break` and
-  /// `continue` statements (i.e. loops and switch statements) to the to their
-  /// context information.
-  final Map<Statement, _BranchTargetContext<Variable, Type>>
-      _statementToContext = {};
-
-  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;
-
-  /// If [_expressionWithInfo] is not `null`, the [_ExpressionInfo] object
-  /// corresponding to it.  Otherwise `null`.
-  _ExpressionInfo<Variable, Type> _expressionInfo;
-
-  int _functionNestingLevel = 0;
-
-  _FlowAnalysisImpl(this.typeOperations, this._variablesWrittenAnywhere,
-      this._variablesCapturedAnywhere) {
-    _current = new FlowModel<Variable, Type>(true);
-  }
-
-  @override
-  bool get isReachable => _current.reachable;
-
-  @override
-  void booleanLiteral(Expression expression, bool value) {
-    FlowModel<Variable, Type> unreachable = _current.setReachable(false);
-    _storeExpressionInfo(
-        expression,
-        value
-            ? new _ExpressionInfo(_current, _current, unreachable)
-            : new _ExpressionInfo(_current, unreachable, _current));
-  }
-
-  @override
-  void conditional_elseBegin(Expression thenExpression) {
-    _ConditionalContext<Variable, Type> context =
-        _stack.last as _ConditionalContext<Variable, Type>;
-    context._thenInfo = _expressionEnd(thenExpression);
-    _current = context._conditionInfo._ifFalse;
-  }
-
-  @override
-  void conditional_end(
-      Expression conditionalExpression, Expression elseExpression) {
-    _ConditionalContext<Variable, Type> context =
-        _stack.removeLast() as _ConditionalContext<Variable, Type>;
-    _ExpressionInfo<Variable, Type> thenInfo = context._thenInfo;
-    _ExpressionInfo<Variable, Type> elseInfo = _expressionEnd(elseExpression);
-    _storeExpressionInfo(
-        conditionalExpression,
-        new _ExpressionInfo(
-            _join(thenInfo._after, elseInfo._after),
-            _join(thenInfo._ifTrue, elseInfo._ifTrue),
-            _join(thenInfo._ifFalse, elseInfo._ifFalse)));
-  }
-
-  @override
-  void conditional_thenBegin(Expression condition) {
-    _ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
-    _stack.add(new _ConditionalContext(conditionInfo));
-    _current = conditionInfo._ifTrue;
-  }
-
-  @override
-  void doStatement_bodyBegin(Statement doStatement,
-      Iterable<Variable> loopAssigned, Iterable<Variable> loopCaptured) {
-    _BranchTargetContext<Variable, Type> context =
-        new _BranchTargetContext<Variable, Type>();
-    _stack.add(context);
-    _current = _current.removePromotedAll(loopAssigned, loopCaptured);
-    _statementToContext[doStatement] = context;
-  }
-
-  @override
-  void doStatement_conditionBegin() {
-    _BranchTargetContext<Variable, Type> context =
-        _stack.last as _BranchTargetContext<Variable, Type>;
-    _current = _join(_current, context._continueModel);
-  }
-
-  @override
-  void doStatement_end(Expression condition) {
-    _BranchTargetContext<Variable, Type> context =
-        _stack.removeLast() as _BranchTargetContext<Variable, Type>;
-    _current = _join(_expressionEnd(condition)._ifFalse, context._breakModel);
-  }
-
-  @override
-  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
-      {bool notEqual = false}) {
-    _BranchContext<Variable, Type> context =
-        _stack.removeLast() as _BranchContext<Variable, Type>;
-    _ExpressionInfo<Variable, Type> lhsInfo = context._conditionInfo;
-    _ExpressionInfo<Variable, Type> rhsInfo = _getExpressionInfo(rightOperand);
-    Variable variable;
-    if (lhsInfo is _NullInfo<Variable, Type> &&
-        rhsInfo is _VariableReadInfo<Variable, Type>) {
-      variable = rhsInfo._variable;
-    } else if (rhsInfo is _NullInfo<Variable, Type> &&
-        lhsInfo is _VariableReadInfo<Variable, Type>) {
-      variable = lhsInfo._variable;
-    } else {
-      return;
-    }
-    FlowModel<Variable, Type> ifNotNull =
-        _current.markNonNullable(typeOperations, variable);
-    _storeExpressionInfo(
-        wholeExpression,
-        notEqual
-            ? new _ExpressionInfo(_current, ifNotNull, _current)
-            : new _ExpressionInfo(_current, _current, ifNotNull));
-  }
-
-  @override
-  void equalityOp_rightBegin(Expression leftOperand) {
-    _stack.add(
-        new _BranchContext<Variable, Type>(_getExpressionInfo(leftOperand)));
-  }
-
-  @override
-  void finish() {
-    assert(_stack.isEmpty);
-  }
-
-  @override
-  void for_bodyBegin(Statement node, Expression condition) {
-    _ExpressionInfo<Variable, Type> conditionInfo = condition == null
-        ? new _ExpressionInfo(_current, _current, _current.setReachable(false))
-        : _expressionEnd(condition);
-    _WhileContext<Variable, Type> context =
-        new _WhileContext<Variable, Type>(conditionInfo);
-    _stack.add(context);
-    if (node != null) {
-      _statementToContext[node] = context;
-    }
-    _current = conditionInfo._ifTrue;
-  }
-
-  @override
-  void for_conditionBegin(
-      Set<Variable> loopAssigned, Set<Variable> loopCaptured) {
-    _current = _current.removePromotedAll(loopAssigned, loopCaptured);
-  }
-
-  @override
-  void for_end() {
-    _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> falseCondition = context._conditionInfo._ifFalse;
-
-    _current = _join(falseCondition, breakState);
-  }
-
-  @override
-  void for_updaterBegin() {
-    _WhileContext<Variable, Type> context =
-        _stack.last as _WhileContext<Variable, Type>;
-    _current = _join(_current, context._continueModel);
-  }
-
-  @override
-  void forEach_bodyBegin(Iterable<Variable> loopAssigned,
-      Iterable<Variable> loopCaptured, Variable loopVariable) {
-    _SimpleStatementContext<Variable, Type> context =
-        new _SimpleStatementContext<Variable, Type>(_current);
-    _stack.add(context);
-    _current = _current.removePromotedAll(loopAssigned, loopCaptured);
-    if (loopVariable != null) {
-      _current = _current.write(loopVariable);
-    }
-  }
-
-  @override
-  void forEach_end() {
-    _SimpleStatementContext<Variable, Type> context =
-        _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
-    _current = _join(_current, context._previous);
-  }
-
-  @override
-  void functionExpression_begin(Iterable<Variable> writeCaptured) {
-    ++_functionNestingLevel;
-    _current = _current.removePromotedAll(const [], writeCaptured);
-    _stack.add(new _SimpleContext(_current));
-    _current = _current.removePromotedAll(
-        _variablesWrittenAnywhere, _variablesCapturedAnywhere);
-  }
-
-  @override
-  void functionExpression_end() {
-    --_functionNestingLevel;
-    assert(_functionNestingLevel >= 0);
-    _SimpleContext<Variable, Type> context =
-        _stack.removeLast() as _SimpleContext<Variable, Type>;
-    _current = context._previous;
-  }
-
-  @override
-  void handleBreak(Statement target) {
-    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
-    if (context != null) {
-      context._breakModel = _join(context._breakModel, _current);
-    }
-    _current = _current.setReachable(false);
-  }
-
-  @override
-  void handleContinue(Statement target) {
-    _BranchTargetContext<Variable, Type> context = _statementToContext[target];
-    if (context != null) {
-      context._continueModel = _join(context._continueModel, _current);
-    }
-    _current = _current.setReachable(false);
-  }
-
-  @override
-  void handleExit() {
-    _current = _current.setReachable(false);
-  }
-
-  @override
-  void ifNullExpression_end() {
-    _SimpleContext<Variable, Type> context =
-        _stack.removeLast() as _SimpleContext<Variable, Type>;
-    _current = _join(_current, context._previous);
-  }
-
-  @override
-  void ifNullExpression_rightBegin() {
-    _stack.add(new _SimpleContext<Variable, Type>(_current));
-  }
-
-  @override
-  void ifStatement_elseBegin() {
-    _IfContext<Variable, Type> context =
-        _stack.last as _IfContext<Variable, Type>;
-    context._afterThen = _current;
-    _current = context._conditionInfo._ifFalse;
-  }
-
-  @override
-  void ifStatement_end(bool hasElse) {
-    _IfContext<Variable, Type> context =
-        _stack.removeLast() as _IfContext<Variable, Type>;
-    FlowModel<Variable, Type> afterThen;
-    FlowModel<Variable, Type> afterElse;
-    if (hasElse) {
-      afterThen = context._afterThen;
-      afterElse = _current;
-    } else {
-      afterThen = _current; // no `else`, so `then` is still current
-      afterElse = context._conditionInfo._ifFalse;
-    }
-    _current = _join(afterThen, afterElse);
-  }
-
-  @override
-  void ifStatement_thenBegin(Expression condition) {
-    _ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
-    _stack.add(new _IfContext(conditionInfo));
-    _current = conditionInfo._ifTrue;
-  }
-
-  @override
-  void initialize(Variable variable) {
-    _current = _current.write(variable);
-  }
-
-  @override
-  bool isAssigned(Variable variable) {
-    return _current.infoFor(variable).assigned;
-  }
-
-  @override
-  void isExpression_end(
-      Expression isExpression, Variable variable, bool isNot, Type type) {
-    FlowModel<Variable, Type> promoted =
-        _current.promote(typeOperations, variable, type);
-    _storeExpressionInfo(
-        isExpression,
-        isNot
-            ? new _ExpressionInfo(_current, _current, promoted)
-            : new _ExpressionInfo(_current, promoted, _current));
-  }
-
-  @override
-  void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
-      {@required bool isAnd}) {
-    _BranchContext<Variable, Type> context =
-        _stack.removeLast() as _BranchContext<Variable, Type>;
-    _ExpressionInfo<Variable, Type> rhsInfo = _expressionEnd(rightOperand);
-
-    FlowModel<Variable, Type> trueResult;
-    FlowModel<Variable, Type> falseResult;
-    if (isAnd) {
-      trueResult = rhsInfo._ifTrue;
-      falseResult = _join(context._conditionInfo._ifFalse, rhsInfo._ifFalse);
-    } else {
-      trueResult = _join(context._conditionInfo._ifTrue, rhsInfo._ifTrue);
-      falseResult = rhsInfo._ifFalse;
-    }
-    _storeExpressionInfo(
-        wholeExpression,
-        new _ExpressionInfo(
-            _join(trueResult, falseResult), trueResult, falseResult));
-  }
-
-  @override
-  void logicalBinaryOp_rightBegin(Expression leftOperand,
-      {@required bool isAnd}) {
-    _ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(leftOperand);
-    _stack.add(new _BranchContext<Variable, Type>(conditionInfo));
-    _current = isAnd ? conditionInfo._ifTrue : conditionInfo._ifFalse;
-  }
-
-  @override
-  void logicalNot_end(Expression notExpression, Expression operand) {
-    _ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(operand);
-    _storeExpressionInfo(
-        notExpression,
-        new _ExpressionInfo(conditionInfo._after, conditionInfo._ifFalse,
-            conditionInfo._ifTrue));
-  }
-
-  @override
-  void nonNullAssert_end(Expression operand) {
-    _ExpressionInfo<Variable, Type> operandInfo = _getExpressionInfo(operand);
-    if (operandInfo is _VariableReadInfo<Variable, Type>) {
-      _current =
-          _current.markNonNullable(typeOperations, operandInfo._variable);
-    }
-  }
-
-  @override
-  void nullLiteral(Expression expression) {
-    _storeExpressionInfo(expression, new _NullInfo(_current));
-  }
-
-  @override
-  void parenthesizedExpression(
-      Expression outerExpression, Expression innerExpression) {
-    if (identical(_expressionWithInfo, innerExpression)) {
-      _expressionWithInfo = outerExpression;
-    }
-  }
-
-  @override
-  Type promotedType(Variable variable) {
-    return _current.infoFor(variable).promotedType;
-  }
-
-  @override
-  void switchStatement_beginCase(bool hasLabel, Iterable<Variable> notPromoted,
-      Iterable<Variable> captured) {
-    _SimpleStatementContext<Variable, Type> context =
-        _stack.last as _SimpleStatementContext<Variable, Type>;
-    if (hasLabel) {
-      _current = context._previous.removePromotedAll(notPromoted, captured);
-    } else {
-      _current = context._previous;
-    }
-  }
-
-  @override
-  void switchStatement_end(bool hasDefault) {
-    _SimpleStatementContext<Variable, Type> context =
-        _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
-    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.
-    breakState = _join(breakState, _current);
-
-    // And, if there is an implicit fall-through default, join it to any breaks.
-    if (!hasDefault) breakState = _join(breakState, context._previous);
-
-    _current = breakState;
-  }
-
-  @override
-  void switchStatement_expressionEnd(Statement switchStatement) {
-    _SimpleStatementContext<Variable, Type> context =
-        new _SimpleStatementContext<Variable, Type>(_current);
-    _stack.add(context);
-    _statementToContext[switchStatement] = context;
-  }
-
-  @override
-  void tryCatchStatement_bodyBegin() {
-    _stack.add(new _TryContext<Variable, Type>(_current));
-  }
-
-  @override
-  void tryCatchStatement_bodyEnd(
-      Iterable<Variable> assignedInBody, Iterable<Variable> capturedInBody) {
-    _TryContext<Variable, Type> context =
-        _stack.last as _TryContext<Variable, Type>;
-    FlowModel<Variable, Type> beforeBody = context._previous;
-    FlowModel<Variable, Type> beforeCatch =
-        beforeBody.removePromotedAll(assignedInBody, capturedInBody);
-    context._beforeCatch = beforeCatch;
-    context._afterBodyAndCatches = _current;
-  }
-
-  @override
-  void tryCatchStatement_catchBegin() {
-    _TryContext<Variable, Type> context =
-        _stack.last as _TryContext<Variable, Type>;
-    _current = context._beforeCatch;
-  }
-
-  @override
-  void tryCatchStatement_catchEnd() {
-    _TryContext<Variable, Type> context =
-        _stack.last as _TryContext<Variable, Type>;
-    context._afterBodyAndCatches =
-        _join(context._afterBodyAndCatches, _current);
-  }
-
-  @override
-  void tryCatchStatement_end() {
-    _TryContext<Variable, Type> context =
-        _stack.removeLast() as _TryContext<Variable, Type>;
-    _current = context._afterBodyAndCatches;
-  }
-
-  @override
-  void tryFinallyStatement_bodyBegin() {
-    _stack.add(new _TryContext<Variable, Type>(_current));
-  }
-
-  @override
-  void tryFinallyStatement_end(Set<Variable> assignedInFinally) {
-    _TryContext<Variable, Type> context =
-        _stack.removeLast() as _TryContext<Variable, Type>;
-    _current = _current.restrict(
-        typeOperations, context._afterBodyAndCatches, assignedInFinally);
-  }
-
-  @override
-  void tryFinallyStatement_finallyBegin(
-      Iterable<Variable> assignedInBody, Iterable<Variable> capturedInBody) {
-    _TryContext<Variable, Type> context =
-        _stack.last as _TryContext<Variable, Type>;
-    context._afterBodyAndCatches = _current;
-    _current = _join(_current,
-        context._previous.removePromotedAll(assignedInBody, capturedInBody));
-  }
-
-  @override
-  Type variableRead(Expression expression, Variable variable) {
-    _storeExpressionInfo(expression, new _VariableReadInfo(_current, variable));
-    return _current.infoFor(variable).promotedType;
-  }
-
-  @override
-  void whileStatement_bodyBegin(
-      Statement whileStatement, Expression condition) {
-    _ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
-    _WhileContext<Variable, Type> context =
-        new _WhileContext<Variable, Type>(conditionInfo);
-    _stack.add(context);
-    _statementToContext[whileStatement] = context;
-    _current = conditionInfo._ifTrue;
-  }
-
-  @override
-  void whileStatement_conditionBegin(
-      Iterable<Variable> loopAssigned, Iterable<Variable> loopCaptured) {
-    _current = _current.removePromotedAll(loopAssigned, loopCaptured);
-  }
-
-  @override
-  void whileStatement_end() {
-    _WhileContext<Variable, Type> context =
-        _stack.removeLast() as _WhileContext<Variable, Type>;
-    _current = _join(context._conditionInfo._ifFalse, context._breakModel);
-  }
-
-  @override
-  void write(Variable variable) {
-    assert(
-        _variablesWrittenAnywhere.contains(variable),
-        "Variable is written to, but was not included in "
-        "_variablesWrittenAnywhere: $variable");
-    _current = _current.write(variable);
-  }
-
-  /// 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 a fresh
-  /// [_ExpressionInfo] is created recording the current flow analysis state.
-  _ExpressionInfo<Variable, Type> _expressionEnd(Expression expression) =>
-      _getExpressionInfo(expression) ??
-      new _ExpressionInfo(_current, _current, _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) {
-    if (identical(expression, _expressionWithInfo)) {
-      _ExpressionInfo<Variable, Type> expressionInfo = _expressionInfo;
-      _expressionInfo = null;
-      return expressionInfo;
-    } else {
-      return null;
-    }
-  }
-
-  FlowModel<Variable, Type> _join(
-          FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
-      FlowModel.join(typeOperations, first, second);
-
-  /// Associates [expression], which should be the most recently visited
-  /// expression, with the given [expressionInfo] object, and updates the
-  /// current flow model state to correspond to it.
-  void _storeExpressionInfo(
-      Expression expression, _ExpressionInfo<Variable, Type> expressionInfo) {
-    _expressionWithInfo = expression;
-    _expressionInfo = expressionInfo;
-    _current = expressionInfo._after;
-  }
-}
-
-/// Base class for objects representing constructs in the Dart programming
-/// language for which flow analysis information needs to be tracked.
-class _FlowContext {}
-
-/// [_FlowContext] representing an `if` statement.
-class _IfContext<Variable, Type> 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;
-
-  _IfContext(_ExpressionInfo<Variable, Type> conditionInfo)
-      : super(conditionInfo);
-}
-
-/// [_ExpressionInfo] representing a `null` literal.
-class _NullInfo<Variable, Type> implements _ExpressionInfo<Variable, Type> {
-  @override
-  final FlowModel<Variable, Type> _after;
-
-  _NullInfo(this._after);
-
-  @override
-  FlowModel<Variable, Type> get _ifFalse => _after;
-
-  @override
-  FlowModel<Variable, Type> get _ifTrue => _after;
-}
-
-/// [_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.
-class _SimpleContext<Variable, Type> 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"
-  /// expression, this is the state after execution of the expression before the
-  /// `??`.
-  final FlowModel<Variable, Type> _previous;
-
-  _SimpleContext(this._previous);
-}
-
-/// [_FlowContext] representing a language construct that can be targeted by
-/// `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>
-    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
-  /// after evaluation of the switch expression.
-  final FlowModel<Variable, Type> _previous;
-
-  _SimpleStatementContext(this._previous);
-}
-
-/// [_FlowContext] representing a try statement.
-class _TryContext<Variable, Type> 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;
-
-  /// 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;
-
-  _TryContext(FlowModel<Variable, Type> previous) : super(previous);
-}
-
-/// [_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;
-
-  /// 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;
-}
-
-/// [_FlowContext] representing a `while` loop (or a C-style `for` loop, which
-/// is functionally similar).
-class _WhileContext<Variable, Type>
-    extends _BranchTargetContext<Variable, Type> {
-  /// Flow models associated with the loop condition.
-  final _ExpressionInfo<Variable, Type> _conditionInfo;
-
-  _WhileContext(this._conditionInfo);
-}
diff --git a/pkg/front_end/lib/src/fasta/identifiers.dart b/pkg/front_end/lib/src/fasta/identifiers.dart
index bc18ef4..644cd6a 100644
--- a/pkg/front_end/lib/src/fasta/identifiers.dart
+++ b/pkg/front_end/lib/src/fasta/identifiers.dart
@@ -4,12 +4,12 @@
 
 library fasta.qualified_name;
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
 import 'package:kernel/ast.dart' show Expression;
 
 import 'problems.dart' show unhandled, unsupported;
 
-import 'scanner.dart' show Token;
-
 class Identifier {
   final String name;
   final int charOffset;
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 7fa63c8..fbd01f9 100644
--- a/pkg/front_end/lib/src/fasta/ignored_parser_errors.dart
+++ b/pkg/front_end/lib/src/fasta/ignored_parser_errors.dart
@@ -4,12 +4,12 @@
 
 library fasta.ignored_parser_errors;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show optional;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
 import 'fasta_codes.dart' show Code, codeNonPartOfDirectiveInPart;
 
-import 'parser.dart' show optional;
-
-import 'scanner.dart' show Token;
-
 bool isIgnoredParserError(Code<Object> code, Token token) {
   if (code == codeNonPartOfDirectiveInPart) {
     // Ignored. This error is handled in the outline phase (part resolution).
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 891567a0..a184705 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -328,7 +328,7 @@
             if (builder.isBuiltAndMarked) {
               // Clear cached calculations in classes which upon calculation can
               // mark things as needed.
-              for (Builder builder in builder.scope.local.values) {
+              for (Builder builder in builder.scope.localMembers) {
                 if (builder is DillClassBuilder) {
                   builder.supertype = null;
                   builder.interfaces = null;
@@ -635,7 +635,14 @@
   /// Internal method.
   Uri getPartFileUri(
       Uri parentFileUri, LibraryPart part, UriTranslator uriTranslator) {
-    Uri fileUri = parentFileUri.resolve(part.partUri);
+    Uri fileUri;
+    try {
+      fileUri = parentFileUri.resolve(part.partUri);
+    } on FormatException {
+      return new Uri(
+          scheme: SourceLibraryBuilder.MALFORMED_URI_SCHEME,
+          query: Uri.encodeQueryComponent(part.partUri));
+    }
     if (fileUri.scheme == "package") {
       // Part was specified via package URI and the resolve above thus
       // did not go as expected. Translate the package URI to get the
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 b99e4e9..a815e0d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -6,6 +6,27 @@
 
 import 'dart:core' hide MapEntry;
 
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show
+        Assert,
+        BlockKind,
+        FormalParameterKind,
+        IdentifierContext,
+        MemberKind,
+        Parser,
+        lengthForToken,
+        lengthOfSpan,
+        optional;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
+    show isBinaryOperator, isMinusOperator, isUserDefinableOperator;
+
 import 'package:kernel/ast.dart';
 import 'package:kernel/type_environment.dart';
 
@@ -31,6 +52,7 @@
 import '../builder/type_declaration_builder.dart';
 import '../builder/type_variable_builder.dart';
 import '../builder/unresolved_type.dart';
+import '../builder/variable_builder.dart';
 import '../builder/void_type_builder.dart';
 
 import '../constant_context.dart' show ConstantContext;
@@ -56,18 +78,6 @@
 
 import '../names.dart' show callName, emptyName, minusName, plusName;
 
-import '../parser.dart'
-    show
-        Assert,
-        Parser,
-        FormalParameterKind,
-        IdentifierContext,
-        MemberKind,
-        lengthForToken,
-        lengthOfSpan,
-        offsetForToken,
-        optional;
-
 import '../problems.dart'
     show internalProblem, unexpected, unhandled, unsupported;
 
@@ -80,15 +90,8 @@
         unescapeLastStringPart,
         unescapeString;
 
-import '../scanner.dart' show Token;
-
-import '../scanner/token.dart'
-    show isBinaryOperator, isMinusOperator, isUserDefinableOperator;
-
 import '../scope.dart';
 
-import '../severity.dart' show Severity;
-
 import '../source/scope_listener.dart'
     show
         FixedNullableList,
@@ -100,6 +103,8 @@
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
+import '../source/stack_listener.dart' show offsetForToken;
+
 import '../source/value_kinds.dart';
 
 import '../type_inference/type_inferrer.dart' show TypeInferrer;
@@ -107,12 +112,7 @@
 import '../type_inference/type_promotion.dart'
     show TypePromoter, TypePromotionFact, TypePromotionScope;
 
-import 'collections.dart'
-    show
-        SpreadElement,
-        SpreadMapEntry,
-        convertToMapEntry,
-        isConvertibleToMapEntry;
+import 'collections.dart';
 
 import 'constness.dart' show Constness;
 
@@ -197,7 +197,6 @@
 
   final TypeInferrer typeInferrer;
 
-  @override
   final TypePromoter typePromoter;
 
   /// Only used when [member] is a constructor. It tracks if an implicit super
@@ -241,6 +240,18 @@
   /// This is used to determine whether instance properties are available.
   bool inFieldInitializer = false;
 
+  /// `true` if this access is directly in a field initializer of a late field.
+  ///
+  /// For instance in `<init>` in
+  ///
+  ///    late var foo = <init>;
+  ///    class Class {
+  ///      late var bar = <init>;
+  ///      Class() : bar = 42;
+  ///    }
+  ///
+  bool inLateFieldInitializer = false;
+
   bool inCatchClause = false;
 
   bool inCatchBlock = false;
@@ -318,7 +329,13 @@
         needsImplicitSuperInitializer = declarationBuilder is ClassBuilder &&
             coreTypes?.objectClass != declarationBuilder.cls,
         typePromoter = typeInferrer?.typePromoter,
-        super(enclosingScope);
+        super(enclosingScope) {
+    formalParameterScope?.forEach((String name, Builder builder) {
+      if (builder is VariableBuilder) {
+        typeInferrer?.assignedVariables?.declare(builder.variable);
+      }
+    });
+  }
 
   BodyBuilder.withParents(FieldBuilder field, SourceLibraryBuilder part,
       DeclarationBuilder declarationBuilder, TypeInferrer typeInferrer)
@@ -364,7 +381,7 @@
             uri: fileUri,
             typeInferrer: library.loader.typeInferenceEngine
                 ?.createLocalTypeInferrer(
-                    fileUri, declarationBuilder?.thisType, library));
+                    fileUri, declarationBuilder?.thisType, library, null));
 
   bool get inConstructor {
     return functionNestingLevel == 0 && member is ConstructorBuilder;
@@ -379,6 +396,12 @@
   DartType get implicitTypeArgument => const ImplicitTypeArgument();
 
   @override
+  void registerVariableAssignment(VariableDeclaration variable) {
+    typePromoter?.mutateVariable(variable, functionNestingLevel);
+    typeInferrer?.assignedVariables?.write(variable);
+  }
+
+  @override
   void push(Object node) {
     if (node is DartType) {
       unhandled("DartType", "push", -1, uri);
@@ -454,10 +477,9 @@
     Scope outerSwitchScope = pop();
     if (switchScope.unclaimedForwardDeclarations != null) {
       switchScope.unclaimedForwardDeclarations
-          .forEach((String name, Builder declaration) {
+          .forEach((String name, JumpTarget declaration) {
         if (outerSwitchScope == null) {
-          JumpTarget target = declaration;
-          for (Statement statement in target.users) {
+          for (Statement statement in declaration.users) {
             statement.parent.replaceChild(
                 statement,
                 wrapInProblemStatement(statement,
@@ -492,7 +514,7 @@
 
   void declareVariable(VariableDeclaration variable, Scope scope) {
     String name = variable.name;
-    Builder existing = scope.local[name];
+    Builder existing = scope.lookupLocalMember(name, setter: false);
     if (existing != null) {
       // This reports an error for duplicated declarations in the same scope:
       // `{ var x; var x; }`
@@ -506,7 +528,7 @@
     }
     LocatedMessage context = scope.declare(
         variable.name,
-        new VariableBuilder(
+        new VariableBuilderImpl(
             variable, member ?? classBuilder ?? libraryBuilder, uri),
         uri);
     if (context != null) {
@@ -526,9 +548,9 @@
     return new JumpTarget(kind, functionNestingLevel, member, charOffset);
   }
 
-  void inferAnnotations(List<Expression> annotations) {
+  void inferAnnotations(TreeNode parent, List<Expression> annotations) {
     if (annotations != null) {
-      typeInferrer?.inferMetadata(this, annotations);
+      typeInferrer?.inferMetadata(this, parent, annotations);
       libraryBuilder.loader.transformListPostInference(
           annotations, transformSetLiterals, transformCollections);
     }
@@ -575,7 +597,12 @@
 
       ConstantContext savedConstantContext = pop();
       if (expression is! StaticAccessGenerator &&
-          expression is! VariableUseGenerator) {
+          expression is! VariableUseGenerator &&
+          // TODO(johnniwinther): Stop using the type of the generator here.
+          // Ask a property instead.
+          (expression is! ReadOnlyAccessGenerator ||
+              expression is TypeUseGenerator ||
+              expression is ParenthesizedExpressionGenerator)) {
         push(wrapInProblem(
             toValue(expression), fasta.messageExpressionNotMetadata, noLength));
       } else {
@@ -606,7 +633,7 @@
       Token beginToken,
       Token endToken) {
     debugEvent("TopLevelFields");
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(lateToken);
     }
     push(count);
@@ -616,7 +643,7 @@
   void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
       Token varFinalOrConst, int count, Token beginToken, Token endToken) {
     debugEvent("Fields");
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(lateToken);
     }
     push(count);
@@ -655,8 +682,7 @@
           // outline, like constant field initializers) so we do not need to
           // perform type inference or transformations.
         } else {
-          fieldBuilder.initializer = initializer;
-          typeInferrer?.inferFieldInitializer(
+          fieldBuilder.initializer = typeInferrer?.inferFieldInitializer(
               this, fieldBuilder.builtType, initializer);
           libraryBuilder.loader.transformPostInference(
               fieldBuilder.field, transformSetLiterals, transformCollections);
@@ -810,6 +836,7 @@
       FormalParameters formals, AsyncMarker asyncModifier, Statement body) {
     debugEvent("finishFunction");
     typePromoter?.finished();
+    typeInferrer?.assignedVariables?.finish();
 
     FunctionBuilder builder = member;
     if (formals?.parameters != null) {
@@ -824,9 +851,9 @@
                 noLocation);
           }
           VariableDeclaration originParameter = builder.getFormalParameter(i);
-          originParameter.initializer = initializer..parent = originParameter;
-          typeInferrer?.inferParameterInitializer(
+          initializer = typeInferrer?.inferParameterInitializer(
               this, initializer, originParameter.type);
+          originParameter.initializer = initializer..parent = originParameter;
           libraryBuilder.loader.transformPostInference(
               originParameter, transformSetLiterals, transformCollections);
 
@@ -1115,14 +1142,15 @@
 
     if (variablesWithMetadata != null) {
       for (int i = 0; i < variablesWithMetadata.length; i++) {
-        inferAnnotations(variablesWithMetadata[i].annotations);
+        inferAnnotations(
+            variablesWithMetadata[i], variablesWithMetadata[i].annotations);
       }
     }
     if (multiVariablesWithMetadata != null) {
       for (int i = 0; i < multiVariablesWithMetadata.length; i++) {
         List<VariableDeclaration> variables = multiVariablesWithMetadata[i];
         List<Expression> annotations = variables.first.annotations;
-        inferAnnotations(annotations);
+        inferAnnotations(variables.first, annotations);
         for (int i = 1; i < variables.length; i++) {
           cloner ??= new CloneVisitor();
           VariableDeclaration variable = variables[i];
@@ -1137,7 +1165,7 @@
   @override
   List<Expression> finishMetadata(TreeNode parent) {
     List<Expression> expressions = pop();
-    inferAnnotations(expressions);
+    inferAnnotations(parent, expressions);
 
     // The invocation of [resolveRedirectingFactoryTargets] below may change the
     // root nodes of the annotation expressions.  We need to have a parent of
@@ -1447,13 +1475,14 @@
     Expression expression = popForValue();
     if (expression is Cascade) {
       push(expression);
-      push(new VariableUseGenerator(this, token, expression.variable));
-      expression.extend();
+      push(_createReadOnlyVariableAccess(
+          expression.variable, token, expression.fileOffset, null));
     } else {
       VariableDeclaration variable =
           forest.createVariableDeclarationForValue(expression);
       push(new Cascade(variable)..fileOffset = expression.fileOffset);
-      push(new VariableUseGenerator(this, token, variable));
+      push(_createReadOnlyVariableAccess(
+          variable, token, expression.fileOffset, null));
     }
   }
 
@@ -1462,7 +1491,7 @@
     debugEvent("endCascade");
     Expression expression = popForEffect();
     Cascade cascadeReceiver = pop();
-    cascadeReceiver.finalize(expression);
+    cascadeReceiver.addCascadeExpression(expression);
     push(cascadeReceiver);
   }
 
@@ -1835,7 +1864,7 @@
     }
     if (declaration != null &&
         declaration.isDeclarationInstanceMember &&
-        inFieldInitializer &&
+        (inFieldInitializer && !inLateFieldInitializer) &&
         !inInitializer) {
       // We cannot access a class instance member in an initializer of a
       // field.
@@ -1864,18 +1893,11 @@
         if (extensionThis != null) {
           // If we are in an extension instance member we interpret this as an
           // implicit access on the 'this' parameter.
-          return PropertyAccessGenerator.make(
-              this,
-              token,
-              createVariableGet(extensionThis, charOffset),
-              n,
-              null,
-              null,
-              false);
+          return PropertyAccessGenerator.make(this, token,
+              createVariableGet(extensionThis, charOffset), n, false);
         } else {
           // This is an implicit access on 'this'.
-          return new ThisPropertyAccessGenerator(this, token, n,
-              lookupInstanceMember(n), lookupInstanceMember(n, isSetter: true));
+          return new ThisPropertyAccessGenerator(this, token, n);
         }
       } else if (ignoreMainInGetMainClosure &&
           name == "main" &&
@@ -1887,21 +1909,18 @@
     } else if (declaration.isTypeDeclaration) {
       return new TypeUseGenerator(this, token, declaration, name);
     } else if (declaration.isLocal) {
+      VariableBuilder variableBuilder = declaration;
       if (constantContext != ConstantContext.none &&
-          !declaration.isConst &&
+          !variableBuilder.isConst &&
           !member.isConstructor) {
         return new IncompleteErrorGenerator(
             this, token, fasta.messageNotAConstantExpression);
       }
-      // An initializing formal parameter might be final without its
-      // VariableDeclaration being final. See
-      // [ProcedureBuilder.computeFormalParameterInitializerScope]. If that
-      // wasn't the case, we could always use [VariableUseGenerator].
-      if (declaration.isFinal) {
-        return _createReadOnlyVariableAccess(
-            declaration.target, token, charOffset, name);
+      VariableDeclaration variable = variableBuilder.variable;
+      if (!variableBuilder.isAssignable) {
+        return _createReadOnlyVariableAccess(variable, token, charOffset, name);
       } else {
-        return new VariableUseGenerator(this, token, declaration.target);
+        return new VariableUseGenerator(this, token, variable);
       }
     } else if (declaration.isClassInstanceMember) {
       if (constantContext != ConstantContext.none &&
@@ -1915,31 +1934,25 @@
             fasta.messageNotAConstantExpression, charOffset, token.length);
       }
       Name n = new Name(name, libraryBuilder.nameOrigin);
-      Member getter;
-      Member setter;
-      if (declaration is AccessErrorBuilder) {
-        setter = declaration.parent.target;
-        getter = lookupInstanceMember(n);
-      } else {
-        getter = declaration.target;
-        setter = lookupInstanceMember(n, isSetter: true);
-      }
-      return new ThisPropertyAccessGenerator(this, token, n, getter, setter);
+      return new ThisPropertyAccessGenerator(this, token, n);
     } else if (declaration.isExtensionInstanceMember) {
       ExtensionBuilder extensionBuilder = declarationBuilder;
-      Builder setter =
+      MemberBuilder setterBuilder =
           _getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
       // TODO(johnniwinther): Check for constantContext like below?
       if (declaration.isField) {
         declaration = null;
       }
-      if (setter != null && (setter.isField || setter.isStatic)) {
-        setter = null;
+      if (setterBuilder != null &&
+          (setterBuilder.isField || setterBuilder.isStatic)) {
+        setterBuilder = null;
       }
-      if (declaration == null && setter == null) {
+      if (declaration == null && setterBuilder == null) {
         return new UnresolvedNameGenerator(
             this, token, new Name(name, libraryBuilder.nameOrigin));
       }
+      MemberBuilder getterBuilder =
+          declaration is MemberBuilder ? declaration : null;
       return new ExtensionInstanceAccessGenerator.fromBuilder(
           this,
           token,
@@ -1947,12 +1960,13 @@
           name,
           extensionThis,
           extensionTypeParameters,
-          declaration,
-          setter);
+          getterBuilder,
+          setterBuilder);
     } else if (declaration.isRegularMethod) {
       assert(declaration.isStatic || declaration.isTopLevel);
+      MemberBuilder memberBuilder = declaration;
       return new StaticAccessGenerator(
-          this, token, name, declaration.target, null);
+          this, token, name, memberBuilder.member, null);
     } else if (declaration is PrefixBuilder) {
       assert(prefix == null);
       return new PrefixUseGenerator(this, token, declaration);
@@ -1961,10 +1975,13 @@
     } else if (declaration.hasProblem && declaration is! AccessErrorBuilder) {
       return declaration;
     } else {
-      Builder setter =
+      MemberBuilder setterBuilder =
           _getCorrespondingSetterBuilder(scope, declaration, name, charOffset);
+      MemberBuilder getterBuilder =
+          declaration is MemberBuilder ? declaration : null;
+      assert(getterBuilder != null || setterBuilder != null);
       StaticAccessGenerator generator = new StaticAccessGenerator.fromBuilder(
-          this, name, declaration, token, setter);
+          this, name, token, getterBuilder, setterBuilder);
       if (constantContext != ConstantContext.none) {
         Member readTarget = generator.readTarget;
         if (!(readTarget is Field && readTarget.isConst ||
@@ -1980,7 +1997,7 @@
 
   /// Returns the setter builder corresponding to [declaration] using the
   /// [name] and [charOffset] for the lookup into [scope] if necessary.
-  Builder _getCorrespondingSetterBuilder(
+  MemberBuilder _getCorrespondingSetterBuilder(
       Scope scope, Builder declaration, String name, int charOffset) {
     Builder setter;
     if (declaration.isSetter) {
@@ -1988,13 +2005,14 @@
     } else if (declaration.isGetter) {
       setter = scope.lookupSetter(name, charOffset, uri);
     } else if (declaration.isField) {
-      if (declaration.isFinal || declaration.isConst) {
+      MemberBuilder fieldBuilder = declaration;
+      if (!fieldBuilder.isAssignable) {
         setter = scope.lookupSetter(name, charOffset, uri);
       } else {
         setter = declaration;
       }
     }
-    return setter;
+    return setter is MemberBuilder ? setter : null;
   }
 
   @override
@@ -2189,6 +2207,7 @@
     debugEvent("NoVariableInitializer");
     bool isConst = (currentLocalVariableModifiers & constMask) != 0;
     bool isFinal = (currentLocalVariableModifiers & finalMask) != 0;
+    bool isLate = (currentLocalVariableModifiers & lateMask) != 0;
     Expression initializer;
     if (!optional("in", token)) {
       // A for-in loop-variable can't have an initializer. So let's remain
@@ -2200,7 +2219,7 @@
                 .withArguments(token.lexeme),
             token.charOffset,
             token.length);
-      } else if (isFinal) {
+      } else if (isFinal && !isLate) {
         initializer = buildProblem(
             fasta.templateFinalFieldWithoutInitializer
                 .withArguments(token.lexeme),
@@ -2233,6 +2252,7 @@
         isLate: isLate)
       ..fileOffset = identifier.charOffset
       ..fileEqualsOffset = offsetForToken(equalsToken);
+    typeInferrer?.assignedVariables?.declare(variable);
     libraryBuilder.checkBoundsInVariableDeclaration(
         variable, typeEnvironment, uri);
     push(variable);
@@ -2241,12 +2261,19 @@
   @override
   void beginFieldInitializer(Token token) {
     inFieldInitializer = true;
+    if (member is FieldBuilder) {
+      FieldBuilder fieldBuilder = member;
+      inLateFieldInitializer = fieldBuilder.isLate;
+    } else {
+      inLateFieldInitializer = false;
+    }
   }
 
   @override
   void endFieldInitializer(Token assignmentOperator, Token token) {
     debugEvent("FieldInitializer");
     inFieldInitializer = false;
+    inLateFieldInitializer = false;
     assert(assignmentOperator.stringValue == "=");
     push(popForValue());
   }
@@ -2281,7 +2308,7 @@
   void beginVariablesDeclaration(
       Token token, Token lateToken, Token varFinalOrConst) {
     debugEvent("beginVariablesDeclaration");
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(lateToken);
     }
     UnresolvedType type = pop();
@@ -2342,11 +2369,29 @@
   }
 
   @override
-  void endBlock(int count, Token openBrace, Token closeBrace) {
+  void beginBlock(Token token, BlockKind blockKind) {
+    if (blockKind == BlockKind.tryStatement) {
+      // This is matched by the call to [endNode] in [endBlock].
+      typeInferrer?.assignedVariables?.beginNode();
+    } else if (blockKind == BlockKind.finallyClause) {
+      // This is matched by the call to [endNode] in [endTryStatement].
+      typeInferrer?.assignedVariables?.beginNode();
+    }
+    super.beginBlock(token, blockKind);
+  }
+
+  @override
+  void endBlock(
+      int count, Token openBrace, Token closeBrace, BlockKind blockKind) {
     debugEvent("Block");
     Statement block = popBlock(count, openBrace, closeBrace);
     exitLocalScope();
     push(block);
+    if (blockKind == BlockKind.tryStatement) {
+      // This is matched by the calls to [deferNode] and [endNode] in
+      // [endTryStatement].
+      typeInferrer?.assignedVariables?.endNode(block);
+    }
   }
 
   void handleInvalidTopLevelBlock(Token token) {
@@ -2425,16 +2470,29 @@
   void handleForInitializerEmptyStatement(Token token) {
     debugEvent("ForInitializerEmptyStatement");
     push(NullValue.Expression);
+    // This is matched by the call to [deferNode] in [endForStatement] or
+    // [endForControlFlow].
+    typeInferrer?.assignedVariables?.beginNode();
   }
 
   @override
-  void handleForInitializerExpressionStatement(Token token) {
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
     debugEvent("ForInitializerExpressionStatement");
+    if (!forIn) {
+      // This is matched by the call to [deferNode] in [endForStatement] or
+      // [endForControlFlow].
+      typeInferrer?.assignedVariables?.beginNode();
+    }
   }
 
   @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
     debugEvent("ForInitializerLocalVariableDeclaration");
+    if (!forIn) {
+      // This is matched by the call to [deferNode] in [endForStatement] or
+      // [endForControlFlow].
+      typeInferrer?.assignedVariables?.beginNode();
+    }
   }
 
   @override
@@ -2456,10 +2514,12 @@
     Token forToken = pop();
     List<Expression> updates = popListForEffect(updateExpressionCount);
     Statement conditionStatement = popStatement(); // condition
-    Object variableOrExpression = pop();
-    exitLocalScope();
 
     if (constantContext != ConstantContext.none) {
+      pop(); // Pop variable or expression.
+      exitLocalScope();
+      typeInferrer?.assignedVariables?.discardNode();
+
       handleRecoverableError(
           fasta.templateCantUseControlFlowOrSpreadAsConstant
               .withArguments(forToken),
@@ -2469,6 +2529,16 @@
       return;
     }
 
+    // This is matched by the call to [beginNode] in
+    // [handleForInitializerEmptyStatement],
+    // [handleForInitializerExpressionStatement], and
+    // [handleForInitializerLocalVariableDeclaration].
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
+        typeInferrer?.assignedVariables?.deferNode();
+
+    Object variableOrExpression = pop();
+    exitLocalScope();
+
     transformCollections = true;
     List<VariableDeclaration> variables =
         buildVariableDeclarations(variableOrExpression);
@@ -2479,11 +2549,17 @@
       assert(conditionStatement is EmptyStatement);
     }
     if (entry is MapEntry) {
-      push(forest.createForMapEntry(
-          offsetForToken(forToken), variables, condition, updates, entry));
+      ForMapEntry result = forest.createForMapEntry(
+          offsetForToken(forToken), variables, condition, updates, entry);
+      typeInferrer?.assignedVariables
+          ?.storeInfo(result, assignedVariablesNodeInfo);
+      push(result);
     } else {
-      push(forest.createForElement(offsetForToken(forToken), variables,
-          condition, updates, toValue(entry)));
+      ForElement result = forest.createForElement(offsetForToken(forToken),
+          variables, condition, updates, toValue(entry));
+      typeInferrer?.assignedVariables
+          ?.storeInfo(result, assignedVariablesNodeInfo);
+      push(result);
     }
   }
 
@@ -2520,6 +2596,13 @@
 
     List<Expression> updates = popListForEffect(updateExpressionCount);
     Statement conditionStatement = popStatement();
+    // This is matched by the call to [beginNode] in
+    // [handleForInitializerEmptyStatement],
+    // [handleForInitializerExpressionStatement], and
+    // [handleForInitializerLocalVariableDeclaration].
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
+        typeInferrer?.assignedVariables?.deferNode();
+
     Object variableOrExpression = pop();
     List<VariableDeclaration> variables =
         buildVariableDeclarations(variableOrExpression);
@@ -2536,8 +2619,10 @@
     } else {
       assert(conditionStatement is EmptyStatement);
     }
-    Statement result = forest.createForStatement(offsetForToken(forKeyword),
-        variables, condition, conditionStatement, updates, body);
+    Statement result = forest.createForStatement(
+        offsetForToken(forKeyword), variables, condition, updates, body);
+    typeInferrer?.assignedVariables
+        ?.storeInfo(result, assignedVariablesNodeInfo);
     if (breakTarget.hasUsers) {
       result = forest.createLabeledStatement(result);
       breakTarget.resolveBreaks(forest, result);
@@ -2723,7 +2808,8 @@
         if (setOrMapEntries[i] is MapEntry) {
           mapEntries[i] = setOrMapEntries[i];
         } else {
-          mapEntries[i] = convertToMapEntry(setOrMapEntries[i], this);
+          mapEntries[i] = convertToMapEntry(setOrMapEntries[i], this,
+              typeInferrer?.assignedVariables?.reassignInfo);
         }
       }
       buildLiteralMap(typeArguments, constKeyword, leftBrace, mapEntries);
@@ -2835,7 +2921,7 @@
     assert(checkState(bang, [
       unionOfKinds([ValueKind.Expression, ValueKind.Generator])
     ]));
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullAssertExpressionNotEnabled(bang);
     }
     Object operand = pop();
@@ -2853,7 +2939,7 @@
   void handleType(Token beginToken, Token questionMark) {
     // TODO(ahe): The scope is wrong for return types of generic functions.
     debugEvent("Type");
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportErrorIfNullableType(questionMark);
     }
     bool isMarkedAsNullable = questionMark != null;
@@ -2934,7 +3020,7 @@
   @override
   void endFunctionType(Token functionToken, Token questionMark) {
     debugEvent("FunctionType");
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportErrorIfNullableType(questionMark);
     }
     FormalParameters formals = pop();
@@ -3035,7 +3121,7 @@
   void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
       Token covariantToken, Token varFinalOrConst) {
     // TODO(danrubel): handle required token
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportNonNullableModifierError(requiredToken);
     }
     push((covariantToken != null ? covariantMask : 0) |
@@ -3115,13 +3201,14 @@
     }
     if (annotations != null) {
       if (functionNestingLevel == 0) {
-        inferAnnotations(annotations);
+        inferAnnotations(variable, annotations);
       }
       for (Expression annotation in annotations) {
         variable.addAnnotation(annotation);
       }
     }
     push(parameter);
+    typeInferrer?.assignedVariables?.declare(variable);
   }
 
   @override
@@ -3162,7 +3249,7 @@
     FormalParameters formals = pop();
     UnresolvedType returnType = pop();
     List<TypeVariableBuilder> typeVariables = pop();
-    if (!libraryBuilder.loader.target.enableNonNullable) {
+    if (!libraryBuilder.isNonNullableByDefault) {
       reportErrorIfNullableType(question);
     }
     UnresolvedType type = formals.toFunctionType(returnType,
@@ -3309,7 +3396,11 @@
 
   @override
   void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
-    Statement finallyBlock = popStatementIfNotNull(finallyKeyword);
+    Statement finallyBlock;
+    if (finallyKeyword != null) {
+      finallyBlock = pop();
+      typeInferrer?.assignedVariables?.endNode(finallyBlock);
+    }
     List<Catch> catchBlocks;
     List<Statement> compileTimeErrors;
     if (catchCount != 0) {
@@ -3326,13 +3417,20 @@
       }
     }
     Statement tryBlock = popStatement();
-    Statement tryStatement = forest.createTryStatement(
-        offsetForToken(tryKeyword), tryBlock, catchBlocks, finallyBlock);
+    int fileOffset = offsetForToken(tryKeyword);
+    Statement result = tryBlock;
+    if (catchBlocks != null) {
+      result = forest.createTryCatch(fileOffset, result, catchBlocks);
+    }
+    if (finallyBlock != null) {
+      result = forest.createTryFinally(fileOffset, result, finallyBlock);
+    }
+
     if (compileTimeErrors != null) {
-      compileTimeErrors.add(tryStatement);
+      compileTimeErrors.add(result);
       push(forest.createBlock(noLocation, compileTimeErrors));
     } else {
-      push(tryStatement);
+      push(result);
     }
   }
 
@@ -3962,12 +4060,22 @@
       if (elseEntry is MapEntry) {
         push(forest.createIfMapEntry(
             offsetForToken(ifToken), toValue(condition), thenEntry, elseEntry));
-      } else if (elseEntry is SpreadElement) {
-        push(forest.createIfMapEntry(
-            offsetForToken(ifToken),
-            toValue(condition),
-            thenEntry,
-            new SpreadMapEntry(elseEntry.expression, elseEntry.isNullAware)));
+      } else if (elseEntry is ControlFlowElement) {
+        MapEntry elseMapEntry =
+            elseEntry.toMapEntry(typeInferrer?.assignedVariables?.reassignInfo);
+        if (elseMapEntry != null) {
+          push(forest.createIfMapEntry(offsetForToken(ifToken),
+              toValue(condition), thenEntry, elseMapEntry));
+        } else {
+          int offset = elseEntry is Expression
+              ? elseEntry.fileOffset
+              : offsetForToken(ifToken);
+          push(new MapEntry(
+              buildProblem(
+                  fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
+              new NullLiteral())
+            ..fileOffset = offsetForToken(ifToken));
+        }
       } else {
         int offset = elseEntry is Expression
             ? elseEntry.fileOffset
@@ -3979,12 +4087,22 @@
           ..fileOffset = offsetForToken(ifToken));
       }
     } else if (elseEntry is MapEntry) {
-      if (thenEntry is SpreadElement) {
-        push(forest.createIfMapEntry(
-            offsetForToken(ifToken),
-            toValue(condition),
-            new SpreadMapEntry(thenEntry.expression, thenEntry.isNullAware),
-            elseEntry));
+      if (thenEntry is ControlFlowElement) {
+        MapEntry thenMapEntry =
+            thenEntry.toMapEntry(typeInferrer?.assignedVariables?.reassignInfo);
+        if (thenMapEntry != null) {
+          push(forest.createIfMapEntry(offsetForToken(ifToken),
+              toValue(condition), thenMapEntry, elseEntry));
+        } else {
+          int offset = thenEntry is Expression
+              ? thenEntry.fileOffset
+              : offsetForToken(ifToken);
+          push(new MapEntry(
+              buildProblem(
+                  fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
+              new NullLiteral())
+            ..fileOffset = offsetForToken(ifToken));
+        }
       } else {
         int offset = thenEntry is Expression
             ? thenEntry.fileOffset
@@ -4032,8 +4150,8 @@
         push(_createReadOnlyVariableAccess(
             extensionThis, token, offsetForToken(token), 'this'));
       } else {
-        push(new ThisAccessGenerator(
-            this, token, inInitializer, inFieldInitializer));
+        push(new ThisAccessGenerator(this, token, inInitializer,
+            inFieldInitializer, inLateFieldInitializer));
       }
     } else {
       push(new IncompleteErrorGenerator(
@@ -4047,10 +4165,10 @@
     if (context.isScopeReference &&
         isDeclarationInstanceContext &&
         extensionThis == null) {
-      Member member = this.member.target;
-      member.transformerFlags |= TransformerFlag.superCalls;
-      push(new ThisAccessGenerator(
-          this, token, inInitializer, inFieldInitializer,
+      MemberBuilder memberBuilder = member;
+      memberBuilder.member.transformerFlags |= TransformerFlag.superCalls;
+      push(new ThisAccessGenerator(this, token, inInitializer,
+          inFieldInitializer, inLateFieldInitializer,
           isSuper: true));
     } else {
       push(new IncompleteErrorGenerator(
@@ -4080,7 +4198,7 @@
       ..fileOffset = name.charOffset;
     // TODO(ahe): Why are we looking up in local scope, but declaring in parent
     // scope?
-    Builder existing = scope.local[name.name];
+    Builder existing = scope.lookupLocalMember(name.name, setter: false);
     if (existing != null) {
       reportDuplicatedDeclaration(existing, name.name, name.charOffset);
     }
@@ -4099,6 +4217,9 @@
     switchScope = null;
     push(inCatchBlock);
     inCatchBlock = false;
+    // This is matched by the call to [endNode] in [pushNamedFunction] or
+    // [endFunctionExpression].
+    typeInferrer?.assignedVariables?.beginNode();
   }
 
   void exitFunction() {
@@ -4202,6 +4323,8 @@
           push(declaration);
         }
       }
+      // This is matched by the call to [beginNode] in [enterFunction].
+      typeInferrer?.assignedVariables?.endNode(declaration, isClosure: true);
     } else {
       return unhandled("${declaration.runtimeType}", "pushNamedFunction",
           token.charOffset, uri);
@@ -4233,13 +4356,24 @@
         typeParameters, asyncModifier, body, token.charOffset)
       ..fileOffset = beginToken.charOffset;
 
+    Expression result;
     if (constantContext != ConstantContext.none) {
-      push(buildProblem(fasta.messageNotAConstantExpression, formals.charOffset,
-          formals.length));
+      result = buildProblem(fasta.messageNotAConstantExpression,
+          formals.charOffset, formals.length);
     } else {
-      push(new FunctionExpression(function)
-        ..fileOffset = offsetForToken(beginToken));
+      result = new FunctionExpression(function)
+        ..fileOffset = offsetForToken(beginToken);
     }
+    push(result);
+    // This is matched by the call to [beginNode] in [enterFunction].
+    typeInferrer?.assignedVariables?.endNode(result, isClosure: true);
+  }
+
+  @override
+  void beginDoWhileStatement(Token token) {
+    // This is matched by the [endNode] call in [endDoWhileStatement].
+    typeInferrer?.assignedVariables?.beginNode();
+    super.beginDoWhileStatement(token);
   }
 
   @override
@@ -4256,6 +4390,8 @@
     }
     Statement result =
         forest.createDoStatement(offsetForToken(doKeyword), body, condition);
+    // This is matched by the [beginNode] call in [beginDoWhileStatement].
+    typeInferrer?.assignedVariables?.endNode(result);
     if (breakTarget.hasUsers) {
       result = forest.createLabeledStatement(result);
       breakTarget.resolveBreaks(forest, result);
@@ -4282,6 +4418,9 @@
     push(awaitToken ?? NullValue.AwaitToken);
     push(forToken);
     push(inKeyword);
+    // This is matched by the call to [deferNode] in [endForIn] or
+    // [endForInControlFlow].
+    typeInferrer?.assignedVariables?.beginNode();
   }
 
   @override
@@ -4291,11 +4430,13 @@
     Token inToken = pop();
     Token forToken = pop();
     Token awaitToken = pop(NullValue.AwaitToken);
-    Expression iterable = popForValue();
-    Object lvalue = pop(); // lvalue
-    exitLocalScope();
 
     if (constantContext != ConstantContext.none) {
+      popForValue(); // Pop iterable
+      pop(); // Pop lvalue
+      exitLocalScope();
+      typeInferrer?.assignedVariables?.discardNode();
+
       handleRecoverableError(
           fasta.templateCantUseControlFlowOrSpreadAsConstant
               .withArguments(forToken),
@@ -4305,23 +4446,45 @@
       return;
     }
 
+    // This is matched by the call to [beginNode] in [handleForInLoopParts].
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
+        typeInferrer?.assignedVariables?.deferNode();
+
+    Expression iterable = popForValue();
+    Object lvalue = pop(); // lvalue
+    exitLocalScope();
+
     transformCollections = true;
     VariableDeclaration variable = buildForInVariable(forToken, lvalue);
     Expression problem = checkForInVariable(lvalue, variable, forToken);
     Statement prologue = buildForInBody(lvalue, variable, forToken, inToken);
     if (entry is MapEntry) {
-      push(forest.createForInMapEntry(offsetForToken(forToken), variable,
-          iterable, prologue, entry, problem,
-          isAsync: awaitToken != null));
+      ForInMapEntry result = forest.createForInMapEntry(
+          offsetForToken(forToken),
+          variable,
+          iterable,
+          prologue,
+          entry,
+          problem,
+          isAsync: awaitToken != null);
+      typeInferrer?.assignedVariables
+          ?.storeInfo(result, assignedVariablesNodeInfo);
+      push(result);
     } else {
-      push(forest.createForInElement(offsetForToken(forToken), variable,
-          iterable, prologue, toValue(entry), problem,
-          isAsync: awaitToken != null));
+      ForInElement result = forest.createForInElement(offsetForToken(forToken),
+          variable, iterable, prologue, toValue(entry), problem,
+          isAsync: awaitToken != null);
+      typeInferrer?.assignedVariables
+          ?.storeInfo(result, assignedVariablesNodeInfo);
+      push(result);
     }
   }
 
   VariableDeclaration buildForInVariable(Token token, Object lvalue) {
-    if (lvalue is VariableDeclaration) return lvalue;
+    if (lvalue is VariableDeclaration) {
+      typeInferrer?.assignedVariables?.write(lvalue);
+      return lvalue;
+    }
     return forest.createVariableDeclaration(
         offsetForToken(token), null, functionNestingLevel,
         isFinal: true);
@@ -4399,6 +4562,10 @@
     Token forToken = pop();
     Token awaitToken = pop(NullValue.AwaitToken);
 
+    // This is matched by the call to [beginNode] in [handleForInLoopParts].
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
+        typeInferrer?.assignedVariables?.deferNode();
+
     Expression expression = popForValue();
     Object lvalue = pop();
     exitLocalScope();
@@ -4429,6 +4596,8 @@
         isAsync: awaitToken != null)
       ..fileOffset = awaitToken?.charOffset ?? forToken.charOffset
       ..bodyOffset = body.fileOffset; // TODO(ahe): Isn't this redundant?
+    typeInferrer?.assignedVariables
+        ?.storeInfo(result, assignedVariablesNodeInfo);
     if (breakTarget.hasUsers) {
       result = forest.createLabeledStatement(result);
       breakTarget.resolveBreaks(forest, result);
@@ -4505,6 +4674,13 @@
   }
 
   @override
+  void beginWhileStatement(Token token) {
+    // This is matched by the [endNode] call in [endWhileStatement].
+    typeInferrer?.assignedVariables?.beginNode();
+    super.beginWhileStatement(token);
+  }
+
+  @override
   void endWhileStatement(Token whileKeyword, Token endToken) {
     debugEvent("WhileStatement");
     Statement body = popStatement();
@@ -4515,13 +4691,16 @@
       body = forest.createLabeledStatement(body);
       continueTarget.resolveContinues(forest, body);
     }
-    Statement result = forest.createWhileStatement(
+    Statement whileStatement = forest.createWhileStatement(
         offsetForToken(whileKeyword), condition, body);
+    Statement result = whileStatement;
     if (breakTarget.hasUsers) {
       result = forest.createLabeledStatement(result);
       breakTarget.resolveBreaks(forest, result);
     }
     exitLoopOrSwitch(result);
+    // This is matched by the [beginNode] call in [beginWhileStatement].
+    typeInferrer?.assignedVariables?.endNode(whileStatement);
   }
 
   @override
@@ -4615,6 +4794,8 @@
   @override
   void beginSwitchBlock(Token token) {
     debugEvent("beginSwitchBlock");
+    // This is matched by the [endNode] call in [endSwitchStatement].
+    typeInferrer?.assignedVariables?.beginNode();
     enterLocalScope("switch block");
     enterSwitchScope();
     enterBreakTarget(token.charOffset);
@@ -4700,13 +4881,16 @@
     exitSwitchScope();
     exitLocalScope();
     Expression expression = popForValue();
-    Statement result = new SwitchStatement(expression, cases)
+    Statement switchStatement = new SwitchStatement(expression, cases)
       ..fileOffset = switchKeyword.charOffset;
+    Statement result = switchStatement;
     if (target.hasUsers) {
       result = forest.createLabeledStatement(result);
       target.resolveBreaks(forest, result);
     }
     exitLoopOrSwitch(result);
+    // This is matched by the [beginNode] call in [beginSwitchBlock].
+    typeInferrer?.assignedVariables?.endNode(switchStatement);
   }
 
   @override
@@ -4881,7 +5065,7 @@
     TypeVariableBuilder variable =
         new TypeVariableBuilder(name.name, libraryBuilder, name.charOffset);
     if (annotations != null) {
-      inferAnnotations(annotations);
+      inferAnnotations(variable.parameter, annotations);
       for (Expression annotation in annotations) {
         variable.parameter.addAnnotation(annotation);
       }
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 5820b4f..42703d9 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
@@ -14,6 +14,7 @@
         InvalidType,
         Member,
         Name,
+        Nullability,
         Procedure,
         ProcedureKind,
         Supertype,
@@ -115,6 +116,7 @@
 abstract class ClassMember {
   bool get isStatic;
   bool get isField;
+  bool get isAssignable;
   bool get isSetter;
   bool get isGetter;
   bool get isFinal;
@@ -145,7 +147,7 @@
 }
 
 bool impliesSetter(ClassMember declaration) {
-  return declaration.isField && !(declaration.isFinal || declaration.isConst);
+  return declaration.isAssignable;
 }
 
 bool hasSameSignature(FunctionNode a, FunctionNode b) {
@@ -1201,12 +1203,12 @@
 
     /// Members (excluding setters) declared in [cls].
     List<ClassMember> localMembers =
-        new List<ClassMember>.from(scope.local.values)
+        new List<ClassMember>.from(scope.localMembers)
           ..sort(compareDeclarations);
 
     /// Setters declared in [cls].
     List<ClassMember> localSetters =
-        new List<ClassMember>.from(scope.setters.values)
+        new List<ClassMember>.from(scope.localSetters)
           ..sort(compareDeclarations);
 
     // Add implied setters from fields in [localMembers].
@@ -2014,8 +2016,9 @@
   }
 
   @override
-  InterfaceType futureType(DartType type) {
-    return new InterfaceType(hierarchy.futureClass, <DartType>[type]);
+  InterfaceType futureType(DartType type, Nullability nullability) {
+    return new InterfaceType(
+        hierarchy.futureClass, <DartType>[type], nullability);
   }
 
   @override
@@ -2155,10 +2158,10 @@
 
   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;
 
   void addAllDeclarationsTo(List<ClassMember> declarations) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index 8803399..ce5307c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -55,6 +55,14 @@
   @override
   R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
       v.defaultExpression(this, arg);
+
+  /// Returns this control flow element as a [MapEntry], or `null` if this
+  /// control flow element cannot be converted into a [MapEntry].
+  ///
+  /// [onConvertForElement] is called when a [ForElement] or [ForInElement] is
+  /// converted to a [ForMapEntry] or [ForInMapEntry], respectively.
+  // TODO(johnniwinther): Merge this with [convertToMapEntry].
+  MapEntry toMapEntry(void onConvertForElement(TreeNode from, TreeNode to));
 }
 
 /// A spread element in a list or set literal.
@@ -84,6 +92,12 @@
       expression?.parent = this;
     }
   }
+
+  @override
+  SpreadMapEntry toMapEntry(
+      void onConvertForElement(TreeNode from, TreeNode to)) {
+    return new SpreadMapEntry(expression, isNullAware)..fileOffset = fileOffset;
+  }
 }
 
 /// An 'if' element in a list or set literal.
@@ -120,6 +134,26 @@
       otherwise?.parent = this;
     }
   }
+
+  @override
+  MapEntry toMapEntry(void onConvertForElement(TreeNode from, TreeNode to)) {
+    MapEntry thenEntry;
+    if (then is ControlFlowElement) {
+      ControlFlowElement thenElement = then;
+      thenEntry = thenElement.toMapEntry(onConvertForElement);
+    }
+    if (thenEntry == null) return null;
+    MapEntry otherwiseEntry;
+    if (otherwise != null) {
+      if (otherwise is ControlFlowElement) {
+        ControlFlowElement otherwiseElement = otherwise;
+        otherwiseEntry = otherwiseElement.toMapEntry(onConvertForElement);
+      }
+      if (otherwiseEntry == null) return null;
+    }
+    return new IfMapEntry(condition, thenEntry, otherwiseEntry)
+      ..fileOffset = fileOffset;
+  }
 }
 
 /// A 'for' element in a list or set literal.
@@ -157,6 +191,21 @@
       body?.parent = this;
     }
   }
+
+  @override
+  MapEntry toMapEntry(void onConvertForElement(TreeNode from, TreeNode to)) {
+    MapEntry bodyEntry;
+    if (body is ControlFlowElement) {
+      ControlFlowElement bodyElement = body;
+      bodyEntry = bodyElement.toMapEntry(onConvertForElement);
+    }
+    if (bodyEntry == null) return null;
+    ForMapEntry result =
+        new ForMapEntry(variables, condition, updates, bodyEntry)
+          ..fileOffset = fileOffset;
+    onConvertForElement(this, result);
+    return result;
+  }
 }
 
 /// A 'for-in' element in a list or set literal.
@@ -208,6 +257,21 @@
       problem?.parent = this;
     }
   }
+
+  @override
+  MapEntry toMapEntry(void onConvertForElement(TreeNode from, TreeNode to)) {
+    MapEntry bodyEntry;
+    if (body is ControlFlowElement) {
+      ControlFlowElement bodyElement = body;
+      bodyEntry = bodyElement.toMapEntry(onConvertForElement);
+    }
+    if (bodyEntry == null) return null;
+    ForInMapEntry result =
+        new ForInMapEntry(variable, iterable, prologue, bodyEntry, problem)
+          ..fileOffset = fileOffset;
+    onConvertForElement(this, result);
+    return result;
+  }
 }
 
 mixin ControlFlowMapEntry implements MapEntry {
@@ -388,7 +452,14 @@
   }
 }
 
-Expression convertToElement(MapEntry entry, InferenceHelper helper) {
+/// Convert [entry] to an [Expression], if possible. If [entry] cannot be
+/// converted an error reported through [helper] and an invalid expression is
+/// returned.
+///
+/// [onConvertForMapEntry] is called when a [ForMapEntry] or [ForInMapEntry] is
+/// converted to a [ForElement] or [ForInElement], respectively.
+Expression convertToElement(MapEntry entry, InferenceHelper helper,
+    void onConvertForMapEntry(TreeNode from, TreeNode to)) {
   if (entry is SpreadMapEntry) {
     return new SpreadElement(entry.expression, entry.isNullAware)
       ..fileOffset = entry.expression.fileOffset;
@@ -396,22 +467,33 @@
   if (entry is IfMapEntry) {
     return new IfElement(
         entry.condition,
-        convertToElement(entry.then, helper),
+        convertToElement(entry.then, helper, onConvertForMapEntry),
         entry.otherwise == null
             ? null
-            : convertToElement(entry.otherwise, helper))
+            : convertToElement(entry.otherwise, helper, onConvertForMapEntry))
       ..fileOffset = entry.fileOffset;
   }
   if (entry is ForMapEntry) {
-    return new ForElement(entry.variables, entry.condition, entry.updates,
-        convertToElement(entry.body, helper))
+    ForElement result = new ForElement(
+        entry.variables,
+        entry.condition,
+        entry.updates,
+        convertToElement(entry.body, helper, onConvertForMapEntry))
       ..fileOffset = entry.fileOffset;
+    onConvertForMapEntry(entry, result);
+    return result;
   }
   if (entry is ForInMapEntry) {
-    return new ForInElement(entry.variable, entry.iterable, entry.prologue,
-        convertToElement(entry.body, helper), entry.problem,
+    ForInElement result = new ForInElement(
+        entry.variable,
+        entry.iterable,
+        entry.prologue,
+        convertToElement(entry.body, helper, onConvertForMapEntry),
+        entry.problem,
         isAsync: entry.isAsync)
       ..fileOffset = entry.fileOffset;
+    onConvertForMapEntry(entry, result);
+    return result;
   }
   return helper.buildProblem(
     templateExpectedButGot.withArguments(','),
@@ -436,7 +518,14 @@
   return false;
 }
 
-MapEntry convertToMapEntry(Expression element, InferenceHelper helper) {
+/// Convert [element] to a [MapEntry], if possible. If [element] cannot be
+/// converted an error reported through [helper] and a map entry holding an
+/// invalid expression is returned.
+///
+/// [onConvertForElement] is called when a [ForElement] or [ForInElement] is
+/// converted to a [ForMapEntry] or [ForInMapEntry], respectively.
+MapEntry convertToMapEntry(Expression element, InferenceHelper helper,
+    void onConvertForElement(TreeNode from, TreeNode to)) {
   if (element is SpreadElement) {
     return new SpreadMapEntry(element.expression, element.isNullAware)
       ..fileOffset = element.expression.fileOffset;
@@ -444,26 +533,33 @@
   if (element is IfElement) {
     return new IfMapEntry(
         element.condition,
-        convertToMapEntry(element.then, helper),
+        convertToMapEntry(element.then, helper, onConvertForElement),
         element.otherwise == null
             ? null
-            : convertToMapEntry(element.otherwise, helper))
+            : convertToMapEntry(element.otherwise, helper, onConvertForElement))
       ..fileOffset = element.fileOffset;
   }
   if (element is ForElement) {
-    return new ForMapEntry(element.variables, element.condition,
-        element.updates, convertToMapEntry(element.body, helper))
+    ForMapEntry result = new ForMapEntry(
+        element.variables,
+        element.condition,
+        element.updates,
+        convertToMapEntry(element.body, helper, onConvertForElement))
       ..fileOffset = element.fileOffset;
+    onConvertForElement(element, result);
+    return result;
   }
   if (element is ForInElement) {
-    return new ForInMapEntry(
+    ForInMapEntry result = new ForInMapEntry(
         element.variable,
         element.iterable,
         element.prologue,
-        convertToMapEntry(element.body, helper),
+        convertToMapEntry(element.body, helper, onConvertForElement),
         element.problem,
         isAsync: element.isAsync)
       ..fileOffset = element.fileOffset;
+    onConvertForElement(element, result);
+    return result;
   }
   return new MapEntry(
       helper.buildProblem(
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 4b10818..cdede9d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -38,6 +38,7 @@
         Message,
         messageConstEvalCircularity,
         messageConstEvalContext,
+        messageConstEvalExtension,
         messageConstEvalFailedAssertion,
         messageConstEvalNotListOrSetInSpread,
         messageConstEvalNotMapInSpread,
@@ -1726,6 +1727,8 @@
         // identical here.
         return makeBoolConstant(identical(left, right));
       }
+    } else if (target.isExtensionMember) {
+      return report(node, messageConstEvalExtension);
     }
 
     String name = target.name.name;
@@ -1756,8 +1759,10 @@
       return unevaluated(node, new IsExpression(extract(constant), node.type));
     }
     if (constant is NullConstant) {
-      return makeBoolConstant(node.type == typeEnvironment.nullType ||
-          node.type == typeEnvironment.coreTypes.objectLegacyRawType ||
+      DartType nodeType = node.type;
+      return makeBoolConstant(nodeType == typeEnvironment.nullType ||
+          nodeType is InterfaceType &&
+              nodeType.classNode == typeEnvironment.coreTypes.objectClass ||
           node.type is DynamicType);
     }
     return makeBoolConstant(
@@ -1863,14 +1868,18 @@
   bool isSubtype(Constant constant, DartType type) {
     DartType constantType = constant.getType(typeEnvironment);
     if (targetingJavaScript) {
-      if (constantType == typeEnvironment.coreTypes.intLegacyRawType &&
-          type == typeEnvironment.coreTypes.doubleLegacyRawType) {
+      if (constantType is InterfaceType &&
+          constantType.classNode == typeEnvironment.coreTypes.intClass &&
+          type is InterfaceType &&
+          type.classNode == typeEnvironment.coreTypes.doubleClass) {
         // With JS semantics, an integer is also a double.
         return true;
       }
 
-      if (constantType == typeEnvironment.coreTypes.doubleLegacyRawType &&
-          type == typeEnvironment.coreTypes.intLegacyRawType) {
+      if (constantType is InterfaceType &&
+          constantType.classNode == typeEnvironment.coreTypes.doubleClass &&
+          type is InterfaceType &&
+          type.classNode == typeEnvironment.coreTypes.intClass) {
         double value = (constant as DoubleConstant).value;
         if (value.isFinite && value == value.truncateToDouble()) {
           return true;
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 9840652..0c2f81f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -7,9 +7,12 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show lengthForToken, lengthOfSpan;
 
-import '../../scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
+import 'package:kernel/ast.dart';
 
 import '../builder/builder.dart';
 import '../builder/declaration_builder.dart';
@@ -48,12 +51,12 @@
         rightShiftName,
         tripleShiftName;
 
-import '../parser.dart' show lengthForToken, lengthOfSpan, offsetForToken;
-
 import '../problems.dart';
 
 import '../scope.dart';
 
+import '../source/stack_listener.dart' show offsetForToken;
+
 import 'body_builder.dart' show noLocation;
 
 import 'constness.dart' show Constness;
@@ -239,8 +242,8 @@
         _helper.addProblem(
             messageNotAConstantExpression, fileOffset, token.length);
       }
-      return PropertyAccessGenerator.make(_helper, send.token,
-          buildSimpleRead(), send.name, null, null, isNullAware);
+      return PropertyAccessGenerator.make(
+          _helper, send.token, buildSimpleRead(), send.name, isNullAware);
     }
   }
 
@@ -321,7 +324,8 @@
   VariableUseGenerator(
       ExpressionGeneratorHelper helper, Token token, this.variable,
       [this.promotedType])
-      : super(helper, token);
+      : assert(variable.isAssignable, 'Variable $variable is not assignable'),
+        super(helper, token);
 
   @override
   String get _debugName => "VariableUseGenerator";
@@ -344,15 +348,8 @@
   }
 
   Expression _createWrite(int offset, Expression value) {
-    _helper.typePromoter
-        ?.mutateVariable(variable, _helper.functionNestingLevel);
-    Expression write;
-    if (variable.isFinal || variable.isConst) {
-      write = _makeInvalidWrite(value);
-    } else {
-      write = new VariableSet(variable, value)..fileOffset = offset;
-    }
-    return write;
+    _helper.registerVariableAssignment(variable);
+    return new VariableSet(variable, value)..fileOffset = offset;
   }
 
   @override
@@ -452,14 +449,8 @@
   /// documentation.
   final Name name;
 
-  // TODO(johnniwinther): Remove [getter] and [setter]? These are never
-  // passed.
-  final Member getter;
-
-  final Member setter;
-
-  PropertyAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.receiver, this.name, this.getter, this.setter)
+  PropertyAccessGenerator(
+      ExpressionGeneratorHelper helper, Token token, this.receiver, this.name)
       : super(helper, token);
 
   @override
@@ -480,21 +471,17 @@
     printNodeOn(receiver, sink, syntheticNames: syntheticNames);
     sink.write(", name: ");
     sink.write(name.name);
-    sink.write(", getter: ");
-    printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
-    sink.write(", setter: ");
-    printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
   }
 
   @override
   Expression buildSimpleRead() {
-    return new PropertyGet(receiver, name, getter)..fileOffset = fileOffset;
+    return _forest.createPropertyGet(fileOffset, receiver, name);
   }
 
   @override
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
     return _helper.forest.createPropertySet(fileOffset, receiver, name, value,
-        interfaceTarget: setter, forEffect: voidContext);
+        forEffect: voidContext);
   }
 
   @override
@@ -502,9 +489,8 @@
       {bool voidContext = false}) {
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiver);
-    PropertyGet read = new PropertyGet(
-        _helper.createVariableGet(variable, receiver.fileOffset), name)
-      ..fileOffset = fileOffset;
+    PropertyGet read = _forest.createPropertyGet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name);
     PropertySet write = _helper.forest.createPropertySet(fileOffset,
         _helper.createVariableGet(variable, receiver.fileOffset), name, value,
         forEffect: voidContext);
@@ -519,20 +505,13 @@
       Procedure interfaceTarget,
       bool isPreIncDec: false,
       bool isPostIncDec: false}) {
-    VariableDeclaration variable =
-        _helper.forest.createVariableDeclarationForValue(receiver);
-    MethodInvocation binary = _helper.forest.createMethodInvocation(
-        offset,
-        new PropertyGet(
-            _helper.createVariableGet(variable, receiver.fileOffset), name)
-          ..fileOffset = fileOffset,
-        binaryOperator,
-        _helper.forest.createArguments(offset, <Expression>[value]),
-        interfaceTarget: interfaceTarget);
-    PropertySet write = _helper.forest.createPropertySet(fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset), name, binary,
-        forEffect: voidContext);
-    return new CompoundPropertySet(variable, write)..fileOffset = offset;
+    return new CompoundPropertySet(receiver, name, binaryOperator, value,
+        forEffect: voidContext,
+        readOnlyReceiver: false,
+        readOffset: fileOffset,
+        binaryOffset: offset,
+        writeOffset: fileOffset)
+      ..fileOffset = offset;
   }
 
   @override
@@ -551,9 +530,8 @@
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiver);
     VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
-        new PropertyGet(
-            _helper.createVariableGet(variable, receiver.fileOffset), name)
-          ..fileOffset = fileOffset);
+        _forest.createPropertyGet(fileOffset,
+            _helper.createVariableGet(variable, receiver.fileOffset), name));
     MethodInvocation binary = _helper.forest.createMethodInvocation(
         offset,
         _helper.createVariableGet(read, fileOffset),
@@ -577,27 +555,14 @@
   }
 
   /// Creates a [Generator] for the access of property [name] on [receiver].
-  static Generator make(
-      ExpressionGeneratorHelper helper,
-      Token token,
-      Expression receiver,
-      Name name,
-      // TODO(johnniwinther): Remove [getter] and [setter]? These are never
-      // passed.
-      Member getter,
-      Member setter,
-      bool isNullAware) {
+  static Generator make(ExpressionGeneratorHelper helper, Token token,
+      Expression receiver, Name name, bool isNullAware) {
     if (helper.forest.isThisExpression(receiver)) {
-      getter ??= helper.lookupInstanceMember(name);
-      setter ??= helper.lookupInstanceMember(name, isSetter: true);
-      return new ThisPropertyAccessGenerator(
-          helper, token, name, getter, setter);
+      return new ThisPropertyAccessGenerator(helper, token, name);
     } else {
       return isNullAware
-          ? new NullAwarePropertyAccessGenerator(
-              helper, token, receiver, name, getter, setter, null)
-          : new PropertyAccessGenerator(
-              helper, token, receiver, name, getter, setter);
+          ? new NullAwarePropertyAccessGenerator(helper, token, receiver, name)
+          : new PropertyAccessGenerator(helper, token, receiver, name);
     }
   }
 }
@@ -636,20 +601,8 @@
   /// documentation.
   final Name name;
 
-  /// The member accessed if this subexpression has a read.
-  ///
-  /// This is `null` if the `this` class does not have a readable property named
-  /// [name].
-  final Member getter;
-
-  /// The member accessed if this subexpression has a write.
-  ///
-  /// This is `null` if the `this` class does not have a writable property named
-  /// [name].
-  final Member setter;
-
-  ThisPropertyAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.name, this.getter, this.setter)
+  ThisPropertyAccessGenerator(
+      ExpressionGeneratorHelper helper, Token token, this.name)
       : super(helper, token);
 
   @override
@@ -664,9 +617,8 @@
   }
 
   Expression _createRead() {
-    return new PropertyGet(
-        _forest.createThisExpression(fileOffset), name, getter)
-      ..fileOffset = fileOffset;
+    return _forest.createPropertyGet(
+        fileOffset, _forest.createThisExpression(fileOffset), name);
   }
 
   @override
@@ -677,7 +629,7 @@
   Expression _createWrite(int offset, Expression value, {bool forEffect}) {
     return _helper.forest.createPropertySet(
         fileOffset, _forest.createThisExpression(fileOffset), name, value,
-        interfaceTarget: setter, forEffect: forEffect);
+        forEffect: forEffect);
   }
 
   @override
@@ -698,8 +650,8 @@
       bool isPostIncDec: false}) {
     MethodInvocation binary = _helper.forest.createMethodInvocation(
         offset,
-        new PropertyGet(_forest.createThisExpression(fileOffset), name)
-          ..fileOffset = fileOffset,
+        _forest.createPropertyGet(
+            fileOffset, _forest.createThisExpression(fileOffset), name),
         binaryOperator,
         _helper.forest.createArguments(offset, <Expression>[value]),
         interfaceTarget: interfaceTarget);
@@ -720,8 +672,8 @@
           isPostIncDec: true);
     }
     VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
-        new PropertyGet(_forest.createThisExpression(fileOffset), name)
-          ..fileOffset = fileOffset);
+        _forest.createPropertyGet(
+            fileOffset, _forest.createThisExpression(fileOffset), name));
     MethodInvocation binary = _helper.forest.createMethodInvocation(
         offset,
         _helper.createVariableGet(read, fileOffset),
@@ -736,15 +688,8 @@
 
   @override
   Expression doInvocation(int offset, Arguments arguments) {
-    Member interfaceTarget = getter;
-    if (interfaceTarget is Field) {
-      // TODO(ahe): In strong mode we should probably rewrite this to
-      // `this.name.call(arguments)`.
-      interfaceTarget = null;
-    }
     return _helper.buildMethodInvocation(
-        _forest.createThisExpression(fileOffset), name, arguments, offset,
-        interfaceTarget: interfaceTarget);
+        _forest.createThisExpression(fileOffset), name, arguments, offset);
   }
 
   @override
@@ -755,13 +700,8 @@
 
   @override
   void printOn(StringSink sink) {
-    NameSystem syntheticNames = new NameSystem();
     sink.write(", name: ");
     sink.write(name.name);
-    sink.write(", getter: ");
-    printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
-    sink.write(", setter: ");
-    printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
   }
 }
 
@@ -772,20 +712,8 @@
 
   final Name name;
 
-  final Member getter;
-
-  final Member setter;
-
-  final DartType type;
-
-  NullAwarePropertyAccessGenerator(
-      ExpressionGeneratorHelper helper,
-      Token token,
-      this.receiverExpression,
-      this.name,
-      this.getter,
-      this.setter,
-      this.type)
+  NullAwarePropertyAccessGenerator(ExpressionGeneratorHelper helper,
+      Token token, this.receiverExpression, this.name)
       : this.receiver = makeOrReuseVariable(receiverExpression),
         super(helper, token);
 
@@ -801,10 +729,10 @@
   Expression buildSimpleRead() {
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiverExpression);
-    PropertyGet read = new PropertyGet(
+    PropertyGet read = _forest.createPropertyGet(
+        fileOffset,
         _helper.createVariableGet(variable, receiverExpression.fileOffset),
-        name)
-      ..fileOffset = fileOffset;
+        name);
     return new NullAwarePropertyGet(variable, read)
       ..fileOffset = receiverExpression.fileOffset;
   }
@@ -881,12 +809,6 @@
     printNodeOn(receiverExpression, sink, syntheticNames: syntheticNames);
     sink.write(", name: ");
     sink.write(name.name);
-    sink.write(", getter: ");
-    printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
-    sink.write(", setter: ");
-    printQualifiedNameOn(setter, sink, syntheticNames: syntheticNames);
-    sink.write(", type: ");
-    printNodeOn(type, sink, syntheticNames: syntheticNames);
   }
 }
 
@@ -1427,30 +1349,11 @@
   factory StaticAccessGenerator.fromBuilder(
       ExpressionGeneratorHelper helper,
       String targetName,
-      Builder declaration,
       Token token,
-      Builder builderSetter) {
-    if (declaration is AccessErrorBuilder) {
-      AccessErrorBuilder error = declaration;
-      declaration = error.builder;
-      // We should only see an access error here if we've looked up a setter
-      // when not explicitly looking for a setter.
-      assert(declaration.isSetter);
-    } else if (declaration.target == null) {
-      return unhandled(
-          "${declaration.runtimeType}",
-          "StaticAccessGenerator.fromBuilder",
-          offsetForToken(token),
-          helper.uri);
-    }
-    Member getter = declaration.target.hasGetter ? declaration.target : null;
-    Member setter = declaration.target.hasSetter ? declaration.target : null;
-    if (setter == null) {
-      if (builderSetter?.target?.hasSetter ?? false) {
-        setter = builderSetter.target;
-      }
-    }
-    return new StaticAccessGenerator(helper, token, targetName, getter, setter);
+      MemberBuilder getterBuilder,
+      MemberBuilder setterBuilder) {
+    return new StaticAccessGenerator(helper, token, targetName,
+        getterBuilder?.member, setterBuilder?.member);
   }
 
   @override
@@ -1659,46 +1562,29 @@
       String targetName,
       VariableDeclaration extensionThis,
       List<TypeParameter> extensionTypeParameters,
-      Builder getterBuilder,
-      Builder setterBuilder) {
+      MemberBuilder getterBuilder,
+      MemberBuilder setterBuilder) {
     Procedure readTarget;
     Procedure invokeTarget;
     if (getterBuilder != null) {
-      if (getterBuilder is AccessErrorBuilder) {
-        AccessErrorBuilder error = getterBuilder;
-        getterBuilder = error.builder;
-        // We should only see an access error here if we've looked up a setter
-        // when not explicitly looking for a setter.
-        assert(getterBuilder.isSetter);
-      } else if (getterBuilder.target == null) {
-        return unhandled(
-            "${getterBuilder.runtimeType}",
-            "ExtensionInstanceAccessGenerator.fromBuilder",
-            offsetForToken(token),
-            helper.uri);
-      }
       if (getterBuilder.isGetter) {
         assert(!getterBuilder.isStatic);
-        readTarget = getterBuilder.target;
+        readTarget = getterBuilder.member;
       } else if (getterBuilder.isRegularMethod) {
         assert(!getterBuilder.isStatic);
-        MemberBuilder procedureBuilder = getterBuilder;
-        readTarget = procedureBuilder.extensionTearOff;
-        invokeTarget = procedureBuilder.procedure;
+        readTarget = getterBuilder.extensionTearOff;
+        invokeTarget = getterBuilder.procedure;
       } else if (getterBuilder is FunctionBuilder && getterBuilder.isOperator) {
         assert(!getterBuilder.isStatic);
-        invokeTarget = getterBuilder.target;
+        invokeTarget = getterBuilder.member;
       }
     }
     Procedure writeTarget;
     if (setterBuilder != null) {
-      if (setterBuilder is AccessErrorBuilder) {
-        targetName ??= setterBuilder.name;
-      } else if (setterBuilder.isSetter) {
+      if (setterBuilder.isSetter) {
         assert(!setterBuilder.isStatic);
-        MemberBuilder memberBuilder = setterBuilder;
-        writeTarget = memberBuilder.member;
-        targetName ??= memberBuilder.name;
+        writeTarget = setterBuilder.member;
+        targetName ??= setterBuilder.name;
       } else {
         return unhandled(
             "${setterBuilder.runtimeType}",
@@ -1909,7 +1795,7 @@
   final Extension extension;
 
   /// The name of the original target;
-  final String targetName;
+  final Name targetName;
 
   /// The static [Member] generated for an instance extension member which is
   /// used for performing a read on this subexpression.
@@ -1973,6 +1859,7 @@
       Token token,
       int extensionTypeArgumentOffset,
       Extension extension,
+      Name targetName,
       Builder getterBuilder,
       Builder setterBuilder,
       Expression receiver,
@@ -1980,7 +1867,6 @@
       int extensionTypeParameterCount,
       {bool isNullAware}) {
     assert(getterBuilder != null || setterBuilder != null);
-    String targetName;
     Procedure readTarget;
     Procedure invokeTarget;
     if (getterBuilder != null) {
@@ -1995,18 +1881,15 @@
         assert(!getterBuilder.isStatic);
         MemberBuilder memberBuilder = getterBuilder;
         readTarget = memberBuilder.member;
-        targetName = memberBuilder.name;
       } else if (getterBuilder.isRegularMethod) {
         assert(!getterBuilder.isStatic);
         MemberBuilder procedureBuilder = getterBuilder;
         readTarget = procedureBuilder.extensionTearOff;
         invokeTarget = procedureBuilder.procedure;
-        targetName = procedureBuilder.name;
       } else if (getterBuilder is FunctionBuilder && getterBuilder.isOperator) {
         assert(!getterBuilder.isStatic);
         MemberBuilder memberBuilder = getterBuilder;
         invokeTarget = memberBuilder.member;
-        targetName = memberBuilder.name;
       } else {
         return unhandled(
             "${getterBuilder.runtimeType}",
@@ -2019,12 +1902,11 @@
     if (setterBuilder != null) {
       assert(!setterBuilder.isStatic);
       if (setterBuilder is AccessErrorBuilder) {
-        targetName ??= setterBuilder.name;
+        // No setter.
       } else if (setterBuilder.isSetter) {
         assert(!setterBuilder.isStatic);
         MemberBuilder memberBuilder = setterBuilder;
         writeTarget = memberBuilder.member;
-        targetName ??= memberBuilder.name;
       } else {
         return unhandled(
             "${setterBuilder.runtimeType}",
@@ -2052,7 +1934,7 @@
   String get _debugName => "ExplicitExtensionIndexedAccessGenerator";
 
   @override
-  String get _plainNameForRead => targetName;
+  String get _plainNameForRead => targetName.name;
 
   List<DartType> _createExtensionTypeArguments() {
     return explicitTypeArguments ?? const <DartType>[];
@@ -2177,18 +2059,14 @@
           forEffect: voidContext, readOnlyReceiver: true);
       return new NullAwareExtension(variable, write)..fileOffset = offset;
     } else {
-      VariableDeclaration variable =
-          _helper.forest.createVariableDeclarationForValue(receiver);
-      MethodInvocation binary = _helper.forest.createMethodInvocation(
-          offset,
-          _createRead(_helper.createVariableGet(variable, receiver.fileOffset)),
-          binaryOperator,
-          _helper.forest.createArguments(offset, <Expression>[value]),
-          interfaceTarget: interfaceTarget);
-      Expression write = _createWrite(fileOffset,
-          _helper.createVariableGet(variable, receiver.fileOffset), binary,
-          forEffect: voidContext, readOnlyReceiver: true);
-      return new CompoundPropertySet(variable, write)..fileOffset = offset;
+      return new CompoundExtensionSet(extension, explicitTypeArguments,
+          receiver, targetName, readTarget, binaryOperator, value, writeTarget,
+          readOnlyReceiver: false,
+          forEffect: voidContext,
+          readOffset: fileOffset,
+          binaryOffset: offset,
+          writeOffset: fileOffset)
+        ..fileOffset = offset;
     }
   }
 
@@ -2610,6 +2488,7 @@
         // omitted).
         fileOffset,
         extensionBuilder.extension,
+        name,
         getter,
         setter,
         receiver,
@@ -3086,12 +2965,14 @@
         Builder setter;
         if (member.isSetter) {
           setter = member;
+          member = null;
         } else if (member.isGetter) {
           setter = declaration.findStaticBuilder(
               name.name, fileOffset, _uri, _helper.libraryBuilder,
               isSetter: true);
         } else if (member.isField) {
-          if (member.isFinal || member.isConst) {
+          MemberBuilder fieldBuilder = member;
+          if (!fieldBuilder.isAssignable) {
             setter = declaration.findStaticBuilder(
                 name.name, fileOffset, _uri, _helper.libraryBuilder,
                 isSetter: true);
@@ -3100,7 +2981,11 @@
           }
         }
         generator = new StaticAccessGenerator.fromBuilder(
-            _helper, name.name, member, send.token, setter);
+            _helper,
+            name.name,
+            send.token,
+            member is MemberBuilder ? member : null,
+            setter is MemberBuilder ? setter : null);
       }
 
       return arguments == null
@@ -3488,7 +3373,7 @@
 
   @override
   Expression buildSimpleRead() {
-    return new PropertyGet(receiver, name)..fileOffset = fileOffset;
+    return _forest.createPropertyGet(fileOffset, receiver, name);
   }
 
   @override
@@ -3496,9 +3381,8 @@
       {bool voidContext: false}) {
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiver);
-    PropertyGet read = new PropertyGet(
-        _helper.createVariableGet(variable, receiver.fileOffset), name)
-      ..fileOffset = fileOffset;
+    PropertyGet read = _forest.createPropertyGet(fileOffset,
+        _helper.createVariableGet(variable, receiver.fileOffset), name);
     PropertySet write = _helper.forest.createPropertySet(fileOffset,
         _helper.createVariableGet(variable, receiver.fileOffset), name, value,
         forEffect: voidContext);
@@ -3513,20 +3397,13 @@
       Procedure interfaceTarget,
       bool isPreIncDec: false,
       bool isPostIncDec: false}) {
-    VariableDeclaration variable =
-        _helper.forest.createVariableDeclarationForValue(receiver);
-    MethodInvocation binary = _helper.forest.createMethodInvocation(
-        offset,
-        new PropertyGet(
-            _helper.createVariableGet(variable, receiver.fileOffset), name)
-          ..fileOffset = fileOffset,
-        binaryOperator,
-        _helper.forest.createArguments(offset, <Expression>[value]),
-        interfaceTarget: interfaceTarget);
-    PropertySet write = _helper.forest.createPropertySet(fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset), name, binary,
-        forEffect: voidContext);
-    return new CompoundPropertySet(variable, write)..fileOffset = offset;
+    return new CompoundPropertySet(receiver, name, binaryOperator, value,
+        forEffect: voidContext,
+        readOnlyReceiver: false,
+        readOffset: fileOffset,
+        binaryOffset: offset,
+        writeOffset: fileOffset)
+      ..fileOffset = offset;
   }
 
   @override
@@ -3545,9 +3422,8 @@
     VariableDeclaration variable =
         _helper.forest.createVariableDeclarationForValue(receiver);
     VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
-        new PropertyGet(
-            _helper.createVariableGet(variable, receiver.fileOffset), name)
-          ..fileOffset = fileOffset);
+        _forest.createPropertyGet(fileOffset,
+            _helper.createVariableGet(variable, receiver.fileOffset), name));
     MethodInvocation binary = _helper.forest.createMethodInvocation(
         offset,
         _helper.createVariableGet(read, fileOffset),
@@ -4134,11 +4010,23 @@
   ///
   final bool inFieldInitializer;
 
+  /// `true` if this access is directly in a field initializer of a late field.
+  ///
+  /// For instance in `<init>` in
+  ///
+  ///    late var foo = <init>;
+  ///    class Class {
+  ///      late var bar = <init>;
+  ///      Class() : bar = 42;
+  ///    }
+  ///
+  final bool inLateFieldInitializer;
+
   /// `true` if this subexpression represents a `super` prefix.
   final bool isSuper;
 
   ThisAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.isInitializer, this.inFieldInitializer,
+      this.isInitializer, this.inFieldInitializer, this.inLateFieldInitializer,
       {this.isSuper: false})
       : super(helper, token);
 
@@ -4151,7 +4039,7 @@
 
   Expression buildSimpleRead() {
     if (!isSuper) {
-      if (inFieldInitializer) {
+      if (inFieldInitializer && !inLateFieldInitializer) {
         return buildFieldInitializerError(null);
       } else {
         return _forest.createThisExpression(fileOffset);
@@ -4188,28 +4076,23 @@
       }
       return buildConstructorInitializer(offset, name, arguments);
     }
-    if (inFieldInitializer && !isInitializer) {
+    if (inFieldInitializer && !inLateFieldInitializer && !isInitializer) {
       return buildFieldInitializerError(null);
     }
-    Member getter = _helper.lookupInstanceMember(name, isSuper: isSuper);
     if (send is SendAccessGenerator) {
       // Notice that 'this' or 'super' can't be null. So we can ignore the
       // value of [isNullAware].
-      if (getter == null) {
-        _helper.warnUnresolvedMethod(name, offsetForToken(send.token),
-            isSuper: isSuper);
-      }
       return _helper.buildMethodInvocation(
           _forest.createThisExpression(fileOffset),
           name,
           send.arguments,
           offsetForToken(send.token),
-          isSuper: isSuper,
-          interfaceTarget: getter);
+          isSuper: isSuper);
     } else {
-      Member setter =
-          _helper.lookupInstanceMember(name, isSuper: isSuper, isSetter: true);
       if (isSuper) {
+        Member getter = _helper.lookupInstanceMember(name, isSuper: isSuper);
+        Member setter = _helper.lookupInstanceMember(name,
+            isSuper: isSuper, isSetter: true);
         return new SuperPropertyAccessGenerator(
             _helper,
             // TODO(ahe): This is not the 'super' token.
@@ -4222,9 +4105,7 @@
             _helper,
             // TODO(ahe): This is not the 'this' token.
             send.token,
-            name,
-            getter,
-            setter);
+            name);
       }
     }
   }
@@ -4336,6 +4217,8 @@
     sink.write(isInitializer);
     sink.write(", inFieldInitializer: ");
     sink.write(inFieldInitializer);
+    sink.write(", inLateFieldInitializer: ");
+    sink.write(inLateFieldInitializer);
     sink.write(", isSuper: ");
     sink.write(isSuper);
   }
@@ -4503,8 +4386,8 @@
     if (receiver is Generator) {
       return receiver.buildPropertyAccess(this, operatorOffset, isNullAware);
     }
-    return PropertyAccessGenerator.make(_helper, token,
-        _helper.toValue(receiver), name, null, null, isNullAware);
+    return PropertyAccessGenerator.make(
+        _helper, token, _helper.toValue(receiver), name, isNullAware);
   }
 
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
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 b327ff7..9930e0b 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
@@ -4,7 +4,7 @@
 
 library fasta.expression_generator_helper;
 
-import '../../scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import '../builder/builder.dart';
 import '../builder/library_builder.dart';
@@ -22,8 +22,6 @@
 
 import '../type_inference/inference_helper.dart' show InferenceHelper;
 
-import '../type_inference/type_promotion.dart' show TypePromoter;
-
 import 'constness.dart' show Constness;
 
 import 'forest.dart' show Forest;
@@ -48,10 +46,6 @@
 abstract class ExpressionGeneratorHelper implements InferenceHelper {
   LibraryBuilder get libraryBuilder;
 
-  TypePromoter get typePromoter;
-
-  int get functionNestingLevel;
-
   ConstantContext get constantContext;
 
   Forest get forest;
@@ -158,4 +152,9 @@
   /// Creates a [VariableGet] of the [variable] using [charOffset] as the file
   /// offset of the created node.
   Expression createVariableGet(VariableDeclaration variable, int charOffset);
+
+  /// Registers that [variable] is assigned to.
+  ///
+  /// This is needed for type promotion.
+  void registerVariableAssignment(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 c551700..6d4a8a5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -383,7 +383,6 @@
       int fileOffset,
       List<VariableDeclaration> variables,
       Expression condition,
-      Statement conditionStatement,
       List<Expression> updaters,
       Statement body) {
     assert(fileOffset != null);
@@ -476,22 +475,16 @@
 
   bool isThrow(Object o) => o is Throw;
 
-  /// Return a representation of a try statement at the given [fileOffset].
-  /// The statement is introduced by the given [body]. If catch clauses were
-  /// included, then the [catchClauses] will represent them, otherwise it will
-  /// be `null`. Similarly, if a finally block was included, then the
-  /// [finallyBlock] will be non-`null`, otherwise both will be `null`.
-  Statement createTryStatement(int fileOffset, Statement body,
-      List<Catch> catchClauses, Statement finallyBlock) {
+  TryCatch createTryCatch(
+      int fileOffset, Statement tryBlock, List<Catch> catchBlocks) {
     assert(fileOffset != null);
-    Statement result = body;
-    if (catchClauses != null) {
-      result = new TryCatch(result, catchClauses)..fileOffset = fileOffset;
-    }
-    if (finallyBlock != null) {
-      result = new TryFinally(result, finallyBlock)..fileOffset = fileOffset;
-    }
-    return result;
+    return new TryCatch(tryBlock, catchBlocks)..fileOffset = fileOffset;
+  }
+
+  TryFinally createTryFinally(
+      int fileOffset, Statement tryBlock, Statement finallyBlock) {
+    assert(fileOffset != null);
+    return new TryFinally(tryBlock, finallyBlock)..fileOffset = fileOffset;
   }
 
   _VariablesDeclaration variablesDeclaration(
@@ -665,6 +658,13 @@
     return new NullCheck(expression)..fileOffset = fileOffset;
   }
 
+  PropertyGet createPropertyGet(int fileOffset, Expression receiver, Name name,
+      {Member interfaceTarget}) {
+    assert(fileOffset != null);
+    return new PropertyGet(receiver, name, interfaceTarget)
+      ..fileOffset = fileOffset;
+  }
+
   PropertySet createPropertySet(
       int fileOffset, Expression receiver, Name name, Expression value,
       {Member interfaceTarget, bool forEffect, bool readOnlyReceiver: false}) {
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 d1eb056..edd980c 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
@@ -4,11 +4,11 @@
 
 library fasta.implicit_type;
 
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
 import 'package:kernel/ast.dart'
     show DartType, DartTypeVisitor, DartTypeVisitor1, Nullability, Visitor;
 
-import '../../scanner/token.dart' show Token;
-
 import '../builder/member_builder.dart';
 
 import '../problems.dart' show unsupported;
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 57503845..b411490 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -9,7 +9,7 @@
         ExpressionVisitor1<ExpressionInferenceResult, DartType>,
         StatementVisitor<void>,
         InitializerVisitor<void> {
-  final ShadowTypeInferrer inferrer;
+  final TypeInferrerImpl inferrer;
 
   Class mapEntryClass;
 
@@ -31,7 +31,7 @@
       Expression node, DartType typeContext) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
         inferrer.helper.uri);
-    return const ExpressionInferenceResult(const InvalidType());
+    return new ExpressionInferenceResult(const InvalidType(), node);
   }
 
   @override
@@ -43,6 +43,8 @@
           return visitCascade(node, typeContext);
         case InternalExpressionKind.CompoundExtensionIndexSet:
           return visitCompoundExtensionIndexSet(node, typeContext);
+        case InternalExpressionKind.CompoundExtensionSet:
+          return visitCompoundExtensionSet(node, typeContext);
         case InternalExpressionKind.CompoundIndexSet:
           return visitCompoundIndexSet(node, typeContext);
         case InternalExpressionKind.CompoundPropertySet:
@@ -58,7 +60,7 @@
         case InternalExpressionKind.ExtensionSet:
           return visitExtensionSet(node, typeContext);
         case InternalExpressionKind.IfNull:
-          return visitIfNull(node, typeContext);
+          return visitIfNullExpression(node, typeContext);
         case InternalExpressionKind.IfNullExtensionIndexSet:
           return visitIfNullExtensionIndexSet(node, typeContext);
         case InternalExpressionKind.IfNullIndexSet:
@@ -212,23 +214,24 @@
       InvalidExpression node, DartType typeContext) {
     // TODO(johnniwinther): The inferred type should be an InvalidType. Using
     // BottomType leads to cascading errors so we use DynamicType for now.
-    return const ExpressionInferenceResult(const DynamicType());
+    return new ExpressionInferenceResult(const DynamicType(), node);
   }
 
   @override
   ExpressionInferenceResult visitIntLiteral(
       IntLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.intRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.intRawType(inferrer.library.nonNullable), node);
   }
 
   @override
   ExpressionInferenceResult visitAsExpression(
       AsExpression node, DartType typeContext) {
-    inferrer.inferExpression(
+    ExpressionInferenceResult operandResult = inferrer.inferExpression(
         node.operand, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: true);
-    return new ExpressionInferenceResult(node.type);
+    node.operand = operandResult.expression..parent = node;
+    return new ExpressionInferenceResult(node.type, node);
   }
 
   @override
@@ -240,17 +243,22 @@
   void visitAssertStatement(AssertStatement node) {
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
-            isVoidAllowed: true)
-        .inferredType;
-    inferrer.ensureAssignable(
-        expectedType, conditionType, node.condition, node.condition.fileOffset);
+    inferrer.flowAnalysis.assert_begin();
+    ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+        node.condition, expectedType, !inferrer.isTopLevel,
+        isVoidAllowed: true);
+
+    Expression condition =
+        inferrer.ensureAssignableResult(expectedType, conditionResult);
+    node.condition = condition..parent = node;
+    inferrer.flowAnalysis.assert_afterCondition(node.condition);
     if (node.message != null) {
-      inferrer.inferExpression(
+      ExpressionInferenceResult messageResult = inferrer.inferExpression(
           node.message, const UnknownType(), !inferrer.isTopLevel,
           isVoidAllowed: true);
+      node.message = messageResult.expression..parent = node;
     }
+    inferrer.flowAnalysis.assert_end();
   }
 
   @override
@@ -259,16 +267,17 @@
     if (!inferrer.typeSchemaEnvironment.isEmptyContext(typeContext)) {
       typeContext = inferrer.wrapFutureOrType(typeContext);
     }
-    DartType operandType = inferrer
-        .inferExpression(node.operand, typeContext, true, isVoidAllowed: true)
-        .inferredType;
+    ExpressionInferenceResult operandResult = inferrer
+        .inferExpression(node.operand, typeContext, true, isVoidAllowed: true);
     DartType inferredType =
-        inferrer.typeSchemaEnvironment.unfutureType(operandType);
-    return new ExpressionInferenceResult(inferredType);
+        inferrer.typeSchemaEnvironment.unfutureType(operandResult.inferredType);
+    node.operand = operandResult.expression..parent = node;
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
   void visitBlock(Block node) {
+    inferrer.registerIfUnreachableForTesting(node);
     for (Statement statement in node.statements) {
       inferrer.inferStatement(statement);
     }
@@ -277,8 +286,9 @@
   @override
   ExpressionInferenceResult visitBoolLiteral(
       BoolLiteral node, DartType typeContext) {
+    inferrer.flowAnalysis.booleanLiteral(node, node.value);
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), node);
   }
 
   @override
@@ -288,15 +298,25 @@
 
   ExpressionInferenceResult visitCascade(Cascade node, DartType typeContext) {
     ExpressionInferenceResult result = inferrer.inferExpression(
-        node.expression, typeContext, true,
+        node.variable.initializer, typeContext, true,
         isVoidAllowed: false);
+    node.variable.initializer = result.expression..parent = node.variable;
     node.variable.type = result.inferredType;
-    for (Expression judgment in node.cascades) {
-      inferrer.inferExpression(
-          judgment, const UnknownType(), !inferrer.isTopLevel,
-          isVoidAllowed: true);
+    List<ExpressionInferenceResult> expressionResults =
+        <ExpressionInferenceResult>[];
+    for (Expression expression in node.expressions) {
+      expressionResults.add(inferrer.inferExpression(
+          expression, const UnknownType(), !inferrer.isTopLevel,
+          isVoidAllowed: true));
     }
-    Expression replacement = node.replace();
+    Expression replacement = createVariableGet(node.variable);
+    for (int index = expressionResults.length - 1; index >= 0; index--) {
+      replacement = createLet(
+          createVariable(expressionResults[index].expression, const VoidType()),
+          replacement);
+    }
+    replacement = new Let(node.variable, replacement)
+      ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(result.inferredType, replacement);
   }
 
@@ -305,22 +325,33 @@
       ConditionalExpression node, DartType typeContext) {
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
-            isVoidAllowed: true)
-        .inferredType;
-    inferrer.ensureAssignable(
-        expectedType, conditionType, node.condition, node.condition.fileOffset);
-    DartType thenType = inferrer
-        .inferExpression(node.then, typeContext, true, isVoidAllowed: true)
-        .inferredType;
-    DartType otherwiseType = inferrer
-        .inferExpression(node.otherwise, typeContext, true, isVoidAllowed: true)
-        .inferredType;
+    ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+        node.condition, expectedType, !inferrer.isTopLevel,
+        isVoidAllowed: true);
+    Expression condition =
+        inferrer.ensureAssignableResult(expectedType, conditionResult);
+    node.condition = condition..parent = node;
+    inferrer.flowAnalysis.conditional_thenBegin(node.condition);
+    bool isThenReachable = inferrer.flowAnalysis.isReachable;
+    ExpressionInferenceResult thenResult = inferrer
+        .inferExpression(node.then, typeContext, true, isVoidAllowed: true);
+    node.then = thenResult.expression..parent = node;
+    inferrer.registerIfUnreachableForTesting(node.then,
+        isReachable: isThenReachable);
+    inferrer.flowAnalysis.conditional_elseBegin(node.then);
+    bool isOtherwiseReachable = inferrer.flowAnalysis.isReachable;
+    ExpressionInferenceResult otherwiseResult = inferrer.inferExpression(
+        node.otherwise, typeContext, true,
+        isVoidAllowed: true);
+    node.otherwise = otherwiseResult.expression..parent = node;
+    inferrer.registerIfUnreachableForTesting(node.otherwise,
+        isReachable: isOtherwiseReachable);
+    inferrer.flowAnalysis.conditional_end(node.condition, node.otherwise);
     DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(thenType, otherwiseType);
+        .getStandardUpperBound(
+            thenResult.inferredType, otherwiseResult.inferredType);
     node.staticType = inferredType;
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -378,7 +409,7 @@
             inferred: true);
       }
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -402,10 +433,7 @@
           inferrer.helper.uri,
           typeArgumentsInfo);
     }
-    node.replaceWith(replacement);
-    inferredType =
-        inferrer.instantiateTearOff(inferredType, typeContext, replacement);
-    return new ExpressionInferenceResult(inferredType);
+    return inferrer.instantiateTearOff(inferredType, typeContext, replacement);
   }
 
   ExpressionInferenceResult visitExtensionSet(
@@ -421,8 +449,8 @@
     DartType receiverType = inferrer.getExtensionReceiverType(
         node.extension, extensionTypeArguments);
 
-    inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
-        node.receiver, node.receiver.fileOffset);
+    Expression receiver =
+        inferrer.ensureAssignableResult(receiverType, receiverResult);
 
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.target, null, ProcedureKind.Setter, extensionTypeArguments);
@@ -433,25 +461,21 @@
     ExpressionInferenceResult valueResult = inferrer.inferExpression(
         node.value, const UnknownType(), true,
         isVoidAllowed: false);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
-    Expression value;
     VariableDeclaration valueVariable;
     if (node.forEffect) {
-      value = node.value;
+      // No need for value variable.
     } else {
-      valueVariable = createVariable(node.value, valueResult.inferredType);
+      valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
     }
 
     VariableDeclaration receiverVariable;
-    Expression receiver;
     if (node.forEffect || node.readOnlyReceiver) {
-      receiver = node.receiver;
+      // No need for receiver variable.
     } else {
-      receiverVariable =
-          createVariable(node.receiver, receiverResult.inferredType);
+      receiverVariable = createVariable(receiver, receiverResult.inferredType);
       receiver = createVariableGet(receiverVariable);
     }
     Expression assignment = new StaticInvocation(
@@ -477,10 +501,116 @@
       }
     }
     replacement.fileOffset = node.fileOffset;
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(valueResult.inferredType, replacement);
   }
 
+  ExpressionInferenceResult visitCompoundExtensionSet(
+      CompoundExtensionSet node, DartType typeContext) {
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+
+    List<DartType> extensionTypeArguments =
+        inferrer.computeExtensionTypeArgument(node.extension,
+            node.explicitTypeArguments, receiverResult.inferredType);
+
+    DartType receiverType = inferrer.getExtensionReceiverType(
+        node.extension, extensionTypeArguments);
+
+    Expression receiver =
+        inferrer.ensureAssignableResult(receiverType, receiverResult);
+
+    VariableDeclaration receiverVariable;
+    Expression readReceiver;
+    Expression writeReceiver;
+    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+      readReceiver = receiver;
+      writeReceiver = receiver.accept<TreeNode>(new CloneVisitor());
+    } else {
+      receiverVariable = createVariable(receiver, receiverType);
+      readReceiver = createVariableGet(receiverVariable);
+      writeReceiver = createVariableGet(receiverVariable);
+    }
+
+    ObjectAccessTarget readTarget = node.getter == null
+        ? const ObjectAccessTarget.missing()
+        : new ExtensionAccessTarget(
+            node.getter, null, ProcedureKind.Getter, extensionTypeArguments);
+
+    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+
+    Expression read;
+    if (readTarget.isMissing) {
+      read = inferrer.createMissingPropertyGet(
+          node.readOffset, readReceiver, readType, node.propertyName);
+    } else {
+      assert(readTarget.isExtensionMember);
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            readReceiver,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.readOffset)
+        ..fileOffset = node.readOffset;
+    }
+
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, read, readType, node.binaryName, node.rhs);
+    Expression binary = binaryResult.expression;
+    DartType binaryType = binaryResult.inferredType;
+
+    ObjectAccessTarget writeTarget = node.setter == null
+        ? const ObjectAccessTarget.missing()
+        : new ExtensionAccessTarget(
+            node.setter, null, ProcedureKind.Setter, extensionTypeArguments);
+
+    DartType valueType = inferrer.getSetterType(writeTarget, receiverType);
+
+    Expression value = inferrer.ensureAssignable(valueType, binaryType, binary,
+        isVoidAllowed: true);
+
+    VariableDeclaration valueVariable;
+    if (node.forEffect) {
+      // No need for value variable.
+    } else {
+      valueVariable = createVariable(value, valueType);
+      value = createVariableGet(valueVariable);
+    }
+
+    Expression write;
+    if (writeTarget.isMissing) {
+      write = inferrer.createMissingPropertySet(
+          node.writeOffset, writeReceiver, readType, node.propertyName, value);
+    } else {
+      assert(writeTarget.isExtensionMember);
+      write = new StaticInvocation(
+          writeTarget.member,
+          new Arguments(<Expression>[
+            writeReceiver,
+            value,
+          ], types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = node.writeOffset)
+        ..fileOffset = node.writeOffset;
+    }
+
+    Expression replacement;
+    if (node.forEffect) {
+      assert(valueVariable == null);
+      replacement = write;
+    } else {
+      assert(valueVariable != null);
+      VariableDeclaration writeVariable =
+          createVariable(write, const VoidType());
+      replacement = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
+    }
+    if (receiverVariable != null) {
+      replacement = createLet(receiverVariable, replacement);
+    }
+    replacement.fileOffset = node.fileOffset;
+    return new ExpressionInferenceResult(valueType, replacement);
+  }
+
   ExpressionInferenceResult visitDeferredCheck(
       DeferredCheck node, DartType typeContext) {
     // Since the variable is not used in the body we don't need to type infer
@@ -488,27 +618,32 @@
     ExpressionInferenceResult result = inferrer.inferExpression(
         node.expression, typeContext, true,
         isVoidAllowed: true);
-    Expression replacement = node.replace();
+
+    Expression replacement = new Let(node.variable, result.expression)
+      ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(result.inferredType, replacement);
   }
 
   @override
   void visitDoStatement(DoStatement node) {
+    inferrer.flowAnalysis.doStatement_bodyBegin(node);
     inferrer.inferStatement(node.body);
+    inferrer.flowAnalysis.doStatement_conditionBegin();
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType conditionType = inferrer
-        .inferExpression(node.condition, boolType, !inferrer.isTopLevel,
-            isVoidAllowed: true)
-        .inferredType;
-    inferrer.ensureAssignable(
-        boolType, conditionType, node.condition, node.condition.fileOffset);
+    ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+        node.condition, boolType, !inferrer.isTopLevel,
+        isVoidAllowed: true);
+    Expression condition =
+        inferrer.ensureAssignableResult(boolType, conditionResult);
+    node.condition = condition..parent = node;
+    inferrer.flowAnalysis.doStatement_end(condition);
   }
 
   ExpressionInferenceResult visitDoubleLiteral(
       DoubleLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable), node);
   }
 
   @override
@@ -518,9 +653,10 @@
 
   @override
   void visitExpressionStatement(ExpressionStatement node) {
-    inferrer.inferExpression(
+    ExpressionInferenceResult result = inferrer.inferExpression(
         node.expression, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: true);
+    node.expression = result.expression..parent = node;
   }
 
   ExpressionInferenceResult visitFactoryConstructorInvocationJudgment(
@@ -540,19 +676,20 @@
             inferred: true);
       }
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
   void visitFieldInitializer(FieldInitializer node) {
     ExpressionInferenceResult initializerResult =
         inferrer.inferExpression(node.value, node.field.type, true);
-    DartType initializerType = initializerResult.inferredType;
-    inferrer.ensureAssignable(
-        node.field.type, initializerType, node.value, node.fileOffset);
+    Expression initializer = inferrer.ensureAssignableResult(
+        node.field.type, initializerResult,
+        fileOffset: node.fileOffset);
+    node.value = initializer..parent = node;
   }
 
-  void handleForInDeclaringVariable(
+  ForInResult handleForInDeclaringVariable(
       VariableDeclaration variable, Expression iterable, Statement body,
       {bool isAsync: false}) {
     DartType elementType;
@@ -565,9 +702,10 @@
       elementType = variable.type;
     }
 
-    DartType inferredType = inferForInIterable(
+    ExpressionInferenceResult iterableResult = inferForInIterable(
         iterable, elementType, typeNeeded || typeChecksNeeded,
         isAsync: isAsync);
+    DartType inferredType = iterableResult.inferredType;
     if (typeNeeded) {
       inferrer.instrumentation?.record(
           inferrer.uriForInstrumentation,
@@ -577,35 +715,39 @@
       variable.type = inferredType;
     }
 
-    if (body != null) inferrer.inferStatement(body);
+    if (body != null) {
+      inferrer.flowAnalysis
+          .forEach_bodyBegin(body?.parent, variable, variable.type);
+      inferrer.inferStatement(body);
+      inferrer.flowAnalysis.forEach_end();
+    }
 
-    VariableDeclaration tempVar =
+    VariableDeclaration tempVariable =
         new VariableDeclaration(null, type: inferredType, isFinal: true);
-    VariableGet variableGet = new VariableGet(tempVar)
+    VariableGet variableGet = new VariableGet(tempVariable)
       ..fileOffset = variable.fileOffset;
     TreeNode parent = variable.parent;
     Expression implicitDowncast = inferrer.ensureAssignable(
-        variable.type, inferredType, variableGet, parent.fileOffset,
+        variable.type, inferredType, variableGet,
+        fileOffset: parent.fileOffset,
         template: templateForInLoopElementTypeNotAssignable);
-    if (implicitDowncast != null) {
-      parent.replaceChild(variable, tempVar);
+    if (!identical(implicitDowncast, variableGet)) {
       variable.initializer = implicitDowncast..parent = variable;
       if (body == null) {
-        if (parent is ForInElement) {
-          parent.prologue = variable;
-        } else if (parent is ForInMapEntry) {
-          parent.prologue = variable;
-        } else {
-          unhandled("${parent.runtimeType}", "handleForInDeclaringVariable",
-              variable.fileOffset, variable.location.file);
-        }
+        assert(
+            parent is ForInElement || parent is ForInMapEntry,
+            "Unexpected missing for-in body for "
+            "$parent (${parent.runtimeType}).");
+        body = variable;
       } else {
-        parent.replaceChild(body, combineStatements(variable, body));
+        body = combineStatements(variable, body);
       }
+      variable = tempVariable;
     }
+    return new ForInResult(variable, iterableResult.expression, body);
   }
 
-  DartType inferForInIterable(
+  ExpressionInferenceResult inferForInIterable(
       Expression iterable, DartType elementType, bool typeNeeded,
       {bool isAsync: false}) {
     Class iterableClass = isAsync
@@ -615,16 +757,13 @@
     ExpressionInferenceResult iterableResult = inferrer
         .inferExpression(iterable, context, typeNeeded, isVoidAllowed: false);
     DartType iterableType = iterableResult.inferredType;
-    if (iterableResult.replacement != null) {
-      iterable = iterableResult.replacement;
-    }
+    iterable = iterableResult.expression;
     DartType inferredExpressionType =
         inferrer.resolveTypeParameter(iterableType);
-    inferrer.ensureAssignable(
+    iterable = inferrer.ensureAssignable(
         inferrer.wrapType(const DynamicType(), iterableClass),
         inferredExpressionType,
         iterable,
-        iterable.fileOffset,
         template: templateForInLoopTypeNotIterable);
     DartType inferredType;
     if (typeNeeded) {
@@ -637,10 +776,10 @@
         }
       }
     }
-    return inferredType;
+    return new ExpressionInferenceResult(inferredType, iterable);
   }
 
-  void handleForInWithoutVariable(
+  ForInResult handleForInWithoutVariable(
       VariableDeclaration variable, Expression iterable, Statement body,
       {bool isAsync: false}) {
     DartType elementType;
@@ -652,28 +791,77 @@
     ExpressionStatement syntheticStatement =
         body is Block ? body.statements.first : body;
     Expression statementExpression = syntheticStatement.expression;
+    // TODO(johnniwinther): Refactor handling of synthetic assignment to avoid
+    // case handling here.
     Expression syntheticAssignment = statementExpression;
+    VariableSet syntheticVariableSet;
+    PropertySet syntheticPropertySet;
+    SuperPropertySet syntheticSuperPropertySet;
+    StaticSet syntheticStaticSet;
     if (syntheticAssignment is VariableSet) {
-      syntheticWriteType = elementType = syntheticAssignment.variable.type;
-      rhs = syntheticAssignment.value;
+      syntheticVariableSet = syntheticAssignment;
+      syntheticWriteType = elementType = syntheticVariableSet.variable.type;
+      rhs = syntheticVariableSet.value;
       // This expression is fully handled in this method so we should not
       // visit the synthetic statement.
       skipStatement = true;
-    } else if (syntheticAssignment is PropertySet ||
-        syntheticAssignment is SuperPropertySet) {
-      DartType receiverType = inferrer.thisType;
-      ObjectAccessTarget writeTarget =
-          inferrer.findPropertySetMember(receiverType, syntheticAssignment);
+    } else if (syntheticAssignment is PropertySet) {
+      syntheticPropertySet = syntheticAssignment;
+      ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+          syntheticPropertySet.receiver, const UnknownType(), true);
+      syntheticPropertySet.receiver = receiverResult.expression
+        ..parent = syntheticPropertySet;
+      DartType receiverType = receiverResult.inferredType;
+      ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+          receiverType,
+          syntheticPropertySet.name,
+          syntheticPropertySet.fileOffset,
+          setter: true,
+          instrumented: true,
+          includeExtensionMethods: true);
       syntheticWriteType =
           elementType = inferrer.getSetterType(writeTarget, receiverType);
-      if (syntheticAssignment is PropertySet) {
-        rhs = syntheticAssignment.value;
-      } else if (syntheticAssignment is SuperPropertySet) {
-        rhs = syntheticAssignment.value;
+      Expression error = inferrer.reportMissingInterfaceMember(
+          writeTarget,
+          receiverType,
+          syntheticPropertySet.name,
+          syntheticPropertySet.fileOffset,
+          templateUndefinedSetter);
+      if (error != null) {
+        rhs = error;
+      } else {
+        if (writeTarget.isInstanceMember) {
+          if (inferrer.instrumentation != null &&
+              receiverType == const DynamicType()) {
+            inferrer.instrumentation.record(
+                inferrer.uriForInstrumentation,
+                syntheticPropertySet.fileOffset,
+                'target',
+                new InstrumentationValueForMember(writeTarget.member));
+          }
+          syntheticPropertySet.interfaceTarget = writeTarget.member;
+        }
+        rhs = syntheticPropertySet.value;
       }
+    } else if (syntheticAssignment is SuperPropertySet) {
+      syntheticSuperPropertySet = syntheticAssignment;
+      DartType receiverType = inferrer.thisType;
+      ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+          receiverType,
+          syntheticSuperPropertySet.name,
+          syntheticSuperPropertySet.fileOffset,
+          setter: true,
+          instrumented: true);
+      if (writeTarget.isInstanceMember) {
+        syntheticSuperPropertySet.interfaceTarget = writeTarget.member;
+      }
+      syntheticWriteType =
+          elementType = inferrer.getSetterType(writeTarget, receiverType);
+      rhs = syntheticSuperPropertySet.value;
     } else if (syntheticAssignment is StaticSet) {
-      syntheticWriteType = elementType = syntheticAssignment.target.setterType;
-      rhs = syntheticAssignment.value;
+      syntheticStaticSet = syntheticAssignment;
+      syntheticWriteType = elementType = syntheticStaticSet.target.setterType;
+      rhs = syntheticStaticSet.value;
     } else if (syntheticAssignment is InvalidExpression) {
       elementType = const UnknownType();
     } else {
@@ -684,13 +872,16 @@
           inferrer.helper.uri);
     }
 
-    DartType inferredType = inferForInIterable(
+    ExpressionInferenceResult iterableResult = inferForInIterable(
         iterable, elementType, typeChecksNeeded,
         isAsync: isAsync);
+    DartType inferredType = iterableResult.inferredType;
     if (typeChecksNeeded) {
       variable.type = inferredType;
     }
 
+    inferrer.flowAnalysis
+        .forEach_bodyBegin(body.parent, variable, variable.type);
     if (body is Block) {
       for (Statement statement in body.statements) {
         if (!skipStatement || statement != syntheticStatement) {
@@ -702,27 +893,44 @@
         inferrer.inferStatement(body);
       }
     }
+    inferrer.flowAnalysis.forEach_end();
 
     if (syntheticWriteType != null) {
-      inferrer.ensureAssignable(
+      rhs = inferrer.ensureAssignable(
           greatestClosure(inferrer.coreTypes, syntheticWriteType),
           variable.type,
           rhs,
-          rhs.fileOffset,
           template: templateForInLoopElementTypeNotAssignable,
           isVoidAllowed: true);
+      if (syntheticVariableSet != null) {
+        syntheticVariableSet.value = rhs..parent = syntheticVariableSet;
+      } else if (syntheticPropertySet != null) {
+        syntheticPropertySet.value = rhs..parent = syntheticPropertySet;
+      } else if (syntheticSuperPropertySet != null) {
+        syntheticSuperPropertySet.value = rhs
+          ..parent = syntheticSuperPropertySet;
+      } else if (syntheticStaticSet != null) {
+        syntheticStaticSet.value = rhs..parent = syntheticStaticSet;
+      }
     }
+    return new ForInResult(variable, iterableResult.expression, body);
   }
 
   @override
   void visitForInStatement(ForInStatement node) {
+    ForInResult result;
     if (node.variable.name == null) {
-      handleForInWithoutVariable(node.variable, node.iterable, node.body,
+      result = handleForInWithoutVariable(
+          node.variable, node.iterable, node.body,
           isAsync: node.isAsync);
     } else {
-      handleForInDeclaringVariable(node.variable, node.iterable, node.body,
+      result = handleForInDeclaringVariable(
+          node.variable, node.iterable, node.body,
           isAsync: node.isAsync);
     }
+    node.variable = result.variable..parent = node;
+    node.iterable = result.iterable..parent = node;
+    node.body = result.body..parent = node;
   }
 
   @override
@@ -733,28 +941,35 @@
           ExpressionInferenceResult result = inferrer.inferExpression(
               variable.initializer, const UnknownType(), true,
               isVoidAllowed: true);
+          variable.initializer = result.expression..parent = variable;
           variable.type = result.inferredType;
         }
       } else {
         inferrer.inferStatement(variable);
       }
     }
+    inferrer.flowAnalysis.for_conditionBegin(node);
     if (node.condition != null) {
       InterfaceType expectedType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-      DartType conditionType = inferrer
-          .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
-              isVoidAllowed: true)
-          .inferredType;
-      inferrer.ensureAssignable(expectedType, conditionType, node.condition,
-          node.condition.fileOffset);
-    }
-    for (Expression update in node.updates) {
-      inferrer.inferExpression(
-          update, const UnknownType(), !inferrer.isTopLevel,
+      ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+          node.condition, expectedType, !inferrer.isTopLevel,
           isVoidAllowed: true);
+      Expression condition =
+          inferrer.ensureAssignableResult(expectedType, conditionResult);
+      node.condition = condition..parent = node;
     }
+
+    inferrer.flowAnalysis.for_bodyBegin(node.body, node.condition);
     inferrer.inferStatement(node.body);
+    inferrer.flowAnalysis.for_updaterBegin();
+    for (int index = 0; index < node.updates.length; index++) {
+      ExpressionInferenceResult updateResult = inferrer.inferExpression(
+          node.updates[index], const UnknownType(), !inferrer.isTopLevel,
+          isVoidAllowed: true);
+      node.updates[index] = updateResult.expression..parent = node;
+    }
+    inferrer.flowAnalysis.for_end();
   }
 
   DartType visitFunctionNode(FunctionNode node, DartType typeContext,
@@ -765,7 +980,8 @@
 
   @override
   void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
-    inferrer.inferMetadataKeepingHelper(node.variable.annotations);
+    inferrer.inferMetadataKeepingHelper(
+        node.variable, node.variable.annotations);
     DartType returnContext =
         node._hasImplicitReturnType ? null : node.function.returnType;
     DartType inferredType =
@@ -778,7 +994,7 @@
       FunctionExpression node, DartType typeContext) {
     DartType inferredType =
         visitFunctionNode(node.function, typeContext, null, node.fileOffset);
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   void visitInvalidSuperInitializerJudgment(
@@ -796,43 +1012,44 @@
         skipTypeArgumentInference: true);
   }
 
-  ExpressionInferenceResult visitIfNull(
+  ExpressionInferenceResult visitIfNullExpression(
       IfNullExpression node, DartType typeContext) {
     // To infer `e0 ?? e1` in context K:
     // - Infer e0 in context K to get T0
-    DartType lhsType = inferrer
-        .inferExpression(node.left, typeContext, true, isVoidAllowed: false)
-        .inferredType;
+    ExpressionInferenceResult lhsResult = inferrer
+        .inferExpression(node.left, typeContext, true, isVoidAllowed: false);
 
     Member equalsMember = inferrer
-        .findInterfaceMember(lhsType, equalsName, node.fileOffset)
+        .findInterfaceMember(
+            lhsResult.inferredType, equalsName, node.fileOffset)
         .member;
 
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
-    DartType rhsType;
+    ExpressionInferenceResult rhsResult;
     if (typeContext is UnknownType) {
-      rhsType = inferrer
-          .inferExpression(node.right, lhsType, true, isVoidAllowed: true)
-          .inferredType;
+      rhsResult = inferrer.inferExpression(
+          node.right, lhsResult.inferredType, true,
+          isVoidAllowed: true);
     } else {
-      rhsType = inferrer
-          .inferExpression(node.right, typeContext, true, isVoidAllowed: true)
-          .inferredType;
+      rhsResult = inferrer.inferExpression(node.right, typeContext, true,
+          isVoidAllowed: true);
     }
     // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
     //   UP(t0, t1)
     // - Then the inferred type is T.
-    DartType inferredType =
-        inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType);
-    VariableDeclaration variable = createVariable(node.left, lhsType);
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .getStandardUpperBound(lhsResult.inferredType, rhsResult.inferredType);
+    VariableDeclaration variable =
+        createVariable(lhsResult.expression, lhsResult.inferredType);
     MethodInvocation equalsNull = createEqualsNull(
-        node.left.fileOffset, createVariableGet(variable), equalsMember);
-    ConditionalExpression conditional = new ConditionalExpression(
-        equalsNull, node.right, createVariableGet(variable), inferredType);
+        lhsResult.expression.fileOffset,
+        createVariableGet(variable),
+        equalsMember);
+    ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+        rhsResult.expression, createVariableGet(variable), inferredType);
     Expression replacement = new Let(variable, conditional)
       ..fileOffset = node.fileOffset;
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -840,16 +1057,19 @@
   void visitIfStatement(IfStatement node) {
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
-            isVoidAllowed: true)
-        .inferredType;
-    inferrer.ensureAssignable(
-        expectedType, conditionType, node.condition, node.condition.fileOffset);
+    ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+        node.condition, expectedType, !inferrer.isTopLevel,
+        isVoidAllowed: true);
+    Expression condition =
+        inferrer.ensureAssignableResult(expectedType, conditionResult);
+    node.condition = condition..parent = node;
+    inferrer.flowAnalysis.ifStatement_thenBegin(condition);
     inferrer.inferStatement(node.then);
     if (node.otherwise != null) {
+      inferrer.flowAnalysis.ifStatement_elseBegin();
       inferrer.inferStatement(node.otherwise);
     }
+    inferrer.flowAnalysis.ifStatement_end(node.otherwise != null);
   }
 
   ExpressionInferenceResult visitIntJudgment(
@@ -857,23 +1077,21 @@
     if (inferrer.isDoubleContext(typeContext)) {
       double doubleValue = node.asDouble();
       if (doubleValue != null) {
-        node.parent.replaceChild(
-            node, new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
+        Expression replacement = new DoubleLiteral(doubleValue)
+          ..fileOffset = node.fileOffset;
         DartType inferredType =
             inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
-        return new ExpressionInferenceResult(inferredType);
+        return new ExpressionInferenceResult(inferredType, replacement);
       }
     }
     Expression error = checkWebIntLiteralsErrorIfUnexact(
         inferrer, node.value, node.literal, node.fileOffset);
-
     if (error != null) {
-      node.parent.replaceChild(node, error);
-      return const ExpressionInferenceResult(const BottomType());
+      return new ExpressionInferenceResult(const DynamicType(), error);
     }
     DartType inferredType =
         inferrer.coreTypes.intRawType(inferrer.library.nonNullable);
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   ExpressionInferenceResult visitShadowLargeIntLiteral(
@@ -881,11 +1099,11 @@
     if (inferrer.isDoubleContext(typeContext)) {
       double doubleValue = node.asDouble();
       if (doubleValue != null) {
-        node.parent.replaceChild(
-            node, new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
+        Expression replacement = new DoubleLiteral(doubleValue)
+          ..fileOffset = node.fileOffset;
         DartType inferredType =
             inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
-        return new ExpressionInferenceResult(inferredType);
+        return new ExpressionInferenceResult(inferredType, replacement);
       }
     }
 
@@ -895,20 +1113,17 @@
           templateIntegerLiteralIsOutOfRange.withArguments(node.literal),
           node.fileOffset,
           node.literal.length);
-      node.parent.replaceChild(node, replacement);
-      return const ExpressionInferenceResult(const BottomType());
+      return new ExpressionInferenceResult(const DynamicType(), replacement);
     }
     Expression error = checkWebIntLiteralsErrorIfUnexact(
         inferrer, intValue, node.literal, node.fileOffset);
     if (error != null) {
-      node.parent.replaceChild(node, error);
-      return const ExpressionInferenceResult(const BottomType());
+      return new ExpressionInferenceResult(const DynamicType(), error);
     }
-    node.parent.replaceChild(
-        node, new IntLiteral(intValue)..fileOffset = node.fileOffset);
+    Expression replacement = new IntLiteral(intValue);
     DartType inferredType =
         inferrer.coreTypes.intRawType(inferrer.library.nonNullable);
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   void visitShadowInvalidInitializer(ShadowInvalidInitializer node) {
@@ -918,18 +1133,21 @@
   }
 
   void visitShadowInvalidFieldInitializer(ShadowInvalidFieldInitializer node) {
-    inferrer.inferExpression(node.value, node.field.type, !inferrer.isTopLevel,
+    ExpressionInferenceResult initializerResult = inferrer.inferExpression(
+        node.value, node.field.type, !inferrer.isTopLevel,
         isVoidAllowed: false);
+    node.value = initializerResult.expression..parent = node;
   }
 
   @override
   ExpressionInferenceResult visitIsExpression(
       IsExpression node, DartType typeContext) {
-    inferrer.inferExpression(
+    ExpressionInferenceResult operandResult = inferrer.inferExpression(
         node.operand, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: false);
+    node.operand = operandResult.expression..parent = node;
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.boolRawType(inferrer.library.nonNullable), node);
   }
 
   @override
@@ -951,9 +1169,8 @@
     return null;
   }
 
-  DartType inferElement(
+  ExpressionInferenceResult inferElement(
       Expression element,
-      TreeNode parent,
       DartType inferredTypeArgument,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes,
@@ -966,8 +1183,10 @@
               <DartType>[inferredTypeArgument]),
           inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
+      element.expression = spreadResult.expression..parent = element;
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[element.expression] = spreadType;
+      Expression replacement = element;
       if (typeChecksNeeded) {
         DartType spreadElementType =
             getSpreadElementType(spreadType, element.isNullAware);
@@ -975,66 +1194,65 @@
           if (spreadType is InterfaceType &&
               spreadType.classNode == inferrer.coreTypes.nullClass &&
               !element.isNullAware) {
-            parent.replaceChild(
-                element,
-                inferrer.helper.buildProblem(messageNonNullAwareSpreadIsNull,
-                    element.expression.fileOffset, 1));
+            replacement = inferrer.helper.buildProblem(
+                messageNonNullAwareSpreadIsNull,
+                element.expression.fileOffset,
+                1);
           } else {
-            parent.replaceChild(
-                element,
-                inferrer.helper.buildProblem(
-                    templateSpreadTypeMismatch.withArguments(spreadType),
-                    element.expression.fileOffset,
-                    1));
+            replacement = inferrer.helper.buildProblem(
+                templateSpreadTypeMismatch.withArguments(spreadType),
+                element.expression.fileOffset,
+                1);
           }
         } else if (spreadType is InterfaceType) {
           if (!inferrer.isAssignable(inferredTypeArgument, spreadElementType)) {
-            parent.replaceChild(
-                element,
-                inferrer.helper.buildProblem(
-                    templateSpreadElementTypeMismatch.withArguments(
-                        spreadElementType, inferredTypeArgument),
-                    element.expression.fileOffset,
-                    1));
+            replacement = inferrer.helper.buildProblem(
+                templateSpreadElementTypeMismatch.withArguments(
+                    spreadElementType, inferredTypeArgument),
+                element.expression.fileOffset,
+                1);
           }
         }
       }
       // Use 'dynamic' for error recovery.
-      return element.elementType =
+      element.elementType =
           getSpreadElementType(spreadType, element.isNullAware) ??
               const DynamicType();
+      return new ExpressionInferenceResult(element.elementType, replacement);
     } else if (element is IfElement) {
       DartType boolType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
           element.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
-      DartType conditionType = conditionResult.inferredType;
-      inferrer.ensureAssignable(boolType, conditionType, element.condition,
-          element.condition.fileOffset);
-      DartType thenType = inferElement(
+      Expression condition =
+          inferrer.ensureAssignableResult(boolType, conditionResult);
+      element.condition = condition..parent = element;
+      ExpressionInferenceResult thenResult = inferElement(
           element.then,
-          element,
           inferredTypeArgument,
           inferredSpreadTypes,
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
-      DartType otherwiseType;
+      element.then = thenResult.expression..parent = element;
+      ExpressionInferenceResult otherwiseResult;
       if (element.otherwise != null) {
-        otherwiseType = inferElement(
+        otherwiseResult = inferElement(
             element.otherwise,
-            element,
             inferredTypeArgument,
             inferredSpreadTypes,
             inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
+        element.otherwise = otherwiseResult.expression..parent = element;
       }
-      return otherwiseType == null
-          ? thenType
-          : inferrer.typeSchemaEnvironment
-              .getStandardUpperBound(thenType, otherwiseType);
+      return new ExpressionInferenceResult(
+          otherwiseResult == null
+              ? thenResult.inferredType
+              : inferrer.typeSchemaEnvironment.getStandardUpperBound(
+                  thenResult.inferredType, otherwiseResult.inferredType),
+          element);
     } else if (element is ForElement) {
       for (VariableDeclaration declaration in element.variables) {
         if (declaration.name == null) {
@@ -1043,71 +1261,94 @@
                 inferrer.inferExpression(declaration.initializer,
                     declaration.type, inferenceNeeded || typeChecksNeeded,
                     isVoidAllowed: true);
+            declaration.initializer = initializerResult.expression
+              ..parent = declaration;
             declaration.type = initializerResult.inferredType;
           }
         } else {
           inferrer.inferStatement(declaration);
         }
       }
+      inferrer.flowAnalysis.for_conditionBegin(element);
       if (element.condition != null) {
-        inferredConditionTypes[element.condition] = inferrer
-            .inferExpression(
-                element.condition,
-                inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
-                inferenceNeeded || typeChecksNeeded,
-                isVoidAllowed: false)
-            .inferredType;
-      }
-      for (Expression expression in element.updates) {
-        inferrer.inferExpression(expression, const UnknownType(),
+        ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+            element.condition,
+            inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
             inferenceNeeded || typeChecksNeeded,
-            isVoidAllowed: true);
+            isVoidAllowed: false);
+        element.condition = conditionResult.expression..parent = element;
+        inferredConditionTypes[element.condition] =
+            conditionResult.inferredType;
       }
-      return inferElement(
+      inferrer.flowAnalysis.for_bodyBegin(null, element.condition);
+      ExpressionInferenceResult bodyResult = inferElement(
           element.body,
-          element,
           inferredTypeArgument,
           inferredSpreadTypes,
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
+      element.body = bodyResult.expression..parent = element;
+      inferrer.flowAnalysis.for_updaterBegin();
+      for (int index = 0; index < element.updates.length; index++) {
+        ExpressionInferenceResult updateResult = inferrer.inferExpression(
+            element.updates[index],
+            const UnknownType(),
+            inferenceNeeded || typeChecksNeeded,
+            isVoidAllowed: true);
+        element.updates[index] = updateResult.expression..parent = element;
+      }
+      inferrer.flowAnalysis.for_end();
+      return new ExpressionInferenceResult(bodyResult.inferredType, element);
     } else if (element is ForInElement) {
+      ForInResult result;
       if (element.variable.name == null) {
-        handleForInWithoutVariable(
+        result = handleForInWithoutVariable(
             element.variable, element.iterable, element.prologue,
             isAsync: element.isAsync);
       } else {
-        handleForInDeclaringVariable(
+        result = handleForInDeclaringVariable(
             element.variable, element.iterable, element.prologue,
             isAsync: element.isAsync);
       }
+      element.variable = result.variable..parent = element;
+      element.iterable = result.iterable..parent = element;
+      // TODO(johnniwinther): Use ?.. here instead.
+      element.prologue = result.body;
+      result.body?.parent = element;
       if (element.problem != null) {
-        inferrer.inferExpression(element.problem, const UnknownType(),
+        ExpressionInferenceResult problemResult = inferrer.inferExpression(
+            element.problem,
+            const UnknownType(),
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: true);
+        element.problem = problemResult.expression..parent = element;
       }
-      return inferElement(
+      inferrer.flowAnalysis
+          .forEach_bodyBegin(element, element.variable, element.variable.type);
+      ExpressionInferenceResult bodyResult = inferElement(
           element.body,
-          element,
           inferredTypeArgument,
           inferredSpreadTypes,
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
+      element.body = bodyResult.expression..parent = element;
+      inferrer.flowAnalysis.forEach_end();
+      return new ExpressionInferenceResult(bodyResult.inferredType, element);
     } else {
       ExpressionInferenceResult result = inferrer.inferExpression(
           element, inferredTypeArgument, inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
-      if (result.replacement != null) {
-        element = result.replacement;
-      }
-      DartType inferredType = result.inferredType;
+      Expression replacement;
       if (inferredTypeArgument is! UnknownType) {
-        inferrer.ensureAssignable(
-            inferredTypeArgument, inferredType, element, element.fileOffset,
+        replacement = inferrer.ensureAssignableResult(
+            inferredTypeArgument, result,
             isVoidAllowed: inferredTypeArgument is VoidType);
+      } else {
+        replacement = result.expression;
       }
-      return inferredType;
+      return new ExpressionInferenceResult(result.inferredType, replacement);
     }
   }
 
@@ -1120,12 +1361,12 @@
     if (item is SpreadElement) {
       DartType spreadType = inferredSpreadTypes[item.expression];
       if (spreadType is DynamicType) {
-        inferrer.ensureAssignable(
+        Expression expression = inferrer.ensureAssignable(
             inferrer.coreTypes.iterableRawType(
                 inferrer.library.nullableIfTrue(item.isNullAware)),
             spreadType,
-            item.expression,
-            item.expression.fileOffset);
+            item.expression);
+        item.expression = expression..parent = item;
       }
     } else if (item is IfElement) {
       checkElement(item.then, item, typeArgument, inferredSpreadTypes,
@@ -1137,11 +1378,11 @@
     } else if (item is ForElement) {
       if (item.condition != null) {
         DartType conditionType = inferredConditionTypes[item.condition];
-        inferrer.ensureAssignable(
+        Expression condition = inferrer.ensureAssignable(
             inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
             conditionType,
-            item.condition,
-            item.condition.fileOffset);
+            item.condition);
+        item.condition = condition..parent = item;
       }
       checkElement(item.body, item, typeArgument, inferredSpreadTypes,
           inferredConditionTypes);
@@ -1182,16 +1423,16 @@
       inferredTypeArgument = node.typeArgument;
     }
     if (inferenceNeeded || typeChecksNeeded) {
-      for (int i = 0; i < node.expressions.length; ++i) {
-        DartType type = inferElement(
-            node.expressions[i],
-            node,
+      for (int index = 0; index < node.expressions.length; ++index) {
+        ExpressionInferenceResult result = inferElement(
+            node.expressions[index],
             inferredTypeArgument,
             inferredSpreadTypes,
             inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
-        actualTypes.add(type);
+        node.expressions[index] = result.expression..parent = node;
+        actualTypes.add(result.inferredType);
         if (inferenceNeeded) {
           formalTypes.add(listType.typeArguments[0]);
         }
@@ -1230,7 +1471,7 @@
       }
     }
 
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -1238,19 +1479,17 @@
       LogicalExpression node, DartType typeContext) {
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType leftType = inferrer
-        .inferExpression(node.left, boolType, !inferrer.isTopLevel,
-            isVoidAllowed: false)
-        .inferredType;
-    DartType rightType = inferrer
-        .inferExpression(node.right, boolType, !inferrer.isTopLevel,
-            isVoidAllowed: false)
-        .inferredType;
-    inferrer.ensureAssignable(
-        boolType, leftType, node.left, node.left.fileOffset);
-    inferrer.ensureAssignable(
-        boolType, rightType, node.right, node.right.fileOffset);
-    return new ExpressionInferenceResult(boolType);
+    ExpressionInferenceResult leftResult = inferrer.inferExpression(
+        node.left, boolType, !inferrer.isTopLevel,
+        isVoidAllowed: false);
+    ExpressionInferenceResult rightResult = inferrer.inferExpression(
+        node.right, boolType, !inferrer.isTopLevel,
+        isVoidAllowed: false);
+    Expression left = inferrer.ensureAssignableResult(boolType, leftResult);
+    node.left = left..parent = node;
+    Expression right = inferrer.ensureAssignableResult(boolType, rightResult);
+    node.right = right..parent = node;
+    return new ExpressionInferenceResult(boolType, node);
   }
 
   // Calculates the key and the value type of a spread map entry of type
@@ -1280,7 +1519,7 @@
   // actualTypesForSet, only inferMapEntry adds exactly one element to that
   // list: the actual type of the iterable spread elements in case the map
   // literal will be disambiguated as a set literal later.
-  void inferMapEntry(
+  MapEntry inferMapEntry(
       MapEntry entry,
       TreeNode parent,
       DartType inferredKeyType,
@@ -1296,6 +1535,7 @@
       ExpressionInferenceResult spreadResult = inferrer.inferExpression(
           entry.expression, spreadContext, inferenceNeeded || typeChecksNeeded,
           isVoidAllowed: true);
+      entry.expression = spreadResult.expression..parent = entry;
       DartType spreadType = spreadResult.inferredType;
       inferredSpreadTypes[entry.expression] = spreadType;
       int length = actualTypes.length;
@@ -1308,35 +1548,30 @@
       DartType actualElementType =
           getSpreadElementType(spreadType, entry.isNullAware);
 
+      MapEntry replacement = entry;
       if (typeChecksNeeded) {
         if (actualKeyType == null) {
           if (spreadType is InterfaceType &&
               spreadType.classNode == inferrer.coreTypes.nullClass &&
               !entry.isNullAware) {
-            parent.replaceChild(
-                entry,
-                new MapEntry(
-                    inferrer.helper.buildProblem(
-                        messageNonNullAwareSpreadIsNull,
-                        entry.expression.fileOffset,
-                        1),
-                    new NullLiteral())
-                  ..fileOffset = entry.fileOffset);
+            replacement = new MapEntry(
+                inferrer.helper.buildProblem(messageNonNullAwareSpreadIsNull,
+                    entry.expression.fileOffset, 1),
+                new NullLiteral())
+              ..fileOffset = entry.fileOffset;
           } else if (actualElementType != null) {
             // Don't report the error here, it might be an ambiguous Set.  The
             // error is reported in checkMapEntry if it's disambiguated as map.
             iterableSpreadType = spreadType;
           } else {
-            parent.replaceChild(
-                entry,
-                new MapEntry(
-                    inferrer.helper.buildProblem(
-                        templateSpreadMapEntryTypeMismatch
-                            .withArguments(spreadType),
-                        entry.expression.fileOffset,
-                        1),
-                    new NullLiteral())
-                  ..fileOffset = entry.fileOffset);
+            replacement = new MapEntry(
+                inferrer.helper.buildProblem(
+                    templateSpreadMapEntryTypeMismatch
+                        .withArguments(spreadType),
+                    entry.expression.fileOffset,
+                    1),
+                new NullLiteral())
+              ..fileOffset = entry.fileOffset;
           }
         } else if (spreadType is InterfaceType) {
           Expression keyError;
@@ -1358,10 +1593,8 @@
           if (keyError != null || valueError != null) {
             keyError ??= new NullLiteral();
             valueError ??= new NullLiteral();
-            parent.replaceChild(
-                entry,
-                new MapEntry(keyError, valueError)
-                  ..fileOffset = entry.fileOffset);
+            replacement = new MapEntry(keyError, valueError)
+              ..fileOffset = entry.fileOffset;
           }
         }
       }
@@ -1396,20 +1629,20 @@
         iterableSpreadOffset = entry.expression.fileOffset;
       }
 
-      return;
+      return replacement;
     } else if (entry is IfMapEntry) {
       DartType boolType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
           entry.condition, boolType, typeChecksNeeded,
           isVoidAllowed: false);
-      DartType conditionType = conditionResult.inferredType;
-      inferrer.ensureAssignable(
-          boolType, conditionType, entry.condition, entry.condition.fileOffset);
+      Expression condition =
+          inferrer.ensureAssignableResult(boolType, conditionResult);
+      entry.condition = condition..parent = 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.
-      inferMapEntry(
+      MapEntry then = inferMapEntry(
           entry.then,
           entry,
           inferredKeyType,
@@ -1421,13 +1654,15 @@
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
+      entry.then = then..parent = entry;
+      MapEntry otherwise;
       if (entry.otherwise != null) {
         // We need to modify the actual types added in the recursive call to
         // inferMapEntry.
         DartType actualValueType = actualTypes.removeLast();
         DartType actualKeyType = actualTypes.removeLast();
         DartType actualTypeForSet = actualTypesForSet.removeLast();
-        inferMapEntry(
+        otherwise = inferMapEntry(
             entry.otherwise,
             entry,
             inferredKeyType,
@@ -1448,8 +1683,9 @@
         actualTypesForSet[lengthForSet - 1] = inferrer.typeSchemaEnvironment
             .getStandardUpperBound(
                 actualTypeForSet, actualTypesForSet[lengthForSet - 1]);
+        entry.otherwise = otherwise..parent = entry;
       }
-      return;
+      return entry;
     } else if (entry is ForMapEntry) {
       for (VariableDeclaration declaration in entry.variables) {
         if (declaration.name == null) {
@@ -1459,28 +1695,27 @@
                 declaration.type,
                 inferenceNeeded || typeChecksNeeded,
                 isVoidAllowed: true);
+            declaration.initializer = result.expression..parent = declaration;
             declaration.type = result.inferredType;
           }
         } else {
           inferrer.inferStatement(declaration);
         }
       }
+      inferrer.flowAnalysis.for_conditionBegin(entry);
       if (entry.condition != null) {
-        inferredConditionTypes[entry.condition] = inferrer
-            .inferExpression(
-                entry.condition,
-                inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
-                inferenceNeeded || typeChecksNeeded,
-                isVoidAllowed: false)
-            .inferredType;
-      }
-      for (Expression expression in entry.updates) {
-        inferrer.inferExpression(expression, const UnknownType(),
+        ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+            entry.condition,
+            inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
             inferenceNeeded || typeChecksNeeded,
-            isVoidAllowed: true);
+            isVoidAllowed: false);
+        entry.condition = conditionResult.expression..parent = entry;
+        // TODO(johnniwinther): Ensure assignability of condition?
+        inferredConditionTypes[entry.condition] = conditionResult.inferredType;
       }
+      inferrer.flowAnalysis.for_bodyBegin(null, entry.condition);
       // Actual types are added by the recursive call.
-      return inferMapEntry(
+      MapEntry body = inferMapEntry(
           entry.body,
           entry,
           inferredKeyType,
@@ -1492,23 +1727,46 @@
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
+      entry.body = body..parent = entry;
+      inferrer.flowAnalysis.for_updaterBegin();
+      for (int index = 0; index < entry.updates.length; index++) {
+        ExpressionInferenceResult updateResult = inferrer.inferExpression(
+            entry.updates[index],
+            const UnknownType(),
+            inferenceNeeded || typeChecksNeeded,
+            isVoidAllowed: true);
+        entry.updates[index] = updateResult.expression..parent = entry;
+      }
+      inferrer.flowAnalysis.for_end();
+      return entry;
     } else if (entry is ForInMapEntry) {
+      ForInResult result;
       if (entry.variable.name == null) {
-        handleForInWithoutVariable(
+        result = handleForInWithoutVariable(
             entry.variable, entry.iterable, entry.prologue,
             isAsync: entry.isAsync);
       } else {
-        handleForInDeclaringVariable(
+        result = handleForInDeclaringVariable(
             entry.variable, entry.iterable, entry.prologue,
             isAsync: entry.isAsync);
       }
+      entry.variable = result.variable..parent = entry;
+      entry.iterable = result.iterable..parent = entry;
+      // TODO(johnniwinther): Use ?.. here instead.
+      entry.prologue = result.body;
+      result.body?.parent = entry;
       if (entry.problem != null) {
-        inferrer.inferExpression(entry.problem, const UnknownType(),
+        ExpressionInferenceResult problemResult = inferrer.inferExpression(
+            entry.problem,
+            const UnknownType(),
             inferenceNeeded || typeChecksNeeded,
             isVoidAllowed: true);
+        entry.problem = problemResult.expression..parent = entry;
       }
+      inferrer.flowAnalysis
+          .forEach_bodyBegin(entry, entry.variable, entry.variable.type);
       // Actual types are added by the recursive call.
-      inferMapEntry(
+      MapEntry body = inferMapEntry(
           entry.body,
           entry,
           inferredKeyType,
@@ -1520,85 +1778,89 @@
           inferredConditionTypes,
           inferenceNeeded,
           typeChecksNeeded);
+      entry.body = body..parent = entry;
+      inferrer.flowAnalysis.forEach_end();
+      return entry;
     } else {
       ExpressionInferenceResult keyResult = inferrer.inferExpression(
           entry.key, inferredKeyType, true,
           isVoidAllowed: true);
-      DartType keyType = keyResult.inferredType;
+      Expression key = inferrer.ensureAssignableResult(
+          inferredKeyType, keyResult,
+          isVoidAllowed: inferredKeyType is VoidType);
+      entry.key = key..parent = entry;
       ExpressionInferenceResult valueResult = inferrer.inferExpression(
           entry.value, inferredValueType, true,
           isVoidAllowed: true);
-      DartType valueType = valueResult.inferredType;
-      inferrer.ensureAssignable(
-          inferredKeyType, keyType, entry.key, entry.key.fileOffset,
-          isVoidAllowed: inferredKeyType is VoidType);
-      inferrer.ensureAssignable(
-          inferredValueType, valueType, entry.value, entry.value.fileOffset,
+      Expression value = inferrer.ensureAssignableResult(
+          inferredValueType, valueResult,
           isVoidAllowed: inferredValueType is VoidType);
-      actualTypes.add(keyType);
-      actualTypes.add(valueType);
+      entry.value = value..parent = entry;
+      actualTypes.add(keyResult.inferredType);
+      actualTypes.add(valueResult.inferredType);
       // Use 'dynamic' for error recovery.
       actualTypesForSet.add(const DynamicType());
       mapEntryOffset = entry.fileOffset;
-      return;
+      return entry;
     }
   }
 
-  void checkMapEntry(
+  MapEntry checkMapEntry(
       MapEntry entry,
-      TreeNode parent,
-      Expression cachedKey,
-      Expression cachedValue,
       DartType keyType,
       DartType valueType,
       Map<TreeNode, DartType> inferredSpreadTypes,
       Map<Expression, DartType> inferredConditionTypes) {
     // It's disambiguated as a map literal.
+    MapEntry replacement = entry;
     if (iterableSpreadOffset != null) {
-      parent.replaceChild(
-          entry,
-          new MapEntry(
-              inferrer.helper.buildProblem(
-                  templateSpreadMapEntryTypeMismatch
-                      .withArguments(iterableSpreadType),
-                  iterableSpreadOffset,
-                  1),
-              new NullLiteral()));
+      replacement = new MapEntry(
+          inferrer.helper.buildProblem(
+              templateSpreadMapEntryTypeMismatch
+                  .withArguments(iterableSpreadType),
+              iterableSpreadOffset,
+              1),
+          new NullLiteral());
     }
     if (entry is SpreadMapEntry) {
       DartType spreadType = inferredSpreadTypes[entry.expression];
       if (spreadType is DynamicType) {
-        inferrer.ensureAssignable(
+        Expression expression = inferrer.ensureAssignable(
             inferrer.coreTypes
                 .mapRawType(inferrer.library.nullableIfTrue(entry.isNullAware)),
             spreadType,
-            entry.expression,
-            entry.expression.fileOffset);
+            entry.expression);
+        entry.expression = expression..parent = entry;
       }
     } else if (entry is IfMapEntry) {
-      checkMapEntry(entry.then, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes, inferredConditionTypes);
+      MapEntry then = checkMapEntry(entry.then, keyType, valueType,
+          inferredSpreadTypes, inferredConditionTypes);
+      entry.then = then..parent = entry;
       if (entry.otherwise != null) {
-        checkMapEntry(entry.otherwise, entry, cachedKey, cachedValue, keyType,
-            valueType, inferredSpreadTypes, inferredConditionTypes);
+        MapEntry otherwise = checkMapEntry(entry.otherwise, keyType, valueType,
+            inferredSpreadTypes, inferredConditionTypes);
+        entry.otherwise = otherwise..parent = entry;
       }
     } else if (entry is ForMapEntry) {
       if (entry.condition != null) {
         DartType conditionType = inferredConditionTypes[entry.condition];
-        inferrer.ensureAssignable(
+        Expression condition = inferrer.ensureAssignable(
             inferrer.coreTypes.boolRawType(inferrer.library.nonNullable),
             conditionType,
-            entry.condition,
-            entry.condition.fileOffset);
+            entry.condition);
+        entry.condition = condition..parent = entry;
       }
-      checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes, inferredConditionTypes);
+      MapEntry body = checkMapEntry(entry.body, keyType, valueType,
+          inferredSpreadTypes, inferredConditionTypes);
+      entry.body = body..parent = entry;
     } else if (entry is ForInMapEntry) {
-      checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
-          valueType, inferredSpreadTypes, inferredConditionTypes);
+      MapEntry body = checkMapEntry(entry.body, keyType, valueType,
+          inferredSpreadTypes, inferredConditionTypes);
+      entry.body = body..parent = entry;
     } else {
       // Do nothing.  Assignability checks are done during type inference.
     }
+    return replacement;
   }
 
   @override
@@ -1635,11 +1897,7 @@
           SetLiteral setLiteral = new SetLiteral([],
               typeArgument: const ImplicitTypeArgument(), isConst: node.isConst)
             ..fileOffset = node.fileOffset;
-          node.parent.replaceChild(node, setLiteral);
-          ExpressionInferenceResult setLiteralResult =
-              visitSetLiteral(setLiteral, typeContext);
-          DartType inferredType = setLiteralResult.inferredType;
-          return new ExpressionInferenceResult(inferredType);
+          return visitSetLiteral(setLiteral, typeContext);
         }
       }
     }
@@ -1664,15 +1922,6 @@
       inferredKeyType = node.keyType;
       inferredValueType = node.valueType;
     }
-    List<Expression> cachedKeys = new List(node.entries.length);
-    List<Expression> cachedValues = new List(node.entries.length);
-    for (int i = 0; i < node.entries.length; i++) {
-      MapEntry entry = node.entries[i];
-      if (entry is! ControlFlowMapEntry) {
-        cachedKeys[i] = node.entries[i].key;
-        cachedValues[i] = node.entries[i].value;
-      }
-    }
     bool hasMapEntry = false;
     bool hasMapSpread = false;
     bool hasIterableSpread = false;
@@ -1689,9 +1938,9 @@
         spreadTypeContext = new InterfaceType(inferrer.coreTypes.mapClass,
             <DartType>[inferredKeyType, inferredValueType]);
       }
-      for (int i = 0; i < node.entries.length; ++i) {
-        MapEntry entry = node.entries[i];
-        inferMapEntry(
+      for (int index = 0; index < node.entries.length; ++index) {
+        MapEntry entry = node.entries[index];
+        entry = inferMapEntry(
             entry,
             node,
             inferredKeyType,
@@ -1703,6 +1952,7 @@
             inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
+        node.entries[index] = entry..parent = node;
         if (inferenceNeeded) {
           formalTypes.add(mapType.typeArguments[0]);
           formalTypes.add(mapType.typeArguments[1]);
@@ -1720,7 +1970,8 @@
         List<DartType> formalTypesForSet = <DartType>[];
         InterfaceType setType = inferrer.coreTypes.setClass.thisType;
         for (int i = 0; i < node.entries.length; ++i) {
-          setElements.add(convertToElement(node.entries[i], inferrer.helper));
+          setElements.add(convertToElement(node.entries[i], inferrer.helper,
+              inferrer.assignedVariables.reassignInfo));
           formalTypesForSet.add(setType.typeArguments[0]);
         }
 
@@ -1750,7 +2001,6 @@
         SetLiteral setLiteral = new SetLiteral(setElements,
             typeArgument: inferredTypeArgument, isConst: node.isConst)
           ..fileOffset = node.fileOffset;
-        node.parent.replaceChild(node, setLiteral);
         if (typeChecksNeeded) {
           for (int i = 0; i < setLiteral.expressions.length; i++) {
             checkElement(
@@ -1764,27 +2014,20 @@
 
         DartType inferredType =
             new InterfaceType(inferrer.coreTypes.setClass, inferredTypesForSet);
-        return new ExpressionInferenceResult(inferredType);
+        return new ExpressionInferenceResult(inferredType, setLiteral);
       }
       if (canBeSet && canBeMap && node.entries.isNotEmpty) {
-        node.parent.replaceChild(
-            node,
-            inferrer.helper.buildProblem(
-                messageCantDisambiguateNotEnoughInformation,
-                node.fileOffset,
-                1));
-        return const ExpressionInferenceResult(const BottomType());
+        Expression error = inferrer.helper.buildProblem(
+            messageCantDisambiguateNotEnoughInformation, node.fileOffset, 1);
+        return new ExpressionInferenceResult(const BottomType(), error);
       }
       if (!canBeSet && !canBeMap) {
+        Expression replacement = node;
         if (!inferrer.isTopLevel) {
-          node.parent.replaceChild(
-              node,
-              inferrer.helper.buildProblem(
-                  messageCantDisambiguateAmbiguousInformation,
-                  node.fileOffset,
-                  1));
+          replacement = inferrer.helper.buildProblem(
+              messageCantDisambiguateAmbiguousInformation, node.fileOffset, 1);
         }
-        return const ExpressionInferenceResult(const BottomType());
+        return new ExpressionInferenceResult(const BottomType(), replacement);
       }
       inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
           mapType,
@@ -1805,16 +2048,10 @@
       node.valueType = inferredValueType;
     }
     if (typeChecksNeeded) {
-      for (int i = 0; i < node.entries.length; ++i) {
-        checkMapEntry(
-            node.entries[i],
-            node,
-            cachedKeys[i],
-            cachedValues[i],
-            node.keyType,
-            node.valueType,
-            inferredSpreadTypes,
-            inferredConditionTypes);
+      for (int index = 0; index < node.entries.length; ++index) {
+        MapEntry entry = checkMapEntry(node.entries[index], node.keyType,
+            node.valueType, inferredSpreadTypes, inferredConditionTypes);
+        node.entries[index] = entry..parent = node;
       }
     }
     DartType inferredType =
@@ -1829,7 +2066,7 @@
             inferred: true);
       }
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -1853,18 +2090,17 @@
         if (inferrer.isDoubleContext(typeContext)) {
           double doubleValue = receiver.asDouble(negated: true);
           if (doubleValue != null) {
-            node.parent.replaceChild(node,
-                new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
+            Expression replacement = new DoubleLiteral(doubleValue)
+              ..fileOffset = node.fileOffset;
             DartType inferredType =
                 inferrer.coreTypes.doubleRawType(inferrer.library.nonNullable);
-            return new ExpressionInferenceResult(inferredType);
+            return new ExpressionInferenceResult(inferredType, replacement);
           }
         }
         Expression error = checkWebIntLiteralsErrorIfUnexact(
             inferrer, receiver.value, receiver.literal, receiver.fileOffset);
         if (error != null) {
-          node.parent.replaceChild(node, error);
-          return const ExpressionInferenceResult(const BottomType());
+          return new ExpressionInferenceResult(const DynamicType(), error);
         }
       } else if (node.receiver is ShadowLargeIntLiteral) {
         ShadowLargeIntLiteral receiver = node.receiver;
@@ -1872,11 +2108,11 @@
           if (inferrer.isDoubleContext(typeContext)) {
             double doubleValue = receiver.asDouble(negated: true);
             if (doubleValue != null) {
-              node.parent.replaceChild(node,
-                  new DoubleLiteral(doubleValue)..fileOffset = node.fileOffset);
+              Expression replacement = new DoubleLiteral(doubleValue)
+                ..fileOffset = node.fileOffset;
               DartType inferredType = inferrer.coreTypes
                   .doubleRawType(inferrer.library.nonNullable);
-              return new ExpressionInferenceResult(inferredType);
+              return new ExpressionInferenceResult(inferredType, replacement);
             }
           }
           int intValue = receiver.asInt64(negated: true);
@@ -1886,15 +2122,13 @@
                     .withArguments(receiver.literal),
                 receiver.fileOffset,
                 receiver.literal.length);
-            node.parent.replaceChild(node, error);
-            return const ExpressionInferenceResult(const BottomType());
+            return new ExpressionInferenceResult(const DynamicType(), error);
           }
           if (intValue != null) {
             Expression error = checkWebIntLiteralsErrorIfUnexact(
                 inferrer, intValue, receiver.literal, receiver.fileOffset);
             if (error != null) {
-              node.parent.replaceChild(node, error);
-              return const ExpressionInferenceResult(const BottomType());
+              return new ExpressionInferenceResult(const DynamicType(), error);
             }
             node.receiver = new IntLiteral(-intValue)
               ..fileOffset = node.receiver.fileOffset
@@ -1903,31 +2137,30 @@
         }
       }
     }
-    ExpressionInferenceResult result =
-        inferrer.inferMethodInvocation(node, typeContext);
-    return new ExpressionInferenceResult(
-        result.inferredType, result.replacement);
+    return inferrer.inferMethodInvocation(node, typeContext);
   }
 
   ExpressionInferenceResult visitNamedFunctionExpressionJudgment(
       NamedFunctionExpressionJudgment node, DartType typeContext) {
-    DartType inferredType = inferrer
-        .inferExpression(node.variable.initializer, typeContext, true)
-        .inferredType;
-    node.variable.type = inferredType;
-    return new ExpressionInferenceResult(inferredType);
+    ExpressionInferenceResult initializerResult =
+        inferrer.inferExpression(node.variable.initializer, typeContext, true);
+    node.variable.initializer = initializerResult.expression
+      ..parent = node.variable;
+    node.variable.type = initializerResult.inferredType;
+    return new ExpressionInferenceResult(initializerResult.inferredType, node);
   }
 
   @override
   ExpressionInferenceResult visitNot(Not node, DartType typeContext) {
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType inferredType = inferrer
-        .inferExpression(node.operand, boolType, !inferrer.isTopLevel)
-        .inferredType;
-    inferrer.ensureAssignable(
-        boolType, inferredType, node.operand, node.fileOffset);
-    return new ExpressionInferenceResult(boolType);
+    ExpressionInferenceResult operandResult =
+        inferrer.inferExpression(node.operand, boolType, !inferrer.isTopLevel);
+    Expression operand = inferrer.ensureAssignableResult(
+        boolType, operandResult,
+        fileOffset: node.fileOffset);
+    node.operand = operand..parent = node;
+    return new ExpressionInferenceResult(boolType, node);
   }
 
   @override
@@ -1935,40 +2168,28 @@
       NullCheck node, DartType typeContext) {
     // TODO(johnniwinther): Should the typeContext for the operand be
     //  `Nullable(typeContext)`?
-    DartType inferredType = inferrer
-        .inferExpression(node.operand, typeContext, !inferrer.isTopLevel)
-        .inferredType;
+    ExpressionInferenceResult operandResult = inferrer.inferExpression(
+        node.operand, typeContext, !inferrer.isTopLevel);
+    node.operand = operandResult.expression..parent = node;
     // TODO(johnniwinther): Check that the inferred type is potentially
     //  nullable.
     // TODO(johnniwinther): Return `NonNull(inferredType)`.
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(operandResult.inferredType, node);
   }
 
   ExpressionInferenceResult visitNullAwareMethodInvocation(
       NullAwareMethodInvocation node, DartType typeContext) {
     inferrer.inferStatement(node.variable);
-    ExpressionInferenceResult readResult = inferrer.inferExpression(
+    ExpressionInferenceResult invocationResult = inferrer.inferExpression(
         node.invocation, typeContext, true,
         isVoidAllowed: true);
     Member equalsMember = inferrer
         .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
-
-    DartType inferredType = readResult.inferredType;
-
-    Expression replacement;
-    MethodInvocation equalsNull = createEqualsNull(
-        node.fileOffset,
-        new VariableGet(node.variable)..fileOffset = node.fileOffset,
-        equalsMember);
-    ConditionalExpression condition = new ConditionalExpression(
-        equalsNull,
-        new NullLiteral()..fileOffset = node.fileOffset,
-        node.invocation,
-        inferredType);
-    node.replaceWith(replacement = new Let(node.variable, condition)
-      ..fileOffset = node.fileOffset);
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        invocationResult.inferredType,
+        invocationResult.expression,
+        new NullAwareGuard(node.variable, node.fileOffset, equalsMember));
   }
 
   ExpressionInferenceResult visitNullAwarePropertyGet(
@@ -1979,22 +2200,10 @@
     Member equalsMember = inferrer
         .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
-
-    DartType inferredType = readResult.inferredType;
-
-    Expression replacement;
-    MethodInvocation equalsNull = createEqualsNull(
-        node.fileOffset,
-        new VariableGet(node.variable)..fileOffset = node.fileOffset,
-        equalsMember);
-    ConditionalExpression condition = new ConditionalExpression(
-        equalsNull,
-        new NullLiteral()..fileOffset = node.fileOffset,
-        node.read,
-        inferredType);
-    node.replaceWith(replacement = new Let(node.variable, condition)
-      ..fileOffset = node.fileOffset);
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        readResult.inferredType,
+        readResult.expression,
+        new NullAwareGuard(node.variable, node.fileOffset, equalsMember));
   }
 
   ExpressionInferenceResult visitNullAwarePropertySet(
@@ -2005,22 +2214,10 @@
     Member equalsMember = inferrer
         .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
-
-    DartType inferredType = writeResult.inferredType;
-
-    Expression replacement;
-    MethodInvocation equalsNull = createEqualsNull(
-        node.fileOffset,
-        new VariableGet(node.variable)..fileOffset = node.fileOffset,
-        equalsMember);
-    ConditionalExpression condition = new ConditionalExpression(
-        equalsNull,
-        new NullLiteral()..fileOffset = node.fileOffset,
-        node.write,
-        inferredType);
-    node.replaceWith(replacement = new Let(node.variable, condition)
-      ..fileOffset = node.fileOffset);
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        writeResult.inferredType,
+        writeResult.expression,
+        new NullAwareGuard(node.variable, node.fileOffset, equalsMember));
   }
 
   ExpressionInferenceResult visitNullAwareExtension(
@@ -2031,22 +2228,10 @@
     Member equalsMember = inferrer
         .findInterfaceMember(node.variable.type, equalsName, node.fileOffset)
         .member;
-
-    DartType inferredType = expressionResult.inferredType;
-
-    Expression replacement;
-    MethodInvocation equalsNull = createEqualsNull(
-        node.fileOffset,
-        new VariableGet(node.variable)..fileOffset = node.fileOffset,
-        equalsMember);
-    ConditionalExpression condition = new ConditionalExpression(
-        equalsNull,
-        new NullLiteral()..fileOffset = node.fileOffset,
-        node.expression,
-        inferredType);
-    node.replaceWith(replacement = new Let(node.variable, condition)
-      ..fileOffset = node.fileOffset);
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        expressionResult.inferredType,
+        expressionResult.expression,
+        new NullAwareGuard(node.variable, node.fileOffset, equalsMember));
   }
 
   ExpressionInferenceResult visitStaticPostIncDec(
@@ -2054,7 +2239,10 @@
     inferrer.inferStatement(node.read);
     inferrer.inferStatement(node.write);
     DartType inferredType = node.read.type;
-    Expression replacement = node.replace();
+
+    Expression replacement =
+        new Let(node.read, createLet(node.write, createVariableGet(node.read)))
+          ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2063,7 +2251,10 @@
     inferrer.inferStatement(node.read);
     inferrer.inferStatement(node.write);
     DartType inferredType = node.read.type;
-    Expression replacement = node.replace();
+
+    Expression replacement =
+        new Let(node.read, createLet(node.write, createVariableGet(node.read)))
+          ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2072,7 +2263,9 @@
     inferrer.inferStatement(node.read);
     inferrer.inferStatement(node.write);
     DartType inferredType = node.read.type;
-    Expression replacement = node.replace();
+    Expression replacement =
+        new Let(node.read, createLet(node.write, createVariableGet(node.read)))
+          ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2082,17 +2275,84 @@
     inferrer.inferStatement(node.read);
     inferrer.inferStatement(node.write);
     DartType inferredType = node.read.type;
-    Expression replacement = node.replace();
+
+    Expression replacement;
+    if (node.variable != null) {
+      replacement = new Let(
+          node.variable,
+          createLet(
+              node.read, createLet(node.write, createVariableGet(node.read))))
+        ..fileOffset = node.fileOffset;
+    } else {
+      replacement = new Let(
+          node.read, createLet(node.write, createVariableGet(node.read)))
+        ..fileOffset = node.fileOffset;
+    }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   ExpressionInferenceResult visitCompoundPropertySet(
       CompoundPropertySet node, DartType typeContext) {
-    inferrer.inferStatement(node.variable);
-    ExpressionInferenceResult writeResult = inferrer
-        .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
-    Expression replacement = node.replace();
-    return new ExpressionInferenceResult(writeResult.inferredType, replacement);
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+
+    NullAwareGuard nullAwareGuard;
+    Expression receiver;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = receiverResult.nullAwareGuard;
+      receiver = receiverResult.nullAwareAction;
+    } else {
+      receiver = receiverResult.expression;
+    }
+    DartType receiverType = receiverResult.inferredType;
+
+    VariableDeclaration receiverVariable;
+    Expression readReceiver;
+    Expression writeReceiver;
+    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+      readReceiver = receiver;
+      writeReceiver = receiver.accept<TreeNode>(new CloneVisitor());
+    } else {
+      receiverVariable = createVariable(receiver, receiverType);
+      inferrer.instrumentation?.record(
+          inferrer.uriForInstrumentation,
+          receiverVariable.fileOffset,
+          'type',
+          new InstrumentationValueForType(receiverType));
+      readReceiver = createVariableGet(receiverVariable);
+      writeReceiver = createVariableGet(receiverVariable);
+    }
+
+    ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
+        readReceiver, receiverType, node.propertyName, const UnknownType(),
+        isThisReceiver: node.receiver is ThisExpression);
+
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
+
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, read, readType, node.binaryName, node.rhs);
+    DartType binaryType = binaryResult.inferredType;
+
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, node.propertyName, node.writeOffset,
+        setter: true, instrumented: true, includeExtensionMethods: true);
+    DartType writeType = inferrer.getSetterType(writeTarget, receiverType);
+    Expression binary =
+        inferrer.ensureAssignableResult(writeType, binaryResult);
+
+    Expression write = _computePropertySet(node.writeOffset, writeReceiver,
+        receiverType, node.propertyName, writeTarget, binary,
+        valueType: binaryType, forEffect: node.forEffect);
+
+    Expression replacement = write;
+    if (receiverVariable != null) {
+      replacement = createLet(receiverVariable, replacement);
+    }
+    replacement.fileOffset = node.fileOffset;
+    return new ExpressionInferenceResult.nullAware(
+        binaryType, replacement, nullAwareGuard);
   }
 
   ExpressionInferenceResult visitIfNullPropertySet(
@@ -2118,31 +2378,30 @@
       //
       //     let v1 = o in v1.a == null ? v1.a = b : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.fileOffset, node.read, equalsMember);
+      MethodInvocation equalsNull = createEqualsNull(
+          node.fileOffset, readResult.expression, equalsMember);
       ConditionalExpression conditional = new ConditionalExpression(
           equalsNull,
-          node.write,
+          writeResult.expression,
           new NullLiteral()..fileOffset = node.fileOffset,
           inferredType)
         ..fileOffset = node.fileOffset;
-      node.replaceWith(replacement =
-          new Let(node.variable, conditional..fileOffset = node.fileOffset));
+      replacement =
+          new Let(node.variable, conditional..fileOffset = node.fileOffset);
     } else {
       // Encode `o.a ??= b` as:
       //
       //     let v1 = o in let v2 = v1.a in v2 == null ? v1.a = b : v2
       //
       VariableDeclaration readVariable =
-          createVariable(node.read, readResult.inferredType);
+          createVariable(readResult.expression, readResult.inferredType);
       MethodInvocation equalsNull = createEqualsNull(
           node.fileOffset, createVariableGet(readVariable), equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull, node.write, createVariableGet(readVariable), inferredType)
+      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+          writeResult.expression, createVariableGet(readVariable), inferredType)
         ..fileOffset = node.fileOffset;
-      node.replaceWith(replacement =
-          new Let(node.variable, createLet(readVariable, conditional))
-            ..fileOffset = node.fileOffset);
+      replacement = new Let(node.variable, createLet(readVariable, conditional))
+        ..fileOffset = node.fileOffset;
     }
 
     return new ExpressionInferenceResult(inferredType, replacement);
@@ -2169,28 +2428,28 @@
       //
       //     a == null ? a = b : null
       //
-      MethodInvocation equalsNull =
-          createEqualsNull(node.fileOffset, node.read, equalsMember);
-      node.replaceWith(replacement = new ConditionalExpression(
+      MethodInvocation equalsNull = createEqualsNull(
+          node.fileOffset, readResult.expression, equalsMember);
+      replacement = new ConditionalExpression(
           equalsNull,
-          node.write,
+          writeResult.expression,
           new NullLiteral()..fileOffset = node.fileOffset,
           inferredType)
-        ..fileOffset = node.fileOffset);
+        ..fileOffset = node.fileOffset;
     } else {
       // Encode `a ??= b` as:
       //
       //      let v1 = a in v1 == null ? a = b : v1
       //
       VariableDeclaration readVariable =
-          createVariable(node.read, readResult.inferredType);
+          createVariable(readResult.expression, readResult.inferredType);
       MethodInvocation equalsNull = createEqualsNull(
           node.fileOffset, createVariableGet(readVariable), equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull, node.write, createVariableGet(readVariable), inferredType)
+      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+          writeResult.expression, createVariableGet(readVariable), inferredType)
         ..fileOffset = node.fileOffset;
-      node.replaceWith(replacement = new Let(readVariable, conditional)
-        ..fileOffset = node.fileOffset);
+      replacement = new Let(readVariable, conditional)
+        ..fileOffset = node.fileOffset;
     }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
@@ -2199,9 +2458,17 @@
     ExpressionInferenceResult receiverResult = inferrer.inferExpression(
         node.receiver, const UnknownType(), true,
         isVoidAllowed: true);
+    Expression receiver;
+    NullAwareGuard nullAwareGuard;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = receiverResult.nullAwareGuard;
+      receiver = receiverResult.nullAwareAction;
+    } else {
+      receiver = receiverResult.expression;
+    }
     DartType receiverType = receiverResult.inferredType;
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariable(receiver, receiverType);
 
     ObjectAccessTarget indexSetTarget = inferrer.findInterfaceMember(
         receiverType, indexSetName, node.fileOffset,
@@ -2214,56 +2481,32 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
-    inferrer.ensureAssignable(
-        indexType, indexResult.inferredType, node.index, node.index.fileOffset);
+    Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
     VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+        createVariable(index, indexResult.inferredType);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
     VariableDeclaration valueVariable =
-        createVariable(node.value, valueResult.inferredType);
+        createVariable(value, valueResult.inferredType);
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression replacement;
-    Expression assignment;
-    if (indexSetTarget.isMissing) {
-      assignment = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]=', receiverType),
-          node.fileOffset,
-          '[]='.length);
-    } else if (indexSetTarget.isExtensionMember) {
-      assert(indexSetTarget.extensionMethodKind != ProcedureKind.Setter);
-      assignment = new StaticInvocation(
-          indexSetTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            createVariableGet(indexVariable),
-            createVariableGet(valueVariable)
-          ], types: indexSetTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.fileOffset)
-        ..fileOffset = node.fileOffset;
-    } else {
-      assignment = new MethodInvocation(
-          createVariableGet(receiverVariable),
-          indexSetName,
-          new Arguments(<Expression>[
-            createVariableGet(indexVariable),
-            createVariableGet(valueVariable)
-          ])
-            ..fileOffset = node.fileOffset,
-          indexSetTarget.member)
-        ..fileOffset = node.fileOffset;
-    }
+    Expression assignment = _computeIndexSet(
+        node.fileOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        indexSetTarget,
+        createVariableGet(indexVariable),
+        createVariableGet(valueVariable));
+
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    node.replaceWith(replacement = new Let(
+    Expression replacement = new Let(
         receiverVariable,
         createLet(
             indexVariable,
@@ -2271,8 +2514,9 @@
                 valueVariable,
                 createLet(
                     assignmentVariable, createVariableGet(valueVariable))))
-          ..fileOffset = node.fileOffset));
-    return new ExpressionInferenceResult(inferredType, replacement);
+          ..fileOffset = node.fileOffset);
+    return new ExpressionInferenceResult.nullAware(
+        inferredType, replacement, nullAwareGuard);
   }
 
   ExpressionInferenceResult visitSuperIndexSet(
@@ -2289,30 +2533,25 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
-    inferrer.ensureAssignable(
-        indexType, indexResult.inferredType, node.index, node.index.fileOffset);
+    Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
     VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+        createVariable(index, indexResult.inferredType);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
     VariableDeclaration valueVariable =
-        createVariable(node.value, valueResult.inferredType);
+        createVariable(value, valueResult.inferredType);
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression replacement;
     Expression assignment;
     if (indexSetTarget.isMissing) {
-      assignment = inferrer.helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments(indexSetName.name),
-          node.fileOffset,
-          noLength);
+      assignment = inferrer.createMissingSuperIndexSet(node.fileOffset,
+          createVariableGet(indexVariable), createVariableGet(valueVariable));
     } else {
       assert(indexSetTarget.isInstanceMember);
       inferrer.instrumentation?.record(
@@ -2332,11 +2571,11 @@
     }
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    node.replaceWith(replacement = new Let(
+    Expression replacement = new Let(
         indexVariable,
         createLet(valueVariable,
             createLet(assignmentVariable, createVariableGet(valueVariable))))
-      ..fileOffset = node.fileOffset);
+      ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2353,11 +2592,11 @@
     DartType receiverType = inferrer.getExtensionReceiverType(
         node.extension, extensionTypeArguments);
 
-    inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
-        node.receiver, node.receiver.fileOffset);
+    Expression receiver =
+        inferrer.ensureAssignableResult(receiverType, receiverResult);
 
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariable(receiver, receiverType);
 
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.setter, null, ProcedureKind.Operator, extensionTypeArguments);
@@ -2368,46 +2607,32 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, indexType, true, isVoidAllowed: true);
 
-    inferrer.ensureAssignable(
-        indexType, indexResult.inferredType, node.index, node.index.fileOffset);
+    Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
     VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+        createVariable(index, indexResult.inferredType);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
     VariableDeclaration valueVariable =
-        createVariable(node.value, valueResult.inferredType);
+        createVariable(value, valueResult.inferredType);
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression replacement;
-    Expression assignment;
-    if (target.isMissing) {
-      assignment = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              indexSetName.name, receiverType),
-          node.fileOffset,
-          noLength);
-    } else {
-      assert(target.isExtensionMember);
-      assignment = new StaticInvocation(
-          target.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            createVariableGet(indexVariable),
-            createVariableGet(valueVariable)
-          ], types: target.inferredExtensionTypeArguments)
-            ..fileOffset = node.fileOffset)
-        ..fileOffset = node.fileOffset;
-    }
+    Expression assignment = _computeIndexSet(
+        node.fileOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        target,
+        createVariableGet(indexVariable),
+        createVariableGet(valueVariable));
+
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    node.replaceWith(replacement = new Let(
+    Expression replacement = new Let(
         receiverVariable,
         createLet(
             indexVariable,
@@ -2415,7 +2640,7 @@
                 valueVariable,
                 createLet(
                     assignmentVariable, createVariableGet(valueVariable)))))
-      ..fileOffset = node.fileOffset);
+      ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2424,15 +2649,23 @@
     ExpressionInferenceResult receiverResult = inferrer.inferExpression(
         node.receiver, const UnknownType(), true,
         isVoidAllowed: true);
+
+    Expression receiver;
+    NullAwareGuard nullAwareGuard;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = receiverResult.nullAwareGuard;
+      receiver = receiverResult.nullAwareAction;
+    } else {
+      receiver = receiverResult.expression;
+    }
     DartType receiverType = receiverResult.inferredType;
     VariableDeclaration receiverVariable;
-    Expression readReceiver;
+    Expression readReceiver = receiver;
     Expression writeReceiver;
     if (node.readOnlyReceiver) {
-      readReceiver = node.receiver;
       writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
     } else {
-      receiverVariable = createVariable(node.receiver, receiverType);
+      receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
       writeReceiver = createVariableGet(receiverVariable);
     }
@@ -2445,13 +2678,8 @@
         inferrer.preCheckInvocationContravariance(receiverType, readTarget,
             isThisReceiver: node.receiver is ThisExpression);
 
-    DartType readType = inferrer.getReturnType(readTarget, receiverType);
     DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
 
-    Member equalsMember = inferrer
-        .findInterfaceMember(readType, equalsName, node.testOffset)
-        .member;
-
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
         receiverType, indexSetName, node.writeOffset,
         includeExtensionMethods: true);
@@ -2464,102 +2692,42 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
     Expression readIndex = createVariableGet(indexVariable);
-    readIndex = inferrer.ensureAssignable(readIndexType,
-            indexResult.inferredType, readIndex, readIndex.fileOffset) ??
-        readIndex;
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
+
+    ExpressionInferenceResult readResult = _computeIndexGet(node.readOffset,
+        readReceiver, receiverType, readTarget, readIndex, checkKind);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
+
+    Member equalsMember = inferrer
+        .findInterfaceMember(readType, equalsName, node.testOffset)
+        .member;
 
     Expression writeIndex = createVariableGet(indexVariable);
-    writeIndex = inferrer.ensureAssignable(writeIndexType,
-            indexResult.inferredType, writeIndex, writeIndex.fileOffset) ??
-        writeIndex;
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(readType, valueResult.inferredType);
 
-    Expression read;
-
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]', receiverType),
-          node.readOffset,
-          '[]'.length);
-    } else if (readTarget.isExtensionMember) {
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            readReceiver,
-            readIndex,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    } else {
-      read = new MethodInvocation(
-          readReceiver,
-          indexGetName,
-          new Arguments(<Expression>[
-            readIndex,
-          ])
-            ..fileOffset = node.readOffset,
-          readTarget.member)
-        ..fileOffset = node.readOffset;
-
-      if (checkKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.readOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        read = new AsExpression(read, readType)
-          ..isTypeError = true
-          ..fileOffset = node.readOffset;
-      }
-    }
-
     VariableDeclaration valueVariable;
-    Expression valueExpression;
     if (node.forEffect) {
-      valueExpression = node.value;
+      // No need for value variable.
     } else {
-      valueVariable = createVariable(node.value, valueResult.inferredType);
-      valueExpression = createVariableGet(valueVariable);
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
     }
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]=', receiverType),
-          node.writeOffset,
-          '[]='.length);
-    } else if (writeTarget.isExtensionMember) {
-      assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
-      write = new StaticInvocation(
-          writeTarget.member,
-          new Arguments(
-              <Expression>[writeReceiver, writeIndex, valueExpression],
-              types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.writeOffset)
-        ..fileOffset = node.writeOffset;
-    } else {
-      write = new MethodInvocation(
-          writeReceiver,
-          indexSetName,
-          new Arguments(<Expression>[writeIndex, valueExpression])
-            ..fileOffset = node.writeOffset,
-          writeTarget.member)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
+        receiverType, writeTarget, writeIndex, value);
 
     Expression inner;
     if (node.forEffect) {
@@ -2626,12 +2794,13 @@
 
     Expression replacement;
     if (receiverVariable != null) {
-      node.replaceWith(replacement = new Let(receiverVariable, inner)
-        ..fileOffset = node.fileOffset);
+      replacement = new Let(receiverVariable, inner)
+        ..fileOffset = node.fileOffset;
     } else {
-      node.replaceWith(replacement = inner);
+      replacement = inner;
     }
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        inferredType, replacement, nullAwareGuard);
   }
 
   ExpressionInferenceResult visitIfNullSuperIndexSet(
@@ -2660,21 +2829,19 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    VariableGet readIndex = createVariableGet(indexVariable);
-    inferrer.ensureAssignable(readIndexType, indexResult.inferredType,
-        readIndex, readIndex.fileOffset);
+    Expression readIndex = createVariableGet(indexVariable);
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
 
-    VariableGet writeIndex = createVariableGet(indexVariable);
-    inferrer.ensureAssignable(writeIndexType, indexResult.inferredType,
-        writeIndex, writeIndex.fileOffset);
+    Expression writeIndex = createVariableGet(indexVariable);
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(readType, valueResult.inferredType);
@@ -2682,10 +2849,7 @@
     Expression read;
 
     if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments('[]'),
-          node.readOffset,
-          '[]'.length);
+      read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
       assert(readTarget.isInstanceMember);
       inferrer.instrumentation?.record(
@@ -2704,21 +2868,18 @@
     }
 
     VariableDeclaration valueVariable;
-    Expression valueExpression;
     if (node.forEffect) {
-      valueExpression = node.value;
+      // No need for a value variable.
     } else {
-      valueVariable = createVariable(node.value, valueResult.inferredType);
-      valueExpression = createVariableGet(valueVariable);
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
     }
 
     Expression write;
 
     if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments('[]='),
-          node.writeOffset,
-          '[]='.length);
+      write = inferrer.createMissingSuperIndexSet(
+          node.writeOffset, writeIndex, value);
     } else {
       assert(writeTarget.isInstanceMember);
       inferrer.instrumentation?.record(
@@ -2728,8 +2889,7 @@
           new InstrumentationValueForMember(node.setter));
       write = new SuperMethodInvocation(
           indexSetName,
-          new Arguments(
-              <Expression>[createVariableGet(indexVariable), valueExpression])
+          new Arguments(<Expression>[writeIndex, value])
             ..fileOffset = node.writeOffset,
           writeTarget.member)
         ..fileOffset = node.writeOffset;
@@ -2777,7 +2937,6 @@
           createLet(indexVariable, createLet(readVariable, conditional));
     }
 
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -2794,24 +2953,19 @@
     DartType receiverType = inferrer.getExtensionReceiverType(
         node.extension, extensionTypeArguments);
 
-    inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
-        node.receiver, node.receiver.fileOffset);
+    Expression receiver =
+        inferrer.ensureAssignableResult(receiverType, receiverResult);
 
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariable(receiver, receiverType);
 
     ObjectAccessTarget readTarget = node.getter != null
         ? new ExtensionAccessTarget(
             node.getter, null, ProcedureKind.Operator, extensionTypeArguments)
         : const ObjectAccessTarget.missing();
 
-    DartType readType = inferrer.getReturnType(readTarget, receiverType);
     DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
 
-    Member equalsMember = inferrer
-        .findInterfaceMember(readType, equalsName, node.testOffset)
-        .member;
-
     ObjectAccessTarget writeTarget = node.setter != null
         ? new ExtensionAccessTarget(
             node.setter, null, ProcedureKind.Operator, extensionTypeArguments)
@@ -2825,74 +2979,52 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    VariableGet readIndex = createVariableGet(indexVariable);
-    inferrer.ensureAssignable(readIndexType, indexResult.inferredType,
-        readIndex, readIndex.fileOffset);
+    Expression readIndex = createVariableGet(indexVariable);
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
 
-    VariableGet writeIndex = createVariableGet(indexVariable);
-    inferrer.ensureAssignable(writeIndexType, indexResult.inferredType,
-        writeIndex, writeIndex.fileOffset);
+    ExpressionInferenceResult readResult = _computeIndexGet(
+        node.readOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        readTarget,
+        readIndex,
+        MethodContravarianceCheckKind.none);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
+
+    Member equalsMember = inferrer
+        .findInterfaceMember(readType, equalsName, node.testOffset)
+        .member;
+
+    Expression writeIndex = createVariableGet(indexVariable);
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(readType, valueResult.inferredType);
 
-    Expression read;
-
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              indexGetName.name, receiverType),
-          node.readOffset,
-          noLength);
-    } else {
-      assert(readTarget.isExtensionMember);
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            readIndex,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    }
-
     VariableDeclaration valueVariable;
-    Expression valueExpression;
     if (node.forEffect) {
-      valueExpression = node.value;
+      // No need for a value variable.
     } else {
-      valueVariable = createVariable(node.value, valueResult.inferredType);
-      valueExpression = createVariableGet(valueVariable);
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
     }
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              indexSetName.name, receiverType),
-          node.writeOffset,
-          noLength);
-    } else {
-      assert(writeTarget.isExtensionMember);
-      write = new StaticInvocation(
-          writeTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            writeIndex,
-            valueExpression
-          ], types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.writeOffset)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        writeTarget,
+        writeIndex,
+        value);
 
     Expression inner;
     if (node.forEffect) {
@@ -2941,25 +3073,347 @@
 
     Expression replacement = new Let(receiverVariable, inner)
       ..fileOffset = node.fileOffset;
-
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
+  /// Creates a binary expression of the binary operator with [binaryName] using
+  /// [left] and [right] as operands.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [leftType] is
+  /// the already inferred type of the [left] expression. The inferred type of
+  /// [right] is computed by this method.
+  ExpressionInferenceResult _computeBinaryExpression(int fileOffset,
+      Expression left, DartType leftType, Name binaryName, Expression right) {
+    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
+        leftType, binaryName, fileOffset,
+        includeExtensionMethods: true);
+
+    MethodContravarianceCheckKind binaryCheckKind =
+        inferrer.preCheckInvocationContravariance(leftType, binaryTarget,
+            isThisReceiver: false);
+
+    DartType binaryType = inferrer.getReturnType(binaryTarget, leftType);
+    DartType rightType =
+        inferrer.getPositionalParameterTypeForTarget(binaryTarget, leftType, 0);
+
+    ExpressionInferenceResult rightResult =
+        inferrer.inferExpression(right, rightType, true, isVoidAllowed: true);
+    right = inferrer.ensureAssignableResult(rightType, rightResult);
+
+    if (inferrer.isOverloadedArithmeticOperatorAndType(
+        binaryTarget, leftType)) {
+      binaryType = inferrer.typeSchemaEnvironment
+          .getTypeOfOverloadedArithmetic(leftType, rightResult.inferredType);
+    }
+
+    Expression binary;
+    if (binaryTarget.isMissing) {
+      binary = inferrer.createMissingBinary(
+          fileOffset, left, leftType, binaryName, right);
+    } else if (binaryTarget.isExtensionMember) {
+      assert(binaryTarget.extensionMethodKind != ProcedureKind.Setter);
+      binary = new StaticInvocation(
+          binaryTarget.member,
+          new Arguments(<Expression>[
+            left,
+            right,
+          ], types: binaryTarget.inferredExtensionTypeArguments)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    } else {
+      binary = new MethodInvocation(
+          left,
+          binaryName,
+          new Arguments(<Expression>[
+            right,
+          ])
+            ..fileOffset = fileOffset,
+          binaryTarget.member)
+        ..fileOffset = fileOffset;
+
+      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(
+              inferrer.uriForInstrumentation,
+              fileOffset,
+              'checkReturn',
+              new InstrumentationValueForType(binaryType));
+        }
+        binary = new AsExpression(binary, binaryType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
+      }
+    }
+    return new ExpressionInferenceResult(binaryType, binary);
+  }
+
+  /// Creates an index operation of [readTarget] on [receiver] using [index] as
+  /// the argument.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [receiverType]
+  /// is the already inferred type of the [receiver] expression. The inferred
+  /// type of [index] must already have been computed.
+  ExpressionInferenceResult _computeIndexGet(
+      int fileOffset,
+      Expression readReceiver,
+      DartType receiverType,
+      ObjectAccessTarget readTarget,
+      Expression readIndex,
+      MethodContravarianceCheckKind readCheckKind) {
+    Expression read;
+    DartType readType = inferrer.getReturnType(readTarget, receiverType);
+    if (readTarget.isMissing) {
+      read = inferrer.createMissingIndexGet(
+          fileOffset, readReceiver, receiverType, readIndex);
+    } else if (readTarget.isExtensionMember) {
+      read = new StaticInvocation(
+          readTarget.member,
+          new Arguments(<Expression>[
+            readReceiver,
+            readIndex,
+          ], types: readTarget.inferredExtensionTypeArguments)
+            ..fileOffset = fileOffset)
+        ..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(
+              inferrer.uriForInstrumentation,
+              fileOffset,
+              'checkReturn',
+              new InstrumentationValueForType(readType));
+        }
+        read = new AsExpression(read, readType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
+      }
+    }
+    return new ExpressionInferenceResult(readType, read);
+  }
+
+  /// Creates an index set operation of [writeTarget] on [receiver] using
+  /// [index] and [value] as the arguments.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [receiverType]
+  /// is the already inferred type of the [receiver] expression. The inferred
+  /// type of [index] and [value] must already have been computed.
+  Expression _computeIndexSet(
+      int fileOffset,
+      Expression receiver,
+      DartType receiverType,
+      ObjectAccessTarget writeTarget,
+      Expression index,
+      Expression value) {
+    Expression write;
+    if (writeTarget.isMissing) {
+      write = inferrer.createMissingIndexSet(
+          fileOffset, receiver, receiverType, index, value);
+    } else if (writeTarget.isExtensionMember) {
+      assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
+      write = new StaticInvocation(
+          writeTarget.member,
+          new Arguments(<Expression>[receiver, index, value],
+              types: writeTarget.inferredExtensionTypeArguments)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    } else {
+      write = new MethodInvocation(
+          receiver,
+          indexSetName,
+          new Arguments(<Expression>[index, value])..fileOffset = fileOffset,
+          writeTarget.member)
+        ..fileOffset = fileOffset;
+    }
+    return write;
+  }
+
+  /// Creates a property get of [propertyName] on [receiver] of type
+  /// [receiverType].
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [receiverType]
+  /// is the already inferred type of the [receiver] expression. The
+  /// [typeContext] is used to create implicit generic tearoff instantiation
+  /// if necessary. [isThisReceiver] must be set to `true` if the receiver is a
+  /// `this` expression.
+  ExpressionInferenceResult _computePropertyGet(
+      int fileOffset,
+      Expression receiver,
+      DartType receiverType,
+      Name propertyName,
+      DartType typeContext,
+      {bool isThisReceiver}) {
+    assert(isThisReceiver != null);
+
+    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
+        receiverType, propertyName, fileOffset,
+        includeExtensionMethods: true);
+
+    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+
+    Expression read;
+    if (readTarget.isMissing) {
+      read = inferrer.createMissingPropertyGet(
+          fileOffset, receiver, receiverType, propertyName);
+    } else if (readTarget.isExtensionMember) {
+      switch (readTarget.extensionMethodKind) {
+        case ProcedureKind.Getter:
+          read = new StaticInvocation(
+              readTarget.member,
+              new Arguments(<Expression>[
+                receiver,
+              ], types: readTarget.inferredExtensionTypeArguments)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset;
+          break;
+        case ProcedureKind.Method:
+          read = new StaticInvocation(
+              readTarget.tearoffTarget,
+              new Arguments(<Expression>[
+                receiver,
+              ], types: readTarget.inferredExtensionTypeArguments)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset;
+          return inferrer.instantiateTearOff(readType, typeContext, read);
+        case ProcedureKind.Setter:
+        case ProcedureKind.Factory:
+        case ProcedureKind.Operator:
+          unhandled('$readTarget', "inferPropertyGet", null, null);
+          break;
+      }
+    } else {
+      if (readTarget.isInstanceMember &&
+          inferrer.instrumentation != null &&
+          receiverType == const DynamicType()) {
+        inferrer.instrumentation.record(
+            inferrer.uriForInstrumentation,
+            fileOffset,
+            'target',
+            new InstrumentationValueForMember(readTarget.member));
+      }
+      read = new PropertyGet(receiver, propertyName, readTarget.member)
+        ..fileOffset = fileOffset;
+      bool checkReturn = false;
+      if (readTarget.isInstanceMember && !isThisReceiver) {
+        Member interfaceMember = readTarget.member;
+        if (interfaceMember is Procedure) {
+          checkReturn =
+              TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
+                  interfaceMember.enclosingClass,
+                  interfaceMember.function.returnType);
+        } else if (interfaceMember is Field) {
+          checkReturn =
+              TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
+                  interfaceMember.enclosingClass, interfaceMember.type);
+        }
+      }
+      if (checkReturn) {
+        if (inferrer.instrumentation != null) {
+          inferrer.instrumentation.record(
+              inferrer.uriForInstrumentation,
+              fileOffset,
+              'checkReturn',
+              new InstrumentationValueForType(readType));
+        }
+        read = new AsExpression(read, readType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
+      }
+      Member member = readTarget.member;
+      if (member is Procedure && member.kind == ProcedureKind.Method) {
+        return inferrer.instantiateTearOff(readType, typeContext, read);
+      }
+    }
+    return new ExpressionInferenceResult(readType, read);
+  }
+
+  /// Creates a property set operation of [writeTarget] on [receiver] using
+  /// [value] as the right-hand side.
+  ///
+  /// [fileOffset] is used as the file offset for created nodes. [propertyName]
+  /// is used for error reporting. [receiverType] is the already inferred type
+  /// of the [receiver] expression. The inferred type of [value] must already
+  /// have been computed.
+  ///
+  /// If [forEffect] the resulting expression is ensured to return the [value]
+  /// of static type [valueType]. This is needed for extension setters which are
+  /// encoded as static method calls that do not implicitly return the value.
+  Expression _computePropertySet(
+      int fileOffset,
+      Expression receiver,
+      DartType receiverType,
+      Name propertyName,
+      ObjectAccessTarget writeTarget,
+      Expression value,
+      {DartType valueType,
+      bool forEffect}) {
+    assert(forEffect != null);
+    assert(forEffect || valueType != null,
+        "No value type provided for property set needed for value.");
+    Expression write;
+    if (writeTarget.isMissing) {
+      write = inferrer.createMissingPropertySet(
+          fileOffset, receiver, receiverType, propertyName, value,
+          forEffect: forEffect);
+    } else if (writeTarget.isExtensionMember) {
+      if (forEffect) {
+        write = new StaticInvocation(
+            writeTarget.member,
+            new Arguments(<Expression>[receiver, value],
+                types: writeTarget.inferredExtensionTypeArguments)
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset;
+      } else {
+        VariableDeclaration valueVariable = createVariable(value, valueType);
+        VariableDeclaration assignmentVariable = createVariable(
+            new StaticInvocation(
+                writeTarget.member,
+                new Arguments(
+                    <Expression>[receiver, createVariableGet(valueVariable)],
+                    types: writeTarget.inferredExtensionTypeArguments)
+                  ..fileOffset = fileOffset)
+              ..fileOffset = fileOffset,
+            const VoidType());
+        write = createLet(valueVariable,
+            createLet(assignmentVariable, createVariableGet(valueVariable)))
+          ..fileOffset = fileOffset;
+      }
+    } else {
+      write = new PropertySet(receiver, propertyName, value, writeTarget.member)
+        ..fileOffset = fileOffset;
+    }
+    return write;
+  }
+
   ExpressionInferenceResult visitCompoundIndexSet(
       CompoundIndexSet node, DartType typeContext) {
     ExpressionInferenceResult receiverResult = inferrer.inferExpression(
         node.receiver, const UnknownType(), true,
         isVoidAllowed: true);
-    DartType receiverType = receiverResult.inferredType;
+    Expression receiver;
+    NullAwareGuard nullAwareGuard;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = receiverResult.nullAwareGuard;
+      receiver = receiverResult.nullAwareAction;
+    } else {
+      receiver = receiverResult.expression;
+    }
     VariableDeclaration receiverVariable;
-    Expression readReceiver;
+    DartType receiverType = receiverResult.inferredType;
+    Expression readReceiver = receiver;
     Expression writeReceiver;
     if (node.readOnlyReceiver) {
-      readReceiver = node.receiver;
       writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
     } else {
-      receiverVariable = createVariable(node.receiver, receiverType);
+      receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
       writeReceiver = createVariableGet(receiverVariable);
     }
@@ -2972,60 +3426,21 @@
         inferrer.preCheckInvocationContravariance(receiverType, readTarget,
             isThisReceiver: node.receiver is ThisExpression);
 
-    DartType readType = inferrer.getReturnType(readTarget, receiverType);
     DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
         readTarget, receiverType, 0);
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
     Expression readIndex = createVariableGet(indexVariable);
-    Expression readIndexReplacement = inferrer.ensureAssignable(readIndexType,
-        indexResult.inferredType, readIndex, readIndex.fileOffset);
-    if (readIndexReplacement != null) {
-      readIndex = readIndexReplacement;
-    }
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
 
-    Expression read;
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]', receiverType),
-          node.readOffset,
-          '[]'.length);
-    } else if (readTarget.isExtensionMember) {
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            readReceiver,
-            readIndex,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    } else {
-      read = new MethodInvocation(
-          readReceiver,
-          indexGetName,
-          new Arguments(<Expression>[
-            readIndex,
-          ])
-            ..fileOffset = node.readOffset,
-          readTarget.member)
-        ..fileOffset = node.readOffset;
-      if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.readOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        read = new AsExpression(read, readType)
-          ..isTypeError = true
-          ..fileOffset = node.readOffset;
-      }
-    }
+    ExpressionInferenceResult readResult = _computeIndexGet(node.readOffset,
+        readReceiver, receiverType, readTarget, readIndex, readCheckKind);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
 
     VariableDeclaration leftVariable;
     Expression left;
@@ -3038,69 +3453,10 @@
       left = read;
     }
 
-    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
-        readType, node.binaryName, node.binaryOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind binaryCheckKind =
-        inferrer.preCheckInvocationContravariance(readType, binaryTarget,
-            isThisReceiver: false);
-
-    DartType binaryType = inferrer.getReturnType(binaryTarget, readType);
-    DartType rhsType =
-        inferrer.getPositionalParameterTypeForTarget(binaryTarget, readType, 0);
-
-    ExpressionInferenceResult rhsResult =
-        inferrer.inferExpression(node.rhs, rhsType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        rhsType, rhsResult.inferredType, node.rhs, node.rhs.fileOffset);
-
-    if (inferrer.isOverloadedArithmeticOperatorAndType(
-        binaryTarget, readType)) {
-      binaryType = inferrer.typeSchemaEnvironment
-          .getTypeOfOverloadedArithmetic(readType, rhsResult.inferredType);
-    }
-
-    Expression binary;
-    if (binaryTarget.isMissing) {
-      binary = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.binaryName.name, readType),
-          node.binaryOffset,
-          node.binaryName.name.length);
-    } else if (binaryTarget.isExtensionMember) {
-      assert(binaryTarget.extensionMethodKind != ProcedureKind.Setter);
-      binary = new StaticInvocation(
-          binaryTarget.member,
-          new Arguments(<Expression>[
-            left,
-            node.rhs,
-          ], types: binaryTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.binaryOffset)
-        ..fileOffset = node.binaryOffset;
-    } else {
-      binary = new MethodInvocation(
-          left,
-          node.binaryName,
-          new Arguments(<Expression>[
-            node.rhs,
-          ])
-            ..fileOffset = node.binaryOffset,
-          binaryTarget.member)
-        ..fileOffset = node.binaryOffset;
-
-      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.binaryOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        binary = new AsExpression(binary, binaryType)
-          ..isTypeError = true
-          ..fileOffset = node.binaryOffset;
-      }
-    }
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, left, readType, node.binaryName, node.rhs);
+    Expression binary = binaryResult.expression;
+    DartType binaryType = binaryResult.inferredType;
 
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
         receiverType, indexSetName, node.writeOffset,
@@ -3109,19 +3465,13 @@
     DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
         writeTarget, receiverType, 0);
     Expression writeIndex = createVariableGet(indexVariable);
-    Expression writeIndexReplacement = inferrer.ensureAssignable(writeIndexType,
-        indexResult.inferredType, writeIndex, writeIndex.fileOffset);
-    if (writeIndexReplacement != null) {
-      writeIndex = writeIndexReplacement;
-    }
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     DartType valueType =
         inferrer.getIndexSetValueType(writeTarget, receiverType);
-    Expression binaryReplacement = inferrer.ensureAssignable(
-        valueType, binaryType, binary, node.fileOffset);
-    if (binaryReplacement != null) {
-      binary = binaryReplacement;
-    }
+    binary = inferrer.ensureAssignable(valueType, binaryType, binary,
+        fileOffset: node.fileOffset);
 
     VariableDeclaration valueVariable;
     Expression valueExpression;
@@ -3132,31 +3482,8 @@
       valueExpression = createVariableGet(valueVariable);
     }
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments('[]=', receiverType),
-          node.writeOffset,
-          '[]='.length);
-    } else if (writeTarget.isExtensionMember) {
-      assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
-      write = new StaticInvocation(
-          writeTarget.member,
-          new Arguments(
-              <Expression>[writeReceiver, writeIndex, valueExpression],
-              types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.writeOffset)
-        ..fileOffset = node.writeOffset;
-    } else {
-      write = new MethodInvocation(
-          writeReceiver,
-          indexSetName,
-          new Arguments(<Expression>[writeIndex, valueExpression])
-            ..fileOffset = node.writeOffset,
-          writeTarget.member)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
+        receiverType, writeTarget, writeIndex, valueExpression);
 
     Expression inner;
     if (node.forEffect) {
@@ -3205,13 +3532,15 @@
 
     Expression replacement;
     if (receiverVariable != null) {
-      node.replaceWith(replacement = new Let(receiverVariable, inner)
-        ..fileOffset = node.fileOffset);
+      replacement = new Let(receiverVariable, inner)
+        ..fileOffset = node.fileOffset;
     } else {
-      node.replaceWith(replacement = inner);
+      replacement = inner;
     }
-    return new ExpressionInferenceResult(
-        node.forPostIncDec ? readType : binaryType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        node.forPostIncDec ? readType : binaryType,
+        replacement,
+        nullAwareGuard);
   }
 
   ExpressionInferenceResult visitNullAwareCompoundSet(
@@ -3221,7 +3550,7 @@
         isVoidAllowed: true);
     DartType receiverType = receiverResult.inferredType;
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariableForResult(receiverResult);
     Expression readReceiver = createVariableGet(receiverVariable);
     Expression writeReceiver = createVariableGet(receiverVariable);
 
@@ -3229,47 +3558,11 @@
         .findInterfaceMember(receiverType, equalsName, node.receiver.fileOffset)
         .member;
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
-        receiverType, node.propertyName, node.readOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind readCheckKind =
-        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
-            isThisReceiver: node.receiver is ThisExpression);
-
-    DartType readType = inferrer.getGetterType(readTarget, receiverType);
-
-    Expression read;
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              node.propertyName.name, receiverType),
-          node.readOffset,
-          node.propertyName.name.length);
-    } else if (readTarget.isExtensionMember) {
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            readReceiver,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    } else {
-      read = new PropertyGet(readReceiver, node.propertyName, readTarget.member)
-        ..fileOffset = node.readOffset;
-      if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.readOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        read = new AsExpression(read, readType)
-          ..isTypeError = true
-          ..fileOffset = node.readOffset;
-      }
-    }
+    ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
+        readReceiver, receiverType, node.propertyName, const UnknownType(),
+        isThisReceiver: node.receiver is ThisExpression);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
 
     VariableDeclaration leftVariable;
     Expression left;
@@ -3282,79 +3575,18 @@
       left = read;
     }
 
-    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
-        readType, node.binaryName, node.binaryOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind binaryCheckKind =
-        inferrer.preCheckInvocationContravariance(readType, binaryTarget,
-            isThisReceiver: false);
-
-    DartType binaryType = inferrer.getReturnType(binaryTarget, readType);
-    DartType rhsType =
-        inferrer.getPositionalParameterTypeForTarget(binaryTarget, readType, 0);
-
-    ExpressionInferenceResult rhsResult =
-        inferrer.inferExpression(node.rhs, rhsType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        rhsType, rhsResult.inferredType, node.rhs, node.rhs.fileOffset);
-
-    if (inferrer.isOverloadedArithmeticOperatorAndType(
-        binaryTarget, readType)) {
-      binaryType = inferrer.typeSchemaEnvironment
-          .getTypeOfOverloadedArithmetic(readType, rhsResult.inferredType);
-    }
-
-    Expression binary;
-    if (binaryTarget.isMissing) {
-      binary = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.binaryName.name, readType),
-          node.binaryOffset,
-          node.binaryName.name.length);
-    } else if (binaryTarget.isExtensionMember) {
-      binary = new StaticInvocation(
-          binaryTarget.member,
-          new Arguments(<Expression>[
-            left,
-            node.rhs,
-          ], types: binaryTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.binaryOffset)
-        ..fileOffset = node.binaryOffset;
-    } else {
-      binary = new MethodInvocation(
-          left,
-          node.binaryName,
-          new Arguments(<Expression>[
-            node.rhs,
-          ])
-            ..fileOffset = node.binaryOffset,
-          binaryTarget.member)
-        ..fileOffset = node.binaryOffset;
-
-      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.binaryOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        binary = new AsExpression(binary, binaryType)
-          ..isTypeError = true
-          ..fileOffset = node.binaryOffset;
-      }
-    }
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, left, readType, node.binaryName, node.rhs);
+    Expression binary = binaryResult.expression;
+    DartType binaryType = binaryResult.inferredType;
 
     ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
         receiverType, node.propertyName, node.writeOffset,
         setter: true, includeExtensionMethods: true);
 
     DartType valueType = inferrer.getSetterType(writeTarget, receiverType);
-    Expression binaryReplacement = inferrer.ensureAssignable(
-        valueType, binaryType, binary, node.fileOffset);
-    if (binaryReplacement != null) {
-      binary = binaryReplacement;
-    }
+    binary = inferrer.ensureAssignable(valueType, binaryType, binary,
+        fileOffset: node.fileOffset);
 
     VariableDeclaration valueVariable;
     Expression valueExpression;
@@ -3365,30 +3597,13 @@
       valueExpression = createVariableGet(valueVariable);
     }
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              node.propertyName.name, receiverType),
-          node.writeOffset,
-          node.propertyName.name.length);
-    } else if (writeTarget.isExtensionMember) {
-      write = new StaticInvocation(
-          writeTarget.member,
-          new Arguments(<Expression>[writeReceiver, valueExpression],
-              types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.writeOffset)
-        ..fileOffset = node.writeOffset;
-    } else {
-      write = new PropertySet(
-          writeReceiver, node.propertyName, valueExpression, writeTarget.member)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computePropertySet(node.writeOffset, writeReceiver,
+        receiverType, node.propertyName, writeTarget, valueExpression,
+        forEffect: true);
 
     DartType resultType = node.forPostIncDec ? readType : binaryType;
 
-    Expression replacement;
+    Expression action;
     if (node.forEffect) {
       assert(leftVariable == null);
       assert(valueVariable == null);
@@ -3400,13 +3615,7 @@
       //             receiverVariable.propertyName + rhs
       //
 
-      MethodInvocation equalsNull = createEqualsNull(
-          receiverVariable.fileOffset,
-          createVariableGet(receiverVariable),
-          equalsMember);
-      ConditionalExpression condition = new ConditionalExpression(equalsNull,
-          new NullLiteral()..fileOffset = node.readOffset, write, resultType);
-      replacement = createLet(receiverVariable, condition);
+      action = write;
     } else if (node.forPostIncDec) {
       // Encode `receiver?.propertyName binaryName= rhs` from a postfix
       // expression like `o?.a++` as:
@@ -3424,17 +3633,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      MethodInvocation equalsNull = createEqualsNull(
-          receiverVariable.fileOffset,
-          createVariableGet(receiverVariable),
-          equalsMember);
-      ConditionalExpression condition = new ConditionalExpression(
-          equalsNull,
-          new NullLiteral()..fileOffset = node.readOffset,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))),
-          resultType);
-      replacement = createLet(receiverVariable, condition);
+      action = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `receiver?.propertyName binaryName= rhs` as:
       //
@@ -3452,21 +3652,12 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      MethodInvocation equalsNull = createEqualsNull(
-          receiverVariable.fileOffset,
-          createVariableGet(receiverVariable),
-          equalsMember);
-      ConditionalExpression condition = new ConditionalExpression(
-          equalsNull,
-          new NullLiteral()..fileOffset = node.readOffset,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          resultType);
-      replacement = createLet(receiverVariable, condition);
+      action = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
     }
 
-    node.replaceWith(replacement);
-    return new ExpressionInferenceResult(resultType, replacement);
+    return new ExpressionInferenceResult.nullAware(resultType, action,
+        new NullAwareGuard(receiverVariable, node.fileOffset, equalsMember));
   }
 
   ExpressionInferenceResult visitCompoundSuperIndexSet(
@@ -3481,22 +3672,15 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
     Expression readIndex = createVariableGet(indexVariable);
-    Expression readIndexReplacement = inferrer.ensureAssignable(readIndexType,
-        indexResult.inferredType, readIndex, readIndex.fileOffset);
-    if (readIndexReplacement != null) {
-      readIndex = readIndexReplacement;
-    }
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
 
     Expression read;
     if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments('[]'),
-          node.readOffset,
-          '[]'.length);
+      read = inferrer.createMissingSuperIndexGet(node.readOffset, readIndex);
     } else {
       assert(readTarget.isInstanceMember);
       inferrer.instrumentation?.record(
@@ -3525,68 +3709,10 @@
       left = read;
     }
 
-    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
-        readType, node.binaryName, node.binaryOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind binaryCheckKind =
-        inferrer.preCheckInvocationContravariance(readType, binaryTarget,
-            isThisReceiver: false);
-
-    DartType binaryType = inferrer.getReturnType(binaryTarget, readType);
-    DartType rhsType =
-        inferrer.getPositionalParameterTypeForTarget(binaryTarget, readType, 0);
-
-    ExpressionInferenceResult rhsResult =
-        inferrer.inferExpression(node.rhs, rhsType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        rhsType, rhsResult.inferredType, node.rhs, node.rhs.fileOffset);
-
-    if (inferrer.isOverloadedArithmeticOperatorAndType(
-        binaryTarget, readType)) {
-      binaryType = inferrer.typeSchemaEnvironment
-          .getTypeOfOverloadedArithmetic(readType, rhsResult.inferredType);
-    }
-
-    Expression binary;
-    if (binaryTarget.isMissing) {
-      binary = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.binaryName.name, readType),
-          node.binaryOffset,
-          node.binaryName.name.length);
-    } else if (binaryTarget.isExtensionMember) {
-      binary = new StaticInvocation(
-          binaryTarget.member,
-          new Arguments(<Expression>[
-            left,
-            node.rhs,
-          ], types: binaryTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.binaryOffset)
-        ..fileOffset = node.binaryOffset;
-    } else {
-      binary = new MethodInvocation(
-          left,
-          node.binaryName,
-          new Arguments(<Expression>[
-            node.rhs,
-          ])
-            ..fileOffset = node.binaryOffset,
-          binaryTarget.member)
-        ..fileOffset = node.binaryOffset;
-
-      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.binaryOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        binary = new AsExpression(binary, binaryType)
-          ..isTypeError = true
-          ..fileOffset = node.binaryOffset;
-      }
-    }
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, left, readType, node.binaryName, node.rhs);
+    Expression binary = binaryResult.expression;
+    DartType binaryType = binaryResult.inferredType;
 
     ObjectAccessTarget writeTarget = node.setter != null
         ? new ObjectAccessTarget.interfaceMember(node.setter)
@@ -3595,16 +3721,14 @@
     DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
         writeTarget, inferrer.thisType, 0);
     Expression writeIndex = createVariableGet(indexVariable);
-    Expression writeIndexReplacement = inferrer.ensureAssignable(writeIndexType,
-        indexResult.inferredType, writeIndex, writeIndex.fileOffset);
-    if (writeIndexReplacement != null) {
-      writeIndex = writeIndexReplacement;
-    }
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     DartType valueType =
         inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
     Expression binaryReplacement = inferrer.ensureAssignable(
-        valueType, binaryType, binary, node.fileOffset);
+        valueType, binaryType, binary,
+        fileOffset: node.fileOffset);
     if (binaryReplacement != null) {
       binary = binaryReplacement;
     }
@@ -3621,10 +3745,8 @@
     Expression write;
 
     if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments('[]='),
-          node.writeOffset,
-          '[]='.length);
+      write = inferrer.createMissingSuperIndexSet(
+          node.writeOffset, writeIndex, valueExpression);
     } else {
       assert(writeTarget.isInstanceMember);
       inferrer.instrumentation?.record(
@@ -3684,7 +3806,6 @@
               createLet(writeVariable, createVariableGet(valueVariable))));
     }
 
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType, replacement);
   }
@@ -3707,46 +3828,32 @@
     DartType receiverType = inferrer.getPositionalParameterTypeForTarget(
         readTarget, receiverResult.inferredType, 0);
 
-    inferrer.ensureAssignable(receiverType, receiverResult.inferredType,
-        node.receiver, node.receiver.fileOffset);
+    Expression receiver =
+        inferrer.ensureAssignableResult(receiverType, receiverResult);
 
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariable(receiver, receiverType);
 
-    DartType readType = inferrer.getReturnType(readTarget, receiverType);
     DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
         readTarget, receiverType, 0);
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable =
-        createVariable(node.index, indexResult.inferredType);
+    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
     Expression readIndex = createVariableGet(indexVariable);
-    Expression readIndexReplacement = inferrer.ensureAssignable(readIndexType,
-        indexResult.inferredType, readIndex, readIndex.fileOffset);
-    if (readIndexReplacement != null) {
-      readIndex = readIndexReplacement;
-    }
+    readIndex = inferrer.ensureAssignable(
+        readIndexType, indexResult.inferredType, readIndex);
 
-    Expression read;
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              indexGetName.name, receiverType),
-          node.readOffset,
-          noLength);
-    } else {
-      assert(readTarget.isExtensionMember);
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            readIndex,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    }
+    ExpressionInferenceResult readResult = _computeIndexGet(
+        node.readOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        readTarget,
+        readIndex,
+        MethodContravarianceCheckKind.none);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
 
     VariableDeclaration leftVariable;
     Expression left;
@@ -3759,68 +3866,10 @@
       left = read;
     }
 
-    ObjectAccessTarget binaryTarget = inferrer.findInterfaceMember(
-        readType, node.binaryName, node.binaryOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind binaryCheckKind =
-        inferrer.preCheckInvocationContravariance(readType, binaryTarget,
-            isThisReceiver: false);
-
-    DartType binaryType = inferrer.getReturnType(binaryTarget, readType);
-    DartType rhsType =
-        inferrer.getPositionalParameterTypeForTarget(binaryTarget, readType, 0);
-
-    ExpressionInferenceResult rhsResult =
-        inferrer.inferExpression(node.rhs, rhsType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        rhsType, rhsResult.inferredType, node.rhs, node.rhs.fileOffset);
-
-    if (inferrer.isOverloadedArithmeticOperatorAndType(
-        binaryTarget, readType)) {
-      binaryType = inferrer.typeSchemaEnvironment
-          .getTypeOfOverloadedArithmetic(readType, rhsResult.inferredType);
-    }
-
-    Expression binary;
-    if (binaryTarget.isMissing) {
-      binary = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.binaryName.name, readType),
-          node.binaryOffset,
-          node.binaryName.name.length);
-    } else if (binaryTarget.isExtensionMember) {
-      binary = new StaticInvocation(
-          binaryTarget.member,
-          new Arguments(<Expression>[
-            left,
-            node.rhs,
-          ], types: binaryTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.binaryOffset)
-        ..fileOffset = node.binaryOffset;
-    } else {
-      binary = new MethodInvocation(
-          left,
-          node.binaryName,
-          new Arguments(<Expression>[
-            node.rhs,
-          ])
-            ..fileOffset = node.binaryOffset,
-          binaryTarget.member)
-        ..fileOffset = node.binaryOffset;
-
-      if (binaryCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.binaryOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        binary = new AsExpression(binary, binaryType)
-          ..isTypeError = true
-          ..fileOffset = node.binaryOffset;
-      }
-    }
+    ExpressionInferenceResult binaryResult = _computeBinaryExpression(
+        node.binaryOffset, left, readType, node.binaryName, node.rhs);
+    Expression binary = binaryResult.expression;
+    DartType binaryType = binaryResult.inferredType;
 
     ObjectAccessTarget writeTarget = node.setter != null
         ? new ExtensionAccessTarget(
@@ -3830,19 +3879,13 @@
     DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
         writeTarget, receiverType, 0);
     Expression writeIndex = createVariableGet(indexVariable);
-    Expression writeIndexReplacement = inferrer.ensureAssignable(writeIndexType,
-        indexResult.inferredType, writeIndex, writeIndex.fileOffset);
-    if (writeIndexReplacement != null) {
-      writeIndex = writeIndexReplacement;
-    }
+    writeIndex = inferrer.ensureAssignable(
+        writeIndexType, indexResult.inferredType, writeIndex);
 
     DartType valueType =
         inferrer.getIndexSetValueType(writeTarget, inferrer.thisType);
-    Expression binaryReplacement = inferrer.ensureAssignable(
-        valueType, binaryType, binary, node.fileOffset);
-    if (binaryReplacement != null) {
-      binary = binaryReplacement;
-    }
+    binary = inferrer.ensureAssignable(valueType, binaryType, binary,
+        fileOffset: node.fileOffset);
 
     VariableDeclaration valueVariable;
     Expression valueExpression;
@@ -3853,26 +3896,13 @@
       valueExpression = createVariableGet(valueVariable);
     }
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(
-              indexSetName.name, receiverType),
-          node.writeOffset,
-          noLength);
-    } else {
-      assert(writeTarget.isExtensionMember);
-      write = new StaticInvocation(
-          writeTarget.member,
-          new Arguments(<Expression>[
-            createVariableGet(receiverVariable),
-            writeIndex,
-            valueExpression
-          ], types: writeTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.writeOffset)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computeIndexSet(
+        node.writeOffset,
+        createVariableGet(receiverVariable),
+        receiverType,
+        writeTarget,
+        writeIndex,
+        valueExpression);
 
     Expression inner;
     if (node.forEffect) {
@@ -3927,8 +3957,6 @@
 
     Expression replacement = new Let(receiverVariable, inner)
       ..fileOffset = node.fileOffset;
-
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType, replacement);
   }
@@ -3936,75 +3964,67 @@
   @override
   ExpressionInferenceResult visitNullLiteral(
       NullLiteral node, DartType typeContext) {
-    return new ExpressionInferenceResult(inferrer.coreTypes.nullType);
+    return new ExpressionInferenceResult(inferrer.coreTypes.nullType, node);
   }
 
   @override
   ExpressionInferenceResult visitLet(Let node, DartType typeContext) {
     DartType variableType = node.variable.type;
-    inferrer.inferExpression(node.variable.initializer, variableType, true,
+    ExpressionInferenceResult initializerResult = inferrer.inferExpression(
+        node.variable.initializer, variableType, true,
         isVoidAllowed: true);
-    ExpressionInferenceResult result = inferrer
+    node.variable.initializer = initializerResult.expression
+      ..parent = node.variable;
+    ExpressionInferenceResult bodyResult = inferrer
         .inferExpression(node.body, typeContext, true, isVoidAllowed: true);
-    DartType inferredType = result.inferredType;
-    return new ExpressionInferenceResult(inferredType);
+    node.body = bodyResult.expression..parent = node;
+    DartType inferredType = bodyResult.inferredType;
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
   ExpressionInferenceResult visitPropertySet(
       covariant PropertySetImpl node, DartType typeContext) {
-    DartType receiverType = inferrer
-        .inferExpression(node.receiver, const UnknownType(), true,
-            isVoidAllowed: false)
-        .inferredType;
-    ObjectAccessTarget target =
-        inferrer.findPropertySetMember(receiverType, node);
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+    DartType receiverType = receiverResult.inferredType;
+    Expression receiver;
+    NullAwareGuard nullAwareGuard;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = receiverResult.nullAwareGuard;
+      receiver = receiverResult.nullAwareAction;
+    } else {
+      receiver = receiverResult.expression;
+    }
+    ObjectAccessTarget target = inferrer.findInterfaceMember(
+        receiverType, node.name, node.fileOffset,
+        setter: true, instrumented: true, includeExtensionMethods: true);
+    if (target.isInstanceMember) {
+      if (inferrer.instrumentation != null &&
+          receiverType == const DynamicType()) {
+        inferrer.instrumentation.record(
+            inferrer.uriForInstrumentation,
+            node.fileOffset,
+            'target',
+            new InstrumentationValueForMember(target.member));
+      }
+      node.interfaceTarget = target.member;
+    }
     DartType writeContext = inferrer.getSetterType(target, receiverType);
     ExpressionInferenceResult rhsResult = inferrer.inferExpression(
         node.value, writeContext ?? const UnknownType(), true,
         isVoidAllowed: true);
     DartType rhsType = rhsResult.inferredType;
-    inferrer.ensureAssignable(
-        writeContext, rhsType, node.value, node.fileOffset,
-        isVoidAllowed: writeContext is VoidType);
-    Expression replacement;
-    if (target.isExtensionMember) {
-      if (node.forEffect) {
-        replacement = new StaticInvocation(
-            target.member,
-            new Arguments(<Expression>[node.receiver, node.value],
-                types: target.inferredExtensionTypeArguments)
-              ..fileOffset = node.fileOffset)
-          ..fileOffset = node.fileOffset;
-      } else {
-        Expression receiver;
-        VariableDeclaration receiverVariable;
-        if (node.readOnlyReceiver) {
-          receiver = node.receiver;
-        } else {
-          receiverVariable = createVariable(node.receiver, receiverType);
-          receiver = createVariableGet(receiverVariable);
-        }
-        VariableDeclaration valueVariable = createVariable(node.value, rhsType);
-        VariableDeclaration assignmentVariable = createVariable(
-            new StaticInvocation(
-                target.member,
-                new Arguments(
-                    <Expression>[receiver, createVariableGet(valueVariable)],
-                    types: target.inferredExtensionTypeArguments)
-                  ..fileOffset = node.fileOffset)
-              ..fileOffset = node.fileOffset,
-            const VoidType());
-        replacement = createLet(valueVariable,
-            createLet(assignmentVariable, createVariableGet(valueVariable)));
-        if (receiverVariable != null) {
-          replacement = createLet(receiverVariable, replacement);
-        }
-        replacement..fileOffset = node.fileOffset;
-      }
-      node.replaceWith(replacement);
-    }
-    return new ExpressionInferenceResult(rhsType, replacement);
+    Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
+        fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
+
+    Expression replacement = _computePropertySet(
+        node.fileOffset, receiver, receiverType, node.name, target, rhs,
+        valueType: rhsType, forEffect: node.forEffect);
+
+    return new ExpressionInferenceResult.nullAware(
+        rhsType, replacement, nullAwareGuard);
   }
 
   ExpressionInferenceResult visitNullAwareIfNullSet(
@@ -4014,7 +4034,7 @@
         isVoidAllowed: false);
     DartType receiverType = receiverResult.inferredType;
     VariableDeclaration receiverVariable =
-        createVariable(node.receiver, receiverType);
+        createVariableForResult(receiverResult);
     Expression readReceiver = createVariableGet(receiverVariable);
     Expression writeReceiver = createVariableGet(receiverVariable);
 
@@ -4022,51 +4042,16 @@
         .findInterfaceMember(receiverType, equalsName, node.receiver.fileOffset)
         .member;
 
-    ObjectAccessTarget readTarget = inferrer.findInterfaceMember(
-        receiverType, node.name, node.readOffset,
-        includeExtensionMethods: true);
-
-    MethodContravarianceCheckKind readCheckKind =
-        inferrer.preCheckInvocationContravariance(receiverType, readTarget,
-            isThisReceiver: node.receiver is ThisExpression);
-
-    DartType readType = inferrer.getGetterType(readTarget, receiverType);
+    ExpressionInferenceResult readResult = _computePropertyGet(
+        node.readOffset, readReceiver, receiverType, node.name, typeContext,
+        isThisReceiver: node.receiver is ThisExpression);
+    Expression read = readResult.expression;
+    DartType readType = readResult.inferredType;
 
     Member readEqualsMember = inferrer
         .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
-    Expression read;
-    if (readTarget.isMissing) {
-      read = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.name.name, receiverType),
-          node.readOffset,
-          node.name.name.length);
-    } else if (readTarget.isExtensionMember) {
-      read = new StaticInvocation(
-          readTarget.member,
-          new Arguments(<Expression>[
-            readReceiver,
-          ], types: readTarget.inferredExtensionTypeArguments)
-            ..fileOffset = node.readOffset)
-        ..fileOffset = node.readOffset;
-    } else {
-      read = new PropertyGet(readReceiver, node.name, readTarget.member)
-        ..fileOffset = node.readOffset;
-      if (readCheckKind == MethodContravarianceCheckKind.checkMethodReturn) {
-        if (inferrer.instrumentation != null) {
-          inferrer.instrumentation.record(
-              inferrer.uriForInstrumentation,
-              node.readOffset,
-              'checkReturn',
-              new InstrumentationValueForType(readType));
-        }
-        read = new AsExpression(read, readType)
-          ..isTypeError = true
-          ..fileOffset = node.readOffset;
-      }
-    }
-
     VariableDeclaration readVariable;
     if (!node.forEffect) {
       readVariable = createVariable(read, readType);
@@ -4081,46 +4066,11 @@
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
-    inferrer.ensureAssignable(
-        valueType, valueResult.inferredType, node.value, node.value.fileOffset);
+    Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
-    Expression write;
-
-    if (writeTarget.isMissing) {
-      write = inferrer.helper.buildProblem(
-          templateUndefinedMethod.withArguments(node.name.name, receiverType),
-          node.writeOffset,
-          node.name.name.length);
-    } else if (writeTarget.isExtensionMember) {
-      if (node.forEffect) {
-        write = new StaticInvocation(
-            writeTarget.member,
-            new Arguments(<Expression>[writeReceiver, node.value],
-                types: writeTarget.inferredExtensionTypeArguments)
-              ..fileOffset = node.writeOffset)
-          ..fileOffset = node.writeOffset;
-      } else {
-        VariableDeclaration valueVariable =
-            createVariable(node.value, valueResult.inferredType);
-        VariableDeclaration assignmentVariable = createVariable(
-            new StaticInvocation(
-                writeTarget.member,
-                new Arguments(<Expression>[
-                  writeReceiver,
-                  createVariableGet(valueVariable)
-                ], types: writeTarget.inferredExtensionTypeArguments)
-                  ..fileOffset = node.writeOffset)
-              ..fileOffset = node.writeOffset,
-            const VoidType());
-        write = createLet(valueVariable,
-            createLet(assignmentVariable, createVariableGet(valueVariable)))
-          ..fileOffset = node.writeOffset;
-      }
-    } else {
-      write = new PropertySet(
-          writeReceiver, node.name, node.value, writeTarget.member)
-        ..fileOffset = node.writeOffset;
-    }
+    Expression write = _computePropertySet(node.writeOffset, writeReceiver,
+        receiverType, node.name, writeTarget, value,
+        valueType: valueResult.inferredType, forEffect: node.forEffect);
 
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(readType, valueResult.inferredType);
@@ -4180,15 +4130,29 @@
       replacement = createLet(receiverVariable, outerCondition);
     }
 
-    node.replaceWith(replacement);
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
   @override
   ExpressionInferenceResult visitPropertyGet(
       PropertyGet node, DartType typeContext) {
-    return inferrer.inferPropertyGet(
-        node, node.receiver, node.fileOffset, typeContext, node);
+    ExpressionInferenceResult result =
+        inferrer.inferExpression(node.receiver, const UnknownType(), true);
+    NullAwareGuard nullAwareGuard;
+    Expression receiver;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuard = result.nullAwareGuard;
+      receiver = result.nullAwareAction;
+    } else {
+      receiver = result.expression;
+    }
+    node.receiver = receiver..parent = node;
+    DartType receiverType = result.inferredType;
+    ExpressionInferenceResult readResult = _computePropertyGet(
+        node.fileOffset, receiver, receiverType, node.name, typeContext,
+        isThisReceiver: node.receiver is ThisExpression);
+    return new ExpressionInferenceResult.nullAware(
+        readResult.inferredType, readResult.expression, nullAwareGuard);
   }
 
   @override
@@ -4210,7 +4174,8 @@
 
   @override
   ExpressionInferenceResult visitRethrow(Rethrow node, DartType typeContext) {
-    return const ExpressionInferenceResult(const BottomType());
+    inferrer.flowAnalysis.handleExit();
+    return new ExpressionInferenceResult(const BottomType(), node);
   }
 
   @override
@@ -4221,14 +4186,16 @@
         : const UnknownType();
     DartType inferredType;
     if (node.expression != null) {
-      inferredType = inferrer
-          .inferExpression(node.expression, typeContext, true,
-              isVoidAllowed: true)
-          .inferredType;
+      ExpressionInferenceResult expressionResult = inferrer.inferExpression(
+          node.expression, typeContext, true,
+          isVoidAllowed: true);
+      node.expression = expressionResult.expression..parent = node;
+      inferredType = expressionResult.inferredType;
     } else {
       inferredType = inferrer.coreTypes.nullType;
     }
     closureContext.handleReturn(inferrer, node, inferredType, node.isArrow);
+    inferrer.flowAnalysis.handleExit();
   }
 
   @override
@@ -4260,16 +4227,16 @@
       inferredTypeArgument = node.typeArgument;
     }
     if (inferenceNeeded || typeChecksNeeded) {
-      for (int i = 0; i < node.expressions.length; ++i) {
-        DartType type = inferElement(
-            node.expressions[i],
-            node,
+      for (int index = 0; index < node.expressions.length; ++index) {
+        ExpressionInferenceResult result = inferElement(
+            node.expressions[index],
             inferredTypeArgument,
             inferredSpreadTypes,
             inferredConditionTypes,
             inferenceNeeded,
             typeChecksNeeded);
-        actualTypes.add(type);
+        node.expressions[index] = result.expression..parent = node;
+        actualTypes.add(result.inferredType);
         if (inferenceNeeded) {
           formalTypes.add(setType.typeArguments[0]);
         }
@@ -4310,7 +4277,7 @@
         inferrer.helper.transformSetLiterals = true;
       }
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -4322,11 +4289,11 @@
     ExpressionInferenceResult rhsResult = inferrer.inferExpression(
         node.value, writeContext ?? const UnknownType(), true,
         isVoidAllowed: true);
+    Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
+        fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
+    node.value = rhs..parent = node;
     DartType rhsType = rhsResult.inferredType;
-    inferrer.ensureAssignable(
-        writeContext, rhsType, node.value, node.fileOffset,
-        isVoidAllowed: writeContext is VoidType);
-    return new ExpressionInferenceResult(rhsType);
+    return new ExpressionInferenceResult(rhsType, node);
   }
 
   @override
@@ -4336,9 +4303,10 @@
     TypeInferenceEngine.resolveInferenceNode(target);
     DartType type = target.getterType;
     if (target is Procedure && target.kind == ProcedureKind.Method) {
-      type = inferrer.instantiateTearOff(type, typeContext, node);
+      return inferrer.instantiateTearOff(type, typeContext, node);
+    } else {
+      return new ExpressionInferenceResult(type, node);
     }
-    return new ExpressionInferenceResult(type);
   }
 
   @override
@@ -4357,28 +4325,29 @@
           inferrer.helper.uri,
           typeArgumentsInfo);
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
   ExpressionInferenceResult visitStringConcatenation(
       StringConcatenation node, DartType typeContext) {
     if (!inferrer.isTopLevel) {
-      for (Expression expression in node.expressions) {
-        inferrer.inferExpression(
-            expression, const UnknownType(), !inferrer.isTopLevel,
+      for (int index = 0; index < node.expressions.length; index++) {
+        ExpressionInferenceResult result = inferrer.inferExpression(
+            node.expressions[index], const UnknownType(), !inferrer.isTopLevel,
             isVoidAllowed: false);
+        node.expressions[index] = result.expression..parent = node;
       }
     }
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable), node);
   }
 
   @override
   ExpressionInferenceResult visitStringLiteral(
       StringLiteral node, DartType typeContext) {
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable));
+        inferrer.coreTypes.stringRawType(inferrer.library.nonNullable), node);
   }
 
   @override
@@ -4406,13 +4375,12 @@
           'target',
           new InstrumentationValueForMember(node.interfaceTarget));
     }
-    ExpressionInferenceResult result = inferrer.inferSuperMethodInvocation(
+    return inferrer.inferSuperMethodInvocation(
         node,
         typeContext,
         node.interfaceTarget != null
             ? new ObjectAccessTarget.interfaceMember(node.interfaceTarget)
             : const ObjectAccessTarget.unresolved());
-    return new ExpressionInferenceResult(result.inferredType);
   }
 
   @override
@@ -4449,29 +4417,33 @@
     ExpressionInferenceResult rhsResult = inferrer.inferExpression(
         node.value, writeContext ?? const UnknownType(), true,
         isVoidAllowed: true);
-    DartType rhsType = rhsResult.inferredType;
-    inferrer.ensureAssignable(
-        writeContext, rhsType, node.value, node.fileOffset,
-        isVoidAllowed: writeContext is VoidType);
-
-    return new ExpressionInferenceResult(rhsType);
+    Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
+        fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
+    node.value = rhs..parent = node;
+    return new ExpressionInferenceResult(rhsResult.inferredType, node);
   }
 
   @override
   void visitSwitchStatement(SwitchStatement node) {
-    DartType expressionType = inferrer
-        .inferExpression(node.expression, const UnknownType(), true,
-            isVoidAllowed: false)
-        .inferredType;
+    ExpressionInferenceResult expressionResult = inferrer.inferExpression(
+        node.expression, const UnknownType(), true,
+        isVoidAllowed: false);
+    node.expression = expressionResult.expression..parent = node;
+    DartType expressionType = expressionResult.inferredType;
+    inferrer.flowAnalysis.switchStatement_expressionEnd(node);
 
+    bool hasDefault = false;
     for (SwitchCase switchCase in node.cases) {
-      for (Expression caseExpression in switchCase.expressions) {
+      hasDefault = hasDefault || switchCase.isDefault;
+      // TODO(dmitryas): Pass in the actual value for the first parameter.
+      inferrer.flowAnalysis.switchStatement_beginCase(false, node);
+      for (int index = 0; index < switchCase.expressions.length; index++) {
         ExpressionInferenceResult caseExpressionResult =
-            inferrer.inferExpression(caseExpression, expressionType, true,
+            inferrer.inferExpression(
+                switchCase.expressions[index], expressionType, true,
                 isVoidAllowed: false);
-        if (caseExpressionResult.replacement != null) {
-          caseExpression = caseExpressionResult.replacement;
-        }
+        Expression caseExpression = caseExpressionResult.expression;
+        switchCase.expressions[index] = caseExpression..parent = switchCase;
         DartType caseExpressionType = caseExpressionResult.inferredType;
 
         // Check whether the expression type is assignable to the case
@@ -4492,6 +4464,7 @@
       }
       inferrer.inferStatement(switchCase.body);
     }
+    inferrer.flowAnalysis.switchStatement_end(hasDefault);
   }
 
   @override
@@ -4499,20 +4472,22 @@
       SymbolLiteral node, DartType typeContext) {
     DartType inferredType =
         inferrer.coreTypes.symbolRawType(inferrer.library.nonNullable);
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   ExpressionInferenceResult visitThisExpression(
       ThisExpression node, DartType typeContext) {
-    return new ExpressionInferenceResult(inferrer.thisType);
+    return new ExpressionInferenceResult(inferrer.thisType, node);
   }
 
   @override
   ExpressionInferenceResult visitThrow(Throw node, DartType typeContext) {
-    inferrer.inferExpression(
+    ExpressionInferenceResult expressionResult = inferrer.inferExpression(
         node.expression, const UnknownType(), !inferrer.isTopLevel,
         isVoidAllowed: false);
-    return const ExpressionInferenceResult(const BottomType());
+    node.expression = expressionResult.expression..parent = node;
+    inferrer.flowAnalysis.handleExit();
+    return new ExpressionInferenceResult(const BottomType(), node);
   }
 
   void visitCatch(Catch node) {
@@ -4521,16 +4496,27 @@
 
   @override
   void visitTryCatch(TryCatch node) {
+    inferrer.flowAnalysis.tryCatchStatement_bodyBegin();
     inferrer.inferStatement(node.body);
+    inferrer.flowAnalysis.tryCatchStatement_bodyEnd(node.body);
     for (Catch catch_ in node.catches) {
+      inferrer.flowAnalysis
+          .tryCatchStatement_catchBegin(catch_.exception, catch_.stackTrace);
+      inferrer.flowAnalysis.initialize(catch_.exception);
+      inferrer.flowAnalysis.initialize(catch_.stackTrace);
       visitCatch(catch_);
+      inferrer.flowAnalysis.tryCatchStatement_catchEnd();
     }
+    inferrer.flowAnalysis.tryCatchStatement_end();
   }
 
   @override
   void visitTryFinally(TryFinally node) {
+    inferrer.flowAnalysis.tryFinallyStatement_bodyBegin();
     inferrer.inferStatement(node.body);
+    inferrer.flowAnalysis.tryFinallyStatement_finallyBegin(node.finalizer);
     inferrer.inferStatement(node.finalizer);
+    inferrer.flowAnalysis.tryFinallyStatement_end(node.finalizer);
   }
 
   @override
@@ -4538,7 +4524,7 @@
       TypeLiteral node, DartType typeContext) {
     DartType inferredType =
         inferrer.coreTypes.typeRawType(inferrer.library.nonNullable);
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   @override
@@ -4548,11 +4534,10 @@
     ExpressionInferenceResult rhsResult = inferrer.inferExpression(
         node.value, writeContext ?? const UnknownType(), true,
         isVoidAllowed: true);
-    DartType rhsType = rhsResult.inferredType;
-    inferrer.ensureAssignable(
-        writeContext, rhsType, node.value, node.fileOffset,
-        isVoidAllowed: writeContext is VoidType);
-    return new ExpressionInferenceResult(rhsType);
+    Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
+        fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
+    node.value = rhs..parent = node;
+    return new ExpressionInferenceResult(rhsResult.inferredType, node);
   }
 
   @override
@@ -4560,15 +4545,13 @@
     DartType declaredType =
         node._implicitlyTyped ? const UnknownType() : node.type;
     DartType inferredType;
-    DartType initializerType;
+    ExpressionInferenceResult initializerResult;
     if (node.initializer != null) {
-      ExpressionInferenceResult initializerResult = inferrer.inferExpression(
-          node.initializer,
-          declaredType,
-          !inferrer.isTopLevel || node._implicitlyTyped,
+      initializerResult = inferrer.inferExpression(node.initializer,
+          declaredType, !inferrer.isTopLevel || node._implicitlyTyped,
           isVoidAllowed: true);
-      initializerType = initializerResult.inferredType;
-      inferredType = inferrer.inferDeclarationType(initializerType);
+      inferredType =
+          inferrer.inferDeclarationType(initializerResult.inferredType);
     } else {
       inferredType = const DynamicType();
     }
@@ -4580,13 +4563,11 @@
           new InstrumentationValueForType(inferredType));
       node.type = inferredType;
     }
-    if (node.initializer != null) {
-      Expression replacedInitializer = inferrer.ensureAssignable(
-          node.type, initializerType, node.initializer, node.fileOffset,
-          isVoidAllowed: node.type is VoidType);
-      if (replacedInitializer != null) {
-        node.initializer = replacedInitializer;
-      }
+    if (initializerResult != null) {
+      Expression initializer = inferrer.ensureAssignableResult(
+          node.type, initializerResult,
+          fileOffset: node.fileOffset, isVoidAllowed: node.type is VoidType);
+      node.initializer = initializer..parent = node;
     }
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
@@ -4617,28 +4598,29 @@
     node.promotedType = promotedType;
     DartType type = promotedType ?? declaredOrInferredType;
     if (variable._isLocalFunction) {
-      type = inferrer.instantiateTearOff(type, typeContext, node);
+      return inferrer.instantiateTearOff(type, typeContext, node);
+    } else {
+      return new ExpressionInferenceResult(type, node);
     }
-    return new ExpressionInferenceResult(type);
   }
 
   @override
   void visitWhileStatement(WhileStatement node) {
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
-    DartType conditionType = inferrer
-        .inferExpression(node.condition, expectedType, !inferrer.isTopLevel,
-            isVoidAllowed: false)
-        .inferredType;
-    inferrer.ensureAssignable(
-        expectedType, conditionType, node.condition, node.condition.fileOffset);
+    ExpressionInferenceResult conditionResult = inferrer.inferExpression(
+        node.condition, expectedType, !inferrer.isTopLevel,
+        isVoidAllowed: false);
+    Expression condition =
+        inferrer.ensureAssignableResult(expectedType, conditionResult);
+    node.condition = condition..parent = node;
     inferrer.inferStatement(node.body);
   }
 
   @override
   void visitYieldStatement(YieldStatement node) {
     ClosureContext closureContext = inferrer.closureContext;
-    DartType inferredType;
+    ExpressionInferenceResult expressionResult;
     if (closureContext.isGenerator) {
       DartType typeContext = closureContext.returnOrYieldContext;
       if (node.isYieldStar && typeContext != null) {
@@ -4648,38 +4630,38 @@
                 ? inferrer.coreTypes.streamClass
                 : inferrer.coreTypes.iterableClass);
       }
-      inferredType = inferrer
-          .inferExpression(node.expression, typeContext, true,
-              isVoidAllowed: true)
-          .inferredType;
+      expressionResult = inferrer.inferExpression(
+          node.expression, typeContext, true,
+          isVoidAllowed: true);
     } else {
-      inferredType = inferrer
-          .inferExpression(node.expression, const UnknownType(), true,
-              isVoidAllowed: true)
-          .inferredType;
+      expressionResult = inferrer.inferExpression(
+          node.expression, const UnknownType(), true,
+          isVoidAllowed: true);
     }
-    closureContext.handleYield(inferrer, node.isYieldStar, inferredType,
-        node.expression, node.fileOffset);
+    closureContext.handleYield(inferrer, node, expressionResult);
   }
 
   @override
   ExpressionInferenceResult visitLoadLibrary(
       covariant LoadLibraryImpl node, DartType typeContext) {
-    DartType inferredType =
-        inferrer.typeSchemaEnvironment.futureType(const DynamicType());
+    DartType inferredType = inferrer.typeSchemaEnvironment
+        .futureType(const DynamicType(), Nullability.legacy);
     if (node.arguments != null) {
       FunctionType calleeType = new FunctionType([], inferredType);
       inferrer.inferInvocation(
           typeContext, node.fileOffset, calleeType, node.arguments);
     }
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, node);
   }
 
   ExpressionInferenceResult visitLoadLibraryTearOff(
       LoadLibraryTearOff node, DartType typeContext) {
     DartType inferredType = new FunctionType(
-        [], inferrer.typeSchemaEnvironment.futureType(const DynamicType()));
-    Expression replacement = node.replace();
+        [],
+        inferrer.typeSchemaEnvironment
+            .futureType(const DynamicType(), Nullability.legacy));
+    Expression replacement = new StaticGet(node.target)
+      ..fileOffset = node.fileOffset;
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -4688,6 +4670,16 @@
       CheckLibraryIsLoaded node, DartType typeContext) {
     // TODO(dmitryas): Figure out the suitable nullability for that.
     return new ExpressionInferenceResult(
-        inferrer.coreTypes.objectRawType(inferrer.library.nullable));
+        inferrer.coreTypes.objectRawType(inferrer.library.nullable), node);
   }
 }
+
+class ForInResult {
+  final VariableDeclaration variable;
+  final Expression iterable;
+  final Statement body;
+
+  ForInResult(this.variable, this.iterable, this.body);
+
+  String toString() => 'ForInResult($variable,$iterable,$body)';
+}
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 21cb163..ebbb736 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -19,7 +19,7 @@
 
 export 'implicit_field_type.dart' show ImplicitFieldType;
 
-export 'kernel_variable_builder.dart' show VariableBuilder;
+export 'kernel_variable_builder.dart' show VariableBuilderImpl;
 
 export 'load_library_builder.dart' show LoadLibraryBuilder;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 44da49f..5a7862b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -20,7 +20,7 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' hide Variance;
 
 import 'package:kernel/type_algebra.dart' show Substitution;
 
@@ -30,12 +30,11 @@
 
 import '../../base/instrumentation.dart'
     show
-        Instrumentation,
         InstrumentationValueForMember,
         InstrumentationValueForType,
         InstrumentationValueForTypeArgs;
 
-import '../builder/library_builder.dart' show LibraryBuilder;
+import '../builder/library_builder.dart';
 
 import '../fasta_codes.dart'
     show
@@ -43,7 +42,6 @@
         messageCantDisambiguateNotEnoughInformation,
         messageNonNullAwareSpreadIsNull,
         messageSwitchExpressionNotAssignableCause,
-        messageVoidExpression,
         noLength,
         templateCantInferTypeDueToCircularity,
         templateForInLoopElementTypeNotAssignable,
@@ -54,9 +52,8 @@
         templateSpreadMapEntryElementValueTypeMismatch,
         templateSpreadMapEntryTypeMismatch,
         templateSpreadTypeMismatch,
-        templateSuperclassHasNoMethod,
         templateSwitchExpressionNotAssignable,
-        templateUndefinedMethod,
+        templateUndefinedSetter,
         templateWebLiteralCannotBeRepresentedExactly;
 
 import '../names.dart';
@@ -67,11 +64,7 @@
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import '../type_inference/inference_helper.dart' show InferenceHelper;
-
-import '../type_inference/type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly, TypeInferenceEngine;
-
+import '../type_inference/type_inference_engine.dart';
 import '../type_inference/type_inferrer.dart';
 
 import '../type_inference/type_promotion.dart'
@@ -88,7 +81,6 @@
 
 import 'collections.dart'
     show
-        ControlFlowMapEntry,
         ForElement,
         ForInElement,
         ForInMapEntry,
@@ -99,8 +91,6 @@
         SpreadMapEntry,
         convertToElement;
 
-import 'expression_generator.dart' show makeLet;
-
 import 'implicit_type_argument.dart' show ImplicitTypeArgument;
 
 part "inference_visitor.dart";
@@ -255,6 +245,7 @@
 enum InternalExpressionKind {
   Cascade,
   CompoundExtensionIndexSet,
+  CompoundExtensionSet,
   CompoundIndexSet,
   CompoundPropertySet,
   CompoundSuperIndexSet,
@@ -287,15 +278,6 @@
 abstract class InternalExpression extends Expression {
   InternalExpressionKind get kind;
 
-  /// Replaces this [InternalExpression] with a semantically equivalent
-  /// [Expression] and returns the replacing [Expression].
-  ///
-  /// This method most be called after inference has been performed to ensure
-  /// that [InternalExpression] nodes do not leak.
-  Expression replace() {
-    throw new UnsupportedError('$runtimeType.replace()');
-  }
-
   @override
   R accept<R>(ExpressionVisitor<R> visitor) => visitor.defaultExpression(this);
 
@@ -385,86 +367,35 @@
 /// In the documentation that follows, `v` is referred to as the "cascade
 /// variable"--this is the variable that remembers the value of the expression
 /// preceding the first `..` while the cascades are being evaluated.
-///
-/// After constructing a [Cascade], the caller should
-/// call [finalize] with an expression representing the expression after the
-/// `..`.  If a further `..` follows that expression, the caller should call
-/// [extend] followed by [finalize] for each subsequent cascade.
-// TODO(johnniwinther): Change the representation to be direct and perform
-// the [Let] encoding in [replace].
 class Cascade extends InternalExpression {
+  /// The temporary variable holding the cascade receiver expression in its
+  /// initializer;
   VariableDeclaration variable;
 
-  /// Pointer to the first "let" expression in the cascade, i.e. `e1` in
-  /// `e..e1..e2..e3`;
-  Let _firstCascade;
-
-  /// Pointer to the last "let" expression in the cascade, i.e. `e3` in
-  //  /// `e..e1..e2..e3`;
-  Let _lastCascade;
+  /// The expressions performed on [variable].
+  final List<Expression> expressions = <Expression>[];
 
   /// Creates a [Cascade] using [variable] as the cascade
   /// variable.  Caller is responsible for ensuring that [variable]'s
   /// initializer is the expression preceding the first `..` of the cascade
   /// expression.
   Cascade(this.variable) {
-    _lastCascade = _firstCascade = makeLet(
-        new VariableDeclaration.forValue(new _UnfinishedCascade()),
-        new VariableGet(variable));
     variable?.parent = this;
-    _firstCascade.parent = this;
   }
 
   @override
   InternalExpressionKind get kind => InternalExpressionKind.Cascade;
 
-  /// The initial expression of the cascade, i.e. `e` in `e..e1..e2..e3`.
-  Expression get expression => variable.initializer;
-
-  /// Returns the cascade expressions of the cascade, i.e. `e1`, `e2`, and `e3`
-  /// in `e..e1..e2..e3`.
-  Iterable<Expression> get cascades sync* {
-    Let section = _firstCascade;
-    while (true) {
-      yield section.variable.initializer;
-      if (section.body is! Let) break;
-      section = section.body;
-    }
-  }
-
-  /// Adds a new unfinalized section to the end of the cascade.  Should be
-  /// called after the previous cascade section has been finalized.
-  void extend() {
-    assert(_lastCascade.variable.initializer is! _UnfinishedCascade);
-    Let newCascade = makeLet(
-        new VariableDeclaration.forValue(new _UnfinishedCascade()),
-        _lastCascade.body);
-    _lastCascade.body = newCascade;
-    newCascade.parent = _lastCascade;
-    _lastCascade = newCascade;
-  }
-
-  /// Finalizes the last cascade section with the given [expression].
-  void finalize(Expression expression) {
-    assert(_lastCascade.variable.initializer is _UnfinishedCascade);
-    _lastCascade.variable.initializer = expression;
-    expression.parent = _lastCascade.variable;
-  }
-
-  @override
-  Expression replace() {
-    Expression replacement;
-    parent.replaceChild(
-        this,
-        replacement = new Let(variable, _firstCascade)
-          ..fileOffset = fileOffset);
-    return replacement;
+  /// Adds [expression] to the list of [expressions] performed on [variable].
+  void addCascadeExpression(Expression expression) {
+    expressions.add(expression);
+    expression.parent = this;
   }
 
   @override
   void visitChildren(Visitor<dynamic> v) {
     variable?.accept(v);
-    _firstCascade?.accept(v);
+    visitList(expressions, v);
   }
 
   @override
@@ -473,46 +404,35 @@
       variable = variable.accept<TreeNode>(v);
       variable?.parent = this;
     }
-    if (_firstCascade != null) {
-      _firstCascade = _firstCascade.accept<TreeNode>(v);
-      _firstCascade?.parent = this;
-    }
+    transformList(expressions, v, this);
   }
 }
 
 /// Internal expression representing a deferred check.
 // TODO(johnniwinther): Change the representation to be direct and perform
-// the [Let] encoding in [replace].
+// the [Let] encoding in the replacement.
 class DeferredCheck extends InternalExpression {
-  VariableDeclaration _variable;
+  VariableDeclaration variable;
   Expression expression;
 
-  DeferredCheck(this._variable, this.expression) {
-    _variable?.parent = this;
+  DeferredCheck(this.variable, this.expression) {
+    variable?.parent = this;
     expression?.parent = this;
   }
 
   InternalExpressionKind get kind => InternalExpressionKind.DeferredCheck;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    parent.replaceChild(this,
-        replacement = new Let(_variable, expression)..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
-    _variable?.accept(v);
+    variable?.accept(v);
     expression?.accept(v);
   }
 
   @override
   void transformChildren(Transformer v) {
-    if (_variable != null) {
-      _variable = _variable.accept<TreeNode>(v);
-      _variable?.parent = this;
+    if (variable != null) {
+      variable = variable.accept<TreeNode>(v);
+      variable?.parent = this;
     }
     if (expression != null) {
       expression = expression.accept<TreeNode>(v);
@@ -624,7 +544,7 @@
 }
 
 Expression checkWebIntLiteralsErrorIfUnexact(
-    ShadowTypeInferrer inferrer, int value, String literal, int charOffset) {
+    TypeInferrerImpl inferrer, int value, String literal, int charOffset) {
   if (value >= 0 && value <= (1 << 53)) return null;
   if (inferrer.isTopLevel) return null;
   if (!inferrer.library.loader.target.backendTarget
@@ -706,8 +626,8 @@
 /// Concrete shadow object representing an invalid initializer in kernel form.
 class ShadowInvalidFieldInitializer extends LocalInitializer
     implements InitializerJudgment {
-  final Field field;
-  final Expression value;
+  Field field;
+  Expression value;
 
   ShadowInvalidFieldInitializer(
       this.field, this.value, VariableDeclaration variable)
@@ -884,108 +804,6 @@
       : super(expression);
 }
 
-/// Concrete implementation of [TypeInferenceEngine] specialized to work with
-/// kernel objects.
-class ShadowTypeInferenceEngine extends TypeInferenceEngine {
-  ShadowTypeInferenceEngine(Instrumentation instrumentation)
-      : super(instrumentation);
-
-  @override
-  ShadowTypeInferrer createLocalTypeInferrer(
-      Uri uri, InterfaceType thisType, SourceLibraryBuilder library) {
-    return new TypeInferrer(this, uri, false, thisType, library);
-  }
-
-  @override
-  ShadowTypeInferrer createTopLevelTypeInferrer(
-      Uri uri, InterfaceType thisType, SourceLibraryBuilder library) {
-    return new TypeInferrer(this, uri, true, thisType, library);
-  }
-}
-
-/// Concrete implementation of [TypeInferrer] specialized to work with kernel
-/// objects.
-class ShadowTypeInferrer extends TypeInferrerImpl {
-  @override
-  final TypePromoter typePromoter;
-
-  ShadowTypeInferrer.private(ShadowTypeInferenceEngine engine, Uri uri,
-      bool topLevel, InterfaceType thisType, SourceLibraryBuilder library)
-      : typePromoter = new TypePromoter(engine.typeSchemaEnvironment),
-        super.private(engine, uri, topLevel, thisType, library);
-
-  @override
-  Expression getFieldInitializer(Field field) {
-    return field.initializer;
-  }
-
-  @override
-  ExpressionInferenceResult inferExpression(
-      Expression expression, DartType typeContext, bool typeNeeded,
-      {bool isVoidAllowed: false}) {
-    // `null` should never be used as the type context.  An instance of
-    // `UnknownType` should be used instead.
-    assert(typeContext != null);
-
-    // It isn't safe to do type inference on an expression without a parent,
-    // because type inference might cause us to have to replace one expression
-    // with another, and we can only replace a node if it has a parent pointer.
-    assert(expression.parent != null);
-
-    // For full (non-top level) inference, we need access to the
-    // ExpressionGeneratorHelper so that we can perform error recovery.
-    assert(isTopLevel || helper != null);
-
-    // When doing top level inference, we skip subexpressions whose type isn't
-    // needed so that we don't induce bogus dependencies on fields mentioned in
-    // those subexpressions.
-    if (!typeNeeded) return const ExpressionInferenceResult(null);
-
-    InferenceVisitor visitor = new InferenceVisitor(this);
-    ExpressionInferenceResult result;
-    if (expression is ExpressionJudgment) {
-      result = expression.acceptInference(visitor, typeContext);
-    } else {
-      result = expression.accept1(visitor, typeContext);
-    }
-    DartType inferredType = result.inferredType;
-    assert(inferredType != null, "No type inferred for $expression.");
-    if (inferredType is VoidType && !isVoidAllowed) {
-      if (expression.parent is! ArgumentsImpl) {
-        helper?.addProblem(
-            messageVoidExpression, expression.fileOffset, noLength);
-      }
-    }
-    return result;
-  }
-
-  @override
-  void inferInitializer(InferenceHelper helper, Initializer initializer) {
-    this.helper = helper;
-    // Use polymorphic dispatch on [KernelInitializer] to perform whatever
-    // kind of type inference is correct for this kind of initializer.
-    // TODO(paulberry): experiment to see if dynamic dispatch would be better,
-    // so that the type hierarchy will be simpler (which may speed up "is"
-    // checks).
-    if (initializer is InitializerJudgment) {
-      initializer.acceptInference(new InferenceVisitor(this));
-    } else {
-      initializer.accept(new InferenceVisitor(this));
-    }
-    this.helper = null;
-  }
-
-  @override
-  void inferStatement(Statement statement) {
-    // For full (non-top level) inference, we need access to the
-    // ExpressionGeneratorHelper so that we can perform error recovery.
-    if (!isTopLevel) assert(helper != null);
-    if (statement != null) {
-      statement.accept(new InferenceVisitor(this));
-    }
-  }
-}
-
 /// Concrete implementation of [TypePromoter] specialized to work with kernel
 /// objects.
 class ShadowTypePromoter extends TypePromoterImpl {
@@ -1159,14 +977,6 @@
   InternalExpressionKind get kind => InternalExpressionKind.LoadLibraryTearOff;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    parent.replaceChild(
-        this, replacement = new StaticGet(target)..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
     import?.accept(v);
     target?.accept(v);
@@ -1183,18 +993,6 @@
   }
 }
 
-class _UnfinishedCascade extends Expression {
-  R accept<R>(v) => unsupported("accept", -1, null);
-
-  R accept1<R, A>(v, arg) => unsupported("accept1", -1, null);
-
-  DartType getStaticType(types) => unsupported("getStaticType", -1, null);
-
-  void transformChildren(v) => unsupported("transformChildren", -1, null);
-
-  void visitChildren(v) => unsupported("visitChildren", -1, null);
-}
-
 /// Internal expression representing an if-null property set.
 ///
 /// An if-null property set of the form `o.a ??= b` is, if used for value,
@@ -1302,52 +1100,191 @@
   }
 }
 
+/// Internal expression representing an compound extension assignment.
+///
+/// An compound extension assignment of the form
+///
+///     Extension(receiver).propertyName += rhs
+///
+/// is, if used for value, encoded as the expression:
+///
+///     let receiverVariable = receiver in
+///       let valueVariable =
+///           Extension|get#propertyName(receiverVariable) + rhs) in
+///         let writeVariable =
+///             Extension|set#propertyName(receiverVariable, valueVariable) in
+///           valueVariable
+///
+/// and if used for effect as:
+///
+///     let receiverVariable = receiver in
+///         Extension|set#propertyName(receiverVariable,
+///           Extension|get#propertyName(receiverVariable) + rhs)
+///
+/// If [readOnlyReceiver] is `true` the [receiverVariable] is not created
+/// and the [receiver] is used directly.
+class CompoundExtensionSet extends InternalExpression {
+  /// The extension in which the [setter] is declared.
+  final Extension extension;
+
+  /// The explicit type arguments for the type parameters declared in
+  /// [extension].
+  final List<DartType> explicitTypeArguments;
+
+  /// The receiver used for the read/write operations.
+  Expression receiver;
+
+  /// The name of the property accessed by the read/write operations.
+  final Name propertyName;
+
+  /// The member used for the read operation.
+  final Member getter;
+
+  /// The binary operation performed on the getter result and [rhs].
+  final Name binaryName;
+
+  /// The right-hand side of the binary operation.
+  Expression rhs;
+
+  /// 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;
+
+  /// The file offset for the read operation.
+  final int readOffset;
+
+  /// The file offset for the binary operation.
+  final int binaryOffset;
+
+  /// The file offset for the write operation.
+  final int writeOffset;
+
+  CompoundExtensionSet(
+      this.extension,
+      this.explicitTypeArguments,
+      this.receiver,
+      this.propertyName,
+      this.getter,
+      this.binaryName,
+      this.rhs,
+      this.setter,
+      {this.readOnlyReceiver,
+      this.forEffect,
+      this.readOffset,
+      this.binaryOffset,
+      this.writeOffset})
+      : assert(readOnlyReceiver != null),
+        assert(forEffect != null),
+        assert(readOffset != null),
+        assert(binaryOffset != null),
+        assert(writeOffset != null) {
+    receiver?.parent = this;
+    rhs?.parent = this;
+  }
+
+  @override
+  InternalExpressionKind get kind =>
+      InternalExpressionKind.CompoundExtensionSet;
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    receiver?.accept(v);
+    rhs?.accept(v);
+  }
+
+  @override
+  void transformChildren(Transformer v) {
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
+    }
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
+    }
+  }
+}
+
 /// Internal expression representing an compound property assignment.
 ///
-/// An compound property assignment of the form `o.a += b` is encoded as the
-/// expression:
+/// An compound property assignment of the form
 ///
-///     let v1 = o in v1.a = v1.a + b
+///     receiver.propertyName += rhs
+///
+/// is encoded as the expression:
+///
+///     let receiverVariable = receiver in
+///       receiverVariable.propertyName = receiverVariable.propertyName + rhs
 ///
 class CompoundPropertySet extends InternalExpression {
-  /// The synthetic variable whose initializer hold the receiver.
-  VariableDeclaration variable;
+  /// The receiver used for the read/write operations.
+  Expression receiver;
 
-  /// The expression that writes the result of the binary operation to the
-  /// property on [variable].
-  Expression write;
+  /// The name of the property accessed by the read/write operations.
+  final Name propertyName;
 
-  CompoundPropertySet(this.variable, this.write) {
-    variable?.parent = this;
-    write?.parent = this;
+  /// The binary operation performed on the getter result and [rhs].
+  final Name binaryName;
+
+  /// The right-hand side of the binary operation.
+  Expression rhs;
+
+  /// 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;
+
+  /// The file offset for the binary operation.
+  final int binaryOffset;
+
+  /// The file offset for the write operation.
+  final int writeOffset;
+
+  CompoundPropertySet(
+      this.receiver, this.propertyName, this.binaryName, this.rhs,
+      {this.forEffect,
+      this.readOnlyReceiver,
+      this.readOffset,
+      this.binaryOffset,
+      this.writeOffset})
+      : assert(forEffect != null),
+        assert(readOnlyReceiver != null),
+        assert(readOffset != null),
+        assert(binaryOffset != null),
+        assert(writeOffset != null) {
+    receiver?.parent = this;
+    rhs?.parent = this;
   }
 
   @override
   InternalExpressionKind get kind => InternalExpressionKind.CompoundPropertySet;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    replaceWith(
-        replacement = new Let(variable, write)..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
-    variable?.accept(v);
-    write?.accept(v);
+    receiver?.accept(v);
+    rhs?.accept(v);
   }
 
   @override
   void transformChildren(Transformer v) {
-    if (variable != null) {
-      variable = variable.accept<TreeNode>(v);
-      variable?.parent = this;
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
     }
-    if (write != null) {
-      write = write.accept<TreeNode>(v);
-      write?.parent = this;
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
     }
   }
 }
@@ -1387,21 +1324,6 @@
   InternalExpressionKind get kind => InternalExpressionKind.PropertyPostIncDec;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    if (variable != null) {
-      replaceWith(replacement = new Let(
-          variable, createLet(read, createLet(write, createVariableGet(read))))
-        ..fileOffset = fileOffset);
-    } else {
-      replaceWith(
-          replacement = new Let(read, createLet(write, createVariableGet(read)))
-            ..fileOffset = fileOffset);
-    }
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
     variable?.accept(v);
     read?.accept(v);
@@ -1445,15 +1367,6 @@
   InternalExpressionKind get kind => InternalExpressionKind.LocalPostIncDec;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    replaceWith(
-        replacement = new Let(read, createLet(write, createVariableGet(read)))
-          ..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
     read?.accept(v);
     write?.accept(v);
@@ -1496,15 +1409,6 @@
   InternalExpressionKind get kind => InternalExpressionKind.StaticPostIncDec;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    replaceWith(
-        replacement = new Let(read, createLet(write, createVariableGet(read)))
-          ..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
     read?.accept(v);
     write?.accept(v);
@@ -1547,15 +1451,6 @@
   InternalExpressionKind get kind => InternalExpressionKind.SuperPostIncDec;
 
   @override
-  Expression replace() {
-    Expression replacement;
-    replaceWith(
-        replacement = new Let(read, createLet(write, createVariableGet(read)))
-          ..fileOffset = fileOffset);
-    return replacement;
-  }
-
-  @override
   void visitChildren(Visitor<dynamic> v) {
     read?.accept(v);
     write?.accept(v);
@@ -1700,8 +1595,11 @@
 /// using [StaticInvocation].
 ///
 class ExtensionIndexSet extends InternalExpression {
+  /// The extension in which the [setter] is declared.
   final Extension extension;
 
+  /// The explicit type arguments for the type parameters declared in
+  /// [extension].
   final List<DartType> explicitTypeArguments;
 
   /// The receiver of the extension access.
@@ -2656,6 +2554,15 @@
     ..fileOffset = expression.fileOffset;
 }
 
+/// Creates a [VariableDeclaration] for the expression inference [result]
+/// using `result.expression.fileOffset` as the file offset for the declaration.
+///
+/// This is useful for creating let variables for expressions in replacement
+/// code.
+VariableDeclaration createVariableForResult(ExpressionInferenceResult result) {
+  return createVariable(result.expression, result.inferredType);
+}
+
 /// Creates a [VariableGet] of [variable] using `variable.fileOffset` as the
 /// file offset for the expression.
 ///
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 0bc8ffa..22369f8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -256,6 +256,7 @@
       loader.computeLibraryScopes();
       setupTopAndBottomTypes();
       loader.resolveTypes();
+      loader.computeVariances();
       loader.computeDefaultTypes(dynamicType, bottomType, objectClassBuilder);
       List<SourceClassBuilder> myClasses =
           loader.checkSemantics(objectClassBuilder);
@@ -696,9 +697,14 @@
         for (VariableDeclaration formal
             in constructor.function.positionalParameters) {
           if (formal.isFieldFormal) {
-            Builder fieldBuilder = builder.scope.local[formal.name] ??
-                builder.origin.scope.local[formal.name];
-            if (fieldBuilder is FieldBuilder) {
+            Builder fieldBuilder =
+                builder.scope.lookupLocalMember(formal.name, setter: false) ??
+                    builder.origin.scope
+                        .lookupLocalMember(formal.name, setter: false);
+            // If next is not null it's a duplicated field,
+            // and it doesn't need to be initialized to null below
+            // (and doing it will crash serialization).
+            if (fieldBuilder?.next == null && fieldBuilder is FieldBuilder) {
               myInitializedFields.add(fieldBuilder.field);
             }
           }
@@ -729,23 +735,26 @@
     // set their initializer to `null`.
     for (Field field in uninitializedFields) {
       if (initializedFields == null || !initializedFields.contains(field)) {
-        field.initializer = new NullLiteral()..parent = field;
-        if (field.isFinal &&
-            (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
-          String uri = '${field.enclosingLibrary.importUri}';
-          String file = field.fileUri.pathSegments.last;
-          if (uri == 'dart:html' ||
-              uri == 'dart:svg' ||
-              uri == 'dart:_native_typed_data' ||
-              uri == 'dart:_interceptors' && file == 'js_string.dart') {
-            // TODO(johnniwinther): Use external getters instead of final
-            // fields. See https://github.com/dart-lang/sdk/issues/33762
-          } else {
-            builder.library.addProblem(
-                templateFinalFieldNotInitialized.withArguments(field.name.name),
-                field.fileOffset,
-                field.name.name.length,
-                field.fileUri);
+        if (!field.isLate) {
+          field.initializer = new NullLiteral()..parent = field;
+          if (field.isFinal &&
+              (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
+            String uri = '${field.enclosingLibrary.importUri}';
+            String file = field.fileUri.pathSegments.last;
+            if (uri == 'dart:html' ||
+                uri == 'dart:svg' ||
+                uri == 'dart:_native_typed_data' ||
+                uri == 'dart:_interceptors' && file == 'js_string.dart') {
+              // TODO(johnniwinther): Use external getters instead of final
+              // fields. See https://github.com/dart-lang/sdk/issues/33762
+            } else {
+              builder.library.addProblem(
+                  templateFinalFieldNotInitialized
+                      .withArguments(field.name.name),
+                  field.fileOffset,
+                  field.name.name.length,
+                  field.fileUri);
+            }
           }
         }
       }
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 2fb7c13..c3400b1 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
@@ -7,29 +7,38 @@
 import 'package:kernel/ast.dart' show VariableDeclaration;
 
 import '../builder/builder.dart';
+import '../builder/variable_builder.dart';
 
-class VariableBuilder extends BuilderImpl {
+class VariableBuilderImpl extends BuilderImpl implements VariableBuilder {
   @override
   final Builder parent;
 
   @override
   final Uri fileUri;
 
+  @override
   final VariableDeclaration variable;
 
-  VariableBuilder(this.variable, this.parent, this.fileUri);
+  VariableBuilderImpl(this.variable, this.parent, this.fileUri);
 
   @override
   int get charOffset => variable.fileOffset;
 
+  @override
   bool get isLocal => true;
 
+  @override
   bool get isConst => variable.isConst;
 
+  @override
   bool get isFinal => variable.isFinal;
 
-  VariableDeclaration get target => variable;
+  @override
+  bool get isAssignable => variable.isAssignable;
 
   @override
   String get fullNameForErrors => variable.name ?? "<unnamed>";
+
+  @override
+  String toString() => 'VariableBuilderImpl($fullNameForErrors)';
 }
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 0e7d4d4..d210b0c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -66,7 +66,7 @@
 
 import '../problems.dart' show getFileUri, unhandled;
 
-import '../source/source_loader.dart' show SourceLoader;
+import '../source/source_loader.dart';
 
 import 'redirecting_factory_body.dart' show RedirectingFactoryBody;
 
@@ -82,6 +82,7 @@
   final Class mapEntryClass;
   final Field mapEntryKey;
   final Field mapEntryValue;
+  final SourceLoaderDataForTesting dataForTesting;
 
   static Procedure _findSetFactory(CoreTypes coreTypes) {
     Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
@@ -105,7 +106,8 @@
         mapEntryKey =
             loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'key'),
         mapEntryValue =
-            loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'value');
+            loader.coreTypes.index.getMember('dart:core', 'MapEntry', 'value'),
+        dataForTesting = loader.dataForTesting;
 
   TreeNode _translateListOrSet(
       Expression node, DartType elementType, List<Expression> elements,
@@ -208,6 +210,7 @@
       ..fileOffset = element.fileOffset;
     transformList(loop.variables, this, loop);
     transformList(loop.updates, this, loop);
+    dataForTesting?.registerAlias(element, loop);
     body.add(loop);
   }
 
@@ -228,10 +231,12 @@
     if (element.problem != null) {
       body.add(new ExpressionStatement(element.problem.accept<TreeNode>(this)));
     }
-    body.add(new ForInStatement(
+    ForInStatement loop = new ForInStatement(
         element.variable, element.iterable.accept<TreeNode>(this), loopBody,
         isAsync: element.isAsync)
-      ..fileOffset = element.fileOffset);
+      ..fileOffset = element.fileOffset;
+    dataForTesting?.registerAlias(element, loop);
+    body.add(loop);
   }
 
   void _translateSpreadElement(SpreadElement element, DartType elementType,
@@ -396,6 +401,7 @@
     ForStatement loop = new ForStatement(entry.variables,
         entry.condition?.accept<TreeNode>(this), entry.updates, loopBody)
       ..fileOffset = entry.fileOffset;
+    dataForTesting?.registerAlias(entry, loop);
     transformList(loop.variables, this, loop);
     transformList(loop.updates, this, loop);
     body.add(loop);
@@ -418,10 +424,12 @@
     if (entry.problem != null) {
       body.add(new ExpressionStatement(entry.problem.accept<TreeNode>(this)));
     }
-    body.add(new ForInStatement(
+    ForInStatement loop = new ForInStatement(
         entry.variable, entry.iterable.accept<TreeNode>(this), loopBody,
         isAsync: entry.isAsync)
-      ..fileOffset = entry.fileOffset);
+      ..fileOffset = entry.fileOffset;
+    dataForTesting?.registerAlias(entry, loop);
+    body.add(loop);
   }
 
   void _translateSpreadEntry(SpreadMapEntry entry, DartType keyType,
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 552dc88..658de83 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -12,6 +12,7 @@
         InterfaceType,
         InvalidType,
         NamedType,
+        NeverType,
         TypeParameter,
         TypeParameterType,
         TypedefType,
@@ -26,6 +27,7 @@
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_type_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
+import '../builder/library_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/type_alias_builder.dart';
@@ -43,21 +45,27 @@
         templateBoundIssueViaCycleNonSimplicity,
         templateBoundIssueViaLoopNonSimplicity,
         templateBoundIssueViaRawTypeWithNonSimpleBounds,
+        templateCyclicTypedef,
         templateNonSimpleBoundViaReference,
         templateNonSimpleBoundViaVariable;
 
 export 'package:kernel/ast.dart' show Variance;
 
+/// Initial value for "variance" that is to be computed by the compiler.
+const int pendingVariance = -1;
+
 // Computes the variance of a variable in a type.  The function can be run
 // before the types are resolved to compute variances of typedefs' type
 // variables.  For that case if the type has its declaration set to null and its
 // name matches that of the variable, it's interpreted as an occurrence of a
 // type variable.
-int computeVariance(TypeVariableBuilder variable, TypeBuilder type) {
+int computeVariance(TypeVariableBuilder variable, TypeBuilder type,
+    LibraryBuilder libraryBuilder) {
   if (type is NamedTypeBuilder) {
+    assert(type.declaration != null);
     TypeDeclarationBuilder declaration = type.declaration;
-    if (declaration == null || declaration is TypeVariableBuilder) {
-      if (type.name == variable.name) {
+    if (declaration is TypeVariableBuilder) {
+      if (declaration == variable) {
         return Variance.covariant;
       } else {
         return Variance.unrelated;
@@ -69,21 +77,46 @@
           for (int i = 0; i < type.arguments.length; ++i) {
             result = Variance.meet(
                 result,
-                Variance.combine(declaration.cls.typeParameters[i].variance,
-                    computeVariance(variable, type.arguments[i])));
+                Variance.combine(
+                    declaration.cls.typeParameters[i].variance,
+                    computeVariance(
+                        variable, type.arguments[i], libraryBuilder)));
           }
         }
         return result;
       } else if (declaration is TypeAliasBuilder) {
         int result = Variance.unrelated;
+
         if (type.arguments != null) {
           for (int i = 0; i < type.arguments.length; ++i) {
+            const int visitMarker = -2;
+
+            TypeVariableBuilder declarationTypeVariable =
+                declaration.typeVariables[i];
+
+            if (declarationTypeVariable.variance == pendingVariance) {
+              declarationTypeVariable.variance = visitMarker;
+              int computedVariance = computeVariance(
+                  declarationTypeVariable, declaration.type, libraryBuilder);
+              declarationTypeVariable.variance = computedVariance;
+            } else if (declarationTypeVariable.variance == visitMarker) {
+              libraryBuilder.addProblem(
+                  templateCyclicTypedef.withArguments(declaration.name),
+                  declaration.charOffset,
+                  declaration.name.length,
+                  declaration.fileUri);
+              // Use [Variance.unrelated] for recovery.  The type with the
+              // cyclic dependency will be replaced with an [InvalidType]
+              // elsewhere.
+              declarationTypeVariable.variance = Variance.unrelated;
+            }
+
             result = Variance.meet(
                 result,
                 Variance.combine(
-                    computeVariance(variable, type.arguments[i]),
                     computeVariance(
-                        declaration.typeVariables[i], declaration.type)));
+                        variable, type.arguments[i], libraryBuilder),
+                    declarationTypeVariable.variance));
           }
         }
         return result;
@@ -92,8 +125,8 @@
   } else if (type is FunctionTypeBuilder) {
     int result = Variance.unrelated;
     if (type.returnType != null) {
-      result =
-          Variance.meet(result, computeVariance(variable, type.returnType));
+      result = Variance.meet(
+          result, computeVariance(variable, type.returnType, libraryBuilder));
     }
     if (type.typeVariables != null) {
       for (TypeVariableBuilder typeVariable in type.typeVariables) {
@@ -102,7 +135,7 @@
         // of [computeVariance] below is made to simply figure out if [variable]
         // occurs in the bound.
         if (typeVariable.bound != null &&
-            computeVariance(variable, typeVariable.bound) !=
+            computeVariance(variable, typeVariable.bound, libraryBuilder) !=
                 Variance.unrelated) {
           result = Variance.invariant;
         }
@@ -113,7 +146,7 @@
         result = Variance.meet(
             result,
             Variance.combine(Variance.contravariant,
-                computeVariance(variable, formal.type)));
+                computeVariance(variable, formal.type, libraryBuilder)));
       }
     }
     return result;
@@ -974,6 +1007,8 @@
 
   bool visitBottomType(BottomType node) => false;
 
+  bool visitNeverType(NeverType node) => false;
+
   bool visitInterfaceType(InterfaceType node) {
     return anyTypeVariables(node.typeArguments);
   }
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 83b88be..4368752 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
@@ -4,6 +4,9 @@
 
 library fasta.type_builder_computer;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show FormalParameterKind;
+
 import 'package:kernel/ast.dart'
     show
         BottomType,
@@ -16,6 +19,7 @@
         InvalidType,
         Library,
         NamedType,
+        NeverType,
         TypeParameter,
         TypeParameterType,
         TypedefType,
@@ -27,6 +31,7 @@
 import '../builder/function_type_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/named_type_builder.dart';
+import '../builder/never_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
@@ -34,8 +39,6 @@
 
 import '../loader.dart' show Loader;
 
-import '../parser.dart' show FormalParameterKind;
-
 class TypeBuilderComputer implements DartTypeVisitor<TypeBuilder> {
   final Loader loader;
 
@@ -68,6 +71,12 @@
     throw "Not implemented";
   }
 
+  TypeBuilder visitNeverType(NeverType node) {
+    return new NamedTypeBuilder(
+        "Never", new NullabilityBuilder.fromNullability(node.nullability), null)
+      ..bind(new NeverTypeBuilder(node, loader.coreLibrary, -1));
+  }
+
   TypeBuilder visitInterfaceType(InterfaceType node) {
     ClassBuilder cls =
         loader.computeClassBuilderFromTargetClass(node.classNode);
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 0bb51ac..2a5cbe3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -23,6 +23,7 @@
         Library,
         ListConstant,
         MapConstant,
+        NeverType,
         NullConstant,
         PartialInstantiationConstant,
         Procedure,
@@ -139,6 +140,12 @@
     result.add("bottom-type");
   }
 
+  void visitNeverType(NeverType node) {
+    // TODO(askesc): Consider throwing internal error if NeverType appears in
+    //  diagnostics.
+    result.add("Never");
+  }
+
   void visitDynamicType(DynamicType node) {
     result.add("dynamic");
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
index d384d59..d44fcec 100644
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/types.dart
@@ -14,6 +14,7 @@
         InterfaceType,
         InvalidType,
         NamedType,
+        NeverType,
         Nullability,
         TypeParameter,
         TypeParameterType,
@@ -27,13 +28,14 @@
 
 import 'kernel_builder.dart' show ClassHierarchyBuilder;
 
-class Types {
+class Types implements SubtypeTester {
   final ClassHierarchyBuilder hierarchy;
 
   Types(this.hierarchy);
 
   /// Returns true if [s] is a subtype of [t].
   bool isSubtypeOfKernel(DartType s, DartType t, SubtypeCheckMode mode) {
+    // TODO(dmitryas): Remove InvalidType from subtype relation.
     if (s is InvalidType) {
       // InvalidType is a bottom type.
       return true;
@@ -41,186 +43,176 @@
     if (t is InvalidType) {
       return false;
     }
-    return isSubtypeOfKernelNullability(s, s.nullability, t, t.nullability);
+
+    IsSubtypeOf result = performNullabilityAwareSubtypeCheck(s, t);
+    switch (mode) {
+      case SubtypeCheckMode.withNullabilities:
+        return result.isSubtypeWhenUsingNullabilities();
+      case SubtypeCheckMode.ignoringNullabilities:
+        return result.isSubtypeWhenIgnoringNullabilities();
+      default:
+        throw new StateError("Unhandled subtype checking mode '$mode'");
+    }
   }
 
-  bool isSubtypeOfKernelNullability(
-      DartType s, Nullability sNullability, DartType t, tNullability) {
+  @override
+  IsSubtypeOf performNullabilityAwareSubtypeCheck(DartType s, DartType t) {
     if (s is BottomType) {
-      return true; // Rule 3.
+      return const IsSubtypeOf.always(); // Rule 3.
     }
     if (t is DynamicType) {
-      return true; // Rule 2.
+      return const IsSubtypeOf.always(); // Rule 2.
     }
     if (t is VoidType) {
-      return true; // Rule 2.
+      return const IsSubtypeOf.always(); // Rule 2.
     }
     if (t is BottomType) {
-      return false;
+      return const IsSubtypeOf.never();
+    }
+    if (s is NeverType) {
+      return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
     }
     if (t is InterfaceType) {
       Class cls = t.classNode;
-      if (cls == hierarchy.objectClass) {
-        return true; // Rule 2.
+      if (cls == hierarchy.objectClass &&
+          !(s is InterfaceType && s.classNode == hierarchy.futureOrClass)) {
+        return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
       }
       if (cls == hierarchy.futureOrClass) {
         const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
         if (s is DynamicType) {
-          return relation.isDynamicRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isDynamicRelated(s, t, this);
         } else if (s is VoidType) {
-          return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+          return relation.isVoidRelated(s, t, this);
         } else if (s is InterfaceType) {
           return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isInterfaceRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
         } else if (s is FunctionType) {
-          return relation.isFunctionRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isFunctionRelated(s, t, this);
         } else if (s is TypeParameterType) {
           return s.promotedBound == null
-              ? relation.isTypeParameterRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isIntersectionRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
         } else if (s is TypedefType) {
-          return relation.isTypedefRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isTypedefRelated(s, t, this);
         }
       } else {
         const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
         if (s is DynamicType) {
-          return relation.isDynamicRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isDynamicRelated(s, t, this);
         } else if (s is VoidType) {
-          return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+          return relation.isVoidRelated(s, t, this);
         } else if (s is InterfaceType) {
           return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isInterfaceRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
         } else if (s is FunctionType) {
-          return relation.isFunctionRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isFunctionRelated(s, t, this);
         } else if (s is TypeParameterType) {
           return s.promotedBound == null
-              ? relation.isTypeParameterRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isIntersectionRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
         } else if (s is TypedefType) {
-          return relation.isTypedefRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isTypedefRelated(s, t, this);
         }
       }
     } else if (t is FunctionType) {
       const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
       if (s is DynamicType) {
-        return relation.isDynamicRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isDynamicRelated(s, t, this);
       } else if (s is VoidType) {
-        return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+        return relation.isVoidRelated(s, t, this);
       } else if (s is InterfaceType) {
         return s.classNode == hierarchy.futureOrClass
-            ? relation.isFutureOrRelated(s, sNullability, t, tNullability, this)
-            : relation.isInterfaceRelated(
-                s, sNullability, t, tNullability, this);
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
       } else if (s is FunctionType) {
-        return relation.isFunctionRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isFunctionRelated(s, t, this);
       } else if (s is TypeParameterType) {
         return s.promotedBound == null
-            ? relation.isTypeParameterRelated(
-                s, sNullability, t, tNullability, this)
-            : relation.isIntersectionRelated(
-                s, sNullability, t, tNullability, this);
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
       } else if (s is TypedefType) {
-        return relation.isTypedefRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isTypedefRelated(s, t, this);
       }
     } else if (t is TypeParameterType) {
       if (t.promotedBound == null) {
         const IsTypeParameterSubtypeOf relation =
             const IsTypeParameterSubtypeOf();
         if (s is DynamicType) {
-          return relation.isDynamicRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isDynamicRelated(s, t, this);
         } else if (s is VoidType) {
-          return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+          return relation.isVoidRelated(s, t, this);
         } else if (s is InterfaceType) {
           return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isInterfaceRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
         } else if (s is FunctionType) {
-          return relation.isFunctionRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isFunctionRelated(s, t, this);
         } else if (s is TypeParameterType) {
           return s.promotedBound == null
-              ? relation.isTypeParameterRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isIntersectionRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
         } else if (s is TypedefType) {
-          return relation.isTypedefRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isTypedefRelated(s, t, this);
         }
       } else {
         const IsIntersectionSubtypeOf relation =
             const IsIntersectionSubtypeOf();
         if (s is DynamicType) {
-          return relation.isDynamicRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isDynamicRelated(s, t, this);
         } else if (s is VoidType) {
-          return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+          return relation.isVoidRelated(s, t, this);
         } else if (s is InterfaceType) {
           return s.classNode == hierarchy.futureOrClass
-              ? relation.isFutureOrRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isInterfaceRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
         } else if (s is FunctionType) {
-          return relation.isFunctionRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isFunctionRelated(s, t, this);
         } else if (s is TypeParameterType) {
           return s.promotedBound == null
-              ? relation.isTypeParameterRelated(
-                  s, sNullability, t, tNullability, this)
-              : relation.isIntersectionRelated(
-                  s, sNullability, t, tNullability, this);
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
         } else if (s is TypedefType) {
-          return relation.isTypedefRelated(
-              s, sNullability, t, tNullability, this);
+          return relation.isTypedefRelated(s, t, this);
         }
       }
     } else if (t is TypedefType) {
       const IsTypedefSubtypeOf relation = const IsTypedefSubtypeOf();
       if (s is DynamicType) {
-        return relation.isDynamicRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isDynamicRelated(s, t, this);
       } else if (s is VoidType) {
-        return relation.isVoidRelated(s, sNullability, t, tNullability, this);
+        return relation.isVoidRelated(s, t, this);
       } else if (s is InterfaceType) {
         return s.classNode == hierarchy.futureOrClass
-            ? relation.isFutureOrRelated(s, sNullability, t, tNullability, this)
-            : relation.isInterfaceRelated(
-                s, sNullability, t, tNullability, this);
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
       } else if (s is FunctionType) {
-        return relation.isFunctionRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isFunctionRelated(s, t, this);
       } else if (s is TypeParameterType) {
         return s.promotedBound == null
-            ? relation.isTypeParameterRelated(
-                s, sNullability, t, tNullability, this)
-            : relation.isIntersectionRelated(
-                s, sNullability, t, tNullability, this);
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
       } else if (s is TypedefType) {
-        return relation.isTypedefRelated(
-            s, sNullability, t, tNullability, this);
+        return relation.isTypedefRelated(s, t, this);
+      }
+    } else if (t is NeverType) {
+      const IsNeverTypeSubtypeOf relation = const IsNeverTypeSubtypeOf();
+      if (s is DynamicType) {
+        return relation.isDynamicRelated(s, t, this);
+      } else if (s is VoidType) {
+        return relation.isVoidRelated(s, t, this);
+      } else if (s is InterfaceType) {
+        return relation.isInterfaceRelated(s, t, this);
+      } else if (s is FunctionType) {
+        return relation.isFunctionRelated(s, t, this);
+      } else if (s is TypeParameterType) {
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
+      } else if (s is TypedefType) {
+        return relation.isTypedefRelated(s, t, this);
       }
     } else {
       throw "Unhandled type: ${t.runtimeType}";
@@ -230,152 +222,194 @@
 
   /// Returns true if all type arguments in [s] and [t] pairwise are subtypes
   /// with respect to the variance of the corresponding [p] type parameter.
-  bool areTypeArgumentsOfSubtypeKernel(
+  IsSubtypeOf areTypeArgumentsOfSubtypeKernel(
       List<DartType> s, List<DartType> t, List<TypeParameter> p) {
     if (s.length != t.length || s.length != p.length) {
       throw "Numbers of type arguments don't match $s $t with parameters $p.";
     }
+    IsSubtypeOf result = const IsSubtypeOf.always();
     for (int i = 0; i < s.length; i++) {
       int variance = p[i].variance;
       if (variance == Variance.contravariant) {
-        if (!isSubtypeOfKernel(
-            t[i], s[i], SubtypeCheckMode.ignoringNullabilities)) return false;
+        result = result.join(performNullabilityAwareSubtypeCheck(t[i], s[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
       } else if (variance == Variance.invariant) {
-        if (!isSameTypeKernel(s[i], t[i])) return false;
+        result = result.join(isSameTypeKernel(s[i], t[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
       } else {
-        if (!isSubtypeOfKernel(
-            s[i], t[i], SubtypeCheckMode.ignoringNullabilities)) return false;
+        result = result.join(performNullabilityAwareSubtypeCheck(s[i], t[i]));
+        if (!result.isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
+        }
       }
     }
-    return true;
+    return result;
   }
 
-  bool isSameTypeKernel(DartType s, DartType t) {
-    return isSubtypeOfKernel(s, t, SubtypeCheckMode.ignoringNullabilities) &&
-        isSubtypeOfKernel(t, s, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isSameTypeKernel(DartType s, DartType t) {
+    return performNullabilityAwareSubtypeCheck(s, t)
+        .joinWithSubtypeCheckFor(t, s, this);
+  }
+
+  @override
+  bool isSubtypeOf(
+      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
+    return isSubtypeOfKernel(subtype, supertype, mode);
+  }
+
+  @override
+  Class get futureOrClass => hierarchy.coreTypes.futureOrClass;
+
+  @override
+  Class get functionClass => hierarchy.coreTypes.functionClass;
+
+  @override
+  InterfaceType get functionLegacyRawType =>
+      hierarchy.coreTypes.functionLegacyRawType;
+
+  @override
+  InterfaceType futureType(DartType type,
+      [Nullability nullability = Nullability.legacy]) {
+    return new InterfaceType(
+        hierarchy.coreTypes.futureClass, <DartType>[type], nullability);
+  }
+
+  @override
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+    return hierarchy.getKernelTypeAsInstanceOf(type, superclass);
+  }
+
+  @override
+  bool isTop(DartType type) {
+    return type is DynamicType ||
+        type is VoidType ||
+        type == objectLegacyRawType ||
+        type == objectNullableRawType;
+  }
+
+  @override
+  InterfaceType get nullType => hierarchy.coreTypes.nullType;
+
+  @override
+  Class get objectClass => hierarchy.coreTypes.objectClass;
+
+  @override
+  InterfaceType get objectLegacyRawType {
+    return hierarchy.coreTypes.objectLegacyRawType;
+  }
+
+  @override
+  InterfaceType get objectNullableRawType {
+    return hierarchy.coreTypes.objectNullableRawType;
+  }
+
+  @override
+  IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
+      DartType type1, DartType type2) {
+    return isSameTypeKernel(type1, type2);
   }
 }
 
 abstract class TypeRelation<T extends DartType> {
   const TypeRelation();
 
-  bool isDynamicRelated(DynamicType s, Nullability sNullability, T t,
-      Nullability tNullability, Types types);
+  IsSubtypeOf isDynamicRelated(DynamicType s, T t, Types types);
 
-  bool isVoidRelated(VoidType s, Nullability sNullability, T t,
-      Nullability tNullability, Types types);
+  IsSubtypeOf isVoidRelated(VoidType s, T t, Types types);
 
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability, T t,
-      Nullability tNullability, Types types);
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, T t, Types types);
 
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      T t,
-      Nullability tNullability,
-      Types types);
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, T t, Types types);
 
-  bool isFunctionRelated(FunctionType s, Nullability sNullability, T t,
-      Nullability tNullability, Types types);
+  IsSubtypeOf isFunctionRelated(FunctionType s, T t, Types types);
 
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      T t,
-      Nullability tNullability,
-      Types types);
+  IsSubtypeOf isFutureOrRelated(InterfaceType futureOr, T t, Types types);
 
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      T t, Nullability tNullability, Types types);
+  IsSubtypeOf isTypeParameterRelated(TypeParameterType s, T t, Types types);
 
-  bool isTypedefRelated(TypedefType s, Nullability sNullability, T t,
-      Nullability tNullability, Types types);
+  IsSubtypeOf isTypedefRelated(TypedefType s, T t, Types types);
 }
 
 class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
   const IsInterfaceSubtypeOf();
 
   @override
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
-      InterfaceType t, Nullability tNullability, Types types) {
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, InterfaceType t, Types types) {
     if (s.classNode == types.hierarchy.nullClass) {
       // This is an optimization, to avoid instantiating unnecessary type
       // arguments in getKernelTypeAsInstanceOf.
-      return true;
+      return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
     }
     InterfaceType asSupertype =
         types.hierarchy.getKernelTypeAsInstanceOf(s, t.classNode);
     if (asSupertype == null) {
-      return false;
-    } else {
-      return types.areTypeArgumentsOfSubtypeKernel(asSupertype.typeArguments,
-          t.typeArguments, t.classNode.typeParameters);
+      return const IsSubtypeOf.never();
     }
+    return types
+        .areTypeArgumentsOfSubtypeKernel(asSupertype.typeArguments,
+            t.typeArguments, t.classNode.typeParameters)
+        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      InterfaceType t, Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s.parameter.bound, t, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, InterfaceType t, Types types) {
+    return types
+        .performNullabilityAwareSubtypeCheck(s.parameter.bound, t)
+        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      InterfaceType t,
-      Nullability tNullability,
-      Types types) {
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, InterfaceType t, Types types) {
     List<DartType> arguments = futureOr.typeArguments;
-    if (!types.isSubtypeOfKernel(
-        arguments.single, t, SubtypeCheckMode.ignoringNullabilities)) {
-      return false; // Rule 7.1
-    }
-    if (!types.isSubtypeOfKernel(
-        new InterfaceType(types.hierarchy.futureClass, arguments),
-        t,
-        SubtypeCheckMode.ignoringNullabilities)) {
-      return false; // Rule 7.2
-    }
-    return true;
+    // Rules 7.1 and 7.2.
+    return types
+        .performNullabilityAwareSubtypeCheck(arguments.single, t)
+        .joinWithSubtypeCheckFor(
+            new InterfaceType(types.hierarchy.futureClass, arguments,
+                Nullability.nonNullable),
+            t,
+            types)
+        .join(new IsSubtypeOf.basedSolelyOnNullabilities(futureOr, t));
   }
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      InterfaceType t,
-      Nullability tNullability,
-      Types types) {
-    return types.isSubtypeOfKernel(intersection.promotedBound, t,
-        SubtypeCheckMode.ignoringNullabilities); // Rule 12.
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, InterfaceType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t); // Rule 12.
   }
 
   @override
-  bool isDynamicRelated(DynamicType s, Nullability sNullability,
-      InterfaceType t, Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isDynamicRelated(DynamicType s, InterfaceType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFunctionRelated(FunctionType s, Nullability sNullability,
-      InterfaceType t, Nullability tNullability, Types types) {
-    return t.classNode == types.hierarchy.functionClass; // Rule 14.
+  IsSubtypeOf isFunctionRelated(FunctionType s, InterfaceType t, Types types) {
+    return t.classNode == types.hierarchy.functionClass
+        ? new IsSubtypeOf.basedSolelyOnNullabilities(s, t)
+        : const IsSubtypeOf.never(); // Rule 14.
   }
 
   @override
-  bool isTypedefRelated(TypedefType s, Nullability sNullability,
-      InterfaceType t, Nullability tNullability, Types types) {
+  IsSubtypeOf isTypedefRelated(TypedefType s, InterfaceType t, Types types) {
     // Rule 5.
-    return types.isSubtypeOfKernel(
-        s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
+    return types
+        .performNullabilityAwareSubtypeCheck(s.unalias, t)
+        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
   }
 
   @override
-  bool isVoidRelated(VoidType s, Nullability sNullability, InterfaceType t,
-      Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 }
 
@@ -383,11 +417,12 @@
   const IsFunctionSubtypeOf();
 
   @override
-  bool isFunctionRelated(FunctionType s, Nullability sNullability,
-      FunctionType t, Nullability tNullability, Types types) {
+  IsSubtypeOf isFunctionRelated(FunctionType s, FunctionType t, Types types) {
     List<TypeParameter> sTypeVariables = s.typeParameters;
     List<TypeParameter> tTypeVariables = t.typeParameters;
-    if (sTypeVariables.length != tTypeVariables.length) return false;
+    if (sTypeVariables.length != tTypeVariables.length) {
+      return const IsSubtypeOf.never();
+    }
     if (sTypeVariables.isNotEmpty) {
       // If the function types have type variables, we alpha-rename the type
       // variables of [s] to use those of [t].
@@ -396,7 +431,9 @@
       for (int i = 0; i < sTypeVariables.length; i++) {
         TypeParameter sTypeVariable = sTypeVariables[i];
         TypeParameter tTypeVariable = tTypeVariables[i];
-        if (!types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound)) {
+        if (!types
+            .isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound)
+            .isSubtypeWhenIgnoringNullabilities()) {
           // If the bounds aren't the same, we need to try again after
           // computing the substitution of type variables.
           secondBoundsCheckNeeded = true;
@@ -409,42 +446,50 @@
         for (int i = 0; i < sTypeVariables.length; i++) {
           TypeParameter sTypeVariable = sTypeVariables[i];
           TypeParameter tTypeVariable = tTypeVariables[i];
-          if (!types.isSameTypeKernel(
-              substitution.substituteType(sTypeVariable.bound),
-              tTypeVariable.bound)) {
-            return false;
+          if (!types
+              .isSameTypeKernel(
+                  substitution.substituteType(sTypeVariable.bound),
+                  tTypeVariable.bound)
+              .isSubtypeWhenIgnoringNullabilities()) {
+            return const IsSubtypeOf.never();
           }
         }
       }
       s = substitution.substituteType(s.withoutTypeParameters);
     }
-    if (!types.isSubtypeOfKernel(
-        s.returnType, t.returnType, SubtypeCheckMode.ignoringNullabilities)) {
-      return false;
+    if (!types
+        .performNullabilityAwareSubtypeCheck(s.returnType, t.returnType)
+        .isSubtypeWhenIgnoringNullabilities()) {
+      return const IsSubtypeOf.never();
     }
     List<DartType> sPositional = s.positionalParameters;
     List<DartType> tPositional = t.positionalParameters;
     if (s.requiredParameterCount > t.requiredParameterCount) {
       // Rule 15, n1 <= n2.
-      return false;
+      return const IsSubtypeOf.never();
     }
     if (sPositional.length < tPositional.length) {
       // Rule 15, n1 + k1 >= n2 + k2.
-      return false;
+      return const IsSubtypeOf.never();
     }
     for (int i = 0; i < tPositional.length; i++) {
-      if (!types.isSubtypeOfKernel(tPositional[i], sPositional[i],
-          SubtypeCheckMode.ignoringNullabilities)) {
+      if (!types
+          .performNullabilityAwareSubtypeCheck(tPositional[i], sPositional[i])
+          .isSubtypeWhenIgnoringNullabilities()) {
         // Rule 15, Tj <: Sj.
-        return false;
+        return const IsSubtypeOf.never();
       }
     }
     List<NamedType> sNamed = s.namedParameters;
     List<NamedType> tNamed = t.namedParameters;
     if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
       // Rule 16, the number of positional parameters must be the same.
-      if (sPositional.length != tPositional.length) return false;
-      if (s.requiredParameterCount != t.requiredParameterCount) return false;
+      if (sPositional.length != tPositional.length) {
+        return const IsSubtypeOf.never();
+      }
+      if (s.requiredParameterCount != t.requiredParameterCount) {
+        return const IsSubtypeOf.never();
+      }
 
       // Rule 16, the parameter names of [t] must be a subset of those of
       // [s]. Also, for the intersection, the type of the parameter of [t] must
@@ -455,70 +500,62 @@
         for (; sCount < sNamed.length; sCount++) {
           if (sNamed[sCount].name == name) break;
         }
-        if (sCount == sNamed.length) return false;
-        if (!types.isSubtypeOfKernel(tNamed[tCount].type, sNamed[sCount].type,
-            SubtypeCheckMode.ignoringNullabilities)) {
-          return false;
+        if (sCount == sNamed.length) return const IsSubtypeOf.never();
+        if (!types
+            .performNullabilityAwareSubtypeCheck(
+                tNamed[tCount].type, sNamed[sCount].type)
+            .isSubtypeWhenIgnoringNullabilities()) {
+          return const IsSubtypeOf.never();
         }
       }
     }
-    return true;
+    return const IsSubtypeOf.always();
   }
 
   @override
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
-      FunctionType t, Nullability tNullability, Types types) {
-    return s.classNode == types.hierarchy.nullClass; // Rule 4.
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, FunctionType t, Types types) {
+    if (s.classNode == types.hierarchy.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
+    }
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isDynamicRelated(DynamicType s, Nullability sNullability, FunctionType t,
-      Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isDynamicRelated(DynamicType s, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      FunctionType t,
-      Nullability tNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      FunctionType t,
-      Nullability tNullability,
-      Types types) {
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, FunctionType t, Types types) {
     // Rule 12.
-    return types.isSubtypeOfKernel(
-        intersection.promotedBound, t, SubtypeCheckMode.ignoringNullabilities);
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t);
   }
 
   @override
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      FunctionType t, Nullability tNullability, Types types) {
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, FunctionType t, Types types) {
     // Rule 13.
-    return types.isSubtypeOfKernel(
-        s.parameter.bound, t, SubtypeCheckMode.ignoringNullabilities);
+    return types.performNullabilityAwareSubtypeCheck(s.parameter.bound, t);
   }
 
   @override
-  bool isTypedefRelated(TypedefType s, Nullability sNullability, FunctionType t,
-      Nullability tNullability, Types types) {
+  IsSubtypeOf isTypedefRelated(TypedefType s, FunctionType t, Types types) {
     // Rule 5.
-    return types.isSubtypeOfKernel(
-        s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
   }
 
   @override
-  bool isVoidRelated(VoidType s, Nullability sNullability, FunctionType t,
-      Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isVoidRelated(VoidType s, FunctionType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 }
 
@@ -526,63 +563,62 @@
   const IsTypeParameterSubtypeOf();
 
   @override
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      TypeParameterType t, Nullability tNullability, Types types) {
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType t, Types types) {
     return s.parameter == t.parameter ||
-        // Rule 13.
-        types.isSubtypeOfKernel(
-            s.bound, t, SubtypeCheckMode.ignoringNullabilities);
+            // Rule 13.
+            types
+                .performNullabilityAwareSubtypeCheck(s.bound, t)
+                .isSubtypeWhenIgnoringNullabilities()
+        ? const IsSubtypeOf.always()
+        : const IsSubtypeOf.never();
   }
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      TypeParameterType t,
-      Nullability tNullability,
-      Types types) {
-    return intersection.parameter == t.parameter; // Rule 8.
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, TypeParameterType t, Types types) {
+    return intersection.parameter == t.parameter
+        ? const IsSubtypeOf.always()
+        : const IsSubtypeOf.never(); // Rule 8.
   }
 
   @override
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
-      TypeParameterType t, Nullability tNullability, Types types) {
-    return s.classNode == types.hierarchy.nullClass; // Rule 4.
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, TypeParameterType t, Types types) {
+    if (s.classNode == types.hierarchy.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
+    }
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isDynamicRelated(DynamicType s, Nullability sNullability,
-      TypeParameterType t, Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFunctionRelated(FunctionType s, Nullability sNullability,
-      TypeParameterType t, Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      TypeParameterType t,
-      Nullability tNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isTypedefRelated(TypedefType s, Nullability sNullability,
-      TypeParameterType t, Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s.unalias, t, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, TypeParameterType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
   }
 
   @override
-  bool isVoidRelated(VoidType s, Nullability sNullability, TypeParameterType t,
-      Nullability tNullability, Types types) {
-    return false;
+  IsSubtypeOf isVoidRelated(VoidType s, TypeParameterType t, Types types) {
+    return const IsSubtypeOf.never();
   }
 }
 
@@ -590,67 +626,46 @@
   const IsTypedefSubtypeOf();
 
   @override
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
-      TypedefType t, Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
   }
 
   @override
-  bool isDynamicRelated(DynamicType s, Nullability sNullability, TypedefType t,
-      Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isDynamicRelated(DynamicType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
   }
 
   @override
-  bool isFunctionRelated(FunctionType s, Nullability sNullability,
-      TypedefType t, Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isFunctionRelated(FunctionType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      TypedefType t,
-      Nullability tNullability,
-      Types types) {
-    return types.isSubtypeOfKernel(
-        futureOr, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(futureOr, t.unalias);
   }
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      TypedefType t,
-      Nullability tNullability,
-      Types types) {
-    return types.isSubtypeOfKernel(
-        intersection, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(intersection, t.unalias);
   }
 
   @override
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      TypedefType t, Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
   }
 
   @override
-  bool isTypedefRelated(TypedefType s, Nullability sNullability, TypedefType t,
-      Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s.unalias, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isTypedefRelated(TypedefType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t.unalias);
   }
 
   @override
-  bool isVoidRelated(VoidType s, Nullability sNullability, TypedefType t,
-      Nullability tNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s, t.unalias, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isVoidRelated(VoidType s, TypedefType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s, t.unalias);
   }
 }
 
@@ -658,101 +673,95 @@
   const IsFutureOrSubtypeOf();
 
   @override
-  bool isInterfaceRelated(InterfaceType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, InterfaceType futureOr, Types types) {
     List<DartType> arguments = futureOr.typeArguments;
-    if (types.isSubtypeOfKernel(
-        s, arguments.single, SubtypeCheckMode.ignoringNullabilities)) {
-      return true; // Rule 11.
+    if (types
+        .performNullabilityAwareSubtypeCheck(s, arguments.single)
+        .isSubtypeWhenIgnoringNullabilities()) {
+      return const IsSubtypeOf.always(); // Rule 11.
     }
     // Rule 10.
-    return types.isSubtypeOfKernel(
+    return types.performNullabilityAwareSubtypeCheck(
         s,
-        new InterfaceType(types.hierarchy.futureClass, arguments),
-        SubtypeCheckMode.ignoringNullabilities);
+        new InterfaceType(
+            types.hierarchy.futureClass, arguments, futureOr.nullability));
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType sFutureOr,
-      Nullability sFutureOrNullability,
-      InterfaceType tFutureOr,
-      Nullability tFutureOrNullability,
-      Types types) {
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType sFutureOr, InterfaceType tFutureOr, Types types) {
     // This follows from combining rules 7, 10, and 11.
-    return types.isSubtypeOfKernel(sFutureOr.typeArguments.single,
-        tFutureOr.typeArguments.single, SubtypeCheckMode.ignoringNullabilities);
+    DartType sArgument = sFutureOr.typeArguments.single;
+    DartType tArgument = tFutureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(sArgument, tArgument);
   }
 
   @override
-  bool isDynamicRelated(DynamicType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, InterfaceType futureOr, Types types) {
     // Rule 11.
-    return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
-        SubtypeCheckMode.ignoringNullabilities);
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(s, argument);
   }
 
   @override
-  bool isVoidRelated(VoidType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
+  IsSubtypeOf isVoidRelated(VoidType s, InterfaceType futureOr, Types types) {
     // Rule 11.
-    return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
-        SubtypeCheckMode.ignoringNullabilities);
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(s, argument);
   }
 
   @override
-  bool isTypeParameterRelated(TypeParameterType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, InterfaceType futureOr, Types types) {
     List<DartType> arguments = futureOr.typeArguments;
-    if (types.isSubtypeOfKernel(
-        s, arguments.single, SubtypeCheckMode.ignoringNullabilities)) {
+    if (types
+        .performNullabilityAwareSubtypeCheck(s, arguments.single)
+        .isSubtypeWhenIgnoringNullabilities()) {
       // Rule 11.
-      return true;
+      return const IsSubtypeOf.always();
     }
 
-    if (types.isSubtypeOfKernel(
-        s.parameter.bound, futureOr, SubtypeCheckMode.ignoringNullabilities)) {
+    if (types
+        .performNullabilityAwareSubtypeCheck(s.parameter.bound, futureOr)
+        .isSubtypeWhenIgnoringNullabilities()) {
       // Rule 13.
-      return true;
+      return const IsSubtypeOf.always();
     }
 
     // Rule 10.
-    return types.isSubtypeOfKernel(
+    return types.performNullabilityAwareSubtypeCheck(
         s,
-        new InterfaceType(types.hierarchy.futureClass, arguments),
-        SubtypeCheckMode.ignoringNullabilities);
+        new InterfaceType(
+            types.hierarchy.futureClass, arguments, futureOr.nullability));
   }
 
   @override
-  bool isFunctionRelated(FunctionType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, InterfaceType futureOr, Types types) {
     // Rule 11.
-    return types.isSubtypeOfKernel(s, futureOr.typeArguments.single,
-        SubtypeCheckMode.ignoringNullabilities);
+    DartType argument = futureOr.typeArguments.single;
+    return types.performNullabilityAwareSubtypeCheck(s, argument);
   }
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      Types types) {
-    if (isTypeParameterRelated(intersection, intersectionNullability, futureOr,
-        futureOrNullability, types)) {
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, InterfaceType futureOr, Types types) {
+    if (isTypeParameterRelated(intersection, futureOr, types)
+        .isSubtypeWhenIgnoringNullabilities()) {
       // Rule 8.
-      return true;
+      return const IsSubtypeOf.always();
     }
     // Rule 12.
-    return types.isSubtypeOfKernel(intersection.promotedBound, futureOr,
-        SubtypeCheckMode.ignoringNullabilities);
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, futureOr);
   }
 
   @override
-  bool isTypedefRelated(TypedefType s, Nullability sNullability,
-      InterfaceType futureOr, Nullability futureOrNullability, Types types) {
-    return types.isSubtypeOfKernel(
-        s.unalias, futureOr, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, InterfaceType futureOr, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, futureOr);
   }
 }
 
@@ -760,96 +769,125 @@
   const IsIntersectionSubtypeOf();
 
   @override
-  bool isIntersectionRelated(
-      TypeParameterType sIntersection,
-      Nullability sIntersectionNullability,
-      TypeParameterType tIntersection,
-      Nullability tIntersectionNullability,
-      Types types) {
+  IsSubtypeOf isIntersectionRelated(TypeParameterType sIntersection,
+      TypeParameterType tIntersection, Types types) {
     // Rule 9.
-    return const IsTypeParameterSubtypeOf().isIntersectionRelated(
-            sIntersection,
-            sIntersectionNullability,
-            tIntersection,
-            tIntersectionNullability,
-            types) &&
-        types.isSubtypeOfKernel(sIntersection, tIntersection.promotedBound,
-            SubtypeCheckMode.ignoringNullabilities);
+    return const IsTypeParameterSubtypeOf()
+                .isIntersectionRelated(sIntersection, tIntersection, types)
+                .isSubtypeWhenIgnoringNullabilities() &&
+            types
+                .performNullabilityAwareSubtypeCheck(
+                    sIntersection, tIntersection.promotedBound)
+                .isSubtypeWhenIgnoringNullabilities()
+        ? const IsSubtypeOf.always()
+        : const IsSubtypeOf.never();
   }
 
   @override
-  bool isTypeParameterRelated(
-      TypeParameterType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType intersection, Types types) {
     // Rule 9.
-    return const IsTypeParameterSubtypeOf().isTypeParameterRelated(
-            s, sNullability, intersection, intersectionNullability, types) &&
-        types.isSubtypeOfKernel(s, intersection.promotedBound,
-            SubtypeCheckMode.ignoringNullabilities);
+    return const IsTypeParameterSubtypeOf()
+                .isTypeParameterRelated(s, intersection, types)
+                .isSubtypeWhenIgnoringNullabilities() &&
+            types
+                .performNullabilityAwareSubtypeCheck(
+                    s, intersection.promotedBound)
+                .isSubtypeWhenIgnoringNullabilities()
+        ? const IsSubtypeOf.always()
+        : const IsSubtypeOf.never();
   }
 
   @override
-  bool isInterfaceRelated(
-      InterfaceType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
-    return s.classNode == types.hierarchy.nullClass; // Rule 4.
+  IsSubtypeOf isInterfaceRelated(
+      InterfaceType s, TypeParameterType intersection, Types types) {
+    if (s.classNode == types.hierarchy.nullClass) {
+      // Rule 4.
+      return new IsSubtypeOf.basedSolelyOnNullabilities(s, intersection);
+    }
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isDynamicRelated(
-      DynamicType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isDynamicRelated(
+      DynamicType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFunctionRelated(
-      FunctionType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isFunctionRelated(
+      FunctionType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isFutureOrRelated(
-      InterfaceType futureOr,
-      Nullability futureOrNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
   }
 
   @override
-  bool isTypedefRelated(
-      TypedefType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
+  IsSubtypeOf isTypedefRelated(
+      TypedefType s, TypeParameterType intersection, Types types) {
     // Rule 5.
-    return types.isSubtypeOfKernel(
-        s.unalias, intersection, SubtypeCheckMode.ignoringNullabilities);
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, intersection);
   }
 
   @override
-  bool isVoidRelated(
-      VoidType s,
-      Nullability sNullability,
-      TypeParameterType intersection,
-      Nullability intersectionNullability,
-      Types types) {
-    return false;
+  IsSubtypeOf isVoidRelated(
+      VoidType s, TypeParameterType intersection, Types types) {
+    return const IsSubtypeOf.never();
+  }
+}
+
+class IsNeverTypeSubtypeOf implements TypeRelation<NeverType> {
+  const IsNeverTypeSubtypeOf();
+
+  IsSubtypeOf isDynamicRelated(DynamicType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isVoidRelated(VoidType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isInterfaceRelated(InterfaceType s, NeverType t, Types types) {
+    if (s.classNode == types.hierarchy.nullClass) {
+      if (t.nullability == Nullability.nullable) {
+        return const IsSubtypeOf.always();
+      }
+      if (t.nullability == Nullability.nonNullable) {
+        return const IsSubtypeOf.never();
+      }
+      throw new StateError(
+          "Unexpected nullability '$t.nullability' of type Never");
+    }
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isIntersectionRelated(
+      TypeParameterType intersection, NeverType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(
+        intersection.promotedBound, t);
+  }
+
+  IsSubtypeOf isFunctionRelated(FunctionType s, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isFutureOrRelated(
+      InterfaceType futureOr, NeverType t, Types types) {
+    return const IsSubtypeOf.never();
+  }
+
+  IsSubtypeOf isTypeParameterRelated(
+      TypeParameterType s, NeverType t, Types types) {
+    return types
+        .performNullabilityAwareSubtypeCheck(s.bound, t)
+        .join(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
+  }
+
+  IsSubtypeOf isTypedefRelated(TypedefType s, NeverType t, Types types) {
+    return types.performNullabilityAwareSubtypeCheck(s.unalias, t);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index d6a1f87..bae007a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -4,6 +4,8 @@
 
 library fasta.verifier;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart'
     show
         AsExpression,
@@ -34,8 +36,6 @@
 import '../fasta_codes.dart'
     show LocatedMessage, noLength, templateInternalProblemVerificationError;
 
-import '../severity.dart' show Severity;
-
 import '../type_inference/type_schema.dart' show UnknownType;
 
 import 'redirecting_factory_body.dart'
diff --git a/pkg/front_end/lib/src/fasta/library_graph.dart b/pkg/front_end/lib/src/fasta/library_graph.dart
index acf183f..ddbf967 100644
--- a/pkg/front_end/lib/src/fasta/library_graph.dart
+++ b/pkg/front_end/lib/src/fasta/library_graph.dart
@@ -4,6 +4,9 @@
 
 library fasta.library_graph;
 
+import 'package:front_end/src/fasta/source/source_library_builder.dart'
+    show SourceLibraryBuilder;
+
 import 'package:kernel/kernel.dart'
     show Library, LibraryDependency, LibraryPart;
 
@@ -39,8 +42,8 @@
     // Normally there won't be libraries for these, but if, for instance,
     // the part didn't exist there will be a synthetic library.
     for (LibraryPart part in library.parts) {
-      Uri partUri = library.importUri.resolve(part.partUri);
-      Uri fileUri = library.fileUri.resolve(part.partUri);
+      Uri partUri = getPartUri(library.importUri, part.partUri);
+      Uri fileUri = getPartUri(library.fileUri, part.partUri);
       if (libraries.containsKey(partUri)) {
         yield partUri;
       } else if (fileUri != partUri && libraries.containsKey(fileUri)) {
@@ -48,4 +51,15 @@
       }
     }
   }
+
+  Uri getPartUri(Uri base, String part) {
+    try {
+      return base.resolve(part);
+    } on FormatException {
+      // This is also done in [SourceLibraryBuilder.resolve]
+      return new Uri(
+          scheme: SourceLibraryBuilder.MALFORMED_URI_SCHEME,
+          query: Uri.encodeQueryComponent(part));
+    }
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index aaf35d3..3cfe51d 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -8,6 +8,8 @@
 
 import 'dart:collection' show Queue;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart' show Class, DartType, Library;
 
 import 'scope.dart';
@@ -37,8 +39,6 @@
 
 import 'problems.dart' show internalProblem, unhandled;
 
-import 'severity.dart' show Severity;
-
 import 'target_implementation.dart' show TargetImplementation;
 
 import 'ticker.dart' show Ticker;
diff --git a/pkg/front_end/lib/src/fasta/parser.dart b/pkg/front_end/lib/src/fasta/parser.dart
deleted file mode 100644
index 950a70c..0000000
--- a/pkg/front_end/lib/src/fasta/parser.dart
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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.md file.
-
-library fasta.parser;
-
-import '../scanner/token.dart' show Token;
-
-import 'parser/listener.dart' show Listener;
-
-import 'parser/parser.dart' show Parser;
-
-import 'parser/parser_error.dart' show ParserError;
-
-import 'fasta_codes.dart' show Message, messageNativeClauseShouldBeAnnotation;
-
-export 'parser/assert.dart' show Assert;
-
-export 'parser/class_member_parser.dart' show ClassMemberParser;
-
-export 'parser/formal_parameter_kind.dart' show FormalParameterKind;
-
-export 'parser/identifier_context.dart' show IdentifierContext;
-
-export 'parser/listener.dart' show Listener;
-
-export 'parser/declaration_kind.dart' show DeclarationKind;
-
-export 'parser/member_kind.dart' show MemberKind;
-
-export 'parser/parser.dart' show Parser;
-
-export 'parser/parser_error.dart' show ParserError;
-
-export 'parser/top_level_parser.dart' show TopLevelParser;
-
-export 'parser/util.dart'
-    show lengthForToken, lengthOfSpan, offsetForToken, optional;
-
-class ErrorCollectingListener extends Listener {
-  final List<ParserError> recoverableErrors = <ParserError>[];
-
-  void handleRecoverableError(
-      Message message, Token startToken, Token endToken) {
-    /// TODO(danrubel): Ignore this error until we deprecate `native` support.
-    if (message == messageNativeClauseShouldBeAnnotation) {
-      return;
-    }
-    recoverableErrors
-        .add(new ParserError.fromTokens(startToken, endToken, message));
-  }
-}
-
-List<ParserError> parse(Token tokens) {
-  ErrorCollectingListener listener = new ErrorCollectingListener();
-  Parser parser = new Parser(listener);
-  parser.parseUnit(tokens);
-  return listener.recoverableErrors;
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/assert.dart b/pkg/front_end/lib/src/fasta/parser/assert.dart
deleted file mode 100644
index d6a9794..0000000
--- a/pkg/front_end/lib/src/fasta/parser/assert.dart
+++ /dev/null
@@ -1,16 +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.
-
-library fasta.parser.Assert;
-
-/// Syntactic forms of `assert`.
-///
-/// An assertion can legally occur as a statement. However, assertions are also
-/// experimentally allowed in initializers. For improved error recovery, we
-/// also attempt to parse asserts as expressions.
-enum Assert {
-  Expression,
-  Initializer,
-  Statement,
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/async_modifier.dart b/pkg/front_end/lib/src/fasta/parser/async_modifier.dart
deleted file mode 100644
index 0c09d23..0000000
--- a/pkg/front_end/lib/src/fasta/parser/async_modifier.dart
+++ /dev/null
@@ -1,12 +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.
-
-library fasta.parser.async_modifier;
-
-enum AsyncModifier {
-  Sync,
-  SyncStar,
-  Async,
-  AsyncStar,
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/class_member_parser.dart b/pkg/front_end/lib/src/fasta/parser/class_member_parser.dart
deleted file mode 100644
index 27e7370..0000000
--- a/pkg/front_end/lib/src/fasta/parser/class_member_parser.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.parser.class_member_parser;
-
-import '../../scanner/token.dart' show Token;
-
-import 'error_delegation_listener.dart' show ErrorDelegationListener;
-
-import 'listener.dart' show Listener;
-
-import 'parser.dart' show Parser;
-
-/// Parser similar to [TopLevelParser] but also parses class members (excluding
-/// their bodies).
-class ClassMemberParser extends Parser {
-  Parser skipParser;
-
-  ClassMemberParser(Listener listener) : super(listener);
-
-  @override
-  Token parseExpression(Token token) {
-    return skipExpression(token);
-  }
-
-  @override
-  Token parseIdentifierExpression(Token token) {
-    return token.next;
-  }
-
-  Token skipExpression(Token token) {
-    // TODO(askesc): We listen to errors occurring during expression parsing,
-    // since the parser may rewrite the token stream such that the error is
-    // 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));
-    skipParser.mayParseFunctionExpressions = mayParseFunctionExpressions;
-    skipParser.asyncState = asyncState;
-    skipParser.loopState = loopState;
-    return skipParser.parseExpression(token);
-  }
-
-  // This method is overridden for two reasons:
-  // 1. Avoid generating events for arguments.
-  // 2. Avoid calling skip expression for each argument (which doesn't work).
-  Token parseArgumentsOpt(Token token) => skipArgumentsOpt(token);
-
-  Token parseFunctionBody(Token token, bool isExpression, bool allowAbstract) {
-    return skipFunctionBody(token, isExpression, allowAbstract);
-  }
-
-  @override
-  Token parseInvalidBlock(Token token) => skipBlock(token);
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/directive_context.dart b/pkg/front_end/lib/src/fasta/parser/directive_context.dart
deleted file mode 100644
index 26e9dc2..0000000
--- a/pkg/front_end/lib/src/fasta/parser/directive_context.dart
+++ /dev/null
@@ -1,108 +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 '../fasta_codes.dart';
-import 'parser.dart';
-import '../../scanner/token.dart';
-
-class DirectiveContext {
-  DirectiveState state = DirectiveState.Unknown;
-
-  void checkScriptTag(Parser parser, Token token) {
-    if (state == DirectiveState.Unknown) {
-      state = DirectiveState.Script;
-      return;
-    }
-    // The scanner only produces the SCRIPT_TAG
-    // when it is the first token in the file.
-    throw "Internal error: Unexpected script tag.";
-  }
-
-  void checkDeclaration() {
-    if (state != DirectiveState.PartOf) {
-      state = DirectiveState.Declarations;
-    }
-  }
-
-  void checkExport(Parser parser, Token token) {
-    if (state.index <= DirectiveState.ImportAndExport.index) {
-      state = DirectiveState.ImportAndExport;
-      return;
-    }
-    // Recovery
-    if (state == DirectiveState.Part) {
-      parser.reportRecoverableError(token, messageExportAfterPart);
-    } else if (state == DirectiveState.PartOf) {
-      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
-    } else {
-      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
-    }
-  }
-
-  void checkImport(Parser parser, Token token) {
-    if (state.index <= DirectiveState.ImportAndExport.index) {
-      state = DirectiveState.ImportAndExport;
-      return;
-    }
-    // Recovery
-    if (state == DirectiveState.Part) {
-      parser.reportRecoverableError(token, messageImportAfterPart);
-    } else if (state == DirectiveState.PartOf) {
-      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
-    } else {
-      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
-    }
-  }
-
-  void checkLibrary(Parser parser, Token token) {
-    if (state.index < DirectiveState.Library.index) {
-      state = DirectiveState.Library;
-      return;
-    }
-    // Recovery
-    if (state == DirectiveState.Library) {
-      parser.reportRecoverableError(token, messageMultipleLibraryDirectives);
-    } else if (state == DirectiveState.PartOf) {
-      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
-    } else {
-      parser.reportRecoverableError(token, messageLibraryDirectiveNotFirst);
-    }
-  }
-
-  void checkPart(Parser parser, Token token) {
-    if (state.index <= DirectiveState.Part.index) {
-      state = DirectiveState.Part;
-      return;
-    }
-    // Recovery
-    if (state == DirectiveState.PartOf) {
-      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
-    } else {
-      parser.reportRecoverableError(token, messageDirectiveAfterDeclaration);
-    }
-  }
-
-  void checkPartOf(Parser parser, Token token) {
-    if (state == DirectiveState.Unknown) {
-      state = DirectiveState.PartOf;
-      return;
-    }
-    // Recovery
-    if (state == DirectiveState.PartOf) {
-      parser.reportRecoverableError(token, messagePartOfTwice);
-    } else {
-      parser.reportRecoverableError(token, messageNonPartOfDirectiveInPart);
-    }
-  }
-}
-
-enum DirectiveState {
-  Unknown,
-  Script,
-  Library,
-  ImportAndExport,
-  Part,
-  PartOf,
-  Declarations,
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/error_delegation_listener.dart b/pkg/front_end/lib/src/fasta/parser/error_delegation_listener.dart
deleted file mode 100644
index 3d20dfa..0000000
--- a/pkg/front_end/lib/src/fasta/parser/error_delegation_listener.dart
+++ /dev/null
@@ -1,22 +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 '../../scanner/token.dart' show Token;
-
-import '../fasta_codes.dart' show Message;
-
-import 'listener.dart' show Listener;
-
-/// A listener which forwards error reports to another listener but ignores
-/// all other events.
-class ErrorDelegationListener extends Listener {
-  Listener delegate;
-
-  ErrorDelegationListener(this.delegate);
-
-  void handleRecoverableError(
-      Message message, Token startToken, Token endToken) {
-    return delegate.handleRecoverableError(message, startToken, endToken);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/formal_parameter_kind.dart b/pkg/front_end/lib/src/fasta/parser/formal_parameter_kind.dart
deleted file mode 100644
index 11b1041..0000000
--- a/pkg/front_end/lib/src/fasta/parser/formal_parameter_kind.dart
+++ /dev/null
@@ -1,24 +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.
-
-library fasta.parser.formal_parameter_kind;
-
-// TODO(johnniwinther): Update this to support required named arguments.
-enum FormalParameterKind {
-  mandatory,
-  optionalNamed,
-  optionalPositional,
-}
-
-bool isMandatoryFormalParameterKind(FormalParameterKind type) {
-  return FormalParameterKind.mandatory == type;
-}
-
-bool isOptionalNamedFormalParameterKind(FormalParameterKind type) {
-  return FormalParameterKind.optionalNamed == type;
-}
-
-bool isOptionalPositionalFormalParameterKind(FormalParameterKind type) {
-  return FormalParameterKind.optionalPositional == type;
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
deleted file mode 100644
index 16384d7..0000000
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ /dev/null
@@ -1,1587 +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 '../messages.dart';
-import '../parser.dart';
-import '../scanner.dart';
-
-class ForwardingListener implements Listener {
-  Listener listener;
-  bool forwardErrors = true;
-
-  ForwardingListener([this.listener]);
-
-  @override
-  set suppressParseErrors(bool value) {
-    listener?.suppressParseErrors = value;
-  }
-
-  @override
-  Uri get uri => listener?.uri;
-
-  @override
-  void beginArguments(Token token) {
-    listener?.beginArguments(token);
-  }
-
-  @override
-  void beginAssert(Token assertKeyword, Assert kind) {
-    listener?.beginAssert(assertKeyword, kind);
-  }
-
-  @override
-  void beginAwaitExpression(Token token) {
-    listener?.beginAwaitExpression(token);
-  }
-
-  @override
-  void beginBinaryExpression(Token token) {
-    listener?.beginBinaryExpression(token);
-  }
-
-  @override
-  void beginBlock(Token token) {
-    listener?.beginBlock(token);
-  }
-
-  @override
-  void beginBlockFunctionBody(Token token) {
-    listener?.beginBlockFunctionBody(token);
-  }
-
-  @override
-  void beginCascade(Token token) {
-    listener?.beginCascade(token);
-  }
-
-  @override
-  void beginCaseExpression(Token caseKeyword) {
-    listener?.beginCaseExpression(caseKeyword);
-  }
-
-  @override
-  void beginCatchClause(Token token) {
-    listener?.beginCatchClause(token);
-  }
-
-  @override
-  void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
-    listener?.beginClassDeclaration(begin, abstractToken, name);
-  }
-
-  @override
-  void beginClassOrMixinBody(DeclarationKind kind, Token token) {
-    listener?.beginClassOrMixinBody(kind, token);
-  }
-
-  @override
-  void beginClassOrNamedMixinApplicationPrelude(Token token) {
-    listener?.beginClassOrNamedMixinApplicationPrelude(token);
-  }
-
-  @override
-  void beginCombinators(Token token) {
-    listener?.beginCombinators(token);
-  }
-
-  @override
-  void beginCompilationUnit(Token token) {
-    listener?.beginCompilationUnit(token);
-  }
-
-  @override
-  void beginConditionalExpression(Token question) {
-    listener?.beginConditionalExpression(question);
-  }
-
-  @override
-  void beginConditionalUri(Token ifKeyword) {
-    listener?.beginConditionalUri(ifKeyword);
-  }
-
-  @override
-  void beginConditionalUris(Token token) {
-    listener?.beginConditionalUris(token);
-  }
-
-  @override
-  void beginConstExpression(Token constKeyword) {
-    listener?.beginConstExpression(constKeyword);
-  }
-
-  @override
-  void beginConstLiteral(Token token) {
-    listener?.beginConstLiteral(token);
-  }
-
-  @override
-  void beginConstructorReference(Token start) {
-    listener?.beginConstructorReference(start);
-  }
-
-  @override
-  void beginDoWhileStatement(Token token) {
-    listener?.beginDoWhileStatement(token);
-  }
-
-  @override
-  void beginDoWhileStatementBody(Token token) {
-    listener?.beginDoWhileStatementBody(token);
-  }
-
-  @override
-  void beginElseStatement(Token token) {
-    listener?.beginElseStatement(token);
-  }
-
-  @override
-  void beginEnum(Token enumKeyword) {
-    listener?.beginEnum(enumKeyword);
-  }
-
-  @override
-  void beginExport(Token token) {
-    listener?.beginExport(token);
-  }
-
-  @override
-  void beginExtensionDeclarationPrelude(Token extensionKeyword) {
-    listener?.beginExtensionDeclarationPrelude(extensionKeyword);
-  }
-
-  @override
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {
-    listener?.beginExtensionDeclaration(extensionKeyword, name);
-  }
-
-  @override
-  void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {
-    listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
-  }
-
-  @override
-  void beginFieldInitializer(Token token) {
-    listener?.beginFieldInitializer(token);
-  }
-
-  @override
-  void beginForControlFlow(Token awaitToken, Token forToken) {
-    listener?.beginForControlFlow(awaitToken, forToken);
-  }
-
-  @override
-  void beginForInBody(Token token) {
-    listener?.beginForInBody(token);
-  }
-
-  @override
-  void beginForInExpression(Token token) {
-    listener?.beginForInExpression(token);
-  }
-
-  @override
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {
-    listener?.beginFormalParameter(
-        token, kind, requiredToken, covariantToken, varFinalOrConst);
-  }
-
-  @override
-  void beginFormalParameterDefaultValueExpression() {
-    listener?.beginFormalParameterDefaultValueExpression();
-  }
-
-  @override
-  void beginFormalParameters(Token token, MemberKind kind) {
-    listener?.beginFormalParameters(token, kind);
-  }
-
-  @override
-  void beginForStatement(Token token) {
-    listener?.beginForStatement(token);
-  }
-
-  @override
-  void beginForStatementBody(Token token) {
-    listener?.beginForStatementBody(token);
-  }
-
-  @override
-  void beginFunctionExpression(Token token) {
-    listener?.beginFunctionExpression(token);
-  }
-
-  @override
-  void beginFunctionName(Token token) {
-    listener?.beginFunctionName(token);
-  }
-
-  @override
-  void beginFunctionType(Token beginToken) {
-    listener?.beginFunctionType(beginToken);
-  }
-
-  @override
-  void beginFunctionTypeAlias(Token token) {
-    listener?.beginFunctionTypeAlias(token);
-  }
-
-  @override
-  void beginFunctionTypedFormalParameter(Token token) {
-    listener?.beginFunctionTypedFormalParameter(token);
-  }
-
-  @override
-  void beginHide(Token hideKeyword) {
-    listener?.beginHide(hideKeyword);
-  }
-
-  @override
-  void beginIfControlFlow(Token ifToken) {
-    listener?.beginIfControlFlow(ifToken);
-  }
-
-  @override
-  void beginIfStatement(Token token) {
-    listener?.beginIfStatement(token);
-  }
-
-  @override
-  void beginImplicitCreationExpression(Token token) {
-    listener?.beginImplicitCreationExpression(token);
-  }
-
-  @override
-  void beginImport(Token importKeyword) {
-    listener?.beginImport(importKeyword);
-  }
-
-  @override
-  void beginInitializedIdentifier(Token token) {
-    listener?.beginInitializedIdentifier(token);
-  }
-
-  @override
-  void beginInitializer(Token token) {
-    listener?.beginInitializer(token);
-  }
-
-  @override
-  void beginInitializers(Token token) {
-    listener?.beginInitializers(token);
-  }
-
-  @override
-  void beginLabeledStatement(Token token, int labelCount) {
-    listener?.beginLabeledStatement(token, labelCount);
-  }
-
-  @override
-  void beginLibraryName(Token token) {
-    listener?.beginLibraryName(token);
-  }
-
-  @override
-  void beginLiteralString(Token token) {
-    listener?.beginLiteralString(token);
-  }
-
-  @override
-  void beginLiteralSymbol(Token token) {
-    listener?.beginLiteralSymbol(token);
-  }
-
-  @override
-  void beginLocalFunctionDeclaration(Token token) {
-    listener?.beginLocalFunctionDeclaration(token);
-  }
-
-  @override
-  void beginMember() {
-    listener?.beginMember();
-  }
-
-  @override
-  void beginMetadata(Token token) {
-    listener?.beginMetadata(token);
-  }
-
-  @override
-  void beginMetadataStar(Token token) {
-    listener?.beginMetadataStar(token);
-  }
-
-  @override
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {
-    listener?.beginMethod(externalToken, staticToken, covariantToken,
-        varFinalOrConst, getOrSet, name);
-  }
-
-  @override
-  void beginMixinDeclaration(Token mixinKeyword, Token name) {
-    listener?.beginMixinDeclaration(mixinKeyword, name);
-  }
-
-  @override
-  void beginNamedFunctionExpression(Token token) {
-    listener?.beginNamedFunctionExpression(token);
-  }
-
-  @override
-  void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {
-    listener?.beginNamedMixinApplication(begin, abstractToken, name);
-  }
-
-  @override
-  void beginNewExpression(Token token) {
-    listener?.beginNewExpression(token);
-  }
-
-  @override
-  void beginOptionalFormalParameters(Token token) {
-    listener?.beginOptionalFormalParameters(token);
-  }
-
-  @override
-  void beginPart(Token token) {
-    listener?.beginPart(token);
-  }
-
-  @override
-  void beginPartOf(Token token) {
-    listener?.beginPartOf(token);
-  }
-
-  @override
-  void beginRedirectingFactoryBody(Token token) {
-    listener?.beginRedirectingFactoryBody(token);
-  }
-
-  @override
-  void beginRethrowStatement(Token token) {
-    listener?.beginRethrowStatement(token);
-  }
-
-  @override
-  void beginReturnStatement(Token token) {
-    listener?.beginReturnStatement(token);
-  }
-
-  @override
-  void beginShow(Token showKeyword) {
-    listener?.beginShow(showKeyword);
-  }
-
-  @override
-  void beginSwitchBlock(Token token) {
-    listener?.beginSwitchBlock(token);
-  }
-
-  @override
-  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {
-    listener?.beginSwitchCase(labelCount, expressionCount, firstToken);
-  }
-
-  @override
-  void beginSwitchStatement(Token token) {
-    listener?.beginSwitchStatement(token);
-  }
-
-  @override
-  void beginThenControlFlow(Token token) {
-    listener?.beginThenControlFlow(token);
-  }
-
-  @override
-  void beginThenStatement(Token token) {
-    listener?.beginThenStatement(token);
-  }
-
-  @override
-  void beginTopLevelMember(Token token) {
-    listener?.beginTopLevelMember(token);
-  }
-
-  @override
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {
-    listener?.beginTopLevelMethod(lastConsumed, externalToken);
-  }
-
-  @override
-  void beginTryStatement(Token token) {
-    listener?.beginTryStatement(token);
-  }
-
-  @override
-  void beginTypeArguments(Token token) {
-    listener?.beginTypeArguments(token);
-  }
-
-  @override
-  void beginTypeList(Token token) {
-    listener?.beginTypeList(token);
-  }
-
-  @override
-  void beginTypeVariable(Token token) {
-    listener?.beginTypeVariable(token);
-  }
-
-  @override
-  void beginTypeVariables(Token token) {
-    listener?.beginTypeVariables(token);
-  }
-
-  @override
-  void beginVariableInitializer(Token token) {
-    listener?.beginVariableInitializer(token);
-  }
-
-  @override
-  void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {
-    listener?.beginVariablesDeclaration(token, lateToken, varFinalOrConst);
-  }
-
-  @override
-  void beginWhileStatement(Token token) {
-    listener?.beginWhileStatement(token);
-  }
-
-  @override
-  void beginWhileStatementBody(Token token) {
-    listener?.beginWhileStatementBody(token);
-  }
-
-  @override
-  void beginYieldStatement(Token token) {
-    listener?.beginYieldStatement(token);
-  }
-
-  @override
-  void discardTypeReplacedWithCommentTypeAssign() {
-    listener?.discardTypeReplacedWithCommentTypeAssign();
-  }
-
-  @override
-  void endArguments(int count, Token beginToken, Token endToken) {
-    listener?.endArguments(count, beginToken, endToken);
-  }
-
-  @override
-  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
-    listener?.endAssert(
-        assertKeyword, kind, leftParenthesis, commaToken, semicolonToken);
-  }
-
-  @override
-  void endAwaitExpression(Token beginToken, Token endToken) {
-    listener?.endAwaitExpression(beginToken, endToken);
-  }
-
-  @override
-  void endBinaryExpression(Token token) {
-    listener?.endBinaryExpression(token);
-  }
-
-  @override
-  void endBlock(int count, Token beginToken, Token endToken) {
-    listener?.endBlock(count, beginToken, endToken);
-  }
-
-  @override
-  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
-    listener?.endBlockFunctionBody(count, beginToken, endToken);
-  }
-
-  @override
-  void endCascade() {
-    listener?.endCascade();
-  }
-
-  @override
-  void endCaseExpression(Token colon) {
-    listener?.endCaseExpression(colon);
-  }
-
-  @override
-  void endCatchClause(Token token) {
-    listener?.endCatchClause(token);
-  }
-
-  @override
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    listener?.endClassConstructor(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endClassDeclaration(Token beginToken, Token endToken) {
-    listener?.endClassDeclaration(beginToken, endToken);
-  }
-
-  @override
-  void endClassFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    listener?.endClassFactoryMethod(beginToken, factoryKeyword, endToken);
-  }
-
-  @override
-  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    listener?.endClassFields(staticToken, covariantToken, lateToken,
-        varFinalOrConst, count, beginToken, endToken);
-  }
-
-  @override
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    listener?.endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endClassOrMixinBody(
-      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
-    listener?.endClassOrMixinBody(kind, memberCount, beginToken, endToken);
-  }
-
-  @override
-  void endCombinators(int count) {
-    listener?.endCombinators(count);
-  }
-
-  @override
-  void endCompilationUnit(int count, Token token) {
-    listener?.endCompilationUnit(count, token);
-  }
-
-  @override
-  void endConditionalExpression(Token question, Token colon) {
-    listener?.endConditionalExpression(question, colon);
-  }
-
-  @override
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
-    listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
-  }
-
-  @override
-  void endConditionalUris(int count) {
-    listener?.endConditionalUris(count);
-  }
-
-  @override
-  void endConstExpression(Token token) {
-    listener?.endConstExpression(token);
-  }
-
-  @override
-  void endConstLiteral(Token token) {
-    listener?.endConstLiteral(token);
-  }
-
-  @override
-  void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
-    listener?.endConstructorReference(start, periodBeforeName, endToken);
-  }
-
-  @override
-  void endDoWhileStatement(
-      Token doKeyword, Token whileKeyword, Token endToken) {
-    listener?.endDoWhileStatement(doKeyword, whileKeyword, endToken);
-  }
-
-  @override
-  void endDoWhileStatementBody(Token token) {
-    listener?.endDoWhileStatementBody(token);
-  }
-
-  @override
-  void endElseStatement(Token token) {
-    listener?.endElseStatement(token);
-  }
-
-  @override
-  void endEnum(Token enumKeyword, Token leftBrace, int count) {
-    listener?.endEnum(enumKeyword, leftBrace, count);
-  }
-
-  @override
-  void endExport(Token exportKeyword, Token semicolon) {
-    listener?.endExport(exportKeyword, semicolon);
-  }
-
-  @override
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
-    listener?.endExtensionConstructor(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endExtensionDeclaration(
-      Token extensionKeyword, Token onKeyword, Token token) {
-    listener?.endExtensionDeclaration(extensionKeyword, onKeyword, token);
-  }
-
-  @override
-  void endExtensionFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    listener?.endExtensionFactoryMethod(beginToken, factoryKeyword, endToken);
-  }
-
-  @override
-  void endExtensionFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    listener?.endExtensionFields(staticToken, covariantToken, lateToken,
-        varFinalOrConst, count, beginToken, endToken);
-  }
-
-  @override
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    listener?.endExtensionMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endFieldInitializer(Token assignment, Token token) {
-    listener?.endFieldInitializer(assignment, token);
-  }
-
-  @override
-  void endForControlFlow(Token token) {
-    listener?.endForControlFlow(token);
-  }
-
-  @override
-  void endForIn(Token endToken) {
-    listener?.endForIn(endToken);
-  }
-
-  @override
-  void endForInBody(Token token) {
-    listener?.endForInBody(token);
-  }
-
-  @override
-  void endForInControlFlow(Token token) {
-    listener?.endForInControlFlow(token);
-  }
-
-  @override
-  void endForInExpression(Token token) {
-    listener?.endForInExpression(token);
-  }
-
-  @override
-  void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
-      Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
-      FormalParameterKind kind,
-      MemberKind memberKind) {
-    listener?.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
-        initializerStart, initializerEnd, kind, memberKind);
-  }
-
-  @override
-  void endFormalParameterDefaultValueExpression() {
-    listener?.endFormalParameterDefaultValueExpression();
-  }
-
-  @override
-  void endFormalParameters(
-      int count, Token beginToken, Token endToken, MemberKind kind) {
-    listener?.endFormalParameters(count, beginToken, endToken, kind);
-  }
-
-  @override
-  void endForStatement(Token endToken) {
-    listener?.endForStatement(endToken);
-  }
-
-  @override
-  void endForStatementBody(Token token) {
-    listener?.endForStatementBody(token);
-  }
-
-  @override
-  void endFunctionExpression(Token beginToken, Token token) {
-    listener?.endFunctionExpression(beginToken, token);
-  }
-
-  @override
-  void endFunctionName(Token beginToken, Token token) {
-    listener?.endFunctionName(beginToken, token);
-  }
-
-  @override
-  void endFunctionType(Token functionToken, Token questionMark) {
-    listener?.endFunctionType(functionToken, questionMark);
-  }
-
-  @override
-  void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
-    listener?.endFunctionTypeAlias(typedefKeyword, equals, endToken);
-  }
-
-  @override
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
-    listener?.endFunctionTypedFormalParameter(nameToken, question);
-  }
-
-  @override
-  void endHide(Token hideKeyword) {
-    listener?.endHide(hideKeyword);
-  }
-
-  @override
-  void endIfControlFlow(Token token) {
-    listener?.endIfControlFlow(token);
-  }
-
-  @override
-  void endIfElseControlFlow(Token token) {
-    listener?.endIfElseControlFlow(token);
-  }
-
-  @override
-  void endIfStatement(Token ifToken, Token elseToken) {
-    listener?.endIfStatement(ifToken, elseToken);
-  }
-
-  @override
-  void endImplicitCreationExpression(Token token) {
-    listener?.endImplicitCreationExpression(token);
-  }
-
-  @override
-  void endImport(Token importKeyword, Token semicolon) {
-    listener?.endImport(importKeyword, semicolon);
-  }
-
-  @override
-  void endInitializedIdentifier(Token nameToken) {
-    listener?.endInitializedIdentifier(nameToken);
-  }
-
-  @override
-  void endInitializer(Token token) {
-    listener?.endInitializer(token);
-  }
-
-  @override
-  void endInitializers(int count, Token beginToken, Token endToken) {
-    listener?.endInitializers(count, beginToken, endToken);
-  }
-
-  @override
-  void endInvalidAwaitExpression(
-      Token beginToken, Token endToken, MessageCode errorCode) {
-    listener?.endInvalidAwaitExpression(beginToken, endToken, errorCode);
-  }
-
-  @override
-  void endLabeledStatement(int labelCount) {
-    listener?.endLabeledStatement(labelCount);
-  }
-
-  @override
-  void endLibraryName(Token libraryKeyword, Token semicolon) {
-    listener?.endLibraryName(libraryKeyword, semicolon);
-  }
-
-  @override
-  void endLiteralString(int interpolationCount, Token endToken) {
-    listener?.endLiteralString(interpolationCount, endToken);
-  }
-
-  @override
-  void endLiteralSymbol(Token hashToken, int identifierCount) {
-    listener?.endLiteralSymbol(hashToken, identifierCount);
-  }
-
-  @override
-  void endLocalFunctionDeclaration(Token endToken) {
-    listener?.endLocalFunctionDeclaration(endToken);
-  }
-
-  @override
-  void endMember() {
-    listener?.endMember();
-  }
-
-  @override
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
-    listener?.endMetadata(beginToken, periodBeforeName, endToken);
-  }
-
-  @override
-  void endMetadataStar(int count) {
-    listener?.endMetadataStar(count);
-  }
-
-  @override
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    listener?.endMixinConstructor(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
-    listener?.endMixinDeclaration(mixinKeyword, endToken);
-  }
-
-  @override
-  void endMixinFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    listener?.endMixinFactoryMethod(beginToken, factoryKeyword, endToken);
-  }
-
-  @override
-  void endMixinFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    listener?.endMixinFields(staticToken, covariantToken, lateToken,
-        varFinalOrConst, count, beginToken, endToken);
-  }
-
-  @override
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    listener?.endMixinMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  @override
-  void endNamedFunctionExpression(Token endToken) {
-    listener?.endNamedFunctionExpression(endToken);
-  }
-
-  @override
-  void endNamedMixinApplication(Token begin, Token classKeyword, Token equals,
-      Token implementsKeyword, Token endToken) {
-    listener?.endNamedMixinApplication(
-        begin, classKeyword, equals, implementsKeyword, endToken);
-  }
-
-  @override
-  void endNewExpression(Token token) {
-    listener?.endNewExpression(token);
-  }
-
-  @override
-  void endOptionalFormalParameters(
-      int count, Token beginToken, Token endToken) {
-    listener?.endOptionalFormalParameters(count, beginToken, endToken);
-  }
-
-  @override
-  void endPart(Token partKeyword, Token semicolon) {
-    listener?.endPart(partKeyword, semicolon);
-  }
-
-  @override
-  void endPartOf(
-      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
-    listener?.endPartOf(partKeyword, ofKeyword, semicolon, hasName);
-  }
-
-  @override
-  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
-    listener?.endRedirectingFactoryBody(beginToken, endToken);
-  }
-
-  @override
-  void endRethrowStatement(Token rethrowToken, Token endToken) {
-    listener?.endRethrowStatement(rethrowToken, endToken);
-  }
-
-  @override
-  void endReturnStatement(
-      bool hasExpression, Token beginToken, Token endToken) {
-    listener?.endReturnStatement(hasExpression, beginToken, endToken);
-  }
-
-  @override
-  void endShow(Token showKeyword) {
-    listener?.endShow(showKeyword);
-  }
-
-  @override
-  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
-    listener?.endSwitchBlock(caseCount, beginToken, endToken);
-  }
-
-  @override
-  void endSwitchCase(
-      int labelCount,
-      int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
-      int statementCount,
-      Token firstToken,
-      Token endToken) {
-    listener?.endSwitchCase(labelCount, expressionCount, defaultKeyword,
-        colonAfterDefault, statementCount, firstToken, endToken);
-  }
-
-  @override
-  void endSwitchStatement(Token switchKeyword, Token endToken) {
-    listener?.endSwitchStatement(switchKeyword, endToken);
-  }
-
-  @override
-  void endThenStatement(Token token) {
-    listener?.endThenStatement(token);
-  }
-
-  @override
-  void endTopLevelDeclaration(Token token) {
-    listener?.endTopLevelDeclaration(token);
-  }
-
-  @override
-  void endTopLevelFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    listener?.endTopLevelFields(staticToken, covariantToken, lateToken,
-        varFinalOrConst, count, beginToken, endToken);
-  }
-
-  @override
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
-    listener?.endTopLevelMethod(beginToken, getOrSet, endToken);
-  }
-
-  @override
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
-    listener?.endTryStatement(catchCount, tryKeyword, finallyKeyword);
-  }
-
-  @override
-  void endTypeArguments(int count, Token beginToken, Token endToken) {
-    listener?.endTypeArguments(count, beginToken, endToken);
-  }
-
-  @override
-  void endTypeList(int count) {
-    listener?.endTypeList(count);
-  }
-
-  @override
-  void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
-    listener?.endTypeVariable(token, index, extendsOrSuper, variance);
-  }
-
-  @override
-  void endTypeVariables(Token beginToken, Token endToken) {
-    listener?.endTypeVariables(beginToken, endToken);
-  }
-
-  @override
-  void endVariableInitializer(Token assignmentOperator) {
-    listener?.endVariableInitializer(assignmentOperator);
-  }
-
-  @override
-  void endVariablesDeclaration(int count, Token endToken) {
-    listener?.endVariablesDeclaration(count, endToken);
-  }
-
-  @override
-  void endWhileStatement(Token whileKeyword, Token endToken) {
-    listener?.endWhileStatement(whileKeyword, endToken);
-  }
-
-  @override
-  void endWhileStatementBody(Token token) {
-    listener?.endWhileStatementBody(token);
-  }
-
-  @override
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
-    listener?.endYieldStatement(yieldToken, starToken, endToken);
-  }
-
-  @override
-  void handleAsOperator(Token operator) {
-    listener?.handleAsOperator(operator);
-  }
-
-  @override
-  void handleAssignmentExpression(Token token) {
-    listener?.handleAssignmentExpression(token);
-  }
-
-  @override
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
-    listener?.handleAsyncModifier(asyncToken, starToken);
-  }
-
-  @override
-  void handleBreakStatement(
-      bool hasTarget, Token breakKeyword, Token endToken) {
-    listener?.handleBreakStatement(hasTarget, breakKeyword, endToken);
-  }
-
-  @override
-  void handleCaseMatch(Token caseKeyword, Token colon) {
-    listener?.handleCaseMatch(caseKeyword, colon);
-  }
-
-  @override
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
-    listener?.handleCatchBlock(onKeyword, catchKeyword, comma);
-  }
-
-  @override
-  void handleClassExtends(Token extendsKeyword) {
-    listener?.handleClassExtends(extendsKeyword);
-  }
-
-  @override
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
-    listener?.handleClassHeader(begin, classKeyword, nativeToken);
-  }
-
-  @override
-  void handleClassNoWithClause() {
-    listener?.handleClassNoWithClause();
-  }
-
-  @override
-  void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
-    listener?.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
-  }
-
-  @override
-  void handleClassWithClause(Token withKeyword) {
-    listener?.handleClassWithClause(withKeyword);
-  }
-
-  @override
-  void handleCommentReference(
-      Token newKeyword, Token prefix, Token period, Token token) {
-    listener?.handleCommentReference(newKeyword, prefix, period, token);
-  }
-
-  @override
-  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
-    listener?.handleCommentReferenceText(referenceSource, referenceOffset);
-  }
-
-  @override
-  void handleConditionalExpressionColon() {
-    listener?.handleConditionalExpressionColon();
-  }
-
-  @override
-  void handleContinueStatement(
-      bool hasTarget, Token continueKeyword, Token endToken) {
-    listener?.handleContinueStatement(hasTarget, continueKeyword, endToken);
-  }
-
-  @override
-  void handleDirectivesOnly() {
-    listener?.handleDirectivesOnly();
-  }
-
-  @override
-  void handleDottedName(int count, Token firstIdentifier) {
-    listener?.handleDottedName(count, firstIdentifier);
-  }
-
-  @override
-  void handleElseControlFlow(Token elseToken) {
-    listener?.handleElseControlFlow(elseToken);
-  }
-
-  @override
-  void handleEmptyFunctionBody(Token semicolon) {
-    listener?.handleEmptyFunctionBody(semicolon);
-  }
-
-  @override
-  void handleEmptyStatement(Token token) {
-    listener?.handleEmptyStatement(token);
-  }
-
-  @override
-  void handleErrorToken(ErrorToken token) {
-    listener?.handleErrorToken(token);
-  }
-
-  @override
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
-    listener?.handleExpressionFunctionBody(arrowToken, endToken);
-  }
-
-  @override
-  void handleExpressionStatement(Token token) {
-    listener?.handleExpressionStatement(token);
-  }
-
-  @override
-  void handleExtraneousExpression(Token token, Message message) {
-    listener?.handleExtraneousExpression(token, message);
-  }
-
-  @override
-  void handleFinallyBlock(Token finallyKeyword) {
-    listener?.handleFinallyBlock(finallyKeyword);
-  }
-
-  @override
-  void handleForInitializerEmptyStatement(Token token) {
-    listener?.handleForInitializerEmptyStatement(token);
-  }
-
-  @override
-  void handleForInitializerExpressionStatement(Token token) {
-    listener?.handleForInitializerExpressionStatement(token);
-  }
-
-  @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
-    listener?.handleForInitializerLocalVariableDeclaration(token);
-  }
-
-  @override
-  void handleForInLoopParts(Token awaitToken, Token forToken,
-      Token leftParenthesis, Token inKeyword) {
-    listener?.handleForInLoopParts(
-        awaitToken, forToken, leftParenthesis, inKeyword);
-  }
-
-  @override
-  void handleForLoopParts(Token forKeyword, Token leftParen,
-      Token leftSeparator, int updateExpressionCount) {
-    listener?.handleForLoopParts(
-        forKeyword, leftParen, leftSeparator, updateExpressionCount);
-  }
-
-  @override
-  void handleFormalParameterWithoutValue(Token token) {
-    listener?.handleFormalParameterWithoutValue(token);
-  }
-
-  @override
-  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {
-    listener?.handleFunctionBodySkipped(token, isExpressionBody);
-  }
-
-  @override
-  void handleIdentifier(Token token, IdentifierContext context) {
-    listener?.handleIdentifier(token, context);
-  }
-
-  @override
-  void handleIdentifierList(int count) {
-    listener?.handleIdentifierList(count);
-  }
-
-  @override
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    listener?.handleImportPrefix(deferredKeyword, asKeyword);
-  }
-
-  @override
-  void handleIndexedExpression(
-      Token openSquareBracket, Token closeSquareBracket) {
-    listener?.handleIndexedExpression(openSquareBracket, closeSquareBracket);
-  }
-
-  @override
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {
-    listener?.handleInterpolationExpression(leftBracket, rightBracket);
-  }
-
-  @override
-  void handleInvalidExpression(Token token) {
-    listener?.handleInvalidExpression(token);
-  }
-
-  @override
-  void handleInvalidFunctionBody(Token token) {
-    listener?.handleInvalidFunctionBody(token);
-  }
-
-  @override
-  void handleInvalidMember(Token endToken) {
-    listener?.handleInvalidMember(endToken);
-  }
-
-  @override
-  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
-    listener?.handleInvalidOperatorName(operatorKeyword, token);
-  }
-
-  @override
-  void handleInvalidStatement(Token token, Message message) {
-    listener?.handleInvalidStatement(token, message);
-  }
-
-  void handleInvalidTopLevelBlock(Token token) {
-    listener?.handleInvalidTopLevelBlock(token);
-  }
-
-  @override
-  void handleInvalidTopLevelDeclaration(Token endToken) {
-    listener?.handleInvalidTopLevelDeclaration(endToken);
-  }
-
-  @override
-  void handleInvalidTypeArguments(Token token) {
-    listener?.handleInvalidTypeArguments(token);
-  }
-
-  @override
-  void handleInvalidTypeReference(Token token) {
-    listener?.handleInvalidTypeReference(token);
-  }
-
-  @override
-  void handleIsOperator(Token isOperator, Token not) {
-    listener?.handleIsOperator(isOperator, not);
-  }
-
-  @override
-  void handleLabel(Token token) {
-    listener?.handleLabel(token);
-  }
-
-  @override
-  void handleLiteralBool(Token token) {
-    listener?.handleLiteralBool(token);
-  }
-
-  @override
-  void handleLiteralDouble(Token token) {
-    listener?.handleLiteralDouble(token);
-  }
-
-  @override
-  void handleLiteralInt(Token token) {
-    listener?.handleLiteralInt(token);
-  }
-
-  @override
-  void handleLiteralList(
-      int count, Token beginToken, Token constKeyword, Token endToken) {
-    listener?.handleLiteralList(count, beginToken, constKeyword, endToken);
-  }
-
-  @override
-  void handleLiteralMapEntry(Token colon, Token endToken) {
-    listener?.handleLiteralMapEntry(colon, endToken);
-  }
-
-  @override
-  void handleLiteralNull(Token token) {
-    listener?.handleLiteralNull(token);
-  }
-
-  @override
-  void handleLiteralSetOrMap(
-    int count,
-    Token leftBrace,
-    Token constKeyword,
-    Token rightBrace,
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry,
-  ) {
-    listener?.handleLiteralSetOrMap(
-        count, leftBrace, constKeyword, rightBrace, hasSetEntry);
-  }
-
-  @override
-  void handleMixinHeader(Token mixinKeyword) {
-    listener?.handleMixinHeader(mixinKeyword);
-  }
-
-  @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
-    listener?.handleMixinOn(onKeyword, typeCount);
-  }
-
-  @override
-  void handleNamedArgument(Token colon) {
-    listener?.handleNamedArgument(colon);
-  }
-
-  @override
-  void handleNamedMixinApplicationWithClause(Token withKeyword) {
-    listener?.handleNamedMixinApplicationWithClause(withKeyword);
-  }
-
-  @override
-  void handleNativeClause(Token nativeToken, bool hasName) {
-    listener?.handleNativeClause(nativeToken, hasName);
-  }
-
-  @override
-  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
-    listener?.handleNativeFunctionBody(nativeToken, semicolon);
-  }
-
-  @override
-  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
-    listener?.handleNativeFunctionBodyIgnored(nativeToken, semicolon);
-  }
-
-  @override
-  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
-    listener?.handleNativeFunctionBodySkipped(nativeToken, semicolon);
-  }
-
-  @override
-  void handleNoArguments(Token token) {
-    listener?.handleNoArguments(token);
-  }
-
-  @override
-  void handleNoCommentReference() {
-    listener?.handleNoCommentReference();
-  }
-
-  @override
-  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
-    listener?.handleNoConstructorReferenceContinuationAfterTypeArguments(token);
-  }
-
-  @override
-  void handleNoFieldInitializer(Token token) {
-    listener?.handleNoFieldInitializer(token);
-  }
-
-  @override
-  void handleNoFormalParameters(Token token, MemberKind kind) {
-    listener?.handleNoFormalParameters(token, kind);
-  }
-
-  @override
-  void handleNoFunctionBody(Token token) {
-    listener?.handleNoFunctionBody(token);
-  }
-
-  @override
-  void handleNoInitializers() {
-    listener?.handleNoInitializers();
-  }
-
-  @override
-  void handleNoName(Token token) {
-    listener?.handleNoName(token);
-  }
-
-  @override
-  void handleNonNullAssertExpression(Token bang) {
-    listener?.handleNonNullAssertExpression(bang);
-  }
-
-  @override
-  void handleNoType(Token lastConsumed) {
-    listener?.handleNoType(lastConsumed);
-  }
-
-  @override
-  void handleNoTypeArguments(Token token) {
-    listener?.handleNoTypeArguments(token);
-  }
-
-  @override
-  void handleNoTypeVariables(Token token) {
-    listener?.handleNoTypeVariables(token);
-  }
-
-  @override
-  void handleNoVariableInitializer(Token token) {
-    listener?.handleNoVariableInitializer(token);
-  }
-
-  @override
-  void handleOperator(Token token) {
-    listener?.handleOperator(token);
-  }
-
-  @override
-  void handleOperatorName(Token operatorKeyword, Token token) {
-    listener?.handleOperatorName(operatorKeyword, token);
-  }
-
-  @override
-  void handleParenthesizedCondition(Token token) {
-    listener?.handleParenthesizedCondition(token);
-  }
-
-  @override
-  void handleParenthesizedExpression(Token token) {
-    listener?.handleParenthesizedExpression(token);
-  }
-
-  @override
-  void handleQualified(Token period) {
-    listener?.handleQualified(period);
-  }
-
-  @override
-  void handleRecoverableError(
-      Message message, Token startToken, Token endToken) {
-    if (forwardErrors) {
-      listener?.handleRecoverableError(message, startToken, endToken);
-    }
-  }
-
-  @override
-  void handleRecoverClassHeader() {
-    listener?.handleRecoverClassHeader();
-  }
-
-  @override
-  void handleRecoverImport(Token semicolon) {
-    listener?.handleRecoverImport(semicolon);
-  }
-
-  @override
-  void handleRecoverMixinHeader() {
-    listener?.handleRecoverMixinHeader();
-  }
-
-  @override
-  void handleScript(Token token) {
-    listener?.handleScript(token);
-  }
-
-  @override
-  void handleSend(Token beginToken, Token endToken) {
-    listener?.handleSend(beginToken, endToken);
-  }
-
-  @override
-  void handleSpreadExpression(Token spreadToken) {
-    listener?.handleSpreadExpression(spreadToken);
-  }
-
-  @override
-  void handleStringJuxtaposition(int literalCount) {
-    listener?.handleStringJuxtaposition(literalCount);
-  }
-
-  @override
-  void handleStringPart(Token token) {
-    listener?.handleStringPart(token);
-  }
-
-  @override
-  void handleSuperExpression(Token token, IdentifierContext context) {
-    listener?.handleSuperExpression(token, context);
-  }
-
-  @override
-  void handleSymbolVoid(Token token) {
-    listener?.handleSymbolVoid(token);
-  }
-
-  @override
-  void handleThisExpression(Token token, IdentifierContext context) {
-    listener?.handleThisExpression(token, context);
-  }
-
-  @override
-  void handleThrowExpression(Token throwToken, Token endToken) {
-    listener?.handleThrowExpression(throwToken, endToken);
-  }
-
-  @override
-  void handleType(Token beginToken, Token questionMark) {
-    listener?.handleType(beginToken, questionMark);
-  }
-
-  @override
-  void handleTypeVariablesDefined(Token token, int count) {
-    listener?.handleTypeVariablesDefined(token, count);
-  }
-
-  @override
-  void handleUnaryPostfixAssignmentExpression(Token token) {
-    listener?.handleUnaryPostfixAssignmentExpression(token);
-  }
-
-  @override
-  void handleUnaryPrefixAssignmentExpression(Token token) {
-    listener?.handleUnaryPrefixAssignmentExpression(token);
-  }
-
-  @override
-  void handleUnaryPrefixExpression(Token token) {
-    listener?.handleUnaryPrefixExpression(token);
-  }
-
-  @override
-  void handleUnescapeError(
-      Message message, Token location, int offset, int length) {
-    listener?.handleUnescapeError(message, location, offset, length);
-  }
-
-  @override
-  void handleValuedFormalParameter(Token equals, Token token) {
-    listener?.handleValuedFormalParameter(equals, token);
-  }
-
-  @override
-  void handleVoidKeyword(Token token) {
-    listener?.handleVoidKeyword(token);
-  }
-
-  @override
-  void logEvent(String name) {
-    listener?.logEvent(name);
-  }
-
-  @override
-  void reportErrorIfNullableType(Token questionMark) {
-    listener?.reportErrorIfNullableType(questionMark);
-  }
-
-  @override
-  void reportNonNullableModifierError(Token modifierToken) {
-    listener?.reportNonNullableModifierError(modifierToken);
-  }
-
-  @override
-  void reportNonNullAssertExpressionNotEnabled(Token bang) {
-    listener?.reportNonNullAssertExpressionNotEnabled(bang);
-  }
-
-  @override
-  void reportVarianceModifierNotEnabled(Token variance) {
-    listener?.reportVarianceModifierNotEnabled(variance);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
deleted file mode 100644
index bfeab30..0000000
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ /dev/null
@@ -1,333 +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 '../../scanner/token.dart' show Token, TokenType;
-
-import '../fasta_codes.dart' show Message, Template, templateExpectedIdentifier;
-
-import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
-
-import 'identifier_context_impl.dart';
-
-import 'parser.dart' show Parser;
-
-import 'util.dart' show isOneOfOrEof, optional;
-
-/// Information about the parser state that is passed to the listener at the
-/// time an identifier is encountered. It is also used by the parser for error
-/// recovery when a recovery template is defined.
-///
-/// This can be used by the listener to determine the context in which the
-/// identifier appears; that in turn can help the listener decide how to resolve
-/// the identifier (if the listener is doing resolution).
-class IdentifierContext {
-  /// Identifier is being declared as the name of an import prefix (i.e. `Foo`
-  /// in `import "..." as Foo;`)
-  static const ImportPrefixIdentifierContext importPrefixDeclaration =
-      const ImportPrefixIdentifierContext();
-
-  /// Identifier is the start of a dotted name in a conditional import or
-  /// export.
-  static const DottedNameIdentifierContext dottedName =
-      const DottedNameIdentifierContext();
-
-  /// Identifier is part of a dotted name in a conditional import or export, but
-  /// it's not the first identifier of the dotted name.
-  static const DottedNameIdentifierContext dottedNameContinuation =
-      const DottedNameIdentifierContext.continuation();
-
-  /// Identifier is one of the shown/hidden names in an import/export
-  /// combinator.
-  static const CombinatorIdentifierContext combinator =
-      const CombinatorIdentifierContext();
-
-  /// Identifier is the start of a name in an annotation that precedes a
-  /// declaration (i.e. it appears directly after an `@`).
-  static const MetadataReferenceIdentifierContext metadataReference =
-      const MetadataReferenceIdentifierContext();
-
-  /// Identifier is part of a name in an annotation that precedes a declaration,
-  /// but it's not the first identifier in the name.
-  static const MetadataReferenceIdentifierContext metadataContinuation =
-      const MetadataReferenceIdentifierContext.continuation();
-
-  /// Identifier is part of a name in an annotation that precedes a declaration,
-  /// but it appears after type parameters (e.g. `foo` in `@X<Y>.foo()`).
-  static const MetadataReferenceIdentifierContext
-      metadataContinuationAfterTypeArguments =
-      const MetadataReferenceIdentifierContext.continuationAfterTypeArguments();
-
-  /// Identifier is the name being declared by a typedef declaration.
-  static const TypedefDeclarationIdentifierContext typedefDeclaration =
-      const TypedefDeclarationIdentifierContext();
-
-  /// Identifier is a field initializer in a formal parameter list (i.e. it
-  /// appears directly after `this.`).
-  static const FieldInitializerIdentifierContext fieldInitializer =
-      const FieldInitializerIdentifierContext();
-
-  /// Identifier is a formal parameter being declared as part of a function,
-  /// method, or typedef declaration.
-  static const FormalParameterDeclarationIdentifierContext
-      formalParameterDeclaration =
-      const FormalParameterDeclarationIdentifierContext();
-
-  /// Identifier is a formal parameter being declared as part of a catch block
-  /// in a try/catch/finally statement.
-  static const CatchParameterIdentifierContext catchParameter =
-      const CatchParameterIdentifierContext();
-
-  /// Identifier is the start of a library name (e.g. `foo` in the directive
-  /// 'library foo;`).
-  static const LibraryIdentifierContext libraryName =
-      const LibraryIdentifierContext();
-
-  /// Identifier is part of a library name, but it's not the first identifier in
-  /// the name.
-  static const LibraryIdentifierContext libraryNameContinuation =
-      const LibraryIdentifierContext.continuation();
-
-  /// Identifier is the start of a library name referenced by a `part of`
-  /// directive (e.g. `foo` in the directive `part of foo;`).
-  static const LibraryIdentifierContext partName =
-      const LibraryIdentifierContext.partName();
-
-  /// Identifier is part of a library name referenced by a `part of` directive,
-  /// but it's not the first identifier in the name.
-  static const LibraryIdentifierContext partNameContinuation =
-      const LibraryIdentifierContext.partNameContinuation();
-
-  /// Identifier is the type name being declared by an enum declaration.
-  static const EnumDeclarationIdentifierContext enumDeclaration =
-      const EnumDeclarationIdentifierContext();
-
-  /// Identifier is an enumerated value name being declared by an enum
-  /// declaration.
-  static const EnumValueDeclarationIdentifierContext enumValueDeclaration =
-      const EnumValueDeclarationIdentifierContext();
-
-  /// Identifier is the name being declared by a class declaration, a mixin
-  /// declaration, or a named mixin application, for example,
-  /// `Foo` in `class Foo = X with Y;`.
-  static const ClassOrMixinOrExtensionIdentifierContext
-      classOrMixinOrExtensionDeclaration =
-      const ClassOrMixinOrExtensionIdentifierContext();
-
-  /// Identifier is the name of a type variable being declared (e.g. `Foo` in
-  /// `class C<Foo extends num> {}`).
-  static const TypeVariableDeclarationIdentifierContext
-      typeVariableDeclaration =
-      const TypeVariableDeclarationIdentifierContext();
-
-  /// Identifier is the start of a reference to a type that starts with prefix.
-  static const TypeReferenceIdentifierContext prefixedTypeReference =
-      const TypeReferenceIdentifierContext.prefixed();
-
-  /// Identifier is the start of a reference to a type declared elsewhere.
-  static const TypeReferenceIdentifierContext typeReference =
-      const TypeReferenceIdentifierContext();
-
-  /// Identifier is part of a reference to a type declared elsewhere, but it's
-  /// not the first identifier of the reference.
-  static const TypeReferenceIdentifierContext typeReferenceContinuation =
-      const TypeReferenceIdentifierContext.continuation();
-
-  /// Identifier is a name being declared by a top level variable declaration.
-  static const TopLevelDeclarationIdentifierContext
-      topLevelVariableDeclaration = const TopLevelDeclarationIdentifierContext(
-          'topLevelVariableDeclaration', const [';', '=', ',']);
-
-  /// Identifier is a name being declared by a field declaration.
-  static const FieldDeclarationIdentifierContext fieldDeclaration =
-      const FieldDeclarationIdentifierContext();
-
-  /// Identifier is the name being declared by a top level function declaration.
-  static const TopLevelDeclarationIdentifierContext
-      topLevelFunctionDeclaration = const TopLevelDeclarationIdentifierContext(
-          'topLevelFunctionDeclaration', const ['<', '(', '{', '=>']);
-
-  /// Identifier is the start of the name being declared by a method
-  /// declaration.
-  static const MethodDeclarationIdentifierContext methodDeclaration =
-      const MethodDeclarationIdentifierContext();
-
-  /// Identifier is part of the name being declared by a method declaration,
-  /// but it's not the first identifier of the name.
-  ///
-  /// In valid Dart, this can only happen if the identifier is the name of a
-  /// named constructor which is being declared, e.g. `foo` in
-  /// `class C { C.foo(); }`.
-  static const MethodDeclarationIdentifierContext
-      methodDeclarationContinuation =
-      const MethodDeclarationIdentifierContext.continuation();
-
-  /// Identifier appears after the word `operator` in a method declaration.
-  ///
-  /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
-  /// occur as part of error recovery?  If it's only as part of error recovery,
-  /// perhaps we should just re-use methodDeclaration.
-  static const MethodDeclarationIdentifierContext operatorName =
-      const MethodDeclarationIdentifierContext.continuation();
-
-  /// Identifier is the start of the name being declared by a local function
-  /// declaration.
-  static const LocalFunctionDeclarationIdentifierContext
-      localFunctionDeclaration =
-      const LocalFunctionDeclarationIdentifierContext();
-
-  /// Identifier is part of the name being declared by a local function
-  /// declaration, but it's not the first identifier of the name.
-  ///
-  /// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
-  /// occur as part of error recovery?
-  static const LocalFunctionDeclarationIdentifierContext
-      localFunctionDeclarationContinuation =
-      const LocalFunctionDeclarationIdentifierContext.continuation();
-
-  /// Identifier is the start of a reference to a constructor declared
-  /// elsewhere.
-  static const ConstructorReferenceIdentifierContext constructorReference =
-      const ConstructorReferenceIdentifierContext();
-
-  /// Identifier is part of a reference to a constructor declared elsewhere, but
-  /// it's not the first identifier of the reference.
-  static const ConstructorReferenceIdentifierContext
-      constructorReferenceContinuation =
-      const ConstructorReferenceIdentifierContext.continuation();
-
-  /// Identifier is part of a reference to a constructor declared elsewhere, but
-  /// it appears after type parameters (e.g. `foo` in `X<Y>.foo`).
-  static const ConstructorReferenceIdentifierContext
-      constructorReferenceContinuationAfterTypeArguments =
-      const ConstructorReferenceIdentifierContext
-          .continuationAfterTypeArguments();
-
-  /// Identifier is the declaration of a label (i.e. it is followed by `:` and
-  /// then a statement).
-  static const LabelDeclarationIdentifierContext labelDeclaration =
-      const LabelDeclarationIdentifierContext();
-
-  /// Identifier is the start of a reference occurring in a literal symbol (e.g.
-  /// `foo` in `#foo`).
-  static const LiteralSymbolIdentifierContext literalSymbol =
-      const LiteralSymbolIdentifierContext();
-
-  /// Identifier is part of a reference occurring in a literal symbol, but it's
-  /// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
-  static const LiteralSymbolIdentifierContext literalSymbolContinuation =
-      const LiteralSymbolIdentifierContext.continuation();
-
-  /// Identifier appears in an expression, and it does not immediately follow a
-  /// `.`.
-  static const ExpressionIdentifierContext expression =
-      const ExpressionIdentifierContext();
-
-  /// Identifier appears in an expression, and it immediately follows a `.`.
-  static const ExpressionIdentifierContext expressionContinuation =
-      const ExpressionIdentifierContext.continuation();
-
-  /// Identifier is a reference to a named argument of a function or method
-  /// invocation (e.g. `foo` in `f(foo: 0);`.
-  static const NamedArgumentReferenceIdentifierContext namedArgumentReference =
-      const NamedArgumentReferenceIdentifierContext();
-
-  /// Identifier is a name being declared by a local variable declaration.
-  static const LocalVariableDeclarationIdentifierContext
-      localVariableDeclaration =
-      const LocalVariableDeclarationIdentifierContext();
-
-  /// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
-  /// Labels have their own scope.
-  static const LabelReferenceIdentifierContext labelReference =
-      const LabelReferenceIdentifierContext();
-
-  final String _name;
-
-  /// Indicates whether the identifier represents a name which is being
-  /// declared.
-  final bool inDeclaration;
-
-  /// Indicates whether the identifier is within a `library` or `part of`
-  /// declaration.
-  final bool inLibraryOrPartOfDeclaration;
-
-  /// Indicates whether the identifier is within a symbol literal.
-  final bool inSymbol;
-
-  /// Indicates whether the identifier follows a `.`.
-  final bool isContinuation;
-
-  /// Indicates whether the identifier should be looked up in the current scope.
-  final bool isScopeReference;
-
-  /// Indicates whether built-in identifiers are allowed in this context.
-  final bool isBuiltInIdentifierAllowed;
-
-  /// Indicated whether the identifier is allowed in a context where constant
-  /// expressions are required.
-  final bool allowedInConstantExpression;
-
-  final Template<_MessageWithArgument<Token>> recoveryTemplate;
-
-  const IdentifierContext(this._name,
-      {this.inDeclaration: false,
-      this.inLibraryOrPartOfDeclaration: false,
-      this.inSymbol: false,
-      this.isContinuation: false,
-      this.isScopeReference: false,
-      this.isBuiltInIdentifierAllowed: true,
-      bool allowedInConstantExpression,
-      this.recoveryTemplate: templateExpectedIdentifier})
-      : this.allowedInConstantExpression =
-            // Generally, declarations are legal in constant expressions.  A
-            // continuation doesn't affect constant expressions: if what it's
-            // continuing is a problem, it has already been reported.
-            allowedInConstantExpression ??
-                (inDeclaration || isContinuation || inSymbol);
-
-  String toString() => _name;
-
-  /// Ensure that the next token is an identifier (or keyword which should be
-  /// treated as an identifier) and return that identifier.
-  /// Report errors as necessary via [parser].
-  Token ensureIdentifier(Token token, Parser parser) {
-    assert(token.next.kind != IDENTIFIER_TOKEN);
-    // TODO(danrubel): Implement this method for each identifier context
-    // such that they return a non-null value.
-    return null;
-  }
-}
-
-/// Return `true` if the given [token] should be treated like the start of
-/// an expression for the purposes of recovery.
-bool looksLikeExpressionStart(Token next) =>
-    next.isIdentifier ||
-    next.isKeyword && !looksLikeStatementStart(next) ||
-    next.type == TokenType.DOUBLE ||
-    next.type == TokenType.HASH ||
-    next.type == TokenType.HEXADECIMAL ||
-    next.type == TokenType.IDENTIFIER ||
-    next.type == TokenType.INT ||
-    next.type == TokenType.STRING ||
-    optional('{', next) ||
-    optional('(', next) ||
-    optional('[', next) ||
-    optional('[]', next) ||
-    optional('<', next) ||
-    optional('!', next) ||
-    optional('-', next) ||
-    optional('~', next) ||
-    optional('++', next) ||
-    optional('--', next);
-
-/// Return `true` if the given [token] should be treated like the start of
-/// a new statement for the purposes of recovery.
-bool looksLikeStatementStart(Token token) => isOneOfOrEof(token, const [
-      '@',
-      'assert', 'break', 'continue', 'do', 'else', 'final', 'for', //
-      'if', 'return', 'switch', 'try', 'var', 'void', 'while', //
-    ]);
-
-// TODO(ahe): Remove when analyzer supports generalized function syntax.
-typedef _MessageWithArgument<T> = Message Function(T);
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
deleted file mode 100644
index c7899be..0000000
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ /dev/null
@@ -1,989 +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 '../../scanner/token.dart' show Token;
-
-import '../fasta_codes.dart' as fasta;
-
-import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN, STRING_TOKEN;
-
-import 'identifier_context.dart';
-
-import 'parser.dart' show Parser;
-
-import 'type_info.dart' show isValidTypeReference;
-
-import 'util.dart' show isOneOfOrEof, optional;
-
-/// See [IdentifierContext.catchParameter].
-class CatchParameterIdentifierContext extends IdentifierContext {
-  const CatchParameterIdentifierContext() : super('catchParameter');
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    parser.reportRecoverableError(identifier, fasta.messageCatchSyntax);
-    if (looksLikeStatementStart(identifier) ||
-        isOneOfOrEof(identifier, const [',', ')'])) {
-      return parser.rewriter.insertSyntheticIdentifier(token);
-    } else if (!identifier.isKeywordOrIdentifier) {
-      // When in doubt, consume the token to ensure we make progress
-      // but insert a synthetic identifier to satisfy listeners.
-      return parser.rewriter.insertSyntheticIdentifier(identifier);
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.classOrMixinOrExtensionDeclaration].
-class ClassOrMixinOrExtensionIdentifierContext extends IdentifierContext {
-  const ClassOrMixinOrExtensionIdentifierContext()
-      : super('classOrMixinDeclaration',
-            inDeclaration: true, isBuiltInIdentifierAllowed: false);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.type.isPseudo) {
-      return identifier;
-    }
-
-    // Recovery
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier,
-            const ['<', '{', 'extends', 'with', 'implements', 'on'])) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else if (identifier.type.isBuiltIn) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.combinator].
-class CombinatorIdentifierContext extends IdentifierContext {
-  const CombinatorIdentifierContext() : super('combinator');
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    const List<String> followingValues = const [
-      ';',
-      ',',
-      'if',
-      'as',
-      'show',
-      'hide'
-    ];
-
-    if (identifier.isIdentifier) {
-      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-          isOneOfOrEof(identifier.next, followingValues)) {
-        return identifier;
-      }
-      // Although this is a valid identifier name, the import declaration
-      // is invalid and this looks like the start of the next declaration.
-      // In this situation, fall through to insert a synthetic identifier.
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, followingValues) ||
-        looksLikeStartOfNextTopLevelDeclaration(identifier)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.constructorReference]
-/// and [IdentifierContext.constructorReferenceContinuation]
-/// and [IdentifierContext.constructorReferenceContinuationAfterTypeArguments].
-class ConstructorReferenceIdentifierContext extends IdentifierContext {
-  const ConstructorReferenceIdentifierContext()
-      : super('constructorReference', isScopeReference: true);
-
-  const ConstructorReferenceIdentifierContext.continuation()
-      : super('constructorReferenceContinuation', isContinuation: true);
-
-  const ConstructorReferenceIdentifierContext.continuationAfterTypeArguments()
-      : super('constructorReferenceContinuationAfterTypeArguments',
-            isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (!identifier.isKeywordOrIdentifier) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.dottedName].
-class DottedNameIdentifierContext extends IdentifierContext {
-  const DottedNameIdentifierContext() : super('dottedName');
-
-  const DottedNameIdentifierContext.continuation()
-      : super('dottedNameContinuation', isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    const List<String> followingValues = const ['.', '==', ')'];
-
-    if (identifier.isIdentifier) {
-      // DottedNameIdentifierContext are only used in conditional import
-      // expressions. Although some top level keywords such as `import` can be
-      // used as identifiers, they are more likely the start of the next
-      // directive or declaration.
-      if (!identifier.isTopLevelKeyword ||
-          isOneOfOrEof(identifier.next, followingValues)) {
-        return identifier;
-      }
-    }
-
-    // Recovery
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.enumDeclaration].
-class EnumDeclarationIdentifierContext extends IdentifierContext {
-  const EnumDeclarationIdentifierContext()
-      : super('enumDeclaration',
-            inDeclaration: true, isBuiltInIdentifierAllowed: false);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.type.isPseudo) {
-      return identifier;
-    }
-
-    // Recovery
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, const ['{'])) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else if (identifier.type.isBuiltIn) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.enumValueDeclaration].
-class EnumValueDeclarationIdentifierContext extends IdentifierContext {
-  const EnumValueDeclarationIdentifierContext()
-      : super('enumValueDeclaration', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      return identifier;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, fasta.templateExpectedIdentifier);
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, const [',', '}'])) {
-      return parser.rewriter.insertSyntheticIdentifier(token);
-    } else if (!identifier.isKeywordOrIdentifier) {
-      // When in doubt, consume the token to ensure we make progress
-      // but insert a synthetic identifier to satisfy listeners.
-      return parser.rewriter.insertSyntheticIdentifier(identifier);
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.expression].
-class ExpressionIdentifierContext extends IdentifierContext {
-  const ExpressionIdentifierContext()
-      : super('expression', isScopeReference: true);
-
-  const ExpressionIdentifierContext.continuation()
-      : super('expressionContinuation', isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.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
-        // rather than the token following it.
-        parser.reportRecoverableErrorWithToken(
-            identifier, fasta.templateUnexpectedToken);
-
-        // 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;
-      } else {
-        checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      }
-      return identifier;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, fasta.templateExpectedIdentifier);
-    if (optional(r'$', token) &&
-        identifier.isKeyword &&
-        identifier.next.kind == STRING_TOKEN) {
-      // Keyword used as identifier in string interpolation
-      return identifier;
-    } else if (!looksLikeStatementStart(identifier)) {
-      if (identifier.isKeywordOrIdentifier) {
-        if (isContinuation || !isOneOfOrEof(identifier, const ['as', 'is'])) {
-          return identifier;
-        }
-      } else if (!identifier.isOperator &&
-          !isOneOfOrEof(identifier,
-              const ['.', ',', '(', ')', '[', ']', '{', '}', '?', ':', ';'])) {
-        // When in doubt, consume the token to ensure we make progress
-        token = identifier;
-        identifier = token.next;
-      }
-    }
-    // Insert a synthetic identifier to satisfy listeners.
-    return parser.rewriter.insertSyntheticIdentifier(token);
-  }
-}
-
-/// See [IdentifierContext.fieldDeclaration].
-class FieldDeclarationIdentifierContext extends IdentifierContext {
-  const FieldDeclarationIdentifierContext()
-      : super('fieldDeclaration', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const [';', '=', ',', '}']) ||
-        looksLikeStartOfNextClassMember(identifier)) {
-      return parser.insertSyntheticIdentifier(token, this);
-    } else if (!identifier.isKeywordOrIdentifier) {
-      // When in doubt, consume the token to ensure we make progress
-      // but insert a synthetic identifier to satisfy listeners.
-      return parser.insertSyntheticIdentifier(identifier, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier),
-          messageOnToken: identifier);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      return identifier;
-    }
-  }
-}
-
-/// See [IdentifierContext.fieldInitializer].
-class FieldInitializerIdentifierContext extends IdentifierContext {
-  const FieldInitializerIdentifierContext()
-      : super('fieldInitializer', isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    assert(optional('.', token));
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      return identifier;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, fasta.templateExpectedIdentifier);
-    // Insert a synthetic identifier to satisfy listeners.
-    return parser.rewriter.insertSyntheticIdentifier(token);
-  }
-}
-
-/// See [IdentifierContext.formalParameterDeclaration].
-class FormalParameterDeclarationIdentifierContext extends IdentifierContext {
-  const FormalParameterDeclarationIdentifierContext()
-      : super('formalParameterDeclaration', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    const List<String> followingValues = const [
-      ':',
-      '=',
-      ',',
-      '(',
-      ')',
-      '[',
-      ']',
-      '{',
-      '}'
-    ];
-    if (looksLikeStartOfNextClassMember(identifier) ||
-        looksLikeStatementStart(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.importPrefixDeclaration].
-class ImportPrefixIdentifierContext extends IdentifierContext {
-  const ImportPrefixIdentifierContext()
-      : super('importPrefixDeclaration',
-            inDeclaration: true, isBuiltInIdentifierAllowed: false);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.type.isPseudo) {
-      return identifier;
-    }
-
-    // Recovery
-    const List<String> followingValues = const [
-      ';',
-      'if',
-      'show',
-      'hide',
-      'deferred',
-      'as'
-    ];
-    if (identifier.type.isBuiltIn &&
-        isOneOfOrEof(identifier.next, followingValues)) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-class LiteralSymbolIdentifierContext extends IdentifierContext {
-  const LiteralSymbolIdentifierContext()
-      : super('literalSymbol', inSymbol: true);
-
-  const LiteralSymbolIdentifierContext.continuation()
-      : super('literalSymbolContinuation',
-            inSymbol: true, isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      return identifier;
-    }
-
-    // Recovery
-    return parser.insertSyntheticIdentifier(token, this,
-        message: fasta.templateExpectedIdentifier.withArguments(identifier));
-  }
-}
-
-/// See [IdentifierContext.localFunctionDeclaration]
-/// and [IdentifierContext.localFunctionDeclarationContinuation].
-class LocalFunctionDeclarationIdentifierContext extends IdentifierContext {
-  const LocalFunctionDeclarationIdentifierContext()
-      : super('localFunctionDeclaration', inDeclaration: true);
-
-  const LocalFunctionDeclarationIdentifierContext.continuation()
-      : super('localFunctionDeclarationContinuation',
-            inDeclaration: true, isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const ['.', '(', '{', '=>']) ||
-        looksLikeStatementStart(identifier)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.labelDeclaration].
-class LabelDeclarationIdentifierContext extends IdentifierContext {
-  const LabelDeclarationIdentifierContext()
-      : super('labelDeclaration', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const [':']) ||
-        looksLikeStatementStart(identifier)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.labelReference].
-class LabelReferenceIdentifierContext extends IdentifierContext {
-  const LabelReferenceIdentifierContext() : super('labelReference');
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const [';'])) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.libraryName],
-/// and [IdentifierContext.libraryNameContinuation]
-/// and [IdentifierContext.partName],
-/// and [IdentifierContext.partNameContinuation].
-class LibraryIdentifierContext extends IdentifierContext {
-  const LibraryIdentifierContext()
-      : super('libraryName', inLibraryOrPartOfDeclaration: true);
-
-  const LibraryIdentifierContext.continuation()
-      : super('libraryNameContinuation',
-            inLibraryOrPartOfDeclaration: true, isContinuation: true);
-
-  const LibraryIdentifierContext.partName()
-      : super('partName', inLibraryOrPartOfDeclaration: true);
-
-  const LibraryIdentifierContext.partNameContinuation()
-      : super('partNameContinuation',
-            inLibraryOrPartOfDeclaration: true, isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    const List<String> followingValues = const ['.', ';'];
-
-    if (identifier.isIdentifier) {
-      Token next = identifier.next;
-      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-          isOneOfOrEof(next, followingValues)) {
-        return identifier;
-      }
-      // Although this is a valid library name, the library declaration
-      // is invalid and this looks like the start of the next declaration.
-      // In this situation, fall through to insert a synthetic library name.
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, followingValues) ||
-        looksLikeStartOfNextTopLevelDeclaration(identifier)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.localVariableDeclaration].
-class LocalVariableDeclarationIdentifierContext extends IdentifierContext {
-  const LocalVariableDeclarationIdentifierContext()
-      : super('localVariableDeclaration', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const [';', '=', ',', '{', '}']) ||
-        looksLikeStatementStart(identifier) ||
-        identifier.kind == STRING_TOKEN) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.metadataReference]
-/// and [IdentifierContext.metadataContinuation]
-/// and [IdentifierContext.metadataContinuationAfterTypeArguments].
-class MetadataReferenceIdentifierContext extends IdentifierContext {
-  const MetadataReferenceIdentifierContext()
-      : super('metadataReference', isScopeReference: true);
-
-  const MetadataReferenceIdentifierContext.continuation()
-      : super('metadataContinuation', isContinuation: true);
-
-  const MetadataReferenceIdentifierContext.continuationAfterTypeArguments()
-      : super('metadataContinuationAfterTypeArguments', isContinuation: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const ['{', '}', '(', ')', ']']) ||
-        looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        looksLikeStartOfNextClassMember(identifier) ||
-        looksLikeStatementStart(identifier)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.methodDeclaration],
-/// and [IdentifierContext.methodDeclarationContinuation],
-/// and [IdentifierContext.operatorName].
-class MethodDeclarationIdentifierContext extends IdentifierContext {
-  const MethodDeclarationIdentifierContext()
-      : super('methodDeclaration', inDeclaration: true);
-
-  const MethodDeclarationIdentifierContext.continuation()
-      : super('methodDeclarationContinuation',
-            inDeclaration: true, isContinuation: true);
-
-  const MethodDeclarationIdentifierContext.operatorName()
-      : super('operatorName', inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      return identifier;
-    }
-
-    // Recovery
-    if (identifier.isUserDefinableOperator && !isContinuation) {
-      return parser.insertSyntheticIdentifier(identifier, this,
-          message: fasta.messageMissingOperatorKeyword,
-          messageOnToken: identifier);
-    } else if (isOneOfOrEof(identifier, const ['.', '(', '{', '=>', '}']) ||
-        looksLikeStartOfNextClassMember(identifier)) {
-      return parser.insertSyntheticIdentifier(token, this);
-    } else if (!identifier.isKeywordOrIdentifier) {
-      // When in doubt, consume the token to ensure we make progress
-      // but insert a synthetic identifier to satisfy listeners.
-      return parser.insertSyntheticIdentifier(identifier, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier),
-          messageOnToken: identifier);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      return identifier;
-    }
-  }
-}
-
-/// See [IdentifierContext.namedArgumentReference].
-class NamedArgumentReferenceIdentifierContext extends IdentifierContext {
-  const NamedArgumentReferenceIdentifierContext()
-      : super('namedArgumentReference', allowedInConstantExpression: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.isIdentifier) {
-      checkAsyncAwaitYieldAsIdentifier(identifier, parser);
-      return identifier;
-    }
-
-    // Recovery
-    if (isOneOfOrEof(identifier, const [':'])) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.topLevelFunctionDeclaration]
-/// and [IdentifierContext.topLevelVariableDeclaration].
-class TopLevelDeclarationIdentifierContext extends IdentifierContext {
-  final List<String> followingValues;
-
-  const TopLevelDeclarationIdentifierContext(String name, this.followingValues)
-      : super(name, inDeclaration: true);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-
-    if (identifier.isIdentifier) {
-      Token next = identifier.next;
-      if (!looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-          isOneOfOrEof(next, followingValues)) {
-        return identifier;
-      }
-      // Although this is a valid top level name, the declaration
-      // is invalid and this looks like the start of the next declaration.
-      // In this situation, fall through to insert a synthetic name.
-    }
-
-    // Recovery
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else if (identifier.type.isBuiltIn) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.typedefDeclaration].
-class TypedefDeclarationIdentifierContext extends IdentifierContext {
-  const TypedefDeclarationIdentifierContext()
-      : super('typedefDeclaration',
-            inDeclaration: true, isBuiltInIdentifierAllowed: false);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.type.isPseudo) {
-      if (optional('Function', identifier)) {
-        parser.reportRecoverableErrorWithToken(
-            identifier, fasta.templateExpectedIdentifier);
-      }
-      return identifier;
-    }
-
-    // Recovery
-    const List<String> followingValues = const ['(', '<', '=', ';'];
-    if (identifier.type.isBuiltIn &&
-        isOneOfOrEof(identifier.next, followingValues)) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      identifier = parser.insertSyntheticIdentifier(token, this,
-          message: fasta.templateExpectedIdentifier.withArguments(identifier));
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-/// See [IdentifierContext.typeReference].
-class TypeReferenceIdentifierContext extends IdentifierContext {
-  const TypeReferenceIdentifierContext()
-      : super('typeReference',
-            isScopeReference: true,
-            isBuiltInIdentifierAllowed: false,
-            recoveryTemplate: fasta.templateExpectedType);
-
-  const TypeReferenceIdentifierContext.continuation()
-      : super('typeReferenceContinuation',
-            isContinuation: true, isBuiltInIdentifierAllowed: false);
-
-  const TypeReferenceIdentifierContext.prefixed()
-      : super('prefixedTypeReference',
-            isScopeReference: true,
-            isBuiltInIdentifierAllowed: true,
-            recoveryTemplate: fasta.templateExpectedType);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token next = token.next;
-    assert(next.kind != IDENTIFIER_TOKEN);
-    if (isValidTypeReference(next)) {
-      return next;
-    } else if (next.isKeywordOrIdentifier) {
-      if (optional("void", next)) {
-        parser.reportRecoverableError(next, fasta.messageInvalidVoid);
-      } else if (next.type.isBuiltIn) {
-        if (!isBuiltInIdentifierAllowed) {
-          parser.reportRecoverableErrorWithToken(
-              next, fasta.templateBuiltInIdentifierAsType);
-        }
-      } else if (optional('var', next)) {
-        parser.reportRecoverableError(next, fasta.messageVarAsTypeName);
-      } else {
-        parser.reportRecoverableErrorWithToken(
-            next, fasta.templateExpectedType);
-      }
-      return next;
-    }
-    parser.reportRecoverableErrorWithToken(next, fasta.templateExpectedType);
-    if (!isOneOfOrEof(
-        next, const ['<', '>', ')', '[', ']', '[]', '{', '}', ',', ';'])) {
-      // When in doubt, consume the token to ensure we make progress
-      token = next;
-      next = token.next;
-    }
-    // Insert a synthetic identifier to satisfy listeners.
-    return parser.rewriter.insertSyntheticIdentifier(token);
-  }
-}
-
-// See [IdentifierContext.typeVariableDeclaration].
-class TypeVariableDeclarationIdentifierContext extends IdentifierContext {
-  const TypeVariableDeclarationIdentifierContext()
-      : super('typeVariableDeclaration',
-            inDeclaration: true, isBuiltInIdentifierAllowed: false);
-
-  @override
-  Token ensureIdentifier(Token token, Parser parser) {
-    Token identifier = token.next;
-    assert(identifier.kind != IDENTIFIER_TOKEN);
-    if (identifier.type.isPseudo) {
-      return identifier;
-    }
-
-    // Recovery
-    const List<String> followingValues = const [
-      '<',
-      '>',
-      ';',
-      '}',
-      'extends',
-      'super'
-    ];
-    if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
-        looksLikeStartOfNextClassMember(identifier) ||
-        looksLikeStatementStart(identifier) ||
-        isOneOfOrEof(identifier, followingValues)) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      identifier = parser.rewriter.insertSyntheticIdentifier(token);
-    } else if (identifier.type.isBuiltIn) {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateBuiltInIdentifierInDeclaration);
-    } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-      if (!identifier.isKeywordOrIdentifier) {
-        // When in doubt, consume the token to ensure we make progress
-        // but insert a synthetic identifier to satisfy listeners.
-        identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
-      }
-    }
-    return identifier;
-  }
-}
-
-void checkAsyncAwaitYieldAsIdentifier(Token identifier, Parser parser) {
-  if (!parser.inPlainSync && identifier.type.isPseudo) {
-    if (optional('await', identifier)) {
-      parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
-    } else if (optional('yield', identifier)) {
-      parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
-    }
-  }
-}
-
-bool looksLikeStartOfNextClassMember(Token token) =>
-    token.isModifier || isOneOfOrEof(token, const ['@', 'get', 'set', 'void']);
-
-bool looksLikeStartOfNextTopLevelDeclaration(Token token) =>
-    token.isTopLevelKeyword ||
-    isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
deleted file mode 100644
index 89851cb..0000000
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ /dev/null
@@ -1,1644 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.parser.listener;
-
-import '../../scanner/token.dart' show Token;
-
-import '../fasta_codes.dart'
-    show Message, MessageCode, templateExperimentNotEnabled;
-
-import '../quote.dart' show UnescapeErrorListener;
-
-import '../scanner/error_token.dart' show ErrorToken;
-
-import 'assert.dart' show Assert;
-
-import 'formal_parameter_kind.dart' show FormalParameterKind;
-
-import 'identifier_context.dart' show IdentifierContext;
-
-import 'declaration_kind.dart' show DeclarationKind;
-
-import 'member_kind.dart' show MemberKind;
-
-import 'util.dart' show optional;
-
-/// A parser event listener that does nothing except throw exceptions
-/// on parser errors.
-///
-/// Events are methods that begin with one of: `begin`, `end`, or `handle`.
-///
-/// Events starting with `begin` and `end` come in pairs. Normally, a
-/// `beginFoo` event is followed by an `endFoo` event. There's a few exceptions
-/// documented below.
-///
-/// Events starting with `handle` are used when isn't possible to have a begin
-/// event.
-class Listener implements UnescapeErrorListener {
-  Uri get uri => null;
-
-  void logEvent(String name) {}
-
-  set suppressParseErrors(bool value) {}
-
-  void beginArguments(Token token) {}
-
-  void endArguments(int count, Token beginToken, Token endToken) {
-    logEvent("Arguments");
-  }
-
-  /// Handle async modifiers `async`, `async*`, `sync`.
-  void handleAsyncModifier(Token asyncToken, Token starToken) {
-    logEvent("AsyncModifier");
-  }
-
-  void beginAwaitExpression(Token token) {}
-
-  void endAwaitExpression(Token beginToken, Token endToken) {
-    logEvent("AwaitExpression");
-  }
-
-  void endInvalidAwaitExpression(
-      Token beginToken, Token endToken, MessageCode errorCode) {
-    logEvent("InvalidAwaitExpression");
-  }
-
-  void beginBlock(Token token) {}
-
-  void endBlock(int count, Token beginToken, Token endToken) {
-    logEvent("Block");
-  }
-
-  /// Called to handle a block that has been parsed but is not associated
-  /// with any top level function declaration. Substructures:
-  /// - block
-  void handleInvalidTopLevelBlock(Token token) {}
-
-  void beginCascade(Token token) {}
-
-  void endCascade() {
-    logEvent("Cascade");
-  }
-
-  void beginCaseExpression(Token caseKeyword) {}
-
-  void endCaseExpression(Token colon) {
-    logEvent("CaseExpression");
-  }
-
-  /// Handle the start of the body of a class, mixin or extension declaration
-  /// beginning at [token]. The actual kind of declaration is indicated by
-  /// [kind].
-  void beginClassOrMixinBody(DeclarationKind kind, Token token) {}
-
-  /// Handle the end of the body of a class, mixin or extension declaration.
-  /// The only substructures are the class, mixin or extension members.
-  ///
-  /// The actual kind of declaration is indicated by [kind].
-  void endClassOrMixinBody(
-      DeclarationKind kind, int memberCount, Token beginToken, Token endToken) {
-    logEvent("ClassOrMixinBody");
-  }
-
-  /// Called before parsing a class or named mixin application.
-  ///
-  /// At this point only the `class` keyword have been seen, so we know a
-  /// declaration is coming but not its name or type parameter declarations.
-  void beginClassOrNamedMixinApplicationPrelude(Token token) {}
-
-  /// Handle the beginning of a class declaration.
-  /// [begin] may be the same as [name], or may point to modifiers
-  /// (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) {}
-
-  /// Handle an extends clause in a class declaration. Substructures:
-  /// - supertype (may be a mixin application)
-  void handleClassExtends(Token extendsKeyword) {
-    logEvent("ClassExtends");
-  }
-
-  /// Handle an implements clause in a class or mixin declaration.
-  /// Substructures:
-  /// - implemented types
-  void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
-    logEvent("ClassImplements");
-  }
-
-  /// Handle the header of a class declaration.  Substructures:
-  /// - metadata
-  /// - modifiers
-  /// - class name
-  /// - type variables
-  /// - supertype
-  /// - with clause
-  /// - implemented types
-  /// - native clause
-  void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
-    logEvent("ClassHeader");
-  }
-
-  /// Handle recovery associated with a class header.
-  /// This may be called multiple times after [handleClassHeader]
-  /// to recover information about the previous class header.
-  /// The substructures are a subset of
-  /// and in the same order as [handleClassHeader]:
-  /// - supertype
-  /// - with clause
-  /// - implemented types
-  void handleRecoverClassHeader() {
-    logEvent("RecoverClassHeader");
-  }
-
-  /// Handle the end of a class declaration.  Substructures:
-  /// - class header
-  /// - class body
-  void endClassDeclaration(Token beginToken, Token endToken) {
-    logEvent("ClassDeclaration");
-  }
-
-  /// Handle the beginning of a mixin declaration.
-  void beginMixinDeclaration(Token mixinKeyword, Token name) {}
-
-  /// Handle an on clause in a mixin declaration. Substructures:
-  /// - implemented types
-  void handleMixinOn(Token onKeyword, int typeCount) {
-    logEvent("MixinOn");
-  }
-
-  /// Handle the header of a mixin declaration.  Substructures:
-  /// - metadata
-  /// - mixin name
-  /// - type variables
-  /// - on types
-  /// - implemented types
-  void handleMixinHeader(Token mixinKeyword) {
-    logEvent("MixinHeader");
-  }
-
-  /// Handle recovery associated with a mixin header.
-  /// This may be called multiple times after [handleMixinHeader]
-  /// to recover information about the previous mixin header.
-  /// The substructures are a subset of
-  /// and in the same order as [handleMixinHeader]
-  /// - on types
-  /// - implemented types
-  void handleRecoverMixinHeader() {
-    logEvent("RecoverMixinHeader");
-  }
-
-  /// Handle the end of a mixin declaration.  Substructures:
-  /// - mixin header
-  /// - class or mixin body
-  void endMixinDeclaration(Token mixinKeyword, Token endToken) {
-    logEvent("MixinDeclaration");
-  }
-
-  /// Handle the beginning of an extension methods declaration.  Substructures:
-  /// - metadata
-  ///
-  /// At this point only the `extension` keyword have been seen, so we know a
-  /// declaration is coming but not its name or type parameter declarations.
-  void beginExtensionDeclarationPrelude(Token extensionKeyword) {}
-
-  /// Handle the beginning of an extension methods declaration.  Substructures:
-  /// - type variables
-  ///
-  /// At this point we have parsed the name and type parameter declarations.
-  void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
-
-  /// Handle the end of an extension methods declaration.  Substructures:
-  /// - substructures from [beginExtensionDeclaration]
-  /// - on type
-  /// - body
-  void endExtensionDeclaration(
-      Token extensionKeyword, Token onKeyword, Token token) {
-    logEvent('ExtensionDeclaration');
-  }
-
-  void beginCombinators(Token token) {}
-
-  void endCombinators(int count) {
-    logEvent("Combinators");
-  }
-
-  void beginCompilationUnit(Token token) {}
-
-  /// This method exists for analyzer compatibility only
-  /// and will be removed once analyzer/fasta integration is complete.
-  ///
-  /// This is called when [parseDirectives] has parsed all directives
-  /// and is skipping the remainder of the file.  Substructures:
-  /// - metadata
-  void handleDirectivesOnly() {}
-
-  void endCompilationUnit(int count, Token token) {
-    logEvent("CompilationUnit");
-  }
-
-  void beginConstLiteral(Token token) {}
-
-  void endConstLiteral(Token token) {
-    logEvent("ConstLiteral");
-  }
-
-  void beginConstructorReference(Token start) {}
-
-  void endConstructorReference(
-      Token start, Token periodBeforeName, Token endToken) {
-    logEvent("ConstructorReference");
-  }
-
-  void beginDoWhileStatement(Token token) {}
-
-  void endDoWhileStatement(
-      Token doKeyword, Token whileKeyword, Token endToken) {
-    logEvent("DoWhileStatement");
-  }
-
-  void beginDoWhileStatementBody(Token token) {}
-
-  void endDoWhileStatementBody(Token token) {
-    logEvent("DoWhileStatementBody");
-  }
-
-  void beginWhileStatementBody(Token token) {}
-
-  void endWhileStatementBody(Token token) {
-    logEvent("WhileStatementBody");
-  }
-
-  void beginEnum(Token enumKeyword) {}
-
-  /// Handle the end of an enum declaration.  Substructures:
-  /// - Metadata
-  /// - Enum name (identifier)
-  /// - [count] times:
-  ///   - Enum value (identifier)
-  void endEnum(Token enumKeyword, Token leftBrace, int count) {
-    logEvent("Enum");
-  }
-
-  void beginExport(Token token) {}
-
-  /// Handle the end of an export directive.  Substructures:
-  /// - metadata
-  /// - uri
-  /// - conditional uris
-  /// - combinators
-  void endExport(Token exportKeyword, Token semicolon) {
-    logEvent("Export");
-  }
-
-  /// Called by [Parser] after parsing an extraneous expression as error
-  /// recovery. For a stack-based listener, the suggested action is to discard
-  /// an expression from the stack.
-  void handleExtraneousExpression(Token token, Message message) {
-    logEvent("ExtraneousExpression");
-  }
-
-  void handleExpressionStatement(Token token) {
-    logEvent("ExpressionStatement");
-  }
-
-  void beginFactoryMethod(
-      Token lastConsumed, Token externalToken, Token constToken) {}
-
-  void endClassFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    logEvent("ClassFactoryMethod");
-  }
-
-  void endMixinFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassFactoryMethod(beginToken, factoryKeyword, endToken);
-  }
-
-  void endExtensionFactoryMethod(
-      Token beginToken, Token factoryKeyword, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassFactoryMethod(beginToken, factoryKeyword, endToken);
-  }
-
-  void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
-      Token covariantToken, Token varFinalOrConst) {}
-
-  void endFormalParameter(
-      Token thisKeyword,
-      Token periodAfterThis,
-      Token nameToken,
-      Token initializerStart,
-      Token initializerEnd,
-      FormalParameterKind kind,
-      MemberKind memberKind) {
-    logEvent("FormalParameter");
-  }
-
-  void handleNoFormalParameters(Token token, MemberKind kind) {
-    logEvent("NoFormalParameters");
-  }
-
-  void beginFormalParameters(Token token, MemberKind kind) {}
-
-  void endFormalParameters(
-      int count, Token beginToken, Token endToken, MemberKind kind) {
-    logEvent("FormalParameters");
-  }
-
-  /// Handle the end of a class field declaration.  Substructures:
-  /// - Metadata
-  /// - Modifiers
-  /// - Type
-  /// - Variable declarations (count times)
-  ///
-  /// Doesn't have a corresponding begin event, use [beginMember] instead.
-  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    logEvent("Fields");
-  }
-
-  /// Handle the end of a mixin field declaration.  Substructures:
-  /// - Metadata
-  /// - Modifiers
-  /// - Type
-  /// - Variable declarations (count times)
-  ///
-  /// Doesn't have a corresponding begin event, use [beginMember] instead.
-  void endMixinFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassFields(staticToken, covariantToken, lateToken, varFinalOrConst,
-        count, beginToken, endToken);
-  }
-
-  /// Handle the end of a extension field declaration.  Substructures:
-  /// - Metadata
-  /// - Modifiers
-  /// - Type
-  /// - Variable declarations (count times)
-  ///
-  /// Doesn't have a corresponding begin event, use [beginMember] instead.
-  void endExtensionFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassFields(staticToken, covariantToken, lateToken, varFinalOrConst,
-        count, beginToken, endToken);
-  }
-
-  /// Marks that the grammar term `forInitializerStatement` has been parsed and
-  /// it was an empty statement.
-  void handleForInitializerEmptyStatement(Token token) {
-    logEvent("ForInitializerEmptyStatement");
-  }
-
-  /// Marks that the grammar term `forInitializerStatement` has been parsed and
-  /// it was an expression statement.
-  void handleForInitializerExpressionStatement(Token token) {
-    logEvent("ForInitializerExpressionStatement");
-  }
-
-  /// Marks that the grammar term `forInitializerStatement` has been parsed and
-  /// it was a `localVariableDeclaration`.
-  void handleForInitializerLocalVariableDeclaration(Token token) {
-    logEvent("ForInitializerLocalVariableDeclaration");
-  }
-
-  /// Marks the start of a for statement which is ended by either
-  /// [endForStatement] or [endForIn].
-  void beginForStatement(Token token) {}
-
-  /// Marks the end of parsing the control structure of a for statement
-  /// or for control flow entry up to and including the closing parenthesis.
-  /// `for` `(` initialization `;` condition `;` updaters `)`
-  void handleForLoopParts(Token forKeyword, Token leftParen,
-      Token leftSeparator, int updateExpressionCount) {}
-
-  void endForStatement(Token endToken) {
-    logEvent("ForStatement");
-  }
-
-  void beginForStatementBody(Token token) {}
-
-  void endForStatementBody(Token token) {
-    logEvent("ForStatementBody");
-  }
-
-  /// 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,
-      Token leftParenthesis, Token inKeyword) {}
-
-  // One of the two possible corresponding end events for [beginForStatement].
-  void endForIn(Token endToken) {
-    logEvent("ForIn");
-  }
-
-  void beginForInExpression(Token token) {}
-
-  void endForInExpression(Token token) {
-    logEvent("ForInExpression");
-  }
-
-  void beginForInBody(Token token) {}
-
-  void endForInBody(Token token) {
-    logEvent("ForInBody");
-  }
-
-  /// Handle the beginning of a named function expression which isn't legal
-  /// syntax in Dart.  Useful for recovering from Javascript code being pasted
-  /// into a Dart program, as it will interpret `function foo() {}` as a named
-  /// function expression with return type `function` and name `foo`.
-  ///
-  /// Substructures:
-  /// - Type variables
-  void beginNamedFunctionExpression(Token token) {}
-
-  /// A named function expression which isn't legal syntax in Dart.
-  /// Useful for recovering from Javascript code being pasted into a Dart
-  /// program, as it will interpret `function foo() {}` as a named function
-  /// expression with return type `function` and name `foo`.
-  ///
-  /// Substructures:
-  /// - Type variables
-  /// - Modifiers
-  /// - Return type
-  /// - Name
-  /// - Formals
-  /// - Initializers
-  /// - Async modifier
-  /// - Function body (block or arrow expression).
-  void endNamedFunctionExpression(Token endToken) {
-    logEvent("NamedFunctionExpression");
-  }
-
-  /// Handle the beginning of a local function declaration.  Substructures:
-  /// - Metadata
-  /// - Type variables
-  void beginLocalFunctionDeclaration(Token token) {}
-
-  /// A function declaration.
-  ///
-  /// Substructures:
-  /// - Metadata
-  /// - Type variables
-  /// - Return type
-  /// - Name
-  /// - Type variables
-  /// - Formals
-  /// - Initializers
-  /// - Async modifier
-  /// - Function body (block or arrow expression).
-  void endLocalFunctionDeclaration(Token endToken) {
-    logEvent("FunctionDeclaration");
-  }
-
-  /// This method is invoked when the parser sees that a function has a
-  /// block function body.  This method is not invoked for empty or expression
-  /// function bodies, see the corresponding methods [handleEmptyFunctionBody]
-  /// and [handleExpressionFunctionBody].
-  void beginBlockFunctionBody(Token token) {}
-
-  /// This method is invoked by the parser after it finished parsing a block
-  /// function body.  This method is not invoked for empty or expression
-  /// function bodies, see the corresponding methods [handleEmptyFunctionBody]
-  /// and [handleExpressionFunctionBody].  The [beginToken] is the '{' token,
-  /// and the [endToken] is the '}' token of the block.  The number of
-  /// statements is given as the [count] parameter.
-  void endBlockFunctionBody(int count, Token beginToken, Token endToken) {
-    logEvent("BlockFunctionBody");
-  }
-
-  void handleNoFunctionBody(Token token) {
-    logEvent("NoFunctionBody");
-  }
-
-  /// Handle the end of a function body that was skipped by the parser.
-  ///
-  /// The boolean [isExpressionBody] indicates whether the function body that
-  /// was skipped used "=>" syntax.
-  void handleFunctionBodySkipped(Token token, bool isExpressionBody) {}
-
-  void beginFunctionName(Token token) {}
-
-  void endFunctionName(Token beginToken, Token token) {
-    logEvent("FunctionName");
-  }
-
-  void beginFunctionTypeAlias(Token token) {}
-
-  /// Handle the end of a typedef declaration.
-  ///
-  /// If [equals] is null, then we have the following substructures:
-  /// - Metadata
-  /// - Return type
-  /// - Name (identifier)
-  /// - Alias type variables
-  /// - Formal parameters
-  ///
-  /// If [equals] is not null, then the have the following substructures:
-  /// - Metadata
-  /// - Name (identifier)
-  /// - Alias type variables
-  /// - Type (FunctionTypeAnnotation)
-  void endFunctionTypeAlias(
-      Token typedefKeyword, Token equals, Token endToken) {
-    logEvent("FunctionTypeAlias");
-  }
-
-  /// Handle the end of a with clause (e.g. "with B, C").
-  /// Substructures:
-  /// - mixin types (TypeList)
-  void handleClassWithClause(Token withKeyword) {
-    logEvent("ClassWithClause");
-  }
-
-  /// Handle the absence of a with clause.
-  void handleClassNoWithClause() {
-    logEvent("ClassNoWithClause");
-  }
-
-  /// Handle the beginning of a named mixin application.
-  /// [beginToken] may be the same as [name], or may point to modifiers
-  /// (or extraneous modifiers in the case of recovery) preceding [name].
-  ///
-  /// At this point we have parsed the name and type parameter declarations.
-  void beginNamedMixinApplication(
-      Token begin, Token abstractToken, Token name) {}
-
-  /// Handle a named mixin application with clause (e.g. "A with B, C").
-  /// Substructures:
-  /// - supertype
-  /// - mixin types (TypeList)
-  void handleNamedMixinApplicationWithClause(Token withKeyword) {
-    logEvent("NamedMixinApplicationWithClause");
-  }
-
-  /// Handle the end of a named mixin declaration.  Substructures:
-  /// - metadata
-  /// - modifiers
-  /// - class name
-  /// - type variables
-  /// - supertype
-  /// - with clause
-  /// - implemented types (TypeList)
-  ///
-  /// TODO(paulberry,ahe): it seems inconsistent that for a named mixin
-  /// application, the implemented types are a TypeList, whereas for a class
-  /// 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) {
-    logEvent("NamedMixinApplication");
-  }
-
-  void beginHide(Token hideKeyword) {}
-
-  /// Handle the end of a "hide" combinator.  Substructures:
-  /// - hidden names (IdentifierList)
-  void endHide(Token hideKeyword) {
-    logEvent("Hide");
-  }
-
-  void handleIdentifierList(int count) {
-    logEvent("IdentifierList");
-  }
-
-  void beginTypeList(Token token) {}
-
-  void endTypeList(int count) {
-    logEvent("TypeList");
-  }
-
-  void beginIfStatement(Token token) {}
-
-  void endIfStatement(Token ifToken, Token elseToken) {
-    logEvent("IfStatement");
-  }
-
-  void beginThenStatement(Token token) {}
-
-  void endThenStatement(Token token) {
-    logEvent("ThenStatement");
-  }
-
-  void beginElseStatement(Token token) {}
-
-  void endElseStatement(Token token) {
-    logEvent("ElseStatement");
-  }
-
-  void beginImport(Token importKeyword) {}
-
-  /// Signals that the current import is deferred and/or has a prefix
-  /// depending upon whether [deferredKeyword] and [asKeyword]
-  /// are not `null` respectively. Substructures:
-  /// - prefix identifier (only if asKeyword != null)
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    logEvent("ImportPrefix");
-  }
-
-  /// Handle the end of an import directive.  Substructures:
-  /// - metadata
-  /// - uri
-  /// - conditional uris
-  /// - prefix identifier
-  /// - combinators
-  void endImport(Token importKeyword, Token semicolon) {
-    logEvent("Import");
-  }
-
-  /// Handle recovery associated with an import directive.
-  /// This may be called multiple times after [endImport]
-  /// to recover information about the previous import directive.
-  /// The substructures are a subset of and in the same order as [endImport]:
-  /// - conditional uris
-  /// - prefix identifier
-  /// - combinators
-  void handleRecoverImport(Token semicolon) {
-    logEvent("ImportRecovery");
-  }
-
-  void beginConditionalUris(Token token) {}
-
-  void endConditionalUris(int count) {
-    logEvent("ConditionalUris");
-  }
-
-  void beginConditionalUri(Token ifKeyword) {}
-
-  /// Handle the end of a conditional URI construct.  Substructures:
-  /// - Dotted name
-  /// - Condition (literal string; only if [equalSign] != null)
-  /// - URI (literal string)
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
-    logEvent("ConditionalUri");
-  }
-
-  void handleDottedName(int count, Token firstIdentifier) {
-    logEvent("DottedName");
-  }
-
-  void beginImplicitCreationExpression(Token token) {}
-
-  void endImplicitCreationExpression(Token token) {
-    logEvent("ImplicitCreationExpression");
-  }
-
-  void beginInitializedIdentifier(Token token) {}
-
-  void endInitializedIdentifier(Token nameToken) {
-    logEvent("InitializedIdentifier");
-  }
-
-  void beginFieldInitializer(Token token) {}
-
-  /// Handle the end of a field initializer.  Substructures:
-  /// - Initializer expression
-  void endFieldInitializer(Token assignment, Token token) {
-    logEvent("FieldInitializer");
-  }
-
-  /// Handle the lack of a field initializer.
-  void handleNoFieldInitializer(Token token) {
-    logEvent("NoFieldInitializer");
-  }
-
-  void beginVariableInitializer(Token token) {}
-
-  /// Handle the end of a variable initializer. Substructures:
-  /// - Initializer expression.
-  void endVariableInitializer(Token assignmentOperator) {
-    logEvent("VariableInitializer");
-  }
-
-  /// Used when a variable has no initializer.
-  void handleNoVariableInitializer(Token token) {
-    logEvent("NoVariableInitializer");
-  }
-
-  void beginInitializer(Token token) {}
-
-  void endInitializer(Token token) {
-    logEvent("ConstructorInitializer");
-  }
-
-  void beginInitializers(Token token) {}
-
-  void endInitializers(int count, Token beginToken, Token endToken) {
-    logEvent("Initializers");
-  }
-
-  void handleNoInitializers() {
-    logEvent("NoInitializers");
-  }
-
-  /// Called after the listener has recovered from an invalid expression. The
-  /// parser will resume parsing from [token]. Exactly where the parser will
-  /// resume parsing is unspecified.
-  void handleInvalidExpression(Token token) {
-    logEvent("InvalidExpression");
-  }
-
-  /// Called after the listener has recovered from an invalid function
-  /// body. The parser expected an open curly brace `{` and will resume parsing
-  /// from [token] as if a function body had preceded it.
-  void handleInvalidFunctionBody(Token token) {
-    logEvent("InvalidFunctionBody");
-  }
-
-  /// Called after the listener has recovered from an invalid type. The parser
-  /// expected an identifier, and will resume parsing type arguments from
-  /// [token].
-  void handleInvalidTypeReference(Token token) {
-    logEvent("InvalidTypeReference");
-  }
-
-  void handleLabel(Token token) {
-    logEvent("Label");
-  }
-
-  void beginLabeledStatement(Token token, int labelCount) {}
-
-  void endLabeledStatement(int labelCount) {
-    logEvent("LabeledStatement");
-  }
-
-  void beginLibraryName(Token token) {}
-
-  /// Handle the end of a library directive.  Substructures:
-  /// - Metadata
-  /// - Library name (a qualified identifier)
-  void endLibraryName(Token libraryKeyword, Token semicolon) {
-    logEvent("LibraryName");
-  }
-
-  void handleLiteralMapEntry(Token colon, Token endToken) {
-    logEvent("LiteralMapEntry");
-  }
-
-  void beginLiteralString(Token token) {}
-
-  void handleInterpolationExpression(Token leftBracket, Token rightBracket) {}
-
-  void endLiteralString(int interpolationCount, Token endToken) {
-    logEvent("LiteralString");
-  }
-
-  void handleStringJuxtaposition(int literalCount) {
-    logEvent("StringJuxtaposition");
-  }
-
-  void beginMember() {}
-
-  /// Handle an invalid member declaration. Substructures:
-  /// - metadata
-  void handleInvalidMember(Token endToken) {
-    logEvent("InvalidMember");
-  }
-
-  /// This event is added for convenience. Normally, one should override
-  /// [endClassFields], [endMixinFields], [endExtensionFields],
-  /// [endClassMethod], [endMixinMethod], [endExtensionMethod],
-  /// [endClassConstructor], [endMixinConstructor],
-  /// or [endExtensionConstructor] instead.
-  void endMember() {
-    logEvent("Member");
-  }
-
-  /// Handle the beginning of a method declaration.  Substructures:
-  /// - metadata
-  void beginMethod(Token externalToken, Token staticToken, Token covariantToken,
-      Token varFinalOrConst, Token getOrSet, Token name) {}
-
-  /// Handle the end of a class method declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    logEvent("ClassMethod");
-  }
-
-  /// Handle the end of a mixin method declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endMixinMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  /// Handle the end of a extension method declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endExtensionMethod(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  /// Handle the end of a class constructor declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  /// Handle the end of a mixin constructor declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endMixinConstructor(Token getOrSet, Token beginToken, Token beginParam,
-      Token beginInitializers, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  /// Handle the end of a extension constructor declaration.  Substructures:
-  /// - metadata
-  /// - return type
-  /// - method name (identifier, possibly qualified)
-  /// - type variables
-  /// - formal parameters
-  /// - initializers
-  /// - async marker
-  /// - body
-  void endExtensionConstructor(Token getOrSet, Token beginToken,
-      Token beginParam, Token beginInitializers, Token endToken) {
-    // TODO(danrubel): push implementation into subclasses
-    endClassMethod(
-        getOrSet, beginToken, beginParam, beginInitializers, endToken);
-  }
-
-  void beginMetadataStar(Token token) {}
-
-  void endMetadataStar(int count) {
-    logEvent("MetadataStar");
-  }
-
-  void beginMetadata(Token token) {}
-
-  /// Handle the end of a metadata annotation.  Substructures:
-  /// - Identifier
-  /// - Type arguments
-  /// - Constructor name (only if [periodBeforeName] is not `null`)
-  /// - Arguments
-  void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
-    logEvent("Metadata");
-  }
-
-  void beginOptionalFormalParameters(Token token) {}
-
-  void endOptionalFormalParameters(
-      int count, Token beginToken, Token endToken) {
-    logEvent("OptionalFormalParameters");
-  }
-
-  void beginPart(Token token) {}
-
-  /// Handle the end of a part directive.  Substructures:
-  /// - metadata
-  /// - uri
-  void endPart(Token partKeyword, Token semicolon) {
-    logEvent("Part");
-  }
-
-  void beginPartOf(Token token) {}
-
-  /// Handle the end of a "part of" directive.  Substructures:
-  /// - Metadata
-  /// - Library name (a qualified identifier)
-  ///
-  /// If [hasName] is true, this part refers to its library by name, otherwise,
-  /// by URI.
-  void endPartOf(
-      Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
-    logEvent("PartOf");
-  }
-
-  void beginRedirectingFactoryBody(Token token) {}
-
-  void endRedirectingFactoryBody(Token beginToken, Token endToken) {
-    logEvent("RedirectingFactoryBody");
-  }
-
-  void beginReturnStatement(Token token) {}
-
-  /// Handle the end of a `native` function.
-  /// The [handleNativeClause] event is sent prior to this event.
-  void handleNativeFunctionBody(Token nativeToken, Token semicolon) {
-    logEvent("NativeFunctionBody");
-  }
-
-  /// Called after the [handleNativeClause] event when the parser determines
-  /// that the native clause should be discarded / ignored.
-  /// For example, this method is called a native clause is followed by
-  /// a function body.
-  void handleNativeFunctionBodyIgnored(Token nativeToken, Token semicolon) {
-    logEvent("NativeFunctionBodyIgnored");
-  }
-
-  /// Handle the end of a `native` function that was skipped by the parser.
-  /// The [handleNativeClause] event is sent prior to this event.
-  void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
-    logEvent("NativeFunctionBodySkipped");
-  }
-
-  /// This method is invoked when a function has the empty body.
-  void handleEmptyFunctionBody(Token semicolon) {
-    logEvent("EmptyFunctionBody");
-  }
-
-  /// This method is invoked when parser finishes parsing the corresponding
-  /// expression of the expression function body.
-  void handleExpressionFunctionBody(Token arrowToken, Token endToken) {
-    logEvent("ExpressionFunctionBody");
-  }
-
-  void endReturnStatement(
-      bool hasExpression, Token beginToken, Token endToken) {
-    logEvent("ReturnStatement");
-  }
-
-  void handleSend(Token beginToken, Token endToken) {
-    logEvent("Send");
-  }
-
-  void beginShow(Token showKeyword) {}
-
-  /// Handle the end of a "show" combinator.  Substructures:
-  /// - shown names (IdentifierList)
-  void endShow(Token showKeyword) {
-    logEvent("Show");
-  }
-
-  void beginSwitchStatement(Token token) {}
-
-  void endSwitchStatement(Token switchKeyword, Token endToken) {
-    logEvent("SwitchStatement");
-  }
-
-  void beginSwitchBlock(Token token) {}
-
-  void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
-    logEvent("SwitchBlock");
-  }
-
-  void beginLiteralSymbol(Token token) {}
-
-  void endLiteralSymbol(Token hashToken, int identifierCount) {
-    logEvent("LiteralSymbol");
-  }
-
-  void handleThrowExpression(Token throwToken, Token endToken) {
-    logEvent("ThrowExpression");
-  }
-
-  void beginRethrowStatement(Token token) {}
-
-  void endRethrowStatement(Token rethrowToken, Token endToken) {
-    logEvent("RethrowStatement");
-  }
-
-  /// This event is added for convenience. Normally, one should use
-  /// [endClassDeclaration], [endNamedMixinApplication], [endEnum],
-  /// [endFunctionTypeAlias], [endLibraryName], [endImport], [endExport],
-  /// [endPart], [endPartOf], [endTopLevelFields], or [endTopLevelMethod].
-  void endTopLevelDeclaration(Token token) {
-    logEvent("TopLevelDeclaration");
-  }
-
-  /// Called by the [Parser] when it recovers from an invalid top level
-  /// declaration, where [endToken] is the last token in the declaration
-  /// This is called after the begin/end metadata star events,
-  /// and is followed by [endTopLevelDeclaration].
-  ///
-  /// Substructures:
-  /// - metadata
-  void handleInvalidTopLevelDeclaration(Token endToken) {
-    logEvent("InvalidTopLevelDeclaration");
-  }
-
-  /// Marks the beginning of a top level field or method declaration.
-  /// Doesn't have a corresponding end event.
-  /// See [endTopLevelFields] and [endTopLevelMethod].
-  void beginTopLevelMember(Token token) {}
-
-  /// Handle the end of a top level variable declaration.  Substructures:
-  /// - Metadata
-  /// - Type
-  /// - Repeated [count] times:
-  ///   - Variable name (identifier)
-  ///   - Field initializer
-  /// Doesn't have a corresponding begin event.
-  /// Use [beginTopLevelMember] instead.
-  void endTopLevelFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    logEvent("TopLevelFields");
-  }
-
-  void beginTopLevelMethod(Token lastConsumed, Token externalToken) {}
-
-  /// Handle the end of a top level method.  Substructures:
-  /// - metadata
-  /// - modifiers
-  /// - return type
-  /// - identifier
-  /// - type variables
-  /// - formal parameters
-  /// - async marker
-  /// - body
-  void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
-    logEvent("TopLevelMethod");
-  }
-
-  void beginTryStatement(Token token) {}
-
-  void handleCaseMatch(Token caseKeyword, Token colon) {
-    logEvent("CaseMatch");
-  }
-
-  void beginCatchClause(Token token) {}
-
-  void endCatchClause(Token token) {
-    logEvent("CatchClause");
-  }
-
-  void handleCatchBlock(Token onKeyword, Token catchKeyword, Token comma) {
-    logEvent("CatchBlock");
-  }
-
-  void handleFinallyBlock(Token finallyKeyword) {
-    logEvent("FinallyBlock");
-  }
-
-  void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
-    logEvent("TryStatement");
-  }
-
-  void handleType(Token beginToken, Token questionMark) {
-    logEvent("Type");
-  }
-
-  /// Called when parser encounters a '!'
-  /// used as a non-null postfix assertion in an expression.
-  void handleNonNullAssertExpression(Token bang) {
-    logEvent("NonNullAssertExpression");
-  }
-
-  // TODO(danrubel): Remove this once all listeners have been updated
-  // to properly handle nullable types
-  void reportErrorIfNullableType(Token questionMark) {
-    if (questionMark != null) {
-      assert(optional('?', questionMark));
-      handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('non-nullable'),
-          questionMark,
-          questionMark);
-    }
-  }
-
-  // TODO(danrubel): Remove this once all listeners have been updated
-  // to properly handle nullable types
-  void reportNonNullableModifierError(Token modifierToken) {
-    if (modifierToken != null) {
-      handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('non-nullable'),
-          modifierToken,
-          modifierToken);
-    }
-  }
-
-  // TODO(danrubel): Remove this once all listeners have been updated
-  // to properly handle non-null assert expressions
-  void reportNonNullAssertExpressionNotEnabled(Token bang) {
-    handleRecoverableError(
-        templateExperimentNotEnabled.withArguments('non-nullable'), bang, bang);
-  }
-
-  void handleNoName(Token token) {
-    logEvent("NoName");
-  }
-
-  void beginFunctionType(Token beginToken) {}
-
-  /// Handle the end of a generic function type declaration.
-  ///
-  /// Substructures:
-  /// - Type variables
-  /// - Return type
-  /// - Formal parameters
-  void endFunctionType(Token functionToken, Token questionMark) {
-    logEvent("FunctionType");
-  }
-
-  void beginTypeArguments(Token token) {}
-
-  void endTypeArguments(int count, Token beginToken, Token endToken) {
-    logEvent("TypeArguments");
-  }
-
-  /// After endTypeArguments has been called,
-  /// this event is called if those type arguments are invalid.
-  void handleInvalidTypeArguments(Token token) {
-    logEvent("NoTypeArguments");
-  }
-
-  void handleNoTypeArguments(Token token) {
-    logEvent("NoTypeArguments");
-  }
-
-  /// Handle the begin of a type formal parameter (e.g. "X extends Y").
-  /// Substructures:
-  /// - Metadata
-  /// - Name (identifier)
-  void beginTypeVariable(Token token) {}
-
-  /// Called when [beginTypeVariable] has been called for all of the variables
-  /// in a group, and before [endTypeVariable] has been called for any of the
-  /// variables in that same group.
-  void handleTypeVariablesDefined(Token token, int count) {}
-
-  /// Handle the end of a type formal parameter (e.g. "X extends Y")
-  /// where [index] is the index of the type variable in the list of
-  /// type variables being declared.
-  ///
-  /// Substructures:
-  /// - Type bound
-  ///
-  /// See [beginTypeVariable] for additional substructures.
-  void endTypeVariable(
-      Token token, int index, Token extendsOrSuper, Token variance) {
-    logEvent("TypeVariable");
-  }
-
-  void beginTypeVariables(Token token) {}
-
-  void endTypeVariables(Token beginToken, Token endToken) {
-    logEvent("TypeVariables");
-  }
-
-  void reportVarianceModifierNotEnabled(Token variance) {
-    if (variance != null) {
-      handleRecoverableError(
-          templateExperimentNotEnabled.withArguments('variance'),
-          variance,
-          variance);
-    }
-  }
-
-  void beginFunctionExpression(Token token) {}
-
-  /// Handle the end of a function expression (e.g. "() { ... }").
-  /// Substructures:
-  /// - Type variables
-  /// - Formal parameters
-  /// - Async marker
-  /// - Body
-  void endFunctionExpression(Token beginToken, Token token) {
-    logEvent("FunctionExpression");
-  }
-
-  /// Handle the start of a variables declaration.  Substructures:
-  /// - Metadata
-  /// - Type
-  void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {}
-
-  void endVariablesDeclaration(int count, Token endToken) {
-    logEvent("VariablesDeclaration");
-  }
-
-  void beginWhileStatement(Token token) {}
-
-  void endWhileStatement(Token whileKeyword, Token endToken) {
-    logEvent("WhileStatement");
-  }
-
-  void handleAsOperator(Token operator) {
-    logEvent("AsOperator");
-  }
-
-  void handleAssignmentExpression(Token token) {
-    logEvent("AssignmentExpression");
-  }
-
-  /// Called when the parser encounters a binary operator, in between the LHS
-  /// and RHS subexpressions.
-  ///
-  /// Not called when the binary operator is `.`, `?.`, or `..`.
-  void beginBinaryExpression(Token token) {}
-
-  void endBinaryExpression(Token token) {
-    logEvent("BinaryExpression");
-  }
-
-  /// Called when the parser encounters a `?` operator and begins parsing a
-  /// conditional expression.
-  void beginConditionalExpression(Token question) {}
-
-  /// Called when the parser encounters a `:` operator in a conditional
-  /// expression.
-  void handleConditionalExpressionColon() {}
-
-  /// Called when the parser finishes processing a conditional expression.
-  void endConditionalExpression(Token question, Token colon) {
-    logEvent("ConditionalExpression");
-  }
-
-  void beginConstExpression(Token constKeyword) {}
-
-  void endConstExpression(Token token) {
-    logEvent("ConstExpression");
-  }
-
-  /// Called before parsing a "for" control flow list, set, or map entry.
-  void beginForControlFlow(Token awaitToken, Token forToken) {}
-
-  /// Called after parsing a "for" control flow list, set, or map entry.
-  void endForControlFlow(Token token) {
-    logEvent('endForControlFlow');
-  }
-
-  /// Called after parsing a "for-in" control flow list, set, or map entry.
-  void endForInControlFlow(Token token) {
-    logEvent('endForInControlFlow');
-  }
-
-  /// Called before parsing an `if` control flow list, set, or map entry.
-  void beginIfControlFlow(Token ifToken) {}
-
-  /// Called before parsing the `then` portion of an `if` control flow list,
-  /// set, or map entry.
-  void beginThenControlFlow(Token token) {}
-
-  /// Called before parsing the `else` portion of an `if` control flow list,
-  /// set, or map entry.
-  void handleElseControlFlow(Token elseToken) {
-    logEvent("ElseControlFlow");
-  }
-
-  /// Called after parsing an `if` control flow list, set, or map entry.
-  /// Substructures:
-  /// - if conditional expression
-  /// - expression
-  void endIfControlFlow(Token token) {
-    logEvent("endIfControlFlow");
-  }
-
-  /// Called after parsing an if-else control flow list, set, or map entry.
-  /// Substructures:
-  /// - if conditional expression
-  /// - then expression
-  /// - else expression
-  void endIfElseControlFlow(Token token) {
-    logEvent("endIfElseControlFlow");
-  }
-
-  /// Called after parsing a list, set, or map entry that starts with
-  /// one of the spread collection tokens `...` or `...?`.  Substructures:
-  /// - expression
-  void handleSpreadExpression(Token spreadToken) {
-    logEvent("SpreadExpression");
-  }
-
-  /// Handle the start of a function typed formal parameter.  Substructures:
-  /// - type variables
-  void beginFunctionTypedFormalParameter(Token token) {}
-
-  /// Handle the end of a function typed formal parameter.  Substructures:
-  /// - type variables
-  /// - return type
-  /// - formal parameters
-  void endFunctionTypedFormalParameter(Token nameToken, Token question) {
-    logEvent("FunctionTypedFormalParameter");
-  }
-
-  /// Handle an identifier token.
-  ///
-  /// [context] indicates what kind of construct the identifier appears in.
-  void handleIdentifier(Token token, IdentifierContext context) {
-    logEvent("Identifier");
-  }
-
-  void handleIndexedExpression(
-      Token openSquareBracket, Token closeSquareBracket) {
-    logEvent("IndexedExpression");
-  }
-
-  void handleIsOperator(Token isOperator, Token not) {
-    logEvent("IsOperator");
-  }
-
-  void handleLiteralBool(Token token) {
-    logEvent("LiteralBool");
-  }
-
-  void handleBreakStatement(
-      bool hasTarget, Token breakKeyword, Token endToken) {
-    logEvent("BreakStatement");
-  }
-
-  void handleContinueStatement(
-      bool hasTarget, Token continueKeyword, Token endToken) {
-    logEvent("ContinueStatement");
-  }
-
-  void handleEmptyStatement(Token token) {
-    logEvent("EmptyStatement");
-  }
-
-  void beginAssert(Token assertKeyword, Assert kind) {}
-
-  void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
-      Token commaToken, Token semicolonToken) {
-    logEvent("Assert");
-  }
-
-  /** Called with either the token containing a double literal, or
-    * an immediately preceding "unary plus" token.
-    */
-  void handleLiteralDouble(Token token) {
-    logEvent("LiteralDouble");
-  }
-
-  /** Called with either the token containing an integer literal,
-    * or an immediately preceding "unary plus" token.
-    */
-  void handleLiteralInt(Token token) {
-    logEvent("LiteralInt");
-  }
-
-  void handleLiteralList(
-      int count, Token leftBracket, Token constKeyword, Token rightBracket) {
-    logEvent("LiteralList");
-  }
-
-  void handleLiteralSetOrMap(
-    int count,
-    Token leftBrace,
-    Token constKeyword,
-    Token rightBrace,
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry,
-  ) {
-    logEvent('LiteralSetOrMap');
-  }
-
-  void handleLiteralNull(Token token) {
-    logEvent("LiteralNull");
-  }
-
-  void handleNativeClause(Token nativeToken, bool hasName) {
-    logEvent("NativeClause");
-  }
-
-  void handleNamedArgument(Token colon) {
-    logEvent("NamedArgument");
-  }
-
-  void beginNewExpression(Token token) {}
-
-  void endNewExpression(Token token) {
-    logEvent("NewExpression");
-  }
-
-  void handleNoArguments(Token token) {
-    logEvent("NoArguments");
-  }
-
-  void handleNoConstructorReferenceContinuationAfterTypeArguments(Token token) {
-    logEvent("NoConstructorReferenceContinuationAfterTypeArguments");
-  }
-
-  void handleNoType(Token lastConsumed) {
-    logEvent("NoType");
-  }
-
-  void handleNoTypeVariables(Token token) {
-    logEvent("NoTypeVariables");
-  }
-
-  void handleOperator(Token token) {
-    logEvent("Operator");
-  }
-
-  void handleSymbolVoid(Token token) {
-    logEvent("SymbolVoid");
-  }
-
-  /// Handle the end of a construct of the form "operator <token>".
-  void handleOperatorName(Token operatorKeyword, Token token) {
-    logEvent("OperatorName");
-  }
-
-  /// Handle the end of a construct of the form "operator <token>"
-  /// where <token> is not a valid operator token.
-  void handleInvalidOperatorName(Token operatorKeyword, Token token) {
-    logEvent("InvalidOperatorName");
-  }
-
-  /// Handle the condition in a control structure:
-  /// - if statement
-  /// - do while loop
-  /// - switch statement
-  /// - while loop
-  void handleParenthesizedCondition(Token token) {
-    logEvent("ParenthesizedCondition");
-  }
-
-  /// Handle a parenthesized expression.
-  /// These may be within the condition expression of a control structure
-  /// but will not be the condition of a control structure.
-  void handleParenthesizedExpression(Token token) {
-    logEvent("ParenthesizedExpression");
-  }
-
-  /// Handle a construct of the form "identifier.identifier" occurring in a part
-  /// of the grammar where expressions in general are not allowed.
-  /// Substructures:
-  /// - Qualified identifier (before the period)
-  /// - Identifier (after the period)
-  void handleQualified(Token period) {
-    logEvent("Qualified");
-  }
-
-  void handleStringPart(Token token) {
-    logEvent("StringPart");
-  }
-
-  void handleSuperExpression(Token token, IdentifierContext context) {
-    logEvent("SuperExpression");
-  }
-
-  void beginSwitchCase(int labelCount, int expressionCount, Token firstToken) {}
-
-  void endSwitchCase(
-      int labelCount,
-      int expressionCount,
-      Token defaultKeyword,
-      Token colonAfterDefault,
-      int statementCount,
-      Token firstToken,
-      Token endToken) {
-    logEvent("SwitchCase");
-  }
-
-  void handleThisExpression(Token token, IdentifierContext context) {
-    logEvent("ThisExpression");
-  }
-
-  void handleUnaryPostfixAssignmentExpression(Token token) {
-    logEvent("UnaryPostfixAssignmentExpression");
-  }
-
-  void handleUnaryPrefixExpression(Token token) {
-    logEvent("UnaryPrefixExpression");
-  }
-
-  void handleUnaryPrefixAssignmentExpression(Token token) {
-    logEvent("UnaryPrefixAssignmentExpression");
-  }
-
-  void beginFormalParameterDefaultValueExpression() {}
-
-  void endFormalParameterDefaultValueExpression() {
-    logEvent("FormalParameterDefaultValueExpression");
-  }
-
-  void handleValuedFormalParameter(Token equals, Token token) {
-    logEvent("ValuedFormalParameter");
-  }
-
-  void handleFormalParameterWithoutValue(Token token) {
-    logEvent("FormalParameterWithoutValue");
-  }
-
-  void handleVoidKeyword(Token token) {
-    logEvent("VoidKeyword");
-  }
-
-  void beginYieldStatement(Token token) {}
-
-  void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
-    logEvent("YieldStatement");
-  }
-
-  /// The parser noticed a syntax error, but was able to recover from it. The
-  /// error should be reported using the [message], and the code between the
-  /// beginning of the [startToken] and the end of the [endToken] should be
-  /// highlighted. The [startToken] and [endToken] can be the same token.
-  void handleRecoverableError(
-      Message message, Token startToken, Token endToken) {}
-
-  /// The parser encountered an [ErrorToken] representing an error
-  /// from the scanner but recovered from it. By default, the error is reported
-  /// by calling [handleRecoverableError] with the message associated
-  /// with the error [token].
-  void handleErrorToken(ErrorToken token) {
-    handleRecoverableError(token.assertionMessage, token, token);
-  }
-
-  @override
-  void handleUnescapeError(
-      Message message, Token location, int stringOffset, int length) {
-    handleRecoverableError(message, location, location);
-  }
-
-  /// Signals to the listener that the previous statement contained a semantic
-  /// error (described by the given [message]). This method can also be called
-  /// after [handleExpressionFunctionBody], in which case it signals that the
-  /// implicit return statement of the function contained a semantic error.
-  void handleInvalidStatement(Token token, Message message) {
-    handleRecoverableError(message, token, token);
-  }
-
-  void handleScript(Token token) {
-    logEvent("Script");
-  }
-
-  /// A type has been just parsed, and the parser noticed that the next token
-  /// has a type substitution comment /*=T*. So, the type that has been just
-  /// parsed should be discarded, and a new type should be parsed instead.
-  void discardTypeReplacedWithCommentTypeAssign() {}
-
-  /// A single comment reference has been found
-  /// where [referenceSource] is the text between the `[` and `]`
-  /// and [referenceOffset] is the character offset in the token stream.
-  ///
-  /// This event is generated by the parser when the parser's
-  /// `parseCommentReferences` method is called. For further processing,
-  /// a listener may scan the [referenceSource] and then pass the resulting
-  /// token stream to the parser's `parseOneCommentReference` method.
-  void handleCommentReferenceText(String referenceSource, int referenceOffset) {
-    logEvent("CommentReferenceText");
-  }
-
-  /// A single comment reference has been parsed.
-  /// * [newKeyword] may be null.
-  /// * [prefix] and [period] are either both tokens or both `null`.
-  /// * [token] can be an identifier or an operator.
-  ///
-  /// 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) {}
-
-  /// This event is generated by the parser when the parser's
-  /// `parseOneCommentReference` method is called.
-  void handleNoCommentReference() {}
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
deleted file mode 100644
index c29fb9a..0000000
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info.dart
+++ /dev/null
@@ -1,77 +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 '../scanner.dart';
-import 'identifier_context.dart';
-import 'literal_entry_info_impl.dart';
-import 'parser.dart';
-import 'util.dart';
-
-/// [simpleEntry] is the first step for parsing a literal entry
-/// without any control flow or spread collection operator.
-const LiteralEntryInfo simpleEntry = const LiteralEntryInfo(true, 0);
-
-/// [LiteralEntryInfo] represents steps for processing an entry
-/// in a literal list, map, or set. These steps will handle parsing
-/// both control flow and spreadable operators, and indicate
-/// when the client should parse the literal entry.
-///
-/// Clients should parse a single entry in a list, set, or map like this:
-/// ```
-///    LiteralEntryInfo info = computeLiteralEntry(token);
-///    while (info != null) {
-///      if (info.hasEntry) {
-///        ... parse expression (`:` expression)? ...
-///        token = lastConsumedToken;
-///      } else {
-///        token = info.parse(token, parser);
-///      }
-///      info = info.computeNext(token);
-///    }
-/// ```
-class LiteralEntryInfo {
-  /// `true` if an entry should be parsed by the caller
-  /// or `false` if this object's [parse] method should be called.
-  final bool hasEntry;
-
-  /// Used for recovery, this indicates
-  /// +1 for an `if` condition and -1 for `else`.
-  final int ifConditionDelta;
-
-  const LiteralEntryInfo(this.hasEntry, this.ifConditionDelta);
-
-  /// Parse the control flow and spread collection aspects of this entry.
-  Token parse(Token token, Parser parser) {
-    throw hasEntry
-        ? 'Internal Error: should not call parse'
-        : 'Internal Error: $runtimeType should implement parse';
-  }
-
-  /// Returns the next step when parsing an entry or `null` if none.
-  LiteralEntryInfo computeNext(Token token) => null;
-}
-
-/// Compute the [LiteralEntryInfo] for the literal list, map, or set entry.
-LiteralEntryInfo computeLiteralEntry(Token token) {
-  Token next = token.next;
-  if (optional('if', next)) {
-    return ifCondition;
-  } else if (optional('for', next) ||
-      (optional('await', next) && optional('for', next.next))) {
-    return new ForCondition();
-  } else if (optional('...', next) || optional('...?', next)) {
-    return spreadOperator;
-  }
-  return simpleEntry;
-}
-
-/// Return `true` if the given [token] should be treated like the start of
-/// a literal entry in a list, set, or map for the purposes of recovery.
-bool looksLikeLiteralEntry(Token token) =>
-    looksLikeExpressionStart(token) ||
-    optional('...', token) ||
-    optional('...?', token) ||
-    optional('if', token) ||
-    optional('for', token) ||
-    (optional('await', token) && optional('for', token.next));
diff --git a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
deleted file mode 100644
index 313d580..0000000
--- a/pkg/front_end/lib/src/fasta/parser/literal_entry_info_impl.dart
+++ /dev/null
@@ -1,289 +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 '../../scanner/token.dart';
-import 'literal_entry_info.dart';
-import 'parser.dart';
-import 'util.dart';
-
-/// [ifCondition] is the first step for parsing a literal entry
-/// starting with `if` control flow.
-const LiteralEntryInfo ifCondition = const IfCondition();
-
-/// [spreadOperator] is the first step for parsing a literal entry
-/// preceded by a '...' spread operator.
-const LiteralEntryInfo spreadOperator = const SpreadOperator();
-
-/// The first step when processing a `for` control flow collection entry.
-class ForCondition extends LiteralEntryInfo {
-  bool inStyle;
-
-  ForCondition() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    Token next = token.next;
-    Token awaitToken;
-    if (optional('await', next)) {
-      awaitToken = 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 = parser.parseForLoopPartsMid(token, awaitToken, forToken);
-
-    if (optional('in', token.next) || optional(':', token.next)) {
-      // Process `for ( ... in ... )`
-      inStyle = true;
-      token = parser.parseForInLoopPartsRest(
-          token, awaitToken, forToken, identifier);
-    } else {
-      // Process `for ( ... ; ... ; ... )`
-      inStyle = false;
-      token = parser.parseForLoopPartsRest(token, forToken, awaitToken);
-    }
-    return token;
-  }
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    Token next = token.next;
-    if (optional('for', next) ||
-        (optional('await', next) && optional('for', next.next))) {
-      return new Nested(
-        new ForCondition(),
-        inStyle ? const ForInComplete() : const ForComplete(),
-      );
-    } else if (optional('if', next)) {
-      return new Nested(
-        ifCondition,
-        inStyle ? const ForInComplete() : const ForComplete(),
-      );
-    } else if (optional('...', next) || optional('...?', next)) {
-      return inStyle ? const ForInSpread() : const ForSpread();
-    }
-    return inStyle ? const ForInEntry() : const ForEntry();
-  }
-}
-
-/// A step for parsing a spread collection
-/// as the "for" control flow's expression.
-class ForSpread extends SpreadOperator {
-  const ForSpread();
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const ForComplete();
-  }
-}
-
-/// A step for parsing a spread collection
-/// as the "for-in" control flow's expression.
-class ForInSpread extends SpreadOperator {
-  const ForInSpread();
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const ForInComplete();
-  }
-}
-
-/// A step for parsing a literal list, set, or map entry
-/// as the "for" control flow's expression.
-class ForEntry extends LiteralEntryInfo {
-  const ForEntry() : super(true, 0);
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const ForComplete();
-  }
-}
-
-/// A step for parsing a literal list, set, or map entry
-/// as the "for-in" control flow's expression.
-class ForInEntry extends LiteralEntryInfo {
-  const ForInEntry() : super(true, 0);
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const ForInComplete();
-  }
-}
-
-class ForComplete extends LiteralEntryInfo {
-  const ForComplete() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    parser.listener.endForControlFlow(token);
-    return token;
-  }
-}
-
-class ForInComplete extends LiteralEntryInfo {
-  const ForInComplete() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    parser.listener.endForInControlFlow(token);
-    return token;
-  }
-}
-
-/// The first step when processing an `if` control flow collection entry.
-class IfCondition extends LiteralEntryInfo {
-  const IfCondition() : super(false, 1);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    final Token ifToken = token.next;
-    assert(optional('if', ifToken));
-    parser.listener.beginIfControlFlow(ifToken);
-    Token result = parser.ensureParenthesizedCondition(ifToken);
-    parser.listener.beginThenControlFlow(result);
-    return result;
-  }
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    Token next = token.next;
-    if (optional('for', 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());
-    } else if (optional('...', next) || optional('...?', next)) {
-      return const IfSpread();
-    }
-    return const IfEntry();
-  }
-}
-
-/// A step for parsing a spread collection
-/// as the `if` control flow's then-expression.
-class IfSpread extends SpreadOperator {
-  const IfSpread();
-
-  @override
-  LiteralEntryInfo computeNext(Token token) => const IfComplete();
-}
-
-/// A step for parsing a literal list, set, or map entry
-/// as the `if` control flow's then-expression.
-class IfEntry extends LiteralEntryInfo {
-  const IfEntry() : super(true, 0);
-
-  @override
-  LiteralEntryInfo computeNext(Token token) => const IfComplete();
-}
-
-class IfComplete extends LiteralEntryInfo {
-  const IfComplete() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    if (!optional('else', token.next)) {
-      parser.listener.endIfControlFlow(token);
-    }
-    return token;
-  }
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return optional('else', token.next) ? const IfElse() : null;
-  }
-}
-
-/// A step for parsing the `else` portion of an `if` control flow.
-class IfElse extends LiteralEntryInfo {
-  const IfElse() : super(false, -1);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    Token elseToken = token.next;
-    assert(optional('else', elseToken));
-    parser.listener.handleElseControlFlow(elseToken);
-    return elseToken;
-  }
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    assert(optional('else', token));
-    Token next = token.next;
-    if (optional('for', 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());
-    } else if (optional('...', next) || optional('...?', next)) {
-      return const ElseSpread();
-    }
-    return const ElseEntry();
-  }
-}
-
-class ElseSpread extends SpreadOperator {
-  const ElseSpread();
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const IfElseComplete();
-  }
-}
-
-class ElseEntry extends LiteralEntryInfo {
-  const ElseEntry() : super(true, 0);
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    return const IfElseComplete();
-  }
-}
-
-class IfElseComplete extends LiteralEntryInfo {
-  const IfElseComplete() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    parser.listener.endIfElseControlFlow(token);
-    return token;
-  }
-}
-
-/// The first step when processing a spread entry.
-class SpreadOperator extends LiteralEntryInfo {
-  const SpreadOperator() : super(false, 0);
-
-  @override
-  Token parse(Token token, Parser parser) {
-    final Token operator = token.next;
-    assert(optional('...', operator) || optional('...?', operator));
-    token = parser.parseExpression(operator);
-    parser.listener.handleSpreadExpression(operator);
-    return token;
-  }
-}
-
-class Nested extends LiteralEntryInfo {
-  LiteralEntryInfo nestedStep;
-  final LiteralEntryInfo lastStep;
-
-  Nested(this.nestedStep, this.lastStep) : super(false, 0);
-
-  @override
-  bool get hasEntry => nestedStep.hasEntry;
-
-  @override
-  Token parse(Token token, Parser parser) => nestedStep.parse(token, parser);
-
-  @override
-  LiteralEntryInfo computeNext(Token token) {
-    nestedStep = nestedStep.computeNext(token);
-    return nestedStep != null ? this : lastStep;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/loop_state.dart b/pkg/front_end/lib/src/fasta/parser/loop_state.dart
deleted file mode 100644
index b6443b8..0000000
--- a/pkg/front_end/lib/src/fasta/parser/loop_state.dart
+++ /dev/null
@@ -1,11 +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.
-
-library fasta.parser.loop_state;
-
-enum LoopState {
-  OutsideLoop,
-  InsideSwitch, // `break` statement allowed
-  InsideLoop, // `break` and `continue` statements allowed
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/member_kind.dart b/pkg/front_end/lib/src/fasta/parser/member_kind.dart
deleted file mode 100644
index 72da388..0000000
--- a/pkg/front_end/lib/src/fasta/parser/member_kind.dart
+++ /dev/null
@@ -1,49 +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.
-
-library fasta.parser.member_kind;
-
-enum MemberKind {
-  /// A catch block, not a real member.
-  Catch,
-
-  /// A factory
-  Factory,
-
-  /// Old-style typedef.
-  FunctionTypeAlias,
-
-  /// Old-style function-typed parameter, not a real member.
-  FunctionTypedParameter,
-
-  /// A generalized function type, not a real member.
-  GeneralizedFunctionType,
-
-  /// A local function.
-  Local,
-
-  /// A non-static method in a class (including constructors).
-  NonStaticMethod,
-
-  /// A static method in a class.
-  StaticMethod,
-
-  /// A top-level method.
-  TopLevelMethod,
-
-  /// A non-static method in an extension.
-  ExtensionNonStaticMethod,
-
-  /// A static method in an extension.
-  ExtensionStaticMethod,
-
-  /// An instance field in a class.
-  NonStaticField,
-
-  /// A static field in a class.
-  StaticField,
-
-  /// A top-level field.
-  TopLevelField,
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
deleted file mode 100644
index 8d9fd2f..0000000
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ /dev/null
@@ -1,482 +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 '../../scanner/token.dart' show Keyword, Token;
-import '../messages.dart' as fasta;
-import 'formal_parameter_kind.dart';
-import 'member_kind.dart' show MemberKind;
-import 'parser.dart' show Parser;
-import 'util.dart' show optional;
-
-bool isModifier(Token token) {
-  if (!token.isModifier) {
-    return false;
-  } else if (token.type.isBuiltIn) {
-    // A built-in keyword can only be a modifier as long as it is
-    // followed by another keyword or an identifier. Otherwise, it is the
-    // identifier.
-    //
-    // For example, `external` is a modifier in this declaration:
-    //   external Foo foo();
-    // but is the identifier in this declaration
-    //   external() => true;
-    // and in
-    //   for (final external in list) { }
-    Token next = token.next;
-    Keyword keyword = next.keyword;
-    if (keyword == null && !next.isIdentifier || keyword == Keyword.IN) {
-      return false;
-    }
-  }
-  return true;
-}
-
-/// This class is used to parse modifiers in most locations where modifiers
-/// 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;
-
-  // Set `true` when parsing modifiers after the `factory` token.
-  bool afterFactory = false;
-
-  // TODO(danrubel): Replace [ModifierRecoveryContext] and [ModifierContext]
-  // with this class.
-
-  ModifierRecoveryContext(this.parser);
-
-  set staticOrCovariant(Token staticOrCovariant) {
-    if (staticOrCovariant == null) {
-      covariantToken = null;
-      staticToken = null;
-    } else if (optional('covariant', staticOrCovariant)) {
-      covariantToken = staticOrCovariant;
-      staticToken = null;
-    } else if (optional('static', staticOrCovariant)) {
-      covariantToken = null;
-      staticToken = staticOrCovariant;
-    } else {
-      throw "Internal error: "
-          "Unexpected staticOrCovariant '$staticOrCovariant'.";
-    }
-  }
-
-  Token get varFinalOrConst => varToken ?? finalToken ?? constToken;
-
-  set varFinalOrConst(Token varFinalOrConst) {
-    if (varFinalOrConst == null) {
-      varToken = null;
-      finalToken = null;
-      constToken = null;
-    } else if (optional('var', varFinalOrConst)) {
-      varToken = varFinalOrConst;
-      finalToken = null;
-      constToken = null;
-    } else if (optional('final', varFinalOrConst)) {
-      varToken = null;
-      finalToken = varFinalOrConst;
-      constToken = null;
-    } else if (optional('const', varFinalOrConst)) {
-      varToken = null;
-      finalToken = null;
-      constToken = varFinalOrConst;
-    } else {
-      throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
-    }
-  }
-
-  /// Parse modifiers for class methods and fields.
-  Token parseClassMemberModifiers(Token token) {
-    token = parseModifiers(token);
-    if (abstractToken != null) {
-      parser.reportRecoverableError(
-          abstractToken, fasta.messageAbstractClassMember);
-    }
-    reportExtraneousModifier(requiredToken);
-    return token;
-  }
-
-  /// Parse modifiers for formal parameters.
-  Token parseFormalParameterModifiers(
-      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
-    token = parseModifiers(token);
-
-    if (parameterKind != FormalParameterKind.optionalNamed) {
-      reportExtraneousModifier(requiredToken);
-    }
-    if (memberKind == MemberKind.StaticMethod ||
-        memberKind == MemberKind.TopLevelMethod) {
-      reportExtraneousModifier(this.covariantToken);
-      this.covariantToken = null;
-    } else if (memberKind == MemberKind.ExtensionNonStaticMethod ||
-        memberKind == MemberKind.ExtensionStaticMethod) {
-      reportExtraneousModifierInExtension(this.covariantToken);
-      this.covariantToken = null;
-    }
-    if (constToken != null) {
-      reportExtraneousModifier(constToken);
-    } else if (memberKind == MemberKind.GeneralizedFunctionType) {
-      if (varFinalOrConst != null) {
-        parser.reportRecoverableError(
-            varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-      }
-    }
-    reportExtraneousModifier(abstractToken);
-    reportExtraneousModifier(externalToken);
-    reportExtraneousModifier(lateToken);
-    reportExtraneousModifier(staticToken);
-    return token;
-  }
-
-  /// Parse modifiers after the `factory` token.
-  Token parseModifiersAfterFactory(Token token) {
-    afterFactory = true;
-    token = parseModifiers(token);
-    if (abstractToken != null) {
-      parser.reportRecoverableError(
-          abstractToken, fasta.messageAbstractClassMember);
-    }
-    reportExtraneousModifier(lateToken);
-    reportExtraneousModifier(requiredToken);
-    return token;
-  }
-
-  /// Parse modifiers for top level functions and fields.
-  Token parseTopLevelModifiers(Token token) {
-    token = parseModifiers(token);
-    reportExtraneousModifier(abstractToken);
-    reportExtraneousModifier(covariantToken);
-    reportExtraneousModifier(requiredToken);
-    reportExtraneousModifier(staticToken);
-    return token;
-  }
-
-  /// Parse modifiers for variable declarations.
-  Token parseVariableDeclarationModifiers(Token token) {
-    token = parseModifiers(token);
-    reportExtraneousModifier(abstractToken);
-    reportExtraneousModifier(covariantToken);
-    reportExtraneousModifier(externalToken);
-    reportExtraneousModifier(requiredToken);
-    reportExtraneousModifier(staticToken);
-    return token;
-  }
-
-  /// Parse modifiers during recovery when modifiers are out of order
-  /// or invalid. Typically clients call methods like
-  /// [parseClassMemberModifiers] which in turn calls this method,
-  /// rather than calling this method directly.
-  ///
-  /// The various modifier token parameters represent tokens of modifiers
-  /// that have already been parsed prior to recovery. The [staticOrCovariant]
-  /// parameter is for convenience if caller has a token that may be either
-  /// `static` or `covariant`. The first non-null parameter of
-  /// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
-  /// in that order, and the others ignored.
-  Token parseModifiers(Token token) {
-    // Process invalid and out-of-order modifiers
-    Token next = token.next;
-    while (true) {
-      final String value = next.stringValue;
-      if (isModifier(next)) {
-        if (identical('abstract', value)) {
-          token = parseAbstract(token);
-        } else if (identical('const', value)) {
-          token = parseConst(token);
-        } else if (identical('covariant', value)) {
-          token = parseCovariant(token);
-        } else if (identical('external', value)) {
-          token = parseExternal(token);
-        } else if (identical('final', value)) {
-          token = parseFinal(token);
-        } else if (identical('late', value)) {
-          token = parseLate(token);
-        } else if (identical('required', value)) {
-          token = parseRequired(token);
-        } else if (identical('static', value)) {
-          token = parseStatic(token);
-        } else if (identical('var', value)) {
-          token = parseVar(token);
-        } else {
-          throw 'Internal Error: Unhandled modifier: $value';
-        }
-      } else if (afterFactory && identical('factory', value)) {
-        parser.reportRecoverableErrorWithToken(
-            next, fasta.templateDuplicatedModifier);
-        token = next;
-      } else {
-        break;
-      }
-      next = token.next;
-    }
-    return token;
-  }
-
-  Token parseAbstract(Token token) {
-    Token next = token.next;
-    assert(optional('abstract', next));
-    if (abstractToken == null) {
-      abstractToken = next;
-      return next;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        next, fasta.templateDuplicatedModifier);
-    return next;
-  }
-
-  Token parseConst(Token token) {
-    Token next = token.next;
-    assert(optional('const', next));
-    if (varFinalOrConst == null && covariantToken == null) {
-      constToken = next;
-
-      if (afterFactory) {
-        reportModifierOutOfOrder(next, 'factory');
-      } else if (lateToken != null) {
-        reportConflictingModifiers(next, lateToken);
-      }
-      return next;
-    }
-
-    // Recovery
-    if (constToken != null) {
-      parser.reportRecoverableErrorWithToken(
-          next, fasta.templateDuplicatedModifier);
-    } else if (covariantToken != null) {
-      reportConflictingModifiers(next, covariantToken);
-    } else if (finalToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndFinal);
-    } else if (varToken != null) {
-      reportConflictingModifiers(next, varToken);
-    } else {
-      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
-    }
-    return next;
-  }
-
-  Token parseCovariant(Token token) {
-    Token next = token.next;
-    assert(optional('covariant', next));
-    if (constToken == null &&
-        covariantToken == null &&
-        staticToken == null &&
-        !afterFactory) {
-      covariantToken = next;
-
-      if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
-      } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
-      } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
-      }
-      return next;
-    }
-
-    // Recovery
-    if (covariantToken != null) {
-      parser.reportRecoverableErrorWithToken(
-          next, fasta.templateDuplicatedModifier);
-    } else if (afterFactory) {
-      reportExtraneousModifier(next);
-    } else if (constToken != null) {
-      reportConflictingModifiers(next, constToken);
-    } else if (staticToken != null) {
-      parser.reportRecoverableError(next, fasta.messageCovariantAndStatic);
-    } else {
-      throw 'Internal Error: Unhandled recovery: $next';
-    }
-    return next;
-  }
-
-  Token parseExternal(Token token) {
-    Token next = token.next;
-    assert(optional('external', next));
-    if (externalToken == null) {
-      externalToken = next;
-
-      if (afterFactory) {
-        reportModifierOutOfOrder(next, 'factory');
-      } else if (constToken != null) {
-        reportModifierOutOfOrder(next, constToken.lexeme);
-      } else if (staticToken != null) {
-        reportModifierOutOfOrder(next, staticToken.lexeme);
-      } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
-      }
-      return next;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        next, fasta.templateDuplicatedModifier);
-    return next;
-  }
-
-  Token parseFinal(Token token) {
-    Token next = token.next;
-    assert(optional('final', next));
-    if (varFinalOrConst == null && !afterFactory) {
-      finalToken = next;
-      return next;
-    }
-
-    // Recovery
-    if (finalToken != null) {
-      parser.reportRecoverableErrorWithToken(
-          next, fasta.templateDuplicatedModifier);
-    } else if (afterFactory) {
-      reportExtraneousModifier(next);
-    } else if (constToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndFinal);
-    } else if (varToken != null) {
-      parser.reportRecoverableError(next, fasta.messageFinalAndVar);
-    } else if (lateToken != null) {
-      reportModifierOutOfOrder(next, lateToken.lexeme);
-    } else {
-      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
-    }
-    return next;
-  }
-
-  Token parseLate(Token token) {
-    Token next = token.next;
-    assert(optional('late', next));
-    if (lateToken == null) {
-      lateToken = next;
-
-      if (constToken != null) {
-        reportConflictingModifiers(next, constToken);
-      } else if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
-      } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
-      }
-      return next;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        next, fasta.templateDuplicatedModifier);
-    return next;
-  }
-
-  Token parseRequired(Token token) {
-    Token next = token.next;
-    assert(optional('required', next));
-    if (requiredToken == null) {
-      requiredToken = next;
-
-      if (constToken != null) {
-        reportModifierOutOfOrder(requiredToken, constToken.lexeme);
-      } else if (covariantToken != null) {
-        reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
-      } else if (finalToken != null) {
-        reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
-      } else if (varToken != null) {
-        reportModifierOutOfOrder(requiredToken, varToken.lexeme);
-      }
-      return next;
-    }
-
-    // Recovery
-    parser.reportRecoverableErrorWithToken(
-        next, fasta.templateDuplicatedModifier);
-    return next;
-  }
-
-  Token parseStatic(Token token) {
-    Token next = token.next;
-    assert(optional('static', next));
-    if (covariantToken == null && staticToken == null && !afterFactory) {
-      staticToken = next;
-
-      if (constToken != null) {
-        reportModifierOutOfOrder(next, constToken.lexeme);
-      } else if (finalToken != null) {
-        reportModifierOutOfOrder(next, finalToken.lexeme);
-      } else if (varToken != null) {
-        reportModifierOutOfOrder(next, varToken.lexeme);
-      } else if (lateToken != null) {
-        reportModifierOutOfOrder(next, lateToken.lexeme);
-      }
-      return next;
-    }
-
-    // Recovery
-    if (covariantToken != null) {
-      parser.reportRecoverableError(next, fasta.messageCovariantAndStatic);
-    } else if (staticToken != null) {
-      parser.reportRecoverableErrorWithToken(
-          next, fasta.templateDuplicatedModifier);
-    } else if (afterFactory) {
-      reportExtraneousModifier(next);
-    } else {
-      throw 'Internal Error: Unhandled recovery: $next';
-    }
-    return next;
-  }
-
-  Token parseVar(Token token) {
-    Token next = token.next;
-    assert(optional('var', next));
-    if (varFinalOrConst == null && !afterFactory) {
-      varToken = next;
-      return next;
-    }
-
-    // Recovery
-    if (varToken != null) {
-      parser.reportRecoverableErrorWithToken(
-          next, fasta.templateDuplicatedModifier);
-    } else if (afterFactory) {
-      reportExtraneousModifier(next);
-    } else if (constToken != null) {
-      reportConflictingModifiers(next, constToken);
-    } else if (finalToken != null) {
-      parser.reportRecoverableError(next, fasta.messageFinalAndVar);
-    } else {
-      throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
-    }
-    return next;
-  }
-
-  void reportConflictingModifiers(Token modifier, Token earlierModifier) {
-    parser.reportRecoverableError(
-        modifier,
-        fasta.templateConflictingModifiers
-            .withArguments(modifier.lexeme, earlierModifier.lexeme));
-  }
-
-  void reportExtraneousModifier(Token modifier) {
-    if (modifier != null) {
-      parser.reportRecoverableErrorWithToken(
-          modifier, fasta.templateExtraneousModifier);
-    }
-  }
-
-  void reportExtraneousModifierInExtension(Token modifier) {
-    if (modifier != null) {
-      parser.reportRecoverableErrorWithToken(
-          modifier, fasta.templateExtraneousModifierInExtension);
-    }
-  }
-
-  void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
-    parser.reportRecoverableError(
-        modifier,
-        fasta.templateModifierOutOfOrder
-            .withArguments(modifier.lexeme, beforeModifier));
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
deleted file mode 100644
index 2a62ab6..0000000
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ /dev/null
@@ -1,6985 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.parser.parser;
-
-import '../fasta_codes.dart' show Message, Template;
-
-import '../fasta_codes.dart' as fasta;
-
-import '../scanner.dart' show ErrorToken, Token;
-
-import '../../scanner/token.dart'
-    show
-        ASSIGNMENT_PRECEDENCE,
-        BeginToken,
-        CASCADE_PRECEDENCE,
-        EQUALITY_PRECEDENCE,
-        Keyword,
-        POSTFIX_PRECEDENCE,
-        RELATIONAL_PRECEDENCE,
-        SELECTOR_PRECEDENCE,
-        SyntheticBeginToken,
-        SyntheticKeywordToken,
-        SyntheticStringToken,
-        SyntheticToken,
-        TokenType;
-
-import '../scanner/token_constants.dart'
-    show
-        BANG_EQ_EQ_TOKEN,
-        COMMA_TOKEN,
-        DOUBLE_TOKEN,
-        EOF_TOKEN,
-        EQ_EQ_EQ_TOKEN,
-        EQ_TOKEN,
-        FUNCTION_TOKEN,
-        HASH_TOKEN,
-        HEXADECIMAL_TOKEN,
-        IDENTIFIER_TOKEN,
-        INT_TOKEN,
-        KEYWORD_TOKEN,
-        LT_TOKEN,
-        OPEN_CURLY_BRACKET_TOKEN,
-        OPEN_PAREN_TOKEN,
-        OPEN_SQUARE_BRACKET_TOKEN,
-        SEMICOLON_TOKEN,
-        STRING_INTERPOLATION_IDENTIFIER_TOKEN,
-        STRING_INTERPOLATION_TOKEN,
-        STRING_TOKEN;
-
-import 'assert.dart' show Assert;
-
-import 'async_modifier.dart' show AsyncModifier;
-
-import 'declaration_kind.dart' show DeclarationKind;
-
-import 'directive_context.dart';
-
-import 'formal_parameter_kind.dart'
-    show
-        FormalParameterKind,
-        isMandatoryFormalParameterKind,
-        isOptionalPositionalFormalParameterKind;
-
-import 'forwarding_listener.dart' show ForwardingListener;
-
-import 'identifier_context.dart'
-    show IdentifierContext, looksLikeExpressionStart;
-
-import 'listener.dart' show Listener;
-
-import 'literal_entry_info.dart'
-    show
-        LiteralEntryInfo,
-        computeLiteralEntry,
-        looksLikeLiteralEntry,
-        simpleEntry;
-
-import 'loop_state.dart' show LoopState;
-
-import 'member_kind.dart' show MemberKind;
-
-import 'modifier_context.dart' show ModifierRecoveryContext, isModifier;
-
-import 'recovery_listeners.dart'
-    show
-        ClassHeaderRecoveryListener,
-        ImportRecoveryListener,
-        MixinHeaderRecoveryListener;
-
-import 'token_stream_rewriter.dart' show TokenStreamRewriter;
-
-import 'type_info.dart'
-    show
-        TypeInfo,
-        TypeParamOrArgInfo,
-        computeMethodTypeArguments,
-        computeType,
-        computeTypeParamOrArg,
-        isValidTypeReference,
-        noType,
-        noTypeParamOrArg;
-
-import 'util.dart'
-    show
-        findNonZeroLengthToken,
-        findPreviousNonZeroLengthToken,
-        isLetter,
-        isLetterOrDigit,
-        isOneOf,
-        isOneOfOrEof,
-        isWhitespace,
-        optional;
-
-/// An event generating parser of Dart programs. This parser expects all tokens
-/// in a linked list (aka a token stream).
-///
-/// The class [Scanner] is used to generate a token stream. See the file
-/// [scanner.dart](../scanner.dart).
-///
-/// Subclasses of the class [Listener] are used to listen to events.
-///
-/// Most methods of this class belong in one of four major categories: parse
-/// methods, peek methods, ensure methods, and skip methods.
-///
-/// Parse methods all have the prefix `parse`, generate events
-/// (by calling methods on [listener]), and return the next token to parse.
-/// Some exceptions to this last point are methods such as [parseFunctionBody]
-/// and [parseClassOrMixinOrExtensionBody] which return the last token parsed
-/// rather than the next token to be parsed.
-/// Parse methods are generally named `parseGrammarProductionSuffix`.
-/// The suffix can be one of `opt`, or `star`.
-/// `opt` means zero or one matches, `star` means zero or more matches.
-/// For example, [parseMetadataStar] corresponds to this grammar snippet:
-/// `metadata*`, and [parseArgumentsOpt] corresponds to: `arguments?`.
-///
-/// Peek methods all have the prefix `peek`, do not generate events
-/// (except for errors) and may return null.
-///
-/// Ensure methods all have the prefix `ensure` and may generate events.
-/// They return the current token, or insert and return a synthetic token
-/// if the current token does not match. For example,
-/// [ensureSemicolon] returns the current token if the current token is a
-/// semicolon, otherwise inserts a synthetic semicolon in the token stream
-/// before the current token and then returns that new synthetic token.
-///
-/// Skip methods are like parse methods, but all have the prefix `skip`
-/// and skip over some parts of the file being parsed.
-/// Typically, skip methods generate an event for the structure being skipped,
-/// but not for its substructures.
-///
-/// ## Current Token
-///
-/// The current token is always to be found in a formal parameter named
-/// `token`. This parameter should be the first as this increases the chance
-/// that a compiler will place it in a register.
-///
-/// ## Implementation Notes
-///
-/// The parser assumes that keywords, built-in identifiers, and other special
-/// words (pseudo-keywords) are all canonicalized. To extend the parser to
-/// recognize a new identifier, one should modify
-/// [keyword.dart](../scanner/keyword.dart) and ensure the identifier is added
-/// to the keyword table.
-///
-/// As a consequence of this, one should not use `==` to compare strings in the
-/// parser. One should favor the methods [optional] and [expect] to recognize
-/// keywords or identifiers. In some cases, it's possible to compare a token's
-/// `stringValue` using [identical], but normally [optional] will suffice.
-///
-/// Historically, we over-used identical, and when identical is used on objects
-/// other than strings, it can often be replaced by `==`.
-///
-/// ## Flexibility, Extensibility, and Specification
-///
-/// The parser is designed to be flexible and extensible. Its methods are
-/// designed to be overridden in subclasses, so it can be extended to handle
-/// unspecified language extension or experiments while everything in this file
-/// attempts to follow the specification (unless when it interferes with error
-/// recovery).
-///
-/// We achieve flexibility, extensible, and specification compliance by
-/// following a few rules-of-thumb:
-///
-/// 1. All methods in the parser should be public.
-///
-/// 2. The methods follow the specified grammar, and do not implement custom
-/// extensions, for example, `native`.
-///
-/// 3. The parser doesn't rewrite the token stream (when dealing with `>>`).
-///
-/// ### Implementing Extensions
-///
-/// For various reasons, some Dart language implementations have used
-/// custom/unspecified extensions to the Dart grammar. Examples of this
-/// includes diet parsing, patch files, `native` keyword, and generic
-/// comments. This class isn't supposed to implement any of these
-/// features. Instead it provides hooks for those extensions to be implemented
-/// in subclasses or listeners. Let's examine how diet parsing and `native`
-/// keyword is currently supported by Fasta.
-///
-/// #### Legacy Implementation of `native` Keyword
-///
-/// TODO(ahe,danrubel): Remove this section.
-///
-/// Both dart2js and the Dart VM have used the `native` keyword to mark methods
-/// that couldn't be implemented in the Dart language and needed to be
-/// implemented in JavaScript or C++, respectively. An example of the syntax
-/// extension used by the Dart VM is:
-///
-///     nativeFunction() native "NativeFunction";
-///
-/// When attempting to parse this function, the parser eventually calls
-/// [parseFunctionBody]. This method will report an unrecoverable error to the
-/// listener with the code [fasta.messageExpectedFunctionBody]. The listener can
-/// then look at the error code and the token and use the methods in
-/// [native_support.dart](native_support.dart) to parse the native syntax.
-///
-/// #### Implementation of Diet Parsing
-///
-/// We call it _diet_ _parsing_ when the parser skips parts of a file. Both
-/// dart2js and the Dart VM have been relying on this from early on as it allows
-/// them to more quickly compile small programs that use small parts of big
-/// libraries. It's also become an integrated part of how Fasta builds up
-/// outlines before starting to parse method bodies.
-///
-/// When looking through this parser, you'll find a number of unused methods
-/// starting with `skip`. These methods are only used by subclasses, such as
-/// [ClassMemberParser](class_member_parser.dart) and
-/// [TopLevelParser](top_level_parser.dart). These methods violate the
-/// principle above about following the specified grammar, and originally lived
-/// in subclasses. However, we realized that these methods were so widely used
-/// and hard to maintain in subclasses, that it made sense to move them here.
-///
-/// ### Specification and Error Recovery
-///
-/// To improve error recovery, the parser will inform the listener of
-/// recoverable errors and continue to parse.  An example of a recoverable
-/// error is:
-///
-///     Error: Asynchronous for-loop can only be used in 'async' or 'async*'...
-///     main() { await for (var x in []) {} }
-///              ^^^^^
-///
-/// ### Legacy Error Recovery
-///
-/// What's described below will be phased out in preference of the parser
-/// reporting and recovering from syntax errors. The motivation for this is
-/// that we have multiple listeners that use the parser, and this will ensure
-/// consistency.
-///
-/// For unrecoverable errors, the parser will ask the listener for help to
-/// recover from the error. We haven't made much progress on these kinds of
-/// errors, so in most cases, the parser aborts by skipping to the end of file.
-///
-/// Historically, this parser has been rather lax in what it allows, and
-/// deferred the enforcement of some syntactical rules to subsequent phases. It
-/// doesn't matter how we got there, only that we've identified that it's
-/// easier if the parser reports as many errors it can, but informs the
-/// listener if the error is recoverable or not.
-class Parser {
-  Listener listener;
-
-  Uri get uri => listener.uri;
-
-  bool mayParseFunctionExpressions = true;
-
-  /// Represents parser state: what asynchronous syntax is allowed in the
-  /// function being currently parsed. In rare situations, this can be set by
-  /// external clients, for example, to parse an expression outside a function.
-  AsyncModifier asyncState = AsyncModifier.Sync;
-
-  // TODO(danrubel): The [loopState] and associated functionality in the
-  // [Parser] duplicates work that the resolver needs to do when resolving
-  // break/continue targets. Long term, this state and functionality will be
-  // removed from the [Parser] class and the resolver will be responsible
-  // for generating all break/continue error messages.
-
-  /// Represents parser state: whether parsing outside a loop,
-  /// inside a loop, or inside a switch. This is used to determine whether
-  /// break and continue statements are allowed.
-  LoopState loopState = LoopState.OutsideLoop;
-
-  /// A rewriter for inserting synthetic tokens.
-  /// Access using [rewriter] for lazy initialization.
-  TokenStreamRewriter cachedRewriter;
-
-  TokenStreamRewriter get rewriter {
-    cachedRewriter ??= new TokenStreamRewriter();
-    return cachedRewriter;
-  }
-
-  Parser(this.listener);
-
-  bool get inGenerator {
-    return asyncState == AsyncModifier.AsyncStar ||
-        asyncState == AsyncModifier.SyncStar;
-  }
-
-  bool get inAsync {
-    return asyncState == AsyncModifier.Async ||
-        asyncState == AsyncModifier.AsyncStar;
-  }
-
-  bool get inPlainSync => asyncState == AsyncModifier.Sync;
-
-  bool get isBreakAllowed => loopState != LoopState.OutsideLoop;
-
-  bool get isContinueAllowed => loopState == LoopState.InsideLoop;
-
-  bool get isContinueWithLabelAllowed => loopState != LoopState.OutsideLoop;
-
-  /// Parse a compilation unit.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  ///
-  /// ```
-  /// libraryDefinition:
-  ///   scriptTag?
-  ///   libraryName?
-  ///   importOrExport*
-  ///   partDirective*
-  ///   topLevelDefinition*
-  /// ;
-  ///
-  /// partDeclaration:
-  ///   partHeader topLevelDefinition*
-  /// ;
-  /// ```
-  Token parseUnit(Token token) {
-    // Skip over error tokens and report them at the end
-    // so that the parser has the chance to adjust the error location.
-    Token errorToken = token;
-    token = skipErrorTokens(errorToken);
-
-    listener.beginCompilationUnit(token);
-    int count = 0;
-    DirectiveContext directiveState = new DirectiveContext();
-    token = syntheticPreviousToken(token);
-    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;
-      token = parseTopLevelDeclarationImpl(token, directiveState);
-      listener.endTopLevelDeclaration(token.next);
-      count++;
-      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;
-        listener.beginMetadataStar(token);
-        listener.endMetadataStar(0);
-        reportRecoverableErrorWithToken(
-            token, fasta.templateExpectedDeclaration);
-        listener.handleInvalidTopLevelDeclaration(token);
-        listener.endTopLevelDeclaration(token.next);
-        count++;
-      }
-    }
-    token = token.next;
-    reportAllErrorTokens(errorToken);
-    listener.endCompilationUnit(count, token);
-    // Clear fields that could lead to memory leak.
-    cachedRewriter = null;
-    return token;
-  }
-
-  /// This method exists for analyzer compatibility only
-  /// and will be removed once analyzer/fasta integration is complete.
-  ///
-  /// Similar to [parseUnit], this method parses a compilation unit,
-  /// but stops when it reaches the first declaration or EOF.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseDirectives(Token token) {
-    listener.beginCompilationUnit(token);
-    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;
-
-      // If a built-in keyword is being used as function name, then stop.
-      if (identical(nextValue, '.') ||
-          identical(nextValue, '<') ||
-          identical(nextValue, '(')) {
-        break;
-      }
-
-      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;
-        if (identical(value, 'import')) {
-          directiveState?.checkImport(this, keyword);
-          token = parseImport(keyword);
-        } else if (identical(value, 'export')) {
-          directiveState?.checkExport(this, keyword);
-          token = parseExport(keyword);
-        } else if (identical(value, 'library')) {
-          directiveState?.checkLibrary(this, keyword);
-          token = parseLibraryName(keyword);
-        } else if (identical(value, 'part')) {
-          token = parsePartOrPartOf(keyword, directiveState);
-        } else if (identical(value, ';')) {
-          token = start;
-        } else {
-          listener.handleDirectivesOnly();
-          break;
-        }
-      }
-      listener.endTopLevelDeclaration(token.next);
-    }
-    token = token.next;
-    listener.endCompilationUnit(count, token);
-    // Clear fields that could lead to memory leak.
-    cachedRewriter = null;
-    return token;
-  }
-
-  /// Parse a top-level declaration.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseTopLevelDeclaration(Token token) {
-    token =
-        parseTopLevelDeclarationImpl(syntheticPreviousToken(token), null).next;
-    listener.endTopLevelDeclaration(token);
-    return token;
-  }
-
-  /// ```
-  /// topLevelDefinition:
-  ///   classDefinition |
-  ///   enumType |
-  ///   typeAlias |
-  ///   'external'? functionSignature ';' |
-  ///   'external'? getterSignature ';' |
-  ///   'external''? setterSignature ';' |
-  ///   functionSignature functionBody |
-  ///   returnType? 'get' identifier functionBody |
-  ///   returnType? 'set' identifier formalParameterList functionBody |
-  ///   ('final' | 'const') type? staticFinalDeclarationList ';' |
-  ///   variableDeclaration ';'
-  /// ;
-  /// ```
-  Token parseTopLevelDeclarationImpl(
-      Token token, DirectiveContext directiveState) {
-    token = parseMetadataStar(token);
-    Token next = token.next;
-    if (next.isTopLevelKeyword) {
-      return parseTopLevelKeywordDeclaration(token, next, directiveState);
-    }
-    Token start = token;
-    // Skip modifiers to find a top level keyword or identifier
-    if (next.isModifier) {
-      if (optional('var', next) ||
-          optional('late', next) ||
-          ((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))) {
-        directiveState?.checkDeclaration();
-        return parseTopLevelMemberImpl(token);
-      }
-      while (token.next.isModifier) {
-        token = token.next;
-      }
-    }
-    next = token.next;
-    if (next.isTopLevelKeyword) {
-      return parseTopLevelKeywordDeclaration(start, next, directiveState);
-    } else if (next.isKeywordOrIdentifier) {
-      // TODO(danrubel): improve parseTopLevelMember
-      // so that we don't parse modifiers twice.
-      directiveState?.checkDeclaration();
-      return parseTopLevelMemberImpl(start);
-    } else if (start.next != next) {
-      directiveState?.checkDeclaration();
-      // Handle the edge case where a modifier is being used as an identifier
-      return parseTopLevelMemberImpl(start);
-    }
-    // Recovery
-    if (next.isOperator && optional('(', next.next)) {
-      // This appears to be a top level operator declaration, which is invalid.
-      reportRecoverableError(next, fasta.messageTopLevelOperator);
-      // Insert a synthetic identifier
-      // and continue parsing as a top level function.
-      rewriter.insertSyntheticIdentifier(
-          next, '#synthetic_function_${next.charOffset}');
-      return parseTopLevelMemberImpl(next);
-    }
-    // Ignore any preceding modifiers and just report the unexpected token
-    listener.beginTopLevelMember(next);
-    return parseInvalidTopLevelDeclaration(token);
-  }
-
-  /// 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;
-    while (modifier != keyword) {
-      if (optional('abstract', modifier)) {
-        parseTopLevelKeywordModifiers(modifier, keyword);
-        return modifier;
-      } else {
-        // Recovery
-        reportTopLevelModifierError(modifier, keyword);
-      }
-      modifier = modifier.next;
-    }
-    return null;
-  }
-
-  /// Report errors on any modifiers before the specified keyword.
-  void parseTopLevelKeywordModifiers(Token start, Token keyword) {
-    Token modifier = start.next;
-    while (modifier != keyword) {
-      // Recovery
-      reportTopLevelModifierError(modifier, keyword);
-      modifier = modifier.next;
-    }
-  }
-
-  // Report an error for the given modifier preceding a top level keyword
-  // such as `import` or `class`.
-  void reportTopLevelModifierError(Token modifier, Token afterModifiers) {
-    if (optional('const', modifier) && optional('class', afterModifiers)) {
-      reportRecoverableError(modifier, fasta.messageConstClass);
-    } else if (optional('external', modifier)) {
-      if (optional('class', afterModifiers)) {
-        reportRecoverableError(modifier, fasta.messageExternalClass);
-      } else if (optional('enum', afterModifiers)) {
-        reportRecoverableError(modifier, fasta.messageExternalEnum);
-      } else if (optional('typedef', afterModifiers)) {
-        reportRecoverableError(modifier, fasta.messageExternalTypedef);
-      } else {
-        reportRecoverableErrorWithToken(
-            modifier, fasta.templateExtraneousModifier);
-      }
-    } else {
-      reportRecoverableErrorWithToken(
-          modifier, fasta.templateExtraneousModifier);
-    }
-  }
-
-  /// 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) {
-    assert(keyword.isTopLevelKeyword);
-    final String value = keyword.stringValue;
-    if (identical(value, 'class')) {
-      directiveState?.checkDeclaration();
-      Token abstractToken = parseClassDeclarationModifiers(start, keyword);
-      return parseClassOrNamedMixinApplication(abstractToken, keyword);
-    } else if (identical(value, 'enum')) {
-      directiveState?.checkDeclaration();
-      parseTopLevelKeywordModifiers(start, keyword);
-      return parseEnum(keyword);
-    } else {
-      // The remaining top level keywords are built-in keywords
-      // 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;
-      if (identical(nextValue, '(') || identical(nextValue, '.')) {
-        directiveState?.checkDeclaration();
-        return parseTopLevelMemberImpl(start);
-      } else if (identical(nextValue, '<')) {
-        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)) {
-            directiveState?.checkDeclaration();
-            return parseExtension(keyword);
-          }
-        }
-        directiveState?.checkDeclaration();
-        return parseTopLevelMemberImpl(start);
-      } else {
-        parseTopLevelKeywordModifiers(start, keyword);
-        if (identical(value, 'import')) {
-          directiveState?.checkImport(this, keyword);
-          return parseImport(keyword);
-        } else if (identical(value, 'export')) {
-          directiveState?.checkExport(this, keyword);
-          return parseExport(keyword);
-        } else if (identical(value, 'typedef')) {
-          directiveState?.checkDeclaration();
-          return parseTypedef(keyword);
-        } else if (identical(value, 'mixin')) {
-          directiveState?.checkDeclaration();
-          return parseMixin(keyword);
-        } else if (identical(value, 'extension')) {
-          directiveState?.checkDeclaration();
-          return parseExtension(keyword);
-        } else if (identical(value, 'part')) {
-          return parsePartOrPartOf(keyword, directiveState);
-        } else if (identical(value, 'library')) {
-          directiveState?.checkLibrary(this, keyword);
-          return parseLibraryName(keyword);
-        }
-      }
-    }
-
-    throw "Internal error: Unhandled top level keyword '$value'.";
-  }
-
-  /// ```
-  /// libraryDirective:
-  ///   'library' qualified ';'
-  /// ;
-  /// ```
-  Token parseLibraryName(Token libraryKeyword) {
-    assert(optional('library', libraryKeyword));
-    listener.beginLibraryName(libraryKeyword);
-    Token token = parseQualified(libraryKeyword, IdentifierContext.libraryName,
-        IdentifierContext.libraryNameContinuation);
-    token = ensureSemicolon(token);
-    listener.endLibraryName(libraryKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// importPrefix:
-  ///   'deferred'? 'as' identifier
-  /// ;
-  /// ```
-  Token parseImportPrefixOpt(Token token) {
-    Token next = token.next;
-    if (optional('deferred', next) && optional('as', next.next)) {
-      Token deferredToken = next;
-      Token asKeyword = next.next;
-      token = ensureIdentifier(
-          asKeyword, IdentifierContext.importPrefixDeclaration);
-      listener.handleImportPrefix(deferredToken, asKeyword);
-    } else if (optional('as', next)) {
-      Token asKeyword = next;
-      token = ensureIdentifier(next, IdentifierContext.importPrefixDeclaration);
-      listener.handleImportPrefix(null, asKeyword);
-    } else {
-      listener.handleImportPrefix(null, null);
-    }
-    return token;
-  }
-
-  /// ```
-  /// importDirective:
-  ///   'import' uri ('if' '(' test ')' uri)* importPrefix? combinator* ';'
-  /// ;
-  /// ```
-  Token parseImport(Token importKeyword) {
-    assert(optional('import', importKeyword));
-    listener.beginImport(importKeyword);
-    Token token = ensureLiteralString(importKeyword);
-    Token uri = token;
-    token = parseConditionalUriStar(token);
-    token = parseImportPrefixOpt(token);
-    token = parseCombinatorStar(token).next;
-    if (optional(';', token)) {
-      listener.endImport(importKeyword, token);
-      return token;
-    } else {
-      // Recovery
-      listener.endImport(importKeyword, null);
-      return parseImportRecovery(uri);
-    }
-  }
-
-  /// Recover given out-of-order clauses in an import directive where [token] is
-  /// the import keyword.
-  Token parseImportRecovery(Token token) {
-    final Listener primaryListener = listener;
-    final ImportRecoveryListener recoveryListener =
-        new ImportRecoveryListener();
-
-    // Reparse to determine which clauses have already been parsed
-    // but intercept the events so they are not sent to the primary listener
-    listener = recoveryListener;
-    token = parseConditionalUriStar(token);
-    token = parseImportPrefixOpt(token);
-    token = parseCombinatorStar(token);
-
-    Token firstDeferredKeyword = recoveryListener.deferredKeyword;
-    bool hasPrefix = recoveryListener.asKeyword != null;
-    bool hasCombinator = recoveryListener.hasCombinator;
-
-    // Update the recovery listener to forward subsequent events
-    // to the primary listener
-    recoveryListener.listener = primaryListener;
-
-    // Parse additional out-of-order clauses.
-    Token semicolon;
-    do {
-      Token start = token.next;
-
-      // Check for extraneous token in the middle of an import statement.
-      token = skipUnexpectedTokenOpt(
-          token, const <String>['if', 'deferred', 'as', 'hide', 'show', ';']);
-
-      // During recovery, clauses are parsed in the same order
-      // and generate the same events as in the parseImport method above.
-      recoveryListener.clear();
-      token = parseConditionalUriStar(token);
-      if (recoveryListener.ifKeyword != null) {
-        if (firstDeferredKeyword != null) {
-          // TODO(danrubel): report error indicating conditional should
-          // be moved before deferred keyword
-        } else if (hasPrefix) {
-          // TODO(danrubel): report error indicating conditional should
-          // be moved before prefix clause
-        } else if (hasCombinator) {
-          // TODO(danrubel): report error indicating conditional should
-          // be moved before combinators
-        }
-      }
-
-      if (optional('deferred', token.next) &&
-          !optional('as', token.next.next)) {
-        listener.handleImportPrefix(token.next, null);
-        token = token.next;
-      } else {
-        token = parseImportPrefixOpt(token);
-      }
-      if (recoveryListener.deferredKeyword != null) {
-        if (firstDeferredKeyword != null) {
-          reportRecoverableError(
-              recoveryListener.deferredKeyword, fasta.messageDuplicateDeferred);
-        } else {
-          if (hasPrefix) {
-            reportRecoverableError(recoveryListener.deferredKeyword,
-                fasta.messageDeferredAfterPrefix);
-          }
-          firstDeferredKeyword = recoveryListener.deferredKeyword;
-        }
-      }
-      if (recoveryListener.asKeyword != null) {
-        if (hasPrefix) {
-          reportRecoverableError(
-              recoveryListener.asKeyword, fasta.messageDuplicatePrefix);
-        } else {
-          if (hasCombinator) {
-            reportRecoverableError(
-                recoveryListener.asKeyword, fasta.messagePrefixAfterCombinator);
-          }
-          hasPrefix = true;
-        }
-      }
-
-      token = parseCombinatorStar(token);
-      hasCombinator = hasCombinator || recoveryListener.hasCombinator;
-
-      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);
-      }
-      listener.handleRecoverImport(semicolon);
-    } while (semicolon == null);
-
-    if (firstDeferredKeyword != null && !hasPrefix) {
-      reportRecoverableError(
-          firstDeferredKeyword, fasta.messageMissingPrefixInDeferredImport);
-    }
-
-    return semicolon;
-  }
-
-  /// ```
-  /// conditionalUris:
-  ///   conditionalUri*
-  /// ;
-  /// ```
-  Token parseConditionalUriStar(Token token) {
-    listener.beginConditionalUris(token.next);
-    int count = 0;
-    while (optional('if', token.next)) {
-      count++;
-      token = parseConditionalUri(token);
-    }
-    listener.endConditionalUris(count);
-    return token;
-  }
-
-  /// ```
-  /// conditionalUri:
-  ///   'if' '(' dottedName ('==' literalString)? ')' uri
-  /// ;
-  /// ```
-  Token parseConditionalUri(Token token) {
-    Token ifKeyword = token = token.next;
-    assert(optional('if', token));
-    listener.beginConditionalUri(token);
-    Token leftParen = token.next;
-    if (!optional('(', leftParen)) {
-      reportRecoverableError(
-          leftParen, fasta.templateExpectedButGot.withArguments('('));
-      leftParen = rewriter.insertParens(token, true);
-    }
-    token = parseDottedName(leftParen);
-    Token next = token.next;
-    Token equalitySign;
-    if (optional('==', next)) {
-      equalitySign = next;
-      token = ensureLiteralString(next);
-      next = token.next;
-    }
-    if (next != 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);
-      } else {
-        reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-        next = endGroup;
-      }
-    }
-    token = next;
-    assert(optional(')', token));
-
-    token = ensureLiteralString(token);
-    listener.endConditionalUri(ifKeyword, leftParen, equalitySign);
-    return token;
-  }
-
-  /// ```
-  /// dottedName:
-  ///   identifier ('.' identifier)*
-  /// ;
-  /// ```
-  Token parseDottedName(Token token) {
-    token = ensureIdentifier(token, IdentifierContext.dottedName);
-    Token firstIdentifier = token;
-    int count = 1;
-    while (optional('.', token.next)) {
-      token = ensureIdentifier(
-          token.next, IdentifierContext.dottedNameContinuation);
-      count++;
-    }
-    listener.handleDottedName(count, firstIdentifier);
-    return token;
-  }
-
-  /// ```
-  /// exportDirective:
-  ///   'export' uri conditional-uris* combinator* ';'
-  /// ;
-  /// ```
-  Token parseExport(Token exportKeyword) {
-    assert(optional('export', exportKeyword));
-    listener.beginExport(exportKeyword);
-    Token token = ensureLiteralString(exportKeyword);
-    token = parseConditionalUriStar(token);
-    token = parseCombinatorStar(token);
-    token = ensureSemicolon(token);
-    listener.endExport(exportKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// combinators:
-  ///   (hideCombinator | showCombinator)*
-  /// ;
-  /// ```
-  Token parseCombinatorStar(Token token) {
-    Token next = token.next;
-    listener.beginCombinators(next);
-    int count = 0;
-    while (true) {
-      String value = next.stringValue;
-      if (identical('hide', value)) {
-        token = parseHide(token);
-      } else if (identical('show', value)) {
-        token = parseShow(token);
-      } else {
-        listener.endCombinators(count);
-        break;
-      }
-      next = token.next;
-      count++;
-    }
-    return token;
-  }
-
-  /// ```
-  /// hideCombinator:
-  ///   'hide' identifierList
-  /// ;
-  /// ```
-  Token parseHide(Token token) {
-    Token hideKeyword = token.next;
-    assert(optional('hide', hideKeyword));
-    listener.beginHide(hideKeyword);
-    token = parseIdentifierList(hideKeyword);
-    listener.endHide(hideKeyword);
-    return token;
-  }
-
-  /// ```
-  /// showCombinator:
-  ///   'show' identifierList
-  /// ;
-  /// ```
-  Token parseShow(Token token) {
-    Token showKeyword = token.next;
-    assert(optional('show', showKeyword));
-    listener.beginShow(showKeyword);
-    token = parseIdentifierList(showKeyword);
-    listener.endShow(showKeyword);
-    return token;
-  }
-
-  /// ```
-  /// identifierList:
-  ///   identifier (',' identifier)*
-  /// ;
-  /// ```
-  Token parseIdentifierList(Token token) {
-    token = ensureIdentifier(token, IdentifierContext.combinator);
-    int count = 1;
-    while (optional(',', token.next)) {
-      token = ensureIdentifier(token.next, IdentifierContext.combinator);
-      count++;
-    }
-    listener.handleIdentifierList(count);
-    return token;
-  }
-
-  /// ```
-  /// typeList:
-  ///   type (',' type)*
-  /// ;
-  /// ```
-  Token parseTypeList(Token token) {
-    listener.beginTypeList(token.next);
-    token = computeType(token, true).ensureTypeOrVoid(token, this);
-    int count = 1;
-    while (optional(',', token.next)) {
-      token = computeType(token.next, true).ensureTypeOrVoid(token.next, this);
-      count++;
-    }
-    listener.endTypeList(count);
-    return token;
-  }
-
-  Token parsePartOrPartOf(Token partKeyword, DirectiveContext directiveState) {
-    assert(optional('part', partKeyword));
-    if (optional('of', partKeyword.next)) {
-      directiveState?.checkPartOf(this, partKeyword);
-      return parsePartOf(partKeyword);
-    } else {
-      directiveState?.checkPart(this, partKeyword);
-      return parsePart(partKeyword);
-    }
-  }
-
-  /// ```
-  /// partDirective:
-  ///   'part' uri ';'
-  /// ;
-  /// ```
-  Token parsePart(Token partKeyword) {
-    assert(optional('part', partKeyword));
-    listener.beginPart(partKeyword);
-    Token token = ensureLiteralString(partKeyword);
-    token = ensureSemicolon(token);
-    listener.endPart(partKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// partOfDirective:
-  ///   'part' 'of' (qualified | uri) ';'
-  /// ;
-  /// ```
-  Token parsePartOf(Token partKeyword) {
-    Token ofKeyword = partKeyword.next;
-    assert(optional('part', partKeyword));
-    assert(optional('of', ofKeyword));
-    listener.beginPartOf(partKeyword);
-    bool hasName = ofKeyword.next.isIdentifier;
-    Token token;
-    if (hasName) {
-      token = parseQualified(ofKeyword, IdentifierContext.partName,
-          IdentifierContext.partNameContinuation);
-    } else {
-      token = ensureLiteralString(ofKeyword);
-    }
-    token = ensureSemicolon(token);
-    listener.endPartOf(partKeyword, ofKeyword, token, hasName);
-    return token;
-  }
-
-  /// ```
-  /// metadata:
-  ///   annotation*
-  /// ;
-  /// ```
-  Token parseMetadataStar(Token token) {
-    listener.beginMetadataStar(token.next);
-    int count = 0;
-    while (optional('@', token.next)) {
-      token = parseMetadata(token);
-      count++;
-    }
-    listener.endMetadataStar(count);
-    return token;
-  }
-
-  /// ```
-  /// annotation:
-  ///   '@' qualified ('.' identifier)? arguments?
-  /// ;
-  /// ```
-  Token parseMetadata(Token token) {
-    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, fasta.messageMetadataTypeArguments);
-    }
-    token = computeTypeParamOrArg(token).parseArguments(token, this);
-    Token period = null;
-    if (optional('.', token.next)) {
-      period = token.next;
-      token = ensureIdentifier(
-          period, IdentifierContext.metadataContinuationAfterTypeArguments);
-    }
-    token = parseArgumentsOpt(token);
-    listener.endMetadata(atToken, period, token.next);
-    return token;
-  }
-
-  /// ```
-  /// scriptTag:
-  ///   '#!' (˜NEWLINE)* NEWLINE
-  /// ;
-  /// ```
-  Token parseScript(Token token) {
-    token = token.next;
-    assert(identical(token.type, TokenType.SCRIPT_TAG));
-    listener.handleScript(token);
-    return token;
-  }
-
-  /// ```
-  /// typeAlias:
-  ///   metadata 'typedef' typeAliasBody |
-  ///   metadata 'typedef' identifier typeParameters? '=' functionType ';'
-  /// ;
-  ///
-  /// functionType:
-  ///   returnType? 'Function' typeParameters? parameterTypeList
-  ///
-  /// typeAliasBody:
-  ///   functionTypeAlias
-  /// ;
-  ///
-  /// functionTypeAlias:
-  ///   functionPrefix typeParameters? formalParameterList ‘;’
-  /// ;
-  ///
-  /// functionPrefix:
-  ///   returnType? identifier
-  /// ;
-  /// ```
-  Token parseTypedef(Token typedefKeyword) {
-    assert(optional('typedef', typedefKeyword));
-    listener.beginFunctionTypeAlias(typedefKeyword);
-    TypeInfo typeInfo = computeType(typedefKeyword, false);
-    Token token = typeInfo.skipType(typedefKeyword).next;
-    Token equals;
-    TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token, true);
-    if (typeInfo == noType &&
-        (token.kind == IDENTIFIER_TOKEN || token.type.isPseudo) &&
-        optional('=', typeParam.skip(token).next)) {
-      listener.handleIdentifier(token, IdentifierContext.typedefDeclaration);
-      equals = typeParam.parseVariables(token, this).next;
-      assert(optional('=', equals));
-      token = computeType(equals, true).ensureTypeOrVoid(equals, this);
-    } else {
-      token = typeInfo.parseType(typedefKeyword, this);
-      token = ensureIdentifier(token, IdentifierContext.typedefDeclaration);
-      token = typeParam.parseVariables(token, this);
-      token =
-          parseFormalParametersRequiredOpt(token, MemberKind.FunctionTypeAlias);
-    }
-    token = ensureSemicolon(token);
-    listener.endFunctionTypeAlias(typedefKeyword, equals, token);
-    return token;
-  }
-
-  /// Parse a mixin application starting from `with`. Assumes that the first
-  /// type has already been parsed.
-  Token parseMixinApplicationRest(Token token) {
-    Token withKeyword = token.next;
-    if (!optional('with', withKeyword)) {
-      // Recovery: Report an error and insert synthetic `with` clause.
-      reportRecoverableError(
-          withKeyword, fasta.templateExpectedButGot.withArguments('with'));
-      withKeyword = rewriter.insertSyntheticKeyword(token, Keyword.WITH);
-      if (!isValidTypeReference(withKeyword.next)) {
-        rewriter.insertSyntheticIdentifier(withKeyword);
-      }
-    }
-    token = parseTypeList(withKeyword);
-    listener.handleNamedMixinApplicationWithClause(withKeyword);
-    return token;
-  }
-
-  Token parseWithClauseOpt(Token token) {
-    Token withKeyword = token.next;
-    if (optional('with', withKeyword)) {
-      token = parseTypeList(withKeyword);
-      listener.handleClassWithClause(withKeyword);
-    } else {
-      listener.handleClassNoWithClause();
-    }
-    return token;
-  }
-
-  /// Parse the formal parameters of a getter (which shouldn't have parameters)
-  /// or function or method.
-  Token parseGetterOrFormalParameters(
-      Token token, Token name, bool isGetter, MemberKind kind) {
-    Token next = token.next;
-    if (optional("(", next)) {
-      if (isGetter) {
-        reportRecoverableError(next, fasta.messageGetterWithFormals);
-      }
-      token = parseFormalParameters(token, kind);
-    } else if (isGetter) {
-      listener.handleNoFormalParameters(next, kind);
-    } else {
-      // Recovery
-      if (optional('operator', name)) {
-        Token next = name.next;
-        if (next.isOperator) {
-          name = next;
-        } else if (isUnaryMinus(next)) {
-          name = next.next;
-        }
-      }
-      reportRecoverableError(name, missingParameterMessage(kind));
-      token = rewriter.insertParens(token, false);
-      token = parseFormalParametersRest(token, kind);
-    }
-    return token;
-  }
-
-  Token parseFormalParametersOpt(Token token, MemberKind kind) {
-    Token next = token.next;
-    if (optional('(', next)) {
-      token = parseFormalParameters(token, kind);
-    } else {
-      listener.handleNoFormalParameters(next, kind);
-    }
-    return token;
-  }
-
-  Token skipFormalParameters(Token token, MemberKind 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;
-    assert(optional(')', closeBrace));
-    listener.endFormalParameters(0, token, closeBrace, kind);
-    return closeBrace;
-  }
-
-  /// Parses the formal parameter list of a function.
-  ///
-  /// 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;
-    if (!optional('(', next)) {
-      reportRecoverableError(next, missingParameterMessage(kind));
-      next = rewriter.insertParens(token, false);
-    }
-    return parseFormalParametersRest(next, kind);
-  }
-
-  /// Parses the formal parameter list of a function given that the left
-  /// parenthesis is known to exist.
-  ///
-  /// 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);
-  }
-
-  /// Parses the formal parameter list of a function given that the left
-  /// parenthesis passed in as [token].
-  ///
-  /// If `kind == MemberKind.GeneralizedFunctionType`, then names may be
-  /// omitted (except for named arguments). Otherwise, types may be omitted.
-  Token parseFormalParametersRest(Token token, MemberKind kind) {
-    Token begin = token;
-    assert(optional('(', token));
-    listener.beginFormalParameters(begin, kind);
-    int parameterCount = 0;
-    while (true) {
-      Token next = token.next;
-      if (optional(')', next)) {
-        token = next;
-        break;
-      }
-      ++parameterCount;
-      String value = next.stringValue;
-      if (identical(value, '[')) {
-        token = parseOptionalPositionalParameters(token, kind);
-        token = ensureCloseParen(token, begin);
-        break;
-      } else if (identical(value, '{')) {
-        token = parseOptionalNamedParameters(token, kind);
-        token = ensureCloseParen(token, begin);
-        break;
-      } else if (identical(value, '[]')) {
-        // Recovery
-        token = rewriteSquareBrackets(token);
-        token = parseOptionalPositionalParameters(token, kind);
-        token = ensureCloseParen(token, begin);
-        break;
-      }
-      token = parseFormalParameter(token, FormalParameterKind.mandatory, kind);
-      next = token.next;
-      if (!optional(',', next)) {
-        Token next = token.next;
-        if (optional(')', next)) {
-          token = next;
-        } else {
-          // Recovery
-          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);
-          } else if (next.kind == IDENTIFIER_TOKEN &&
-              next.next.kind == IDENTIFIER_TOKEN) {
-            // Looks like a missing comma
-            token = rewriteAndRecover(
-                token,
-                fasta.templateExpectedButGot.withArguments(','),
-                new SyntheticToken(TokenType.COMMA, next.charOffset));
-            continue;
-          } else {
-            token = ensureCloseParen(token, begin);
-          }
-        }
-        break;
-      }
-      token = next;
-    }
-    assert(optional(')', token));
-    listener.endFormalParameters(parameterCount, begin, token, kind);
-    return token;
-  }
-
-  /// Return the message that should be produced when the formal parameters are
-  /// missing.
-  Message missingParameterMessage(MemberKind kind) {
-    if (kind == MemberKind.FunctionTypeAlias) {
-      return fasta.messageMissingTypedefParameters;
-    } else if (kind == MemberKind.NonStaticMethod ||
-        kind == MemberKind.StaticMethod) {
-      return fasta.messageMissingMethodParameters;
-    }
-    return fasta.messageMissingFunctionParameters;
-  }
-
-  /// ```
-  /// normalFormalParameter:
-  ///   functionFormalParameter |
-  ///   fieldFormalParameter |
-  ///   simpleFormalParameter
-  /// ;
-  ///
-  /// functionFormalParameter:
-  ///   metadata 'covariant'? returnType? identifier formalParameterList
-  /// ;
-  ///
-  /// simpleFormalParameter:
-  ///   metadata 'covariant'? finalConstVarOrType? identifier |
-  /// ;
-  ///
-  /// fieldFormalParameter:
-  ///   metadata finalConstVarOrType? 'this' '.' identifier formalParameterList?
-  /// ;
-  /// ```
-  Token parseFormalParameter(
-      Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
-    assert(parameterKind != null);
-    token = parseMetadataStar(token);
-    Token next = token.next;
-    Token start = next;
-
-    final bool inFunctionType =
-        memberKind == MemberKind.GeneralizedFunctionType;
-
-    Token requiredToken;
-    Token covariantToken;
-    Token varFinalOrConst;
-    if (isModifier(next)) {
-      if (optional('required', next)) {
-        if (parameterKind == FormalParameterKind.optionalNamed) {
-          requiredToken = token = next;
-          next = token.next;
-        }
-      }
-
-      if (isModifier(next)) {
-        if (optional('covariant', next)) {
-          if (memberKind != MemberKind.StaticMethod &&
-              memberKind != MemberKind.TopLevelMethod &&
-              memberKind != MemberKind.ExtensionNonStaticMethod &&
-              memberKind != MemberKind.ExtensionStaticMethod) {
-            covariantToken = token = next;
-            next = token.next;
-          }
-        }
-
-        if (isModifier(next)) {
-          if (!inFunctionType) {
-            if (optional('var', next)) {
-              varFinalOrConst = token = next;
-              next = token.next;
-            } else if (optional('final', next)) {
-              varFinalOrConst = token = next;
-              next = token.next;
-            }
-          }
-
-          if (isModifier(next)) {
-            // Recovery
-            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
-              ..covariantToken = covariantToken
-              ..requiredToken = requiredToken
-              ..varFinalOrConst = varFinalOrConst;
-
-            token = context.parseFormalParameterModifiers(
-                token, parameterKind, memberKind);
-            next = token.next;
-
-            covariantToken = context.covariantToken;
-            requiredToken = context.requiredToken;
-            varFinalOrConst = context.varFinalOrConst;
-
-            context = null;
-          }
-        }
-      }
-    }
-
-    listener.beginFormalParameter(
-        start, memberKind, requiredToken, covariantToken, varFinalOrConst);
-
-    // Type is required in a generalized function type, but optional otherwise.
-    final Token beforeType = token;
-    TypeInfo typeInfo = computeType(token, inFunctionType);
-    token = typeInfo.skipType(token);
-    next = token.next;
-    if (typeInfo == noType &&
-        (optional('.', next) ||
-            (next.isIdentifier && optional('.', next.next)))) {
-      // Recovery: Malformed type reference.
-      typeInfo = computeType(beforeType, true);
-      token = typeInfo.skipType(beforeType);
-      next = token.next;
-    }
-
-    final bool isNamedParameter =
-        parameterKind == FormalParameterKind.optionalNamed;
-
-    Token thisKeyword;
-    Token periodAfterThis;
-    IdentifierContext nameContext =
-        IdentifierContext.formalParameterDeclaration;
-
-    if (!inFunctionType && optional('this', next)) {
-      thisKeyword = token = next;
-      next = token.next;
-      if (!optional('.', next)) {
-        // Recover from a missing period by inserting one.
-        next = rewriteAndRecover(
-            token,
-            fasta.templateExpectedButGot.withArguments('.'),
-            new SyntheticToken(TokenType.PERIOD, next.charOffset));
-      }
-      periodAfterThis = token = next;
-      next = token.next;
-      nameContext = IdentifierContext.fieldInitializer;
-    }
-
-    if (next.isIdentifier) {
-      token = next;
-      next = token.next;
-    }
-    Token beforeInlineFunctionType;
-    TypeParamOrArgInfo typeParam = noTypeParamOrArg;
-    if (optional("<", next)) {
-      typeParam = computeTypeParamOrArg(token);
-      if (typeParam != noTypeParamOrArg) {
-        Token closer = typeParam.skip(token);
-        if (optional("(", closer.next)) {
-          if (varFinalOrConst != null) {
-            reportRecoverableError(
-                varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-          }
-          beforeInlineFunctionType = token;
-          token = closer.next.endGroup;
-          next = token.next;
-        }
-      }
-    } else if (optional("(", next)) {
-      if (varFinalOrConst != null) {
-        reportRecoverableError(
-            varFinalOrConst, fasta.messageFunctionTypedParameterVar);
-      }
-      beforeInlineFunctionType = token;
-      token = next.endGroup;
-      next = token.next;
-    }
-    if (typeInfo != noType &&
-        varFinalOrConst != null &&
-        optional('var', varFinalOrConst)) {
-      reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
-    }
-
-    Token endInlineFunctionType;
-    if (beforeInlineFunctionType != null) {
-      endInlineFunctionType =
-          typeParam.parseVariables(beforeInlineFunctionType, this);
-      listener.beginFunctionTypedFormalParameter(beforeInlineFunctionType.next);
-      token = typeInfo.parseType(beforeType, this);
-      endInlineFunctionType = parseFormalParametersRequiredOpt(
-          endInlineFunctionType, MemberKind.FunctionTypedParameter);
-      Token question;
-      if (optional('?', endInlineFunctionType.next)) {
-        question = endInlineFunctionType = endInlineFunctionType.next;
-      }
-      listener.endFunctionTypedFormalParameter(
-          beforeInlineFunctionType, question);
-
-      // Generalized function types don't allow inline function types.
-      // The following isn't allowed:
-      //    int Function(int bar(String x)).
-      if (inFunctionType) {
-        reportRecoverableError(beforeInlineFunctionType.next,
-            fasta.messageInvalidInlineFunctionType);
-      }
-    } else if (inFunctionType) {
-      token = typeInfo.ensureTypeOrVoid(beforeType, this);
-    } else {
-      token = typeInfo.parseType(beforeType, this);
-    }
-
-    Token nameToken;
-    if (periodAfterThis != null) {
-      token = periodAfterThis;
-    }
-    next = token.next;
-    if (inFunctionType &&
-        !isNamedParameter &&
-        !next.isKeywordOrIdentifier &&
-        beforeInlineFunctionType == null) {
-      nameToken = token.next;
-      listener.handleNoName(nameToken);
-    } else {
-      nameToken = token = ensureIdentifier(token, nameContext);
-      if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
-        reportRecoverableError(nameToken, fasta.messagePrivateNamedParameter);
-      }
-    }
-    if (endInlineFunctionType != null) {
-      token = endInlineFunctionType;
-    }
-    next = token.next;
-
-    String value = next.stringValue;
-    Token initializerStart, initializerEnd;
-    if ((identical('=', value)) || (identical(':', value))) {
-      Token equal = next;
-      initializerStart = equal.next;
-      listener.beginFormalParameterDefaultValueExpression();
-      token = initializerEnd = parseExpression(equal);
-      next = token.next;
-      listener.endFormalParameterDefaultValueExpression();
-      // TODO(danrubel): Consider removing the last parameter from the
-      // handleValuedFormalParameter event... it appears to be unused.
-      listener.handleValuedFormalParameter(equal, next);
-      if (isMandatoryFormalParameterKind(parameterKind)) {
-        reportRecoverableError(
-            equal, fasta.messageRequiredParameterWithDefault);
-      } else if (isOptionalPositionalFormalParameterKind(parameterKind) &&
-          identical(':', value)) {
-        reportRecoverableError(
-            equal, fasta.messagePositionalParameterWithEquals);
-      } else if (inFunctionType ||
-          memberKind == MemberKind.FunctionTypeAlias ||
-          memberKind == MemberKind.FunctionTypedParameter) {
-        reportRecoverableError(equal, fasta.messageFunctionTypeDefaultValue);
-      }
-    } else {
-      listener.handleFormalParameterWithoutValue(next);
-    }
-    listener.endFormalParameter(thisKeyword, periodAfterThis, nameToken,
-        initializerStart, initializerEnd, parameterKind, memberKind);
-    return token;
-  }
-
-  /// ```
-  /// defaultFormalParameter:
-  ///   normalFormalParameter ('=' expression)?
-  /// ;
-  /// ```
-  Token parseOptionalPositionalParameters(Token token, MemberKind kind) {
-    Token begin = token = token.next;
-    assert(optional('[', token));
-    listener.beginOptionalFormalParameters(begin);
-    int parameterCount = 0;
-    while (true) {
-      Token next = token.next;
-      if (optional(']', next)) {
-        break;
-      }
-      token = parseFormalParameter(
-          token, FormalParameterKind.optionalPositional, kind);
-      next = token.next;
-      ++parameterCount;
-      if (!optional(',', next)) {
-        if (!optional(']', next)) {
-          // Recovery
-          reportRecoverableError(
-              next, fasta.templateExpectedButGot.withArguments(']'));
-          // Scanner guarantees a closing bracket.
-          next = begin.endGroup;
-          while (token.next != next) {
-            token = token.next;
-          }
-        }
-        break;
-      }
-      token = next;
-    }
-    if (parameterCount == 0) {
-      rewriteAndRecover(
-          token,
-          fasta.messageEmptyOptionalParameterList,
-          new SyntheticStringToken(
-              TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-      token = parseFormalParameter(
-          token, FormalParameterKind.optionalPositional, kind);
-      ++parameterCount;
-    }
-    token = token.next;
-    assert(optional(']', token));
-    listener.endOptionalFormalParameters(parameterCount, begin, token);
-    return token;
-  }
-
-  /// ```
-  /// defaultNamedParameter:
-  ///   normalFormalParameter ('=' expression)? |
-  ///   normalFormalParameter (':' expression)?
-  /// ;
-  /// ```
-  Token parseOptionalNamedParameters(Token token, MemberKind kind) {
-    Token begin = token = token.next;
-    assert(optional('{', token));
-    listener.beginOptionalFormalParameters(begin);
-    int parameterCount = 0;
-    while (true) {
-      Token next = token.next;
-      if (optional('}', next)) {
-        break;
-      }
-      token =
-          parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
-      next = token.next;
-      ++parameterCount;
-      if (!optional(',', next)) {
-        if (!optional('}', next)) {
-          // Recovery
-          reportRecoverableError(
-              next, fasta.templateExpectedButGot.withArguments('}'));
-          // Scanner guarantees a closing bracket.
-          next = begin.endGroup;
-          while (token.next != next) {
-            token = token.next;
-          }
-        }
-        break;
-      }
-      token = next;
-    }
-    if (parameterCount == 0) {
-      rewriteAndRecover(
-          token,
-          fasta.messageEmptyNamedParameterList,
-          new SyntheticStringToken(
-              TokenType.IDENTIFIER, '', token.next.charOffset, 0));
-      token =
-          parseFormalParameter(token, FormalParameterKind.optionalNamed, kind);
-      ++parameterCount;
-    }
-    token = token.next;
-    assert(optional('}', token));
-    listener.endOptionalFormalParameters(parameterCount, begin, token);
-    return token;
-  }
-
-  /// ```
-  /// qualified:
-  ///   identifier qualifiedRest*
-  /// ;
-  /// ```
-  Token parseQualified(Token token, IdentifierContext context,
-      IdentifierContext continuationContext) {
-    token = ensureIdentifier(token, context);
-    while (optional('.', token.next)) {
-      token = parseQualifiedRest(token, continuationContext);
-    }
-    return token;
-  }
-
-  /// ```
-  /// qualifiedRestOpt:
-  ///   qualifiedRest?
-  /// ;
-  /// ```
-  Token parseQualifiedRestOpt(
-      Token token, IdentifierContext continuationContext) {
-    if (optional('.', token.next)) {
-      return parseQualifiedRest(token, continuationContext);
-    } else {
-      return token;
-    }
-  }
-
-  /// ```
-  /// qualifiedRest:
-  ///   '.' identifier
-  /// ;
-  /// ```
-  Token parseQualifiedRest(Token token, IdentifierContext context) {
-    token = token.next;
-    assert(optional('.', token));
-    Token period = token;
-    token = ensureIdentifier(token, context);
-    listener.handleQualified(period);
-    return token;
-  }
-
-  Token skipBlock(Token token) {
-    // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, null, null).endGroup;
-  }
-
-  /// ```
-  /// enumType:
-  ///   metadata 'enum' id '{' metadata id [',' metadata id]* [','] '}'
-  /// ;
-  /// ```
-  Token parseEnum(Token enumKeyword) {
-    assert(optional('enum', enumKeyword));
-    listener.beginEnum(enumKeyword);
-    Token token =
-        ensureIdentifier(enumKeyword, IdentifierContext.enumDeclaration);
-    Token leftBrace = token.next;
-    int count = 0;
-    if (optional('{', leftBrace)) {
-      token = leftBrace;
-      while (true) {
-        Token next = token.next;
-        if (optional('}', next)) {
-          token = next;
-          if (count == 0) {
-            reportRecoverableError(token, fasta.messageEnumDeclarationEmpty);
-          }
-          break;
-        }
-        token = parseMetadataStar(token);
-        token = ensureIdentifier(token, IdentifierContext.enumValueDeclaration);
-        next = token.next;
-        count++;
-        if (optional(',', next)) {
-          token = next;
-        } else if (optional('}', next)) {
-          token = next;
-          break;
-        } else {
-          // Recovery
-          Token endGroup = leftBrace.endGroup;
-          if (endGroup.isSynthetic) {
-            // The scanner did not place the synthetic '}' correctly.
-            token = rewriter.moveSynthetic(token, endGroup);
-            break;
-          } else if (next.isIdentifier) {
-            // If the next token is an identifier, assume a missing comma.
-            // TODO(danrubel): Consider improved recovery for missing `}`
-            // both here and when the scanner inserts a synthetic `}`
-            // for situations such as `enum Letter {a, b   Letter e;`.
-            reportRecoverableError(
-                next, fasta.templateExpectedButGot.withArguments(','));
-          } else {
-            // Otherwise assume a missing `}` and exit the loop
-            reportRecoverableError(
-                next, fasta.templateExpectedButGot.withArguments('}'));
-            token = leftBrace.endGroup;
-            break;
-          }
-        }
-      }
-    } else {
-      // TODO(danrubel): merge this error message with missing class/mixin body
-      leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody, null);
-      token = leftBrace.endGroup;
-    }
-    assert(optional('}', token));
-    listener.endEnum(enumKeyword, leftBrace, count);
-    return token;
-  }
-
-  Token parseClassOrNamedMixinApplication(
-      Token abstractToken, Token classKeyword) {
-    assert(optional('class', classKeyword));
-    Token begin = abstractToken ?? classKeyword;
-    listener.beginClassOrNamedMixinApplicationPrelude(begin);
-    Token name = ensureIdentifier(
-        classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
-    Token token =
-        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
-    if (optional('=', token.next)) {
-      listener.beginNamedMixinApplication(begin, abstractToken, name);
-      return parseNamedMixinApplication(token, begin, classKeyword);
-    } else {
-      listener.beginClassDeclaration(begin, abstractToken, name);
-      return parseClass(token, begin, classKeyword, name.lexeme);
-    }
-  }
-
-  Token parseNamedMixinApplication(
-      Token token, Token begin, Token classKeyword) {
-    Token equals = token = token.next;
-    assert(optional('=', equals));
-    token = computeType(token, true).ensureTypeNotVoid(token, this);
-    token = parseMixinApplicationRest(token);
-    Token implementsKeyword = null;
-    if (optional('implements', token.next)) {
-      implementsKeyword = token.next;
-      token = parseTypeList(implementsKeyword);
-    }
-    token = ensureSemicolon(token);
-    listener.endNamedMixinApplication(
-        begin, classKeyword, equals, implementsKeyword, token);
-    return token;
-  }
-
-  /// Parse the portion of a class declaration (not a mixin application) that
-  /// follows the end of the type parameters.
-  ///
-  /// ```
-  /// classDefinition:
-  ///   metadata abstract? 'class' identifier typeParameters?
-  ///       (superclass mixins?)? interfaces?
-  ///       '{' (metadata classMemberDefinition)* '}' |
-  ///   metadata abstract? 'class' mixinApplicationClass
-  /// ;
-  /// ```
-  Token parseClass(
-      Token token, Token begin, Token classKeyword, String className) {
-    Token start = token;
-    token = parseClassHeaderOpt(token, begin, classKeyword);
-    if (!optional('{', token.next)) {
-      // Recovery
-      token = parseClassHeaderRecovery(start, begin, classKeyword);
-      ensureBlock(token, null, 'class declaration');
-    }
-    token = parseClassOrMixinOrExtensionBody(
-        token, DeclarationKind.Class, className);
-    listener.endClassDeclaration(begin, token);
-    return token;
-  }
-
-  Token parseClassHeaderOpt(Token token, Token begin, Token classKeyword) {
-    token = parseClassExtendsOpt(token);
-    token = parseWithClauseOpt(token);
-    token = parseClassOrMixinImplementsOpt(token);
-    Token nativeToken;
-    if (optional('native', token.next)) {
-      nativeToken = token.next;
-      token = parseNativeClause(token);
-    }
-    listener.handleClassHeader(begin, classKeyword, nativeToken);
-    return token;
-  }
-
-  /// Recover given out-of-order clauses in a class header.
-  Token parseClassHeaderRecovery(Token token, Token begin, Token classKeyword) {
-    final Listener primaryListener = listener;
-    final ClassHeaderRecoveryListener recoveryListener =
-        new ClassHeaderRecoveryListener();
-
-    // Reparse to determine which clauses have already been parsed
-    // but intercept the events so they are not sent to the primary listener.
-    listener = recoveryListener;
-    token = parseClassHeaderOpt(token, begin, classKeyword);
-    bool hasExtends = recoveryListener.extendsKeyword != null;
-    bool hasImplements = recoveryListener.implementsKeyword != null;
-    bool hasWith = recoveryListener.withKeyword != null;
-
-    // Update the recovery listener to forward subsequent events
-    // to the primary listener.
-    recoveryListener.listener = primaryListener;
-
-    // Parse additional out-of-order clauses
-    Token start;
-    do {
-      start = token;
-
-      // Check for extraneous token in the middle of a class header.
-      token = skipUnexpectedTokenOpt(
-          token, const <String>['extends', 'with', 'implements', '{']);
-
-      // During recovery, clauses are parsed in the same order
-      // 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, fasta.templateExpectedInstead.withArguments('extends'));
-        Token incorrectExtendsKeyword = token.next;
-        token = computeType(incorrectExtendsKeyword, true)
-            .ensureTypeNotVoid(incorrectExtendsKeyword, this);
-        listener.handleClassExtends(incorrectExtendsKeyword);
-      } else {
-        token = parseClassExtendsOpt(token);
-      }
-
-      if (recoveryListener.extendsKeyword != null) {
-        if (hasExtends) {
-          reportRecoverableError(
-              recoveryListener.extendsKeyword, fasta.messageMultipleExtends);
-        } else {
-          if (hasWith) {
-            reportRecoverableError(recoveryListener.extendsKeyword,
-                fasta.messageWithBeforeExtends);
-          } else if (hasImplements) {
-            reportRecoverableError(recoveryListener.extendsKeyword,
-                fasta.messageImplementsBeforeExtends);
-          }
-          hasExtends = true;
-        }
-      }
-
-      token = parseWithClauseOpt(token);
-
-      if (recoveryListener.withKeyword != null) {
-        if (hasWith) {
-          reportRecoverableError(
-              recoveryListener.withKeyword, fasta.messageMultipleWith);
-        } else {
-          if (hasImplements) {
-            reportRecoverableError(recoveryListener.withKeyword,
-                fasta.messageImplementsBeforeWith);
-          }
-          hasWith = true;
-        }
-      }
-
-      token = parseClassOrMixinImplementsOpt(token);
-
-      if (recoveryListener.implementsKeyword != null) {
-        if (hasImplements) {
-          reportRecoverableError(recoveryListener.implementsKeyword,
-              fasta.messageMultipleImplements);
-        } else {
-          hasImplements = true;
-        }
-      }
-
-      listener.handleRecoverClassHeader();
-
-      // Exit if a class body is detected, or if no progress has been made
-    } while (!optional('{', token.next) && start != token);
-
-    listener = primaryListener;
-    return token;
-  }
-
-  Token parseClassExtendsOpt(Token token) {
-    Token next = token.next;
-    if (optional('extends', next)) {
-      Token extendsKeyword = next;
-      token = computeType(next, true).ensureTypeNotVoid(next, this);
-      listener.handleClassExtends(extendsKeyword);
-    } else {
-      listener.handleNoType(token);
-      listener.handleClassExtends(null);
-    }
-    return token;
-  }
-
-  /// ```
-  /// implementsClause:
-  ///   'implements' typeName (',' typeName)*
-  /// ;
-  /// ```
-  Token parseClassOrMixinImplementsOpt(Token token) {
-    Token implementsKeyword;
-    int interfacesCount = 0;
-    if (optional('implements', token.next)) {
-      implementsKeyword = token.next;
-      do {
-        token =
-            computeType(token.next, true).ensureTypeNotVoid(token.next, this);
-        ++interfacesCount;
-      } while (optional(',', token.next));
-    }
-    listener.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
-    return token;
-  }
-
-  /// Parse a mixin declaration.
-  ///
-  /// ```
-  /// mixinDeclaration:
-  ///   metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
-  ///        [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
-  /// ;
-  /// ```
-  Token parseMixin(Token mixinKeyword) {
-    assert(optional('mixin', mixinKeyword));
-    listener.beginClassOrNamedMixinApplicationPrelude(mixinKeyword);
-    Token name = ensureIdentifier(
-        mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
-    Token headerStart =
-        computeTypeParamOrArg(name, true, true).parseVariables(name, this);
-    listener.beginMixinDeclaration(mixinKeyword, name);
-    Token token = parseMixinHeaderOpt(headerStart, mixinKeyword);
-    if (!optional('{', token.next)) {
-      // Recovery
-      token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
-      ensureBlock(token, null, 'mixin declaration');
-    }
-    token = parseClassOrMixinOrExtensionBody(
-        token, DeclarationKind.Mixin, name.lexeme);
-    listener.endMixinDeclaration(mixinKeyword, token);
-    return token;
-  }
-
-  Token parseMixinHeaderOpt(Token token, Token mixinKeyword) {
-    token = parseMixinOnOpt(token);
-    token = parseClassOrMixinImplementsOpt(token);
-    listener.handleMixinHeader(mixinKeyword);
-    return token;
-  }
-
-  Token parseMixinHeaderRecovery(
-      Token token, Token mixinKeyword, Token headerStart) {
-    final Listener primaryListener = listener;
-    final MixinHeaderRecoveryListener recoveryListener =
-        new MixinHeaderRecoveryListener();
-
-    // Reparse to determine which clauses have already been parsed
-    // but intercept the events so they are not sent to the primary listener.
-    listener = recoveryListener;
-    token = parseMixinHeaderOpt(headerStart, mixinKeyword);
-    bool hasOn = recoveryListener.onKeyword != null;
-    bool hasImplements = recoveryListener.implementsKeyword != null;
-
-    // Update the recovery listener to forward subsequent events
-    // to the primary listener.
-    recoveryListener.listener = primaryListener;
-
-    // Parse additional out-of-order clauses
-    Token start;
-    do {
-      start = token;
-
-      // Check for extraneous token in the middle of a class header.
-      token = skipUnexpectedTokenOpt(
-          token, const <String>['on', 'implements', '{']);
-
-      // During recovery, clauses are parsed in the same order and
-      // generate the same events as in the parseMixinHeaderOpt method above.
-      recoveryListener.clear();
-
-      if (token.next.isKeywordOrIdentifier &&
-          const ['extend', 'extends'].contains(token.next.lexeme)) {
-        reportRecoverableError(
-            token.next, fasta.templateExpectedInstead.withArguments('on'));
-        token = parseMixinOn(token);
-      } else {
-        token = parseMixinOnOpt(token);
-      }
-
-      if (recoveryListener.onKeyword != null) {
-        if (hasOn) {
-          reportRecoverableError(
-              recoveryListener.onKeyword, fasta.messageMultipleOnClauses);
-        } else {
-          if (hasImplements) {
-            reportRecoverableError(
-                recoveryListener.onKeyword, fasta.messageImplementsBeforeOn);
-          }
-          hasOn = true;
-        }
-      }
-
-      token = parseClassOrMixinImplementsOpt(token);
-
-      if (recoveryListener.implementsKeyword != null) {
-        if (hasImplements) {
-          reportRecoverableError(recoveryListener.implementsKeyword,
-              fasta.messageMultipleImplements);
-        } else {
-          hasImplements = true;
-        }
-      }
-
-      listener.handleRecoverMixinHeader();
-
-      // Exit if a mixin body is detected, or if no progress has been made
-    } while (!optional('{', token.next) && start != token);
-
-    listener = primaryListener;
-    return token;
-  }
-
-  /// ```
-  /// onClause:
-  ///   'on' typeName (',' typeName)*
-  /// ;
-  /// ```
-  Token parseMixinOnOpt(Token token) {
-    if (!optional('on', token.next)) {
-      listener.handleMixinOn(null, 0);
-      return token;
-    }
-    return parseMixinOn(token);
-  }
-
-  Token parseMixinOn(Token token) {
-    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, true).ensureTypeNotVoid(token.next, this);
-      ++typeCount;
-    } while (optional(',', token.next));
-    listener.handleMixinOn(onKeyword, typeCount);
-    return token;
-  }
-
-  /// ```
-  /// 'extension' <identifier>? <typeParameters>? 'on' <type> '?'?
-  //   `{'
-  //     <memberDeclaration>*
-  //   `}'
-  /// ```
-  Token parseExtension(Token extensionKeyword) {
-    assert(optional('extension', extensionKeyword));
-    Token token = extensionKeyword;
-    listener.beginExtensionDeclarationPrelude(extensionKeyword);
-    Token name = token.next;
-    if (name.isIdentifier && !optional('on', name)) {
-      token = name;
-    } else {
-      name = null;
-    }
-    token = computeTypeParamOrArg(token, true).parseVariables(token, this);
-    listener.beginExtensionDeclaration(extensionKeyword, name);
-    Token onKeyword = token.next;
-    if (!optional('on', onKeyword)) {
-      // Recovery
-      if (optional('extends', onKeyword) ||
-          optional('implements', onKeyword) ||
-          optional('with', onKeyword)) {
-        reportRecoverableError(
-            onKeyword, fasta.templateExpectedInstead.withArguments('on'));
-      } else {
-        reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments('on'));
-        onKeyword = rewriter.insertSyntheticKeyword(token, Keyword.ON);
-      }
-    }
-    TypeInfo typeInfo = computeType(onKeyword, true);
-    token = typeInfo.ensureTypeOrVoid(onKeyword, this);
-    if (!optional('{', token.next)) {
-      // Recovery
-      Token next = token.next;
-      while (!next.isEof) {
-        if (optional(',', next) ||
-            optional('extends', next) ||
-            optional('implements', next) ||
-            optional('on', next) ||
-            optional('with', next)) {
-          // Report an error and skip `,` or specific keyword
-          // optionally followed by an identifier
-          reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-          token = next;
-          next = token.next;
-          if (next.isIdentifier) {
-            token = next;
-            next = token.next;
-          }
-        } else {
-          break;
-        }
-      }
-      ensureBlock(token, null, 'extension declaration');
-    }
-    token = parseClassOrMixinOrExtensionBody(
-        token, DeclarationKind.Extension, name?.lexeme);
-    listener.endExtensionDeclaration(extensionKeyword, onKeyword, token);
-    return token;
-  }
-
-  Token parseStringPart(Token token) {
-    Token next = token.next;
-    if (next.kind != STRING_TOKEN) {
-      reportRecoverableErrorWithToken(next, fasta.templateExpectedString);
-      next = rewriter.insertToken(token,
-          new SyntheticStringToken(TokenType.STRING, '', next.charOffset));
-    }
-    listener.handleStringPart(next);
-    return next;
-  }
-
-  /// Insert a synthetic identifier after the given [token] and create an error
-  /// message based on the given [context]. Return the synthetic identifier that
-  /// was inserted.
-  Token insertSyntheticIdentifier(Token token, IdentifierContext context,
-      {Message message, Token messageOnToken}) {
-    Token next = token.next;
-    reportRecoverableError(messageOnToken ?? next,
-        message ?? context.recoveryTemplate.withArguments(next));
-    return rewriter.insertSyntheticIdentifier(token);
-  }
-
-  /// Parse a simple identifier at the given [token], and return the identifier
-  /// that was parsed.
-  ///
-  /// If the token is not an identifier, or is not appropriate for use as an
-  /// identifier in the given [context], create a synthetic identifier, report
-  /// an error, and return the synthetic identifier.
-  Token ensureIdentifier(Token token, IdentifierContext context) {
-    assert(context != null);
-    Token identifier = token.next;
-    if (identifier.kind != IDENTIFIER_TOKEN) {
-      identifier = context.ensureIdentifier(token, this);
-      assert(identifier != null);
-      assert(identifier.isKeywordOrIdentifier);
-    }
-    listener.handleIdentifier(identifier, context);
-    return identifier;
-  }
-
-  bool notEofOrValue(String value, Token token) {
-    return !identical(token.kind, EOF_TOKEN) &&
-        !identical(value, token.stringValue);
-  }
-
-  Token parseTypeVariablesOpt(Token token) {
-    return computeTypeParamOrArg(token, true).parseVariables(token, this);
-  }
-
-  /// Parse a top level field or function.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseTopLevelMember(Token token) {
-    token = parseMetadataStar(syntheticPreviousToken(token));
-    return parseTopLevelMemberImpl(token).next;
-  }
-
-  Token parseTopLevelMemberImpl(Token token) {
-    Token beforeStart = token;
-    Token next = token.next;
-    listener.beginTopLevelMember(next);
-
-    Token externalToken;
-    Token lateToken;
-    Token varFinalOrConst;
-
-    if (isModifier(next)) {
-      if (optional('external', next)) {
-        externalToken = token = next;
-        next = token.next;
-      }
-      if (isModifier(next)) {
-        if (optional('final', next)) {
-          varFinalOrConst = token = next;
-          next = token.next;
-        } else if (optional('var', next)) {
-          varFinalOrConst = token = next;
-          next = token.next;
-        } else if (optional('const', next)) {
-          varFinalOrConst = token = next;
-          next = token.next;
-        } else if (optional('late', next)) {
-          lateToken = token = next;
-          next = token.next;
-          if (isModifier(next) && optional('final', next)) {
-            varFinalOrConst = token = next;
-            next = token.next;
-          }
-        }
-        if (isModifier(next)) {
-          // Recovery
-          if (varFinalOrConst != null &&
-              (optional('final', next) ||
-                  optional('var', next) ||
-                  optional('const', next))) {
-            // If another `var`, `final`, or `const` then fall through
-            // to parse that as part of the next top level declaration.
-          } else {
-            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
-              ..externalToken = externalToken
-              ..lateToken = lateToken
-              ..varFinalOrConst = varFinalOrConst;
-
-            token = context.parseTopLevelModifiers(token);
-            next = token.next;
-
-            externalToken = context.externalToken;
-            lateToken = context.lateToken;
-            varFinalOrConst = context.varFinalOrConst;
-
-            context = null;
-          }
-        }
-      }
-    }
-
-    Token beforeType = token;
-    TypeInfo typeInfo = computeType(token, false, true);
-    token = typeInfo.skipType(token);
-    next = token.next;
-
-    Token getOrSet;
-    String value = next.stringValue;
-    if (identical(value, 'get') || identical(value, 'set')) {
-      if (next.next.isIdentifier) {
-        getOrSet = token = next;
-        next = token.next;
-      }
-    }
-
-    if (next.type != TokenType.IDENTIFIER) {
-      value = next.stringValue;
-      if (identical(value, 'factory') || identical(value, 'operator')) {
-        // `factory` and `operator` can be used as an identifier.
-        value = next.next.stringValue;
-        if (getOrSet == null &&
-            !identical(value, '(') &&
-            !identical(value, '{') &&
-            !identical(value, '<') &&
-            !identical(value, '=>') &&
-            !identical(value, '=') &&
-            !identical(value, ';') &&
-            !identical(value, ',')) {
-          // Recovery
-          value = next.stringValue;
-          if (identical(value, 'factory')) {
-            reportRecoverableError(
-                next, fasta.messageFactoryTopLevelDeclaration);
-          } else {
-            reportRecoverableError(next, fasta.messageTopLevelOperator);
-            if (next.next.isOperator) {
-              token = next;
-              next = token.next;
-              if (optional('(', next.next)) {
-                rewriter.insertSyntheticIdentifier(
-                    next, '#synthetic_identifier_${next.charOffset}');
-              }
-            }
-          }
-          listener.handleInvalidTopLevelDeclaration(next);
-          return next;
-        }
-        // Fall through and continue parsing
-      } else if (!next.isIdentifier) {
-        // Recovery
-        if (next.isKeyword) {
-          // Fall through to parse the keyword as the identifier.
-          // ensureIdentifier will report the error.
-        } else if (token == beforeStart) {
-          // Ensure we make progress.
-          return parseInvalidTopLevelDeclaration(token);
-        } else {
-          // Looks like a declaration missing an identifier.
-          // Insert synthetic identifier and fall through.
-          insertSyntheticIdentifier(token, IdentifierContext.methodDeclaration);
-          next = token.next;
-        }
-      }
-    }
-    // At this point, `token` is beforeName.
-
-    next = next.next;
-    value = next.stringValue;
-    if (getOrSet != null ||
-        identical(value, '(') ||
-        identical(value, '{') ||
-        identical(value, '<') ||
-        identical(value, '.') ||
-        identical(value, '=>')) {
-      if (varFinalOrConst != null) {
-        if (optional('var', varFinalOrConst)) {
-          reportRecoverableError(varFinalOrConst, fasta.messageVarReturnType);
-        } else {
-          reportRecoverableErrorWithToken(
-              varFinalOrConst, fasta.templateExtraneousModifier);
-        }
-      } else if (lateToken != null) {
-        reportRecoverableErrorWithToken(
-            lateToken, fasta.templateExtraneousModifier);
-      }
-      return parseTopLevelMethod(beforeStart, externalToken, beforeType,
-          typeInfo, getOrSet, token.next);
-    }
-
-    if (getOrSet != null) {
-      reportRecoverableErrorWithToken(
-          getOrSet, fasta.templateExtraneousModifier);
-    }
-    return parseFields(
-        beforeStart,
-        externalToken,
-        null,
-        null,
-        lateToken,
-        varFinalOrConst,
-        beforeType,
-        typeInfo,
-        token.next,
-        DeclarationKind.TopLevel);
-  }
-
-  Token parseFields(
-      Token beforeStart,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      Token beforeType,
-      TypeInfo typeInfo,
-      Token name,
-      DeclarationKind kind) {
-    if (externalToken != null) {
-      reportRecoverableError(externalToken, fasta.messageExternalField);
-    }
-    if (covariantToken != null) {
-      if (varFinalOrConst != null && optional('final', varFinalOrConst)) {
-        reportRecoverableError(covariantToken, fasta.messageFinalAndCovariant);
-        covariantToken = null;
-      }
-    }
-    if (typeInfo == noType) {
-      if (varFinalOrConst == null && lateToken == null) {
-        reportRecoverableError(name, fasta.messageMissingConstFinalVarOrType);
-      }
-    } else {
-      if (varFinalOrConst != null && optional('var', varFinalOrConst)) {
-        reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
-      }
-    }
-
-    Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == name);
-
-    IdentifierContext context = kind == DeclarationKind.TopLevel
-        ? IdentifierContext.topLevelVariableDeclaration
-        : IdentifierContext.fieldDeclaration;
-    Token firstName = name = ensureIdentifier(token, context);
-
-    int fieldCount = 1;
-    token =
-        parseFieldInitializerOpt(name, name, lateToken, varFinalOrConst, kind);
-    while (optional(',', token.next)) {
-      name = ensureIdentifier(token.next, context);
-      token = parseFieldInitializerOpt(
-          name, name, lateToken, varFinalOrConst, kind);
-      ++fieldCount;
-    }
-    Token semicolon = token.next;
-    if (optional(';', semicolon)) {
-      token = semicolon;
-    } else {
-      // Recovery
-      if (kind == DeclarationKind.TopLevel &&
-          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,
-            fasta.templateExperimentNotEnabled
-                .withArguments('extension-methods'));
-        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
-      } else {
-        token = ensureSemicolon(token);
-      }
-    }
-    switch (kind) {
-      case DeclarationKind.TopLevel:
-        listener.endTopLevelFields(staticToken, covariantToken, lateToken,
-            varFinalOrConst, fieldCount, beforeStart.next, token);
-        break;
-      case DeclarationKind.Class:
-        listener.endClassFields(staticToken, covariantToken, lateToken,
-            varFinalOrConst, fieldCount, beforeStart.next, token);
-        break;
-      case DeclarationKind.Mixin:
-        listener.endMixinFields(staticToken, covariantToken, lateToken,
-            varFinalOrConst, fieldCount, beforeStart.next, token);
-        break;
-      case DeclarationKind.Extension:
-        if (staticToken == null) {
-          reportRecoverableError(
-              firstName, fasta.messageExtensionDeclaresInstanceField);
-        }
-        listener.endExtensionFields(staticToken, covariantToken, lateToken,
-            varFinalOrConst, fieldCount, beforeStart.next, token);
-        break;
-    }
-    return token;
-  }
-
-  Token parseTopLevelMethod(Token beforeStart, Token externalToken,
-      Token beforeType, TypeInfo typeInfo, Token getOrSet, Token name) {
-    listener.beginTopLevelMethod(beforeStart, externalToken);
-
-    Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == (getOrSet ?? name));
-    name = ensureIdentifier(
-        getOrSet ?? token, IdentifierContext.topLevelFunctionDeclaration);
-
-    bool isGetter = false;
-    if (getOrSet == null) {
-      token = parseMethodTypeVar(name);
-    } else {
-      isGetter = optional("get", getOrSet);
-      token = name;
-      listener.handleNoTypeVariables(token.next);
-    }
-    token = parseGetterOrFormalParameters(
-        token, name, isGetter, MemberKind.TopLevelMethod);
-    AsyncModifier savedAsyncModifier = asyncState;
-    Token asyncToken = token.next;
-    token = parseAsyncModifierOpt(token);
-    if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
-      reportRecoverableError(asyncToken, fasta.messageSetterNotSync);
-    }
-    bool isExternal = externalToken != null;
-    if (isExternal && !optional(';', token.next)) {
-      reportRecoverableError(
-          externalToken, fasta.messageExternalMethodWithBody);
-    }
-    token = parseFunctionBody(token, false, isExternal);
-    asyncState = savedAsyncModifier;
-    listener.endTopLevelMethod(beforeStart.next, getOrSet, token);
-    return token;
-  }
-
-  Token parseMethodTypeVar(Token name) {
-    if (!optional('<', name.next)) {
-      return noTypeParamOrArg.parseVariables(name, this);
-    }
-    TypeParamOrArgInfo typeVar = computeTypeParamOrArg(name, true);
-    Token token = typeVar.parseVariables(name, this);
-    if (optional('=', token.next)) {
-      // Recovery
-      token = token.next;
-      reportRecoverableErrorWithToken(token, fasta.templateUnexpectedToken);
-    }
-    return token;
-  }
-
-  Token parseFieldInitializerOpt(Token token, Token name, Token lateToken,
-      Token varFinalOrConst, DeclarationKind kind) {
-    Token next = token.next;
-    if (optional('=', next)) {
-      Token assignment = next;
-      listener.beginFieldInitializer(next);
-      token = parseExpression(next);
-      listener.endFieldInitializer(assignment, token.next);
-    } else {
-      if (varFinalOrConst != null && !name.isSynthetic) {
-        if (optional("const", varFinalOrConst)) {
-          reportRecoverableError(
-              name,
-              fasta.templateConstFieldWithoutInitializer
-                  .withArguments(name.lexeme));
-        } else if (kind == DeclarationKind.TopLevel &&
-            optional("final", varFinalOrConst) &&
-            lateToken == null) {
-          reportRecoverableError(
-              name,
-              fasta.templateFinalFieldWithoutInitializer
-                  .withArguments(name.lexeme));
-        }
-      }
-      listener.handleNoFieldInitializer(token.next);
-    }
-    return token;
-  }
-
-  Token parseVariableInitializerOpt(Token token) {
-    if (optional('=', token.next)) {
-      Token assignment = token.next;
-      listener.beginVariableInitializer(assignment);
-      token = parseExpression(assignment);
-      listener.endVariableInitializer(assignment);
-    } else {
-      listener.handleNoVariableInitializer(token.next);
-    }
-    return token;
-  }
-
-  Token parseInitializersOpt(Token token) {
-    if (optional(':', token.next)) {
-      return parseInitializers(token.next);
-    } else {
-      listener.handleNoInitializers();
-      return token;
-    }
-  }
-
-  /// ```
-  /// initializers:
-  ///   ':' initializerListEntry (',' initializerListEntry)*
-  /// ;
-  /// ```
-  Token parseInitializers(Token token) {
-    Token begin = token;
-    assert(optional(':', begin));
-    listener.beginInitializers(begin);
-    int count = 0;
-    bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = false;
-    Token next = begin;
-    while (true) {
-      token = parseInitializer(next);
-      ++count;
-      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;
-          if (!optional('(', next)) {
-            break;
-          }
-          // Looks like assert expression ... fall through to insert comma
-        } else if (!next.isIdentifier && !optional('this', next)) {
-          // An identifier that wasn't an initializer. Break.
-          break;
-        } else {
-          if (optional('this', next)) {
-            next = next.next;
-            if (!optional('.', next)) {
-              break;
-            }
-            next = next.next;
-            if (!next.isIdentifier && !optional('assert', next)) {
-              break;
-            }
-          }
-          next = next.next;
-          if (!optional('=', next)) {
-            break;
-          }
-          // Looks like field assignment... fall through to insert comma
-        }
-        // TODO(danrubel): Consider enhancing this to indicate that we are
-        // expecting one of `,` or `;` or `{`
-        reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments(','));
-        next = rewriter.insertSyntheticToken(token, TokenType.COMMA);
-      }
-    }
-    mayParseFunctionExpressions = old;
-    listener.endInitializers(count, begin, token.next);
-    return token;
-  }
-
-  /// ```
-  /// initializerListEntry:
-  ///   'super' ('.' identifier)? arguments |
-  ///   fieldInitializer |
-  ///   assertion
-  /// ;
-  ///
-  /// fieldInitializer:
-  ///   ('this' '.')? identifier '=' conditionalExpression cascadeSection*
-  /// ;
-  /// ```
-  Token parseInitializer(Token token) {
-    Token next = token.next;
-    listener.beginInitializer(next);
-    Token beforeExpression = token;
-    if (optional('assert', next)) {
-      token = parseAssert(token, Assert.Initializer);
-      listener.endInitializer(token.next);
-      return token;
-    } else if (optional('super', next)) {
-      return parseSuperInitializerExpression(token);
-    } else if (optional('this', next)) {
-      token = next;
-      next = token.next;
-      if (optional('.', next)) {
-        token = next;
-        next = token.next;
-        if (next.isIdentifier) {
-          token = next;
-        } else {
-          // Recovery
-          token = insertSyntheticIdentifier(
-              token, IdentifierContext.fieldInitializer);
-        }
-        next = token.next;
-        if (optional('=', next)) {
-          return parseInitializerExpressionRest(beforeExpression);
-        }
-      }
-      if (optional('(', next)) {
-        token = parseInitializerExpressionRest(beforeExpression);
-        next = token.next;
-        if (optional('{', next) || optional('=>', next)) {
-          reportRecoverableError(
-              next, fasta.messageRedirectingConstructorWithBody);
-        }
-        return token;
-      }
-      // Recovery
-      if (optional('this', token)) {
-        // TODO(danrubel): Consider a better error message indicating that
-        // `this.<fieldname>=` is expected.
-        reportRecoverableError(
-            next, fasta.templateExpectedButGot.withArguments('.'));
-        rewriter.insertSyntheticToken(token, TokenType.PERIOD);
-        token = rewriter.insertSyntheticIdentifier(token.next);
-        next = token.next;
-      }
-      // Fall through to recovery
-    } else if (next.isIdentifier) {
-      Token next2 = next.next;
-      if (optional('=', next2)) {
-        return parseInitializerExpressionRest(token);
-      }
-      // Recovery: If this looks like an expression,
-      // then fall through to insert the LHS and `=` of the assignment,
-      // otherwise insert an `=` and synthetic identifier.
-      if (!next2.isOperator && !optional('.', next2)) {
-        token = rewriter.insertSyntheticToken(next, TokenType.EQ);
-        token = insertSyntheticIdentifier(token, IdentifierContext.expression,
-            message: fasta.messageMissingAssignmentInInitializer,
-            messageOnToken: next);
-        return parseInitializerExpressionRest(beforeExpression);
-      }
-    } else {
-      // Recovery: Insert a synthetic assignment.
-      token = insertSyntheticIdentifier(
-          token, IdentifierContext.fieldInitializer,
-          message: fasta.messageExpectedAnInitializer, messageOnToken: token);
-      token = rewriter.insertSyntheticToken(token, TokenType.EQ);
-      token = rewriter.insertSyntheticIdentifier(token);
-      return parseInitializerExpressionRest(beforeExpression);
-    }
-    // Recovery:
-    // Insert a synthetic identifier and assignment operator
-    // to ensure that the expression is indeed an assignment.
-    // Failing to do so causes this test to fail:
-    // pkg/front_end/testcases/regress/issue_31192.dart
-    // TODO(danrubel): Investigate better recovery.
-    token = insertSyntheticIdentifier(
-        beforeExpression, IdentifierContext.fieldInitializer,
-        message: fasta.messageMissingAssignmentInInitializer);
-    rewriter.insertSyntheticToken(token, TokenType.EQ);
-    return parseInitializerExpressionRest(beforeExpression);
-  }
-
-  /// Parse the `super` initializer:
-  /// ```
-  ///   'super' ('.' identifier)? arguments ;
-  /// ```
-  Token parseSuperInitializerExpression(final Token start) {
-    Token token = start.next;
-    assert(optional('super', token));
-    Token next = token.next;
-    if (optional('.', next)) {
-      token = next;
-      next = token.next;
-      if (next.kind != IDENTIFIER_TOKEN) {
-        next = IdentifierContext.expressionContinuation
-            .ensureIdentifier(token, this);
-      }
-      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;
-        if (!next.isIdentifier) {
-          // Insert a synthetic identifier but don't report another error.
-          next = rewriter.insertSyntheticIdentifier(token);
-        }
-        token = next;
-        next = token.next;
-      }
-      if (optional('=', next)) {
-        if (optional('super', token)) {
-          // parseExpression will report error on assignment to super
-        } else {
-          reportRecoverableError(
-              token, fasta.messageFieldInitializedOutsideDeclaringClass);
-        }
-      } else if (!optional('(', next)) {
-        reportRecoverableError(
-            next, fasta.templateExpectedAfterButGot.withArguments('('));
-        rewriter.insertParens(token, false);
-      }
-    }
-    return parseInitializerExpressionRest(start);
-  }
-
-  Token parseInitializerExpressionRest(Token token) {
-    token = parseExpression(token);
-    listener.endInitializer(token.next);
-    return token;
-  }
-
-  /// If the next token is an opening curly brace, return it. Otherwise, use the
-  /// given [template] or [blockKind] to report an error, insert an opening and
-  /// a closing curly brace, and return the newly inserted opening curly brace.
-  /// If  [template] and [blockKind] are `null`, then use
-  /// a default error message instead.
-  Token ensureBlock(Token token,
-      Template<Message Function(Token token)> template, String blockKind) {
-    Token next = token.next;
-    if (optional('{', next)) return next;
-    if (template == null) {
-      if (blockKind == null) {
-        // TODO(danrubel): rename ExpectedButGot to ExpectedBefore
-        reportRecoverableError(
-            next, fasta.templateExpectedButGot.withArguments('{'));
-      } else {
-        // TODO(danrubel): rename ExpectedClassOrMixinBody
-        //  to ExpectedDeclarationOrClauseBody
-        reportRecoverableError(token,
-            fasta.templateExpectedClassOrMixinBody.withArguments(blockKind));
-      }
-    } else {
-      reportRecoverableError(next, template.withArguments(next));
-    }
-    return insertBlock(token);
-  }
-
-  Token insertBlock(Token token) {
-    Token next = token.next;
-    BeginToken beginGroup = rewriter.insertToken(token,
-        new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset));
-    Token endGroup = rewriter.insertToken(beginGroup,
-        new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, next.offset));
-    beginGroup.endGroup = endGroup;
-    return beginGroup;
-  }
-
-  /// If the next token is a closing parenthesis, return it.
-  /// 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;
-    if (optional(')', next)) {
-      return next;
-    }
-    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);
-    }
-
-    // TODO(danrubel): Pass in context for better error message.
-    reportRecoverableError(
-        next, fasta.templateExpectedButGot.withArguments(')'));
-
-    // Scanner guarantees a closing parenthesis
-    // TODO(danrubel): Improve recovery by having callers parse tokens
-    // between `token` and `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;
-    if (optional(':', next)) return next;
-    Message message = fasta.templateExpectedButGot.withArguments(':');
-    Token newToken = new SyntheticToken(TokenType.COLON, next.charOffset);
-    return rewriteAndRecover(token, message, newToken);
-  }
-
-  /// If the token after [token] is a not literal string,
-  /// then insert a synthetic literal string.
-  /// Call `parseLiteralString` and return the result.
-  Token ensureLiteralString(Token token) {
-    Token next = token.next;
-    if (!identical(next.kind, STRING_TOKEN)) {
-      Message message = fasta.templateExpectedString.withArguments(next);
-      Token newToken =
-          new SyntheticStringToken(TokenType.STRING, '""', next.charOffset, 0);
-      rewriteAndRecover(token, message, newToken);
-    }
-    return parseLiteralString(token);
-  }
-
-  /// If the token after [token] is a semi-colon, return it.
-  /// Otherwise, report an error, insert a synthetic semi-colon,
-  /// and return the inserted semi-colon.
-  Token ensureSemicolon(Token token) {
-    // 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;
-    if (optional(';', next)) return next;
-
-    // Find a token on the same line as where the ';' should be inserted.
-    // Reporting the error on this token makes it easier
-    // for users to understand and fix the error.
-    reportRecoverableError(findPreviousNonZeroLengthToken(token),
-        fasta.templateExpectedAfterButGot.withArguments(';'));
-    return rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
-  }
-
-  /// 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, Message message, Token newToken) {
-    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;
-    assert(optional('[]', next));
-    Token replacement = link(
-        new BeginToken(TokenType.OPEN_SQUARE_BRACKET, next.offset),
-        new Token(TokenType.CLOSE_SQUARE_BRACKET, next.offset + 1));
-    rewriter.replaceTokenFollowing(token, replacement);
-    return token;
-  }
-
-  /// 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;
-    if (next.keyword == null) {
-      final String nextValue = next.next.stringValue;
-      for (String expectedValue in expectedNext) {
-        if (identical(nextValue, expectedValue)) {
-          reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-          return next;
-        }
-      }
-    }
-    return token;
-  }
-
-  Token parseNativeClause(Token token) {
-    Token nativeToken = token = token.next;
-    assert(optional('native', nativeToken));
-    bool hasName = false;
-    if (token.next.kind == STRING_TOKEN) {
-      hasName = true;
-      token = parseLiteralString(token);
-    }
-    listener.handleNativeClause(nativeToken, hasName);
-    reportRecoverableError(
-        nativeToken, fasta.messageNativeClauseShouldBeAnnotation);
-    return token;
-  }
-
-  Token skipClassOrMixinOrExtensionBody(Token token) {
-    // The scanner ensures that `{` always has a closing `}`.
-    return ensureBlock(token, null, null);
-  }
-
-  /// ```
-  /// classBody:
-  ///   '{' classMember* '}'
-  /// ;
-  /// ```
-  Token parseClassOrMixinOrExtensionBody(
-      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)) {
-      token = parseClassOrMixinOrExtensionMemberImpl(
-          token, kind, enclosingDeclarationName);
-      ++count;
-    }
-    token = token.next;
-    assert(optional('}', token));
-    listener.endClassOrMixinBody(kind, count, begin, token);
-    return token;
-  }
-
-  bool isUnaryMinus(Token token) =>
-      token.kind == IDENTIFIER_TOKEN &&
-      token.lexeme == 'unary' &&
-      optional('-', token.next);
-
-  /// Parse a class member.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseClassMember(Token token, String className) {
-    return parseClassOrMixinOrExtensionMemberImpl(
-            syntheticPreviousToken(token), DeclarationKind.Class, className)
-        .next;
-  }
-
-  /// Parse a mixin member.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseMixinMember(Token token, String mixinName) {
-    return parseClassOrMixinOrExtensionMemberImpl(
-            syntheticPreviousToken(token), DeclarationKind.Mixin, mixinName)
-        .next;
-  }
-
-  /// Parse an extension member.
-  ///
-  /// This method is only invoked from outside the parser. As a result, this
-  /// method takes the next token to be consumed rather than the last consumed
-  /// token and returns the token after the last consumed token rather than the
-  /// last consumed token.
-  Token parseExtensionMember(Token token, String extensionName) {
-    return parseClassOrMixinOrExtensionMemberImpl(syntheticPreviousToken(token),
-            DeclarationKind.Extension, extensionName)
-        .next;
-  }
-
-  /// ```
-  /// classMember:
-  ///   fieldDeclaration |
-  ///   constructorDeclaration |
-  ///   methodDeclaration
-  /// ;
-  ///
-  /// mixinMember:
-  ///   fieldDeclaration |
-  ///   methodDeclaration
-  /// ;
-  ///
-  /// extensionMember:
-  ///   staticFieldDeclaration |
-  ///   methodDeclaration
-  /// ;
-  /// ```
-  Token parseClassOrMixinOrExtensionMemberImpl(
-      Token token, DeclarationKind kind, String enclosingDeclarationName) {
-    Token beforeStart = token = parseMetadataStar(token);
-
-    Token covariantToken;
-    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;
-      }
-      if (isModifier(next)) {
-        if (optional('static', next)) {
-          staticToken = token = next;
-          next = token.next;
-        } else if (optional('covariant', next)) {
-          covariantToken = token = next;
-          next = token.next;
-        }
-        if (isModifier(next)) {
-          if (optional('final', next)) {
-            varFinalOrConst = token = next;
-            next = token.next;
-          } else if (optional('var', next)) {
-            varFinalOrConst = token = next;
-            next = token.next;
-          } else if (optional('const', next) && covariantToken == null) {
-            varFinalOrConst = token = next;
-            next = token.next;
-          } else if (optional('late', next)) {
-            lateToken = token = next;
-            next = token.next;
-            if (isModifier(next) && optional('final', next)) {
-              varFinalOrConst = token = next;
-              next = token.next;
-            }
-          }
-          if (isModifier(next)) {
-            ModifierRecoveryContext context = new ModifierRecoveryContext(this)
-              ..covariantToken = covariantToken
-              ..externalToken = externalToken
-              ..lateToken = lateToken
-              ..staticToken = staticToken
-              ..varFinalOrConst = varFinalOrConst;
-
-            token = context.parseClassMemberModifiers(token);
-            next = token.next;
-
-            covariantToken = context.covariantToken;
-            externalToken = context.externalToken;
-            lateToken = context.lateToken;
-            staticToken = context.staticToken;
-            varFinalOrConst = context.varFinalOrConst;
-
-            context = null;
-          }
-        }
-      }
-    }
-
-    listener.beginMember();
-
-    Token beforeType = token;
-    TypeInfo typeInfo = computeType(token, false, true);
-    token = typeInfo.skipType(token);
-    next = token.next;
-
-    Token getOrSet;
-    if (next.type != TokenType.IDENTIFIER) {
-      String value = next.stringValue;
-      if (identical(value, 'get') || identical(value, 'set')) {
-        if (next.next.isIdentifier) {
-          getOrSet = token = next;
-          next = token.next;
-        }
-        // Fall through to continue parsing `get` or `set` as an identifier.
-      } else if (identical(value, 'factory')) {
-        Token next2 = next.next;
-        if (next2.isIdentifier || next2.isModifier) {
-          if (beforeType != token) {
-            reportRecoverableError(token, fasta.messageTypeBeforeFactory);
-          }
-          token = parseFactoryMethod(token, kind, beforeStart, externalToken,
-              staticToken ?? covariantToken, varFinalOrConst);
-          listener.endMember();
-          return token;
-        }
-        // Fall through to continue parsing `factory` as an identifier.
-      } else if (identical(value, 'operator')) {
-        Token next2 = next.next;
-        TypeParamOrArgInfo typeParam = computeTypeParamOrArg(next);
-        // `operator` can be used as an identifier as in
-        // `int operator<T>()` or `int operator = 2`
-        if (next2.isUserDefinableOperator && typeParam == noTypeParamOrArg) {
-          token = parseMethod(
-              beforeStart,
-              externalToken,
-              staticToken,
-              covariantToken,
-              lateToken,
-              varFinalOrConst,
-              beforeType,
-              typeInfo,
-              getOrSet,
-              token.next,
-              kind,
-              enclosingDeclarationName);
-          listener.endMember();
-          return token;
-        } else if (optional('===', next2) ||
-            optional('!==', next2) ||
-            (next2.isOperator &&
-                !optional('=', next2) &&
-                !optional('<', next2))) {
-          // Recovery: Invalid operator
-          return parseInvalidOperatorDeclaration(
-              beforeStart,
-              externalToken,
-              staticToken,
-              covariantToken,
-              lateToken,
-              varFinalOrConst,
-              beforeType,
-              kind);
-        } else if (isUnaryMinus(next2)) {
-          // Recovery
-          token = parseMethod(
-              beforeStart,
-              externalToken,
-              staticToken,
-              covariantToken,
-              lateToken,
-              varFinalOrConst,
-              beforeType,
-              typeInfo,
-              getOrSet,
-              token.next,
-              kind,
-              enclosingDeclarationName);
-          listener.endMember();
-          return token;
-        }
-        // Fall through to continue parsing `operator` as an identifier.
-      } else if (!next.isIdentifier ||
-          (identical(value, 'typedef') &&
-              token == beforeStart &&
-              next.next.isIdentifier)) {
-        // Recovery
-        return recoverFromInvalidMember(
-            token,
-            beforeStart,
-            externalToken,
-            staticToken,
-            covariantToken,
-            lateToken,
-            varFinalOrConst,
-            beforeType,
-            typeInfo,
-            getOrSet,
-            kind,
-            enclosingDeclarationName);
-      }
-    } else if (typeInfo == noType && varFinalOrConst == null) {
-      Token next2 = next.next;
-      if (next2.isUserDefinableOperator && next2.endGroup == null) {
-        String value = next2.next.stringValue;
-        if (identical(value, '(') ||
-            identical(value, '{') ||
-            identical(value, '=>')) {
-          // Recovery: Missing `operator` keyword
-          return parseInvalidOperatorDeclaration(
-              beforeStart,
-              externalToken,
-              staticToken,
-              covariantToken,
-              lateToken,
-              varFinalOrConst,
-              beforeType,
-              kind);
-        }
-      }
-    }
-
-    // At this point, token is before the name, and next is the name
-    next = next.next;
-    String value = next.stringValue;
-    if (getOrSet != null ||
-        identical(value, '(') ||
-        identical(value, '{') ||
-        identical(value, '<') ||
-        identical(value, '.') ||
-        identical(value, '=>')) {
-      token = parseMethod(
-          beforeStart,
-          externalToken,
-          staticToken,
-          covariantToken,
-          lateToken,
-          varFinalOrConst,
-          beforeType,
-          typeInfo,
-          getOrSet,
-          token.next,
-          kind,
-          enclosingDeclarationName);
-    } else {
-      if (getOrSet != null) {
-        reportRecoverableErrorWithToken(
-            getOrSet, fasta.templateExtraneousModifier);
-      }
-      token = parseFields(
-          beforeStart,
-          externalToken,
-          staticToken,
-          covariantToken,
-          lateToken,
-          varFinalOrConst,
-          beforeType,
-          typeInfo,
-          token.next,
-          kind);
-    }
-    listener.endMember();
-    return token;
-  }
-
-  Token parseMethod(
-      Token beforeStart,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      Token beforeType,
-      TypeInfo typeInfo,
-      Token getOrSet,
-      Token name,
-      DeclarationKind kind,
-      String enclosingDeclarationName) {
-    if (lateToken != null) {
-      reportRecoverableErrorWithToken(
-          lateToken, fasta.templateExtraneousModifier);
-    }
-    bool isOperator = false;
-    if (getOrSet == null && optional('operator', name)) {
-      Token operator = name.next;
-      if (operator.isOperator ||
-          identical(operator.kind, EQ_EQ_EQ_TOKEN) ||
-          identical(operator.kind, BANG_EQ_EQ_TOKEN) ||
-          isUnaryMinus(operator)) {
-        isOperator = true;
-      }
-    }
-
-    if (staticToken != null) {
-      if (isOperator) {
-        reportRecoverableError(staticToken, fasta.messageStaticOperator);
-        staticToken = null;
-      }
-    } else if (covariantToken != null) {
-      if (getOrSet == null || optional('get', getOrSet)) {
-        reportRecoverableError(covariantToken, fasta.messageCovariantMember);
-        covariantToken = null;
-      }
-    }
-    if (varFinalOrConst != null) {
-      if (optional('const', varFinalOrConst)) {
-        if (getOrSet != null) {
-          reportRecoverableErrorWithToken(
-              varFinalOrConst, fasta.templateExtraneousModifier);
-          varFinalOrConst = null;
-        }
-      } else if (optional('var', varFinalOrConst)) {
-        reportRecoverableError(varFinalOrConst, fasta.messageVarReturnType);
-        varFinalOrConst = null;
-      } else {
-        assert(optional('final', varFinalOrConst));
-        reportRecoverableErrorWithToken(
-            varFinalOrConst, fasta.templateExtraneousModifier);
-        varFinalOrConst = null;
-      }
-    }
-
-    // TODO(danrubel): Consider parsing the name before calling beginMethod
-    // rather than passing the name token into beginMethod.
-    listener.beginMethod(externalToken, staticToken, covariantToken,
-        varFinalOrConst, getOrSet, name);
-
-    Token token = typeInfo.parseType(beforeType, this);
-    assert(token.next == (getOrSet ?? name));
-    token = getOrSet ?? token;
-
-    if (isOperator) {
-      token = parseOperatorName(token);
-    } else {
-      token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
-      if (getOrSet == null) {
-        token = parseQualifiedRestOpt(
-            token, IdentifierContext.methodDeclarationContinuation);
-      }
-    }
-
-    bool isGetter = false;
-    if (getOrSet == null) {
-      token = parseMethodTypeVar(token);
-    } else {
-      isGetter = optional("get", getOrSet);
-      listener.handleNoTypeVariables(token.next);
-    }
-
-    Token beforeParam = token;
-    Token beforeInitializers = parseGetterOrFormalParameters(
-        token,
-        name,
-        isGetter,
-        kind == DeclarationKind.Extension
-            ? staticToken != null
-                ? MemberKind.ExtensionStaticMethod
-                : MemberKind.ExtensionNonStaticMethod
-            : staticToken != null
-                ? MemberKind.StaticMethod
-                : MemberKind.NonStaticMethod);
-    token = parseInitializersOpt(beforeInitializers);
-    if (token == beforeInitializers) beforeInitializers = null;
-
-    AsyncModifier savedAsyncModifier = asyncState;
-    Token asyncToken = token.next;
-    token = parseAsyncModifierOpt(token);
-    if (getOrSet != null && !inPlainSync && optional("set", getOrSet)) {
-      reportRecoverableError(asyncToken, fasta.messageSetterNotSync);
-    }
-    final Token bodyStart = token.next;
-    if (externalToken != null) {
-      if (!optional(';', bodyStart)) {
-        reportRecoverableError(bodyStart, fasta.messageExternalMethodWithBody);
-      }
-    }
-    if (optional('=', bodyStart)) {
-      reportRecoverableError(bodyStart, fasta.messageRedirectionInNonFactory);
-      token = parseRedirectingFactoryBody(token);
-    } else {
-      token = parseFunctionBody(token, false,
-          (staticToken == null || externalToken != null) && inPlainSync);
-    }
-    asyncState = savedAsyncModifier;
-
-    bool isConstructor = false;
-    if (optional('.', name.next) || beforeInitializers != null) {
-      isConstructor = true;
-      if (name.lexeme != enclosingDeclarationName) {
-        // Recovery: The name does not match,
-        // but the name is prefixed or the declaration contains initializers.
-        // Report an error and continue with invalid name.
-        // TODO(danrubel): report invalid constructor name
-        // Currently multiple listeners report this error, but that logic should
-        // be removed and the error reported here instead.
-      }
-      if (getOrSet != null) {
-        // Recovery
-        if (optional('.', name.next)) {
-          // Unexpected get/set before constructor.
-          // Report an error and skip over the token.
-          // TODO(danrubel): report an error on get/set token
-          // This is currently reported by listeners other than AstBuilder.
-          // It should be reported here rather than in the listeners.
-        } else {
-          isConstructor = false;
-          if (beforeInitializers != null) {
-            // Unexpected initializers after get/set declaration.
-            // Report an error on the initializers
-            // and continue with the get/set declaration.
-            // TODO(danrubel): report invalid initializers error
-            // Currently multiple listeners report this error, but that logic
-            // should be removed and the error reported here instead.
-          }
-        }
-      }
-    } else if (name.lexeme == enclosingDeclarationName) {
-      if (getOrSet != null) {
-        // Recovery: The get/set member name is invalid.
-        // Report an error and continue with invalid name.
-        // TODO(danrubel): report invalid get/set member name
-        // Currently multiple listeners report this error, but that logic should
-        // be removed and the error reported here instead.
-      } else {
-        isConstructor = true;
-      }
-    }
-
-    if (isConstructor) {
-      //
-      // constructor
-      //
-      if (staticToken != null) {
-        reportRecoverableError(staticToken, fasta.messageStaticConstructor);
-      }
-      switch (kind) {
-        case DeclarationKind.Class:
-          // TODO(danrubel): Remove getOrSet from constructor events
-          listener.endClassConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
-          break;
-        case DeclarationKind.Mixin:
-          reportRecoverableError(name, fasta.messageMixinDeclaresConstructor);
-          listener.endMixinConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
-          break;
-        case DeclarationKind.Extension:
-          reportRecoverableError(
-              name, fasta.messageExtensionDeclaresConstructor);
-          listener.endExtensionConstructor(getOrSet, beforeStart.next,
-              beforeParam.next, beforeInitializers?.next, token);
-          break;
-        case DeclarationKind.TopLevel:
-          throw "Internal error: TopLevel constructor.";
-          break;
-      }
-    } else {
-      //
-      // method
-      //
-      if (varFinalOrConst != null) {
-        assert(optional('const', varFinalOrConst));
-        reportRecoverableError(varFinalOrConst, fasta.messageConstMethod);
-      }
-      switch (kind) {
-        case DeclarationKind.Class:
-          // TODO(danrubel): Remove beginInitializers token from method events
-          listener.endClassMethod(getOrSet, beforeStart.next, beforeParam.next,
-              beforeInitializers?.next, token);
-          break;
-        case DeclarationKind.Mixin:
-          listener.endMixinMethod(getOrSet, beforeStart.next, beforeParam.next,
-              beforeInitializers?.next, token);
-          break;
-        case DeclarationKind.Extension:
-          if (optional(';', bodyStart) && externalToken == null) {
-            reportRecoverableError(isOperator ? name.next : name,
-                fasta.messageExtensionDeclaresAbstractMember);
-          }
-          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;
-    assert(optional('factory', factoryKeyword));
-
-    if (!isValidTypeReference(token.next)) {
-      // Recovery
-      ModifierRecoveryContext context = new ModifierRecoveryContext(this)
-        ..externalToken = externalToken
-        ..staticOrCovariant = staticOrCovariant
-        ..varFinalOrConst = varFinalOrConst;
-
-      token = context.parseModifiersAfterFactory(token);
-
-      externalToken = context.externalToken;
-      staticOrCovariant = context.staticToken ?? context.covariantToken;
-      varFinalOrConst = context.varFinalOrConst;
-
-      context = null;
-    }
-
-    if (staticOrCovariant != null) {
-      reportRecoverableErrorWithToken(
-          staticOrCovariant, fasta.templateExtraneousModifier);
-    }
-    if (varFinalOrConst != null && !optional('const', varFinalOrConst)) {
-      reportRecoverableErrorWithToken(
-          varFinalOrConst, fasta.templateExtraneousModifier);
-      varFinalOrConst = null;
-    }
-
-    listener.beginFactoryMethod(beforeStart, externalToken, varFinalOrConst);
-    token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
-    token = parseQualifiedRestOpt(
-        token, IdentifierContext.methodDeclarationContinuation);
-    token = parseMethodTypeVar(token);
-    token = parseFormalParametersRequiredOpt(token, MemberKind.Factory);
-    Token asyncToken = token.next;
-    token = parseAsyncModifierOpt(token);
-    Token next = token.next;
-    if (!inPlainSync) {
-      reportRecoverableError(asyncToken, fasta.messageFactoryNotSync);
-    }
-    if (optional('=', next)) {
-      if (externalToken != null) {
-        reportRecoverableError(next, fasta.messageExternalFactoryRedirection);
-      }
-      token = parseRedirectingFactoryBody(token);
-    } else if (externalToken != null) {
-      if (!optional(';', next)) {
-        reportRecoverableError(next, fasta.messageExternalFactoryWithBody);
-      }
-      token = parseFunctionBody(token, false, true);
-    } else {
-      if (varFinalOrConst != null && !optional('native', next)) {
-        if (optional('const', varFinalOrConst)) {
-          reportRecoverableError(varFinalOrConst, fasta.messageConstFactory);
-        }
-      }
-      token = parseFunctionBody(token, false, false);
-    }
-    switch (kind) {
-      case DeclarationKind.Class:
-        listener.endClassFactoryMethod(beforeStart.next, factoryKeyword, token);
-        break;
-      case DeclarationKind.Mixin:
-        reportRecoverableError(
-            factoryKeyword, fasta.messageMixinDeclaresConstructor);
-        listener.endMixinFactoryMethod(beforeStart.next, factoryKeyword, token);
-        break;
-      case DeclarationKind.Extension:
-        reportRecoverableError(
-            factoryKeyword, fasta.messageExtensionDeclaresConstructor);
-        listener.endExtensionFactoryMethod(
-            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;
-    assert(optional('operator', token));
-    Token next = token.next;
-    if (next.isUserDefinableOperator) {
-      if (computeTypeParamOrArg(token) != noTypeParamOrArg) {
-        // `operator` is being used as an identifier.
-        // For example: `int operator<T>(foo) => 0;`
-        listener.handleIdentifier(token, IdentifierContext.methodDeclaration);
-        return token;
-      } else {
-        listener.handleOperatorName(token, next);
-        return next;
-      }
-    } else if (optional('(', next)) {
-      return ensureIdentifier(beforeToken, IdentifierContext.operatorName);
-    } else if (isUnaryMinus(next)) {
-      // Recovery
-      reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-      next = next.next;
-      listener.handleOperatorName(token, next);
-      return next;
-    } else {
-      // Recovery
-      // Scanner reports an error for `===` and `!==`.
-      if (next.type != TokenType.EQ_EQ_EQ &&
-          next.type != TokenType.BANG_EQ_EQ) {
-        // The user has specified an invalid operator name.
-        // Report the error, accept the invalid operator name, and move on.
-        reportRecoverableErrorWithToken(next, fasta.templateInvalidOperator);
-      }
-      listener.handleInvalidOperatorName(token, next);
-      return next;
-    }
-  }
-
-  Token parseFunctionExpression(Token token) {
-    Token beginToken = token.next;
-    listener.beginFunctionExpression(beginToken);
-    token = parseFormalParametersRequiredOpt(token, MemberKind.Local);
-    token = parseAsyncOptBody(token, true, false);
-    listener.endFunctionExpression(beginToken, token.next);
-    return token;
-  }
-
-  Token parseFunctionLiteral(
-      Token start,
-      Token beforeName,
-      Token name,
-      TypeInfo typeInfo,
-      TypeParamOrArgInfo typeParam,
-      IdentifierContext context) {
-    Token formals = typeParam.parseVariables(name, this);
-    listener.beginNamedFunctionExpression(start.next);
-    typeInfo.parseType(start, this);
-    return parseNamedFunctionRest(beforeName, start.next, formals, true);
-  }
-
-  /// Parses the rest of a named function declaration starting from its [name]
-  /// but then skips any type parameters and continue parsing from [formals]
-  /// (the formal parameters).
-  ///
-  /// If [isFunctionExpression] is true, this method parses the rest of named
-  /// function expression which isn't legal syntax in Dart.  Useful for
-  /// recovering from Javascript code being pasted into a Dart program, as it
-  /// will interpret `function foo() {}` as a named function expression with
-  /// return type `function` and name `foo`.
-  ///
-  /// Precondition: the parser has previously generated these events:
-  ///
-  /// - Type variables.
-  /// - `beginLocalFunctionDeclaration` if [isFunctionExpression] is false,
-  ///   otherwise `beginNamedFunctionExpression`.
-  /// - Return type.
-  Token parseNamedFunctionRest(
-      Token beforeName, Token begin, Token formals, bool isFunctionExpression) {
-    Token token = beforeName.next;
-    listener.beginFunctionName(token);
-    token =
-        ensureIdentifier(beforeName, IdentifierContext.localFunctionDeclaration)
-            .next;
-    if (isFunctionExpression) {
-      reportRecoverableError(
-          beforeName.next, fasta.messageNamedFunctionExpression);
-    }
-    listener.endFunctionName(begin, token);
-    token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
-    token = parseInitializersOpt(token);
-    token = parseAsyncOptBody(token, isFunctionExpression, false);
-    if (isFunctionExpression) {
-      listener.endNamedFunctionExpression(token);
-    } else {
-      listener.endLocalFunctionDeclaration(token);
-    }
-    return token;
-  }
-
-  /// Parses a function body optionally preceded by an async modifier (see
-  /// [parseAsyncModifierOpt]).  This method is used in both expression context
-  /// (when [ofFunctionExpression] is true) and statement context. In statement
-  /// context (when [ofFunctionExpression] is false), and if the function body
-  /// is on the form `=> expression`, a trailing semicolon is required.
-  ///
-  /// It's an error if there's no function body unless [allowAbstract] is true.
-  Token parseAsyncOptBody(
-      Token token, bool ofFunctionExpression, bool allowAbstract) {
-    AsyncModifier savedAsyncModifier = asyncState;
-    token = parseAsyncModifierOpt(token);
-    token = parseFunctionBody(token, ofFunctionExpression, allowAbstract);
-    asyncState = savedAsyncModifier;
-    return token;
-  }
-
-  Token parseConstructorReference(Token token, [TypeParamOrArgInfo typeArg]) {
-    Token start =
-        ensureIdentifier(token, IdentifierContext.constructorReference);
-    listener.beginConstructorReference(start);
-    token = parseQualifiedRestOpt(
-        start, IdentifierContext.constructorReferenceContinuation);
-    typeArg ??= computeTypeParamOrArg(token);
-    token = typeArg.parseArguments(token, this);
-    Token period = null;
-    if (optional('.', token.next)) {
-      period = token.next;
-      token = ensureIdentifier(period,
-          IdentifierContext.constructorReferenceContinuationAfterTypeArguments);
-    } else {
-      listener.handleNoConstructorReferenceContinuationAfterTypeArguments(
-          token.next);
-    }
-    listener.endConstructorReference(start, period, token.next);
-    return token;
-  }
-
-  Token parseRedirectingFactoryBody(Token token) {
-    token = token.next;
-    assert(optional('=', token));
-    listener.beginRedirectingFactoryBody(token);
-    Token equals = token;
-    token = parseConstructorReference(token);
-    token = ensureSemicolon(token);
-    listener.endRedirectingFactoryBody(equals, token);
-    return token;
-  }
-
-  Token skipFunctionBody(Token token, bool isExpression, bool allowAbstract) {
-    assert(!isExpression);
-    token = skipAsyncModifier(token);
-    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;
-      if (optional(';', next)) {
-        listener.handleNativeFunctionBodySkipped(nativeToken, next);
-        return token.next;
-      }
-      listener.handleNativeFunctionBodyIgnored(nativeToken, next);
-      // Fall through to recover and skip function body
-    }
-    String value = next.stringValue;
-    if (identical(value, ';')) {
-      token = next;
-      if (!allowAbstract) {
-        reportRecoverableError(token, fasta.messageExpectedBody);
-      }
-      listener.handleNoFunctionBody(token);
-    } else if (identical(value, '=>')) {
-      token = parseExpression(next);
-      // 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;
-      }
-      listener.handleFunctionBodySkipped(token, true);
-    } else if (identical(value, '=')) {
-      token = next;
-      reportRecoverableError(token, fasta.messageExpectedBody);
-      token = parseExpression(token);
-      // 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;
-      }
-      listener.handleFunctionBodySkipped(token, true);
-    } else {
-      token = skipBlock(token);
-      listener.handleFunctionBodySkipped(token, false);
-    }
-    return token;
-  }
-
-  /// Parses a function body.  This method is used in both expression context
-  /// (when [ofFunctionExpression] is true) and statement context. In statement
-  /// context (when [ofFunctionExpression] is false), and if the function body
-  /// is on the form `=> expression`, a trailing semicolon is required.
-  ///
-  /// 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;
-    if (optional('native', next)) {
-      Token nativeToken = next;
-      token = parseNativeClause(token);
-      next = token.next;
-      if (optional(';', next)) {
-        listener.handleNativeFunctionBody(nativeToken, next);
-        return next;
-      }
-      reportRecoverableError(next, fasta.messageExternalMethodWithBody);
-      listener.handleNativeFunctionBodyIgnored(nativeToken, next);
-      // Ignore the native keyword and fall through to parse the body
-    }
-    if (optional(';', next)) {
-      if (!allowAbstract) {
-        reportRecoverableError(next, fasta.messageExpectedBody);
-      }
-      listener.handleEmptyFunctionBody(next);
-      return next;
-    } else if (optional('=>', next)) {
-      return parseExpressionFunctionBody(next, ofFunctionExpression);
-    } else if (optional('=', next)) {
-      // Recover from a bad factory method.
-      reportRecoverableError(next, fasta.messageExpectedBody);
-      next = rewriter.insertToken(
-          next, new SyntheticToken(TokenType.FUNCTION, next.next.charOffset));
-      Token begin = next;
-      token = parseExpression(next);
-      if (!ofFunctionExpression) {
-        token = ensureSemicolon(token);
-        listener.handleExpressionFunctionBody(begin, token);
-      } else {
-        listener.handleExpressionFunctionBody(begin, null);
-      }
-      return token;
-    }
-    Token begin = next;
-    int statementCount = 0;
-    if (!optional('{', next)) {
-      // Recovery
-      // If `return` used instead of `=>`, then report an error and continue
-      if (optional('return', next)) {
-        reportRecoverableError(next, fasta.messageExpectedBody);
-        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)) {
-        reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-        return parseExpressionFunctionBody(next.next, ofFunctionExpression);
-      }
-      if (next.isKeywordOrIdentifier && optional('{', next.next)) {
-        reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-        token = next;
-        begin = next = token.next;
-        // Fall through to parse the block.
-      } else {
-        token = ensureBlock(token, fasta.templateExpectedFunctionBody, null);
-        listener.handleInvalidFunctionBody(token);
-        return token.endGroup;
-      }
-    }
-
-    LoopState savedLoopState = loopState;
-    loopState = LoopState.OutsideLoop;
-    listener.beginBlockFunctionBody(begin);
-    token = next;
-    while (notEofOrValue('}', token.next)) {
-      Token startToken = token.next;
-      token = parseStatement(token);
-      if (identical(token.next, startToken)) {
-        // No progress was made, so we report the current token as being invalid
-        // and move forward.
-        reportRecoverableError(
-            token, fasta.templateUnexpectedToken.withArguments(token));
-        token = token.next;
-      }
-      ++statementCount;
-    }
-    token = token.next;
-    assert(optional('}', token));
-    listener.endBlockFunctionBody(statementCount, begin, token);
-    loopState = savedLoopState;
-    return token;
-  }
-
-  Token parseExpressionFunctionBody(Token token, bool ofFunctionExpression) {
-    assert(optional('=>', token));
-    Token begin = token;
-    token = parseExpression(token);
-    if (!ofFunctionExpression) {
-      token = ensureSemicolon(token);
-      listener.handleExpressionFunctionBody(begin, token);
-    } else {
-      listener.handleExpressionFunctionBody(begin, null);
-    }
-    if (inGenerator) {
-      listener.handleInvalidStatement(
-          begin, fasta.messageGeneratorReturnsValue);
-    }
-    return token;
-  }
-
-  Token skipAsyncModifier(Token token) {
-    String value = token.next.stringValue;
-    if (identical(value, 'async')) {
-      token = token.next;
-      value = token.next.stringValue;
-
-      if (identical(value, '*')) {
-        token = token.next;
-      }
-    } else if (identical(value, 'sync')) {
-      token = token.next;
-      value = token.next.stringValue;
-
-      if (identical(value, '*')) {
-        token = token.next;
-      }
-    }
-    return token;
-  }
-
-  Token parseAsyncModifierOpt(Token token) {
-    Token async;
-    Token star;
-    asyncState = AsyncModifier.Sync;
-    Token next = token.next;
-    if (optional('async', next)) {
-      async = token = next;
-      next = token.next;
-      if (optional('*', next)) {
-        asyncState = AsyncModifier.AsyncStar;
-        star = next;
-        token = next;
-      } else {
-        asyncState = AsyncModifier.Async;
-      }
-    } else if (optional('sync', next)) {
-      async = token = next;
-      next = token.next;
-      if (optional('*', next)) {
-        asyncState = AsyncModifier.SyncStar;
-        star = next;
-        token = next;
-      } else {
-        reportRecoverableError(async, fasta.messageInvalidSyncModifier);
-      }
-    }
-    listener.handleAsyncModifier(async, star);
-    if (!inPlainSync && optional(';', token.next)) {
-      reportRecoverableError(token.next, fasta.messageAbstractNotSync);
-    }
-    return token;
-  }
-
-  int statementDepth = 0;
-  Token parseStatement(Token token) {
-    if (statementDepth++ > 500) {
-      // This happens for degenerate programs, for example, a lot of nested
-      // if-statements. The language test deep_nesting2_negative_test, for
-      // example, provokes this.
-      return recoverFromStackOverflow(token);
-    }
-    Token result = parseStatementX(token);
-    statementDepth--;
-    return result;
-  }
-
-  Token parseStatementX(Token token) {
-    if (identical(token.next.kind, IDENTIFIER_TOKEN)) {
-      if (optional(':', token.next.next)) {
-        return parseLabeledStatement(token);
-      }
-      return parseExpressionStatementOrDeclarationAfterModifiers(
-          token, token, null, null, null, false);
-    }
-    final String value = token.next.stringValue;
-    if (identical(value, '{')) {
-      // The scanner ensures that `{` always has a closing `}`.
-      return parseBlock(token, null);
-    } else if (identical(value, 'return')) {
-      return parseReturnStatement(token);
-    } else if (identical(value, 'var') || identical(value, 'final')) {
-      Token varOrFinal = token.next;
-      if (!isModifier(varOrFinal.next)) {
-        return parseExpressionStatementOrDeclarationAfterModifiers(
-            varOrFinal, token, null, varOrFinal, null, false);
-      }
-      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, 'for')) {
-      return parseForStatement(token, null);
-    } else if (identical(value, 'rethrow')) {
-      return parseRethrowStatement(token);
-    } else if (identical(value, 'while')) {
-      return parseWhileStatement(token);
-    } else if (identical(value, 'do')) {
-      return parseDoWhileStatement(token);
-    } else if (identical(value, 'try')) {
-      return parseTryStatement(token);
-    } else if (identical(value, 'switch')) {
-      return parseSwitchStatement(token);
-    } else if (identical(value, 'break')) {
-      return parseBreakStatement(token);
-    } else if (identical(value, 'continue')) {
-      return parseContinueStatement(token);
-    } else if (identical(value, 'assert')) {
-      return parseAssertStatement(token);
-    } else if (identical(value, ';')) {
-      return parseEmptyStatement(token);
-    } else if (identical(value, 'yield')) {
-      switch (asyncState) {
-        case AsyncModifier.Sync:
-          if (optional(':', token.next.next)) {
-            return parseLabeledStatement(token);
-          }
-          return parseExpressionStatementOrDeclaration(token);
-
-        case AsyncModifier.SyncStar:
-        case AsyncModifier.AsyncStar:
-          return parseYieldStatement(token);
-
-        case AsyncModifier.Async:
-          reportRecoverableError(token.next, fasta.messageYieldNotGenerator);
-          return parseYieldStatement(token);
-      }
-      throw "Internal error: Unknown asyncState: '$asyncState'.";
-    } else if (identical(value, 'const')) {
-      return parseExpressionStatementOrConstDeclaration(token);
-    } else if (identical(value, 'await')) {
-      if (inPlainSync) {
-        if (!looksLikeAwaitExpression(token)) {
-          return parseExpressionStatementOrDeclaration(token);
-        }
-        // Recovery: looks like an expression preceded by `await`
-        // but not inside an async context.
-        // Fall through to parseExpressionStatement
-        // and parseAwaitExpression will report the error.
-      }
-      return parseExpressionStatement(token);
-    } else if (identical(value, 'set') && token.next.next.isIdentifier) {
-      // Recovery: invalid use of `set`
-      reportRecoverableErrorWithToken(
-          token.next, fasta.templateUnexpectedToken);
-      return parseStatementX(token.next);
-    } else if (token.next.isIdentifier) {
-      if (optional(':', token.next.next)) {
-        return parseLabeledStatement(token);
-      }
-      return parseExpressionStatementOrDeclaration(token);
-    } else {
-      return parseExpressionStatementOrDeclaration(token);
-    }
-  }
-
-  /// ```
-  /// yieldStatement:
-  ///   'yield' expression? ';'
-  /// ;
-  /// ```
-  Token parseYieldStatement(Token token) {
-    Token begin = token = token.next;
-    assert(optional('yield', token));
-    listener.beginYieldStatement(begin);
-    Token starToken;
-    if (optional('*', token.next)) {
-      starToken = token = token.next;
-    }
-    token = parseExpression(token);
-    token = ensureSemicolon(token);
-    listener.endYieldStatement(begin, starToken, token);
-    return token;
-  }
-
-  /// ```
-  /// returnStatement:
-  ///   'return' expression? ';'
-  /// ;
-  /// ```
-  Token parseReturnStatement(Token token) {
-    Token begin = token = token.next;
-    assert(optional('return', token));
-    listener.beginReturnStatement(begin);
-    Token next = token.next;
-    if (optional(';', next)) {
-      listener.endReturnStatement(false, begin, next);
-      return next;
-    }
-    token = parseExpression(token);
-    token = ensureSemicolon(token);
-    listener.endReturnStatement(true, begin, token);
-    if (inGenerator) {
-      listener.handleInvalidStatement(
-          begin, fasta.messageGeneratorReturnsValue);
-    }
-    return token;
-  }
-
-  /// ```
-  /// label:
-  ///   identifier ':'
-  /// ;
-  /// ```
-  Token parseLabel(Token token) {
-    assert(token.next.isIdentifier);
-    token = ensureIdentifier(token, IdentifierContext.labelDeclaration).next;
-    assert(optional(':', token));
-    listener.handleLabel(token);
-    return token;
-  }
-
-  /// ```
-  /// statement:
-  ///   label* nonLabelledStatement
-  /// ;
-  /// ```
-  Token parseLabeledStatement(Token token) {
-    Token next = token.next;
-    assert(next.isIdentifier);
-    assert(optional(':', next.next));
-    int labelCount = 0;
-    do {
-      token = parseLabel(token);
-      next = token.next;
-      labelCount++;
-    } while (next.isIdentifier && optional(':', next.next));
-    listener.beginLabeledStatement(next, labelCount);
-    token = parseStatement(token);
-    listener.endLabeledStatement(labelCount);
-    return token;
-  }
-
-  /// ```
-  /// expressionStatement:
-  ///   expression? ';'
-  /// ;
-  /// ```
-  ///
-  /// Note: This method can fail to make progress. If there is neither an
-  /// expression nor a semi-colon, then a synthetic identifier and synthetic
-  /// semicolon will be inserted before [token] and the semicolon will be
-  /// returned.
-  Token parseExpressionStatement(Token token) {
-    // TODO(brianwilkerson): If the next token is not the start of a valid
-    // expression, then this method shouldn't report that we have an expression
-    // statement.
-    token = parseExpression(token);
-    token = ensureSemicolon(token);
-    listener.handleExpressionStatement(token);
-    return token;
-  }
-
-  int expressionDepth = 0;
-  Token parseExpression(Token token) {
-    if (expressionDepth++ > 500) {
-      // 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;
-      reportRecoverableError(next, fasta.messageStackOverflow);
-
-      // Recovery
-      Token endGroup = next.endGroup;
-      if (endGroup != null) {
-        while (!next.isEof && !identical(next, endGroup)) {
-          token = next;
-          next = token.next;
-        }
-      } else {
-        while (!isOneOf(next, const [')', ']', '}', ';'])) {
-          token = next;
-          next = token.next;
-        }
-      }
-      if (!token.isEof) {
-        token = rewriter.insertSyntheticIdentifier(token);
-        listener.handleIdentifier(token, IdentifierContext.expression);
-      }
-    } else {
-      token = optional('throw', token.next)
-          ? parseThrowExpression(token, true)
-          : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, true);
-    }
-    expressionDepth--;
-    return token;
-  }
-
-  Token parseExpressionWithoutCascade(Token token) {
-    return optional('throw', token.next)
-        ? parseThrowExpression(token, false)
-        : parsePrecedenceExpression(token, ASSIGNMENT_PRECEDENCE, false);
-  }
-
-  Token parseConditionalExpressionRest(Token token) {
-    Token question = token = token.next;
-    assert(optional('?', question));
-    listener.beginConditionalExpression(token);
-    token = parseExpressionWithoutCascade(token);
-    Token colon = ensureColon(token);
-    listener.handleConditionalExpressionColon();
-    token = parseExpressionWithoutCascade(colon);
-    listener.endConditionalExpression(question, colon);
-    return token;
-  }
-
-  Token parsePrecedenceExpression(
-      Token token, int precedence, bool allowCascades) {
-    assert(precedence >= 1);
-    assert(precedence <= SELECTOR_PRECEDENCE);
-    token = parseUnaryExpression(token, allowCascades);
-    TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
-    if (typeArg != noTypeParamOrArg) {
-      // For example a(b)<T>(c), where token is before '<'.
-      token = typeArg.parseArguments(token, this);
-      assert(optional('(', token.next));
-    }
-    Token next = token.next;
-    TokenType type = next.type;
-    int tokenLevel = _computePrecedence(next);
-    for (int level = tokenLevel; level >= precedence; --level) {
-      int lastBinaryExpressionLevel = -1;
-      Token lastCascade;
-      while (identical(tokenLevel, level)) {
-        Token operator = next;
-        if (identical(tokenLevel, CASCADE_PRECEDENCE)) {
-          if (!allowCascades) {
-            return token;
-          } else if (lastCascade != null && optional('?..', next)) {
-            reportRecoverableError(
-                next, fasta.messageNullAwareCascadeOutOfOrder);
-          }
-          lastCascade = next;
-          token = parseCascadeExpression(token);
-        } 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)
-              ? parseThrowExpression(next, 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);
-            token = next;
-          } else if (identical(type, TokenType.BANG)) {
-            listener.handleNonNullAssertExpression(next);
-            token = next;
-          }
-        } else if (identical(tokenLevel, SELECTOR_PRECEDENCE)) {
-          if (identical(type, TokenType.PERIOD) ||
-              identical(type, TokenType.QUESTION_PERIOD)) {
-            // Left associative, so we recurse at the next higher precedence
-            // level. However, SELECTOR_PRECEDENCE is the highest level, so we
-            // should just call [parseUnaryExpression] directly. However, a
-            // unary expression isn't legal after a period, so we call
-            // [parsePrimary] instead.
-            token = parsePrimary(
-                token.next, IdentifierContext.expressionContinuation);
-            listener.endBinaryExpression(operator);
-          } else if (identical(type, TokenType.OPEN_PAREN) ||
-              identical(type, TokenType.OPEN_SQUARE_BRACKET) ||
-              identical(type, TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET)) {
-            token = parseArgumentOrIndexStar(token, typeArg);
-          } else if (identical(type, TokenType.INDEX)) {
-            BeginToken replacement = link(
-                new BeginToken(TokenType.OPEN_SQUARE_BRACKET, next.charOffset,
-                    next.precedingComments),
-                new Token(TokenType.CLOSE_SQUARE_BRACKET, next.charOffset + 1));
-            rewriter.replaceTokenFollowing(token, replacement);
-            replacement.endToken = replacement.next;
-            token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
-          } else if (identical(type, TokenType.BANG)) {
-            listener.handleNonNullAssertExpression(token.next);
-            token = next;
-          } else {
-            // Recovery
-            reportRecoverableErrorWithToken(
-                token.next, fasta.templateUnexpectedToken);
-            token = next;
-          }
-        } else if (identical(type, TokenType.IS)) {
-          token = parseIsOperatorRest(token);
-        } else if (identical(type, TokenType.AS)) {
-          token = parseAsOperatorRest(token);
-        } else if (identical(type, TokenType.QUESTION)) {
-          token = parseConditionalExpressionRest(token);
-        } else {
-          if (level == EQUALITY_PRECEDENCE || level == RELATIONAL_PRECEDENCE) {
-            // We don't allow (a == b == c) or (a < b < c).
-            if (lastBinaryExpressionLevel == level) {
-              // Report an error, then continue parsing as if it is legal.
-              reportRecoverableError(
-                  next, fasta.messageEqualityCannotBeEqualityOperand);
-            } else {
-              // Set a flag to catch subsequent binary expressions of this type.
-              lastBinaryExpressionLevel = level;
-            }
-          }
-          listener.beginBinaryExpression(next);
-          // Left associative, so we recurse at the next higher
-          // precedence level.
-          token =
-              parsePrecedenceExpression(token.next, level + 1, allowCascades);
-          listener.endBinaryExpression(operator);
-        }
-        next = token.next;
-        type = next.type;
-        tokenLevel = _computePrecedence(next);
-      }
-    }
-    return token;
-  }
-
-  int _computePrecedence(Token token) {
-    TokenType type = token.type;
-    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;
-      if (identical(nextType, TokenType.PERIOD) ||
-          identical(nextType, TokenType.OPEN_PAREN) ||
-          identical(nextType, TokenType.OPEN_SQUARE_BRACKET)) {
-        return SELECTOR_PRECEDENCE;
-      }
-      return POSTFIX_PRECEDENCE;
-    }
-    return type.precedence;
-  }
-
-  Token parseCascadeExpression(Token token) {
-    Token cascadeOperator = token = token.next;
-    assert(optional('..', cascadeOperator) || optional('?..', cascadeOperator));
-    listener.beginCascade(cascadeOperator);
-    if (optional('[', token.next)) {
-      token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
-    } else {
-      token = parseSend(token, IdentifierContext.expressionContinuation);
-      listener.endBinaryExpression(cascadeOperator);
-    }
-    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;
-        listener.endBinaryExpression(period);
-      }
-      TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
-      if (typeArg != noTypeParamOrArg) {
-        // For example a(b)..<T>(c), where token is '<'.
-        token = typeArg.parseArguments(token, this);
-        next = token.next;
-        assert(optional('(', next));
-      }
-      token = parseArgumentOrIndexStar(token, typeArg);
-      next = token.next;
-    } while (!identical(mark, token));
-
-    if (identical(next.type.precedence, ASSIGNMENT_PRECEDENCE)) {
-      Token assignment = next;
-      token = parseExpressionWithoutCascade(next);
-      listener.handleAssignmentExpression(assignment);
-    }
-    listener.endCascade();
-    return token;
-  }
-
-  Token parseUnaryExpression(Token token, bool allowCascades) {
-    String value = token.next.stringValue;
-    // Prefix:
-    if (identical(value, 'await')) {
-      if (inPlainSync) {
-        if (!looksLikeAwaitExpression(token)) {
-          return parsePrimary(token, IdentifierContext.expression);
-        }
-        // Recovery: Looks like an expression preceded by `await`.
-        // Fall through and let parseAwaitExpression report the error.
-      }
-      return parseAwaitExpression(token, allowCascades);
-    } else if (identical(value, '+')) {
-      // Dart no longer allows prefix-plus.
-      rewriteAndRecover(
-          token,
-          // TODO(danrubel): Consider reporting "missing identifier" instead.
-          fasta.messageUnsupportedPrefixPlus,
-          new SyntheticStringToken(
-              TokenType.IDENTIFIER, '', token.next.offset));
-      return parsePrimary(token, IdentifierContext.expression);
-    } else if ((identical(value, '!')) ||
-        (identical(value, '-')) ||
-        (identical(value, '~'))) {
-      Token operator = token.next;
-      // Right associative, so we recurse at the same precedence
-      // level.
-      token = parsePrecedenceExpression(
-          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;
-      // Right associative, so we recurse at the same precedence
-      // level.
-      token = parsePrecedenceExpression(
-          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;
-      }
-      if (identifier.isIdentifier) {
-        // Looking at `identifier ('.' identifier)?`.
-        if (optional("<", identifier.next)) {
-          TypeParamOrArgInfo typeArg = computeTypeParamOrArg(identifier);
-          if (typeArg != noTypeParamOrArg) {
-            Token endTypeArguments = typeArg.skip(identifier);
-            if (optional(".", endTypeArguments.next)) {
-              return parseImplicitCreationExpression(token, typeArg);
-            }
-          }
-        }
-      }
-    }
-    return parsePrimary(token, IdentifierContext.expression);
-  }
-
-  Token parseArgumentOrIndexStar(Token token, TypeParamOrArgInfo typeArg) {
-    Token next = token.next;
-    Token beginToken = next;
-    while (true) {
-      if (optional('[', next) || optional('?.[', next)) {
-        assert(typeArg == noTypeParamOrArg);
-        Token openSquareBracket = next;
-        bool old = mayParseFunctionExpressions;
-        mayParseFunctionExpressions = true;
-        token = parseExpression(next);
-        next = token.next;
-        mayParseFunctionExpressions = old;
-        if (!optional(']', next)) {
-          // Recovery
-          reportRecoverableError(
-              next, fasta.templateExpectedButGot.withArguments(']'));
-          // Scanner ensures a closing ']'
-          Token endGroup = openSquareBracket.endGroup;
-          if (endGroup.isSynthetic) {
-            // Scanner inserted closing ']' in the wrong place, so move it.
-            next = rewriter.moveSynthetic(token, endGroup);
-          } else {
-            // Skip over unexpected tokens to where the user placed the `]`.
-            next = endGroup;
-          }
-        }
-        listener.handleIndexedExpression(openSquareBracket, next);
-        token = next;
-        typeArg = computeMethodTypeArguments(token);
-        if (typeArg != noTypeParamOrArg) {
-          // For example a[b]<T>(c), where token is before '<'.
-          token = typeArg.parseArguments(token, this);
-          assert(optional('(', token.next));
-        }
-        next = token.next;
-      } else if (optional('(', next)) {
-        if (typeArg == noTypeParamOrArg) {
-          listener.handleNoTypeArguments(next);
-        }
-        token = parseArguments(token);
-        listener.handleSend(beginToken, token);
-        typeArg = computeMethodTypeArguments(token);
-        if (typeArg != noTypeParamOrArg) {
-          // For example a(b)<T>(c), where token is before '<'.
-          token = typeArg.parseArguments(token, this);
-          assert(optional('(', token.next));
-        }
-        next = token.next;
-      } else {
-        break;
-      }
-    }
-    return token;
-  }
-
-  Token parsePrimary(Token token, IdentifierContext context) {
-    final int kind = token.next.kind;
-    if (kind == IDENTIFIER_TOKEN) {
-      return parseSendOrFunctionLiteral(token, context);
-    } else if (kind == INT_TOKEN || kind == HEXADECIMAL_TOKEN) {
-      return parseLiteralInt(token);
-    } else if (kind == DOUBLE_TOKEN) {
-      return parseLiteralDouble(token);
-    } else if (kind == STRING_TOKEN) {
-      return parseLiteralString(token);
-    } else if (kind == HASH_TOKEN) {
-      return parseLiteralSymbol(token);
-    } else if (kind == KEYWORD_TOKEN) {
-      final String value = token.next.stringValue;
-      if (identical(value, "true") || identical(value, "false")) {
-        return parseLiteralBool(token);
-      } else if (identical(value, "null")) {
-        return parseLiteralNull(token);
-      } else if (identical(value, "this")) {
-        return parseThisExpression(token, context);
-      } else if (identical(value, "super")) {
-        return parseSuperExpression(token, context);
-      } else if (identical(value, "new")) {
-        return parseNewExpression(token);
-      } else if (identical(value, "const")) {
-        return parseConstExpression(token);
-      } else if (identical(value, "void")) {
-        return parseSendOrFunctionLiteral(token, context);
-      } else if (!inPlainSync &&
-          (identical(value, "yield") || identical(value, "async"))) {
-        // Fall through to the recovery code.
-      } else if (identical(value, "assert")) {
-        return parseAssert(token, Assert.Expression);
-      } else if (token.next.isIdentifier) {
-        return parseSendOrFunctionLiteral(token, context);
-      } else if (identical(value, "return")) {
-        // Recovery
-        token = token.next;
-        reportRecoverableErrorWithToken(token, fasta.templateUnexpectedToken);
-        return parsePrimary(token, context);
-      } else {
-        // Fall through to the recovery code.
-      }
-    } else if (kind == OPEN_PAREN_TOKEN) {
-      return parseParenthesizedExpressionOrFunctionLiteral(token);
-    } else if (kind == OPEN_SQUARE_BRACKET_TOKEN ||
-        optional('[]', token.next)) {
-      listener.handleNoTypeArguments(token.next);
-      return parseLiteralListSuffix(token, null);
-    } else if (kind == OPEN_CURLY_BRACKET_TOKEN) {
-      listener.handleNoTypeArguments(token.next);
-      return parseLiteralSetOrMapSuffix(token, null);
-    } else if (kind == LT_TOKEN) {
-      return parseLiteralListSetMapOrFunction(token, null);
-    } else {
-      // Fall through to the recovery code.
-    }
-    //
-    // Recovery code.
-    //
-    return parseSend(token, context);
-  }
-
-  Token parseParenthesizedExpressionOrFunctionLiteral(Token token) {
-    Token next = token.next;
-    assert(optional('(', next));
-    Token nextToken = next.endGroup.next;
-    int kind = nextToken.kind;
-    if (mayParseFunctionExpressions) {
-      if ((identical(kind, FUNCTION_TOKEN) ||
-          identical(kind, OPEN_CURLY_BRACKET_TOKEN))) {
-        listener.handleNoTypeVariables(next);
-        return parseFunctionExpression(token);
-      } else if (identical(kind, KEYWORD_TOKEN) ||
-          identical(kind, IDENTIFIER_TOKEN)) {
-        if (optional('async', nextToken) || optional('sync', nextToken)) {
-          listener.handleNoTypeVariables(next);
-          return parseFunctionExpression(token);
-        }
-        // Recovery
-        // 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;
-        if ((identical(kind, FUNCTION_TOKEN) ||
-            identical(kind, OPEN_CURLY_BRACKET_TOKEN))) {
-          listener.handleNoTypeVariables(next);
-          return parseFunctionExpression(token);
-        }
-      }
-    }
-    bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = true;
-    token = parseParenthesizedExpression(token);
-    mayParseFunctionExpressions = old;
-    return token;
-  }
-
-  Token ensureParenthesizedCondition(Token token) {
-    Token openParen = token.next;
-    if (!optional('(', openParen)) {
-      // Recover
-      reportRecoverableError(
-          openParen, fasta.templateExpectedToken.withArguments('('));
-      openParen = rewriter.insertParens(token, false);
-    }
-    token = parseExpressionInParenthesisRest(openParen);
-    listener.handleParenthesizedCondition(openParen);
-    return token;
-  }
-
-  Token parseParenthesizedExpression(Token token) {
-    Token begin = token.next;
-    token = parseExpressionInParenthesis(token);
-    listener.handleParenthesizedExpression(begin);
-    return token;
-  }
-
-  Token parseExpressionInParenthesis(Token token) {
-    return parseExpressionInParenthesisRest(token.next);
-  }
-
-  Token parseExpressionInParenthesisRest(Token token) {
-    assert(optional('(', token));
-    BeginToken begin = token;
-    token = parseExpression(token);
-    token = ensureCloseParen(token, begin);
-    assert(optional(')', token));
-    return token;
-  }
-
-  Token parseThisExpression(Token token, IdentifierContext context) {
-    Token thisToken = token = token.next;
-    assert(optional('this', thisToken));
-    listener.handleThisExpression(thisToken, context);
-    Token next = token.next;
-    if (optional('(', next)) {
-      // Constructor forwarding.
-      listener.handleNoTypeArguments(next);
-      token = parseArguments(token);
-      listener.handleSend(thisToken, token.next);
-    }
-    return token;
-  }
-
-  Token parseSuperExpression(Token token, IdentifierContext context) {
-    Token superToken = token = token.next;
-    assert(optional('super', token));
-    listener.handleSuperExpression(superToken, context);
-    Token next = token.next;
-    if (optional('(', next)) {
-      // Super constructor.
-      listener.handleNoTypeArguments(next);
-      token = parseArguments(token);
-      listener.handleSend(superToken, token.next);
-    } else if (optional("?.", next)) {
-      reportRecoverableError(next, fasta.messageSuperNullAware);
-    }
-    return token;
-  }
-
-  /// This method parses the portion of a list literal starting with the left
-  /// square bracket.
-  ///
-  /// ```
-  /// listLiteral:
-  ///   'const'? typeArguments? '[' (expressionList ','?)? ']'
-  /// ;
-  /// ```
-  ///
-  /// 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 beforeToken = token;
-    Token beginToken = token = token.next;
-    assert(optional('[', token) || optional('[]', token));
-    int count = 0;
-    if (optional('[]', token)) {
-      token = rewriteSquareBrackets(beforeToken).next;
-      listener.handleLiteralList(0, token, constKeyword, token.next);
-      return token.next;
-    }
-    bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = true;
-    while (true) {
-      Token next = token.next;
-      if (optional(']', next)) {
-        token = next;
-        break;
-      }
-      int ifCount = 0;
-      LiteralEntryInfo info = computeLiteralEntry(token);
-      while (info != null) {
-        if (info.hasEntry) {
-          token = parseExpression(token);
-        } else {
-          token = info.parse(token, this);
-        }
-        ifCount += info.ifConditionDelta;
-        info = info.computeNext(token);
-      }
-      next = token.next;
-      ++count;
-      if (!optional(',', next)) {
-        if (optional(']', next)) {
-          token = next;
-          break;
-        }
-
-        // Recovery
-        if (!looksLikeLiteralEntry(next)) {
-          if (beginToken.endGroup.isSynthetic) {
-            // The scanner has already reported an error,
-            // but inserted `]` in the wrong place.
-            token = rewriter.moveSynthetic(token, beginToken.endGroup);
-          } else {
-            // Report an error and jump to the end of the list.
-            reportRecoverableError(
-                next, fasta.templateExpectedButGot.withArguments(']'));
-            token = beginToken.endGroup;
-          }
-          break;
-        }
-        // This looks like the start of an expression.
-        // Report an error, insert the comma, and continue parsing.
-        SyntheticToken comma = new SyntheticToken(TokenType.COMMA, next.offset);
-        Message message = ifCount > 0
-            ? fasta.messageExpectedElseOrComma
-            : fasta.templateExpectedButGot.withArguments(',');
-        next = rewriteAndRecover(token, message, comma);
-      }
-      token = next;
-    }
-    mayParseFunctionExpressions = old;
-    listener.handleLiteralList(count, beginToken, constKeyword, token);
-    return token;
-  }
-
-  /// 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;
-    assert(optional('{', leftBrace));
-    Token next = token.next;
-    if (optional('}', next)) {
-      listener.handleLiteralSetOrMap(0, leftBrace, constKeyword, next, false);
-      return next;
-    }
-
-    final bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = true;
-    int count = 0;
-    // TODO(danrubel): hasSetEntry parameter exists for replicating existing
-    // behavior and will be removed once unified collection has been enabled
-    bool hasSetEntry;
-
-    while (true) {
-      int ifCount = 0;
-      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);
-        hasSetEntry ??= !isMapEntry;
-        if (isMapEntry) {
-          Token colon = token.next;
-          token = parseExpression(colon);
-          listener.handleLiteralMapEntry(colon, token.next);
-        }
-      } else {
-        while (info != null) {
-          if (info.hasEntry) {
-            token = parseExpression(token);
-            if (optional(':', token.next)) {
-              Token colon = token.next;
-              token = parseExpression(colon);
-              listener.handleLiteralMapEntry(colon, token.next);
-            }
-          } else {
-            token = info.parse(token, this);
-          }
-          ifCount += info.ifConditionDelta;
-          info = info.computeNext(token);
-        }
-      }
-      ++count;
-      next = token.next;
-
-      Token comma;
-      if (optional(',', next)) {
-        comma = token = next;
-        next = token.next;
-      }
-      if (optional('}', next)) {
-        listener.handleLiteralSetOrMap(
-            count, leftBrace, constKeyword, next, hasSetEntry ?? false);
-        mayParseFunctionExpressions = old;
-        return next;
-      }
-
-      if (comma == null) {
-        // Recovery
-        if (looksLikeLiteralEntry(next)) {
-          // If this looks like the start of an expression,
-          // then report an error, insert the comma, and continue parsing.
-          // TODO(danrubel): Consider better error message
-          SyntheticToken comma =
-              new SyntheticToken(TokenType.COMMA, next.offset);
-          Message message = ifCount > 0
-              ? fasta.messageExpectedElseOrComma
-              : fasta.templateExpectedButGot.withArguments(',');
-          token = rewriteAndRecover(token, message, comma);
-        } else {
-          reportRecoverableError(
-              next, fasta.templateExpectedButGot.withArguments('}'));
-          // Scanner guarantees a closing curly bracket
-          next = leftBrace.endGroup;
-          listener.handleLiteralSetOrMap(
-              count, leftBrace, constKeyword, next, hasSetEntry ?? false);
-          mayParseFunctionExpressions = old;
-          return next;
-        }
-      }
-    }
-  }
-
-  /// formalParameterList functionBody.
-  ///
-  /// 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));
-    // Scanner ensures `(` has matching `)`.
-    Token next = token.next.endGroup.next;
-    int kind = next.kind;
-    if (!identical(kind, FUNCTION_TOKEN) &&
-        !identical(kind, OPEN_CURLY_BRACKET_TOKEN) &&
-        (!identical(kind, KEYWORD_TOKEN) ||
-            !optional('async', next) && !optional('sync', next))) {
-      reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
-    }
-    return parseFunctionExpression(token);
-  }
-
-  /// genericListLiteral | genericMapLiteral | genericFunctionLiteral.
-  ///
-  /// Where
-  ///   genericListLiteral ::= typeArguments '[' (expressionList ','?)? ']'
-  ///   genericMapLiteral ::=
-  ///       typeArguments '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  ///   genericFunctionLiteral ::=
-  ///       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));
-    TypeParamOrArgInfo typeParamOrArg = computeTypeParamOrArg(start, true);
-    Token token = typeParamOrArg.skip(start);
-    Token next = token.next;
-    if (optional('(', next)) {
-      if (constKeyword != null) {
-        reportRecoverableErrorWithToken(
-            constKeyword, fasta.templateUnexpectedToken);
-      }
-      token = typeParamOrArg.parseVariables(start, this);
-      return parseLiteralFunctionSuffix(token);
-    }
-    token = typeParamOrArg.parseArguments(start, this);
-    if (optional('{', next)) {
-      if (typeParamOrArg.typeArgumentCount > 2) {
-        listener.handleRecoverableError(
-            fasta.messageSetOrMapLiteralTooManyTypeArguments,
-            start.next,
-            token);
-      }
-      return parseLiteralSetOrMapSuffix(token, constKeyword);
-    }
-    if (!optional('[', next) && !optional('[]', next)) {
-      // TODO(danrubel): Improve this error message.
-      reportRecoverableError(
-          next, fasta.templateExpectedButGot.withArguments('['));
-      rewriter.insertSyntheticToken(token, TokenType.INDEX);
-    }
-    return parseLiteralListSuffix(token, constKeyword);
-  }
-
-  /// ```
-  /// mapLiteralEntry:
-  ///   expression ':' expression |
-  ///   'if' '(' expression ')' mapLiteralEntry ( 'else' mapLiteralEntry )? |
-  ///   'await'? 'for' '(' forLoopParts ')' mapLiteralEntry |
-  ///   ( '...' | '...?' ) expression
-  /// ;
-  /// ```
-  Token parseMapLiteralEntry(Token token) {
-    // 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);
-    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);
-      } else {
-        token = info.parse(token, this);
-      }
-      info = info.computeNext(token);
-    }
-    return token;
-  }
-
-  Token parseSendOrFunctionLiteral(Token token, IdentifierContext context) {
-    if (!mayParseFunctionExpressions) {
-      return parseSend(token, context);
-    }
-    TypeInfo typeInfo = computeType(token, false);
-    Token beforeName = typeInfo.skipType(token);
-    Token name = beforeName.next;
-    if (name.isIdentifier) {
-      TypeParamOrArgInfo typeParam = computeTypeParamOrArg(name);
-      Token next = typeParam.skip(name).next;
-      if (optional('(', next)) {
-        if (looksLikeFunctionBody(next.endGroup.next)) {
-          return parseFunctionLiteral(
-              token, beforeName, name, typeInfo, typeParam, context);
-        }
-      }
-    }
-    return parseSend(token, context);
-  }
-
-  Token ensureArguments(Token token) {
-    Token next = token.next;
-    if (!optional('(', next)) {
-      reportRecoverableError(
-          token, fasta.templateExpectedAfterButGot.withArguments('('));
-      next = rewriter.insertParens(token, false);
-    }
-    return parseArgumentsRest(next);
-  }
-
-  Token parseConstructorInvocationArguments(Token token) {
-    Token next = token.next;
-    if (!optional('(', next)) {
-      // Recovery: Check for invalid type parameters
-      TypeParamOrArgInfo typeArg = computeTypeParamOrArg(token);
-      if (typeArg == noTypeParamOrArg) {
-        reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments('('));
-      } else {
-        reportRecoverableError(
-            token, fasta.messageConstructorWithTypeArguments);
-        token = typeArg.parseArguments(token, this);
-        listener.handleInvalidTypeArguments(token);
-        next = token.next;
-      }
-      if (!optional('(', next)) {
-        next = rewriter.insertParens(token, false);
-      }
-    }
-    return parseArgumentsRest(next);
-  }
-
-  /// ```
-  /// newExpression:
-  ///   'new' type ('.' identifier)? arguments
-  /// ;
-  /// ```
-  Token parseNewExpression(Token token) {
-    Token newKeyword = token.next;
-    assert(optional('new', newKeyword));
-    listener.beginNewExpression(newKeyword);
-    token = parseConstructorReference(newKeyword);
-    token = parseConstructorInvocationArguments(token);
-    listener.endNewExpression(newKeyword);
-    return token;
-  }
-
-  Token parseImplicitCreationExpression(
-      Token token, TypeParamOrArgInfo typeArg) {
-    Token begin = token;
-    listener.beginImplicitCreationExpression(token);
-    token = parseConstructorReference(token, typeArg);
-    token = parseConstructorInvocationArguments(token);
-    listener.endImplicitCreationExpression(begin);
-    return token;
-  }
-
-  /// This method parses a list or map literal that is known to start with the
-  /// keyword 'const'.
-  ///
-  /// ```
-  /// listLiteral:
-  ///   'const'? typeArguments? '[' (expressionList ','?)? ']'
-  /// ;
-  ///
-  /// mapLiteral:
-  ///   'const'? typeArguments?
-  ///     '{' (mapLiteralEntry (',' mapLiteralEntry)* ','?)? '}'
-  /// ;
-  ///
-  /// mapLiteralEntry:
-  ///   expression ':' expression
-  /// ;
-  /// ```
-  Token parseConstExpression(Token token) {
-    Token constKeyword = token = token.next;
-    assert(optional('const', constKeyword));
-    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);
-      return token;
-    }
-    if (identical(value, '{')) {
-      listener.beginConstLiteral(next);
-      listener.handleNoTypeArguments(next);
-      token = parseLiteralSetOrMapSuffix(token, constKeyword);
-      listener.endConstLiteral(token.next);
-      return token;
-    }
-    if (identical(value, '<')) {
-      listener.beginConstLiteral(next);
-      token = parseLiteralListSetMapOrFunction(token, constKeyword);
-      listener.endConstLiteral(token.next);
-      return token;
-    }
-    listener.beginConstExpression(constKeyword);
-    token = parseConstructorReference(token);
-    token = parseConstructorInvocationArguments(token);
-    listener.endConstExpression(constKeyword);
-    return token;
-  }
-
-  /// ```
-  /// intLiteral:
-  ///   integer
-  /// ;
-  /// ```
-  Token parseLiteralInt(Token token) {
-    token = token.next;
-    assert(identical(token.kind, INT_TOKEN) ||
-        identical(token.kind, HEXADECIMAL_TOKEN));
-    listener.handleLiteralInt(token);
-    return token;
-  }
-
-  /// ```
-  /// doubleLiteral:
-  ///   double
-  /// ;
-  /// ```
-  Token parseLiteralDouble(Token token) {
-    token = token.next;
-    assert(identical(token.kind, DOUBLE_TOKEN));
-    listener.handleLiteralDouble(token);
-    return token;
-  }
-
-  /// ```
-  /// stringLiteral:
-  ///   (multilineString | singleLineString)+
-  /// ;
-  /// ```
-  Token parseLiteralString(Token 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)) {
-      token = parseSingleLiteralString(token);
-      count++;
-    }
-    if (count > 1) {
-      listener.handleStringJuxtaposition(count);
-    }
-    mayParseFunctionExpressions = old;
-    return token;
-  }
-
-  /// ```
-  /// symbolLiteral:
-  ///   '#' (operator | (identifier ('.' identifier)*))
-  /// ;
-  /// ```
-  Token parseLiteralSymbol(Token token) {
-    Token hashToken = token = token.next;
-    assert(optional('#', hashToken));
-    listener.beginLiteralSymbol(hashToken);
-    Token next = token.next;
-    if (next.isUserDefinableOperator) {
-      listener.handleOperator(next);
-      listener.endLiteralSymbol(hashToken, 1);
-      return next;
-    } else if (optional('void', next)) {
-      listener.handleSymbolVoid(next);
-      listener.endLiteralSymbol(hashToken, 1);
-      return next;
-    } else {
-      int count = 1;
-      token = ensureIdentifier(token, IdentifierContext.literalSymbol);
-      while (optional('.', token.next)) {
-        count++;
-        token = ensureIdentifier(
-            token.next, IdentifierContext.literalSymbolContinuation);
-      }
-      listener.endLiteralSymbol(hashToken, count);
-      return token;
-    }
-  }
-
-  Token parseSingleLiteralString(Token token) {
-    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;
-    int kind = next.kind;
-    while (kind != EOF_TOKEN) {
-      if (identical(kind, STRING_INTERPOLATION_TOKEN)) {
-        // Parsing ${expression}.
-        token = parseExpression(next).next;
-        if (!optional('}', token)) {
-          reportRecoverableError(
-              token, fasta.templateExpectedButGot.withArguments('}'));
-          token = next.endGroup;
-        }
-        listener.handleInterpolationExpression(next, token);
-      } else if (identical(kind, STRING_INTERPOLATION_IDENTIFIER_TOKEN)) {
-        // Parsing $identifier.
-        token = parseIdentifierExpression(next);
-        listener.handleInterpolationExpression(next, null);
-      } else {
-        break;
-      }
-      ++interpolationCount;
-      // Parsing the infix/suffix, for instance y and z' of 'x${id}y${id}z'
-      token = parseStringPart(token);
-      next = token.next;
-      kind = next.kind;
-    }
-    listener.endLiteralString(interpolationCount, next);
-    return token;
-  }
-
-  Token parseIdentifierExpression(Token token) {
-    Token next = token.next;
-    if (next.kind == KEYWORD_TOKEN && identical(next.stringValue, "this")) {
-      listener.handleThisExpression(next, IdentifierContext.expression);
-      return next;
-    } else {
-      return parseSend(token, IdentifierContext.expression);
-    }
-  }
-
-  /// ```
-  /// booleanLiteral:
-  ///   'true' |
-  ///   'false'
-  /// ;
-  /// ```
-  Token parseLiteralBool(Token token) {
-    token = token.next;
-    assert(optional('false', token) || optional('true', token));
-    listener.handleLiteralBool(token);
-    return token;
-  }
-
-  /// ```
-  /// nullLiteral:
-  ///   'null'
-  /// ;
-  /// ```
-  Token parseLiteralNull(Token token) {
-    token = token.next;
-    assert(optional('null', token));
-    listener.handleLiteralNull(token);
-    return token;
-  }
-
-  Token parseSend(Token token, IdentifierContext context) {
-    Token beginToken = token = ensureIdentifier(token, context);
-    TypeParamOrArgInfo typeArg = computeMethodTypeArguments(token);
-    if (typeArg != noTypeParamOrArg) {
-      token = typeArg.parseArguments(token, this);
-    } else {
-      listener.handleNoTypeArguments(token.next);
-    }
-    token = parseArgumentsOpt(token);
-    listener.handleSend(beginToken, token.next);
-    return token;
-  }
-
-  Token skipArgumentsOpt(Token token) {
-    Token next = token.next;
-    listener.handleNoArguments(next);
-    if (optional('(', next)) {
-      return next.endGroup;
-    } else {
-      return token;
-    }
-  }
-
-  Token parseArgumentsOpt(Token token) {
-    Token next = token.next;
-    if (!optional('(', next)) {
-      listener.handleNoArguments(next);
-      return token;
-    } else {
-      return parseArguments(token);
-    }
-  }
-
-  /// ```
-  /// arguments:
-  ///   '(' (argumentList ','?)? ')'
-  /// ;
-  ///
-  /// argumentList:
-  ///   namedArgument (',' namedArgument)* |
-  ///   expressionList (',' namedArgument)*
-  /// ;
-  ///
-  /// namedArgument:
-  ///   label expression
-  /// ;
-  /// ```
-  Token parseArguments(Token token) {
-    return parseArgumentsRest(token.next);
-  }
-
-  Token parseArgumentsRest(Token token) {
-    Token begin = token;
-    assert(optional('(', begin));
-    listener.beginArguments(begin);
-    int argumentCount = 0;
-    bool hasSeenNamedArgument = false;
-    bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = true;
-    while (true) {
-      Token next = token.next;
-      if (optional(')', next)) {
-        token = next;
-        break;
-      }
-      Token colon = null;
-      if (optional(':', next.next)) {
-        token =
-            ensureIdentifier(token, IdentifierContext.namedArgumentReference)
-                .next;
-        colon = token;
-        hasSeenNamedArgument = true;
-      } else if (hasSeenNamedArgument) {
-        // Positional argument after named argument.
-        reportRecoverableError(next, fasta.messagePositionalAfterNamedArgument);
-      }
-      token = parseExpression(token);
-      next = token.next;
-      if (colon != null) listener.handleNamedArgument(colon);
-      ++argumentCount;
-      if (!optional(',', next)) {
-        if (optional(')', next)) {
-          token = next;
-          break;
-        }
-        // Recovery
-        if (looksLikeExpressionStart(next)) {
-          // If this looks like the start of an expression,
-          // then report an error, insert the comma, and continue parsing.
-          next = rewriteAndRecover(
-              token,
-              fasta.templateExpectedButGot.withArguments(','),
-              new SyntheticToken(TokenType.COMMA, next.offset));
-        } else {
-          token = ensureCloseParen(token, begin);
-          break;
-        }
-      }
-      token = next;
-    }
-    assert(optional(')', token));
-    mayParseFunctionExpressions = old;
-    listener.endArguments(argumentCount, begin, token);
-    return token;
-  }
-
-  /// ```
-  /// typeTest::
-  ///   'is' '!'? type
-  /// ;
-  /// ```
-  Token parseIsOperatorRest(Token token) {
-    Token operator = token = token.next;
-    assert(optional('is', operator));
-    Token not = null;
-    if (optional('!', token.next)) {
-      not = token = token.next;
-    }
-    TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
-    token = typeInfo.ensureTypeNotVoid(token, this);
-    listener.handleIsOperator(operator, not);
-    return skipChainedAsIsOperators(token);
-  }
-
-  TypeInfo computeTypeAfterIsOrAs(Token token) {
-    TypeInfo typeInfo = computeType(token, true);
-    if (typeInfo.isNullable) {
-      Token next = typeInfo.skipType(token).next;
-      if (!isOneOfOrEof(next, const [')', '?', ';', 'is', 'as'])) {
-        // TODO(danrubel): investigate other situations
-        // where `?` should be considered part of the type info
-        // rather than the start of a conditional expression.
-        typeInfo = typeInfo.asNonNullable;
-      }
-    }
-    return typeInfo;
-  }
-
-  /// ```
-  /// typeCast:
-  ///   'as' type
-  /// ;
-  /// ```
-  Token parseAsOperatorRest(Token token) {
-    Token operator = token = token.next;
-    assert(optional('as', operator));
-    TypeInfo typeInfo = computeTypeAfterIsOrAs(token);
-    token = typeInfo.ensureTypeNotVoid(token, this);
-    listener.handleAsOperator(operator);
-    return skipChainedAsIsOperators(token);
-  }
-
-  Token skipChainedAsIsOperators(Token token) {
-    while (true) {
-      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, fasta.templateUnexpectedToken);
-      if (optional('!', next.next)) {
-        next = next.next;
-      }
-      TypeInfo typeInfo = computeTypeAfterIsOrAs(next);
-      token = typeInfo.skipType(next);
-      next = token.next;
-      value = next.stringValue;
-    }
-  }
-
-  /// Returns true if [token] could be the start of a function declaration
-  /// without a return type.
-  bool looksLikeLocalFunction(Token token) {
-    if (token.isIdentifier) {
-      if (optional('<', token.next)) {
-        TypeParamOrArgInfo typeParam = computeTypeParamOrArg(token);
-        if (typeParam == noTypeParamOrArg) {
-          return false;
-        }
-        token = typeParam.skip(token);
-      }
-      token = token.next;
-      if (optional('(', token)) {
-        token = token.endGroup.next;
-        return optional('{', token) ||
-            optional('=>', token) ||
-            optional('async', token) ||
-            optional('sync', token);
-      } else if (optional('=>', token)) {
-        // Recovery: Looks like a local function that is missing parenthesis.
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Returns true if [token] could be the start of a function body.
-  bool looksLikeFunctionBody(Token token) {
-    return optional('{', token) ||
-        optional('=>', token) ||
-        optional('async', token) ||
-        optional('sync', token);
-  }
-
-  Token parseExpressionStatementOrConstDeclaration(final Token start) {
-    Token constToken = start.next;
-    assert(optional('const', constToken));
-    if (!isModifier(constToken.next)) {
-      TypeInfo typeInfo = computeType(constToken, false);
-      if (typeInfo == noType) {
-        Token next = constToken.next;
-        if (!next.isIdentifier) {
-          return parseExpressionStatement(start);
-        }
-        next = next.next;
-        if (!(optional('=', next) ||
-            // Recovery
-            next.isKeywordOrIdentifier ||
-            optional(';', next) ||
-            optional(',', next) ||
-            optional('{', next))) {
-          return parseExpressionStatement(start);
-        }
-      }
-      return parseExpressionStatementOrDeclarationAfterModifiers(
-          constToken, start, null, constToken, typeInfo, false);
-    }
-    return parseExpressionStatementOrDeclaration(start);
-  }
-
-  /// This method has two modes based upon [onlyParseVariableDeclarationStart].
-  ///
-  /// If [onlyParseVariableDeclarationStart] is `false` (the default) then this
-  /// method will parse a local variable declaration, a local function,
-  /// or an expression statement, and then return the last consumed token.
-  ///
-  /// If [onlyParseVariableDeclarationStart] is `true` then this method
-  /// will only parse the metadata, modifiers, and type of a local variable
-  /// declaration if it exists. It is the responsibility of the caller to
-  /// call [parseVariablesDeclarationRest] to finish parsing the local variable
-  /// declaration. If a local variable declaration is not found then this
-  /// method will return [start].
-  Token parseExpressionStatementOrDeclaration(final Token start,
-      [bool onlyParseVariableDeclarationStart = false]) {
-    Token token = start;
-    Token next = token.next;
-    if (optional('@', next)) {
-      token = parseMetadataStar(token);
-      next = token.next;
-    }
-
-    Token lateToken;
-    Token varFinalOrConst;
-
-    if (isModifier(next)) {
-      if (optional('var', next) ||
-          optional('final', next) ||
-          optional('const', next)) {
-        varFinalOrConst = token = token.next;
-        next = token.next;
-      } else if (optional('late', next)) {
-        lateToken = token = next;
-        next = token.next;
-        if (isModifier(next) &&
-            (optional('var', next) || optional('final', next))) {
-          varFinalOrConst = token = next;
-          next = token.next;
-        }
-      }
-
-      if (isModifier(next)) {
-        // Recovery
-        ModifierRecoveryContext context = new ModifierRecoveryContext(this)
-          ..lateToken = lateToken
-          ..varFinalOrConst = varFinalOrConst;
-
-        token = context.parseVariableDeclarationModifiers(token);
-        next = token.next;
-
-        lateToken = context.lateToken;
-        varFinalOrConst = context.varFinalOrConst;
-
-        context = null;
-      }
-    }
-
-    return parseExpressionStatementOrDeclarationAfterModifiers(token, start,
-        lateToken, varFinalOrConst, null, onlyParseVariableDeclarationStart);
-  }
-
-  /// See [parseExpressionStatementOrDeclaration]
-  Token parseExpressionStatementOrDeclarationAfterModifiers(
-      final Token beforeType,
-      final Token start,
-      final Token lateToken,
-      Token varFinalOrConst,
-      TypeInfo typeInfo,
-      bool onlyParseVariableDeclarationStart) {
-    typeInfo ??= computeType(beforeType, false);
-
-    Token token = typeInfo.skipType(beforeType);
-    Token next = token.next;
-
-    if (onlyParseVariableDeclarationStart) {
-      if (lateToken != null) {
-        reportRecoverableErrorWithToken(
-            lateToken, fasta.templateExtraneousModifier);
-      }
-    } else {
-      if (looksLikeLocalFunction(next)) {
-        // Parse a local function declaration.
-        if (varFinalOrConst != null) {
-          reportRecoverableErrorWithToken(
-              varFinalOrConst, fasta.templateExtraneousModifier);
-        } else if (lateToken != null) {
-          reportRecoverableErrorWithToken(
-              lateToken, fasta.templateExtraneousModifier);
-        }
-        if (!optional('@', start.next)) {
-          listener.beginMetadataStar(start.next);
-          listener.endMetadataStar(0);
-        }
-        Token beforeFormals =
-            computeTypeParamOrArg(next).parseVariables(next, this);
-        listener.beginLocalFunctionDeclaration(start.next);
-        token = typeInfo.parseType(beforeType, this);
-        return parseNamedFunctionRest(token, start.next, beforeFormals, false);
-      }
-    }
-
-    if (beforeType == start &&
-        typeInfo.isNullable &&
-        typeInfo.couldBeExpression) {
-      assert(optional('?', token));
-      assert(next.isKeywordOrIdentifier);
-      if (!next.isIdentifier) {
-        reportRecoverableError(
-            next, fasta.templateExpectedIdentifier.withArguments(next));
-        next = rewriter.insertSyntheticIdentifier(next);
-      }
-      Token afterIdentifier = next.next;
-      //
-      // found <typeref> `?` <identifier>
-      // with no annotations or modifiers preceeding it
-      //
-      if (optional('=', afterIdentifier)) {
-        //
-        // look past the next expression
-        // to determine if this is part of a conditional expression
-        //
-        Listener originalListener = listener;
-        listener = new ForwardingListener();
-        // TODO(danrubel): consider using TokenStreamGhostWriter here
-        Token afterExpression =
-            parseExpressionWithoutCascade(afterIdentifier).next;
-        listener = originalListener;
-
-        if (optional(':', afterExpression)) {
-          // Looks like part of a conditional expression.
-          // Drop the type information and reset the last consumed token.
-          typeInfo = noType;
-          token = start;
-          next = token.next;
-        }
-      } else if (!afterIdentifier.isKeyword &&
-          !isOneOfOrEof(afterIdentifier, const [';', ',', ')'])) {
-        // Looks like part of a conditional expression.
-        // Drop the type information and reset the last consumed token.
-        typeInfo = noType;
-        token = start;
-        next = token.next;
-      }
-    }
-
-    if (token == start) {
-      // If no annotation, modifier, or type, and this is not a local function
-      // then this must be an expression statement.
-      if (onlyParseVariableDeclarationStart) {
-        return start;
-      } else {
-        return parseExpressionStatement(start);
-      }
-    }
-
-    if (next.type.isBuiltIn &&
-        beforeType == start &&
-        typeInfo.couldBeExpression) {
-      // Detect expressions such as identifier `as` identifier
-      // and treat those as expressions.
-      if (optional('as', next) || optional('is', next)) {
-        int kind = next.next.kind;
-        if (EQ_TOKEN != kind &&
-            SEMICOLON_TOKEN != kind &&
-            COMMA_TOKEN != kind) {
-          if (onlyParseVariableDeclarationStart) {
-            if (!optional('in', next.next)) {
-              return start;
-            }
-          } else {
-            return parseExpressionStatement(start);
-          }
-        }
-      }
-    }
-
-    if (next.isIdentifier) {
-      // Only report these errors if there is an identifier. If there is not an
-      // identifier, then allow ensureIdentifier to report an error
-      // and don't report errors here.
-      if (varFinalOrConst == null) {
-        if (typeInfo == noType && lateToken == null) {
-          reportRecoverableError(next, fasta.messageMissingConstFinalVarOrType);
-        }
-      } else if (optional('var', varFinalOrConst)) {
-        if (typeInfo != noType) {
-          reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
-        }
-      }
-    }
-
-    if (!optional('@', start.next)) {
-      listener.beginMetadataStar(start.next);
-      listener.endMetadataStar(0);
-    }
-    token = typeInfo.parseType(beforeType, this);
-    next = token.next;
-    listener.beginVariablesDeclaration(next, lateToken, varFinalOrConst);
-    if (!onlyParseVariableDeclarationStart) {
-      token = parseVariablesDeclarationRest(token, true);
-    }
-    return token;
-  }
-
-  Token parseVariablesDeclarationRest(Token token, bool endWithSemicolon) {
-    int count = 1;
-    token = parseOptionallyInitializedIdentifier(token);
-    while (optional(',', token.next)) {
-      token = parseOptionallyInitializedIdentifier(token.next);
-      ++count;
-    }
-    if (endWithSemicolon) {
-      Token semicolon = ensureSemicolon(token);
-      listener.endVariablesDeclaration(count, semicolon);
-      return semicolon;
-    } else {
-      listener.endVariablesDeclaration(count, null);
-      return token;
-    }
-  }
-
-  Token parseOptionallyInitializedIdentifier(Token token) {
-    Token nameToken =
-        ensureIdentifier(token, IdentifierContext.localVariableDeclaration);
-    listener.beginInitializedIdentifier(nameToken);
-    token = parseVariableInitializerOpt(nameToken);
-    listener.endInitializedIdentifier(nameToken);
-    return token;
-  }
-
-  /// ```
-  /// ifStatement:
-  ///   'if' '(' expression ')' statement ('else' statement)?
-  /// ;
-  /// ```
-  Token parseIfStatement(Token token) {
-    Token ifToken = token.next;
-    assert(optional('if', ifToken));
-    listener.beginIfStatement(ifToken);
-    token = ensureParenthesizedCondition(ifToken);
-    listener.beginThenStatement(token.next);
-    token = parseStatement(token);
-    listener.endThenStatement(token);
-    Token elseToken = null;
-    if (optional('else', token.next)) {
-      elseToken = token.next;
-      listener.beginElseStatement(elseToken);
-      token = parseStatement(elseToken);
-      listener.endElseStatement(elseToken);
-    }
-    listener.endIfStatement(ifToken, elseToken);
-    return token;
-  }
-
-  /// ```
-  /// forStatement:
-  ///   'await'? 'for' '(' forLoopParts ')' statement
-  /// ;
-  ///
-  ///  forLoopParts:
-  ///      localVariableDeclaration ';' expression? ';' expressionList?
-  ///    | expression? ';' expression? ';' expressionList?
-  ///    | localVariableDeclaration 'in' expression
-  ///    | identifier 'in' expression
-  /// ;
-  ///
-  /// forInitializerStatement:
-  ///   localVariableDeclaration |
-  ///   expression? ';'
-  /// ;
-  /// ```
-  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 = parseForLoopPartsMid(token, awaitToken, forToken);
-    if (optional('in', token.next) || optional(':', token.next)) {
-      // Process `for ( ... in ... )`
-      return parseForInRest(token, awaitToken, forToken, identifier);
-    } else {
-      // Process `for ( ... ; ... ; ... )`
-      return parseForRest(awaitToken, token, forToken);
-    }
-  }
-
-  /// 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;
-    if (!optional('(', leftParenthesis)) {
-      // Recovery
-      reportRecoverableError(
-          leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
-
-      BeginToken openParen = rewriter.insertToken(
-          forToken,
-          new SyntheticBeginToken(
-              TokenType.OPEN_PAREN, leftParenthesis.offset));
-
-      Token token;
-      if (awaitToken != null) {
-        token = rewriter.insertSyntheticIdentifier(openParen);
-        token = rewriter.insertSyntheticKeyword(token, Keyword.IN);
-        token = rewriter.insertSyntheticIdentifier(token);
-      } else {
-        token = rewriter.insertSyntheticToken(openParen, TokenType.SEMICOLON);
-        token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
-      }
-
-      openParen.endGroup = token = rewriter.insertToken(token,
-          new SyntheticToken(TokenType.CLOSE_PAREN, leftParenthesis.offset));
-
-      token = rewriter.insertSyntheticIdentifier(token);
-      rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
-
-      leftParenthesis = openParen;
-    }
-
-    // Pass `true` so that the [parseExpressionStatementOrDeclaration] only
-    // parses the metadata, modifiers, and type of a local variable
-    // declaration if it exists. This enables capturing [beforeIdentifier]
-    // for later error reporting.
-    return parseExpressionStatementOrDeclaration(leftParenthesis, true);
-  }
-
-  /// 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) {
-    if (token != forToken.next) {
-      token = parseVariablesDeclarationRest(token, false);
-      listener.handleForInitializerLocalVariableDeclaration(token);
-    } else if (optional(';', token.next)) {
-      listener.handleForInitializerEmptyStatement(token.next);
-    } else {
-      token = parseExpression(token);
-      listener.handleForInitializerExpressionStatement(token);
-    }
-    Token next = token.next;
-    if (optional(';', next)) {
-      if (awaitToken != null) {
-        reportRecoverableError(awaitToken, fasta.messageInvalidAwaitFor);
-      }
-    } else if (!optional('in', next)) {
-      // Recovery
-      if (optional(':', next)) {
-        reportRecoverableError(next, fasta.messageColonInPlaceOfIn);
-      } else if (awaitToken != null) {
-        reportRecoverableError(
-            next, fasta.templateExpectedButGot.withArguments('in'));
-        token.setNext(
-            new SyntheticKeywordToken(Keyword.IN, next.offset)..setNext(next));
-      }
-    }
-    return token;
-  }
-
-  /// This method parses the portion of the forLoopParts that starts with the
-  /// first semicolon (the one that terminates the forInitializerStatement).
-  ///
-  /// ```
-  ///  forLoopParts:
-  ///      localVariableDeclaration ';' expression? ';' expressionList?
-  ///    | expression? ';' expression? ';' expressionList?
-  ///    | localVariableDeclaration 'in' expression
-  ///    | identifier 'in' expression
-  /// ;
-  /// ```
-  Token parseForRest(Token awaitToken, Token token, Token forToken) {
-    token = parseForLoopPartsRest(token, forToken, awaitToken);
-    listener.beginForStatementBody(token.next);
-    LoopState savedLoopState = loopState;
-    loopState = LoopState.InsideLoop;
-    token = parseStatement(token);
-    loopState = savedLoopState;
-    listener.endForStatementBody(token.next);
-    listener.endForStatement(token.next);
-    return token;
-  }
-
-  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)) {
-      token = parseEmptyStatement(leftSeparator);
-    } else {
-      token = parseExpressionStatement(leftSeparator);
-    }
-    int expressionCount = 0;
-    while (true) {
-      Token next = token.next;
-      if (optional(')', next)) {
-        token = next;
-        break;
-      }
-      token = parseExpression(token).next;
-      ++expressionCount;
-      if (!optional(',', token)) {
-        break;
-      }
-    }
-    if (token != leftParenthesis.endGroup) {
-      reportRecoverableErrorWithToken(token, fasta.templateUnexpectedToken);
-      token = leftParenthesis.endGroup;
-    }
-    listener.handleForLoopParts(
-        forToken, leftParenthesis, leftSeparator, expressionCount);
-    return token;
-  }
-
-  /// This method parses the portion of the forLoopParts that starts with the
-  /// keyword 'in'. For the sake of recovery, we accept a colon in place of the
-  /// keyword.
-  ///
-  /// ```
-  ///  forLoopParts:
-  ///      localVariableDeclaration ';' expression? ';' expressionList?
-  ///    | expression? ';' expression? ';' expressionList?
-  ///    | localVariableDeclaration 'in' expression
-  ///    | identifier 'in' expression
-  /// ;
-  /// ```
-  Token parseForInRest(
-      Token token, Token awaitToken, Token forToken, Token identifier) {
-    token = parseForInLoopPartsRest(token, awaitToken, forToken, identifier);
-    listener.beginForInBody(token.next);
-    LoopState savedLoopState = loopState;
-    loopState = LoopState.InsideLoop;
-    token = parseStatement(token);
-    loopState = savedLoopState;
-    listener.endForInBody(token.next);
-    listener.endForIn(token.next);
-    return token;
-  }
-
-  Token parseForInLoopPartsRest(
-      Token token, Token awaitToken, Token forToken, Token identifier) {
-    Token inKeyword = token.next;
-    assert(optional('for', forToken));
-    assert(optional('(', forToken.next));
-    assert(optional('in', inKeyword) || optional(':', inKeyword));
-
-    if (!identifier.isIdentifier) {
-      reportRecoverableErrorWithToken(
-          identifier, fasta.templateExpectedIdentifier);
-    } else if (identifier != token) {
-      if (optional('=', identifier.next)) {
-        reportRecoverableError(
-            identifier.next, fasta.messageInitializedVariableInForEach);
-      } else {
-        reportRecoverableErrorWithToken(
-            identifier.next, fasta.templateUnexpectedToken);
-      }
-    } else if (awaitToken != null && !inAsync) {
-      // TODO(danrubel): consider reporting the error on awaitToken
-      reportRecoverableError(inKeyword, fasta.messageAwaitForNotAsync);
-    }
-
-    listener.beginForInExpression(inKeyword.next);
-    token = parseExpression(inKeyword);
-    token = ensureCloseParen(token, forToken.next);
-    listener.endForInExpression(token);
-    listener.handleForInLoopParts(
-        awaitToken, forToken, forToken.next, inKeyword);
-    return token;
-  }
-
-  /// ```
-  /// whileStatement:
-  ///   'while' '(' expression ')' statement
-  /// ;
-  /// ```
-  Token parseWhileStatement(Token token) {
-    Token whileToken = token.next;
-    assert(optional('while', whileToken));
-    listener.beginWhileStatement(whileToken);
-    token = ensureParenthesizedCondition(whileToken);
-    listener.beginWhileStatementBody(token.next);
-    LoopState savedLoopState = loopState;
-    loopState = LoopState.InsideLoop;
-    token = parseStatement(token);
-    loopState = savedLoopState;
-    listener.endWhileStatementBody(token.next);
-    listener.endWhileStatement(whileToken, token.next);
-    return token;
-  }
-
-  /// ```
-  /// doStatement:
-  ///   'do' statement 'while' '(' expression ')' ';'
-  /// ;
-  /// ```
-  Token parseDoWhileStatement(Token token) {
-    Token doToken = token.next;
-    assert(optional('do', doToken));
-    listener.beginDoWhileStatement(doToken);
-    listener.beginDoWhileStatementBody(doToken.next);
-    LoopState savedLoopState = loopState;
-    loopState = LoopState.InsideLoop;
-    token = parseStatement(doToken);
-    loopState = savedLoopState;
-    listener.endDoWhileStatementBody(token);
-    Token whileToken = token.next;
-    if (!optional('while', whileToken)) {
-      reportRecoverableError(
-          whileToken, fasta.templateExpectedButGot.withArguments('while'));
-      whileToken = rewriter.insertSyntheticKeyword(token, Keyword.WHILE);
-    }
-    token = ensureParenthesizedCondition(whileToken);
-    token = ensureSemicolon(token);
-    listener.endDoWhileStatement(doToken, whileToken, token);
-    return token;
-  }
-
-  /// ```
-  /// block:
-  ///   '{' statement* '}'
-  /// ;
-  /// ```
-  Token parseBlock(Token token, String blockKind) {
-    Token begin = token = ensureBlock(token, null, blockKind);
-    listener.beginBlock(begin);
-    int statementCount = 0;
-    Token startToken = token.next;
-    while (notEofOrValue('}', startToken)) {
-      token = parseStatement(token);
-      if (identical(token.next, startToken)) {
-        // No progress was made, so we report the current token as being invalid
-        // and move forward.
-        token = token.next;
-        reportRecoverableError(
-            token, fasta.templateUnexpectedToken.withArguments(token));
-      }
-      ++statementCount;
-      startToken = token.next;
-    }
-    token = token.next;
-    assert(optional('}', token));
-    listener.endBlock(statementCount, begin, token);
-    return token;
-  }
-
-  Token parseInvalidBlock(Token token) {
-    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.
-    Listener originalListener = listener;
-    listener = new ForwardingListener(listener)..forwardErrors = false;
-    // The scanner ensures that `{` always has a closing `}`.
-    token = parseBlock(token, null);
-    listener = originalListener;
-    listener.handleInvalidTopLevelBlock(begin);
-    return token;
-  }
-
-  /// 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;
-    assert(optional('await', token));
-    token = token.next;
-
-    // TODO(danrubel): Consider parsing the potential expression following
-    // the `await` token once doing so does not modify the token stream.
-    // For now, use simple look ahead and ensure no false positives.
-
-    if (token.isIdentifier) {
-      token = token.next;
-      if (optional('(', token)) {
-        token = token.endGroup.next;
-        if (isOneOf(token, [';', '.', '..', '?', '?.'])) {
-          return true;
-        }
-      } else if (isOneOf(token, ['.', ')', ']'])) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// ```
-  /// awaitExpression:
-  ///   'await' unaryExpression
-  /// ;
-  /// ```
-  Token parseAwaitExpression(Token token, bool allowCascades) {
-    Token awaitToken = token.next;
-    assert(optional('await', awaitToken));
-    listener.beginAwaitExpression(awaitToken);
-    token = parsePrecedenceExpression(
-        awaitToken, POSTFIX_PRECEDENCE, allowCascades);
-    if (inAsync) {
-      listener.endAwaitExpression(awaitToken, token.next);
-    } else {
-      fasta.MessageCode errorCode = fasta.messageAwaitNotAsync;
-      reportRecoverableError(awaitToken, errorCode);
-      listener.endInvalidAwaitExpression(awaitToken, token.next, errorCode);
-    }
-    return token;
-  }
-
-  /// ```
-  /// throwExpression:
-  ///   'throw' expression
-  /// ;
-  ///
-  /// throwExpressionWithoutCascade:
-  ///   'throw' expressionWithoutCascade
-  /// ;
-  /// ```
-  Token parseThrowExpression(Token token, bool allowCascades) {
-    Token throwToken = token.next;
-    assert(optional('throw', throwToken));
-    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, fasta.messageMissingExpressionInThrow);
-      rewriter.insertToken(
-          throwToken,
-          new SyntheticStringToken(
-              TokenType.STRING, '""', throwToken.next.charOffset, 0));
-    }
-    token = allowCascades
-        ? parseExpression(throwToken)
-        : parseExpressionWithoutCascade(throwToken);
-    listener.handleThrowExpression(throwToken, token.next);
-    return token;
-  }
-
-  /// ```
-  /// rethrowStatement:
-  ///   'rethrow' ';'
-  /// ;
-  /// ```
-  Token parseRethrowStatement(Token token) {
-    Token throwToken = token.next;
-    assert(optional('rethrow', throwToken));
-    listener.beginRethrowStatement(throwToken);
-    token = ensureSemicolon(throwToken);
-    listener.endRethrowStatement(throwToken, token);
-    return token;
-  }
-
-  /// ```
-  /// tryStatement:
-  ///   'try' block (onPart+ finallyPart? | finallyPart)
-  /// ;
-  ///
-  /// onPart:
-  ///   catchPart block |
-  ///   'on' type catchPart? block
-  /// ;
-  ///
-  /// catchPart:
-  ///   'catch' '(' identifier (',' identifier)? ')'
-  /// ;
-  ///
-  /// finallyPart:
-  ///   'finally' block
-  /// ;
-  /// ```
-  Token parseTryStatement(Token token) {
-    Token tryKeyword = token.next;
-    assert(optional('try', tryKeyword));
-    listener.beginTryStatement(tryKeyword);
-    Token lastConsumed = parseBlock(tryKeyword, 'try statement');
-    token = lastConsumed.next;
-    int catchCount = 0;
-
-    String value = token.stringValue;
-    while (identical(value, 'catch') || identical(value, 'on')) {
-      listener.beginCatchClause(token);
-      Token onKeyword = null;
-      if (identical(value, 'on')) {
-        // 'on' type catchPart?
-        onKeyword = token;
-        lastConsumed = computeType(token, true).ensureTypeNotVoid(token, this);
-        token = lastConsumed.next;
-        value = token.stringValue;
-      }
-      Token catchKeyword = null;
-      Token comma = null;
-      if (identical(value, 'catch')) {
-        catchKeyword = token;
-
-        Token openParens = catchKeyword.next;
-        if (!optional("(", openParens)) {
-          reportRecoverableError(openParens, fasta.messageCatchSyntax);
-          openParens = rewriter.insertParens(catchKeyword, true);
-        }
-
-        Token exceptionName = openParens.next;
-        if (exceptionName.kind != IDENTIFIER_TOKEN) {
-          exceptionName = IdentifierContext.catchParameter
-              .ensureIdentifier(openParens, this);
-        }
-
-        if (optional(")", exceptionName.next)) {
-          // OK: `catch (identifier)`.
-        } else {
-          comma = exceptionName.next;
-          if (!optional(",", comma)) {
-            // Recovery
-            if (!exceptionName.isSynthetic) {
-              reportRecoverableError(comma, fasta.messageCatchSyntax);
-            }
-
-            // TODO(danrubel): Consider inserting `on` clause if
-            // exceptionName is preceded by type and followed by a comma.
-            // Then this
-            //   } catch (E e, t) {
-            // will recover to
-            //   } on E catch (e, t) {
-            // with a detailed explanation for the user in the error
-            // indicating what they should do to fix the code.
-
-            // TODO(danrubel): Consider inserting synthetic identifier if
-            // exceptionName is a non-synthetic identifier followed by `.`.
-            // Then this
-            //   } catch (
-            //   e.f();
-            // will recover to
-            //   } catch (_s_) {}
-            //   e.f();
-            // rather than
-            //   } catch (e) {}
-            //   _s_.f();
-
-            if (openParens.endGroup.isSynthetic) {
-              // The scanner did not place the synthetic ')' correctly.
-              rewriter.moveSynthetic(exceptionName, openParens.endGroup);
-              comma = null;
-            } else {
-              comma =
-                  rewriter.insertSyntheticToken(exceptionName, TokenType.COMMA);
-            }
-          }
-          if (comma != null) {
-            Token traceName = comma.next;
-            if (traceName.kind != IDENTIFIER_TOKEN) {
-              traceName = IdentifierContext.catchParameter
-                  .ensureIdentifier(comma, this);
-            }
-            if (!optional(")", traceName.next)) {
-              // Recovery
-              if (!traceName.isSynthetic) {
-                reportRecoverableError(
-                    traceName.next, fasta.messageCatchSyntaxExtraParameters);
-              }
-              if (openParens.endGroup.isSynthetic) {
-                // The scanner did not place the synthetic ')' correctly.
-                rewriter.moveSynthetic(traceName, openParens.endGroup);
-              }
-            }
-          }
-        }
-        lastConsumed = parseFormalParameters(catchKeyword, MemberKind.Catch);
-        token = lastConsumed.next;
-      }
-      listener.endCatchClause(token);
-      lastConsumed = parseBlock(lastConsumed, 'catch clause');
-      token = lastConsumed.next;
-      ++catchCount;
-      listener.handleCatchBlock(onKeyword, catchKeyword, comma);
-      value = token.stringValue; // while condition
-    }
-
-    Token finallyKeyword = null;
-    if (optional('finally', token)) {
-      finallyKeyword = token;
-      lastConsumed = parseBlock(token, 'finally clause');
-      token = lastConsumed.next;
-      listener.handleFinallyBlock(finallyKeyword);
-    } else {
-      if (catchCount == 0) {
-        reportRecoverableError(tryKeyword, fasta.messageOnlyTry);
-      }
-    }
-    listener.endTryStatement(catchCount, tryKeyword, finallyKeyword);
-    return lastConsumed;
-  }
-
-  /// ```
-  /// switchStatement:
-  ///   'switch' parenthesizedExpression switchBlock
-  /// ;
-  /// ```
-  Token parseSwitchStatement(Token token) {
-    Token switchKeyword = token.next;
-    assert(optional('switch', switchKeyword));
-    listener.beginSwitchStatement(switchKeyword);
-    token = ensureParenthesizedCondition(switchKeyword);
-    LoopState savedLoopState = loopState;
-    if (loopState == LoopState.OutsideLoop) {
-      loopState = LoopState.InsideSwitch;
-    }
-    token = parseSwitchBlock(token);
-    loopState = savedLoopState;
-    listener.endSwitchStatement(switchKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// switchBlock:
-  ///   '{' switchCase* defaultCase? '}'
-  /// ;
-  /// ```
-  Token parseSwitchBlock(Token token) {
-    Token beginSwitch = token = ensureBlock(token, null, 'switch statement');
-    listener.beginSwitchBlock(beginSwitch);
-    int caseCount = 0;
-    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;
-        if (identical(value, 'default')) {
-          while (!identical(token.next, peek)) {
-            token = parseLabel(token);
-            labelCount++;
-          }
-          if (defaultKeyword != null) {
-            reportRecoverableError(
-                token.next, fasta.messageSwitchHasMultipleDefaults);
-          }
-          defaultKeyword = token.next;
-          colonAfterDefault = token = ensureColon(defaultKeyword);
-          peek = token.next;
-          break;
-        } else if (identical(value, 'case')) {
-          while (!identical(token.next, peek)) {
-            token = parseLabel(token);
-            labelCount++;
-          }
-          Token caseKeyword = token.next;
-          if (defaultKeyword != null) {
-            reportRecoverableError(
-                caseKeyword, fasta.messageSwitchHasCaseAfterDefault);
-          }
-          listener.beginCaseExpression(caseKeyword);
-          token = parseExpression(caseKeyword);
-          token = ensureColon(token);
-          listener.endCaseExpression(token);
-          listener.handleCaseMatch(caseKeyword, token);
-          expressionCount++;
-          peek = peekPastLabels(token.next);
-        } else if (expressionCount > 0) {
-          break;
-        } else {
-          // Recovery
-          reportRecoverableError(
-              peek, fasta.templateExpectedToken.withArguments("case"));
-          Token endGroup = beginSwitch.endGroup;
-          while (token.next != endGroup) {
-            token = token.next;
-          }
-          peek = peekPastLabels(token.next);
-          break;
-        }
-      }
-      token = parseStatementsInSwitchCase(token, peek, beginCase, labelCount,
-          expressionCount, defaultKeyword, colonAfterDefault);
-      ++caseCount;
-    }
-    token = token.next;
-    listener.endSwitchBlock(caseCount, beginSwitch, token);
-    assert(optional('}', token));
-    return token;
-  }
-
-  /// Peek after the following labels (if any). The following token
-  /// 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;
-    }
-    return token;
-  }
-
-  /// Parse statements after a switch `case:` or `default:`.
-  Token parseStatementsInSwitchCase(
-      Token token,
-      Token peek,
-      Token begin,
-      int labelCount,
-      int expressionCount,
-      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;
-      if ((identical(value, 'case')) ||
-          (identical(value, 'default')) ||
-          ((identical(value, '}')) && (identical(token.next, peek)))) {
-        // A label just before "}" will be handled as a statement error.
-        break;
-      } else {
-        Token startToken = token.next;
-        token = parseStatement(token);
-        Token next = token.next;
-        if (identical(next, startToken)) {
-          // No progress was made, so we report the current token as being
-          // invalid and move forward.
-          reportRecoverableError(
-              next, fasta.templateUnexpectedToken.withArguments(next));
-          token = next;
-        }
-        ++statementCount;
-      }
-      peek = peekPastLabels(token.next);
-    }
-    listener.endSwitchCase(labelCount, expressionCount, defaultKeyword,
-        colonAfterDefault, statementCount, begin, token.next);
-    return token;
-  }
-
-  /// ```
-  /// breakStatement:
-  ///   'break' identifier? ';'
-  /// ;
-  /// ```
-  Token parseBreakStatement(Token token) {
-    Token breakKeyword = token = token.next;
-    assert(optional('break', breakKeyword));
-    bool hasTarget = false;
-    if (token.next.isIdentifier) {
-      token = ensureIdentifier(token, IdentifierContext.labelReference);
-      hasTarget = true;
-    } else if (!isBreakAllowed) {
-      reportRecoverableError(breakKeyword, fasta.messageBreakOutsideOfLoop);
-    }
-    token = ensureSemicolon(token);
-    listener.handleBreakStatement(hasTarget, breakKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// assertion:
-  ///   'assert' '(' expression (',' expression)? ','? ')'
-  /// ;
-  /// ```
-  Token parseAssert(Token token, Assert kind) {
-    token = token.next;
-    assert(optional('assert', token));
-    listener.beginAssert(token, kind);
-    Token assertKeyword = token;
-    Token leftParenthesis = token.next;
-    if (!optional('(', leftParenthesis)) {
-      // Recovery
-      reportRecoverableError(
-          leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
-      leftParenthesis = rewriter.insertParens(token, true);
-    }
-    token = leftParenthesis;
-    Token commaToken = null;
-    bool old = mayParseFunctionExpressions;
-    mayParseFunctionExpressions = true;
-
-    token = parseExpression(token);
-    if (optional(',', token.next)) {
-      token = token.next;
-      if (!optional(')', token.next)) {
-        commaToken = token;
-        token = parseExpression(token);
-        if (optional(',', token.next)) {
-          // Trailing comma is ignored.
-          token = token.next;
-        }
-      }
-    }
-
-    Token endGroup = leftParenthesis.endGroup;
-    if (token.next == endGroup) {
-      token = endGroup;
-    } else {
-      // Recovery
-      if (endGroup.isSynthetic) {
-        // The scanner did not place the synthetic ')' correctly, so move it.
-        token = rewriter.moveSynthetic(token, endGroup);
-      } else {
-        reportRecoverableErrorWithToken(
-            token.next, fasta.templateUnexpectedToken);
-        token = endGroup;
-      }
-    }
-
-    assert(optional(')', token));
-    mayParseFunctionExpressions = old;
-    if (kind == Assert.Expression) {
-      reportRecoverableError(assertKeyword, fasta.messageAssertAsExpression);
-    } else if (kind == Assert.Statement) {
-      ensureSemicolon(token);
-    }
-    listener.endAssert(
-        assertKeyword, kind, leftParenthesis, commaToken, token.next);
-    return token;
-  }
-
-  /// ```
-  /// assertStatement:
-  ///   assertion ';'
-  /// ;
-  /// ```
-  Token parseAssertStatement(Token token) {
-    assert(optional('assert', token.next));
-    // parseAssert ensures that there is a trailing semicolon.
-    return parseAssert(token, Assert.Statement).next;
-  }
-
-  /// ```
-  /// continueStatement:
-  ///   'continue' identifier? ';'
-  /// ;
-  /// ```
-  Token parseContinueStatement(Token token) {
-    Token continueKeyword = token = token.next;
-    assert(optional('continue', continueKeyword));
-    bool hasTarget = false;
-    if (token.next.isIdentifier) {
-      token = ensureIdentifier(token, IdentifierContext.labelReference);
-      hasTarget = true;
-      if (!isContinueWithLabelAllowed) {
-        reportRecoverableError(
-            continueKeyword, fasta.messageContinueOutsideOfLoop);
-      }
-    } else if (!isContinueAllowed) {
-      reportRecoverableError(
-          continueKeyword,
-          loopState == LoopState.InsideSwitch
-              ? fasta.messageContinueWithoutLabelInCase
-              : fasta.messageContinueOutsideOfLoop);
-    }
-    token = ensureSemicolon(token);
-    listener.handleContinueStatement(hasTarget, continueKeyword, token);
-    return token;
-  }
-
-  /// ```
-  /// emptyStatement:
-  ///   ';'
-  /// ;
-  /// ```
-  Token parseEmptyStatement(Token token) {
-    token = token.next;
-    assert(optional(';', token));
-    listener.handleEmptyStatement(token);
-    return token;
-  }
-
-  /// 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;
-    while (next != token && next != beforeToken) {
-      beforeToken = next;
-      next = beforeToken.next;
-    }
-    return beforeToken;
-  }
-
-  /// Recover from finding an operator declaration missing the `operator`
-  /// keyword. The metadata for the member, if any, has already been parsed
-  /// (and events have already been generated).
-  Token parseInvalidOperatorDeclaration(
-      Token beforeStart,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      Token beforeType,
-      DeclarationKind kind) {
-    TypeInfo typeInfo = computeType(beforeType, true, true);
-
-    Token beforeName = typeInfo.skipType(beforeType);
-    Token next = beforeName.next;
-
-    if (optional('operator', next)) {
-      next = next.next;
-    } else {
-      reportRecoverableError(next, fasta.messageMissingOperatorKeyword);
-      rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
-    }
-
-    assert((next.isOperator && next.endGroup == null) ||
-        optional('===', next) ||
-        optional('!==', next));
-
-    Token token = parseMethod(
-        beforeStart,
-        externalToken,
-        staticToken,
-        covariantToken,
-        lateToken,
-        varFinalOrConst,
-        beforeType,
-        typeInfo,
-        null,
-        beforeName.next,
-        kind,
-        null);
-    listener.endMember();
-    return token;
-  }
-
-  /// Recover from finding an invalid class member. The metadata for the member,
-  /// if any, has already been parsed (and events have already been generated).
-  /// The member was expected to start with the token after [token].
-  Token recoverFromInvalidMember(
-      Token token,
-      Token beforeStart,
-      Token externalToken,
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      Token beforeType,
-      TypeInfo typeInfo,
-      Token getOrSet,
-      DeclarationKind kind,
-      String enclosingDeclarationName) {
-    Token next = token.next;
-    String value = next.stringValue;
-
-    if (identical(value, 'class')) {
-      return reportAndSkipClassInClass(next);
-    } else if (identical(value, 'enum')) {
-      return reportAndSkipEnumInClass(next);
-    } else if (identical(value, 'typedef')) {
-      return reportAndSkipTypedefInClass(next);
-    } else if (next.isOperator && next.endGroup == null) {
-      return parseInvalidOperatorDeclaration(
-          beforeStart,
-          externalToken,
-          staticToken,
-          covariantToken,
-          lateToken,
-          varFinalOrConst,
-          beforeType,
-          kind);
-    }
-
-    if (getOrSet != null ||
-        identical(value, '(') ||
-        identical(value, '=>') ||
-        identical(value, '{')) {
-      token = parseMethod(
-          beforeStart,
-          externalToken,
-          staticToken,
-          covariantToken,
-          lateToken,
-          varFinalOrConst,
-          beforeType,
-          typeInfo,
-          getOrSet,
-          token.next,
-          kind,
-          enclosingDeclarationName);
-    } else if (token == beforeStart) {
-      // TODO(danrubel): Provide a more specific error message for extra ';'.
-      reportRecoverableErrorWithToken(next, fasta.templateExpectedClassMember);
-      listener.handleInvalidMember(next);
-      if (!identical(value, '}')) {
-        // Ensure we make progress.
-        token = next;
-      }
-    } else {
-      token = parseFields(
-          beforeStart,
-          externalToken,
-          staticToken,
-          covariantToken,
-          lateToken,
-          varFinalOrConst,
-          beforeType,
-          typeInfo,
-          token.next,
-          kind);
-    }
-
-    listener.endMember();
-    return token;
-  }
-
-  /// 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;
-    reportRecoverableError(next, fasta.messageStackOverflow);
-    next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
-    listener.handleEmptyStatement(next);
-
-    while (notEofOrValue('}', next)) {
-      token = next;
-      next = token.next;
-    }
-    return token;
-  }
-
-  void reportRecoverableError(Token token, Message message) {
-    // Find a non-synthetic token on which to report the error.
-    token = findNonZeroLengthToken(token);
-    listener.handleRecoverableError(message, token, token);
-  }
-
-  void reportRecoverableErrorWithToken(
-      Token token, Template<_MessageWithArgument<Token>> template) {
-    // Find a non-synthetic token on which to report the error.
-    token = findNonZeroLengthToken(token);
-    listener.handleRecoverableError(
-        template.withArguments(token), token, token);
-  }
-
-  Token reportAllErrorTokens(Token token) {
-    while (token is ErrorToken) {
-      listener.handleErrorToken(token);
-      token = token.next;
-    }
-    return token;
-  }
-
-  Token skipErrorTokens(Token token) {
-    while (token is ErrorToken) {
-      token = token.next;
-    }
-    return token;
-  }
-
-  Token parseInvalidTopLevelDeclaration(Token token) {
-    Token next = token.next;
-    reportRecoverableErrorWithToken(
-        next,
-        optional(';', next)
-            ? fasta.templateUnexpectedToken
-            : fasta.templateExpectedDeclaration);
-    if (optional('{', next)) {
-      next = parseInvalidBlock(token);
-    }
-    listener.handleInvalidTopLevelDeclaration(next);
-    return next;
-  }
-
-  Token reportAndSkipClassInClass(Token token) {
-    assert(optional('class', token));
-    reportRecoverableError(token, fasta.messageClassInClass);
-    listener.handleInvalidMember(token);
-    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;
-      // 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;
-      }
-    }
-    return token;
-  }
-
-  Token reportAndSkipEnumInClass(Token token) {
-    assert(optional('enum', token));
-    reportRecoverableError(token, fasta.messageEnumInClass);
-    listener.handleInvalidMember(token);
-    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;
-      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;
-      }
-    }
-    return token;
-  }
-
-  Token reportAndSkipTypedefInClass(Token token) {
-    assert(optional('typedef', token));
-    reportRecoverableError(token, fasta.messageTypedefInClass);
-    listener.handleInvalidMember(token);
-    // TODO(brianwilkerson): If the declaration appears to be a valid typedef
-    // then skip the entire declaration so that we generate a single error
-    // (above) rather than many unhelpful errors.
-    return token;
-  }
-
-  /// Create a short token chain from the [beginToken] and [endToken] and return
-  /// the [beginToken].
-  Token link(BeginToken beginToken, Token endToken) {
-    beginToken.setNext(endToken);
-    beginToken.endGroup = endToken;
-    return beginToken;
-  }
-
-  /// Create and return a token whose next token is the given [token].
-  Token syntheticPreviousToken(Token token) {
-    // Return the previous token if there is one so that any token inserted
-    // before `token` will be properly inserted into the token stream.
-    // TODO(danrubel): remove this once all methods have been converted to
-    // use and return the last token consumed and the `previous` field
-    // has been removed.
-    if (token.previous != null) {
-      return token.previous;
-    }
-    Token before = new Token.eof(-1);
-    before.next = token;
-    return before;
-  }
-
-  /// 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;
-    bool isMultiline = false;
-    while (comments != null) {
-      String lexeme = comments.lexeme;
-      if (lexeme.startsWith('///')) {
-        if (!isMultiline) {
-          dartdoc = comments;
-          isMultiline = true;
-        }
-      } else if (lexeme.startsWith('/**')) {
-        dartdoc = comments;
-        isMultiline = false;
-      }
-      comments = comments.next;
-    }
-    return dartdoc;
-  }
-
-  /// Parse the comment references in a sequence of comment tokens
-  /// where [dartdoc] (not null) is the first token in the sequence.
-  /// Return the number of comment references parsed.
-  int parseCommentReferences(Token dartdoc) {
-    return dartdoc.lexeme.startsWith('///')
-        ? parseReferencesInSingleLineComments(dartdoc)
-        : parseReferencesInMultiLineComment(dartdoc);
-  }
-
-  /// Parse the comment references in a multi-line comment token.
-  /// Return the number of comment references parsed.
-  int parseReferencesInMultiLineComment(Token multiLineDoc) {
-    String comment = multiLineDoc.lexeme;
-    assert(comment.startsWith('/**'));
-    int count = 0;
-    int length = comment.length;
-    int start = 3;
-    bool inCodeBlock = false;
-    int codeBlock = comment.indexOf('```', 3);
-    if (codeBlock == -1) {
-      codeBlock = length;
-    }
-    while (start < length) {
-      if (isWhitespace(comment.codeUnitAt(start))) {
-        ++start;
-        continue;
-      }
-      int end = comment.indexOf('\n', start);
-      if (end == -1) {
-        end = length;
-      }
-      if (codeBlock < end) {
-        inCodeBlock = !inCodeBlock;
-        codeBlock = comment.indexOf('```', end);
-        if (codeBlock == -1) {
-          codeBlock = length;
-        }
-      }
-      if (!inCodeBlock && !comment.startsWith('*     ', start)) {
-        count += parseCommentReferencesInText(multiLineDoc, start, end);
-      }
-      start = end + 1;
-    }
-    return count;
-  }
-
-  /// 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 count = 0;
-    bool inCodeBlock = false;
-    while (token != null && !token.isEof) {
-      String comment = token.lexeme;
-      if (comment.startsWith('///')) {
-        if (comment.indexOf('```', 3) != -1) {
-          inCodeBlock = !inCodeBlock;
-        }
-        if (!inCodeBlock && !comment.startsWith('///    ')) {
-          count += parseCommentReferencesInText(token, 3, comment.length);
-        }
-      }
-      token = token.next;
-    }
-    return count;
-  }
-
-  /// Parse the comment references in the text between [start] inclusive
-  /// and [end] exclusive. Return a count indicating how many were parsed.
-  int parseCommentReferencesInText(Token commentToken, int start, int end) {
-    String comment = commentToken.lexeme;
-    int count = 0;
-    int index = start;
-    while (index < end) {
-      int ch = comment.codeUnitAt(index);
-      if (ch == 0x5B /* `[` */) {
-        ++index;
-        if (index < end && comment.codeUnitAt(index) == 0x3A /* `:` */) {
-          // Skip old-style code block.
-          index = comment.indexOf(':]', index + 1) + 1;
-          if (index == 0 || index > end) {
-            break;
-          }
-        } else {
-          int referenceStart = index;
-          index = comment.indexOf(']', index);
-          if (index == -1 || index >= end) {
-            // Recovery: terminating ']' is not typed yet.
-            index = findReferenceEnd(comment, referenceStart, end);
-          }
-          if (ch != 0x27 /* `'` */ && ch != 0x22 /* `"` */) {
-            if (isLinkText(comment, index)) {
-              // TODO(brianwilkerson) Handle the case where there's a library
-              // URI in the link text.
-            } else {
-              listener.handleCommentReferenceText(
-                  comment.substring(referenceStart, index),
-                  commentToken.charOffset + referenceStart);
-              ++count;
-            }
-          }
-        }
-      } else if (ch == 0x60 /* '`' */) {
-        // Skip inline code block if there is both starting '`' and ending '`'
-        int endCodeBlock = comment.indexOf('`', index + 1);
-        if (endCodeBlock != -1 && endCodeBlock < end) {
-          index = endCodeBlock;
-        }
-      }
-      ++index;
-    }
-    return count;
-  }
-
-  /// Given a comment reference without a closing `]`,
-  /// search for a possible place where `]` should be.
-  int findReferenceEnd(String comment, int index, int end) {
-    // Find the end of the identifier if there is one
-    if (index >= end || !isLetter(comment.codeUnitAt(index))) {
-      return index;
-    }
-    while (index < end && isLetterOrDigit(comment.codeUnitAt(index))) {
-      ++index;
-    }
-
-    // Check for a trailing `.`
-    if (index >= end || comment.codeUnitAt(index) != 0x2E /* `.` */) {
-      return index;
-    }
-    ++index;
-
-    // Find end of the identifier after the `.`
-    if (index >= end || !isLetter(comment.codeUnitAt(index))) {
-      return index;
-    }
-    ++index;
-    while (index < end && isLetterOrDigit(comment.codeUnitAt(index))) {
-      ++index;
-    }
-    return index;
-  }
-
-  /// Parse the tokens in a single comment reference and generate either a
-  /// `handleCommentReference` or `handleNoCommentReference` event.
-  /// Return `true` if a comment reference was successfully parsed.
-  bool parseOneCommentReference(Token token, int referenceOffset) {
-    Token begin = token;
-    Token newKeyword = null;
-    if (optional('new', token)) {
-      newKeyword = token;
-      token = token.next;
-    }
-    Token prefix, period;
-    if (token.isIdentifier && optional('.', token.next)) {
-      prefix = token;
-      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) {
-        begin = token;
-      }
-    }
-    Token operatorKeyword = null;
-    if (optional('operator', token)) {
-      operatorKeyword = token;
-      token = token.next;
-    }
-    if (token.isUserDefinableOperator) {
-      if (token.next.isEof) {
-        parseOneCommentReferenceRest(
-            begin, referenceOffset, newKeyword, prefix, period, token);
-        return true;
-      }
-    } else {
-      token = operatorKeyword ?? token;
-      if (token.next.isEof) {
-        if (token.isIdentifier) {
-          parseOneCommentReferenceRest(
-              begin, referenceOffset, newKeyword, prefix, period, token);
-          return true;
-        }
-        Keyword keyword = token.keyword;
-        if (newKeyword == null &&
-            prefix == null &&
-            (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.
-        }
-      }
-    }
-    listener.handleNoCommentReference();
-    return false;
-  }
-
-  void parseOneCommentReferenceRest(
-      Token begin,
-      int referenceOffset,
-      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;
-    } while (!token.isEof);
-
-    listener.handleCommentReference(
-        newKeyword, prefix, period, identifierOrOperator);
-  }
-
-  /// 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 ch = comment.codeUnitAt(index);
-    if (ch == 0x28 || ch == 0x3A) {
-      return true;
-    }
-    while (isWhitespace(ch)) {
-      index = index + 1;
-      if (index >= length) {
-        return false;
-      }
-      ch = comment.codeUnitAt(index);
-    }
-    return ch == 0x5B;
-  }
-}
-
-// TODO(ahe): Remove when analyzer supports generalized function syntax.
-typedef _MessageWithArgument<T> = Message Function(T);
diff --git a/pkg/front_end/lib/src/fasta/parser/parser_error.dart b/pkg/front_end/lib/src/fasta/parser/parser_error.dart
deleted file mode 100644
index 366ce24..0000000
--- a/pkg/front_end/lib/src/fasta/parser/parser_error.dart
+++ /dev/null
@@ -1,26 +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.
-
-library fasta.parser.parser_error;
-
-import '../fasta_codes.dart' show Message;
-
-import '../scanner.dart' show Token;
-
-class ParserError {
-  /// Character offset from the beginning of file where this error starts.
-  final int beginOffset;
-
-  /// Character offset from the beginning of file where this error ends.
-  final int endOffset;
-
-  final Message message;
-
-  ParserError(this.beginOffset, this.endOffset, this.message);
-
-  ParserError.fromTokens(Token begin, Token end, Message message)
-      : this(begin.charOffset, end.charOffset + end.charCount, message);
-
-  String toString() => "@${beginOffset}: ${message.message}\n${message.tip}";
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser_main.dart b/pkg/front_end/lib/src/fasta/parser/parser_main.dart
deleted file mode 100644
index 0079797..0000000
--- a/pkg/front_end/lib/src/fasta/parser/parser_main.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.parser.main;
-
-import 'dart:convert' show LineSplitter, utf8;
-
-import 'dart:io' show File;
-
-import '../../scanner/token.dart' show Token;
-
-import '../scanner/io.dart' show readBytesFromFileSync;
-
-import '../scanner.dart' show scan;
-
-import 'listener.dart' show Listener;
-
-import 'top_level_parser.dart' show TopLevelParser;
-
-import 'identifier_context.dart' show IdentifierContext;
-
-class DebugListener extends Listener {
-  void handleIdentifier(Token token, IdentifierContext context) {
-    logEvent("Identifier: ${token.lexeme}");
-  }
-
-  void logEvent(String name) {
-    print(name);
-  }
-}
-
-mainEntryPoint(List<String> arguments) async {
-  for (String argument in arguments) {
-    if (argument.startsWith("@")) {
-      Uri uri = Uri.base.resolve(argument.substring(1));
-      await for (String file in new File.fromUri(uri)
-          .openRead()
-          .cast<List<int>>()
-          .transform(utf8.decoder)
-          .transform(const LineSplitter())) {
-        outLine(uri.resolve(file));
-      }
-    } else {
-      outLine(Uri.base.resolve(argument));
-    }
-  }
-}
-
-void outLine(Uri uri) {
-  new TopLevelParser(new DebugListener())
-      .parseUnit(scan(readBytesFromFileSync(uri)).tokens);
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/recovery_listeners.dart b/pkg/front_end/lib/src/fasta/parser/recovery_listeners.dart
deleted file mode 100644
index c10bc98..0000000
--- a/pkg/front_end/lib/src/fasta/parser/recovery_listeners.dart
+++ /dev/null
@@ -1,96 +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 '../../scanner/token.dart' show Token;
-
-import 'forwarding_listener.dart' show ForwardingListener;
-
-class ClassHeaderRecoveryListener extends ForwardingListener {
-  Token extendsKeyword;
-  Token implementsKeyword;
-  Token withKeyword;
-
-  void clear() {
-    extendsKeyword = null;
-    implementsKeyword = null;
-    withKeyword = null;
-  }
-
-  @override
-  void handleClassExtends(Token extendsKeyword) {
-    this.extendsKeyword = extendsKeyword;
-    super.handleClassExtends(extendsKeyword);
-  }
-
-  @override
-  void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
-    this.implementsKeyword = implementsKeyword;
-    super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
-  }
-
-  @override
-  void handleClassWithClause(Token withKeyword) {
-    this.withKeyword = withKeyword;
-    super.handleClassWithClause(withKeyword);
-  }
-}
-
-class ImportRecoveryListener extends ForwardingListener {
-  Token asKeyword;
-  Token deferredKeyword;
-  Token ifKeyword;
-  bool hasCombinator = false;
-
-  void clear() {
-    asKeyword = null;
-    deferredKeyword = null;
-    ifKeyword = null;
-    hasCombinator = false;
-  }
-
-  void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
-    this.ifKeyword = ifKeyword;
-    super.endConditionalUri(ifKeyword, leftParen, equalSign);
-  }
-
-  void endHide(Token hideKeyword) {
-    this.hasCombinator = true;
-    super.endHide(hideKeyword);
-  }
-
-  void endShow(Token showKeyword) {
-    this.hasCombinator = true;
-    super.endShow(showKeyword);
-  }
-
-  void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
-    this.deferredKeyword = deferredKeyword;
-    this.asKeyword = asKeyword;
-    super.handleImportPrefix(deferredKeyword, asKeyword);
-  }
-}
-
-class MixinHeaderRecoveryListener extends ForwardingListener {
-  Token onKeyword;
-  Token implementsKeyword;
-
-  void clear() {
-    onKeyword = null;
-    implementsKeyword = null;
-  }
-
-  @override
-  void handleClassOrMixinImplements(
-      Token implementsKeyword, int interfacesCount) {
-    this.implementsKeyword = implementsKeyword;
-    super.handleClassOrMixinImplements(implementsKeyword, interfacesCount);
-  }
-
-  @override
-  void handleMixinOn(Token onKeyword, int typeCount) {
-    this.onKeyword = onKeyword;
-    super.handleMixinOn(onKeyword, typeCount);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
deleted file mode 100644
index 29ab789..0000000
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ /dev/null
@@ -1,219 +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 '../scanner/error_token.dart' show UnmatchedToken;
-
-import '../../scanner/token.dart'
-    show
-        BeginToken,
-        Keyword,
-        SimpleToken,
-        SyntheticBeginToken,
-        SyntheticKeywordToken,
-        SyntheticStringToken,
-        SyntheticToken,
-        Token,
-        TokenType;
-
-/// Provides the capability of inserting tokens into a token stream. This
-/// implementation does this by rewriting the previous token to point to the
-/// inserted token.
-class TokenStreamRewriter with _TokenStreamMixin {
-  // TODO(brianwilkerson):
-  //
-  // When we get to the point of removing `token.previous`, the plan is to
-  // convert this into an interface and provide two implementations.
-  //
-  // One, used by Fasta, will connect the inserted tokens to the following token
-  // without modifying the previous token.
-  //
-  // The other, used by 'analyzer', will be created with the first token in the
-  // stream (actually with the BOF marker at the beginning of the stream). It
-  // will be created only when invoking 'analyzer' specific parse methods (in
-  // `Parser`), such as
-  //
-  // Token parseUnitWithRewrite(Token bof) {
-  //   rewriter = AnalyzerTokenStreamRewriter(bof);
-  //   return parseUnit(bof.next);
-  // }
-  //
-
-  /// Insert a synthetic open and close parenthesis and return the new synthetic
-  /// 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;
-    int offset = next.charOffset;
-    BeginToken leftParen =
-        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
-    if (includeIdentifier) {
-      next = next.setNext(
-          new SyntheticStringToken(TokenType.IDENTIFIER, '', offset, 0));
-    }
-    next = next.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
-    leftParen.endGroup = next;
-    next.setNext(token.next);
-
-    // A no-op rewriter could skip this step.
-    token.setNext(leftParen);
-
-    return leftParen;
-  }
-
-  /// Insert [newToken] after [token] and return [newToken].
-  Token insertToken(Token token, Token newToken) {
-    newToken.setNext(token.next);
-
-    // A no-op rewriter could skip this step.
-    token.setNext(newToken);
-
-    return newToken;
-  }
-
-  /// 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(endGroup.beforeSynthetic != null);
-    Token errorToken;
-    if (endGroup.next is UnmatchedToken) {
-      errorToken = endGroup.next;
-    }
-
-    // Remove endGroup from its current location
-    endGroup.beforeSynthetic.setNext((errorToken ?? endGroup).next);
-
-    // Insert endGroup into its new location
-    Token next = token.next;
-    token.setNext(endGroup);
-    (errorToken ?? endGroup).setNext(next);
-    endGroup.offset = next.offset;
-    if (errorToken != null) {
-      errorToken.offset = next.offset;
-    }
-
-    return endGroup;
-  }
-
-  /// Replace the single token immediately following the [previousToken] with
-  /// the chain of tokens starting at the [replacementToken]. Return the
-  /// [replacementToken].
-  Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
-    Token replacedToken = previousToken.next;
-    previousToken.setNext(replacementToken);
-
-    (replacementToken as SimpleToken).precedingComments =
-        replacedToken.precedingComments;
-
-    _lastTokenInChain(replacementToken).setNext(replacedToken.next);
-
-    return replacementToken;
-  }
-
-  /// Given the [firstToken] in a chain of tokens to be inserted, return the
-  /// last token in the chain.
-  ///
-  /// 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 current = firstToken;
-    while (current.next != null && current.next.type != TokenType.EOF) {
-      if (previous != null) {
-        current.previous = previous;
-      }
-      previous = current;
-      current = current.next;
-    }
-    if (previous != null) {
-      current.previous = previous;
-    }
-    return current;
-  }
-}
-
-/// Provides the capability of adding tokens that lead into a token stream
-/// without modifying the original token stream and not setting the any token's
-/// `previous` field.
-class TokenStreamGhostWriter
-    with _TokenStreamMixin
-    implements TokenStreamRewriter {
-  @override
-  Token insertParens(Token token, bool includeIdentifier) {
-    Token next = token.next;
-    int offset = next.charOffset;
-    BeginToken leftParen =
-        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
-    if (includeIdentifier) {
-      Token identifier =
-          new SyntheticStringToken(TokenType.IDENTIFIER, '', offset, 0);
-      next.next = identifier;
-      next = identifier;
-    }
-    Token rightParen = new SyntheticToken(TokenType.CLOSE_PAREN, offset);
-    next.next = rightParen;
-    rightParen.next = token.next;
-
-    return leftParen;
-  }
-
-  @override
-  Token insertToken(Token token, Token newToken) {
-    newToken.next = token.next;
-    return newToken;
-  }
-
-  @override
-  Token moveSynthetic(Token token, Token endGroup) {
-    Token newEndGroup =
-        new SyntheticToken(endGroup.type, token.next.charOffset);
-    newEndGroup.next = token.next;
-    return newEndGroup;
-  }
-
-  @override
-  Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
-    Token replacedToken = previousToken.next;
-
-    (replacementToken as SimpleToken).precedingComments =
-        replacedToken.precedingComments;
-
-    _lastTokenInChain(replacementToken).next = replacedToken.next;
-    return replacementToken;
-  }
-
-  /// Given the [firstToken] in a chain of tokens to be inserted, return the
-  /// last token in the chain.
-  Token _lastTokenInChain(Token firstToken) {
-    Token current = firstToken;
-    while (current.next != null && current.next.type != TokenType.EOF) {
-      current = current.next;
-    }
-    return current;
-  }
-}
-
-mixin _TokenStreamMixin {
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token, [String value]) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(
-            TokenType.IDENTIFIER, value ?? '', token.next.charOffset, 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));
-
-  /// 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));
-  }
-
-  /// Insert [newToken] after [token] and return [newToken].
-  Token insertToken(Token token, Token newToken);
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/top_level_parser.dart b/pkg/front_end/lib/src/fasta/parser/top_level_parser.dart
deleted file mode 100644
index 802f28e..0000000
--- a/pkg/front_end/lib/src/fasta/parser/top_level_parser.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.parser.top_level_parser;
-
-import '../../scanner/token.dart' show Token;
-
-import 'declaration_kind.dart' show DeclarationKind;
-
-import 'class_member_parser.dart' show ClassMemberParser;
-
-import 'listener.dart' show Listener;
-
-/// Parser which only parses top-level elements, but ignores their bodies.
-/// Use [Parser] to parse everything.
-class TopLevelParser extends ClassMemberParser {
-  TopLevelParser(Listener listener) : super(listener);
-
-  @override
-  Token parseClassOrMixinOrExtensionBody(
-          Token token, DeclarationKind kind, String enclosingDeclarationName) =>
-      skipClassOrMixinOrExtensionBody(token);
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
deleted file mode 100644
index f18f43e..0000000
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ /dev/null
@@ -1,346 +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.
-
-library fasta.parser.type_info;
-
-import '../../scanner/token.dart' show Token, TokenType;
-
-import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN, KEYWORD_TOKEN;
-
-import 'parser.dart' show Parser;
-
-import 'type_info_impl.dart';
-
-import 'util.dart' show isOneOf, optional;
-
-/// [TypeInfo] provides information collected by [computeType]
-/// about a particular type reference.
-abstract class TypeInfo {
-  /// Return type info representing the receiver without the trailing `?`
-  /// or the receiver if the receiver does not represent a nullable type.
-  TypeInfo get asNonNullable;
-
-  /// Return `true` if the tokens comprising the type represented by the
-  /// receiver could be interpreted as a valid standalone expression.
-  /// For example, `A` or `A.b` could be interpreted as type references
-  /// or expressions, while `A<T>` only looks like a type reference.
-  bool get couldBeExpression;
-
-  /// Return true if the receiver has a trailing `?`.
-  bool get isNullable;
-
-  /// Call this function when the token after [token] must be a type (not void).
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the type, inserting a synthetic type reference if
-  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
-  /// or `>>>=` in valid code or during recovery.
-  Token ensureTypeNotVoid(Token token, Parser parser);
-
-  /// Call this function when the token after [token] must be a type or void.
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the type, inserting a synthetic type reference if
-  /// necessary. This may modify the token stream when parsing `>>` or `>>>`
-  /// or `>>>=` in valid code or during recovery.
-  Token ensureTypeOrVoid(Token token, Parser parser);
-
-  /// Call this function to parse an optional type (not void) after [token].
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the type. This may modify the token stream
-  /// when parsing `>>` or `>>>` or `>>>=`  in valid code or during recovery.
-  Token parseTypeNotVoid(Token token, Parser parser);
-
-  /// Call this function to parse an optional type or void after [token].
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the type. This may modify the token stream
-  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
-  Token parseType(Token token, Parser parser);
-
-  /// Call this function with the [token] before the type to obtain
-  /// the last token in the type. If there is no type, then this method
-  /// will return [token]. This does not modify the token stream.
-  Token skipType(Token token);
-}
-
-/// [TypeParamOrArgInfo] provides information collected by
-/// [computeTypeParamOrArg] about a particular group of type arguments
-/// or type parameters.
-abstract class TypeParamOrArgInfo {
-  const TypeParamOrArgInfo();
-
-  /// Return `true` if the receiver represents a single type argument
-  bool get isSimpleTypeArgument => false;
-
-  /// Return the number of type arguments
-  int get typeArgumentCount;
-
-  /// Return the simple type associated with this simple type argument
-  /// or throw an exception if this is not a simple type argument.
-  TypeInfo get typeInfo {
-    throw "Internal error: $runtimeType is not a SimpleTypeArgument.";
-  }
-
-  /// Call this function to parse optional type arguments after [token].
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the arguments. This may modify the token stream
-  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
-  Token parseArguments(Token token, Parser parser);
-
-  /// Call this function to parse optional type parameters
-  /// (also known as type variables) after [token].
-  /// This function will call the appropriate event methods on the [Parser]'s
-  /// listener to handle the parameters. This may modify the token stream
-  /// when parsing `>>` or `>>>` or `>>>=` in valid code or during recovery.
-  Token parseVariables(Token token, Parser parser);
-
-  /// Call this function with the [token] before the type var to obtain
-  /// the last token in the type var. If there is no type var, then this method
-  /// will return [token]. This does not modify the token stream.
-  Token skip(Token token);
-}
-
-/// [NoType] is a specialized [TypeInfo] returned by [computeType] when
-/// there is no type information in the source.
-const TypeInfo noType = const NoType();
-
-/// [NoTypeParamOrArg] is a specialized [TypeParamOrArgInfo] returned by
-/// [computeTypeParamOrArg] when no type parameters or arguments are found.
-const TypeParamOrArgInfo noTypeParamOrArg = const NoTypeParamOrArg();
-
-/// [VoidType] is a specialized [TypeInfo] returned by [computeType] when
-/// `void` appears in the source.
-const TypeInfo voidType = const VoidType();
-
-bool isGeneralizedFunctionType(Token token) {
-  return optional('Function', token) &&
-      (optional('<', token.next) || optional('(', token.next));
-}
-
-bool isValidTypeReference(Token token) {
-  int kind = token.kind;
-  if (IDENTIFIER_TOKEN == kind) return true;
-  if (KEYWORD_TOKEN == kind) {
-    TokenType type = token.type;
-    String value = type.lexeme;
-    return type.isPseudo ||
-        (type.isBuiltIn && optional('.', token.next)) ||
-        (identical(value, 'dynamic')) ||
-        (identical(value, 'void'));
-  }
-  return false;
-}
-
-/// Called by the parser to obtain information about a possible type reference
-/// that follows [token]. This does not modify the token stream.
-///
-/// If [inDeclaration] is `true`, then this will more aggressively recover
-/// given unbalanced `<` `>` and invalid parameters or arguments.
-TypeInfo computeType(final Token token, bool required,
-    [bool inDeclaration = false]) {
-  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)) {
-          return new ComplexTypeInfo(token, typeParamOrArg)
-              .computeBuiltinOrVarAsType(required);
-        }
-      } 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))) {
-          return new ComplexTypeInfo(token, typeParamOrArg)
-              .computeBuiltinOrVarAsType(required);
-        }
-      }
-    } else if (required) {
-      // Recovery
-      if (optional('.', next)) {
-        // Looks like prefixed type missing the prefix
-        return new ComplexTypeInfo(
-                token, computeTypeParamOrArg(next, inDeclaration))
-            .computePrefixedType(required);
-      } else if (optional('var', next) &&
-          isOneOf(next.next, const ['<', ',', '>'])) {
-        return new ComplexTypeInfo(
-                token, computeTypeParamOrArg(next, inDeclaration))
-            .computeBuiltinOrVarAsType(required);
-      }
-    }
-    return noType;
-  }
-
-  if (optional('void', next)) {
-    next = next.next;
-    if (isGeneralizedFunctionType(next)) {
-      // `void` `Function` ...
-      return new ComplexTypeInfo(token, noTypeParamOrArg)
-          .computeVoidGFT(required);
-    }
-    // `void`
-    return voidType;
-  }
-
-  if (isGeneralizedFunctionType(next)) {
-    // `Function` ...
-    return new ComplexTypeInfo(token, noTypeParamOrArg)
-        .computeNoTypeGFT(token, required);
-  }
-
-  // We've seen an identifier.
-
-  TypeParamOrArgInfo typeParamOrArg =
-      computeTypeParamOrArg(next, inDeclaration);
-  if (typeParamOrArg != noTypeParamOrArg) {
-    if (typeParamOrArg.isSimpleTypeArgument) {
-      // We've seen identifier `<` identifier `>`
-      next = typeParamOrArg.skip(next).next;
-      if (optional('?', next)) {
-        next = next.next;
-        if (!isGeneralizedFunctionType(next)) {
-          if ((required || looksLikeName(next)) &&
-              typeParamOrArg == simpleTypeArgument1) {
-            // identifier `<` identifier `>` `?` identifier
-            return simpleNullableTypeWith1Argument;
-          }
-          // identifier `<` identifier `>` `?` non-identifier
-          return noType;
-        }
-      } else if (!isGeneralizedFunctionType(next)) {
-        if (required || looksLikeName(next)) {
-          // identifier `<` identifier `>` identifier
-          return typeParamOrArg.typeInfo;
-        }
-        // identifier `<` identifier `>` non-identifier
-        return noType;
-      }
-    }
-    // TODO(danrubel): Consider adding a const for
-    // identifier `<` identifier `,` identifier `>`
-    // if that proves to be a common case.
-
-    // identifier `<` ... `>`
-    return new ComplexTypeInfo(token, typeParamOrArg)
-        .computeSimpleWithTypeArguments(required);
-  }
-
-  assert(typeParamOrArg == noTypeParamOrArg);
-  next = next.next;
-  if (optional('.', next)) {
-    next = next.next;
-    if (isValidTypeReference(next)) {
-      // We've seen identifier `.` identifier
-      typeParamOrArg = computeTypeParamOrArg(next, inDeclaration);
-      next = next.next;
-      if (typeParamOrArg == noTypeParamOrArg) {
-        if (optional('?', next)) {
-          next = next.next;
-          if (!isGeneralizedFunctionType(next)) {
-            if (required || looksLikeName(next)) {
-              // identifier `.` identifier `?` identifier
-              // TODO(danrubel): consider adding PrefixedNullableType
-              // Fall through to build complex type
-            } else {
-              // identifier `.` identifier `?` non-identifier
-              return noType;
-            }
-          }
-        } else {
-          if (!isGeneralizedFunctionType(next)) {
-            if (required || looksLikeName(next)) {
-              // identifier `.` identifier identifier
-              return prefixedType;
-            } else {
-              // identifier `.` identifier non-identifier
-              return noType;
-            }
-          }
-        }
-      }
-      // identifier `.` identifier
-      return new ComplexTypeInfo(token, typeParamOrArg)
-          .computePrefixedType(required);
-    }
-    // identifier `.` non-identifier
-    if (required) {
-      typeParamOrArg = computeTypeParamOrArg(token.next.next, inDeclaration);
-      return new ComplexTypeInfo(token, typeParamOrArg)
-          .computePrefixedType(required);
-    }
-    return noType;
-  }
-
-  assert(typeParamOrArg == noTypeParamOrArg);
-  if (isGeneralizedFunctionType(next)) {
-    // identifier `Function`
-    return new ComplexTypeInfo(token, noTypeParamOrArg)
-        .computeIdentifierGFT(required);
-  }
-
-  if (optional('?', next)) {
-    next = next.next;
-    if (isGeneralizedFunctionType(next)) {
-      // identifier `?` Function `(`
-      return new ComplexTypeInfo(token, noTypeParamOrArg)
-          .computeIdentifierQuestionGFT(required);
-    } else if (required || looksLikeName(next)) {
-      // identifier `?`
-      return simpleNullableType;
-    }
-  } else if (required || looksLikeName(next)) {
-    // identifier identifier
-    return simpleType;
-  }
-  return noType;
-}
-
-/// Called by the parser to obtain information about a possible group of type
-/// parameters or type arguments that follow [token].
-/// This does not modify the token stream.
-///
-/// If [inDeclaration] is `true`, then this will more aggressively recover
-/// given unbalanced `<` `>` and invalid parameters or arguments.
-TypeParamOrArgInfo computeTypeParamOrArg(Token token,
-    [bool inDeclaration = false, bool allowsVariance = false]) {
-  Token beginGroup = token.next;
-  if (!optional('<', beginGroup)) {
-    return noTypeParamOrArg;
-  }
-
-  // identifier `<` `void` `>` and `<` `dynamic` `>`
-  // are handled by ComplexTypeInfo.
-  Token next = beginGroup.next;
-  if ((next.kind == IDENTIFIER_TOKEN || next.type.isPseudo)) {
-    if (optional('>', next.next)) {
-      return simpleTypeArgument1;
-    } else if (optional('>>', next.next)) {
-      return simpleTypeArgument1GtGt;
-    } else if (optional('>=', next.next)) {
-      return simpleTypeArgument1GtEq;
-    }
-  } else if (optional('(', next)) {
-    return noTypeParamOrArg;
-  }
-
-  // TODO(danrubel): Consider adding additional const for common situations.
-  return new ComplexTypeParamOrArgInfo(token, inDeclaration, allowsVariance)
-      .compute();
-}
-
-/// Called by the parser to obtain information about a possible group of type
-/// type arguments that follow [token] and that are followed by '('.
-/// Returns the type arguments if [token] matches '<' type (',' type)* '>' '(',
-/// and otherwise returns [noTypeParamOrArg]. The final '(' is not part of the
-/// grammar construct `typeArguments`, but it is required here such that type
-/// arguments in generic method invocations can be recognized, and as few as
-/// 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;
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
deleted file mode 100644
index 1255e8d..0000000
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ /dev/null
@@ -1,1263 +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.
-
-library fasta.parser.type_info_impl;
-
-import '../../scanner/token.dart' show SyntheticToken, Token, TokenType;
-
-import '../fasta_codes.dart' as fasta;
-
-import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
-
-import '../util/link.dart' show Link;
-
-import 'forwarding_listener.dart' show ForwardingListener;
-
-import 'identifier_context.dart' show IdentifierContext;
-
-import 'member_kind.dart' show MemberKind;
-
-import 'listener.dart' show Listener;
-
-import 'parser.dart' show Parser;
-
-import 'type_info.dart';
-
-import 'util.dart'
-    show
-        optional,
-        skipMetadata,
-        splitGtEq,
-        splitGtFromGtGtEq,
-        splitGtFromGtGtGt,
-        splitGtFromGtGtGtEq,
-        splitGtGt,
-        syntheticGt;
-
-/// [SimpleType] is a specialized [TypeInfo] returned by [computeType]
-/// when there is a single identifier as the type reference.
-const TypeInfo simpleType = const SimpleType();
-
-/// [SimpleNullableType] is a specialized [TypeInfo] returned by [computeType]
-/// when there is a single identifier followed by `?` as the type reference.
-const TypeInfo simpleNullableType = const SimpleNullableType();
-
-/// [PrefixedType] is a specialized [TypeInfo] returned by [computeType]
-/// when the type reference is of the form: identifier `.` identifier.
-const TypeInfo prefixedType = const PrefixedType();
-
-/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
-/// [computeType] when the type reference is of the form:
-/// identifier `<` identifier `>`.
-const TypeInfo simpleTypeWith1Argument =
-    const SimpleTypeWith1Argument(simpleTypeArgument1);
-
-/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
-/// [computeType] when the type reference is of the form:
-/// identifier `<` identifier `>=`.
-const TypeInfo simpleTypeWith1ArgumentGtEq =
-    const SimpleTypeWith1Argument(simpleTypeArgument1GtEq);
-
-/// [SimpleTypeWith1Argument] is a specialized [TypeInfo] returned by
-/// [computeType] when the type reference is of the form:
-/// identifier `<` identifier `>>`.
-const TypeInfo simpleTypeWith1ArgumentGtGt =
-    const SimpleTypeWith1Argument(simpleTypeArgument1GtGt);
-
-/// [SimpleNullableTypeWith1Argument] is a specialized [TypeInfo] returned by
-/// [computeType] when the type reference is of the form:
-/// identifier `<` identifier `>` `?`.
-const TypeInfo simpleNullableTypeWith1Argument =
-    const SimpleNullableTypeWith1Argument();
-
-/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
-/// [computeTypeParamOrArg] when the type reference is of the form:
-/// `<` identifier `>`.
-const TypeParamOrArgInfo simpleTypeArgument1 = const SimpleTypeArgument1();
-
-/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
-/// [computeTypeParamOrArg] when the type reference is of the form:
-/// `<` identifier `>=`.
-const TypeParamOrArgInfo simpleTypeArgument1GtEq =
-    const SimpleTypeArgument1GtEq();
-
-/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
-/// [computeTypeParamOrArg] when the type reference is of the form:
-/// `<` identifier `>>`.
-const TypeParamOrArgInfo simpleTypeArgument1GtGt =
-    const SimpleTypeArgument1GtGt();
-
-/// See documentation on the [noType] const.
-class NoType implements TypeInfo {
-  const NoType();
-
-  @override
-  TypeInfo get asNonNullable => this;
-
-  @override
-  bool get couldBeExpression => false;
-
-  @override
-  bool get isNullable => false;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) {
-    parser.reportRecoverableErrorWithToken(
-        token.next, fasta.templateExpectedType);
-    parser.rewriter.insertSyntheticIdentifier(token);
-    return simpleType.parseType(token, parser);
-  }
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      ensureTypeNotVoid(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    parser.listener.handleNoType(token);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return token;
-  }
-}
-
-/// See documentation on the [prefixedType] const.
-class PrefixedType implements TypeInfo {
-  const PrefixedType();
-
-  @override
-  TypeInfo get asNonNullable => this;
-
-  @override
-  bool get couldBeExpression => true;
-
-  @override
-  bool get isNullable => false;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    Token start = token = token.next;
-    assert(token.isKeywordOrIdentifier);
-    Listener listener = parser.listener;
-    listener.handleIdentifier(token, IdentifierContext.prefixedTypeReference);
-
-    Token period = token = token.next;
-    assert(optional('.', token));
-
-    token = token.next;
-    assert(token.isKeywordOrIdentifier);
-    listener.handleIdentifier(
-        token, IdentifierContext.typeReferenceContinuation);
-    listener.handleQualified(period);
-
-    listener.handleNoTypeArguments(token.next);
-    listener.handleType(start, null);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return token.next.next.next;
-  }
-}
-
-/// See documentation on the [simpleNullableTypeWith1Argument] const.
-class SimpleNullableTypeWith1Argument extends SimpleTypeWith1Argument {
-  const SimpleNullableTypeWith1Argument() : super(simpleTypeArgument1);
-
-  @override
-  TypeInfo get asNonNullable => simpleTypeWith1Argument;
-
-  @override
-  bool get isNullable => true;
-
-  @override
-  Token parseTypeRest(Token start, Token token, Parser parser) {
-    token = token.next;
-    assert(optional('?', token));
-    parser.listener.handleType(start, token);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    token = super.skipType(token).next;
-    assert(optional('?', token));
-    return token;
-  }
-}
-
-/// See documentation on the [simpleTypeWith1Argument] const.
-class SimpleTypeWith1Argument implements TypeInfo {
-  final TypeParamOrArgInfo typeArg;
-
-  const SimpleTypeWith1Argument(this.typeArg);
-
-  @override
-  TypeInfo get asNonNullable => this;
-
-  @override
-  bool get couldBeExpression => false;
-
-  @override
-  bool get isNullable => false;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    Token start = token = token.next;
-    assert(token.isKeywordOrIdentifier);
-    parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
-    token = typeArg.parseArguments(token, parser);
-    return parseTypeRest(start, token, parser);
-  }
-
-  Token parseTypeRest(Token start, Token token, Parser parser) {
-    parser.listener.handleType(start, null);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    token = token.next;
-    assert(token.isKeywordOrIdentifier);
-    return typeArg.skip(token);
-  }
-}
-
-/// See documentation on the [simpleNullableType] const.
-class SimpleNullableType extends SimpleType {
-  const SimpleNullableType();
-
-  @override
-  TypeInfo get asNonNullable => simpleType;
-
-  @override
-  bool get isNullable => true;
-
-  @override
-  Token parseTypeRest(Token start, Parser parser) {
-    Token token = start.next;
-    assert(optional('?', token));
-    parser.listener.handleType(start, token);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return token.next.next;
-  }
-}
-
-/// See documentation on the [simpleType] const.
-class SimpleType implements TypeInfo {
-  const SimpleType();
-
-  @override
-  TypeInfo get asNonNullable => this;
-
-  @override
-  bool get couldBeExpression => true;
-
-  @override
-  bool get isNullable => false;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    token = token.next;
-    assert(isValidTypeReference(token));
-    parser.listener.handleIdentifier(token, IdentifierContext.typeReference);
-    token = noTypeParamOrArg.parseArguments(token, parser);
-    return parseTypeRest(token, parser);
-  }
-
-  Token parseTypeRest(Token token, Parser parser) {
-    parser.listener.handleType(token, null);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return token.next;
-  }
-}
-
-/// See documentation on the [voidType] const.
-class VoidType implements TypeInfo {
-  const VoidType();
-
-  @override
-  TypeInfo get asNonNullable => this;
-
-  @override
-  bool get couldBeExpression => false;
-
-  @override
-  bool get isNullable => false;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) {
-    // Report an error, then parse `void` as if it were a type name.
-    parser.reportRecoverableError(token.next, fasta.messageInvalidVoid);
-    return simpleType.parseTypeNotVoid(token, parser);
-  }
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      ensureTypeNotVoid(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    token = token.next;
-    parser.listener.handleVoidKeyword(token);
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return token.next;
-  }
-}
-
-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));
-
-/// 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;
-    if (next.kind == IDENTIFIER_TOKEN ||
-        optional(',', next) ||
-        isCloser(next)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-/// Instances of [ComplexTypeInfo] are returned by [computeType] to represent
-/// type references that cannot be represented by the constants above.
-class ComplexTypeInfo implements TypeInfo {
-  /// The first token in the type reference.
-  Token start;
-
-  /// Type arguments were seen during analysis.
-  final TypeParamOrArgInfo typeArguments;
-
-  /// 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;
-
-  /// The last token in the type reference.
-  Token end;
-
-  /// The `Function` tokens before the start of type variables of function types
-  /// as seen during analysis.
-  Link<Token> typeVariableStarters = const Link<Token>();
-
-  /// If the receiver represents a generalized function type then this indicates
-  /// whether it has a return type, otherwise this is `null`.
-  bool gftHasReturnType;
-
-  ComplexTypeInfo(Token beforeStart, this.typeArguments)
-      : this.start = beforeStart.next {
-    assert(typeArguments != null);
-  }
-
-  ComplexTypeInfo._nonNullable(this.start, this.typeArguments, this.end,
-      this.typeVariableStarters, this.gftHasReturnType);
-
-  @override
-  TypeInfo get asNonNullable {
-    return beforeQuestionMark == null
-        ? this
-        : new ComplexTypeInfo._nonNullable(start, typeArguments,
-            beforeQuestionMark, typeVariableStarters, gftHasReturnType);
-  }
-
-  @override
-  bool get couldBeExpression =>
-      typeArguments == noTypeParamOrArg && typeVariableStarters.isEmpty;
-
-  @override
-  bool get isNullable => beforeQuestionMark != null;
-
-  @override
-  Token ensureTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token ensureTypeOrVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseTypeNotVoid(Token token, Parser parser) =>
-      parseType(token, parser);
-
-  @override
-  Token parseType(Token token, Parser parser) {
-    assert(identical(token.next, start));
-
-    if (optional('.', start)) {
-      // Recovery: Insert missing identifier without sending events
-      start = parser.insertSyntheticIdentifier(
-          token, IdentifierContext.prefixedTypeReference);
-    }
-
-    final List<Token> typeVariableEndGroups = <Token>[];
-    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
-      typeVariableEndGroups.add(
-          computeTypeParamOrArg(t.head, true).parseVariables(t.head, parser));
-      parser.listener.beginFunctionType(start);
-    }
-
-    if (gftHasReturnType == false) {
-      // A function type without return type.
-      // Push the non-existing return type first. The loop below will
-      // generate the full type.
-      noType.parseType(token, parser);
-    } else {
-      Token typeRefOrPrefix = token.next;
-      if (optional('void', typeRefOrPrefix)) {
-        token = voidType.parseType(token, parser);
-      } else {
-        if (!optional('.', typeRefOrPrefix) &&
-            !optional('.', typeRefOrPrefix.next)) {
-          token =
-              parser.ensureIdentifier(token, IdentifierContext.typeReference);
-        } else {
-          token = parser.ensureIdentifier(
-              token, IdentifierContext.prefixedTypeReference);
-          token = parser.parseQualifiedRest(
-              token, IdentifierContext.typeReferenceContinuation);
-          if (token.isSynthetic && end == typeRefOrPrefix.next) {
-            // Recovery: Update `end` if a synthetic identifier was inserted.
-            end = token;
-          }
-        }
-        token = typeArguments.parseArguments(token, parser);
-
-        // Only consume the `?` if it is part of the complex type
-        Token questionMark = token.next;
-        if (optional('?', questionMark) &&
-            (typeVariableEndGroups.isNotEmpty || beforeQuestionMark != null)) {
-          token = questionMark;
-        } else {
-          questionMark = null;
-        }
-
-        parser.listener.handleType(typeRefOrPrefix, questionMark);
-      }
-    }
-
-    int endGroupIndex = typeVariableEndGroups.length - 1;
-    for (Link<Token> t = typeVariableStarters; t.isNotEmpty; t = t.tail) {
-      token = token.next;
-      assert(optional('Function', token));
-      Token functionToken = token;
-
-      if (optional("<", token.next)) {
-        // Skip type parameters, they were parsed above.
-        token = typeVariableEndGroups[endGroupIndex];
-        assert(optional('>', token));
-      }
-      token = parser.parseFormalParametersRequiredOpt(
-          token, MemberKind.GeneralizedFunctionType);
-
-      // Only consume the `?` if it is part of the complex type
-      Token questionMark = token.next;
-      if (optional('?', questionMark) &&
-          (endGroupIndex > 0 || beforeQuestionMark != null)) {
-        token = questionMark;
-      } else {
-        questionMark = null;
-      }
-
-      --endGroupIndex;
-      parser.listener.endFunctionType(functionToken, questionMark);
-    }
-
-    // There are two situations in which the [token] != [end]:
-    // Valid code:    identifier `<` identifier `<` identifier `>>`
-    //    where `>>` is replaced by two tokens.
-    // Invalid code:  identifier `<` identifier identifier `>`
-    //    where a synthetic `>` is inserted between the identifiers.
-    assert(identical(token, end) || optional('>', token));
-
-    // During recovery, [token] may be a synthetic that was inserted in the
-    // middle of the type reference.
-    end = token;
-    return token;
-  }
-
-  @override
-  Token skipType(Token token) {
-    return end;
-  }
-
-  /// Given `Function` non-identifier, compute the type
-  /// and return the receiver or one of the [TypeInfo] constants.
-  TypeInfo computeNoTypeGFT(Token beforeStart, bool required) {
-    assert(optional('Function', start));
-    assert(beforeStart.next == start);
-
-    computeRest(beforeStart, required);
-    if (gftHasReturnType == null) {
-      return required ? simpleType : noType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  /// Given void `Function` non-identifier, compute the type
-  /// and return the receiver or one of the [TypeInfo] constants.
-  TypeInfo computeVoidGFT(bool required) {
-    assert(optional('void', start));
-    assert(optional('Function', start.next));
-
-    computeRest(start, required);
-    if (gftHasReturnType == null) {
-      return voidType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  /// Given identifier `Function` non-identifier, compute the type
-  /// and return the receiver or one of the [TypeInfo] constants.
-  TypeInfo computeIdentifierGFT(bool required) {
-    assert(isValidTypeReference(start));
-    assert(optional('Function', start.next));
-
-    computeRest(start, required);
-    if (gftHasReturnType == null) {
-      return simpleType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  /// Given identifier `?` `Function` non-identifier, compute the type
-  /// 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));
-
-    computeRest(start, required);
-    if (gftHasReturnType == null) {
-      return simpleNullableType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  /// Given a builtin, return the receiver so that parseType will report
-  /// an error for the builtin used as a type.
-  TypeInfo computeBuiltinOrVarAsType(bool required) {
-    assert(start.type.isBuiltIn || optional('var', start));
-
-    end = typeArguments.skip(start);
-    computeRest(end, required);
-    assert(end != null);
-    return this;
-  }
-
-  /// Given identifier `<` ... `>`, compute the type
-  /// and return the receiver or one of the [TypeInfo] constants.
-  TypeInfo computeSimpleWithTypeArguments(bool required) {
-    assert(isValidTypeReference(start));
-    assert(optional('<', start.next));
-    assert(typeArguments != noTypeParamOrArg);
-
-    end = typeArguments.skip(start);
-    computeRest(end, required);
-
-    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
-      return noType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  /// Given identifier `.` identifier (or `.` identifier or identifier `.`
-  /// for recovery), compute the type and return the receiver or one of the
-  /// [TypeInfo] constants.
-  TypeInfo computePrefixedType(bool required) {
-    Token token = start;
-    if (!optional('.', token)) {
-      assert(token.isKeywordOrIdentifier);
-      token = token.next;
-    }
-    assert(optional('.', token));
-    if (token.next.isKeywordOrIdentifier) {
-      token = token.next;
-    }
-
-    end = typeArguments.skip(token);
-    computeRest(end, required);
-    if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
-      return noType;
-    }
-    assert(end != null);
-    return this;
-  }
-
-  void computeRest(Token token, bool required) {
-    if (optional('?', token.next)) {
-      beforeQuestionMark = token;
-      end = token = token.next;
-    }
-    token = token.next;
-    while (optional('Function', token)) {
-      Token typeVariableStart = token;
-      // TODO(danrubel): Consider caching TypeParamOrArgInfo
-      token = computeTypeParamOrArg(token, true).skip(token);
-      token = token.next;
-      if (!optional('(', token)) {
-        break; // Not a function type.
-      }
-      token = token.endGroup;
-      if (token == null) {
-        break; // Not a function type.
-      }
-      if (!required) {
-        Token next = token.next;
-        if (optional('?', next)) {
-          next = next.next;
-        }
-        if (!(next.isIdentifier || optional('this', next))) {
-          break; // `Function` used as the name in a function declaration.
-        }
-      }
-      assert(optional(')', token));
-      gftHasReturnType ??= typeVariableStart != start;
-      typeVariableStarters = typeVariableStarters.prepend(typeVariableStart);
-
-      beforeQuestionMark = null;
-      end = token;
-      token = token.next;
-
-      if (optional('?', token)) {
-        beforeQuestionMark = end;
-        end = token;
-        token = token.next;
-      }
-    }
-  }
-}
-
-/// See [noTypeParamOrArg].
-class NoTypeParamOrArg extends TypeParamOrArgInfo {
-  const NoTypeParamOrArg();
-
-  @override
-  int get typeArgumentCount => 0;
-
-  @override
-  Token parseArguments(Token token, Parser parser) {
-    parser.listener.handleNoTypeArguments(token.next);
-    return token;
-  }
-
-  @override
-  Token parseVariables(Token token, Parser parser) {
-    parser.listener.handleNoTypeVariables(token.next);
-    return token;
-  }
-
-  @override
-  Token skip(Token token) => token;
-}
-
-class SimpleTypeArgument1 extends TypeParamOrArgInfo {
-  const SimpleTypeArgument1();
-
-  @override
-  bool get isSimpleTypeArgument => true;
-
-  @override
-  int get typeArgumentCount => 1;
-
-  @override
-  TypeInfo get typeInfo => simpleTypeWith1Argument;
-
-  @override
-  Token parseArguments(Token token, Parser parser) {
-    Token beginGroup = token.next;
-    assert(optional('<', beginGroup));
-    Token endGroup = parseEndGroup(beginGroup, beginGroup.next);
-    Listener listener = parser.listener;
-    listener.beginTypeArguments(beginGroup);
-    simpleType.parseType(beginGroup, parser);
-    parser.listener.endTypeArguments(1, beginGroup, endGroup);
-    return endGroup;
-  }
-
-  @override
-  Token parseVariables(Token token, Parser parser) {
-    Token beginGroup = token.next;
-    assert(optional('<', beginGroup));
-    token = beginGroup.next;
-    Token endGroup = parseEndGroup(beginGroup, token);
-    Listener listener = parser.listener;
-    listener.beginTypeVariables(beginGroup);
-    listener.beginMetadataStar(token);
-    listener.endMetadataStar(0);
-    listener.handleIdentifier(token, IdentifierContext.typeVariableDeclaration);
-    listener.beginTypeVariable(token);
-    listener.handleTypeVariablesDefined(token, 1);
-    listener.handleNoType(token);
-    listener.endTypeVariable(endGroup, 0, null, null);
-    listener.endTypeVariables(beginGroup, endGroup);
-    return endGroup;
-  }
-
-  @override
-  Token skip(Token token) {
-    token = token.next;
-    assert(optional('<', token));
-    token = token.next;
-    assert(token.isKeywordOrIdentifier);
-    return skipEndGroup(token);
-  }
-
-  Token skipEndGroup(Token token) {
-    token = token.next;
-    assert(optional('>', token));
-    return token;
-  }
-
-  Token parseEndGroup(Token beginGroup, Token token) {
-    token = token.next;
-    assert(optional('>', token));
-    return token;
-  }
-}
-
-class SimpleTypeArgument1GtEq extends SimpleTypeArgument1 {
-  const SimpleTypeArgument1GtEq();
-
-  @override
-  TypeInfo get typeInfo => simpleTypeWith1ArgumentGtEq;
-
-  Token skipEndGroup(Token token) {
-    token = token.next;
-    assert(optional('>=', token));
-    return splitGtEq(token);
-  }
-
-  Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
-    Token endGroup = beforeEndGroup.next;
-    if (!optional('>', endGroup)) {
-      endGroup = splitGtEq(endGroup);
-      endGroup.next.setNext(endGroup.next.next);
-    }
-    beforeEndGroup.setNext(endGroup);
-    return endGroup;
-  }
-}
-
-class SimpleTypeArgument1GtGt extends SimpleTypeArgument1 {
-  const SimpleTypeArgument1GtGt();
-
-  @override
-  TypeInfo get typeInfo => simpleTypeWith1ArgumentGtGt;
-
-  Token skipEndGroup(Token token) {
-    token = token.next;
-    assert(optional('>>', token));
-    return splitGtGt(token);
-  }
-
-  Token parseEndGroup(Token beginGroup, Token beforeEndGroup) {
-    Token endGroup = beforeEndGroup.next;
-    if (!optional('>', endGroup)) {
-      endGroup = splitGtGt(endGroup);
-      endGroup.next.setNext(endGroup.next.next);
-    }
-    beforeEndGroup.setNext(endGroup);
-    return endGroup;
-  }
-}
-
-class ComplexTypeParamOrArgInfo extends TypeParamOrArgInfo {
-  /// The first token in the type var.
-  final Token start;
-
-  /// If [inDeclaration] is `true`, then this will more aggressively recover
-  /// given unbalanced `<` `>` and invalid parameters or arguments.
-  final bool inDeclaration;
-
-  // Only support variance parsing if it makes sense.
-  // Allows parsing of variance for certain structures.
-  // See https://github.com/dart-lang/language/issues/524
-  final bool allowsVariance;
-
-  @override
-  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;
-
-  ComplexTypeParamOrArgInfo(
-      Token token, this.inDeclaration, this.allowsVariance)
-      : assert(optional('<', token.next)),
-        assert(inDeclaration != null),
-        assert(allowsVariance != null),
-        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
-  /// stream.
-  TypeParamOrArgInfo compute() {
-    Token token;
-    Token next = start;
-    typeArgumentCount = 0;
-    while (true) {
-      TypeInfo typeInfo = computeType(next, true, inDeclaration);
-      if (typeInfo == noType) {
-        while (typeInfo == noType && optional('@', next.next)) {
-          next = skipMetadata(next);
-          typeInfo = computeType(next, true, inDeclaration);
-        }
-        if (typeInfo == noType) {
-          if (next == start && !inDeclaration && !isCloser(next.next)) {
-            return noTypeParamOrArg;
-          }
-          if (!optional(',', next.next)) {
-            token = next;
-            next = token.next;
-            break;
-          }
-        }
-        assert(typeInfo != noType || optional(',', next.next));
-        // Fall through to process type (if any) and consume `,`
-      }
-      ++typeArgumentCount;
-      token = typeInfo.skipType(next);
-      next = token.next;
-      if (optional('extends', next)) {
-        token = computeType(next, true, inDeclaration).skipType(next);
-        next = token.next;
-      }
-      if (!optional(',', next)) {
-        skipEnd = splitCloser(next);
-        if (skipEnd != null) {
-          return this;
-        }
-        if (!inDeclaration) {
-          return noTypeParamOrArg;
-        }
-
-        // Recovery
-        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
-          break;
-        }
-        // Looks like missing comma. Continue looping.
-        next = token;
-      }
-    }
-
-    // Recovery
-    skipEnd = splitCloser(next);
-    if (skipEnd == null) {
-      if (optional('(', next)) {
-        token = next.endGroup;
-        next = token.next;
-      }
-      skipEnd = splitCloser(next);
-      if (skipEnd == null) {
-        skipEnd = splitCloser(next.next);
-      }
-      if (skipEnd == null) {
-        skipEnd = syntheticGt(next);
-      }
-    }
-    return this;
-  }
-
-  @override
-  Token parseArguments(Token token, Parser parser) {
-    assert(identical(token.next, start));
-    Token next = start;
-    parser.listener.beginTypeArguments(start);
-    int count = 0;
-    while (true) {
-      TypeInfo typeInfo = computeType(next, true, inDeclaration);
-      if (typeInfo == noType) {
-        // Recovery
-        while (typeInfo == noType && optional('@', next.next)) {
-          parser.reportRecoverableErrorWithToken(
-              next.next, fasta.templateUnexpectedToken);
-          next = skipMetadata(next);
-          typeInfo = computeType(next, true, inDeclaration);
-        }
-        // Fall through to process type (if any) and consume `,`
-      }
-      token = typeInfo.ensureTypeOrVoid(next, parser);
-      next = token.next;
-      ++count;
-      if (!optional(',', next)) {
-        if (parseCloser(token)) {
-          break;
-        }
-
-        // Recovery
-        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
-          token = parseUnexpectedEnd(token, true, parser);
-          break;
-        }
-        // Missing comma. Report error, insert comma, and continue looping.
-        next = parseMissingComma(token, parser);
-      }
-    }
-    Token endGroup = token.next;
-    parser.listener.endTypeArguments(count, start, endGroup);
-    return endGroup;
-  }
-
-  @override
-  Token parseVariables(Token token, Parser parser) {
-    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>();
-
-    while (true) {
-      token = parser.parseMetadataStar(next);
-
-      Token variance = next.next;
-      Token identifier = variance.next;
-      if (allowsVariance &&
-          isVariance(variance) &&
-          identifier != null &&
-          identifier.isKeywordOrIdentifier) {
-        variances = variances.prepend(variance);
-
-        // Recovery for multiple variance modifiers
-        while (isVariance(identifier) &&
-            identifier.next != null &&
-            identifier.next.isKeywordOrIdentifier) {
-          // Report an error and skip actual identifier
-          parser.reportRecoverableError(
-              identifier, fasta.messageMultipleVarianceModifiers);
-          variance = variance.next;
-          identifier = identifier.next;
-        }
-
-        token = variance;
-      } else {
-        variances = variances.prepend(null);
-      }
-
-      next = parser.ensureIdentifier(
-          token, IdentifierContext.typeVariableDeclaration);
-      token = next;
-      listener.beginTypeVariable(token);
-      typeStarts = typeStarts.prepend(token);
-
-      next = token.next;
-      if (optional('extends', next)) {
-        TypeInfo typeInfo = computeType(next, true, inDeclaration);
-        token = typeInfo.skipType(next);
-        next = token.next;
-        superTypeInfos = superTypeInfos.prepend(typeInfo);
-      } else {
-        superTypeInfos = superTypeInfos.prepend(null);
-      }
-
-      ++count;
-      if (!optional(',', next)) {
-        if (isCloser(token)) {
-          break;
-        }
-
-        // Recovery
-        if (!looksLikeTypeParamOrArg(inDeclaration, next)) {
-          break;
-        }
-        // Missing comma. Report error, insert comma, and continue looping.
-        next = parseMissingComma(token, parser);
-      }
-    }
-
-    assert(count > 0);
-    assert(typeStarts.slowLength() == count);
-    assert(superTypeInfos.slowLength() == count);
-    assert(variances.slowLength() == count);
-    listener.handleTypeVariablesDefined(token, count);
-
-    token = null;
-    while (typeStarts.isNotEmpty) {
-      Token token2 = typeStarts.head;
-      TypeInfo typeInfo = superTypeInfos.head;
-      Token variance = variances.head;
-
-      Token extendsOrSuper = null;
-      Token next2 = token2.next;
-      if (typeInfo != null) {
-        assert(optional('extends', next2));
-        extendsOrSuper = next2;
-        token2 = typeInfo.ensureTypeNotVoid(next2, parser);
-        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;
-      listener.endTypeVariable(next2, --count, extendsOrSuper, variance);
-
-      typeStarts = typeStarts.tail;
-      superTypeInfos = superTypeInfos.tail;
-      variances = variances.tail;
-    }
-
-    if (!parseCloser(token)) {
-      token = parseUnexpectedEnd(token, false, parser);
-    }
-    Token endGroup = token.next;
-    listener.endTypeVariables(start, endGroup);
-    return endGroup;
-  }
-
-  Token parseMissingComma(Token token, Parser parser) {
-    Token next = token.next;
-    parser.reportRecoverableError(
-        next, fasta.templateExpectedButGot.withArguments(','));
-    return parser.rewriter.insertToken(
-        token, new SyntheticToken(TokenType.COMMA, next.charOffset));
-  }
-
-  Token parseUnexpectedEnd(Token token, bool isArguments, Parser parser) {
-    Token next = token.next;
-    bool errorReported = token.isSynthetic || (next.isSynthetic && !next.isEof);
-
-    bool typeFollowsExtends = false;
-    if (optional('extends', next)) {
-      if (!errorReported) {
-        parser.reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments('>'));
-        errorReported = true;
-      }
-      token = next;
-      next = token.next;
-      typeFollowsExtends = isValidTypeReference(next);
-
-      if (parseCloser(token)) {
-        return token;
-      }
-    }
-
-    if (typeFollowsExtends ||
-        optional('dynamic', next) ||
-        optional('void', next) ||
-        optional('Function', next)) {
-      TypeInfo invalidType = computeType(token, true);
-      if (invalidType != noType) {
-        if (!errorReported) {
-          parser.reportRecoverableError(
-              token, fasta.templateExpectedAfterButGot.withArguments('>'));
-          errorReported = true;
-        }
-
-        // Parse the type so that the token stream is properly modified,
-        // but ensure that parser events are ignored by replacing the listener.
-        final Listener originalListener = parser.listener;
-        parser.listener = new ForwardingListener();
-        token = invalidType.parseType(token, parser);
-        next = token.next;
-        parser.listener = originalListener;
-
-        if (parseCloser(token)) {
-          return token;
-        }
-      }
-    }
-
-    TypeParamOrArgInfo invalidTypeVar =
-        computeTypeParamOrArg(token, inDeclaration);
-    if (invalidTypeVar != noTypeParamOrArg) {
-      if (!errorReported) {
-        parser.reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments('>'));
-        errorReported = true;
-      }
-
-      // Parse the type so that the token stream is properly modified,
-      // but ensure that parser events are ignored by replacing the listener.
-      final Listener originalListener = parser.listener;
-      parser.listener = new ForwardingListener();
-      token = isArguments
-          ? invalidTypeVar.parseArguments(token, parser)
-          : invalidTypeVar.parseVariables(token, parser);
-      next = token.next;
-      parser.listener = originalListener;
-
-      if (parseCloser(token)) {
-        return token;
-      }
-    }
-
-    if (optional('(', next) && next.endGroup != null) {
-      if (!errorReported) {
-        // Only report an error if one has not already been reported.
-        parser.reportRecoverableError(
-            token, fasta.templateExpectedAfterButGot.withArguments('>'));
-        errorReported = true;
-      }
-      token = next.endGroup;
-      next = token.next;
-
-      if (parseCloser(token)) {
-        return token;
-      }
-    }
-
-    if (!errorReported) {
-      // Only report an error if one has not already been reported.
-      parser.reportRecoverableError(
-          token, fasta.templateExpectedAfterButGot.withArguments('>'));
-    }
-    if (parseCloser(next)) {
-      return next;
-    }
-    Token endGroup = start.endGroup;
-    if (endGroup != null) {
-      while (token.next != endGroup && !token.isEof) {
-        token = token.next;
-      }
-    } else {
-      endGroup = syntheticGt(next);
-      endGroup.setNext(next);
-      token.setNext(endGroup);
-    }
-    return token;
-  }
-
-  @override
-  Token skip(Token token) {
-    assert(skipEnd != null);
-    return skipEnd;
-  }
-}
-
-// Return `true` if [token] is one of `in`, `inout`, or `out`
-bool isVariance(Token token) {
-  return optional('in', token) ||
-      optional('inout', token) ||
-      optional('out', token);
-}
-
-/// Return `true` if [token] is one of `>`, `>>`, `>>>`, `>=`, `>>=`, or `>>>=`.
-bool isCloser(Token token) {
-  final String value = token.stringValue;
-  return identical(value, '>') ||
-      identical(value, '>>') ||
-      identical(value, '>=') ||
-      identical(value, '>>>') ||
-      identical(value, '>>=') ||
-      identical(value, '>>>=');
-}
-
-/// 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);
-  if (split == unsplit) {
-    return true;
-  } else if (split == null) {
-    return false;
-  }
-  split.next.setNext(unsplit.next);
-  beforeCloser.setNext(split);
-  return true;
-}
-
-/// If [closer] is `>` then return it.
-/// 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;
-  if (identical(value, '>')) {
-    return closer;
-  } else if (identical(value, '>>')) {
-    return splitGtGt(closer);
-  } else if (identical(value, '>=')) {
-    return splitGtEq(closer);
-  } else if (identical(value, '>>>')) {
-    return splitGtFromGtGtGt(closer);
-  } else if (identical(value, '>>=')) {
-    return splitGtFromGtGtEq(closer);
-  } else if (identical(value, '>>>=')) {
-    return splitGtFromGtGtGtEq(closer);
-  }
-  return null;
-}
diff --git a/pkg/front_end/lib/src/fasta/parser/util.dart b/pkg/front_end/lib/src/fasta/parser/util.dart
deleted file mode 100644
index 2e7b441..0000000
--- a/pkg/front_end/lib/src/fasta/parser/util.dart
+++ /dev/null
@@ -1,212 +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.
-
-library fasta.parser.util;
-
-import 'package:kernel/ast.dart' show TreeNode;
-
-import '../fasta_codes.dart' show noLength;
-
-import '../scanner.dart' show Token;
-
-import '../../scanner/token.dart'
-    show BeginToken, SimpleToken, SyntheticToken, TokenType;
-
-/// Returns true if [token] is the symbol or keyword [value].
-bool optional(String value, Token token) {
-  return identical(value, token.stringValue);
-}
-
-/// 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;
-  if (endToken == null) {
-    return null;
-  }
-  Token token = left;
-  Token next = token.next;
-  while (next != endToken && next != next.next) {
-    token = next;
-    next = token.next;
-  }
-  return token;
-}
-
-/// Return [token] or a token before [token] which is either
-/// not synthetic or synthetic with non-zero length.
-Token findPreviousNonZeroLengthToken(Token token) {
-  while (token.isSynthetic && token.length == 0) {
-    Token previous = token.beforeSynthetic;
-    if (previous == null) {
-      break;
-    }
-    token = previous;
-  }
-  return token;
-}
-
-/// Return [token] or a token after [token] which is either
-/// not synthetic or synthetic with non-zero length.
-/// 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;
-  }
-  return token;
-}
-
-/// A null-aware alternative to `token.offset`.  If [token] is `null`, returns
-/// `TreeNode.noOffset`.
-int offsetForToken(Token token) {
-  return token == null ? TreeNode.noOffset : token.offset;
-}
-
-bool isDigit(int c) => c >= 0x30 && c <= 0x39;
-
-bool isLetter(int c) => c >= 0x41 && c <= 0x5A || c >= 0x61 && c <= 0x7A;
-
-bool isLetterOrDigit(int c) => isLetter(c) || isDigit(c);
-
-bool isWhitespace(int c) => c == 0x20 || c == 0xA || c == 0xD || c == 0x9;
-
-/// Return true if the given token matches one of the given values.
-bool isOneOf(Token token, Iterable<String> values) {
-  for (String tokenValue in values) {
-    if (optional(tokenValue, token)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-/// Return true if the given token matches one of the given values or is EOF.
-bool isOneOfOrEof(Token token, Iterable<String> values) {
-  for (String tokenValue in values) {
-    if (optional(tokenValue, token)) {
-      return true;
-    }
-  }
-  return token.isEof;
-}
-
-/// A null-aware alternative to `token.length`.  If [token] is `null`, returns
-/// [noLength].
-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) {
-  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;
-  assert(optional('@', token));
-  Token next = token.next;
-  if (next.isIdentifier) {
-    token = next;
-    next = token.next;
-    while (optional('.', next)) {
-      token = next;
-      next = token.next;
-      if (next.isIdentifier) {
-        token = next;
-        next = token.next;
-      }
-    }
-    if (optional('(', next) && !next.endGroup.isSynthetic) {
-      token = next.endGroup;
-      next = token.next;
-    }
-  }
-  return token;
-}
-
-/// Split `>=` into two separate tokens.
-/// Call [Token.setNext] to add the token to the stream.
-Token splitGtEq(Token token) {
-  assert(optional('>=', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.EQ, token.charOffset + 1)
-      // Set next rather than calling Token.setNext
-      // so that the previous token is not set.
-      ..next = token.next);
-}
-
-/// Split `>>` into two separate tokens.
-/// Call [Token.setNext] to add the token to the stream.
-SimpleToken splitGtGt(Token token) {
-  assert(optional('>>', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.GT, token.charOffset + 1)
-      // Set next rather than calling Token.setNext
-      // so that the previous token is not set.
-      ..next = token.next);
-}
-
-/// Split `>>=` into three separate tokens.
-/// Call [Token.setNext] to add the token to the stream.
-Token splitGtGtEq(Token token) {
-  assert(optional('>>=', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.GT, token.charOffset + 1)
-      ..setNext(new SimpleToken(TokenType.EQ, token.charOffset + 2)
-        // Set next rather than calling Token.setNext
-        // so that the previous token is not set.
-        ..next = token.next));
-}
-
-/// Split `>>=` into two separate tokens... `>` followed by `>=`.
-/// Call [Token.setNext] to add the token to the stream.
-Token splitGtFromGtGtEq(Token token) {
-  assert(optional('>>=', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.GT_EQ, token.charOffset + 1)
-      // Set next rather than calling Token.setNext
-      // so that the previous token is not set.
-      ..next = token.next);
-}
-
-/// Split `>>>` into two separate tokens... `>` followed by `>>`.
-/// Call [Token.setNext] to add the token to the stream.
-Token splitGtFromGtGtGt(Token token) {
-  assert(optional('>>>', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.GT_GT, token.charOffset + 1)
-      // Set next rather than calling Token.setNext
-      // so that the previous token is not set.
-      ..next = token.next);
-}
-
-/// Split `>>>=` into two separate tokens... `>` followed by `>>=`.
-/// Call [Token.setNext] to add the token to the stream.
-Token splitGtFromGtGtGtEq(Token token) {
-  assert(optional('>>>=', token));
-  return new SimpleToken(
-      TokenType.GT, token.charOffset, token.precedingComments)
-    ..setNext(new SimpleToken(TokenType.GT_GT_EQ, token.charOffset + 1)
-      // Set next rather than calling Token.setNext
-      // so that the previous token is not set.
-      ..next = token.next);
-}
-
-/// Return a synthetic `<` followed by [next].
-/// Call [Token.setNext] to add the token to the stream.
-Token syntheticGt(Token next) {
-  return new SyntheticToken(TokenType.GT, next.charOffset)
-    // Set next rather than calling Token.setNext
-    // so that the previous token is not set.
-    ..next = next;
-}
diff --git a/pkg/front_end/lib/src/fasta/problems.dart b/pkg/front_end/lib/src/fasta/problems.dart
index 09ec70c..f1d61a2 100644
--- a/pkg/front_end/lib/src/fasta/problems.dart
+++ b/pkg/front_end/lib/src/fasta/problems.dart
@@ -4,6 +4,9 @@
 
 library fasta.problems;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart'
+    show Severity, severityTexts;
+
 import 'package:kernel/ast.dart' show FileUriNode, TreeNode;
 
 import 'compiler_context.dart' show CompilerContext;
@@ -19,8 +22,6 @@
         templateInternalProblemUnimplemented,
         templateInternalProblemUnsupported;
 
-import 'severity.dart' show Severity, severityTexts;
-
 class DebugAbort {
   final LocatedMessage message;
 
diff --git a/pkg/front_end/lib/src/fasta/quote.dart b/pkg/front_end/lib/src/fasta/quote.dart
index c145b5c..71ace2d 100644
--- a/pkg/front_end/lib/src/fasta/quote.dart
+++ b/pkg/front_end/lib/src/fasta/quote.dart
@@ -4,11 +4,10 @@
 
 library fasta.quote;
 
-import 'problems.dart' show unhandled;
+import 'package:_fe_analyzer_shared/src/parser/listener.dart'
+    show UnescapeErrorListener;
 
-import 'fasta_codes.dart' as fasta;
-
-import 'scanner/characters.dart'
+import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
     show
         $BACKSLASH,
         $BS,
@@ -31,6 +30,10 @@
         hexDigitValue,
         isHexDigit;
 
+import 'problems.dart' show unhandled;
+
+import 'fasta_codes.dart' as fasta;
+
 enum Quote {
   Single,
   Double,
@@ -136,12 +139,14 @@
 String unescapeString(
     String string, Object location, UnescapeErrorListener listener) {
   Quote quote = analyzeQuote(string);
+  int startIndex = firstQuoteLength(string, quote);
+  int endIndex = string.length - lastQuoteLength(quote);
+  if (startIndex > endIndex) {
+    // An error has already been signaled.
+    return "";
+  }
   return unescape(
-      string.substring(firstQuoteLength(string, quote),
-          string.length - lastQuoteLength(quote)),
-      quote,
-      location,
-      listener);
+      string.substring(startIndex, endIndex), quote, location, listener);
 }
 
 String unescape(String string, Quote quote, Object location,
@@ -295,8 +300,3 @@
   }
   return new String.fromCharCodes(result, 0, resultOffset);
 }
-
-abstract class UnescapeErrorListener {
-  void handleUnescapeError(
-      fasta.Message message, covariant location, int offset, int length);
-}
diff --git a/pkg/front_end/lib/src/fasta/resolve_input_uri.dart b/pkg/front_end/lib/src/fasta/resolve_input_uri.dart
index 0dd3a17..6f0dba3 100644
--- a/pkg/front_end/lib/src/fasta/resolve_input_uri.dart
+++ b/pkg/front_end/lib/src/fasta/resolve_input_uri.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.
 
-/// Detect if we're on Windows without importing `dart:io`.
-bool isWindows = new Uri.directory("C:\\").path ==
-    new Uri.directory("C:\\", windows: true).path;
+import 'package:_fe_analyzer_shared/src/util/relativize.dart';
 
 Uri resolveInputUri(String path) {
   Uri uri;
diff --git a/pkg/front_end/lib/src/fasta/rewrite_severity.dart b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
index 6f6edf5..5fd9ae8 100644
--- a/pkg/front_end/lib/src/fasta/rewrite_severity.dart
+++ b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'severity.dart' show Severity;
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 import 'messages.dart' as msg;
 
diff --git a/pkg/front_end/lib/src/fasta/scanner.dart b/pkg/front_end/lib/src/fasta/scanner.dart
deleted file mode 100644
index 2a1e410..0000000
--- a/pkg/front_end/lib/src/fasta/scanner.dart
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.md file.
-
-library fasta.scanner;
-
-import 'dart:convert' show unicodeReplacementCharacterRune, utf8;
-
-import '../scanner/token.dart' show Token;
-
-import 'scanner/abstract_scanner.dart'
-    show LanguageVersionChanged, ScannerConfiguration;
-
-import 'scanner/string_scanner.dart' show StringScanner;
-
-import 'scanner/utf8_bytes_scanner.dart' show Utf8BytesScanner;
-
-import 'scanner/recover.dart' show scannerRecovery;
-
-export 'scanner/abstract_scanner.dart'
-    show LanguageVersionChanged, ScannerConfiguration;
-
-export 'scanner/token.dart'
-    show
-        LanguageVersionToken,
-        StringToken,
-        isBinaryOperator,
-        isMinusOperator,
-        isTernaryOperator,
-        isUnaryOperator,
-        isUserDefinableOperator;
-
-export 'scanner/error_token.dart'
-    show ErrorToken, buildUnexpectedCharacterToken;
-
-export 'scanner/token.dart' show LanguageVersionToken;
-
-export 'scanner/token_constants.dart' show EOF_TOKEN;
-
-export 'scanner/utf8_bytes_scanner.dart' show Utf8BytesScanner;
-
-export 'scanner/string_scanner.dart' show StringScanner;
-
-export '../scanner/token.dart' show Keyword, Token;
-
-const int unicodeReplacementCharacter = unicodeReplacementCharacterRune;
-
-typedef Token Recover(List<int> bytes, Token tokens, List<int> lineStarts);
-
-abstract class Scanner {
-  /// Returns true if an error occurred during [tokenize].
-  bool get hasErrors;
-
-  List<int> get lineStarts;
-
-  /// Configure which tokens are produced.
-  set configuration(ScannerConfiguration config);
-
-  Token tokenize();
-}
-
-class ScannerResult {
-  final Token tokens;
-  final List<int> lineStarts;
-  final bool hasErrors;
-
-  ScannerResult(this.tokens, this.lineStarts, this.hasErrors);
-}
-
-/// Scan/tokenize the given UTF8 [bytes].
-ScannerResult scan(List<int> bytes,
-    {ScannerConfiguration configuration,
-    bool includeComments: false,
-    LanguageVersionChanged languageVersionChanged}) {
-  if (bytes.last != 0) {
-    throw new ArgumentError("[bytes]: the last byte must be null.");
-  }
-  Scanner scanner = new Utf8BytesScanner(bytes,
-      configuration: configuration,
-      includeComments: includeComments,
-      languageVersionChanged: languageVersionChanged);
-  return _tokenizeAndRecover(scanner, bytes: bytes);
-}
-
-/// Scan/tokenize the given [source].
-ScannerResult scanString(String source,
-    {ScannerConfiguration configuration,
-    bool includeComments: false,
-    LanguageVersionChanged languageVersionChanged}) {
-  assert(source != null, 'source must not be null');
-  StringScanner scanner = new StringScanner(source,
-      configuration: configuration,
-      includeComments: includeComments,
-      languageVersionChanged: languageVersionChanged);
-  return _tokenizeAndRecover(scanner, source: source);
-}
-
-ScannerResult _tokenizeAndRecover(Scanner scanner,
-    {List<int> bytes, String source}) {
-  Token tokens = scanner.tokenize();
-  if (scanner.hasErrors) {
-    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/front_end/lib/src/fasta/scanner/abstract_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
deleted file mode 100644
index e34362d..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/abstract_scanner.dart
+++ /dev/null
@@ -1,1925 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.scanner.abstract_scanner;
-
-import 'dart:collection' show ListMixin;
-
-import 'dart:typed_data' show Uint16List, Uint32List;
-
-import '../../scanner/token.dart'
-    show BeginToken, Keyword, KeywordToken, SyntheticToken, Token, TokenType;
-
-import '../../scanner/token.dart' as analyzer show StringToken;
-
-import '../fasta_codes.dart'
-    show
-        messageExpectedHexDigit,
-        messageMissingExponent,
-        messageUnexpectedDollarInString,
-        messageUnterminatedComment;
-
-import '../scanner.dart'
-    show ErrorToken, Keyword, Scanner, buildUnexpectedCharacterToken;
-
-import '../util/link.dart' show Link;
-
-import 'error_token.dart'
-    show
-        NonAsciiIdentifierToken,
-        UnmatchedToken,
-        UnsupportedOperator,
-        UnterminatedString,
-        UnterminatedToken;
-
-import 'keyword_state.dart' show KeywordState;
-
-import 'token.dart'
-    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
-
-import 'token_constants.dart';
-
-import 'characters.dart';
-
-typedef void LanguageVersionChanged(
-    Scanner scanner, LanguageVersionToken languageVersion);
-
-abstract class AbstractScanner implements Scanner {
-  /**
-   * A flag indicating whether character sequences `&&=` and `||=`
-   * should be tokenized as the assignment operators
-   * [AMPERSAND_AMPERSAND_EQ_TOKEN] and [BAR_BAR_EQ_TOKEN] respectively.
-   * See issue https://github.com/dart-lang/sdk/issues/30340
-   */
-  static const bool LAZY_ASSIGNMENT_ENABLED = false;
-
-  final bool includeComments;
-
-  /// 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;
-
-  /// Experimental flag for enabling scanning of the `extension` token.
-  bool _enableExtensionMethods = false;
-
-  /// Experimental flag for enabling scanning of NNBD tokens
-  /// such as 'required' and 'late'.
-  bool _enableNonNullable = false;
-
-  /// Experimental flag for enabling scanning of `>>>`.
-  /// See https://github.com/dart-lang/language/issues/61
-  /// and https://github.com/dart-lang/language/issues/60
-  bool _enableTripleShift = false;
-
-  /**
-   * The string offset for the next token that will be created.
-   *
-   * Note that in the [Utf8BytesScanner], [stringOffset] and [scanOffset] values
-   * are different. One string character can be encoded using multiple UTF-8
-   * bytes.
-   */
-  int tokenStart = -1;
-
-  /**
-   * A pointer to the token stream created by this scanner. The first token
-   * is a special token and not part of the source file. This is an
-   * implementation detail to avoids special cases in the scanner. This token
-   * is not exposed to clients of the scanner, which are expected to invoke
-   * [firstToken] to access the token stream.
-   */
-  final Token tokens = new Token.eof(-1);
-
-  /**
-   * A pointer to the last scanned token.
-   */
-  Token tail;
-
-  /**
-   * A pointer to the last prepended error token.
-   */
-  Token errorTail;
-
-  bool hasErrors = false;
-
-  /**
-   * A pointer to the stream of comment tokens created by this scanner
-   * before they are assigned to the [Token] precedingComments field
-   * of a non-comment token. A value of `null` indicates no comment tokens.
-   */
-  CommentToken comments;
-
-  /**
-   * A pointer to the last scanned comment token or `null` if none.
-   */
-  Token commentsTail;
-
-  final List<int> lineStarts;
-
-  /**
-   * The stack of open groups, e.g [: { ... ( .. :]
-   * Each BeginToken has a pointer to the token where the group
-   * ends. This field is set when scanning the end group token.
-   */
-  Link<BeginToken> groupingStack = const Link<BeginToken>();
-
-  AbstractScanner(ScannerConfiguration config, this.includeComments,
-      this.languageVersionChanged,
-      {int numberOfBytesHint})
-      : lineStarts = new LineStarts(numberOfBytesHint) {
-    this.tail = this.tokens;
-    this.errorTail = this.tokens;
-    this.configuration = config;
-  }
-
-  @override
-  set configuration(ScannerConfiguration config) {
-    if (config != null) {
-      _enableExtensionMethods = config.enableExtensionMethods;
-      _enableNonNullable = config.enableNonNullable;
-      _enableTripleShift = config.enableTripleShift;
-    }
-  }
-
-  /**
-   * Advances and returns the next character.
-   *
-   * If the next character is non-ASCII, then the returned value depends on the
-   * scanner implementation. The [Utf8BytesScanner] returns a UTF-8 byte, while
-   * the [StringScanner] returns a UTF-16 code unit.
-   *
-   * The scanner ensures that [advance] is not invoked after it returned [$EOF].
-   * This allows implementations to omit bound checks if the data structure ends
-   * with '0'.
-   */
-  int advance();
-
-  /**
-   * Returns the current unicode character.
-   *
-   * If the current character is ASCII, then it is returned unchanged.
-   *
-   * The [Utf8BytesScanner] decodes the next unicode code point starting at the
-   * current position. Note that every unicode character is returned as a single
-   * code point, that is, for '\u{1d11e}' it returns 119070, and the following
-   * [advance] returns the next character.
-   *
-   * The [StringScanner] returns the current character unchanged, which might
-   * be a surrogate character. In the case of '\u{1d11e}', it returns the first
-   * code unit 55348, and the following [advance] returns the second code unit
-   * 56606.
-   *
-   * Invoking [currentAsUnicode] multiple times is safe, i.e.,
-   * [:currentAsUnicode(next) == currentAsUnicode(currentAsUnicode(next)):].
-   */
-  int currentAsUnicode(int next);
-
-  /**
-   * Returns the character at the next position. Like in [advance], the
-   * [Utf8BytesScanner] returns a UTF-8 byte, while the [StringScanner] returns
-   * a UTF-16 code unit.
-   */
-  int peek();
-
-  /**
-   * Notifies the scanner that unicode characters were detected in either a
-   * comment or a string literal between [startScanOffset] and the current
-   * scan offset.
-   */
-  void handleUnicode(int startScanOffset);
-
-  /**
-   * Returns the current scan offset.
-   *
-   * In the [Utf8BytesScanner] this is the offset into the byte list, in the
-   * [StringScanner] the offset in the source string.
-   */
-  int get scanOffset;
-
-  /**
-   * Returns the current string offset.
-   *
-   * In the [StringScanner] this is identical to the [scanOffset]. In the
-   * [Utf8BytesScanner] it is computed based on encountered UTF-8 characters.
-   */
-  int get stringOffset;
-
-  /**
-   * Returns the first token scanned by this [Scanner].
-   */
-  Token firstToken() => tokens.next;
-
-  /**
-   * Notifies that a new token starts at current offset.
-   */
-  void beginToken() {
-    tokenStart = stringOffset;
-  }
-
-  /**
-   * Appends a substring from the scan offset [:start:] to the current
-   * [:scanOffset:] plus the [:extraOffset:]. For example, if the current
-   * scanOffset is 10, then [:appendSubstringToken(5, -1):] will append the
-   * substring string [5,9).
-   *
-   * Note that [extraOffset] can only be used if the covered character(s) are
-   * known to be ASCII.
-   */
-  void appendSubstringToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    appendToken(createSubstringToken(type, start, asciiOnly, extraOffset));
-  }
-
-  /**
-   * Returns a new substring from the scan offset [start] to the current
-   * [scanOffset] plus the [extraOffset]. For example, if the current
-   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
-   * substring string [5,9).
-   *
-   * Note that [extraOffset] can only be used if the covered character(s) are
-   * known to be ASCII.
-   */
-  analyzer.StringToken createSubstringToken(
-      TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]);
-
-  /**
-   * Appends a substring from the scan offset [start] to the current
-   * [scanOffset] plus [syntheticChars]. The additional char(s) will be added
-   * to the unterminated string literal's lexeme but the returned
-   * token's length will *not* include those additional char(s)
-   * so as to be true to the original source.
-   */
-  void appendSyntheticSubstringToken(
-      TokenType type, int start, bool asciiOnly, String syntheticChars) {
-    appendToken(
-        createSyntheticSubstringToken(type, start, asciiOnly, syntheticChars));
-  }
-
-  /**
-   * Returns a new synthetic substring from the scan offset [start]
-   * to the current [scanOffset] plus the [syntheticChars].
-   * The [syntheticChars] are appended to the unterminated string
-   * literal's lexeme but the returned token's length will *not* include
-   * those additional characters so as to be true to the original source.
-   */
-  analyzer.StringToken createSyntheticSubstringToken(
-      TokenType type, int start, bool asciiOnly, String syntheticChars);
-  /**
-   * Appends a fixed token whose kind and content is determined by [type].
-   * Appends an *operator* token from [type].
-   *
-   * An operator token represent operators like ':', '.', ';', '&&', '==', '--',
-   * '=>', etc.
-   */
-  void appendPrecedenceToken(TokenType type) {
-    appendToken(new Token(type, tokenStart, comments));
-  }
-
-  /**
-   * Appends a fixed token based on whether the current char is [choice] or not.
-   * If the current char is [choice] a fixed token whose kind and content
-   * is determined by [yes] is appended, otherwise a fixed token whose kind
-   * and content is determined by [no] is appended.
-   */
-  int select(int choice, TokenType yes, TokenType no) {
-    int next = advance();
-    if (identical(next, choice)) {
-      appendPrecedenceToken(yes);
-      return advance();
-    } else {
-      appendPrecedenceToken(no);
-      return next;
-    }
-  }
-
-  /**
-   * Appends a keyword token whose kind is determined by [keyword].
-   */
-  void appendKeywordToken(Keyword keyword) {
-    String syntax = keyword.lexeme;
-    // Type parameters and arguments cannot contain 'this'.
-    if (identical(syntax, 'this')) {
-      discardOpenLt();
-    }
-    appendToken(new KeywordToken(keyword, tokenStart, comments));
-  }
-
-  void appendEofToken() {
-    beginToken();
-    discardOpenLt();
-    while (!groupingStack.isEmpty) {
-      unmatchedBeginGroup(groupingStack.head);
-      groupingStack = groupingStack.tail;
-    }
-    appendToken(new Token.eof(tokenStart, comments));
-  }
-
-  /**
-   * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is
-   * not always invoked for [$SPACE] characters.
-   *
-   * This method is used by the scanners to track line breaks and create the
-   * [lineStarts] map.
-   */
-  void appendWhiteSpace(int next) {
-    if (next == $LF) {
-      lineStarts.add(stringOffset + 1); // +1, the line starts after the $LF.
-    }
-  }
-
-  /**
-   * Notifies on [$LF] characters in multi-line comments or strings.
-   *
-   * This method is used by the scanners to track line breaks and create the
-   * [lineStarts] map.
-   */
-  void lineFeedInMultiline() {
-    lineStarts.add(stringOffset + 1);
-  }
-
-  /**
-   * Appends a token that begins a new group, represented by [type].
-   * Group begin tokens are '{', '(', '[', '<' and '${'.
-   */
-  void appendBeginGroup(TokenType type) {
-    Token token = new BeginToken(type, tokenStart, comments);
-    appendToken(token);
-
-    // { [ ${ cannot appear inside a type parameters / arguments.
-    if (!identical(type.kind, LT_TOKEN) &&
-        !identical(type.kind, OPEN_PAREN_TOKEN)) {
-      discardOpenLt();
-    }
-    groupingStack = groupingStack.prepend(token);
-  }
-
-  /**
-   * Appends a token that begins an end group, represented by [type].
-   * It handles the group end tokens '}', ')' and ']'. The tokens '>' and
-   * '>>' are handled separately by [appendGt] and [appendGtGt].
-   */
-  int appendEndGroup(TokenType type, int openKind) {
-    assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
-    if (!discardBeginGroupUntil(openKind)) {
-      // No begin group found. Just continue.
-      appendPrecedenceToken(type);
-      return advance();
-    }
-    appendPrecedenceToken(type);
-    Token close = tail;
-    BeginToken begin = groupingStack.head;
-    if (!identical(begin.kind, openKind) &&
-        !(begin.kind == QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN &&
-            openKind == OPEN_SQUARE_BRACKET_TOKEN)) {
-      assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
-          openKind == OPEN_CURLY_BRACKET_TOKEN);
-      // We're ending an interpolated expression.
-      begin.endGroup = close;
-      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;
-    return advance();
-  }
-
-  /**
-   * Appends a token for '>'.
-   * This method does not issue unmatched errors, because > is also the
-   * greater-than operator. It does not necessarily have to close a group.
-   */
-  void appendGt(TokenType type) {
-    appendPrecedenceToken(type);
-    if (groupingStack.isEmpty) return;
-    if (identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack.head.endGroup = tail;
-      groupingStack = groupingStack.tail;
-    }
-  }
-
-  /**
-   * Appends a token for '>>'.
-   * This method does not issue unmatched errors, because >> is also the
-   * shift operator. It does not necessarily have to close a group.
-   */
-  void appendGtGt(TokenType type) {
-    appendPrecedenceToken(type);
-    if (groupingStack.isEmpty) return;
-    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;
-    }
-    if (groupingStack.isEmpty) return;
-    if (identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack.head.endGroup = tail;
-      groupingStack = groupingStack.tail;
-    }
-  }
-
-  /// Prepend [token] to the token stream.
-  void prependErrorToken(ErrorToken token) {
-    hasErrors = true;
-    if (errorTail == tail) {
-      appendToken(token);
-      errorTail = tail;
-    } else {
-      token.next = errorTail.next;
-      token.next.previous = token;
-      errorTail.next = token;
-      token.previous = errorTail;
-      errorTail = errorTail.next;
-    }
-  }
-
-  /**
-   * Returns a new comment from the scan offset [start] to the current
-   * [scanOffset] plus the [extraOffset]. For example, if the current
-   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
-   * substring string [5,9).
-   *
-   * Note that [extraOffset] can only be used if the covered character(s) are
-   * known to be ASCII.
-   */
-  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]);
-
-  /**
-   * Returns a new dartdoc from the scan offset [start] to the current
-   * [scanOffset] plus the [extraOffset]. For example, if the current
-   * scanOffset is 10, then [appendSubstringToken(5, -1)] will append the
-   * substring string [5,9).
-   *
-   * Note that [extraOffset] can only be used if the covered character(s) are
-   * known to be ASCII.
-   */
-  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]);
-
-  /**
-   * Returns a new language version token from the scan offset [start]
-   * to the current [scanOffset] similar to createCommentToken.
-   */
-  LanguageVersionToken createLanguageVersionToken(
-      int start, int major, int minor);
-
-  /**
-   * If a begin group token matches [openKind],
-   * then discard begin group tokens up to that match and return `true`,
-   * otherwise return `false`.
-   * This recovers nicely from from situations like "{[}" and "{foo());}",
-   * but not "foo(() {bar());});
-   */
-  bool discardBeginGroupUntil(int openKind) {
-    Link<BeginToken> originalStack = groupingStack;
-
-    bool first = true;
-    do {
-      // Don't report unmatched errors for <; it is also the less-than operator.
-      discardOpenLt();
-      if (groupingStack.isEmpty) break; // recover
-      BeginToken begin = groupingStack.head;
-      if (openKind == begin.kind ||
-          (openKind == OPEN_CURLY_BRACKET_TOKEN &&
-              begin.kind == STRING_INTERPOLATION_TOKEN) ||
-          (openKind == OPEN_SQUARE_BRACKET_TOKEN &&
-              begin.kind == QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN)) {
-        if (first) {
-          // If the expected opener has been found on the first pass
-          // then no recovery necessary.
-          return true;
-        }
-        break; // recover
-      }
-      first = false;
-      groupingStack = groupingStack.tail;
-    } while (!groupingStack.isEmpty);
-
-    // If the stack does not have any opener of the given type,
-    // then return without discarding anything.
-    // This recovers nicely from from situations like "{foo());}".
-    if (groupingStack.isEmpty) {
-      groupingStack = originalStack;
-      return false;
-    }
-
-    // Insert synthetic closers and report errors for any unbalanced openers.
-    // This recovers nicely from from situations like "{[}".
-    while (!identical(originalStack, groupingStack)) {
-      // Don't report unmatched errors for <; it is also the less-than operator.
-      if (!identical(groupingStack.head.kind, LT_TOKEN)) {
-        unmatchedBeginGroup(originalStack.head);
-      }
-      originalStack = originalStack.tail;
-    }
-    return true;
-  }
-
-  /**
-   * This method is called to discard '<' from the "grouping" stack.
-   *
-   * [PartialParser.skipExpression] relies on the fact that we do not
-   * create groups for stuff like:
-   * [:a = b < c, d = e > f:].
-   *
-   * In other words, this method is called when the scanner recognizes
-   * something which cannot possibly be part of a type parameter/argument
-   * list, like the '=' in the above example.
-   */
-  void discardOpenLt() {
-    while (!groupingStack.isEmpty &&
-        identical(groupingStack.head.kind, LT_TOKEN)) {
-      groupingStack = groupingStack.tail;
-    }
-  }
-
-  /**
-   * This method is called to discard '${' from the "grouping" stack.
-   *
-   * This method is called when the scanner finds an unterminated
-   * interpolation expression.
-   */
-  void discardInterpolation() {
-    while (!groupingStack.isEmpty) {
-      BeginToken beginToken = groupingStack.head;
-      unmatchedBeginGroup(beginToken);
-      groupingStack = groupingStack.tail;
-      if (identical(beginToken.kind, STRING_INTERPOLATION_TOKEN)) break;
-    }
-  }
-
-  void unmatchedBeginGroup(BeginToken begin) {
-    // We want to ensure that unmatched BeginTokens are reported as
-    // errors.  However, the diet parser assumes that groups are well-balanced
-    // and will never look at the endGroup token.  This is a nice property that
-    // allows us to skip quickly over correct code. By inserting an additional
-    // synthetic token in the stream, we can keep ignoring endGroup tokens.
-    //
-    // [begin] --next--> [tail]
-    // [begin] --endG--> [synthetic] --next--> [next] --next--> [tail]
-    //
-    // This allows the diet parser to skip from [begin] via endGroup to
-    // [synthetic] and ignore the [synthetic] token (assuming it's correct),
-    // then the error will be reported when parsing the [next] token.
-    //
-    // For example, tokenize("{[1};") produces:
-    //
-    // SymbolToken({) --endGroup------------------------+
-    //      |                                           |
-    //     next                                         |
-    //      v                                           |
-    // SymbolToken([) --endGroup--+                     |
-    //      |                     |                     |
-    //     next                   |                     |
-    //      v                     |                     |
-    // StringToken(1)             |                     |
-    //      |                     |                     |
-    //     next                   |                     |
-    //      v                     |                     |
-    // SymbolToken(])<------------+ <-- Synthetic token |
-    //      |                                           |
-    //     next                                         |
-    //      v                                           |
-    // UnmatchedToken([)                                |
-    //      |                                           |
-    //     next                                         |
-    //      v                                           |
-    // SymbolToken(})<----------------------------------+
-    //      |
-    //     next
-    //      v
-    // SymbolToken(;)
-    //      |
-    //     next
-    //      v
-    //     EOF
-    TokenType type = closeBraceInfoFor(begin);
-    appendToken(new SyntheticToken(type, tokenStart)..beforeSynthetic = tail);
-    begin.endGroup = tail;
-    prependErrorToken(new UnmatchedToken(begin));
-  }
-
-  /// Return true when at EOF.
-  bool atEndOfFile();
-
-  Token tokenize() {
-    while (!atEndOfFile()) {
-      int next = advance();
-
-      // Scan the header looking for a language version
-      if (!identical(next, $EOF)) {
-        Token oldTail = tail;
-        next = bigHeaderSwitch(next);
-        if (!identical(next, $EOF) && tail.kind == SCRIPT_TOKEN) {
-          oldTail = tail;
-          next = bigHeaderSwitch(next);
-        }
-        while (!identical(next, $EOF) && tail == oldTail) {
-          next = bigHeaderSwitch(next);
-        }
-        next = next;
-      }
-
-      while (!identical(next, $EOF)) {
-        next = bigSwitch(next);
-      }
-      if (atEndOfFile()) {
-        appendEofToken();
-      } else {
-        unexpected($EOF);
-      }
-    }
-
-    // Always pretend that there's a line at the end of the file.
-    lineStarts.add(stringOffset + 1);
-
-    return firstToken();
-  }
-
-  int bigHeaderSwitch(int next) {
-    if (!identical(next, $SLASH)) {
-      return bigSwitch(next);
-    }
-    beginToken();
-    if (!identical($SLASH, peek())) {
-      return tokenizeSlashOrComment(next);
-    }
-    return tokenizeLanguageVersionOrSingleLineComment(next);
-  }
-
-  int bigSwitch(int next) {
-    beginToken();
-    if (identical(next, $SPACE) ||
-        identical(next, $TAB) ||
-        identical(next, $LF) ||
-        identical(next, $CR)) {
-      appendWhiteSpace(next);
-      next = advance();
-      // Sequences of spaces are common, so advance through them fast.
-      while (identical(next, $SPACE)) {
-        // We don't invoke [:appendWhiteSpace(next):] here for efficiency,
-        // assuming that it does not do anything for space characters.
-        next = advance();
-      }
-      return next;
-    }
-
-    int nextLower = next | 0x20;
-
-    if ($a <= nextLower && nextLower <= $z) {
-      if (identical($r, next)) {
-        return tokenizeRawStringKeywordOrIdentifier(next);
-      }
-      return tokenizeKeywordOrIdentifier(next, true);
-    }
-
-    if (identical(next, $CLOSE_PAREN)) {
-      return appendEndGroup(TokenType.CLOSE_PAREN, OPEN_PAREN_TOKEN);
-    }
-
-    if (identical(next, $OPEN_PAREN)) {
-      appendBeginGroup(TokenType.OPEN_PAREN);
-      return advance();
-    }
-
-    if (identical(next, $SEMICOLON)) {
-      appendPrecedenceToken(TokenType.SEMICOLON);
-      // Type parameters and arguments cannot contain semicolon.
-      discardOpenLt();
-      return advance();
-    }
-
-    if (identical(next, $PERIOD)) {
-      return tokenizeDotsOrNumber(next);
-    }
-
-    if (identical(next, $COMMA)) {
-      appendPrecedenceToken(TokenType.COMMA);
-      return advance();
-    }
-
-    if (identical(next, $EQ)) {
-      return tokenizeEquals(next);
-    }
-
-    if (identical(next, $CLOSE_CURLY_BRACKET)) {
-      return appendEndGroup(
-          TokenType.CLOSE_CURLY_BRACKET, OPEN_CURLY_BRACKET_TOKEN);
-    }
-
-    if (identical(next, $SLASH)) {
-      return tokenizeSlashOrComment(next);
-    }
-
-    if (identical(next, $OPEN_CURLY_BRACKET)) {
-      appendBeginGroup(TokenType.OPEN_CURLY_BRACKET);
-      return advance();
-    }
-
-    if (identical(next, $DQ) || identical(next, $SQ)) {
-      return tokenizeString(next, scanOffset, false);
-    }
-
-    if (identical(next, $_)) {
-      return tokenizeKeywordOrIdentifier(next, true);
-    }
-
-    if (identical(next, $COLON)) {
-      appendPrecedenceToken(TokenType.COLON);
-      return advance();
-    }
-
-    if (identical(next, $LT)) {
-      return tokenizeLessThan(next);
-    }
-
-    if (identical(next, $GT)) {
-      return tokenizeGreaterThan(next);
-    }
-
-    if (identical(next, $BANG)) {
-      return tokenizeExclamation(next);
-    }
-
-    if (identical(next, $OPEN_SQUARE_BRACKET)) {
-      return tokenizeOpenSquareBracket(next);
-    }
-
-    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
-      return appendEndGroup(
-          TokenType.CLOSE_SQUARE_BRACKET, OPEN_SQUARE_BRACKET_TOKEN);
-    }
-
-    if (identical(next, $AT)) {
-      return tokenizeAt(next);
-    }
-
-    if (next >= $1 && next <= $9) {
-      return tokenizeNumber(next);
-    }
-
-    if (identical(next, $AMPERSAND)) {
-      return tokenizeAmpersand(next);
-    }
-
-    if (identical(next, $0)) {
-      return tokenizeHexOrNumber(next);
-    }
-
-    if (identical(next, $QUESTION)) {
-      return tokenizeQuestion(next);
-    }
-
-    if (identical(next, $BAR)) {
-      return tokenizeBar(next);
-    }
-
-    if (identical(next, $PLUS)) {
-      return tokenizePlus(next);
-    }
-
-    if (identical(next, $$)) {
-      return tokenizeKeywordOrIdentifier(next, true);
-    }
-
-    if (identical(next, $MINUS)) {
-      return tokenizeMinus(next);
-    }
-
-    if (identical(next, $STAR)) {
-      return tokenizeMultiply(next);
-    }
-
-    if (identical(next, $CARET)) {
-      return tokenizeCaret(next);
-    }
-
-    if (identical(next, $TILDE)) {
-      return tokenizeTilde(next);
-    }
-
-    if (identical(next, $PERCENT)) {
-      return tokenizePercent(next);
-    }
-
-    if (identical(next, $BACKPING)) {
-      appendPrecedenceToken(TokenType.BACKPING);
-      return advance();
-    }
-
-    if (identical(next, $BACKSLASH)) {
-      appendPrecedenceToken(TokenType.BACKSLASH);
-      return advance();
-    }
-
-    if (identical(next, $HASH)) {
-      return tokenizeTag(next);
-    }
-
-    if (next < 0x1f) {
-      return unexpected(next);
-    }
-
-    next = currentAsUnicode(next);
-
-    return unexpected(next);
-  }
-
-  int tokenizeTag(int next) {
-    // # or #!.*[\n\r]
-    if (scanOffset == 0) {
-      if (identical(peek(), $BANG)) {
-        int start = scanOffset;
-        bool asciiOnly = true;
-        do {
-          next = advance();
-          if (next > 127) asciiOnly = false;
-        } while (!identical(next, $LF) &&
-            !identical(next, $CR) &&
-            !identical(next, $EOF));
-        if (!asciiOnly) handleUnicode(start);
-        appendSubstringToken(TokenType.SCRIPT_TAG, start, asciiOnly);
-        return next;
-      }
-    }
-    appendPrecedenceToken(TokenType.HASH);
-    return advance();
-  }
-
-  int tokenizeTilde(int next) {
-    // ~ ~/ ~/=
-    next = advance();
-    if (identical(next, $SLASH)) {
-      return select($EQ, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
-    } else {
-      appendPrecedenceToken(TokenType.TILDE);
-      return next;
-    }
-  }
-
-  int tokenizeOpenSquareBracket(int next) {
-    // [ [] []=
-    next = advance();
-    if (identical(next, $CLOSE_SQUARE_BRACKET)) {
-      return select($EQ, TokenType.INDEX_EQ, TokenType.INDEX);
-    }
-    appendBeginGroup(TokenType.OPEN_SQUARE_BRACKET);
-    return next;
-  }
-
-  int tokenizeCaret(int next) {
-    // ^ ^=
-    return select($EQ, TokenType.CARET_EQ, TokenType.CARET);
-  }
-
-  int tokenizeQuestion(int next) {
-    // ? ?. ?.. ?? ??=
-    next = advance();
-    if (identical(next, $QUESTION)) {
-      return select(
-          $EQ, TokenType.QUESTION_QUESTION_EQ, TokenType.QUESTION_QUESTION);
-    } else if (identical(next, $PERIOD)) {
-      next = advance();
-      if (_enableNonNullable) {
-        if (identical($PERIOD, next)) {
-          appendPrecedenceToken(TokenType.QUESTION_PERIOD_PERIOD);
-          return advance();
-        }
-        if (identical($OPEN_SQUARE_BRACKET, next)) {
-          appendBeginGroup(TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET);
-          return advance();
-        }
-      }
-      appendPrecedenceToken(TokenType.QUESTION_PERIOD);
-      return next;
-    } else {
-      appendPrecedenceToken(TokenType.QUESTION);
-      return next;
-    }
-  }
-
-  int tokenizeBar(int next) {
-    // | || |= ||=
-    next = advance();
-    if (identical(next, $BAR)) {
-      next = advance();
-      if (LAZY_ASSIGNMENT_ENABLED && identical(next, $EQ)) {
-        appendPrecedenceToken(TokenType.BAR_BAR_EQ);
-        return advance();
-      }
-      appendPrecedenceToken(TokenType.BAR_BAR);
-      return next;
-    } else if (identical(next, $EQ)) {
-      appendPrecedenceToken(TokenType.BAR_EQ);
-      return advance();
-    } else {
-      appendPrecedenceToken(TokenType.BAR);
-      return next;
-    }
-  }
-
-  int tokenizeAmpersand(int next) {
-    // && &= & &&=
-    next = advance();
-    if (identical(next, $AMPERSAND)) {
-      next = advance();
-      if (LAZY_ASSIGNMENT_ENABLED && identical(next, $EQ)) {
-        appendPrecedenceToken(TokenType.AMPERSAND_AMPERSAND_EQ);
-        return advance();
-      }
-      appendPrecedenceToken(TokenType.AMPERSAND_AMPERSAND);
-      return next;
-    } else if (identical(next, $EQ)) {
-      appendPrecedenceToken(TokenType.AMPERSAND_EQ);
-      return advance();
-    } else {
-      appendPrecedenceToken(TokenType.AMPERSAND);
-      return next;
-    }
-  }
-
-  int tokenizePercent(int next) {
-    // % %=
-    return select($EQ, TokenType.PERCENT_EQ, TokenType.PERCENT);
-  }
-
-  int tokenizeMultiply(int next) {
-    // * *=
-    return select($EQ, TokenType.STAR_EQ, TokenType.STAR);
-  }
-
-  int tokenizeMinus(int next) {
-    // - -- -=
-    next = advance();
-    if (identical(next, $MINUS)) {
-      appendPrecedenceToken(TokenType.MINUS_MINUS);
-      return advance();
-    } else if (identical(next, $EQ)) {
-      appendPrecedenceToken(TokenType.MINUS_EQ);
-      return advance();
-    } else {
-      appendPrecedenceToken(TokenType.MINUS);
-      return next;
-    }
-  }
-
-  int tokenizePlus(int next) {
-    // + ++ +=
-    next = advance();
-    if (identical($PLUS, next)) {
-      appendPrecedenceToken(TokenType.PLUS_PLUS);
-      return advance();
-    } else if (identical($EQ, next)) {
-      appendPrecedenceToken(TokenType.PLUS_EQ);
-      return advance();
-    } else {
-      appendPrecedenceToken(TokenType.PLUS);
-      return next;
-    }
-  }
-
-  int tokenizeExclamation(int next) {
-    // ! !=
-    // !== is kept for user-friendly error reporting.
-
-    next = advance();
-    if (identical(next, $EQ)) {
-      //was `return select($EQ, TokenType.BANG_EQ_EQ, TokenType.BANG_EQ);`
-      int next = advance();
-      if (identical(next, $EQ)) {
-        appendPrecedenceToken(TokenType.BANG_EQ_EQ);
-        prependErrorToken(new UnsupportedOperator(tail, tokenStart));
-        return advance();
-      } else {
-        appendPrecedenceToken(TokenType.BANG_EQ);
-        return next;
-      }
-    }
-    appendPrecedenceToken(TokenType.BANG);
-    return next;
-  }
-
-  int tokenizeEquals(int next) {
-    // = == =>
-    // === is kept for user-friendly error reporting.
-
-    // Type parameters and arguments cannot contain any token that
-    // starts with '='.
-    discardOpenLt();
-
-    next = advance();
-    if (identical(next, $EQ)) {
-      // was `return select($EQ, TokenType.EQ_EQ_EQ, TokenType.EQ_EQ);`
-      int next = advance();
-      if (identical(next, $EQ)) {
-        appendPrecedenceToken(TokenType.EQ_EQ_EQ);
-        prependErrorToken(new UnsupportedOperator(tail, tokenStart));
-        return advance();
-      } else {
-        appendPrecedenceToken(TokenType.EQ_EQ);
-        return next;
-      }
-    } else if (identical(next, $GT)) {
-      appendPrecedenceToken(TokenType.FUNCTION);
-      return advance();
-    }
-    appendPrecedenceToken(TokenType.EQ);
-    return next;
-  }
-
-  int tokenizeGreaterThan(int next) {
-    // > >= >> >>= >>> >>>=
-    next = advance();
-    if (identical($EQ, next)) {
-      appendPrecedenceToken(TokenType.GT_EQ);
-      return advance();
-    } else if (identical($GT, next)) {
-      next = advance();
-      if (identical($EQ, next)) {
-        appendPrecedenceToken(TokenType.GT_GT_EQ);
-        return advance();
-      } else if (_enableTripleShift && identical($GT, next)) {
-        next = advance();
-        if (_enableTripleShift && identical($EQ, next)) {
-          appendPrecedenceToken(TokenType.GT_GT_GT_EQ);
-          return advance();
-        }
-        appendPrecedenceToken(TokenType.GT_GT_GT);
-        return next;
-      } else {
-        appendGtGt(TokenType.GT_GT);
-        return next;
-      }
-    } else {
-      appendGt(TokenType.GT);
-      return next;
-    }
-  }
-
-  int tokenizeLessThan(int next) {
-    // < <= << <<=
-    next = advance();
-    if (identical($EQ, next)) {
-      appendPrecedenceToken(TokenType.LT_EQ);
-      return advance();
-    } else if (identical($LT, next)) {
-      return select($EQ, TokenType.LT_LT_EQ, TokenType.LT_LT);
-    } else {
-      appendBeginGroup(TokenType.LT);
-      return next;
-    }
-  }
-
-  int tokenizeNumber(int next) {
-    int start = scanOffset;
-    while (true) {
-      next = advance();
-      if ($0 <= next && next <= $9) {
-        continue;
-      } else if (identical(next, $e) || identical(next, $E)) {
-        return tokenizeFractionPart(next, start);
-      } else {
-        if (identical(next, $PERIOD)) {
-          int nextnext = peek();
-          if ($0 <= nextnext && nextnext <= $9) {
-            return tokenizeFractionPart(advance(), start);
-          }
-        }
-        appendSubstringToken(TokenType.INT, start, true);
-        return next;
-      }
-    }
-  }
-
-  int tokenizeHexOrNumber(int next) {
-    int x = peek();
-    if (identical(x, $x) || identical(x, $X)) {
-      return tokenizeHex(next);
-    }
-    return tokenizeNumber(next);
-  }
-
-  int tokenizeHex(int next) {
-    int start = scanOffset;
-    next = advance(); // Advance past the $x or $X.
-    bool hasDigits = false;
-    while (true) {
-      next = advance();
-      if (($0 <= next && next <= $9) ||
-          ($A <= next && next <= $F) ||
-          ($a <= next && next <= $f)) {
-        hasDigits = true;
-      } else {
-        if (!hasDigits) {
-          prependErrorToken(new UnterminatedToken(
-              messageExpectedHexDigit, start, stringOffset));
-          // Recovery
-          appendSyntheticSubstringToken(
-              TokenType.HEXADECIMAL, start, true, "0");
-          return next;
-        }
-        appendSubstringToken(TokenType.HEXADECIMAL, start, true);
-        return next;
-      }
-    }
-  }
-
-  int tokenizeDotsOrNumber(int next) {
-    int start = scanOffset;
-    next = advance();
-    if (($0 <= next && next <= $9)) {
-      return tokenizeFractionPart(next, start);
-    } else if (identical($PERIOD, next)) {
-      next = advance();
-      if (identical(next, $PERIOD)) {
-        next = advance();
-        if (identical(next, $QUESTION)) {
-          appendPrecedenceToken(TokenType.PERIOD_PERIOD_PERIOD_QUESTION);
-          return advance();
-        } else {
-          appendPrecedenceToken(TokenType.PERIOD_PERIOD_PERIOD);
-          return next;
-        }
-      } else {
-        appendPrecedenceToken(TokenType.PERIOD_PERIOD);
-        return next;
-      }
-    } else {
-      appendPrecedenceToken(TokenType.PERIOD);
-      return next;
-    }
-  }
-
-  int tokenizeFractionPart(int next, int start) {
-    bool done = false;
-    bool hasDigit = false;
-    LOOP:
-    while (!done) {
-      if ($0 <= next && next <= $9) {
-        hasDigit = true;
-      } else if (identical($e, next) || identical($E, next)) {
-        hasDigit = true;
-        next = advance();
-        if (identical(next, $PLUS) || identical(next, $MINUS)) {
-          next = advance();
-        }
-        bool hasExponentDigits = false;
-        while (true) {
-          if ($0 <= next && next <= $9) {
-            hasExponentDigits = true;
-          } else {
-            if (!hasExponentDigits) {
-              appendSyntheticSubstringToken(TokenType.DOUBLE, start, true, '0');
-              prependErrorToken(new UnterminatedToken(
-                  messageMissingExponent, tokenStart, stringOffset));
-              return next;
-            }
-            break;
-          }
-          next = advance();
-        }
-
-        done = true;
-        continue LOOP;
-      } else {
-        done = true;
-        continue LOOP;
-      }
-      next = advance();
-    }
-    if (!hasDigit) {
-      // Reduce offset, we already advanced to the token past the period.
-      appendSubstringToken(TokenType.INT, start, true, -1);
-
-      // TODO(ahe): Wrong offset for the period. Cannot call beginToken because
-      // the scanner already advanced past the period.
-      if (identical($PERIOD, next)) {
-        return select(
-            $PERIOD, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
-      }
-      appendPrecedenceToken(TokenType.PERIOD);
-      return next;
-    }
-    appendSubstringToken(TokenType.DOUBLE, start, true);
-    return next;
-  }
-
-  int tokenizeSlashOrComment(int next) {
-    int start = scanOffset;
-    next = advance();
-    if (identical($STAR, next)) {
-      return tokenizeMultiLineComment(next, start);
-    } else if (identical($SLASH, next)) {
-      return tokenizeSingleLineComment(next, start);
-    } else if (identical($EQ, next)) {
-      appendPrecedenceToken(TokenType.SLASH_EQ);
-      return advance();
-    } else {
-      appendPrecedenceToken(TokenType.SLASH);
-      return next;
-    }
-  }
-
-  int tokenizeLanguageVersionOrSingleLineComment(int next) {
-    int start = scanOffset;
-    next = advance();
-
-    // Dart doc
-    if (identical($SLASH, peek())) {
-      return tokenizeSingleLineComment(next, start);
-    }
-
-    // "@dart"
-    next = advance();
-    while (identical($SPACE, next)) {
-      next = advance();
-    }
-    if (!identical($AT, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-    if (!identical($d, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-    if (!identical($a, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-    if (!identical($r, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-    if (!identical($t, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-
-    // "="
-    while (identical($SPACE, next)) {
-      next = advance();
-    }
-    if (!identical($EQ, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-
-    // major
-    while (identical($SPACE, next)) {
-      next = advance();
-    }
-    int major = 0;
-    int majorStart = scanOffset;
-    while (isDigit(next)) {
-      major = major * 10 + next - $0;
-      next = advance();
-    }
-    if (scanOffset == majorStart) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-
-    // minor
-    if (!identical($PERIOD, next)) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-    next = advance();
-    int minor = 0;
-    int minorStart = scanOffset;
-    while (isDigit(next)) {
-      minor = minor * 10 + next - $0;
-      next = advance();
-    }
-    if (scanOffset == minorStart) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-
-    // trailing spaces
-    while (identical($SPACE, next)) {
-      next = advance();
-    }
-    if (next != $LF && next != $CR && next != $EOF) {
-      return tokenizeSingleLineCommentRest(next, start, false);
-    }
-
-    LanguageVersionToken languageVersion =
-        createLanguageVersionToken(start, major, minor);
-    if (languageVersionChanged != null) {
-      // TODO(danrubel): make this required and remove the languageVersion field
-      languageVersionChanged(this, languageVersion);
-    } else {
-      // TODO(danrubel): remove this hack and require listener to update
-      // the scanner's configuration.
-      configuration = ScannerConfiguration.classic;
-    }
-    if (includeComments) {
-      _appendToCommentStream(languageVersion);
-    }
-    return next;
-  }
-
-  int tokenizeSingleLineComment(int next, int start) {
-    bool dartdoc = identical($SLASH, peek());
-    next = advance();
-    return tokenizeSingleLineCommentRest(next, start, dartdoc);
-  }
-
-  int tokenizeSingleLineCommentRest(int next, int start, bool dartdoc) {
-    bool asciiOnly = true;
-    while (true) {
-      if (next > 127) asciiOnly = false;
-      if (identical($LF, next) ||
-          identical($CR, next) ||
-          identical($EOF, next)) {
-        if (!asciiOnly) handleUnicode(start);
-        if (dartdoc) {
-          appendDartDoc(start, TokenType.SINGLE_LINE_COMMENT, asciiOnly);
-        } else {
-          appendComment(start, TokenType.SINGLE_LINE_COMMENT, asciiOnly);
-        }
-        return next;
-      }
-      next = advance();
-    }
-  }
-
-  int tokenizeMultiLineComment(int next, int start) {
-    bool asciiOnlyComment = true; // Track if the entire comment is ASCII.
-    bool asciiOnlyLines = true; // Track ASCII since the last handleUnicode.
-    int unicodeStart = start;
-    int nesting = 1;
-    next = advance();
-    bool dartdoc = identical($STAR, next);
-    while (true) {
-      if (identical($EOF, next)) {
-        if (!asciiOnlyLines) handleUnicode(unicodeStart);
-        prependErrorToken(new UnterminatedToken(
-            messageUnterminatedComment, tokenStart, stringOffset));
-        advanceAfterError(true);
-        break;
-      } else if (identical($STAR, next)) {
-        next = advance();
-        if (identical($SLASH, next)) {
-          --nesting;
-          if (0 == nesting) {
-            if (!asciiOnlyLines) handleUnicode(unicodeStart);
-            next = advance();
-            if (dartdoc) {
-              appendDartDoc(
-                  start, TokenType.MULTI_LINE_COMMENT, asciiOnlyComment);
-            } else {
-              appendComment(
-                  start, TokenType.MULTI_LINE_COMMENT, asciiOnlyComment);
-            }
-            break;
-          } else {
-            next = advance();
-          }
-        }
-      } else if (identical($SLASH, next)) {
-        next = advance();
-        if (identical($STAR, next)) {
-          next = advance();
-          ++nesting;
-        }
-      } else if (identical(next, $LF)) {
-        if (!asciiOnlyLines) {
-          // Synchronize the string offset in the utf8 scanner.
-          handleUnicode(unicodeStart);
-          asciiOnlyLines = true;
-          unicodeStart = scanOffset;
-        }
-        lineFeedInMultiline();
-        next = advance();
-      } else {
-        if (next > 127) {
-          asciiOnlyLines = false;
-          asciiOnlyComment = false;
-        }
-        next = advance();
-      }
-    }
-    return next;
-  }
-
-  void appendComment(int start, TokenType type, bool asciiOnly) {
-    if (!includeComments) return;
-    CommentToken newComment = createCommentToken(type, start, asciiOnly);
-    _appendToCommentStream(newComment);
-  }
-
-  void appendDartDoc(int start, TokenType type, bool asciiOnly) {
-    if (!includeComments) return;
-    Token newComment = createDartDocToken(type, start, asciiOnly);
-    _appendToCommentStream(newComment);
-  }
-
-  /**
-   * Append the given token to the [tail] of the current stream of tokens.
-   */
-  void appendToken(Token token) {
-    tail.next = token;
-    token.previous = tail;
-    tail = token;
-    if (comments != null && comments == token.precedingComments) {
-      comments = null;
-      commentsTail = null;
-    } else {
-      // It is the responsibility of the caller to construct the token
-      // being appended with preceding comments if any
-      assert(comments == null || token.isSynthetic || token is ErrorToken);
-    }
-  }
-
-  void _appendToCommentStream(Token newComment) {
-    if (comments == null) {
-      comments = newComment;
-      commentsTail = comments;
-    } else {
-      commentsTail.next = newComment;
-      commentsTail.next.previous = commentsTail;
-      commentsTail = commentsTail.next;
-    }
-  }
-
-  int tokenizeRawStringKeywordOrIdentifier(int next) {
-    // [next] is $r.
-    int nextnext = peek();
-    if (identical(nextnext, $DQ) || identical(nextnext, $SQ)) {
-      int start = scanOffset;
-      next = advance();
-      return tokenizeString(next, start, true);
-    }
-    return tokenizeKeywordOrIdentifier(next, true);
-  }
-
-  int tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
-    KeywordState state = KeywordState.KEYWORD_STATE;
-    int start = scanOffset;
-    // We allow a leading capital character.
-    if ($A <= next && next <= $Z) {
-      state = state.nextCapital(next);
-      next = advance();
-    } else if ($a <= next && next <= $z) {
-      // Do the first next call outside the loop to avoid an additional test
-      // and to make the loop monomorphic.
-      state = state.next(next);
-      next = advance();
-    }
-    while (state != null && $a <= next && next <= $z) {
-      state = state.next(next);
-      next = advance();
-    }
-    if (state == null || state.keyword == null) {
-      return tokenizeIdentifier(next, start, allowDollar);
-    }
-    if (!_enableExtensionMethods && state.keyword == Keyword.EXTENSION) {
-      return tokenizeIdentifier(next, start, allowDollar);
-    }
-    if (!_enableNonNullable &&
-        (state.keyword == Keyword.LATE || state.keyword == Keyword.REQUIRED)) {
-      return tokenizeIdentifier(next, start, allowDollar);
-    }
-    if (($A <= next && next <= $Z) ||
-        ($0 <= next && next <= $9) ||
-        identical(next, $_) ||
-        identical(next, $$)) {
-      return tokenizeIdentifier(next, start, allowDollar);
-    } else {
-      appendKeywordToken(state.keyword);
-      return next;
-    }
-  }
-
-  /**
-   * [allowDollar] can exclude '$', which is not allowed as part of a string
-   * interpolation identifier.
-   */
-  int tokenizeIdentifier(int next, int start, bool allowDollar) {
-    while (true) {
-      if (_isIdentifierChar(next, allowDollar)) {
-        next = advance();
-      } else {
-        // Identifier ends here.
-        if (start == scanOffset) {
-          return unexpected(next);
-        } else {
-          appendSubstringToken(TokenType.IDENTIFIER, start, true);
-        }
-        break;
-      }
-    }
-    return next;
-  }
-
-  int tokenizeAt(int next) {
-    appendPrecedenceToken(TokenType.AT);
-    return advance();
-  }
-
-  int tokenizeString(int next, int start, bool raw) {
-    int quoteChar = next;
-    next = advance();
-    if (identical(quoteChar, next)) {
-      next = advance();
-      if (identical(quoteChar, next)) {
-        // Multiline string.
-        return tokenizeMultiLineString(quoteChar, start, raw);
-      } else {
-        // Empty string.
-        appendSubstringToken(TokenType.STRING, start, true);
-        return next;
-      }
-    }
-    if (raw) {
-      return tokenizeSingleLineRawString(next, quoteChar, start);
-    } else {
-      return tokenizeSingleLineString(next, quoteChar, start);
-    }
-  }
-
-  /**
-   * [next] is the first character after the quote.
-   * [quoteStart] is the scanOffset of the quote.
-   *
-   * The token contains a substring of the source file, including the
-   * string quotes, backslashes for escaping. For interpolated strings,
-   * the parts before and after are separate tokens.
-   *
-   *   "a $b c"
-   *
-   * gives StringToken("a $), StringToken(b) and StringToken( c").
-   */
-  int tokenizeSingleLineString(int next, int quoteChar, int quoteStart) {
-    int start = quoteStart;
-    bool asciiOnly = true;
-    while (!identical(next, quoteChar)) {
-      if (identical(next, $BACKSLASH)) {
-        next = advance();
-      } else if (identical(next, $$)) {
-        if (!asciiOnly) handleUnicode(start);
-        next = tokenizeStringInterpolation(start, asciiOnly);
-        start = scanOffset;
-        asciiOnly = true;
-        continue;
-      }
-      if (next <= $CR &&
-          (identical(next, $LF) ||
-              identical(next, $CR) ||
-              identical(next, $EOF))) {
-        if (!asciiOnly) handleUnicode(start);
-        unterminatedString(quoteChar, quoteStart, start,
-            asciiOnly: asciiOnly, isMultiLine: false, isRaw: false);
-        return next;
-      }
-      if (next > 127) asciiOnly = false;
-      next = advance();
-    }
-    if (!asciiOnly) handleUnicode(start);
-    // Advance past the quote character.
-    next = advance();
-    appendSubstringToken(TokenType.STRING, start, asciiOnly);
-    return next;
-  }
-
-  int tokenizeStringInterpolation(int start, bool asciiOnly) {
-    appendSubstringToken(TokenType.STRING, start, asciiOnly);
-    beginToken(); // $ starts here.
-    int next = advance();
-    if (identical(next, $OPEN_CURLY_BRACKET)) {
-      return tokenizeInterpolatedExpression(next);
-    } else {
-      return tokenizeInterpolatedIdentifier(next);
-    }
-  }
-
-  int tokenizeInterpolatedExpression(int next) {
-    appendBeginGroup(TokenType.STRING_INTERPOLATION_EXPRESSION);
-    beginToken(); // The expression starts here.
-    next = advance(); // Move past the curly bracket.
-    while (!identical(next, $EOF) && !identical(next, $STX)) {
-      next = bigSwitch(next);
-    }
-    if (identical(next, $EOF)) {
-      beginToken();
-      discardInterpolation();
-      return next;
-    }
-    next = advance(); // Move past the $STX.
-    beginToken(); // The string interpolation suffix starts here.
-    return next;
-  }
-
-  int tokenizeInterpolatedIdentifier(int next) {
-    appendPrecedenceToken(TokenType.STRING_INTERPOLATION_IDENTIFIER);
-
-    if ($a <= next && next <= $z ||
-        $A <= next && next <= $Z ||
-        identical(next, $_)) {
-      beginToken(); // The identifier starts here.
-      next = tokenizeKeywordOrIdentifier(next, false);
-    } else {
-      beginToken(); // The synthetic identifier starts here.
-      appendSyntheticSubstringToken(TokenType.IDENTIFIER, scanOffset, true, '');
-      prependErrorToken(new UnterminatedToken(
-          messageUnexpectedDollarInString, tokenStart, stringOffset));
-    }
-    beginToken(); // The string interpolation suffix starts here.
-    return next;
-  }
-
-  int tokenizeSingleLineRawString(int next, int quoteChar, int quoteStart) {
-    bool asciiOnly = true;
-    while (next != $EOF) {
-      if (identical(next, quoteChar)) {
-        if (!asciiOnly) handleUnicode(quoteStart);
-        next = advance();
-        appendSubstringToken(TokenType.STRING, quoteStart, asciiOnly);
-        return next;
-      } else if (identical(next, $LF) || identical(next, $CR)) {
-        if (!asciiOnly) handleUnicode(quoteStart);
-        unterminatedString(quoteChar, quoteStart, quoteStart,
-            asciiOnly: asciiOnly, isMultiLine: false, isRaw: true);
-        return next;
-      } else if (next > 127) {
-        asciiOnly = false;
-      }
-      next = advance();
-    }
-    if (!asciiOnly) handleUnicode(quoteStart);
-    unterminatedString(quoteChar, quoteStart, quoteStart,
-        asciiOnly: asciiOnly, isMultiLine: false, isRaw: true);
-    return next;
-  }
-
-  int tokenizeMultiLineRawString(int quoteChar, int quoteStart) {
-    bool asciiOnlyString = true;
-    bool asciiOnlyLine = true;
-    int unicodeStart = quoteStart;
-    int next = advance(); // Advance past the (last) quote (of three).
-    outer:
-    while (!identical(next, $EOF)) {
-      while (!identical(next, quoteChar)) {
-        if (identical(next, $LF)) {
-          if (!asciiOnlyLine) {
-            // Synchronize the string offset in the utf8 scanner.
-            handleUnicode(unicodeStart);
-            asciiOnlyLine = true;
-            unicodeStart = scanOffset;
-          }
-          lineFeedInMultiline();
-        } else if (next > 127) {
-          asciiOnlyLine = false;
-          asciiOnlyString = false;
-        }
-        next = advance();
-        if (identical(next, $EOF)) break outer;
-      }
-      next = advance();
-      if (identical(next, quoteChar)) {
-        next = advance();
-        if (identical(next, quoteChar)) {
-          if (!asciiOnlyLine) handleUnicode(unicodeStart);
-          next = advance();
-          appendSubstringToken(TokenType.STRING, quoteStart, asciiOnlyString);
-          return next;
-        }
-      }
-    }
-    if (!asciiOnlyLine) handleUnicode(unicodeStart);
-    unterminatedString(quoteChar, quoteStart, quoteStart,
-        asciiOnly: asciiOnlyLine, isMultiLine: true, isRaw: true);
-    return next;
-  }
-
-  int tokenizeMultiLineString(int quoteChar, int quoteStart, bool raw) {
-    if (raw) return tokenizeMultiLineRawString(quoteChar, quoteStart);
-    int start = quoteStart;
-    bool asciiOnlyString = true;
-    bool asciiOnlyLine = true;
-    int unicodeStart = start;
-    int next = advance(); // Advance past the (last) quote (of three).
-    while (!identical(next, $EOF)) {
-      if (identical(next, $$)) {
-        if (!asciiOnlyLine) handleUnicode(unicodeStart);
-        next = tokenizeStringInterpolation(start, asciiOnlyString);
-        start = scanOffset;
-        unicodeStart = start;
-        asciiOnlyString = true; // A new string token is created for the rest.
-        asciiOnlyLine = true;
-        continue;
-      }
-      if (identical(next, quoteChar)) {
-        next = advance();
-        if (identical(next, quoteChar)) {
-          next = advance();
-          if (identical(next, quoteChar)) {
-            if (!asciiOnlyLine) handleUnicode(unicodeStart);
-            next = advance();
-            appendSubstringToken(TokenType.STRING, start, asciiOnlyString);
-            return next;
-          }
-        }
-        continue;
-      }
-      if (identical(next, $BACKSLASH)) {
-        next = advance();
-        if (identical(next, $EOF)) break;
-      }
-      if (identical(next, $LF)) {
-        if (!asciiOnlyLine) {
-          // Synchronize the string offset in the utf8 scanner.
-          handleUnicode(unicodeStart);
-          asciiOnlyLine = true;
-          unicodeStart = scanOffset;
-        }
-        lineFeedInMultiline();
-      } else if (next > 127) {
-        asciiOnlyString = false;
-        asciiOnlyLine = false;
-      }
-      next = advance();
-    }
-    if (!asciiOnlyLine) handleUnicode(unicodeStart);
-    unterminatedString(quoteChar, quoteStart, start,
-        asciiOnly: asciiOnlyString, isMultiLine: true, isRaw: false);
-    return next;
-  }
-
-  int unexpected(int character) {
-    ErrorToken errorToken =
-        buildUnexpectedCharacterToken(character, tokenStart);
-    if (errorToken is NonAsciiIdentifierToken) {
-      int charOffset;
-      List<int> codeUnits = <int>[];
-      if (tail.type == TokenType.IDENTIFIER && tail.charEnd == tokenStart) {
-        charOffset = tail.charOffset;
-        codeUnits.addAll(tail.lexeme.codeUnits);
-        tail = tail.previous;
-      } else {
-        charOffset = errorToken.charOffset;
-      }
-      codeUnits.add(errorToken.character);
-      prependErrorToken(errorToken);
-      int next = advanceAfterError(true);
-      while (_isIdentifierChar(next, true)) {
-        codeUnits.add(next);
-        next = advance();
-      }
-      appendToken(new StringToken.fromString(TokenType.IDENTIFIER,
-          new String.fromCharCodes(codeUnits), charOffset));
-      return next;
-    } else {
-      prependErrorToken(errorToken);
-      return advanceAfterError(true);
-    }
-  }
-
-  void unterminatedString(int quoteChar, int quoteStart, int start,
-      {bool asciiOnly, bool isMultiLine, bool isRaw}) {
-    String suffix = new String.fromCharCodes(
-        isMultiLine ? [quoteChar, quoteChar, quoteChar] : [quoteChar]);
-    String prefix = isRaw ? 'r$suffix' : suffix;
-
-    appendSyntheticSubstringToken(TokenType.STRING, start, asciiOnly, suffix);
-    // Ensure that the error is reported on a visible token
-    int errorStart = tokenStart < stringOffset ? tokenStart : quoteStart;
-    prependErrorToken(new UnterminatedString(prefix, errorStart, stringOffset));
-  }
-
-  int advanceAfterError(bool shouldAdvance) {
-    if (atEndOfFile()) return $EOF;
-    if (shouldAdvance) {
-      return advance(); // Ensure progress.
-    } else {
-      return -1;
-    }
-  }
-}
-
-TokenType closeBraceInfoFor(BeginToken begin) {
-  return const {
-    '(': TokenType.CLOSE_PAREN,
-    '[': TokenType.CLOSE_SQUARE_BRACKET,
-    '{': TokenType.CLOSE_CURLY_BRACKET,
-    '<': TokenType.GT,
-    r'${': TokenType.CLOSE_CURLY_BRACKET,
-    '?.[': TokenType.CLOSE_SQUARE_BRACKET,
-  }[begin.lexeme];
-}
-
-class LineStarts extends Object with ListMixin<int> {
-  List<int> array;
-  int arrayLength = 0;
-
-  LineStarts(int numberOfBytesHint) {
-    // Let's assume the average Dart file is 300 bytes.
-    if (numberOfBytesHint == null) numberOfBytesHint = 300;
-
-    // Let's assume we have on average 22 bytes per line.
-    final int expectedNumberOfLines = 1 + (numberOfBytesHint ~/ 22);
-
-    if (numberOfBytesHint > 65535) {
-      array = new Uint32List(expectedNumberOfLines);
-    } else {
-      array = new Uint16List(expectedNumberOfLines);
-    }
-
-    // The first line starts at character offset 0.
-    add(0);
-  }
-
-  // Implement abstract members used by [ListMixin]
-
-  int get length => arrayLength;
-
-  int operator [](int index) {
-    assert(index < arrayLength);
-    return array[index];
-  }
-
-  void set length(int newLength) {
-    if (newLength > array.length) {
-      grow(newLength);
-    }
-    arrayLength = newLength;
-  }
-
-  void operator []=(int index, int value) {
-    if (value > 65535 && array is! Uint32List) {
-      switchToUint32(array.length);
-    }
-    array[index] = value;
-  }
-
-  // Specialize methods from [ListMixin].
-  void add(int value) {
-    if (arrayLength >= array.length) {
-      grow(0);
-    }
-    if (value > 65535 && array is! Uint32List) {
-      switchToUint32(array.length);
-    }
-    array[arrayLength++] = value;
-  }
-
-  // Helper methods.
-
-  void grow(int newLengthMinimum) {
-    int newLength = array.length * 2;
-    if (newLength < newLengthMinimum) newLength = newLengthMinimum;
-
-    if (array is Uint16List) {
-      final Uint16List newArray = new Uint16List(newLength);
-      newArray.setRange(0, arrayLength, array);
-      array = newArray;
-    } else {
-      switchToUint32(newLength);
-    }
-  }
-
-  void switchToUint32(int newLength) {
-    final Uint32List newArray = new Uint32List(newLength);
-    newArray.setRange(0, arrayLength, array);
-    array = newArray;
-  }
-}
-
-/// [ScannerConfiguration] contains information for configuring which tokens
-/// the scanner produces based upon the Dart language level.
-class ScannerConfiguration {
-  static const ScannerConfiguration classic = const ScannerConfiguration();
-  static const ScannerConfiguration nonNullable =
-      const ScannerConfiguration(enableNonNullable: true);
-
-  /// Experimental flag for enabling scanning of the `extension` keyword.
-  final bool enableExtensionMethods;
-
-  /// Experimental flag for enabling scanning of NNBD tokens
-  /// such as 'required' and 'late'
-  final bool enableNonNullable;
-
-  /// Experimental flag for enabling scanning of `>>>`.
-  /// See https://github.com/dart-lang/language/issues/61
-  /// and https://github.com/dart-lang/language/issues/60
-  final bool enableTripleShift;
-
-  const ScannerConfiguration({
-    bool enableExtensionMethods,
-    bool enableNonNullable,
-    bool enableTripleShift,
-  })  : this.enableExtensionMethods = enableExtensionMethods ?? false,
-        this.enableNonNullable = enableNonNullable ?? false,
-        this.enableTripleShift = enableTripleShift ?? false;
-}
-
-bool _isIdentifierChar(int next, bool allowDollar) {
-  return ($a <= next && next <= $z) ||
-      ($A <= next && next <= $Z) ||
-      ($0 <= next && next <= $9) ||
-      identical(next, $_) ||
-      (identical(next, $$) && allowDollar);
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/characters.dart b/pkg/front_end/lib/src/fasta/scanner/characters.dart
deleted file mode 100644
index 21edbe74..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/characters.dart
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.scanner.characters;
-
-const int $EOF = 0;
-const int $STX = 2;
-const int $BS = 8;
-const int $TAB = 9;
-const int $LF = 10;
-const int $VTAB = 11;
-const int $FF = 12;
-const int $CR = 13;
-const int $SPACE = 32;
-const int $BANG = 33;
-const int $DQ = 34;
-const int $HASH = 35;
-const int $$ = 36;
-const int $PERCENT = 37;
-const int $AMPERSAND = 38;
-const int $SQ = 39;
-const int $OPEN_PAREN = 40;
-const int $CLOSE_PAREN = 41;
-const int $STAR = 42;
-const int $PLUS = 43;
-const int $COMMA = 44;
-const int $MINUS = 45;
-const int $PERIOD = 46;
-const int $SLASH = 47;
-const int $0 = 48;
-const int $1 = 49;
-const int $2 = 50;
-const int $3 = 51;
-const int $4 = 52;
-const int $5 = 53;
-const int $6 = 54;
-const int $7 = 55;
-const int $8 = 56;
-const int $9 = 57;
-const int $COLON = 58;
-const int $SEMICOLON = 59;
-const int $LT = 60;
-const int $EQ = 61;
-const int $GT = 62;
-const int $QUESTION = 63;
-const int $AT = 64;
-const int $A = 65;
-const int $B = 66;
-const int $C = 67;
-const int $D = 68;
-const int $E = 69;
-const int $F = 70;
-const int $G = 71;
-const int $H = 72;
-const int $I = 73;
-const int $J = 74;
-const int $K = 75;
-const int $L = 76;
-const int $M = 77;
-const int $N = 78;
-const int $O = 79;
-const int $P = 80;
-const int $Q = 81;
-const int $R = 82;
-const int $S = 83;
-const int $T = 84;
-const int $U = 85;
-const int $V = 86;
-const int $W = 87;
-const int $X = 88;
-const int $Y = 89;
-const int $Z = 90;
-const int $OPEN_SQUARE_BRACKET = 91;
-const int $BACKSLASH = 92;
-const int $CLOSE_SQUARE_BRACKET = 93;
-const int $CARET = 94;
-const int $_ = 95;
-const int $BACKPING = 96;
-const int $a = 97;
-const int $b = 98;
-const int $c = 99;
-const int $d = 100;
-const int $e = 101;
-const int $f = 102;
-const int $g = 103;
-const int $h = 104;
-const int $i = 105;
-const int $j = 106;
-const int $k = 107;
-const int $l = 108;
-const int $m = 109;
-const int $n = 110;
-const int $o = 111;
-const int $p = 112;
-const int $q = 113;
-const int $r = 114;
-const int $s = 115;
-const int $t = 116;
-const int $u = 117;
-const int $v = 118;
-const int $w = 119;
-const int $x = 120;
-const int $y = 121;
-const int $z = 122;
-const int $OPEN_CURLY_BRACKET = 123;
-const int $BAR = 124;
-const int $CLOSE_CURLY_BRACKET = 125;
-const int $TILDE = 126;
-const int $DEL = 127;
-const int $NBSP = 160;
-const int $LS = 0x2028;
-const int $PS = 0x2029;
-
-const int $FIRST_SURROGATE = 0xd800;
-const int $LAST_SURROGATE = 0xdfff;
-const int $LAST_CODE_POINT = 0x10ffff;
-
-bool isDigit(int characterCode) {
-  return $0 <= characterCode && characterCode <= $9;
-}
-
-bool isHexDigit(int characterCode) {
-  if (characterCode <= $9) return $0 <= characterCode;
-  characterCode |= $a ^ $A;
-  return ($a <= characterCode && characterCode <= $f);
-}
-
-int hexDigitValue(int hexDigit) {
-  assert(isHexDigit(hexDigit));
-  // hexDigit is one of '0'..'9', 'A'..'F' and 'a'..'f'.
-  if (hexDigit <= $9) return hexDigit - $0;
-  return (hexDigit | ($a ^ $A)) - ($a - 10);
-}
-
-bool isUnicodeScalarValue(int value) {
-  return value < $FIRST_SURROGATE ||
-      (value > $LAST_SURROGATE && value <= $LAST_CODE_POINT);
-}
-
-bool isUtf16LeadSurrogate(int value) {
-  return value >= 0xd800 && value <= 0xdbff;
-}
-
-bool isUtf16TrailSurrogate(int value) {
-  return value >= 0xdc00 && value <= 0xdfff;
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/error_token.dart b/pkg/front_end/lib/src/fasta/scanner/error_token.dart
deleted file mode 100644
index 57a5e0f..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/error_token.dart
+++ /dev/null
@@ -1,217 +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.
-
-library dart_scanner.error_token;
-
-import '../../scanner/token.dart' show BeginToken, SimpleToken, TokenType;
-
-import '../fasta_codes.dart'
-    show
-        Code,
-        Message,
-        messageEncoding,
-        templateAsciiControlCharacter,
-        templateNonAsciiIdentifier,
-        templateNonAsciiWhitespace,
-        templateUnmatchedToken,
-        templateUnsupportedOperator,
-        templateUnterminatedString;
-
-import '../scanner.dart' show Token, unicodeReplacementCharacter;
-
-import '../scanner/recover.dart' show closeBraceFor, closeQuoteFor;
-
-ErrorToken buildUnexpectedCharacterToken(int character, int charOffset) {
-  if (character < 0x1f) {
-    return new AsciiControlCharacterToken(character, charOffset);
-  }
-  switch (character) {
-    case unicodeReplacementCharacter:
-      return new EncodingErrorToken(charOffset);
-
-    /// See [General Punctuation]
-    /// (http://www.unicode.org/charts/PDF/U2000.pdf).
-    case 0x00A0: // No-break space.
-    case 0x1680: // Ogham space mark.
-    case 0x180E: // Mongolian vowel separator.
-    case 0x2000: // En quad.
-    case 0x2001: // Em quad.
-    case 0x2002: // En space.
-    case 0x2003: // Em space.
-    case 0x2004: // Three-per-em space.
-    case 0x2005: // Four-per-em space.
-    case 0x2006: // Six-per-em space.
-    case 0x2007: // Figure space.
-    case 0x2008: // Punctuation space.
-    case 0x2009: // Thin space.
-    case 0x200A: // Hair space.
-    case 0x200B: // Zero width space.
-    case 0x2028: // Line separator.
-    case 0x2029: // Paragraph separator.
-    case 0x202F: // Narrow no-break space.
-    case 0x205F: // Medium mathematical space.
-    case 0x3000: // Ideographic space.
-    case 0xFEFF: // Zero width no-break space.
-      return new NonAsciiWhitespaceToken(character, charOffset);
-
-    default:
-      return new NonAsciiIdentifierToken(character, charOffset);
-  }
-}
-
-/// Common superclass for all error tokens.
-///
-/// It's considered an implementation error to access [lexeme] of an
-/// [ErrorToken].
-abstract class ErrorToken extends SimpleToken {
-  ErrorToken(int offset) : super(TokenType.BAD_INPUT, offset, null);
-
-  /// This is a token that wraps around an error message. Return 1
-  /// instead of the size of the length of the error message.
-  @override
-  int get length => 1;
-
-  String get lexeme {
-    String errorMsg = assertionMessage.message;
-
-    // Attempt to include the location which is calling the parser
-    // in an effort to debug https://github.com/dart-lang/sdk/issues/37528
-    RegExp pattern = new RegExp('^#[0-9]* *Parser');
-    List<String> traceLines = StackTrace.current.toString().split('\n');
-    for (int index = traceLines.length - 2; index >= 0; --index) {
-      String line = traceLines[index];
-      if (line.startsWith(pattern)) {
-        errorMsg = '$errorMsg - ${traceLines[index + 1]}';
-        break;
-      }
-    }
-
-    throw errorMsg;
-  }
-
-  Message get assertionMessage;
-
-  Code<dynamic> get errorCode => assertionMessage.code;
-
-  int get character => null;
-
-  String get start => null;
-
-  int get endOffset => null;
-
-  BeginToken get begin => null;
-
-  @override
-  Token copy() {
-    throw 'unsupported operation';
-  }
-}
-
-/// Represents an encoding error.
-class EncodingErrorToken extends ErrorToken {
-  EncodingErrorToken(int charOffset) : super(charOffset);
-
-  String toString() => "EncodingErrorToken()";
-
-  Message get assertionMessage => messageEncoding;
-}
-
-/// Represents a non-ASCII character outside a string or comment.
-class NonAsciiIdentifierToken extends ErrorToken {
-  final int character;
-
-  NonAsciiIdentifierToken(this.character, int charOffset) : super(charOffset);
-
-  String toString() => "NonAsciiIdentifierToken($character)";
-
-  Message get assertionMessage => templateNonAsciiIdentifier.withArguments(
-      new String.fromCharCodes([character]), character);
-}
-
-/// Represents a non-ASCII whitespace outside a string or comment.
-class NonAsciiWhitespaceToken extends ErrorToken {
-  final int character;
-
-  NonAsciiWhitespaceToken(this.character, int charOffset) : super(charOffset);
-
-  String toString() => "NonAsciiWhitespaceToken($character)";
-
-  Message get assertionMessage =>
-      templateNonAsciiWhitespace.withArguments(character);
-}
-
-/// Represents an ASCII control character outside a string or comment.
-class AsciiControlCharacterToken extends ErrorToken {
-  final int character;
-
-  AsciiControlCharacterToken(this.character, int charOffset)
-      : super(charOffset);
-
-  String toString() => "AsciiControlCharacterToken($character)";
-
-  Message get assertionMessage =>
-      templateAsciiControlCharacter.withArguments(character);
-}
-
-/// Denotes an operator that is not supported in the Dart language.
-class UnsupportedOperator extends ErrorToken {
-  Token token;
-
-  UnsupportedOperator(this.token, int charOffset) : super(charOffset);
-
-  @override
-  Message get assertionMessage =>
-      templateUnsupportedOperator.withArguments(token);
-
-  @override
-  String toString() => "UnsupportedOperator(${token.lexeme})";
-}
-
-/// Represents an unterminated string.
-class UnterminatedString extends ErrorToken {
-  final String start;
-  final int endOffset;
-
-  UnterminatedString(this.start, int charOffset, this.endOffset)
-      : super(charOffset);
-
-  String toString() => "UnterminatedString($start)";
-
-  int get charCount => endOffset - charOffset;
-
-  int get length => charCount;
-
-  Message get assertionMessage =>
-      templateUnterminatedString.withArguments(start, closeQuoteFor(start));
-}
-
-/// Represents an unterminated token.
-class UnterminatedToken extends ErrorToken {
-  final Message assertionMessage;
-  final int endOffset;
-
-  UnterminatedToken(this.assertionMessage, int charOffset, this.endOffset)
-      : super(charOffset);
-
-  String toString() => "UnterminatedToken(${assertionMessage.code.name})";
-
-  int get charCount => endOffset - charOffset;
-}
-
-/// Represents an open brace without a matching close brace.
-///
-/// In this case, brace means any of `(`, `{`, `[`, and `<`, parenthesis, curly
-/// brace, square brace, and angle brace, respectively.
-class UnmatchedToken extends ErrorToken {
-  final BeginToken begin;
-
-  UnmatchedToken(BeginToken begin)
-      : this.begin = begin,
-        super(begin.charOffset);
-
-  String toString() => "UnmatchedToken(${begin.lexeme})";
-
-  Message get assertionMessage =>
-      templateUnmatchedToken.withArguments(closeBraceFor(begin.lexeme), begin);
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/io.dart b/pkg/front_end/lib/src/fasta/scanner/io.dart
deleted file mode 100644
index 8fdbe23..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/io.dart
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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.md file.
-
-library fasta.scanner.io;
-
-import 'dart:async' show Future;
-
-import 'dart:io' show File, RandomAccessFile;
-
-import 'dart:typed_data' show Uint8List;
-
-List<int> readBytesFromFileSync(Uri uri) {
-  RandomAccessFile file = new File.fromUri(uri).openSync();
-  Uint8List list;
-  try {
-    int length = file.lengthSync();
-    // +1 to have a 0 terminated list, see [Scanner].
-    list = new Uint8List(length + 1);
-    file.readIntoSync(list, 0, length);
-  } finally {
-    file.closeSync();
-  }
-  return list;
-}
-
-Future<List<int>> readBytesFromFile(Uri uri,
-    {bool ensureZeroTermination: true}) async {
-  RandomAccessFile file = await new File.fromUri(uri).open();
-  Uint8List list;
-  try {
-    int length = await file.length();
-    // +1 to have a 0 terminated list, see [Scanner].
-    list = new Uint8List(ensureZeroTermination ? length + 1 : length);
-    int read = await file.readInto(list);
-    if (read != length) {
-      throw "Error reading file: ${uri}";
-    }
-  } finally {
-    await file.close();
-  }
-  return list;
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart b/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart
deleted file mode 100644
index ba66e41..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/keyword_state.dart
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.scanner.keywords;
-
-import '../../scanner/token.dart' as analyzer;
-
-import 'characters.dart' show $a, $z, $A, $Z;
-
-/**
- * Abstract state in a state machine for scanning keywords.
- */
-abstract class KeywordState {
-  KeywordState next(int c);
-  KeywordState nextCapital(int c);
-
-  analyzer.Keyword get keyword;
-
-  static KeywordState _KEYWORD_STATE;
-  static KeywordState get KEYWORD_STATE {
-    if (_KEYWORD_STATE == null) {
-      List<String> strings = new List<String>(analyzer.Keyword.values.length);
-      for (int i = 0; i < analyzer.Keyword.values.length; i++) {
-        strings[i] = analyzer.Keyword.values[i].lexeme;
-      }
-      strings.sort((a, b) => a.compareTo(b));
-      _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length);
-    }
-    return _KEYWORD_STATE;
-  }
-
-  static KeywordState computeKeywordStateTable(
-      int start, List<String> strings, int offset, int length) {
-    bool isLowercase = true;
-
-    List<KeywordState> table = new List<KeywordState>($z - $A + 1);
-    assert(length != 0);
-    int chunk = 0;
-    int chunkStart = -1;
-    bool isLeaf = false;
-    for (int i = offset; i < offset + length; i++) {
-      if (strings[i].length == start) {
-        isLeaf = true;
-      }
-      if (strings[i].length > start) {
-        int c = strings[i].codeUnitAt(start);
-        if ($A <= c && c <= $Z) {
-          isLowercase = false;
-        }
-        if (chunk != c) {
-          if (chunkStart != -1) {
-            assert(table[chunk - $A] == null);
-            table[chunk - $A] = computeKeywordStateTable(
-                start + 1, strings, chunkStart, i - chunkStart);
-          }
-          chunkStart = i;
-          chunk = c;
-        }
-      }
-    }
-    if (chunkStart != -1) {
-      assert(table[chunk - $A] == null);
-      table[chunk - $A] = computeKeywordStateTable(
-          start + 1, strings, chunkStart, offset + length - chunkStart);
-    } else {
-      assert(length == 1);
-      return new LeafKeywordState(strings[offset]);
-    }
-    String syntax = isLeaf ? strings[offset] : null;
-    if (isLowercase) {
-      table = table.sublist($a - $A);
-      return new LowerCaseArrayKeywordState(table, syntax);
-    } else {
-      return new UpperCaseArrayKeywordState(table, syntax);
-    }
-  }
-}
-
-/**
- * A state with multiple outgoing transitions.
- */
-abstract class ArrayKeywordState implements KeywordState {
-  final List<KeywordState> table;
-  final analyzer.Keyword keyword;
-
-  ArrayKeywordState(this.table, String syntax)
-      : keyword = ((syntax == null) ? null : analyzer.Keyword.keywords[syntax]);
-
-  KeywordState next(int c);
-
-  KeywordState nextCapital(int c);
-
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write("[");
-    if (keyword != null) {
-      sb.write("*");
-      sb.write(keyword);
-      sb.write(" ");
-    }
-    List<KeywordState> foo = table;
-    for (int i = 0; i < foo.length; i++) {
-      if (foo[i] != null) {
-        sb.write("${new String.fromCharCodes([i + $a])}: "
-            "${foo[i]}; ");
-      }
-    }
-    sb.write("]");
-    return sb.toString();
-  }
-}
-
-class LowerCaseArrayKeywordState extends ArrayKeywordState {
-  LowerCaseArrayKeywordState(List<KeywordState> table, String syntax)
-      : super(table, syntax) {
-    assert(table.length == $z - $a + 1);
-  }
-
-  KeywordState next(int c) => table[c - $a];
-
-  KeywordState nextCapital(int c) => null;
-}
-
-class UpperCaseArrayKeywordState extends ArrayKeywordState {
-  UpperCaseArrayKeywordState(List<KeywordState> table, String syntax)
-      : super(table, syntax) {
-    assert(table.length == $z - $A + 1);
-  }
-
-  KeywordState next(int c) => table[c - $A];
-
-  KeywordState nextCapital(int c) => table[c - $A];
-}
-
-/**
- * A state that has no outgoing transitions.
- */
-class LeafKeywordState implements KeywordState {
-  final analyzer.Keyword keyword;
-
-  LeafKeywordState(String syntax) : keyword = analyzer.Keyword.keywords[syntax];
-
-  KeywordState next(int c) => null;
-  KeywordState nextCapital(int c) => null;
-
-  String toString() => keyword.lexeme;
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/recover.dart b/pkg/front_end/lib/src/fasta/scanner/recover.dart
deleted file mode 100644
index 6f72ed4..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/recover.dart
+++ /dev/null
@@ -1,86 +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.
-
-library fasta.scanner.recover;
-
-import '../../scanner/token.dart' show TokenType;
-
-import '../../scanner/token.dart' show Token;
-
-import 'token.dart' show StringToken;
-
-import 'error_token.dart' show ErrorToken;
-
-/// Recover from errors in [tokens]. The original sources are provided as
-/// [bytes]. [lineStarts] are the beginning character offsets of lines, and
-/// must be updated if recovery is performed rewriting the original source
-/// code.
-Token scannerRecovery(List<int> bytes, Token tokens, List<int> lineStarts) {
-  // Sanity check that all error tokens are prepended.
-
-  // TODO(danrubel): Remove this in a while after the dust has settled.
-
-  // Skip over prepended error tokens
-  Token token = tokens;
-  while (token is ErrorToken) {
-    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;
-        if (previous.isEof) break;
-        token = previous;
-      }
-      StringBuffer msg = new StringBuffer(
-          "Internal error: All error tokens should have been prepended:");
-      for (int count = 0; count < 7; ++count) {
-        if (token.isEof) break;
-        msg.write(' ${token.runtimeType},');
-        token = token.next;
-      }
-      throw msg.toString();
-    }
-    token = token.next;
-  }
-
-  return tokens;
-}
-
-Token synthesizeToken(int charOffset, String value, TokenType type) {
-  return new StringToken.fromString(type, value, charOffset);
-}
-
-Token skipToEof(Token token) {
-  while (!token.isEof) {
-    token = token.next;
-  }
-  return token;
-}
-
-String closeBraceFor(String openBrace) {
-  return const {
-    '(': ')',
-    '[': ']',
-    '{': '}',
-    '<': '>',
-    r'${': '}',
-    '?.[': ']',
-  }[openBrace];
-}
-
-String closeQuoteFor(String openQuote) {
-  return const {
-    '"': '"',
-    "'": "'",
-    '"""': '"""',
-    "'''": "'''",
-    'r"': '"',
-    "r'": "'",
-    'r"""': '"""',
-    "r'''": "'''",
-  }[openQuote];
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/scanner_main.dart b/pkg/front_end/lib/src/fasta/scanner/scanner_main.dart
deleted file mode 100644
index dfe85de..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/scanner_main.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-// 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.md file.
-
-library fasta.scanner.main;
-
-import 'io.dart' show readBytesFromFileSync;
-
-import '../scanner.dart' show ErrorToken, Token, scan;
-
-scanAll(Map<Uri, List<int>> files, {bool verbose: false, bool verify: false}) {
-  Stopwatch sw = new Stopwatch()..start();
-  int byteCount = 0;
-  files.forEach((Uri uri, List<int> bytes) {
-    Token token = scan(bytes).tokens;
-    if (verbose) printTokens(token);
-    if (verify) verifyErrorTokens(token, uri);
-    byteCount += bytes.length - 1;
-  });
-  sw.stop();
-  print("Scanning files took: ${sw.elapsed}");
-  print("Bytes/ms: ${byteCount / sw.elapsedMilliseconds}");
-}
-
-void printTokens(Token token) {
-  while (!token.isEof) {
-    print("${token.charOffset}: $token");
-    token = token.next;
-  }
-}
-
-/// Verify that the fasta scanner recovery has moved all of the ErrorTokens
-/// to the beginning of the stream. If an out-of-order ErrorToken is
-/// found, then print some diagnostic information and throw an exception.
-void verifyErrorTokens(Token firstToken, Uri uri) {
-  Token token = firstToken;
-  while (token is ErrorToken) {
-    token = token.next;
-  }
-
-  while (!token.isEof) {
-    if (token is ErrorToken) {
-      print('Found out-of-order ErrorTokens when scanning:\n  $uri');
-
-      // Rescan the token stream up to the error token to find the 10 tokens
-      // before the out of order ErrorToken.
-      Token errorToken = token;
-      Token start = firstToken;
-      int count = 0;
-      token = firstToken;
-      while (token != errorToken) {
-        token = token.next;
-        if (count < 10) {
-          ++count;
-        } else {
-          start = start.next;
-        }
-      }
-
-      // Print the out of order error token plus some tokens before and after.
-      count = 0;
-      token = start;
-      while (count < 20 && !token.isEof) {
-        print("${token.charOffset}: $token");
-        token = token.next;
-        ++count;
-      }
-      throw 'Out of order ErrorToken: $errorToken';
-    }
-    token = token.next;
-  }
-}
-
-mainEntryPoint(List<String> arguments) {
-  Map<Uri, List<int>> files = <Uri, List<int>>{};
-  Stopwatch sw = new Stopwatch()..start();
-  bool verbose = const bool.fromEnvironment("printTokens");
-  bool verify = const bool.fromEnvironment('verifyErrorTokens');
-  for (String arg in arguments) {
-    if (arg.startsWith('--')) {
-      if (arg == '--print-tokens') {
-        verbose = true;
-      } else if (arg == '--verify-error-tokens') {
-        verify = true;
-      } else {
-        print('Unrecognized option: $arg');
-      }
-      continue;
-    }
-
-    Uri uri = Uri.base.resolve(arg);
-    List<int> bytes = readBytesFromFileSync(uri);
-    files[uri] = bytes;
-  }
-  sw.stop();
-  print("Reading files took: ${sw.elapsed}");
-  scanAll(files, verbose: verbose, verify: verify);
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_canonicalizer.dart b/pkg/front_end/lib/src/fasta/scanner/string_canonicalizer.dart
deleted file mode 100644
index 3467c53..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/string_canonicalizer.dart
+++ /dev/null
@@ -1,123 +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.
-
-library fasta.scanner.string_canonicalizer;
-
-import 'dart:convert';
-
-class Node {
-  dynamic /* String | List<int> */ data;
-  int start;
-  int end;
-  String payload;
-  Node next;
-  Node(this.data, this.start, this.end, this.payload, this.next);
-}
-
-/// A hash table for triples:
-/// (list of bytes, start, end) --> canonicalized string
-/// Using triples avoids allocating string slices before checking if they
-/// are canonical.
-///
-/// Gives about 3% speedup on dart2js.
-class StringCanonicalizer {
-  /// Mask away top bits to keep hash calculation within 32-bit SMI range.
-  static const int MASK = 16 * 1024 * 1024 - 1;
-
-  static const int INITIAL_SIZE = 8 * 1024;
-
-  /// Linear size of a hash table.
-  int _size = INITIAL_SIZE;
-
-  /// Items in a hash table.
-  int _count = 0;
-
-  /// The table itself.
-  List<Node> _nodes = new List<Node>(INITIAL_SIZE);
-
-  static String decode(List<int> data, int start, int end, bool asciiOnly) {
-    String s;
-    if (asciiOnly) {
-      s = new String.fromCharCodes(data, start, end);
-    } else {
-      s = new Utf8Decoder(allowMalformed: true).convert(data, start, end);
-    }
-    return s;
-  }
-
-  static int hashBytes(List<int> data, int start, int end) {
-    int h = 5381;
-    for (int i = start; i < end; i++) {
-      h = ((h << 5) + h + data[i]) & MASK;
-    }
-    return h;
-  }
-
-  static int hashString(String data, int start, int end) {
-    int h = 5381;
-    for (int i = start; i < end; i++) {
-      h = ((h << 5) + h + data.codeUnitAt(i)) & MASK;
-    }
-    return h;
-  }
-
-  rehash() {
-    int newSize = _size * 2;
-    List<Node> newNodes = new List<Node>(newSize);
-    for (int i = 0; i < _size; i++) {
-      Node t = _nodes[i];
-      while (t != null) {
-        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];
-        t.next = s;
-        newNodes[newIndex] = t;
-        t = n;
-      }
-    }
-    _size = newSize;
-    _nodes = newNodes;
-  }
-
-  String canonicalize(data, int start, int end, bool asciiOnly) {
-    if (_count > _size) rehash();
-    int index = data is String
-        ? hashString(data, start, end)
-        : hashBytes(data, start, end);
-    index = index & (_size - 1);
-    Node s = _nodes[index];
-    Node t = s;
-    int len = end - start;
-    while (t != null) {
-      if (t.end - t.start == len) {
-        int i = start, j = t.start;
-        while (i < end && data[i] == t.data[j]) {
-          i++;
-          j++;
-        }
-        if (i == end) {
-          return t.payload;
-        }
-      }
-      t = t.next;
-    }
-    String payload;
-    if (data is String) {
-      payload = data.substring(start, end);
-    } else {
-      payload = decode(data, start, end, asciiOnly);
-    }
-    _nodes[index] = new Node(data, start, end, payload, s);
-    _count++;
-    return payload;
-  }
-
-  clear() {
-    _size = INITIAL_SIZE;
-    _nodes = new List<Node>(_size);
-    _count = 0;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
deleted file mode 100644
index eab5cbc..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library dart2js.scanner.string_scanner;
-
-import '../../scanner/token.dart' show Token, SyntheticStringToken, TokenType;
-
-import '../../scanner/token.dart' as analyzer show StringToken;
-
-import 'abstract_scanner.dart'
-    show AbstractScanner, LanguageVersionChanged, ScannerConfiguration;
-
-import 'token.dart'
-    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
-
-import 'error_token.dart' show ErrorToken;
-
-/**
- * Scanner that reads from a String and creates tokens that points to
- * substrings.
- */
-class StringScanner extends AbstractScanner {
-  /** The file content. */
-  String string;
-
-  /** The current offset in [string]. */
-  int scanOffset = -1;
-
-  StringScanner(String string,
-      {ScannerConfiguration configuration,
-      bool includeComments: false,
-      LanguageVersionChanged languageVersionChanged})
-      : string = ensureZeroTermination(string),
-        super(configuration, includeComments, languageVersionChanged);
-
-  static String ensureZeroTermination(String string) {
-    return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
-        // TODO(lry): abort instead of copying the array, or warn?
-        ? string + '\x00'
-        : string;
-  }
-
-  static bool isLegalIdentifier(String identifier) {
-    StringScanner scanner = new StringScanner(identifier);
-    Token startToken = scanner.tokenize();
-    return startToken is! ErrorToken && startToken.next.isEof;
-  }
-
-  int advance() => string.codeUnitAt(++scanOffset);
-  int peek() => string.codeUnitAt(scanOffset + 1);
-
-  int get stringOffset => scanOffset;
-
-  int currentAsUnicode(int next) => next;
-
-  void handleUnicode(int startScanOffset) {}
-
-  @override
-  analyzer.StringToken createSubstringToken(
-      TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new StringToken.fromSubstring(
-        type, string, start, scanOffset + extraOffset, tokenStart,
-        canonicalize: true, precedingComments: comments);
-  }
-
-  @override
-  analyzer.StringToken createSyntheticSubstringToken(
-      TokenType type, int start, bool asciiOnly, String syntheticChars) {
-    String source = string.substring(start, scanOffset);
-    return new SyntheticStringToken(
-        type, source + syntheticChars, tokenStart, source.length);
-  }
-
-  @override
-  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new CommentToken.fromSubstring(
-        type, string, start, scanOffset + extraOffset, tokenStart,
-        canonicalize: true);
-  }
-
-  @override
-  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new DartDocToken.fromSubstring(
-        type, string, start, scanOffset + extraOffset, tokenStart,
-        canonicalize: true);
-  }
-
-  @override
-  LanguageVersionToken createLanguageVersionToken(
-      int start, int major, int minor) {
-    return new LanguageVersionToken.fromSubstring(
-        string, start, scanOffset, tokenStart, major, minor,
-        canonicalize: true);
-  }
-
-  bool atEndOfFile() => scanOffset >= string.length - 1;
-}
diff --git a/pkg/front_end/lib/src/fasta/scanner/token.dart b/pkg/front_end/lib/src/fasta/scanner/token.dart
deleted file mode 100644
index 5a4e990..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/token.dart
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.scanner.token;
-
-import '../../scanner/token.dart' as analyzer;
-import '../../scanner/token.dart' show Token, TokenType;
-
-import 'token_constants.dart' show IDENTIFIER_TOKEN;
-
-import 'string_canonicalizer.dart';
-
-/**
- * A String-valued token. Represents identifiers, string literals,
- * number literals, comments, and error tokens, using the corresponding
- * precedence info.
- */
-class StringToken extends analyzer.SimpleToken implements analyzer.StringToken {
-  /**
-   * The length threshold above which substring tokens are computed lazily.
-   *
-   * For string tokens that are substrings of the program source, the actual
-   * substring extraction is performed lazily. This is beneficial because
-   * not all scanned code are actually used. For unused parts, the substrings
-   * are never computed and allocated.
-   */
-  static const int LAZY_THRESHOLD = 4;
-
-  dynamic /* String | LazySubstring */ valueOrLazySubstring;
-
-  /**
-   * Creates a non-lazy string token. If [canonicalize] is true, the string
-   * is canonicalized before the token is created.
-   */
-  StringToken.fromString(TokenType type, String value, int charOffset,
-      {bool canonicalize: false, analyzer.CommentToken precedingComments})
-      : valueOrLazySubstring =
-            canonicalizedString(value, 0, value.length, canonicalize),
-        super(type, charOffset, precedingComments);
-
-  /**
-   * Creates a lazy string token. If [canonicalize] is true, the string
-   * is canonicalized before the token is created.
-   */
-  StringToken.fromSubstring(
-      TokenType type, String data, int start, int end, int charOffset,
-      {bool canonicalize: false, analyzer.CommentToken precedingComments})
-      : super(type, charOffset, precedingComments) {
-    int length = end - start;
-    if (length <= LAZY_THRESHOLD) {
-      valueOrLazySubstring =
-          canonicalizedString(data, start, end, canonicalize);
-    } else {
-      valueOrLazySubstring =
-          new _LazySubstring(data, start, length, canonicalize);
-    }
-  }
-
-  /**
-   * Creates a lazy string token. If [asciiOnly] is false, the byte array
-   * is passed through a UTF-8 decoder.
-   */
-  StringToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
-      bool asciiOnly, int charOffset,
-      {analyzer.CommentToken precedingComments})
-      : super(type, charOffset, precedingComments) {
-    int length = end - start;
-    if (length <= LAZY_THRESHOLD) {
-      valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly);
-    } else {
-      valueOrLazySubstring = new _LazySubstring(data, start, length, asciiOnly);
-    }
-  }
-
-  StringToken._(TokenType type, this.valueOrLazySubstring, int charOffset,
-      [analyzer.CommentToken precedingComments])
-      : super(type, charOffset, precedingComments);
-
-  @override
-  String get lexeme {
-    if (valueOrLazySubstring is String) {
-      return valueOrLazySubstring;
-    } else {
-      assert(valueOrLazySubstring is _LazySubstring);
-      dynamic data = valueOrLazySubstring.data;
-      int start = valueOrLazySubstring.start;
-      int end = start + valueOrLazySubstring.length;
-      if (data is String) {
-        valueOrLazySubstring = canonicalizedString(
-            data, start, end, valueOrLazySubstring.boolValue);
-      } else {
-        valueOrLazySubstring =
-            decodeUtf8(data, start, end, valueOrLazySubstring.boolValue);
-      }
-      return valueOrLazySubstring;
-    }
-  }
-
-  @override
-  bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN);
-
-  @override
-  String toString() => lexeme;
-
-  static final StringCanonicalizer canonicalizer = new StringCanonicalizer();
-
-  static String canonicalizedString(
-      String s, int start, int end, bool canonicalize) {
-    if (!canonicalize) return s;
-    return canonicalizer.canonicalize(s, start, end, false);
-  }
-
-  static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
-    return canonicalizer.canonicalize(data, start, end, asciiOnly);
-  }
-
-  @override
-  Token copy() => new StringToken._(
-      type, valueOrLazySubstring, charOffset, copyComments(precedingComments));
-
-  @override
-  String value() => lexeme;
-}
-
-/**
- * A String-valued token that does not exist in the original source.
- */
-class SyntheticStringToken extends StringToken
-    implements analyzer.SyntheticStringToken {
-  SyntheticStringToken(TokenType type, String value, int offset,
-      [analyzer.CommentToken precedingComments])
-      : super._(type, value, offset, precedingComments);
-
-  @override
-  int get length => 0;
-
-  @override
-  Token copy() => new SyntheticStringToken(
-      type, valueOrLazySubstring, offset, copyComments(precedingComments));
-}
-
-class CommentToken extends StringToken implements analyzer.CommentToken {
-  @override
-  analyzer.SimpleToken parent;
-
-  /**
-   * Creates a lazy comment token. If [canonicalize] is true, the string
-   * is canonicalized before the token is created.
-   */
-  CommentToken.fromSubstring(
-      TokenType type, String data, int start, int end, int charOffset,
-      {bool canonicalize: false})
-      : super.fromSubstring(type, data, start, end, charOffset,
-            canonicalize: canonicalize);
-
-  /**
-   * Creates a non-lazy comment token.
-   */
-  CommentToken.fromString(TokenType type, String lexeme, int charOffset)
-      : super.fromString(type, lexeme, charOffset);
-
-  /**
-   * Creates a lazy string token. If [asciiOnly] is false, the byte array
-   * is passed through a UTF-8 decoder.
-   */
-  CommentToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
-      bool asciiOnly, int charOffset)
-      : super.fromUtf8Bytes(type, data, start, end, asciiOnly, charOffset);
-
-  CommentToken._(TokenType type, valueOrLazySubstring, int charOffset)
-      : super._(type, valueOrLazySubstring, charOffset);
-
-  @override
-  CommentToken copy() =>
-      new CommentToken._(type, valueOrLazySubstring, charOffset);
-
-  @override
-  void remove() {
-    if (previous != null) {
-      previous.setNextWithoutSettingPrevious(next);
-      next?.previous = previous;
-    } else {
-      assert(parent.precedingComments == this);
-      parent.precedingComments = next as CommentToken;
-    }
-  }
-}
-
-/**
- * A specialized comment token representing a language version
- * (e.g. '// @dart = 2.1').
- */
-class LanguageVersionToken extends CommentToken {
-  /**
-   * The major language version.
-   */
-  int major;
-
-  /**
-   * The minor language version.
-   */
-  int minor;
-
-  LanguageVersionToken.from(String text, int offset, this.major, this.minor)
-      : super.fromString(TokenType.SINGLE_LINE_COMMENT, text, offset);
-
-  LanguageVersionToken.fromSubstring(
-      String string, int start, int end, int tokenStart, this.major, this.minor,
-      {bool canonicalize})
-      : super.fromSubstring(
-            TokenType.SINGLE_LINE_COMMENT, string, start, end, tokenStart,
-            canonicalize: canonicalize);
-
-  LanguageVersionToken.fromUtf8Bytes(List<int> bytes, int start, int end,
-      int tokenStart, this.major, this.minor)
-      : super.fromUtf8Bytes(
-            TokenType.SINGLE_LINE_COMMENT, bytes, start, end, true, tokenStart);
-
-  @override
-  LanguageVersionToken copy() =>
-      new LanguageVersionToken.from(lexeme, offset, major, minor);
-}
-
-class DartDocToken extends CommentToken
-    implements analyzer.DocumentationCommentToken {
-  /**
-   * Creates a lazy comment token. If [canonicalize] is true, the string
-   * is canonicalized before the token is created.
-   */
-  DartDocToken.fromSubstring(
-      TokenType type, String data, int start, int end, int charOffset,
-      {bool canonicalize: false})
-      : super.fromSubstring(type, data, start, end, charOffset,
-            canonicalize: canonicalize);
-
-  /**
-   * Creates a lazy string token. If [asciiOnly] is false, the byte array
-   * is passed through a UTF-8 decoder.
-   */
-  DartDocToken.fromUtf8Bytes(TokenType type, List<int> data, int start, int end,
-      bool asciiOnly, int charOffset)
-      : super.fromUtf8Bytes(type, data, start, end, asciiOnly, charOffset);
-
-  DartDocToken._(TokenType type, valueOrLazySubstring, int charOffset)
-      : super._(type, valueOrLazySubstring, charOffset);
-
-  @override
-  DartDocToken copy() =>
-      new DartDocToken._(type, valueOrLazySubstring, charOffset);
-}
-
-/**
- * This class represents the necessary information to compute a substring
- * lazily. The substring can either originate from a string or from
- * a [:List<int>:] of UTF-8 bytes.
- */
-abstract class _LazySubstring {
-  /** The original data, either a string or a List<int> */
-  get data;
-
-  int get start;
-  int get length;
-
-  /**
-   * If this substring is based on a String, the [boolValue] indicates whether
-   * the resulting substring should be canonicalized.
-   *
-   * For substrings based on a byte array, the [boolValue] is true if the
-   * array only holds ASCII characters. The resulting substring will be
-   * canonicalized after decoding.
-   */
-  bool get boolValue;
-
-  _LazySubstring.internal();
-
-  factory _LazySubstring(data, int start, int length, bool b) {
-    // See comment on [CompactLazySubstring].
-    if (start < 0x100000 && length < 0x200) {
-      int fields = (start << 9);
-      fields = fields | length;
-      fields = fields << 1;
-      if (b) fields |= 1;
-      return new _CompactLazySubstring(data, fields);
-    } else {
-      return new _FullLazySubstring(data, start, length, b);
-    }
-  }
-}
-
-/**
- * This class encodes [start], [length] and [boolValue] in a single
- * 30 bit integer. It uses 20 bits for [start], which covers source files
- * of 1MB. [length] has 9 bits, which covers 512 characters.
- *
- * The file html_dart2js.dart is currently around 1MB.
- */
-class _CompactLazySubstring extends _LazySubstring {
-  final dynamic data;
-  final int fields;
-
-  _CompactLazySubstring(this.data, this.fields) : super.internal();
-
-  int get start => fields >> 10;
-  int get length => (fields >> 1) & 0x1ff;
-  bool get boolValue => (fields & 1) == 1;
-}
-
-class _FullLazySubstring extends _LazySubstring {
-  final dynamic data;
-  final int start;
-  final int length;
-  final bool boolValue;
-  _FullLazySubstring(this.data, this.start, this.length, this.boolValue)
-      : super.internal();
-}
-
-bool isUserDefinableOperator(String value) {
-  return isBinaryOperator(value) ||
-      isMinusOperator(value) ||
-      isTernaryOperator(value) ||
-      isUnaryOperator(value);
-}
-
-bool isUnaryOperator(String value) => identical(value, "~");
-
-bool isBinaryOperator(String value) {
-  return identical(value, "==") ||
-      identical(value, "[]") ||
-      identical(value, "*") ||
-      identical(value, "/") ||
-      identical(value, "%") ||
-      identical(value, "~/") ||
-      identical(value, "+") ||
-      identical(value, "<<") ||
-      identical(value, ">>") ||
-      identical(value, ">>>") ||
-      identical(value, ">=") ||
-      identical(value, ">") ||
-      identical(value, "<=") ||
-      identical(value, "<") ||
-      identical(value, "&") ||
-      identical(value, "^") ||
-      identical(value, "|");
-}
-
-bool isTernaryOperator(String value) => identical(value, "[]=");
-
-bool isMinusOperator(String value) => identical(value, "-");
diff --git a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart b/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
deleted file mode 100644
index f8cc645..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/token_constants.dart
+++ /dev/null
@@ -1,94 +0,0 @@
-// 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.
-
-library fasta.scanner.token_constants;
-
-import 'characters.dart';
-
-const int EOF_TOKEN = 0;
-
-const int KEYWORD_TOKEN = $k;
-const int IDENTIFIER_TOKEN = $a;
-const int SCRIPT_TOKEN = $b;
-const int BAD_INPUT_TOKEN = $X;
-const int DOUBLE_TOKEN = $d;
-const int INT_TOKEN = $i;
-const int RECOVERY_TOKEN = $r;
-const int HEXADECIMAL_TOKEN = $x;
-const int STRING_TOKEN = $SQ;
-
-const int AMPERSAND_TOKEN = $AMPERSAND;
-const int BACKPING_TOKEN = $BACKPING;
-const int BACKSLASH_TOKEN = $BACKSLASH;
-const int BANG_TOKEN = $BANG;
-const int BAR_TOKEN = $BAR;
-const int COLON_TOKEN = $COLON;
-const int COMMA_TOKEN = $COMMA;
-const int EQ_TOKEN = $EQ;
-const int GT_TOKEN = $GT;
-const int HASH_TOKEN = $HASH;
-const int OPEN_CURLY_BRACKET_TOKEN = $OPEN_CURLY_BRACKET;
-const int OPEN_SQUARE_BRACKET_TOKEN = $OPEN_SQUARE_BRACKET;
-const int OPEN_PAREN_TOKEN = $OPEN_PAREN;
-const int LT_TOKEN = $LT;
-const int MINUS_TOKEN = $MINUS;
-const int PERIOD_TOKEN = $PERIOD;
-const int PLUS_TOKEN = $PLUS;
-const int QUESTION_TOKEN = $QUESTION;
-const int AT_TOKEN = $AT;
-const int CLOSE_CURLY_BRACKET_TOKEN = $CLOSE_CURLY_BRACKET;
-const int CLOSE_SQUARE_BRACKET_TOKEN = $CLOSE_SQUARE_BRACKET;
-const int CLOSE_PAREN_TOKEN = $CLOSE_PAREN;
-const int SEMICOLON_TOKEN = $SEMICOLON;
-const int SLASH_TOKEN = $SLASH;
-const int TILDE_TOKEN = $TILDE;
-const int STAR_TOKEN = $STAR;
-const int PERCENT_TOKEN = $PERCENT;
-const int CARET_TOKEN = $CARET;
-
-const int STRING_INTERPOLATION_TOKEN = 128;
-const int LT_EQ_TOKEN = STRING_INTERPOLATION_TOKEN + 1;
-const int FUNCTION_TOKEN = LT_EQ_TOKEN + 1;
-const int SLASH_EQ_TOKEN = FUNCTION_TOKEN + 1;
-const int PERIOD_PERIOD_PERIOD_TOKEN = SLASH_EQ_TOKEN + 1;
-const int PERIOD_PERIOD_TOKEN = PERIOD_PERIOD_PERIOD_TOKEN + 1;
-const int EQ_EQ_EQ_TOKEN = PERIOD_PERIOD_TOKEN + 1;
-const int EQ_EQ_TOKEN = EQ_EQ_EQ_TOKEN + 1;
-const int LT_LT_EQ_TOKEN = EQ_EQ_TOKEN + 1;
-const int LT_LT_TOKEN = LT_LT_EQ_TOKEN + 1;
-const int GT_EQ_TOKEN = LT_LT_TOKEN + 1;
-const int GT_GT_EQ_TOKEN = GT_EQ_TOKEN + 1;
-const int INDEX_EQ_TOKEN = GT_GT_EQ_TOKEN + 1;
-const int INDEX_TOKEN = INDEX_EQ_TOKEN + 1;
-const int BANG_EQ_EQ_TOKEN = INDEX_TOKEN + 1;
-const int BANG_EQ_TOKEN = BANG_EQ_EQ_TOKEN + 1;
-const int AMPERSAND_AMPERSAND_TOKEN = BANG_EQ_TOKEN + 1;
-const int AMPERSAND_AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_TOKEN + 1;
-const int AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_EQ_TOKEN + 1;
-const int BAR_BAR_TOKEN = AMPERSAND_EQ_TOKEN + 1;
-const int BAR_BAR_EQ_TOKEN = BAR_BAR_TOKEN + 1;
-const int BAR_EQ_TOKEN = BAR_BAR_EQ_TOKEN + 1;
-const int STAR_EQ_TOKEN = BAR_EQ_TOKEN + 1;
-const int PLUS_PLUS_TOKEN = STAR_EQ_TOKEN + 1;
-const int PLUS_EQ_TOKEN = PLUS_PLUS_TOKEN + 1;
-const int MINUS_MINUS_TOKEN = PLUS_EQ_TOKEN + 1;
-const int MINUS_EQ_TOKEN = MINUS_MINUS_TOKEN + 1;
-const int TILDE_SLASH_EQ_TOKEN = MINUS_EQ_TOKEN + 1;
-const int TILDE_SLASH_TOKEN = TILDE_SLASH_EQ_TOKEN + 1;
-const int PERCENT_EQ_TOKEN = TILDE_SLASH_TOKEN + 1;
-const int GT_GT_TOKEN = PERCENT_EQ_TOKEN + 1;
-const int CARET_EQ_TOKEN = GT_GT_TOKEN + 1;
-const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1;
-const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1;
-const int QUESTION_PERIOD_TOKEN = STRING_INTERPOLATION_IDENTIFIER_TOKEN + 1;
-const int QUESTION_QUESTION_TOKEN = QUESTION_PERIOD_TOKEN + 1;
-const int QUESTION_QUESTION_EQ_TOKEN = QUESTION_QUESTION_TOKEN + 1;
-const int GENERIC_METHOD_TYPE_ASSIGN_TOKEN = QUESTION_QUESTION_EQ_TOKEN + 1;
-const int GENERIC_METHOD_TYPE_LIST_TOKEN = GENERIC_METHOD_TYPE_ASSIGN_TOKEN + 1;
-const int GT_GT_GT_TOKEN = GENERIC_METHOD_TYPE_LIST_TOKEN + 1;
-const int PERIOD_PERIOD_PERIOD_QUESTION_TOKEN = GT_GT_GT_TOKEN + 1;
-const int GT_GT_GT_EQ_TOKEN = PERIOD_PERIOD_PERIOD_QUESTION_TOKEN + 1;
-const int QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN = GT_GT_GT_EQ_TOKEN + 1;
-const int QUESTION_PERIOD_PERIOD_TOKEN =
-    QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN + 1;
diff --git a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
deleted file mode 100644
index 528e5b7..0000000
--- a/pkg/front_end/lib/src/fasta/scanner/utf8_bytes_scanner.dart
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.scanner.utf8_bytes_scanner;
-
-import 'dart:convert' show unicodeBomCharacterRune, utf8;
-
-import '../../scanner/token.dart' show SyntheticStringToken, TokenType;
-
-import '../../scanner/token.dart' as analyzer show StringToken;
-
-import '../scanner.dart' show unicodeReplacementCharacter;
-
-import 'abstract_scanner.dart'
-    show AbstractScanner, LanguageVersionChanged, ScannerConfiguration;
-
-import 'token.dart'
-    show CommentToken, DartDocToken, LanguageVersionToken, StringToken;
-
-/**
- * Scanner that reads from a UTF-8 encoded list of bytes and creates tokens
- * that points to substrings.
- */
-class Utf8BytesScanner extends AbstractScanner {
-  /**
-   * The file content.
-   *
-   * The content is zero-terminated.
-   */
-  List<int> bytes;
-
-  /**
-   * Points to the offset of the last byte returned by [advance].
-   *
-   * After invoking [currentAsUnicode], the [byteOffset] points to the last
-   * byte that is part of the (unicode or ASCII) character. That way, [advance]
-   * can always increase the byte offset by 1.
-   */
-  int byteOffset = -1;
-
-  /**
-   * The getter [scanOffset] is expected to return the index where the current
-   * character *starts*. In case of a non-ascii character, after invoking
-   * [currentAsUnicode], the byte offset points to the *last* byte.
-   *
-   * This field keeps track of the number of bytes for the current unicode
-   * character. For example, if bytes 7,8,9 encode one unicode character, the
-   * [byteOffset] is 9 (after invoking [currentAsUnicode]). The [scanSlack]
-   * will be 2, so that [scanOffset] returns 7.
-   */
-  int scanSlack = 0;
-
-  /**
-   * Holds the [byteOffset] value for which the current [scanSlack] is valid.
-   */
-  int scanSlackOffset = -1;
-
-  /**
-   * Returns the byte offset of the first byte that belongs to the current
-   * character.
-   */
-  int get scanOffset {
-    if (byteOffset == scanSlackOffset) {
-      return byteOffset - scanSlack;
-    } else {
-      return byteOffset;
-    }
-  }
-
-  /**
-   * The difference between the number of bytes and the number of corresponding
-   * string characters, up to the current [byteOffset].
-   */
-  int utf8Slack = 0;
-
-  /**
-   * Creates a new Utf8BytesScanner. The source file is expected to be a
-   * [Utf8BytesSourceFile] that holds a list of UTF-8 bytes. Otherwise the
-   * string text of the source file is decoded.
-   *
-   * The list of UTF-8 bytes [file.slowUtf8Bytes()] is expected to return an
-   * array whose last element is '0' to signal the end of the file. If this
-   * is not the case, the entire array is copied before scanning.
-   */
-  Utf8BytesScanner(this.bytes,
-      {ScannerConfiguration configuration,
-      bool includeComments: false,
-      LanguageVersionChanged languageVersionChanged})
-      : super(configuration, includeComments, languageVersionChanged,
-            numberOfBytesHint: bytes.length) {
-    assert(bytes.last == 0);
-    // Skip a leading BOM.
-    if (containsBomAt(0)) byteOffset += 3;
-  }
-
-  bool containsBomAt(int offset) {
-    const List<int> BOM_UTF8 = const [0xEF, 0xBB, 0xBF];
-
-    return offset + 3 < bytes.length &&
-        bytes[offset] == BOM_UTF8[0] &&
-        bytes[offset + 1] == BOM_UTF8[1] &&
-        bytes[offset + 2] == BOM_UTF8[2];
-  }
-
-  int advance() => bytes[++byteOffset];
-
-  int peek() => bytes[byteOffset + 1];
-
-  /// Returns the unicode code point starting at the byte offset [startOffset]
-  /// with the byte [nextByte].
-  int nextCodePoint(int startOffset, int nextByte) {
-    int expectedHighBytes;
-    if (nextByte < 0xC2) {
-      expectedHighBytes = 1; // Bad code unit.
-    } else if (nextByte < 0xE0) {
-      expectedHighBytes = 2;
-    } else if (nextByte < 0xF0) {
-      expectedHighBytes = 3;
-    } else if (nextByte < 0xF5) {
-      expectedHighBytes = 4;
-    } else {
-      expectedHighBytes = 1; // Bad code unit.
-    }
-    int numBytes = 0;
-    for (int i = 0; i < expectedHighBytes; i++) {
-      if (bytes[byteOffset + i] < 0x80) {
-        break;
-      }
-      numBytes++;
-    }
-    int end = startOffset + numBytes;
-    byteOffset = end - 1;
-    if (expectedHighBytes == 1 || numBytes != expectedHighBytes) {
-      return unicodeReplacementCharacter;
-    }
-    // TODO(lry): measurably slow, decode creates first a Utf8Decoder and a
-    // _Utf8Decoder instance. Also the sublist is eagerly allocated.
-    String codePoint =
-        utf8.decode(bytes.sublist(startOffset, end), allowMalformed: true);
-    if (codePoint.length == 0) {
-      // The UTF-8 decoder discards leading BOM characters.
-      // TODO(floitsch): don't just assume that removed characters were the
-      // BOM.
-      assert(containsBomAt(startOffset));
-      codePoint = new String.fromCharCode(unicodeBomCharacterRune);
-    }
-    if (codePoint.length == 1) {
-      utf8Slack += (numBytes - 1);
-      scanSlack = numBytes - 1;
-      scanSlackOffset = byteOffset;
-      return codePoint.codeUnitAt(0);
-    } else if (codePoint.length == 2) {
-      utf8Slack += (numBytes - 2);
-      scanSlack = numBytes - 1;
-      scanSlackOffset = byteOffset;
-      stringOffsetSlackOffset = byteOffset;
-      // In case of a surrogate pair, return a single code point.
-      // Gracefully degrade given invalid UTF-8.
-      RuneIterator runes = codePoint.runes.iterator;
-      if (!runes.moveNext()) return unicodeReplacementCharacter;
-      int codeUnit = runes.current;
-      return !runes.moveNext() ? codeUnit : unicodeReplacementCharacter;
-    } else {
-      return unicodeReplacementCharacter;
-    }
-  }
-
-  int lastUnicodeOffset = -1;
-  int currentAsUnicode(int next) {
-    if (next < 128) return next;
-    // Check if currentAsUnicode was already invoked.
-    if (byteOffset == lastUnicodeOffset) return next;
-    int res = nextCodePoint(byteOffset, next);
-    lastUnicodeOffset = byteOffset;
-    return res;
-  }
-
-  void handleUnicode(int startScanOffset) {
-    int end = byteOffset;
-    // TODO(lry): this measurably slows down the scanner for files with unicode.
-    String s =
-        utf8.decode(bytes.sublist(startScanOffset, end), allowMalformed: true);
-    utf8Slack += (end - startScanOffset) - s.length;
-  }
-
-  /**
-   * This field remembers the byte offset of the last character decoded with
-   * [nextCodePoint] that used two code units in UTF-16.
-   *
-   * [nextCodePoint] returns a single code point for each unicode character,
-   * even if it needs two code units in UTF-16.
-   *
-   * For example, '\u{1d11e}' uses 4 bytes in UTF-8, and two code units in
-   * UTF-16. The [utf8Slack] is therefore 2. After invoking [nextCodePoint], the
-   * [byteOffset] points to the last (of 4) bytes. The [stringOffset] should
-   * return the offset of the first one, which is one position more left than
-   * the [utf8Slack].
-   */
-  int stringOffsetSlackOffset = -1;
-
-  int get stringOffset {
-    if (stringOffsetSlackOffset == byteOffset) {
-      return byteOffset - utf8Slack - 1;
-    } else {
-      return byteOffset - utf8Slack;
-    }
-  }
-
-  @override
-  analyzer.StringToken createSubstringToken(
-      TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new StringToken.fromUtf8Bytes(
-        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart,
-        precedingComments: comments);
-  }
-
-  @override
-  analyzer.StringToken createSyntheticSubstringToken(
-      TokenType type, int start, bool asciiOnly, String syntheticChars) {
-    String source = StringToken.decodeUtf8(bytes, start, byteOffset, asciiOnly);
-    return new SyntheticStringToken(
-        type, source + syntheticChars, tokenStart, source.length);
-  }
-
-  @override
-  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new CommentToken.fromUtf8Bytes(
-        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
-  }
-
-  @override
-  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
-      [int extraOffset = 0]) {
-    return new DartDocToken.fromUtf8Bytes(
-        type, bytes, start, byteOffset + extraOffset, asciiOnly, tokenStart);
-  }
-
-  @override
-  LanguageVersionToken createLanguageVersionToken(
-      int start, int major, int minor) {
-    return new LanguageVersionToken.fromUtf8Bytes(
-        bytes, start, byteOffset, tokenStart, major, minor);
-  }
-
-  bool atEndOfFile() => byteOffset >= bytes.length - 1;
-}
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 361ba43..f2e6550 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -13,6 +13,7 @@
 import 'builder/member_builder.dart';
 import 'builder/name_iterator.dart';
 import 'builder/type_variable_builder.dart';
+import 'kernel/body_builder.dart' show JumpTarget;
 
 import 'fasta_codes.dart'
     show
@@ -27,10 +28,10 @@
 
 class MutableScope {
   /// Names declared in this scope.
-  Map<String, Builder> local;
+  Map<String, Builder> _local;
 
   /// Setters declared in this scope.
-  Map<String, Builder> setters;
+  Map<String, MemberBuilder> _setters;
 
   /// The extensions declared in this scope.
   ///
@@ -61,20 +62,22 @@
   ///       Extension.staticMethod2();
   ///     }
   ///
-  List<ExtensionBuilder> _extensions;
+  Set<ExtensionBuilder> _extensions;
 
   /// The scope that this scope is nested within, or `null` if this is the top
   /// level scope.
-  Scope parent;
+  Scope _parent;
 
   final String classNameOrDebugName;
 
-  MutableScope(this.local, this.setters, this._extensions, this.parent,
+  MutableScope(this._local, this._setters, this._extensions, this._parent,
       this.classNameOrDebugName) {
     assert(classNameOrDebugName != null);
   }
 
-  String toString() => "Scope($classNameOrDebugName, ${local.keys})";
+  Scope get parent => _parent;
+
+  String toString() => "Scope($classNameOrDebugName, ${_local.keys})";
 }
 
 class Scope extends MutableScope {
@@ -82,40 +85,40 @@
   /// succeed.
   final bool isModifiable;
 
-  Map<String, Builder> labels;
+  Map<String, JumpTarget> labels;
 
-  Map<String, Builder> forwardDeclaredLabels;
+  Map<String, JumpTarget> forwardDeclaredLabels;
 
   Map<String, int> usedNames;
 
   Scope(
       {Map<String, Builder> local,
-      Map<String, Builder> setters,
-      List<ExtensionBuilder> extensions,
+      Map<String, MemberBuilder> setters,
+      Set<ExtensionBuilder> extensions,
       Scope parent,
       String debugName,
       this.isModifiable: true})
-      : super(local, setters = setters ?? const <String, Builder>{}, extensions,
-            parent, debugName);
+      : super(local, setters = setters ?? const <String, MemberBuilder>{},
+            extensions, parent, debugName);
 
   Scope.top({bool isModifiable: false})
       : this(
             local: <String, Builder>{},
-            setters: <String, Builder>{},
+            setters: <String, MemberBuilder>{},
             debugName: "top",
             isModifiable: isModifiable);
 
   Scope.immutable()
       : this(
             local: const <String, Builder>{},
-            setters: const <String, Builder>{},
+            setters: const <String, MemberBuilder>{},
             debugName: "immutable",
             isModifiable: false);
 
   Scope.nested(Scope parent, String debugName, {bool isModifiable: true})
       : this(
             local: <String, Builder>{},
-            setters: <String, Builder>{},
+            setters: <String, MemberBuilder>{},
             parent: parent,
             debugName: debugName,
             isModifiable: isModifiable);
@@ -130,8 +133,8 @@
 
   Scope copyWithParent(Scope parent, String debugName) {
     return new Scope(
-        local: super.local,
-        setters: super.setters,
+        local: super._local,
+        setters: super._setters,
         extensions: _extensions,
         parent: parent,
         debugName: debugName,
@@ -139,22 +142,16 @@
   }
 
   /// Don't use this. Use [becomePartOf] instead.
-  void set local(_) => unsupported("local=", -1, null);
-
-  /// Don't use this. Use [becomePartOf] instead.
-  void set setters(_) => unsupported("setters=", -1, null);
-
-  /// Don't use this. Use [becomePartOf] instead.
   void set parent(_) => unsupported("parent=", -1, null);
 
   /// This scope becomes equivalent to [scope]. This is used for parts to
   /// become part of their library's scope.
   void becomePartOf(Scope scope) {
-    assert(parent.parent == null);
-    assert(scope.parent.parent == null);
-    super.local = scope.local;
-    super.setters = scope.setters;
-    super.parent = scope.parent;
+    assert(_parent._parent == null);
+    assert(scope._parent._parent == null);
+    super._local = scope._local;
+    super._setters = scope._setters;
+    super._parent = scope._parent;
     super._extensions = scope._extensions;
   }
 
@@ -167,7 +164,7 @@
     Scope newScope =
         new Scope.nested(this, "type variables", isModifiable: false);
     for (TypeVariableBuilder t in typeVariables) {
-      newScope.local[t.name] = t;
+      newScope._local[t.name] = t;
     }
     return newScope;
   }
@@ -181,10 +178,10 @@
   ///     print("The answer is $x.");
   Scope createNestedLabelScope() {
     return new Scope(
-        local: local,
-        setters: setters,
+        local: _local,
+        setters: _setters,
         extensions: _extensions,
-        parent: parent,
+        parent: _parent,
         debugName: "label",
         isModifiable: true);
   }
@@ -214,9 +211,9 @@
       {bool isInstanceScope: true}) {
     recordUse(name, charOffset, fileUri);
     Builder builder =
-        lookupIn(name, charOffset, fileUri, local, isInstanceScope);
+        lookupIn(name, charOffset, fileUri, _local, isInstanceScope);
     if (builder != null) return builder;
-    builder = lookupIn(name, charOffset, fileUri, setters, isInstanceScope);
+    builder = lookupIn(name, charOffset, fileUri, _setters, isInstanceScope);
     if (builder != null && !builder.hasProblem) {
       return new AccessErrorBuilder(name, builder, charOffset, fileUri);
     }
@@ -224,16 +221,16 @@
       // For static lookup, do not search the parent scope.
       return builder;
     }
-    return builder ?? parent?.lookup(name, charOffset, fileUri);
+    return builder ?? _parent?.lookup(name, charOffset, fileUri);
   }
 
   Builder lookupSetter(String name, int charOffset, Uri fileUri,
       {bool isInstanceScope: true}) {
     recordUse(name, charOffset, fileUri);
     Builder builder =
-        lookupIn(name, charOffset, fileUri, setters, isInstanceScope);
+        lookupIn(name, charOffset, fileUri, _setters, isInstanceScope);
     if (builder != null) return builder;
-    builder = lookupIn(name, charOffset, fileUri, local, isInstanceScope);
+    builder = lookupIn(name, charOffset, fileUri, _local, isInstanceScope);
     if (builder != null && !builder.hasProblem) {
       return new AccessErrorBuilder(name, builder, charOffset, fileUri);
     }
@@ -241,14 +238,38 @@
       // For static lookup, do not search the parent scope.
       return builder;
     }
-    return builder ?? parent?.lookupSetter(name, charOffset, fileUri);
+    return builder ?? _parent?.lookupSetter(name, charOffset, fileUri);
   }
 
+  Builder lookupLocalMember(String name, {bool setter}) {
+    return setter ? _setters[name] : _local[name];
+  }
+
+  void addLocalMember(String name, Builder member, {bool setter}) {
+    if (setter) {
+      _setters[name] = member;
+    } else {
+      _local[name] = member;
+    }
+  }
+
+  void forEachLocalMember(void Function(String name, Builder member) f) {
+    _local.forEach(f);
+  }
+
+  void forEachLocalSetter(void Function(String name, Builder member) f) {
+    _setters.forEach(f);
+  }
+
+  Iterable<Builder> get localMembers => _local.values;
+
+  Iterable<MemberBuilder> get localSetters => _setters.values;
+
   bool hasLocalLabel(String name) => labels != null && labels.containsKey(name);
 
-  void declareLabel(String name, Builder target) {
+  void declareLabel(String name, JumpTarget target) {
     if (isModifiable) {
-      labels ??= <String, Builder>{};
+      labels ??= <String, JumpTarget>{};
       labels[name] = target;
     } else {
       internalProblem(
@@ -256,9 +277,9 @@
     }
   }
 
-  void forwardDeclareLabel(String name, Builder target) {
+  void forwardDeclareLabel(String name, JumpTarget target) {
     declareLabel(name, target);
-    forwardDeclaredLabels ??= <String, Builder>{};
+    forwardDeclaredLabels ??= <String, JumpTarget>{};
     forwardDeclaredLabels[name] = target;
   }
 
@@ -271,12 +292,12 @@
     return true;
   }
 
-  Map<String, Builder> get unclaimedForwardDeclarations {
+  Map<String, JumpTarget> get unclaimedForwardDeclarations {
     return forwardDeclaredLabels;
   }
 
   Builder lookupLabel(String name) {
-    return (labels == null ? null : labels[name]) ?? parent?.lookupLabel(name);
+    return (labels == null ? null : labels[name]) ?? _parent?.lookupLabel(name);
   }
 
   /// Declares that the meaning of [name] in this scope is [builder].
@@ -292,7 +313,7 @@
             .withArguments(name)
             .withLocation(fileUri, usedNames[name], name.length);
       }
-      local[name] = builder;
+      _local[name] = builder;
     } else {
       internalProblem(
           messageInternalProblemExtendingUnmodifiableScope, -1, null);
@@ -302,21 +323,21 @@
 
   /// Adds [builder] to the extensions in this scope.
   void addExtension(ExtensionBuilder builder) {
-    _extensions ??= [];
+    _extensions ??= <ExtensionBuilder>{};
     _extensions.add(builder);
   }
 
   /// Calls [f] for each extension in this scope and parent scopes.
   void forEachExtension(void Function(ExtensionBuilder) f) {
     _extensions?.forEach(f);
-    parent?.forEachExtension(f);
+    _parent?.forEachExtension(f);
   }
 
   void merge(
       Scope scope,
       Builder computeAmbiguousDeclaration(
           String name, Builder existing, Builder member)) {
-    Map<String, Builder> map = local;
+    Map<String, Builder> map = _local;
 
     void mergeMember(String name, Builder member) {
       Builder existing = map[name];
@@ -328,14 +349,14 @@
       map[name] = member;
     }
 
-    scope.local.forEach(mergeMember);
-    map = setters;
-    scope.setters.forEach(mergeMember);
+    scope._local.forEach(mergeMember);
+    map = _setters;
+    scope._setters.forEach(mergeMember);
   }
 
   void forEach(f(String name, Builder member)) {
-    local.forEach(f);
-    setters.forEach(f);
+    _local.forEach(f);
+    _setters.forEach(f);
   }
 
   String get debugString {
@@ -348,36 +369,36 @@
   }
 
   int writeOn(StringSink sink) {
-    int nestingLevel = (parent?.writeOn(sink) ?? -1) + 1;
+    int nestingLevel = (_parent?.writeOn(sink) ?? -1) + 1;
     String indent = "  " * nestingLevel;
     sink.writeln("$indent{");
-    local.forEach((String name, Builder member) {
+    _local.forEach((String name, Builder member) {
       sink.writeln("$indent  $name");
     });
-    setters.forEach((String name, Builder member) {
+    _setters.forEach((String name, Builder member) {
       sink.writeln("$indent  $name=");
     });
     return nestingLevel;
   }
 
   Scope computeMixinScope() {
-    List<String> names = this.local.keys.toList();
+    List<String> names = this._local.keys.toList();
     Map<String, Builder> local = <String, Builder>{};
     bool needsCopy = false;
     for (int i = 0; i < names.length; i++) {
       String name = names[i];
-      Builder declaration = this.local[name];
+      Builder declaration = this._local[name];
       if (declaration.isStatic) {
         needsCopy = true;
       } else {
         local[name] = declaration;
       }
     }
-    names = this.setters.keys.toList();
-    Map<String, Builder> setters = <String, Builder>{};
+    names = this._setters.keys.toList();
+    Map<String, MemberBuilder> setters = <String, MemberBuilder>{};
     for (int i = 0; i < names.length; i++) {
       String name = names[i];
-      Builder declaration = this.setters[name];
+      MemberBuilder declaration = this._setters[name];
       if (declaration.isStatic) {
         needsCopy = true;
       } else {
@@ -389,7 +410,7 @@
             local: local,
             setters: setters,
             extensions: _extensions,
-            parent: parent,
+            parent: _parent,
             debugName: classNameOrDebugName,
             isModifiable: isModifiable)
         : this;
@@ -422,24 +443,50 @@
   String toString() => "ConstructorScope($className, ${local.keys})";
 }
 
+abstract class LazyScope extends Scope {
+  LazyScope(Map<String, Builder> local, Map<String, MemberBuilder> setters,
+      Scope parent, String debugName, {bool isModifiable: true})
+      : super(
+            local: local,
+            setters: setters,
+            parent: parent,
+            debugName: debugName,
+            isModifiable: isModifiable);
+
+  /// Override this method to lazily populate the scope before access.
+  void ensureScope();
+
+  @override
+  Map<String, Builder> get _local {
+    ensureScope();
+    return super._local;
+  }
+
+  @override
+  Map<String, MemberBuilder> get _setters {
+    ensureScope();
+    return super._setters;
+  }
+}
+
 class ScopeBuilder {
   final Scope scope;
 
   ScopeBuilder(this.scope);
 
   void addMember(String name, Builder builder) {
-    scope.local[name] = builder;
+    scope._local[name] = builder;
   }
 
   void addSetter(String name, Builder builder) {
-    scope.setters[name] = builder;
+    scope._setters[name] = builder;
   }
 
   void addExtension(ExtensionBuilder builder) {
     scope.addExtension(builder);
   }
 
-  Builder operator [](String name) => scope.local[name];
+  Builder operator [](String name) => scope._local[name];
 }
 
 class ConstructorScopeBuilder {
@@ -550,12 +597,13 @@
       String name, Builder builder, int charOffset, Uri fileUri)
       : super(name, builder, charOffset, fileUri);
 
-  Member get target => null;
-
   Member get member => null;
 
   bool get isNative => false;
 
+  @override
+  bool get isAssignable => false;
+
   ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
 
   void set parent(Builder value) {
@@ -597,8 +645,8 @@
   Builder current;
 
   ScopeLocalDeclarationIterator(Scope scope)
-      : local = scope.local.values.iterator,
-        setters = scope.setters.values.iterator;
+      : local = scope._local.values.iterator,
+        setters = scope._setters.values.iterator;
 
   @override
   bool moveNext() {
@@ -633,8 +681,8 @@
   String name;
 
   ScopeLocalDeclarationNameIterator(Scope scope)
-      : localNames = scope.local.keys.iterator,
-        setterNames = scope.setters.keys.iterator,
+      : localNames = scope._local.keys.iterator,
+        setterNames = scope._setters.keys.iterator,
         super(scope);
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/severity.dart b/pkg/front_end/lib/src/fasta/severity.dart
deleted file mode 100644
index fd9b59e..0000000
--- a/pkg/front_end/lib/src/fasta/severity.dart
+++ /dev/null
@@ -1,43 +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.
-
-library fasta.severity;
-
-enum Severity {
-  context,
-  error,
-  ignored,
-  internalProblem,
-  warning,
-}
-
-const Map<String, String> severityEnumNames = const <String, String>{
-  'CONTEXT': 'context',
-  'ERROR': 'error',
-  'IGNORED': 'ignored',
-  'INTERNAL_PROBLEM': 'internalProblem',
-  'WARNING': 'warning',
-};
-
-const Map<String, Severity> severityEnumValues = const <String, Severity>{
-  'CONTEXT': Severity.context,
-  'ERROR': Severity.error,
-  'IGNORED': Severity.ignored,
-  'INTERNAL_PROBLEM': Severity.internalProblem,
-  'WARNING': Severity.warning,
-};
-
-const Map<Severity, String> severityPrefixes = const <Severity, String>{
-  Severity.error: "Error",
-  Severity.internalProblem: "Internal problem",
-  Severity.warning: "Warning",
-  Severity.context: "Context",
-};
-
-const Map<Severity, String> severityTexts = const <Severity, String>{
-  Severity.error: "error",
-  Severity.internalProblem: "internal problem",
-  Severity.warning: "warning",
-  Severity.context: "context",
-};
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 0ac91d5..a9638af 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -4,6 +4,11 @@
 
 library fasta.diet_listener;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show Assert, DeclarationKind, MemberKind, Parser, optional;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
 import 'package:kernel/ast.dart'
     show
         AsyncMarker,
@@ -20,11 +25,10 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-import '../../scanner/token.dart' show Token;
-
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/declaration_builder.dart';
+import '../builder/field_builder.dart';
 import '../builder/formal_parameter_builder.dart';
 import '../builder/function_builder.dart';
 import '../builder/function_type_builder.dart';
@@ -51,9 +55,6 @@
 
 import '../kernel/body_builder.dart' show BodyBuilder;
 
-import '../parser.dart'
-    show Assert, DeclarationKind, MemberKind, Parser, optional;
-
 import '../problems.dart'
     show DebugAbort, internalProblem, unexpected, unhandled;
 
@@ -63,7 +64,8 @@
 
 import '../source/value_kinds.dart';
 
-import '../type_inference/type_inference_engine.dart' show TypeInferenceEngine;
+import '../type_inference/type_inference_engine.dart'
+    show InferenceDataForTesting, TypeInferenceEngine;
 
 import '../type_inference/type_inferrer.dart' show TypeInferrer;
 
@@ -668,7 +670,8 @@
       {bool isDeclarationInstanceMember,
       VariableDeclaration extensionThis,
       List<TypeParameter> extensionTypeParameters,
-      Scope formalParameterScope}) {
+      Scope formalParameterScope,
+      InferenceDataForTesting inferenceDataForTesting}) {
     // Note: we set thisType regardless of whether we are building a static
     // member, since that provides better error recovery.
     // TODO(johnniwinther): Provide a dummy this on static extension methods
@@ -676,7 +679,7 @@
     InterfaceType thisType =
         extensionThis == null ? currentDeclaration?.thisType : null;
     TypeInferrer typeInferrer = typeInferenceEngine?.createLocalTypeInferrer(
-        uri, thisType, libraryBuilder);
+        uri, thisType, libraryBuilder, inferenceDataForTesting);
     ConstantContext constantContext = builder.isConstructor && builder.isConst
         ? ConstantContext.inferred
         : ConstantContext.none;
@@ -716,7 +719,7 @@
       ..constantContext = constantContext;
   }
 
-  StackListener createFunctionListener(FunctionBuilder builder) {
+  StackListener createFunctionListener(FunctionBuilderImpl builder) {
     final Scope typeParameterScope =
         builder.computeTypeParameterScope(memberScope);
     final Scope formalParameterScope =
@@ -727,7 +730,8 @@
         isDeclarationInstanceMember: builder.isDeclarationInstanceMember,
         extensionThis: builder.extensionThis,
         extensionTypeParameters: builder.extensionTypeParameters,
-        formalParameterScope: formalParameterScope);
+        formalParameterScope: formalParameterScope,
+        inferenceDataForTesting: builder.dataForTesting?.inferenceData);
   }
 
   void buildRedirectingFactoryMethod(
@@ -757,13 +761,14 @@
     checkEmpty(token.charOffset);
     if (names == null || currentClassIsParserRecovery) return;
 
-    Builder declaration = lookupBuilder(token, null, names.first);
+    FieldBuilderImpl declaration = lookupBuilder(token, null, names.first);
     // TODO(paulberry): don't re-parse the field if we've already parsed it
     // for type inference.
     parseFields(
         createListener(declaration, memberScope,
             isDeclarationInstanceMember:
-                declaration.isDeclarationInstanceMember),
+                declaration.isDeclarationInstanceMember,
+            inferenceDataForTesting: declaration.dataForTesting?.inferenceData),
         token,
         metadata,
         isTopLevel);
@@ -958,12 +963,14 @@
       }
 
       if (getOrSet != null && optional("set", getOrSet)) {
-        declaration = currentDeclaration.scope.setters[name];
+        declaration =
+            currentDeclaration.scope.lookupLocalMember(name, setter: true);
       } else {
-        declaration = currentDeclaration.scope.local[name];
+        declaration =
+            currentDeclaration.scope.lookupLocalMember(name, setter: false);
       }
     } else if (getOrSet != null && optional("set", getOrSet)) {
-      declaration = libraryBuilder.scope.setters[name];
+      declaration = libraryBuilder.scope.lookupLocalMember(name, setter: true);
     } else {
       declaration = libraryBuilder.scopeBuilder[name];
     }
diff --git a/pkg/front_end/lib/src/fasta/source/diet_parser.dart b/pkg/front_end/lib/src/fasta/source/diet_parser.dart
index bc98715..6bed46d 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_parser.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_parser.dart
@@ -4,9 +4,10 @@
 
 library fasta.diet_parser;
 
-import '../../scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
-import '../parser.dart' show ClassMemberParser, Listener, MemberKind;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show ClassMemberParser, Listener, MemberKind;
 
 // TODO(ahe): Move this to parser package.
 class DietParser extends ClassMemberParser {
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 13600f6..416c577 100644
--- a/pkg/front_end/lib/src/fasta/source/directive_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/directive_listener.dart
@@ -6,10 +6,10 @@
 /// import, part, and export directives.
 library front_end.src.fasta.source.directive_listener;
 
-import '../../scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 import '../fasta_codes.dart' show messageExpectedBlockToSkip;
-import '../parser/identifier_context.dart';
-import '../parser/listener.dart';
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart';
 import '../quote.dart';
 
 /// Listener that records imports, exports, and part directives.
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 ca92153..ea75e1c 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -4,6 +4,18 @@
 
 library fasta.outline_builder;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show
+        Assert,
+        DeclarationKind,
+        FormalParameterKind,
+        IdentifierContext,
+        lengthOfSpan,
+        MemberKind,
+        optional;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
 import 'package:kernel/ast.dart' show InvalidType, ProcedureKind, Variance;
 
 import '../builder/constructor_reference_builder.dart';
@@ -79,23 +91,10 @@
         operatorToString,
         operatorRequiredArgumentCount;
 
-import '../parser.dart'
-    show
-        Assert,
-        DeclarationKind,
-        FormalParameterKind,
-        IdentifierContext,
-        lengthOfSpan,
-        MemberKind,
-        offsetForToken,
-        optional;
-
 import '../problems.dart' show unhandled;
 
 import '../quote.dart' show unescapeString;
 
-import '../scanner.dart' show Token;
-
 import 'source_library_builder.dart'
     show
         TypeParameterScopeBuilder,
@@ -104,7 +103,12 @@
         SourceLibraryBuilder;
 
 import 'stack_listener.dart'
-    show FixedNullableList, NullValue, ParserRecovery, StackListener;
+    show
+        FixedNullableList,
+        NullValue,
+        ParserRecovery,
+        StackListener,
+        offsetForToken;
 
 import 'value_kinds.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 4fdb854..bfc1c29 100644
--- a/pkg/front_end/lib/src/fasta/source/scope_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/scope_listener.dart
@@ -4,7 +4,9 @@
 
 library fasta.scope_listener;
 
-import '../../scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/parser/block_kind.dart' show BlockKind;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
 
 import '../scope.dart' show Scope;
 
@@ -100,7 +102,7 @@
   }
 
   @override
-  void beginBlock(Token token) {
+  void beginBlock(Token token, BlockKind blockKind) {
     debugEvent("beginBlock");
     enterLocalScope("block");
   }
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 f55df6f..34cfbf5 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
@@ -26,7 +26,8 @@
     show
         Message,
         noLength,
-        templateBadTypeVariableInSupertype,
+        templateInvalidTypeVariableInSupertype,
+        templateInvalidTypeVariableInSupertypeWithVariance,
         templateConflictsWithConstructor,
         templateConflictsWithFactory,
         templateConflictsWithMember,
@@ -207,7 +208,7 @@
       }
     });
 
-    scope.setters.forEach((String name, Builder setter) {
+    scope.forEachLocalSetter((String name, Builder setter) {
       Builder member = scopeBuilder[name];
       if (member == null ||
           !(member.isField && !member.isFinal && !member.isConst ||
@@ -221,7 +222,7 @@
           member.charOffset, noLength);
     });
 
-    scope.setters.forEach((String name, Builder setter) {
+    scope.forEachLocalSetter((String name, Builder setter) {
       Builder constructor = constructorScopeBuilder[name];
       if (constructor == null || !setter.isStatic) return;
       addProblem(templateConflictsWithConstructor.withArguments(name),
@@ -238,10 +239,21 @@
     if (typeVariables == null || supertype == null) return supertype;
     Message message;
     for (int i = 0; i < typeVariables.length; ++i) {
-      int variance = computeVariance(typeVariables[i], supertype);
+      int variance = computeVariance(typeVariables[i], supertype, library);
       if (!Variance.greaterThanOrEqual(variance, typeVariables[i].variance)) {
-        message = templateBadTypeVariableInSupertype.withArguments(
-            typeVariables[i].name, supertype.name);
+        if (typeVariables[i].parameter.isLegacyCovariant) {
+          message = templateInvalidTypeVariableInSupertype.withArguments(
+              typeVariables[i].name,
+              Variance.keywordString(variance),
+              supertype.name);
+        } else {
+          message =
+              templateInvalidTypeVariableInSupertypeWithVariance.withArguments(
+                  Variance.keywordString(typeVariables[i].variance),
+                  typeVariables[i].name,
+                  Variance.keywordString(variance),
+                  supertype.name);
+        }
         library.addProblem(message, charOffset, noLength, fileUri);
       }
     }
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 118f28d..be48777 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
@@ -156,7 +156,7 @@
 
     scope.forEach(buildBuilders);
 
-    scope.setters.forEach((String name, Builder setter) {
+    scope.forEachLocalSetter((String name, Builder setter) {
       Builder member = scopeBuilder[name];
       if (member == null) {
         // Setter without getter.
@@ -194,14 +194,15 @@
       if (retainDataForTesting) {
         patchForTesting = patch;
       }
-      scope.local.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.local[name];
+      scope.forEachLocalMember((String name, Builder member) {
+        Builder memberPatch =
+            patch.scope.lookupLocalMember(name, setter: false);
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
       });
-      scope.setters.forEach((String name, Builder member) {
-        Builder memberPatch = patch.scope.setters[name];
+      scope.forEachLocalSetter((String name, Builder member) {
+        Builder memberPatch = patch.scope.lookupLocalMember(name, setter: true);
         if (memberPatch != null) {
           member.applyPatch(memberPatch);
         }
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 52f6b65..56fabe0 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
@@ -6,7 +6,13 @@
 
 import 'dart:convert' show jsonEncode;
 
-import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
+import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
+    show resolveRelativeUri;
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
@@ -28,6 +34,8 @@
         MapLiteral,
         Member,
         Name,
+        NeverType,
+        Nullability,
         Procedure,
         ProcedureKind,
         SetLiteral,
@@ -55,10 +63,6 @@
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 
-import '../../base/resolve_relative_uri.dart' show resolveRelativeUri;
-
-import '../../scanner/token.dart' show Token;
-
 import '../builder/builder.dart';
 import '../builder/builtin_type_builder.dart';
 import '../builder/class_builder.dart';
@@ -78,6 +82,7 @@
 import '../builder/mixin_application_builder.dart';
 import '../builder/name_iterator.dart';
 import '../builder/named_type_builder.dart';
+import '../builder/never_type_builder.dart';
 import '../builder/nullability_builder.dart';
 import '../builder/prefix_builder.dart';
 import '../builder/procedure_builder.dart';
@@ -166,6 +171,8 @@
         compareProcedures,
         toKernelCombinators;
 
+import '../kernel/kernel_shadow_ast.dart';
+
 import '../kernel/metadata_collector.dart';
 
 import '../kernel/type_algorithms.dart'
@@ -174,7 +181,8 @@
         computeVariance,
         findGenericFunctionTypes,
         getNonSimplicityIssuesForDeclaration,
-        getNonSimplicityIssuesForTypeVariables;
+        getNonSimplicityIssuesForTypeVariables,
+        pendingVariance;
 
 import '../loader.dart' show Loader;
 
@@ -196,8 +204,6 @@
 
 import '../scope.dart';
 
-import '../severity.dart' show Severity;
-
 import '../type_inference/type_inferrer.dart' show TypeInferrerImpl;
 
 import 'source_class_builder.dart' show SourceClassBuilder;
@@ -761,7 +767,7 @@
     }
     canAddImplementationBuilders = false;
 
-    scope.setters.forEach((String name, Builder setter) {
+    scope.forEachLocalSetter((String name, Builder setter) {
       Builder member = scopeBuilder[name];
       if (member == null ||
           !member.isField ||
@@ -1034,6 +1040,7 @@
         switch (name) {
           case "dynamic":
           case "void":
+          case "Never":
             unserializableExports ??= <String, String>{};
             unserializableExports[name] = null;
             break;
@@ -1057,8 +1064,11 @@
                 library.additionalExports.add(memberLast.typedef.reference);
               } else if (memberLast is ExtensionBuilder) {
                 library.additionalExports.add(memberLast.extension.reference);
+              } else if (memberLast is MemberBuilder) {
+                library.additionalExports.add(memberLast.member.reference);
               } else {
-                library.additionalExports.add(memberLast.target.reference);
+                unhandled('member', 'exportScope', memberLast.charOffset,
+                    memberLast.fileUri);
               }
             }
         }
@@ -1068,17 +1078,18 @@
 
   @override
   void addToScope(String name, Builder member, int charOffset, bool isImport) {
-    Map<String, Builder> map =
-        member.isSetter ? importScope.setters : importScope.local;
-    Builder existing = map[name];
+    Builder existing =
+        importScope.lookupLocalMember(name, setter: member.isSetter);
     if (existing != null) {
       if (existing != member) {
-        map[name] = computeAmbiguousDeclaration(
-            name, existing, member, charOffset,
-            isImport: isImport);
+        importScope.addLocalMember(
+            name,
+            computeAmbiguousDeclaration(name, existing, member, charOffset,
+                isImport: isImport),
+            setter: member.isSetter);
       }
     } else {
-      map[name] = member;
+      importScope.addLocalMember(name, member, setter: member.isSetter);
     }
     if (member.isExtension) {
       importScope.addExtension(member);
@@ -1154,6 +1165,14 @@
         "dynamic", new DynamicTypeBuilder(const DynamicType(), this, -1), -1);
   }
 
+  void addSyntheticDeclarationOfNever() {
+    addBuilder(
+        "Never",
+        new NeverTypeBuilder(
+            const NeverType(Nullability.nonNullable), this, -1),
+        -1);
+  }
+
   TypeBuilder addNamedType(Object name, NullabilityBuilder nullabilityBuilder,
       List<TypeBuilder> arguments, int charOffset) {
     return addType(
@@ -1584,6 +1603,14 @@
               }
             }
           }
+          List<TypeVariableBuilder> typeVariables = type.typeVariables;
+          if (typeVariables != null) {
+            for (TypeVariableBuilder variable in typeVariables) {
+              if (usesTypeVariables(variable.bound)) {
+                return true;
+              }
+            }
+          }
           return usesTypeVariables(type.returnType);
         }
         return false;
@@ -1749,7 +1776,9 @@
         metadata, type, name, modifiers, this, charOffset, charEndOffset);
     fieldBuilder.constInitializerToken = constInitializerToken;
     addBuilder(name, fieldBuilder, charOffset);
-    if (type == null && initializerToken != null) {
+    if (type == null && initializerToken != 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.
       fieldBuilder.field.type =
           new ImplicitFieldType(fieldBuilder, initializerToken);
       (implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
@@ -1969,9 +1998,8 @@
       FunctionTypeBuilder type,
       int charOffset) {
     if (typeVariables != null) {
-      for (int i = 0; i < typeVariables.length; ++i) {
-        TypeVariableBuilder variable = typeVariables[i];
-        variable.variance = computeVariance(variable, type);
+      for (TypeVariableBuilder typeVariable in typeVariables) {
+        typeVariable.variance = pendingVariance;
       }
     }
     TypeAliasBuilder typedefBuilder = new TypeAliasBuilder(
@@ -2179,7 +2207,7 @@
     Uri otherUri;
     Uri preferredUri;
     Uri hiddenUri;
-    if (scope.local[name] == declaration) {
+    if (scope.lookupLocalMember(name, setter: false) == declaration) {
       isLocal = true;
       preferred = declaration;
       hiddenUri = computeLibraryUri(other);
@@ -2348,7 +2376,8 @@
           variable.name, this, variable.charOffset,
           bound: variable.bound?.clone(newTypes),
           isExtensionTypeParameter: isExtensionTypeParameter,
-          variableVariance: variable.variance);
+          variableVariance:
+              variable.parameter.isLegacyCovariant ? null : variable.variance);
       copy.add(newVariable);
       boundlessTypeVariables.add(newVariable);
     }
@@ -2371,6 +2400,21 @@
     return count;
   }
 
+  int computeVariances() {
+    int count = 0;
+    for (Builder declaration in libraryDeclaration.members.values) {
+      if (declaration is TypeAliasBuilder &&
+          declaration.typeVariablesCount > 0) {
+        for (TypeVariableBuilder typeParameter in declaration.typeVariables) {
+          typeParameter.variance =
+              computeVariance(typeParameter, declaration.type, this);
+          ++count;
+        }
+      }
+    }
+    return count;
+  }
+
   int computeDefaultTypes(TypeBuilder dynamicType, TypeBuilder bottomType,
       ClassBuilder objectClass) {
     int count = 0;
@@ -2469,7 +2513,7 @@
       String name = originDeclarations.name;
       Builder member = originDeclarations.current;
       bool isSetter = member.isSetter;
-      Builder patch = isSetter ? scope.setters[name] : scope.local[name];
+      Builder patch = scope.lookupLocalMember(name, setter: isSetter);
       if (patch != null) {
         // [patch] has the same name as a [member] in [origin] library, so it
         // must be a patch to [member].
@@ -2514,10 +2558,10 @@
 
   void injectMemberFromPatch(String name, Builder member) {
     if (member.isSetter) {
-      assert(scope.setters[name] == null);
+      assert(scope.lookupLocalMember(name, setter: true) == null);
       scopeBuilder.addSetter(name, member);
     } else {
-      assert(scope.local[name] == null);
+      assert(scope.lookupLocalMember(name, setter: false) == null);
       scopeBuilder.addMember(name, member);
     }
   }
@@ -2533,8 +2577,10 @@
 
     // If this member already exist in the origin library scope, it should
     // have been marked as patch.
-    assert((member.isSetter && scope.setters[name] == null) ||
-        (!member.isSetter && scope.local[name] == null));
+    assert((member.isSetter &&
+            scope.lookupLocalMember(name, setter: true) == null) ||
+        (!member.isSetter &&
+            scope.lookupLocalMember(name, setter: false) == null));
     addToExportScope(name, member);
   }
 
@@ -2866,7 +2912,7 @@
         checkBoundsInFunctionNode(declaration.procedure.function,
             typeEnvironment, declaration.fileUri);
       } else if (declaration is ClassBuilder) {
-        declaration.checkBoundsInOutline(typeEnvironment);
+        declaration.checkTypesInOutline(typeEnvironment);
       }
     }
     inferredTypes.clear();
@@ -2911,9 +2957,9 @@
 
   final Map<String, Builder> constructors;
 
-  final Map<String, Builder> setters;
+  final Map<String, MemberBuilder> setters;
 
-  final List<ExtensionBuilder> extensions;
+  final Set<ExtensionBuilder> extensions;
 
   final List<UnresolvedType> types = <UnresolvedType>[];
 
@@ -2951,9 +2997,9 @@
       : this(
             TypeParameterScopeKind.library,
             <String, Builder>{},
-            <String, Builder>{},
+            <String, MemberBuilder>{},
             null, // No support for constructors in library scopes.
-            <ExtensionBuilder>[],
+            <ExtensionBuilder>{},
             "<library>",
             -1,
             null);
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 1abdee5..212600d 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -10,6 +10,21 @@
 
 import 'dart:typed_data' show Uint8List;
 
+import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
+    show ClassMemberParser;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show Parser, lengthForToken;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show
+        ErrorToken,
+        LanguageVersionToken,
+        ScannerConfiguration,
+        ScannerResult,
+        Token,
+        scan;
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
@@ -33,6 +48,8 @@
 
 import '../../api_prototype/file_system.dart';
 
+import '../../base/common.dart';
+
 import '../../base/instrumentation.dart' show Instrumentation;
 
 import '../blacklisted_classes.dart' show blacklistedCoreClasses;
@@ -80,8 +97,6 @@
         templateSourceOutlineSummary,
         templateUntranslatableUri;
 
-import '../kernel/kernel_shadow_ast.dart' show ShadowTypeInferenceEngine;
-
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, DelayedMember, DelayedOverrideCheck;
 
@@ -97,20 +112,11 @@
 
 import '../loader.dart' show Loader, untranslatableUriScheme;
 
-import '../parser/class_member_parser.dart' show ClassMemberParser;
-
-import '../parser.dart' show Parser, lengthForToken, offsetForToken;
-
 import '../problems.dart' show internalProblem;
 
-import '../scanner.dart'
-    show
-        ErrorToken,
-        LanguageVersionToken,
-        ScannerConfiguration,
-        ScannerResult,
-        Token,
-        scan;
+import '../source/stack_listener.dart' show offsetForToken;
+
+import '../type_inference/type_inference_engine.dart';
 
 import '../type_inference/type_inferrer.dart';
 
@@ -143,7 +149,7 @@
   DartType iterableOfBottom;
   DartType streamOfBottom;
 
-  ShadowTypeInferenceEngine typeInferenceEngine;
+  TypeInferenceEngineImpl typeInferenceEngine;
 
   Instrumentation instrumentation;
 
@@ -151,8 +157,12 @@
 
   SetLiteralTransformer setLiteralTransformer;
 
+  final SourceLoaderDataForTesting dataForTesting;
+
   SourceLoader(this.fileSystem, this.includeComments, KernelTarget target)
-      : super(target);
+      : dataForTesting =
+            retainDataForTesting ? new SourceLoaderDataForTesting() : null,
+        super(target);
 
   Template<SummaryTemplate> get outlineSummaryTemplate =>
       templateSourceOutlineSummary;
@@ -513,6 +523,16 @@
     ticker.logMs("Resolved $count type-variable bounds");
   }
 
+  void computeVariances() {
+    int count = 0;
+    builders.forEach((Uri uri, LibraryBuilder library) {
+      if (library.loader == this) {
+        count += library.computeVariances();
+      }
+    });
+    ticker.logMs("Computed variances of $count type variables");
+  }
+
   void computeDefaultTypes(TypeBuilder dynamicType, TypeBuilder bottomType,
       ClassBuilder objectClass) {
     int count = 0;
@@ -986,7 +1006,7 @@
   }
 
   void createTypeInferenceEngine() {
-    typeInferenceEngine = new ShadowTypeInferenceEngine(instrumentation);
+    typeInferenceEngine = new TypeInferenceEngineImpl(instrumentation);
   }
 
   void performTopLevelInference(List<SourceClassBuilder> sourceClasses) {
@@ -1266,3 +1286,19 @@
 
   const AmbiguousTypesRecord(this.cls, this.a, this.b);
 }
+
+class SourceLoaderDataForTesting {
+  final Map<TreeNode, TreeNode> _aliasMap = {};
+
+  /// Registers that [original] has been replaced by [alias] in the generated
+  /// AST.
+  void registerAlias(TreeNode original, TreeNode alias) {
+    _aliasMap[alias] = original;
+  }
+
+  /// Returns the original node for [alias] or [alias] if it was not registered
+  /// as an alias.
+  TreeNode toOriginal(TreeNode alias) {
+    return _aliasMap[alias] ?? alias;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index 457f5d5..89a515c 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -4,6 +4,14 @@
 
 library fasta.stack_listener;
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show Listener, MemberKind, Parser, lengthOfSpan;
+
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'
+    show IdentifierContext;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
 import 'package:kernel/ast.dart'
     show AsyncMarker, Expression, FunctionNode, TreeNode;
 
@@ -16,18 +24,11 @@
         codeNativeClauseShouldBeAnnotation,
         templateInternalProblemStackNotEmpty;
 
-import '../parser.dart'
-    show Listener, MemberKind, Parser, lengthOfSpan, offsetForToken;
-
-import '../parser/identifier_context.dart' show IdentifierContext;
-
 import '../problems.dart'
     show internalProblem, unhandled, unimplemented, unsupported;
 
 import '../quote.dart' show unescapeString;
 
-import '../scanner.dart' show Token;
-
 import 'value_kinds.dart';
 
 enum NullValue {
@@ -626,3 +627,9 @@
 
   String toString() => "ParserRecovery(@$charOffset)";
 }
+
+/// A null-aware alternative to `token.offset`.  If [token] is `null`, returns
+/// `TreeNode.noOffset`.
+int offsetForToken(Token token) {
+  return token == null ? TreeNode.noOffset : token.offset;
+}
diff --git a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
index 69e5e57..91cdbaa 100644
--- a/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/type_promotion_look_ahead_listener.dart
@@ -4,27 +4,28 @@
 
 library fasta.type_promotion_look_ahead_listener;
 
-import '../builder/builder.dart';
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
-import '../messages.dart' show LocatedMessage, Message, MessageCode;
-
-import '../parser.dart'
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
     show
         Assert,
+        BlockKind,
         DeclarationKind,
         FormalParameterKind,
         IdentifierContext,
         Listener,
         MemberKind;
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import '../builder/builder.dart';
+
+import '../messages.dart' show LocatedMessage, Message, MessageCode;
+
 import '../problems.dart' as problems show unhandled;
 
-import '../scanner.dart' show Token;
-
 import '../scope.dart' show Scope;
 
-import '../severity.dart' show Severity;
-
 final NoArguments noArgumentsSentinel = new NoArguments();
 
 abstract class TypePromotionState {
@@ -230,13 +231,14 @@
   }
 
   @override
-  void beginBlock(Token token) {
+  void beginBlock(Token token, BlockKind blockKind) {
     debugEvent("beginBlock", token);
     state.enterScope("block");
   }
 
   @override
-  void endBlock(int count, Token beginToken, Token endToken) {
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
     debugEvent("Block", beginToken);
     state.exitScope(endToken);
   }
@@ -598,13 +600,13 @@
   }
 
   @override
-  void handleForInitializerExpressionStatement(Token token) {
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
     debugEvent("ForInitializerExpressionStatement", token);
     state.pop(); // Expression.
   }
 
   @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
     debugEvent("ForInitializerLocalVariableDeclaration", token);
   }
 
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 49039ab..dde97c4 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,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as type
+    show Token;
+
 import 'package:kernel/ast.dart' as type;
 
 import '../builder/builder.dart' as type;
@@ -39,8 +42,6 @@
 
 import '../operator.dart' as type;
 
-import '../scanner.dart' as type show Token;
-
 import '../scope.dart' as type;
 
 import '../source/outline_builder.dart' as type;
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index e3470f7..7ff4363 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -4,6 +4,8 @@
 
 library fasta.target_implementation;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/ast.dart' show Source;
 
 import 'package:kernel/target/targets.dart' as backend show Target;
@@ -22,8 +24,6 @@
 
 import 'rewrite_severity.dart' show rewriteSeverity;
 
-import 'severity.dart' show Severity;
-
 import 'target.dart' show Target;
 
 import 'ticker.dart' show Ticker;
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 83ce151..f7e9751 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
@@ -15,7 +15,9 @@
         InvalidType,
         NamedType,
         Nullability,
+        TypeParameter,
         TypeParameterType,
+        Variance,
         VoidType;
 
 import 'package:kernel/type_algebra.dart' show Substitution;
@@ -400,13 +402,17 @@
     // causing pain in real code.  The current algorithm is:
     // 1. If either of the types is a supertype of the other, return it.
     //    This is in fact the best result in this case.
-    // 2. If the two types have the same class element, then take the
-    //    pointwise standard upper bound of the type arguments.  This is again
-    //    the best result, except that the recursive calls may not return
-    //    the true standard upper bounds.  The result is guaranteed to be a
-    //    well-formed type under the assumption that the input types were
-    //    well-formed (and assuming that the recursive calls return
-    //    well-formed types).
+    // 2. If the two types have the same class element and is implicitly or
+    //    explicitly covariant, then take the pointwise standard upper bound of
+    //    the type arguments. This is again the best result, except that the
+    //    recursive calls may not return the true standard upper bounds.  The
+    //    result is guaranteed to be a well-formed type under the assumption
+    //    that the input types were well-formed (and assuming that the
+    //    recursive calls return well-formed types).
+    //    If the variance of the type parameter is contravariant, we take the
+    //    standard lower bound of the type arguments. If the variance of the
+    //    type parameter is invariant, we verify if the type arguments satisfy
+    //    subtyping in both directions, then choose a bound.
     // 3. Otherwise return the spec-defined standard upper bound.  This will
     //    be an upper bound, might (or might not) be least, and might
     //    (or might not) be a well-formed type.
@@ -421,11 +427,28 @@
         identical(type1.classNode, type2.classNode)) {
       List<DartType> tArgs1 = type1.typeArguments;
       List<DartType> tArgs2 = type2.typeArguments;
+      List<TypeParameter> tParams = type1.classNode.typeParameters;
 
       assert(tArgs1.length == tArgs2.length);
+      assert(tArgs1.length == tParams.length);
       List<DartType> tArgs = new List(tArgs1.length);
       for (int i = 0; i < tArgs1.length; i++) {
-        tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
+        if (tParams[i].variance == Variance.contravariant) {
+          tArgs[i] = getStandardLowerBound(tArgs1[i], tArgs2[i]);
+        } else if (tParams[i].variance == Variance.invariant) {
+          if (!isSubtypeOf(tArgs1[i], tArgs2[i],
+                  SubtypeCheckMode.ignoringNullabilities) ||
+              !isSubtypeOf(tArgs2[i], tArgs1[i],
+                  SubtypeCheckMode.ignoringNullabilities)) {
+            // No bound will be valid, find bound at the interface level.
+            return getLegacyLeastUpperBound(type1, type2);
+          }
+          // TODO (kallentu) : Fix asymmetric bounds behavior for invariant type
+          //  parameters.
+          tArgs[i] = tArgs1[i];
+        } else {
+          tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
+        }
       }
       return new InterfaceType(type1.classNode, tArgs);
     }
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 930810e..42b0696 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
@@ -12,6 +12,7 @@
         Member,
         Name,
         NamedType,
+        Nullability,
         Procedure,
         TypeParameter,
         TypeParameterType,
@@ -63,7 +64,7 @@
 
   InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass);
 
-  InterfaceType futureType(DartType type);
+  InterfaceType futureType(DartType type, Nullability nullability);
 
   /// Returns the set of type constraints that was gathered.
   Map<TypeParameter, TypeConstraint> computeConstraints() {
@@ -280,7 +281,7 @@
       //   constraints `C0`.
       // - And `P` is a subtype match for `Q` with respect to `L` under
       //   constraints `C1`.
-      InterfaceType subtypeFuture = futureType(subtypeArg);
+      InterfaceType subtypeFuture = futureType(subtypeArg, Nullability.legacy);
       return _isSubtypeMatch(subtypeFuture, supertype) &&
           _isSubtypeMatch(subtypeArg, supertype);
     }
@@ -296,7 +297,7 @@
       //   - And `P` is a subtype match for `Q` with respect to `L` under
       //     constraints `C`
       DartType supertypeArg = supertype.typeArguments[0];
-      DartType supertypeFuture = futureType(supertypeArg);
+      DartType supertypeFuture = futureType(supertypeArg, Nullability.legacy);
 
       // The match against FutureOr<X> succeeds if the match against either
       // Future<X> or X succeeds.  If they both succeed, the one adding new
@@ -453,8 +454,8 @@
   }
 
   @override
-  InterfaceType futureType(DartType type) {
-    return environment.futureType(type);
+  InterfaceType futureType(DartType type, Nullability nullability) {
+    return environment.futureType(type, nullability);
   }
 }
 
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 f58a296..9fbaded 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.
 
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+
 import 'package:kernel/ast.dart'
     show
         Constructor,
@@ -13,6 +15,8 @@
         InterfaceType,
         Member,
         NamedType,
+        Nullability,
+        TreeNode,
         TypeParameter,
         TypeParameterType,
         TypedefType,
@@ -22,6 +26,8 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
+import 'package:kernel/type_environment.dart';
+
 import '../../base/instrumentation.dart' show Instrumentation;
 
 import '../builder/library_builder.dart';
@@ -33,7 +39,7 @@
 
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
-import 'type_inferrer.dart' show TypeInferrer;
+import 'type_inferrer.dart';
 
 import 'type_schema_environment.dart' show TypeSchemaEnvironment;
 
@@ -149,13 +155,13 @@
 
   /// Creates a type inferrer for use inside of a method body declared in a file
   /// with the given [uri].
-  TypeInferrer createLocalTypeInferrer(
-      Uri uri, InterfaceType thisType, SourceLibraryBuilder library);
+  TypeInferrer createLocalTypeInferrer(Uri uri, InterfaceType thisType,
+      SourceLibraryBuilder library, InferenceDataForTesting dataForTesting);
 
   /// Creates a [TypeInferrer] object which is ready to perform type inference
   /// on the given [field].
-  TypeInferrer createTopLevelTypeInferrer(
-      Uri uri, InterfaceType thisType, SourceLibraryBuilder library);
+  TypeInferrer createTopLevelTypeInferrer(Uri uri, InterfaceType thisType,
+      SourceLibraryBuilder library, InferenceDataForTesting dataForTesting);
 
   /// Performs the third phase of top level inference, which is to visit all
   /// constructors still needing inference and infer the types of their
@@ -215,3 +221,96 @@
     return member;
   }
 }
+
+/// Concrete implementation of [TypeInferenceEngine] specialized to work with
+/// kernel objects.
+class TypeInferenceEngineImpl extends TypeInferenceEngine {
+  TypeInferenceEngineImpl(Instrumentation instrumentation)
+      : super(instrumentation);
+
+  @override
+  TypeInferrer createLocalTypeInferrer(Uri uri, InterfaceType thisType,
+      SourceLibraryBuilder library, InferenceDataForTesting dataForTesting) {
+    AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;
+    if (dataForTesting != null) {
+      assignedVariables = dataForTesting.flowAnalysisResult.assignedVariables =
+          new AssignedVariablesForTesting<TreeNode, VariableDeclaration>();
+    } else {
+      assignedVariables =
+          new AssignedVariables<TreeNode, VariableDeclaration>();
+    }
+    return new TypeInferrerImpl(
+        this, uri, false, thisType, library, assignedVariables, dataForTesting);
+  }
+
+  @override
+  TypeInferrer createTopLevelTypeInferrer(Uri uri, InterfaceType thisType,
+      SourceLibraryBuilder library, InferenceDataForTesting dataForTesting) {
+    AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;
+    if (dataForTesting != null) {
+      assignedVariables = dataForTesting.flowAnalysisResult.assignedVariables =
+          new AssignedVariablesForTesting<TreeNode, VariableDeclaration>();
+    } else {
+      assignedVariables =
+          new AssignedVariables<TreeNode, VariableDeclaration>();
+    }
+    return new TypeInferrerImpl(
+        this, uri, true, thisType, library, assignedVariables, dataForTesting);
+  }
+}
+
+class InferenceDataForTesting {
+  final FlowAnalysisResult flowAnalysisResult = new FlowAnalysisResult();
+}
+
+/// The result of performing flow analysis on a unit.
+class FlowAnalysisResult {
+  /// The list of nodes, [Expression]s or [Statement]s, that cannot be reached,
+  /// for example because a previous statement always exits.
+  final List<TreeNode> unreachableNodes = [];
+
+  /// The list of function bodies that don't complete, for example because
+  /// there is a `return` statement at the end of the function body block.
+  final List<TreeNode> functionBodiesThatDontComplete = [];
+
+  /// The list of [Expression]s representing variable accesses that occur before
+  /// the corresponding variable has been definitely assigned.
+  final List<TreeNode> unassignedNodes = [];
+
+  /// The assigned variables information that computed for the member.
+  AssignedVariablesForTesting<TreeNode, VariableDeclaration> assignedVariables;
+}
+
+/// CFE-specific implementation of [TypeOperations].
+class TypeOperationsCfe
+    implements TypeOperations<VariableDeclaration, DartType> {
+  final TypeEnvironment typeEnvironment;
+
+  TypeOperationsCfe(this.typeEnvironment);
+
+  // TODO(dmitryas): Consider checking for mutual subtypes instead of ==.
+  @override
+  bool isSameType(DartType type1, DartType type2) => type1 == type2;
+
+  @override
+  bool isSubtypeOf(DartType leftType, DartType rightType) {
+    return typeEnvironment.isSubtypeOf(
+        leftType, rightType, SubtypeCheckMode.withNullabilities);
+  }
+
+  @override
+  DartType promoteToNonNull(DartType type) {
+    return type.withNullability(Nullability.nonNullable);
+  }
+
+  @override
+  DartType variableType(VariableDeclaration variable) => variable.type;
+
+  @override
+  DartType tryPromoteToType(DartType from, DartType to) {
+    if (from is TypeParameterType) {
+      return new TypeParameterType(from.parameter, to, from.nullability);
+    }
+    return to;
+  }
+}
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 af09eba..5480c6c 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
@@ -4,6 +4,8 @@
 
 import 'dart:core' hide MapEntry;
 
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
 
 import 'package:kernel/ast.dart' hide Variance;
@@ -28,39 +30,12 @@
 import '../builder/extension_builder.dart';
 import '../builder/member_builder.dart';
 
-import '../fasta_codes.dart'
-    show
-        LocatedMessage,
-        Message,
-        Template,
-        messageReturnFromVoidFunction,
-        messageReturnWithoutExpression,
-        messageVoidExpression,
-        noLength,
-        templateArgumentTypeNotAssignable,
-        templateDuplicatedNamedArgument,
-        templateImplicitCallOfNonMethod,
-        templateInvalidAssignment,
-        templateInvalidCastFunctionExpr,
-        templateInvalidCastLiteralList,
-        templateInvalidCastLiteralMap,
-        templateInvalidCastLiteralSet,
-        templateInvalidCastLocalFunction,
-        templateInvalidCastNewExpr,
-        templateInvalidCastStaticMethod,
-        templateInvalidCastTopLevelFunction,
-        templateInvokeNonFunction,
-        templateMixinInferenceNoMatchingClass,
-        templateUndefinedGetter,
-        templateUndefinedMethod,
-        templateUndefinedSetter;
+import '../fasta_codes.dart';
 
 import '../kernel/expression_generator.dart' show buildIsNull;
 
 import '../kernel/kernel_shadow_ast.dart'
     show
-        ShadowTypeInferenceEngine,
-        ShadowTypeInferrer,
         VariableDeclarationImpl,
         getExplicitTypeArguments,
         getExtensionTypeParameterCount;
@@ -77,8 +52,7 @@
 
 import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
 
-import 'type_inference_engine.dart'
-    show IncludesTypeParametersNonCovariantly, TypeInferenceEngine, Variance;
+import 'type_inference_engine.dart';
 
 import 'type_promotion.dart' show TypePromoter;
 
@@ -283,13 +257,17 @@
 
       // The return expression has to be assignable to the return type
       // expectation from the downwards inference context.
-      if (statement.expression != null &&
-          inferrer.ensureAssignable(returnOrYieldContext, type,
-                  statement.expression, statement.fileOffset,
-                  isReturnFromAsync: isAsync, isVoidAllowed: true) !=
-              null) {
-        // Not assignable, use the expectation.
-        type = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
+      if (statement.expression != null) {
+        Expression expression = inferrer.ensureAssignable(
+            returnOrYieldContext, type, statement.expression,
+            fileOffset: statement.fileOffset,
+            isReturnFromAsync: isAsync,
+            isVoidAllowed: true);
+        if (!identical(statement.expression, expression)) {
+          statement.expression = expression..parent = statement;
+          // Not assignable, use the expectation.
+          type = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
+        }
       }
       DartType unwrappedType = type;
       if (isAsync) {
@@ -309,26 +287,32 @@
     // is valid.
     if (checkValidReturn(inferrer, declaredReturnType, statement, type) &&
         statement.expression != null) {
-      inferrer.ensureAssignable(returnOrYieldContext, type,
-          statement.expression, statement.fileOffset,
-          isReturnFromAsync: isAsync, isVoidAllowed: true);
+      Expression expression = inferrer.ensureAssignable(
+          returnOrYieldContext, type, statement.expression,
+          fileOffset: statement.fileOffset,
+          isReturnFromAsync: isAsync,
+          isVoidAllowed: true);
+      statement.expression = expression..parent = statement;
     }
   }
 
-  void handleYield(TypeInferrerImpl inferrer, bool isYieldStar, DartType type,
-      Expression expression, int fileOffset) {
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult) {
     if (!isGenerator) return;
-    DartType expectedType = isYieldStar
+    DartType expectedType = node.isYieldStar
         ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
         : returnOrYieldContext;
-    if (inferrer.ensureAssignable(expectedType, type, expression, fileOffset,
-            isReturnFromAsync: isAsync) !=
-        null) {
+    Expression expression = inferrer.ensureAssignableResult(
+        expectedType, expressionResult,
+        fileOffset: node.fileOffset, isReturnFromAsync: isAsync);
+    node.expression = expression..parent = node;
+    DartType type = expressionResult.inferredType;
+    if (!identical(expressionResult.expression, expression)) {
       type = greatestClosure(inferrer.coreTypes, expectedType);
     }
     if (_needToInferReturnType) {
       DartType unwrappedType = type;
-      if (isYieldStar) {
+      if (node.isYieldStar) {
         unwrappedType = inferrer.getDerivedTypeArgumentOf(
                 type,
                 isAsync
@@ -401,17 +385,6 @@
 /// This class describes the interface for use by clients of type inference
 /// (e.g. BodyBuilder).  Derived classes should derive from [TypeInferrerImpl].
 abstract class TypeInferrer {
-  final CoreTypes coreTypes;
-
-  TypeInferrer.private(this.coreTypes);
-
-  factory TypeInferrer(
-      ShadowTypeInferenceEngine engine,
-      Uri uri,
-      bool topLevel,
-      InterfaceType thisType,
-      SourceLibraryBuilder library) = ShadowTypeInferrer.private;
-
   SourceLibraryBuilder get library;
 
   /// Gets the [TypePromoter] that can be used to perform type promotion within
@@ -425,8 +398,10 @@
   /// performed--this is used for testing.
   Uri get uriForInstrumentation;
 
+  AssignedVariables<TreeNode, VariableDeclaration> get assignedVariables;
+
   /// Performs full type inference on the given field initializer.
-  void inferFieldInitializer(
+  Expression inferFieldInitializer(
       InferenceHelper helper, DartType declaredType, Expression initializer);
 
   /// Performs type inference on the given function body.
@@ -437,24 +412,23 @@
   void inferInitializer(InferenceHelper helper, Initializer initializer);
 
   /// Performs type inference on the given metadata annotations.
-  void inferMetadata(InferenceHelper helper, List<Expression> annotations);
+  void inferMetadata(
+      InferenceHelper helper, TreeNode parent, List<Expression> annotations);
 
   /// Performs type inference on the given metadata annotations keeping the
   /// existing helper if possible.
-  void inferMetadataKeepingHelper(List<Expression> annotations);
+  void inferMetadataKeepingHelper(
+      TreeNode parent, List<Expression> annotations);
 
   /// Performs type inference on the given function parameter initializer
   /// expression.
-  void inferParameterInitializer(
+  Expression inferParameterInitializer(
       InferenceHelper helper, Expression initializer, DartType declaredType);
 }
 
-/// Derived class containing generic implementations of [TypeInferrer].
-///
-/// This class contains as much of the implementation of type inference as
-/// possible without knowing the identity of the type parameters.  It defers to
-/// abstract methods for everything else.
-abstract class TypeInferrerImpl extends TypeInferrer {
+/// Concrete implementation of [TypeInferrer] specialized to work with kernel
+/// objects.
+class TypeInferrerImpl implements TypeInferrer {
   /// Marker object to indicate that a function takes an unknown number
   /// of arguments.
   static final FunctionType unknownFunction =
@@ -463,6 +437,16 @@
   final TypeInferenceEngine engine;
 
   @override
+  final TypePromoter typePromoter;
+
+  final FlowAnalysis<TreeNode, Statement, Expression, VariableDeclaration,
+      DartType> flowAnalysis;
+
+  final AssignedVariables<TreeNode, VariableDeclaration> assignedVariables;
+
+  final InferenceDataForTesting dataForTesting;
+
+  @override
   final Uri uriForInstrumentation;
 
   /// Indicates whether the construct we are currently performing inference for
@@ -495,18 +479,46 @@
   /// if the last invocation didn't require any inference.
   FunctionType lastCalleeType;
 
-  TypeInferrerImpl.private(this.engine, this.uriForInstrumentation,
-      bool topLevel, this.thisType, this.library)
+  TypeInferrerImpl(this.engine, this.uriForInstrumentation, bool topLevel,
+      this.thisType, this.library, this.assignedVariables, this.dataForTesting)
       : assert(library != null),
         classHierarchy = engine.classHierarchy,
         instrumentation = topLevel ? null : engine.instrumentation,
         typeSchemaEnvironment = engine.typeSchemaEnvironment,
         isTopLevel = topLevel,
-        super.private(engine.coreTypes);
+        typePromoter = new TypePromoter(engine.typeSchemaEnvironment),
+        // TODO(dmitryas): Pass in the actual assigned variables.
+        flowAnalysis = new FlowAnalysis(
+            new TypeOperationsCfe(engine.typeSchemaEnvironment),
+            assignedVariables);
 
-  /// Gets the type promoter that should be used to promote types during
-  /// inference.
-  TypePromoter get typePromoter;
+  CoreTypes get coreTypes => engine.coreTypes;
+
+  bool get isNonNullableByDefault => library.isNonNullableByDefault;
+
+  void registerIfUnreachableForTesting(TreeNode node, {bool isReachable}) {
+    if (dataForTesting == null) return;
+    isReachable ??= flowAnalysis.isReachable;
+    if (!isReachable) {
+      dataForTesting.flowAnalysisResult.unreachableNodes.add(node);
+    }
+  }
+
+  @override
+  void inferInitializer(InferenceHelper helper, Initializer initializer) {
+    this.helper = helper;
+    // Use polymorphic dispatch on [KernelInitializer] to perform whatever
+    // kind of type inference is correct for this kind of initializer.
+    // TODO(paulberry): experiment to see if dynamic dispatch would be better,
+    // so that the type hierarchy will be simpler (which may speed up "is"
+    // checks).
+    if (initializer is InitializerJudgment) {
+      initializer.acceptInference(new InferenceVisitor(this));
+    } else {
+      initializer.accept(new InferenceVisitor(this));
+    }
+    this.helper = null;
+  }
 
   bool isDoubleContext(DartType typeContext) {
     // A context is a double context if double is assignable to it but int is
@@ -532,14 +544,28 @@
             actualType, expectedType, SubtypeCheckMode.ignoringNullabilities);
   }
 
+  Expression ensureAssignableResult(
+      DartType expectedType, ExpressionInferenceResult result,
+      {int fileOffset,
+      bool isVoidAllowed: false,
+      bool isReturnFromAsync: false}) {
+    return ensureAssignable(
+        expectedType, result.inferredType, result.expression,
+        fileOffset: fileOffset,
+        isVoidAllowed: isVoidAllowed,
+        isReturnFromAsync: isReturnFromAsync);
+  }
+
   /// Checks whether [actualType] can be assigned to the greatest closure of
   /// [expectedType], and inserts an implicit downcast if appropriate.
-  Expression ensureAssignable(DartType expectedType, DartType actualType,
-      Expression expression, int fileOffset,
-      {bool isReturnFromAsync: false,
+  Expression ensureAssignable(
+      DartType expectedType, DartType actualType, Expression expression,
+      {int fileOffset,
+      bool isReturnFromAsync: false,
       bool isVoidAllowed: false,
       Template<Message Function(DartType, DartType)> template}) {
     assert(expectedType != null);
+    fileOffset ??= expression.fileOffset;
     expectedType = greatestClosure(coreTypes, expectedType);
 
     DartType initialExpectedType = expectedType;
@@ -560,7 +586,9 @@
     // We don't need to insert assignability checks when doing top level type
     // inference since top level type inference only cares about the type that
     // is inferred (the kernel code is discarded).
-    if (isTopLevel) return null;
+    if (isTopLevel) {
+      return expression;
+    }
 
     // If an interface type is being assigned to a function type, see if we
     // should tear off `.call`.
@@ -573,7 +601,6 @@
         if (_shouldTearOffCall(expectedType, actualType)) {
           // Replace expression with:
           // `let t = expression in t == null ? null : t.call`
-          TreeNode parent = expression.parent;
           VariableDeclaration t =
               new VariableDeclaration.forValue(expression, type: actualType)
                 ..fileOffset = fileOffset;
@@ -589,7 +616,6 @@
               tearOff,
               actualType);
           Let let = new Let(t, conditional)..fileOffset = fileOffset;
-          parent?.replaceChild(expression, let);
           expression = let;
         }
       }
@@ -597,24 +623,19 @@
 
     if (actualType is VoidType && !isVoidAllowed) {
       // Error: not assignable.  Perform error recovery.
-      TreeNode parent = expression.parent;
-      Expression errorNode =
-          helper.wrapInProblem(expression, messageVoidExpression, noLength);
-      parent?.replaceChild(expression, errorNode);
-      return errorNode;
+      return helper.wrapInProblem(expression, messageVoidExpression, noLength);
     }
 
     if (expectedType == null ||
         typeSchemaEnvironment.isSubtypeOf(
             actualType, expectedType, SubtypeCheckMode.ignoringNullabilities)) {
       // Types are compatible.
-      return null;
+      return expression;
     }
 
     if (!typeSchemaEnvironment.isSubtypeOf(
         expectedType, actualType, SubtypeCheckMode.ignoringNullabilities)) {
       // Error: not assignable.  Perform error recovery.
-      TreeNode parent = expression.parent;
       Expression errorNode = new AsExpression(
           expression,
           // TODO(ahe): The outline phase doesn't correctly remove invalid
@@ -631,7 +652,6 @@
                 .withArguments(actualType, expectedType),
             noLength);
       }
-      parent?.replaceChild(expression, errorNode);
       return errorNode;
     } else {
       Template<Message Function(DartType, DartType)> template =
@@ -639,20 +659,13 @@
       if (template != null) {
         // The type of the expression is known precisely, so an implicit
         // downcast is guaranteed to fail.  Insert a compile-time error.
-        TreeNode parent = expression.parent;
-        Expression errorNode = helper.wrapInProblem(expression,
+        return helper.wrapInProblem(expression,
             template.withArguments(actualType, expectedType), noLength);
-        parent?.replaceChild(expression, errorNode);
-        return errorNode;
       } else {
         // Insert an implicit downcast.
-        TreeNode parent = expression.parent;
-        AsExpression typeCheck =
-            new AsExpression(expression, initialExpectedType)
-              ..isTypeError = true
-              ..fileOffset = fileOffset;
-        parent?.replaceChild(expression, typeCheck);
-        return typeCheck;
+        return new AsExpression(expression, initialExpectedType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
       }
     }
   }
@@ -727,7 +740,8 @@
       target = const ObjectAccessTarget.dynamic();
     } else if (receiverType is InvalidType) {
       target = const ObjectAccessTarget.invalid();
-    } else if (receiverType == coreTypes.functionLegacyRawType &&
+    } else if (receiverType is InterfaceType &&
+        receiverType.classNode == coreTypes.functionClass &&
         name.name == 'call') {
       target = const ObjectAccessTarget.callFunction();
     } else {
@@ -868,36 +882,14 @@
     return target;
   }
 
-  /// Finds a member of [receiverType] called [name], and if it is found,
-  /// reports it through instrumentation using [fileOffset].
-  ///
-  /// For the case where [receiverType] is a [FunctionType], and the name
-  /// is `call`, the string 'call' is returned as a sentinel object.
-  ///
-  /// For the case where [receiverType] is `dynamic`, and the name is declared
-  /// in Object, the member from Object is returned though the call may not end
-  /// up targeting it if the arguments do not match (the basic principle is that
-  /// the Object member is used for inferring types only if noSuchMethod cannot
-  /// be targeted due to, e.g., an incorrect argument count).
-  ///
-  /// If no target is found on a non-dynamic receiver an error is reported
-  /// using [errorTemplate] and [expression] is replaced by an invalid
-  /// expression.
-  ObjectAccessTarget findInterfaceMemberOrReport(
+  /// If target is missing on a non-dynamic receiver, an error is reported
+  /// using [errorTemplate] and an invalid expression is returned.
+  Expression reportMissingInterfaceMember(
+      ObjectAccessTarget target,
       DartType receiverType,
       Name name,
       int fileOffset,
-      Template<Message Function(String, DartType)> errorTemplate,
-      Expression expression,
-      {bool setter: false,
-      bool instrumented: true,
-      bool includeExtensionMethods: false}) {
-    ObjectAccessTarget target = findInterfaceMember(
-        receiverType, name, fileOffset,
-        setter: setter,
-        instrumented: instrumented,
-        includeExtensionMethods: includeExtensionMethods);
-
+      Template<Message Function(String, DartType)> errorTemplate) {
     assert(receiverType != null && isKnown(receiverType));
     if (!isTopLevel && target.isMissing && errorTemplate != null) {
       int length = name.name.length;
@@ -905,154 +897,13 @@
           identical(name.name, unaryMinusName.name)) {
         length = 1;
       }
-      expression.parent.replaceChild(
-          expression,
-          helper.buildProblem(
-              errorTemplate.withArguments(
-                  name.name, resolveTypeParameter(receiverType)),
-              fileOffset,
-              length));
+      return helper.buildProblem(
+          errorTemplate.withArguments(
+              name.name, resolveTypeParameter(receiverType)),
+          fileOffset,
+          length);
     }
-    return target;
-  }
-
-  /// Finds a member of [receiverType] called [name] and records it in
-  /// [methodInvocation].
-  ObjectAccessTarget findMethodInvocationMember(
-      DartType receiverType, InvocationExpression methodInvocation,
-      {bool instrumented: true}) {
-    // TODO(paulberry): could we add getters to InvocationExpression to make
-    // these is-checks unnecessary?
-    if (methodInvocation is MethodInvocation) {
-      ObjectAccessTarget interfaceTarget = findInterfaceMemberOrReport(
-          receiverType,
-          methodInvocation.name,
-          methodInvocation.fileOffset,
-          templateUndefinedMethod,
-          methodInvocation,
-          instrumented: instrumented,
-          includeExtensionMethods: true);
-      if (interfaceTarget.isInstanceMember) {
-        Member interfaceMember = interfaceTarget.member;
-        if (receiverType == const DynamicType() &&
-            interfaceMember is Procedure) {
-          Arguments arguments = methodInvocation.arguments;
-          FunctionNode signature = interfaceMember.function;
-          if (arguments.positional.length < signature.requiredParameterCount ||
-              arguments.positional.length >
-                  signature.positionalParameters.length) {
-            return const ObjectAccessTarget.unresolved();
-          }
-          for (NamedExpression argument in arguments.named) {
-            if (!signature.namedParameters
-                .any((declaration) => declaration.name == argument.name)) {
-              return const ObjectAccessTarget.unresolved();
-            }
-          }
-          if (instrumented && instrumentation != null) {
-            instrumentation.record(
-                uriForInstrumentation,
-                methodInvocation.fileOffset,
-                'target',
-                new InstrumentationValueForMember(interfaceMember));
-          }
-        }
-        methodInvocation.interfaceTarget = interfaceMember;
-      }
-      return interfaceTarget;
-    } else if (methodInvocation is SuperMethodInvocation) {
-      assert(receiverType != const DynamicType());
-      ObjectAccessTarget interfaceTarget = findInterfaceMember(
-          receiverType, methodInvocation.name, methodInvocation.fileOffset,
-          instrumented: instrumented);
-      if (interfaceTarget.isInstanceMember) {
-        methodInvocation.interfaceTarget = interfaceTarget.member;
-      }
-      return interfaceTarget;
-    } else {
-      throw unhandled("${methodInvocation.runtimeType}",
-          "findMethodInvocationMember", null, null);
-    }
-  }
-
-  /// Finds a member of [receiverType] called [name], and if it is found,
-  /// reports it through instrumentation and records it in [propertyGet].
-  ObjectAccessTarget findPropertyGetMember(
-      DartType receiverType, Expression propertyGet,
-      {bool instrumented: true}) {
-    // TODO(paulberry): could we add a common base class to PropertyGet and
-    // SuperPropertyGet to make these is-checks unnecessary?
-    if (propertyGet is PropertyGet) {
-      ObjectAccessTarget readTarget = findInterfaceMemberOrReport(
-          receiverType,
-          propertyGet.name,
-          propertyGet.fileOffset,
-          templateUndefinedGetter,
-          propertyGet,
-          instrumented: instrumented);
-      if (readTarget.isInstanceMember) {
-        if (instrumented &&
-            instrumentation != null &&
-            receiverType == const DynamicType()) {
-          instrumentation.record(uriForInstrumentation, propertyGet.fileOffset,
-              'target', new InstrumentationValueForMember(readTarget.member));
-        }
-        propertyGet.interfaceTarget = readTarget.member;
-      }
-      return readTarget;
-    } else if (propertyGet is SuperPropertyGet) {
-      assert(receiverType != const DynamicType());
-      ObjectAccessTarget interfaceMember = findInterfaceMember(
-          receiverType, propertyGet.name, propertyGet.fileOffset,
-          instrumented: instrumented);
-      if (interfaceMember.isInstanceMember) {
-        propertyGet.interfaceTarget = interfaceMember.member;
-      }
-      return interfaceMember;
-    } else {
-      return unhandled(
-          "${propertyGet.runtimeType}", "findPropertyGetMember", null, null);
-    }
-  }
-
-  /// Finds a member of [receiverType] called [name], and if it is found,
-  /// reports it through instrumentation and records it in [propertySet].
-  ObjectAccessTarget findPropertySetMember(
-      DartType receiverType, Expression propertySet,
-      {bool instrumented: true}) {
-    if (propertySet is PropertySet) {
-      ObjectAccessTarget writeTarget = findInterfaceMemberOrReport(
-          receiverType,
-          propertySet.name,
-          propertySet.fileOffset,
-          templateUndefinedSetter,
-          propertySet,
-          setter: true,
-          instrumented: instrumented,
-          includeExtensionMethods: true);
-      if (writeTarget.isInstanceMember) {
-        if (instrumented &&
-            instrumentation != null &&
-            receiverType == const DynamicType()) {
-          instrumentation.record(uriForInstrumentation, propertySet.fileOffset,
-              'target', new InstrumentationValueForMember(writeTarget.member));
-        }
-        propertySet.interfaceTarget = writeTarget.member;
-      }
-      return writeTarget;
-    } else if (propertySet is SuperPropertySet) {
-      assert(receiverType != const DynamicType());
-      ObjectAccessTarget interfaceMember = findInterfaceMember(
-          receiverType, propertySet.name, propertySet.fileOffset,
-          setter: true, instrumented: instrumented);
-      if (interfaceMember.isInstanceMember) {
-        propertySet.interfaceTarget = interfaceMember.member;
-      }
-      return interfaceMember;
-    } else {
-      throw unhandled(
-          "${propertySet.runtimeType}", "findPropertySetMember", null, null);
-    }
+    return null;
   }
 
   /// Returns the type of [target] when accessed as a getter on [receiverType].
@@ -1416,10 +1267,6 @@
     return null;
   }
 
-  /// Gets the initializer for the given [field], or `null` if there is no
-  /// initializer.
-  Expression getFieldInitializer(Field field);
-
   /// If the [member] is a forwarding stub, return the target it forwards to.
   /// Otherwise return the given [member].
   Member getRealTarget(Member member) {
@@ -1510,15 +1357,11 @@
       DartType inferredType,
       FunctionType functionType,
       int fileOffset) {
-    Expression expressionToReplace = desugaredInvocation ?? expression;
     switch (checkKind) {
       case MethodContravarianceCheckKind.checkMethodReturn:
-        TreeNode parent = expressionToReplace.parent;
-        AsExpression replacement =
-            new AsExpression(expressionToReplace, inferredType)
-              ..isTypeError = true
-              ..fileOffset = fileOffset;
-        parent.replaceChild(expressionToReplace, replacement);
+        AsExpression replacement = new AsExpression(expression, inferredType)
+          ..isTypeError = true
+          ..fileOffset = fileOffset;
         if (instrumentation != null) {
           int offset = arguments.fileOffset == -1
               ? expression.fileOffset
@@ -1528,7 +1371,6 @@
         }
         return replacement;
       case MethodContravarianceCheckKind.checkGetterReturn:
-        TreeNode parent = expressionToReplace.parent;
         PropertyGet propertyGet = new PropertyGet(desugaredInvocation.receiver,
             desugaredInvocation.name, desugaredInvocation.interfaceTarget);
         AsExpression asExpression = new AsExpression(propertyGet, functionType)
@@ -1536,7 +1378,6 @@
           ..fileOffset = fileOffset;
         MethodInvocation replacement = new MethodInvocation(
             asExpression, callName, desugaredInvocation.arguments);
-        parent.replaceChild(expressionToReplace, replacement);
         if (instrumentation != null) {
           int offset = arguments.fileOffset == -1
               ? expression.fileOffset
@@ -1551,48 +1392,7 @@
       case MethodContravarianceCheckKind.none:
         break;
     }
-    return expressionToReplace;
-  }
-
-  /// Add an "as" check if necessary due to contravariance.
-  ///
-  /// Returns the "as" check if it was added; otherwise returns the original
-  /// expression.
-  Expression handlePropertyGetContravariance(
-      Expression receiver,
-      ObjectAccessTarget readTarget,
-      PropertyGet desugaredGet,
-      Expression expression,
-      DartType inferredType,
-      int fileOffset) {
-    bool checkReturn = false;
-    if (receiver != null &&
-        readTarget.isInstanceMember &&
-        receiver is! ThisExpression) {
-      Member interfaceMember = readTarget.member;
-      if (interfaceMember is Procedure) {
-        checkReturn = returnedTypeParametersOccurNonCovariantly(
-            interfaceMember.enclosingClass,
-            interfaceMember.function.returnType);
-      } else if (interfaceMember is Field) {
-        checkReturn = returnedTypeParametersOccurNonCovariantly(
-            interfaceMember.enclosingClass, interfaceMember.type);
-      }
-    }
-    Expression replacedExpression = desugaredGet ?? expression;
-    if (checkReturn) {
-      Expression expressionToReplace = replacedExpression;
-      TreeNode parent = expressionToReplace.parent;
-      replacedExpression = new AsExpression(expressionToReplace, inferredType)
-        ..isTypeError = true
-        ..fileOffset = fileOffset;
-      parent.replaceChild(expressionToReplace, replacedExpression);
-    }
-    if (instrumentation != null && checkReturn) {
-      instrumentation.record(uriForInstrumentation, expression.fileOffset,
-          'checkReturn', new InstrumentationValueForType(inferredType));
-    }
-    return replacedExpression;
+    return expression;
   }
 
   /// Modifies a type as appropriate when inferring a declared variable's type.
@@ -1621,10 +1421,45 @@
   /// the expression type and calls the appropriate specialized "infer" method.
   ExpressionInferenceResult inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded,
-      {bool isVoidAllowed});
+      {bool isVoidAllowed: false}) {
+    registerIfUnreachableForTesting(expression);
+
+    // `null` should never be used as the type context.  An instance of
+    // `UnknownType` should be used instead.
+    assert(typeContext != null);
+
+    // For full (non-top level) inference, we need access to the
+    // ExpressionGeneratorHelper so that we can perform error recovery.
+    assert(isTopLevel || helper != null);
+
+    // When doing top level inference, we skip subexpressions whose type isn't
+    // needed so that we don't induce bogus dependencies on fields mentioned in
+    // those subexpressions.
+    if (!typeNeeded) return new ExpressionInferenceResult(null, expression);
+
+    InferenceVisitor visitor = new InferenceVisitor(this);
+    ExpressionInferenceResult result;
+    if (expression is ExpressionJudgment) {
+      result = expression.acceptInference(visitor, typeContext);
+    } else {
+      result = expression.accept1(visitor, typeContext);
+    }
+    DartType inferredType = result.inferredType;
+    assert(inferredType != null, "No type inferred for $expression.");
+    if (inferredType is VoidType && !isVoidAllowed) {
+      if (expression.parent is! ArgumentsImpl) {
+        helper?.addProblem(
+            messageVoidExpression, expression.fileOffset, noLength);
+      }
+    }
+    if (result.inferredType is NeverType) {
+      flowAnalysis.handleExit();
+    }
+    return result;
+  }
 
   @override
-  void inferFieldInitializer(
+  Expression inferFieldInitializer(
     InferenceHelper helper,
     DartType context,
     Expression initializer,
@@ -1632,15 +1467,12 @@
     assert(closureContext == null);
     assert(!isTopLevel);
     this.helper = helper;
-    ExpressionInferenceResult result =
+    ExpressionInferenceResult initializerResult =
         inferExpression(initializer, context, true, isVoidAllowed: true);
-    if (result.replacement != null) {
-      initializer = result.replacement;
-    }
-    ensureAssignable(
-        context, result.inferredType, initializer, initializer.fileOffset,
+    initializer = ensureAssignableResult(context, initializerResult,
         isVoidAllowed: context is VoidType);
     this.helper = null;
+    return initializer;
   }
 
   @override
@@ -1652,6 +1484,13 @@
     inferStatement(body);
     closureContext = null;
     this.helper = null;
+    if (dataForTesting != null) {
+      if (!flowAnalysis.isReachable) {
+        dataForTesting.flowAnalysisResult.functionBodiesThatDontComplete
+            .add(body);
+      }
+    }
+    flowAnalysis.finish();
   }
 
   DartType inferInvocation(DartType typeContext, int offset,
@@ -1824,28 +1663,26 @@
     }
     // TODO(paulberry): if we are doing top level inference and type arguments
     // were omitted, report an error.
-    int i = 0;
-    _forEachArgument(arguments, (name, expression) {
-      DartType formalType = name != null
-          ? getNamedParameterType(calleeType, name)
-          : getPositionalParameterType(calleeType, i++);
+    for (int position = 0; position < arguments.positional.length; position++) {
+      DartType formalType = getPositionalParameterType(calleeType, position);
       DartType inferredFormalType = substitution != null
           ? substitution.substituteType(formalType)
           : formalType;
       DartType inferredType;
-      if (isImplicitExtensionMember && i == 1) {
+      if (isImplicitExtensionMember && position == 0) {
         assert(
             receiverType != null,
             "No receiver type provided for implicit extension member "
             "invocation.");
-        return;
+        continue;
       } else {
         ExpressionInferenceResult result = inferExpression(
-            expression,
+            arguments.positional[position],
             inferredFormalType,
             inferenceNeeded ||
                 isOverloadedArithmeticOperator ||
                 typeChecksNeeded);
+        arguments.positional[position] = result.expression..parent = arguments;
         inferredType = result.inferredType;
       }
       if (inferenceNeeded || typeChecksNeeded) {
@@ -1856,7 +1693,26 @@
         returnType = typeSchemaEnvironment.getTypeOfOverloadedArithmetic(
             receiverType, inferredType);
       }
-    });
+    }
+    for (NamedExpression namedArgument in arguments.named) {
+      DartType formalType =
+          getNamedParameterType(calleeType, namedArgument.name);
+      DartType inferredFormalType = substitution != null
+          ? substitution.substituteType(formalType)
+          : formalType;
+      ExpressionInferenceResult result = inferExpression(
+          namedArgument.value,
+          inferredFormalType,
+          inferenceNeeded ||
+              isOverloadedArithmeticOperator ||
+              typeChecksNeeded);
+      namedArgument.value = result.expression..parent = namedArgument;
+      DartType inferredType = result.inferredType;
+      if (inferenceNeeded || typeChecksNeeded) {
+        formalTypes.add(formalType);
+        actualTypes.add(inferredType);
+      }
+    }
 
     // Check for and remove duplicated named arguments.
     List<NamedExpression> named = arguments.named;
@@ -1931,15 +1787,24 @@
               ? substitution.substituteType(formalType)
               : formalType;
           DartType actualType = actualTypes[i];
-          Expression expression = i < numPositionalArgs
-              ? arguments.positional[i]
-              : arguments.named[i - numPositionalArgs].value;
-          ensureAssignable(
-              expectedType, actualType, expression, expression.fileOffset,
+          Expression expression;
+          NamedExpression namedExpression;
+          if (i < numPositionalArgs) {
+            expression = arguments.positional[i];
+          } else {
+            namedExpression = arguments.named[i - numPositionalArgs];
+            expression = namedExpression.value;
+          }
+          expression = ensureAssignable(expectedType, actualType, expression,
               isVoidAllowed: expectedType is VoidType,
               // TODO(johnniwinther): Specialize message for operator
               // invocations.
               template: templateArgumentTypeNotAssignable);
+          if (namedExpression == null) {
+            arguments.positional[i] = expression..parent = arguments;
+          } else {
+            namedExpression.value = expression..parent = namedExpression;
+          }
         }
       }
     }
@@ -1976,14 +1841,20 @@
           function.positionalParameters;
       for (int i = 0; i < positionalParameters.length; i++) {
         VariableDeclaration parameter = positionalParameters[i];
-        inferMetadataKeepingHelper(parameter.annotations);
+        inferMetadataKeepingHelper(parameter, parameter.annotations);
         if (parameter.initializer != null) {
-          inferExpression(parameter.initializer, parameter.type, !isTopLevel);
+          ExpressionInferenceResult initializerResult = inferExpression(
+              parameter.initializer, parameter.type, !isTopLevel);
+          parameter.initializer = initializerResult.expression
+            ..parent = parameter;
         }
       }
       for (VariableDeclaration parameter in function.namedParameters) {
-        inferMetadataKeepingHelper(parameter.annotations);
-        inferExpression(parameter.initializer, parameter.type, !isTopLevel);
+        inferMetadataKeepingHelper(parameter, parameter.annotations);
+        ExpressionInferenceResult initializerResult =
+            inferExpression(parameter.initializer, parameter.type, !isTopLevel);
+        parameter.initializer = initializerResult.expression
+          ..parent = parameter;
       }
     }
 
@@ -2102,27 +1973,23 @@
   }
 
   @override
-  void inferMetadata(InferenceHelper helper, List<Expression> annotations) {
+  void inferMetadata(
+      InferenceHelper helper, TreeNode parent, List<Expression> annotations) {
     if (annotations != null) {
       this.helper = helper;
-      inferMetadataKeepingHelper(annotations);
+      inferMetadataKeepingHelper(parent, annotations);
       this.helper = null;
     }
   }
 
   @override
-  void inferMetadataKeepingHelper(List<Expression> annotations) {
+  void inferMetadataKeepingHelper(
+      TreeNode parent, List<Expression> annotations) {
     if (annotations != null) {
-      // Place annotations in a temporary list literal so that they will have a
-      // parent.  This is necessary in case any of the annotations need to get
-      // replaced during type inference.
-      List<TreeNode> parents = annotations.map((e) => e.parent).toList();
-      new ListLiteral(annotations);
-      for (Expression annotation in annotations) {
-        inferExpression(annotation, const UnknownType(), !isTopLevel);
-      }
-      for (int i = 0; i < annotations.length; ++i) {
-        annotations[i].parent = parents[i];
+      for (int index = 0; index < annotations.length; index++) {
+        ExpressionInferenceResult result = inferExpression(
+            annotations[index], const UnknownType(), !isTopLevel);
+        annotations[index] = result.expression..parent = parent;
       }
     }
   }
@@ -2131,23 +1998,19 @@
       Expression expression, Expression receiver, Arguments arguments) {
     assert(target.isExtensionMember);
     Procedure procedure = target.member;
-    Expression replacement;
-    expression.parent.replaceChild(
-        expression,
-        replacement = engine.forest.createStaticInvocation(
-            expression.fileOffset,
-            target.member,
-            arguments = engine.forest.createArgumentsForExtensionMethod(
-                arguments.fileOffset,
+    return engine.forest.createStaticInvocation(
+        expression.fileOffset,
+        target.member,
+        arguments = engine.forest.createArgumentsForExtensionMethod(
+            arguments.fileOffset,
+            target.inferredExtensionTypeArguments.length,
+            procedure.function.typeParameters.length -
                 target.inferredExtensionTypeArguments.length,
-                procedure.function.typeParameters.length -
-                    target.inferredExtensionTypeArguments.length,
-                receiver,
-                extensionTypeArguments: target.inferredExtensionTypeArguments,
-                positionalArguments: arguments.positional,
-                namedArguments: arguments.named,
-                typeArguments: arguments.types)));
-    return replacement;
+            receiver,
+            extensionTypeArguments: target.inferredExtensionTypeArguments,
+            positionalArguments: arguments.positional,
+            namedArguments: arguments.named,
+            typeArguments: arguments.types));
   }
 
   /// Performs the core type inference algorithm for method invocations (this
@@ -2157,10 +2020,47 @@
     // First infer the receiver so we can look up the method that was invoked.
     ExpressionInferenceResult result =
         inferExpression(node.receiver, const UnknownType(), true);
+    Expression receiver;
+    NullAwareGuard nullAwareGuard;
+    if (isNonNullableByDefault) {
+      nullAwareGuard = result.nullAwareGuard;
+      receiver = result.nullAwareAction;
+    } else {
+      receiver = result.expression;
+    }
     DartType receiverType = result.inferredType;
-    ObjectAccessTarget target = findMethodInvocationMember(receiverType, node);
+    ObjectAccessTarget target = findInterfaceMember(
+        receiverType, node.name, node.fileOffset,
+        instrumented: true, includeExtensionMethods: true);
+    Expression error = reportMissingInterfaceMember(target, receiverType,
+        node.name, node.fileOffset, templateUndefinedMethod);
+    if (target.isInstanceMember) {
+      Member interfaceMember = target.member;
+      if (receiverType == const DynamicType() && interfaceMember is Procedure) {
+        Arguments arguments = node.arguments;
+        FunctionNode signature = interfaceMember.function;
+        if (arguments.positional.length < signature.requiredParameterCount ||
+            arguments.positional.length >
+                signature.positionalParameters.length) {
+          target = const ObjectAccessTarget.unresolved();
+          interfaceMember = null;
+        }
+        for (NamedExpression argument in arguments.named) {
+          if (!signature.namedParameters
+              .any((declaration) => declaration.name == argument.name)) {
+            target = const ObjectAccessTarget.unresolved();
+            interfaceMember = null;
+          }
+        }
+        if (instrumentation != null && interfaceMember != null) {
+          instrumentation.record(uriForInstrumentation, node.fileOffset,
+              'target', new InstrumentationValueForMember(interfaceMember));
+        }
+      }
+      node.interfaceTarget = interfaceMember;
+    }
+
     Name methodName = node.name;
-    Arguments arguments = node.arguments;
     assert(target != null, "No target for ${node}.");
     bool isOverloadedArithmeticOperator =
         isOverloadedArithmeticOperatorAndType(target, receiverType);
@@ -2173,20 +2073,24 @@
         !(calleeType is InterfaceType &&
             calleeType.classNode == coreTypes.functionClass) &&
         identical(functionType, unknownFunction)) {
-      TreeNode parent = node.parent;
       Expression error = helper.wrapInProblem(node,
           templateInvokeNonFunction.withArguments(methodName.name), noLength);
-      parent?.replaceChild(node, error);
-      return const ExpressionInferenceResult(const DynamicType());
+      return new ExpressionInferenceResult(const DynamicType(), error);
     }
     MethodContravarianceCheckKind checkKind = preCheckInvocationContravariance(
         receiverType, target,
-        isThisReceiver: node.receiver is ThisExpression);
-    StaticInvocation replacement;
+        isThisReceiver: receiver is ThisExpression);
+    Expression replacement;
+    Arguments arguments = node.arguments;
     if (target.isExtensionMember) {
-      replacement = transformExtensionMethodInvocation(
-          target, node, node.receiver, arguments);
-      arguments = replacement.arguments;
+      StaticInvocation staticInvocation = transformExtensionMethodInvocation(
+          target, node, receiver, node.arguments);
+      arguments = staticInvocation.arguments;
+      replacement = staticInvocation;
+    } else {
+      node.receiver = receiver..parent = node;
+      arguments = node.arguments;
+      replacement = node;
     }
     DartType inferredType = inferInvocation(
         typeContext, node.fileOffset, functionType, arguments,
@@ -2196,28 +2100,33 @@
     if (methodName.name == '==') {
       inferredType = coreTypes.boolRawType(library.nonNullable);
     }
-    handleInvocationContravariance(checkKind, node, arguments, node,
-        inferredType, functionType, node.fileOffset);
+    replacement = handleInvocationContravariance(checkKind, node, arguments,
+        replacement, inferredType, functionType, node.fileOffset);
+
     if (node.isImplicitCall && target.isInstanceMember) {
       Member member = target.member;
       if (!(member is Procedure && member.kind == ProcedureKind.Method)) {
-        TreeNode parent = node.parent;
-        Expression errorNode = helper.wrapInProblem(
+        Expression error = helper.wrapInProblem(
             node,
             templateImplicitCallOfNonMethod.withArguments(receiverType),
             noLength);
-        parent?.replaceChild(node, errorNode);
+        return new ExpressionInferenceResult(const DynamicType(), error);
       }
     }
     if (!isTopLevel && target.isExtensionMember) {
       library.checkBoundsInStaticInvocation(replacement, typeSchemaEnvironment,
-          helper.uri, getTypeArgumentsInfo(node.arguments));
+          helper.uri, getTypeArgumentsInfo(arguments));
     } else {
       _checkBoundsInMethodInvocation(target, receiverType, calleeType,
           methodName, arguments, node.fileOffset);
     }
+    if (error != null) {
+      // TODO(johnniwinther): Use InvalidType instead.
+      return new ExpressionInferenceResult(const DynamicType(), error);
+    }
 
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult.nullAware(
+        inferredType, replacement, nullAwareGuard);
   }
 
   void _checkBoundsInMethodInvocation(
@@ -2291,11 +2200,9 @@
         !(calleeType is InterfaceType &&
             calleeType.classNode == coreTypes.functionClass) &&
         identical(functionType, unknownFunction)) {
-      TreeNode parent = expression.parent;
       Expression error = helper.wrapInProblem(expression,
           templateInvokeNonFunction.withArguments(methodName.name), noLength);
-      parent?.replaceChild(expression, error);
-      return const ExpressionInferenceResult(const DynamicType());
+      return new ExpressionInferenceResult(const DynamicType(), error);
     }
     DartType inferredType = inferInvocation(
         typeContext, fileOffset, functionType, arguments,
@@ -2308,109 +2215,20 @@
     _checkBoundsInMethodInvocation(
         target, receiverType, calleeType, methodName, arguments, fileOffset);
 
-    return new ExpressionInferenceResult(inferredType);
+    return new ExpressionInferenceResult(inferredType, expression);
   }
 
   @override
-  void inferParameterInitializer(
+  Expression inferParameterInitializer(
       InferenceHelper helper, Expression initializer, DartType declaredType) {
     assert(closureContext == null);
     this.helper = helper;
     assert(declaredType != null);
     ExpressionInferenceResult result =
         inferExpression(initializer, declaredType, true);
-    if (result.replacement != null) {
-      initializer = result.replacement;
-    }
-    ensureAssignable(
-        declaredType, result.inferredType, initializer, initializer.fileOffset);
+    initializer = ensureAssignableResult(declaredType, result);
     this.helper = null;
-  }
-
-  /// Performs the core type inference algorithm for property gets (this handles
-  /// both null-aware and non-null-aware property gets).
-  ExpressionInferenceResult inferPropertyGet(
-      Expression expression,
-      Expression receiver,
-      int fileOffset,
-      DartType typeContext,
-      PropertyGet propertyGet,
-      {VariableDeclaration nullAwareReceiverVariable}) {
-    // First infer the receiver so we can look up the getter that was invoked.
-    DartType receiverType;
-    if (receiver == null) {
-      receiverType = thisType;
-    } else {
-      ExpressionInferenceResult result =
-          inferExpression(receiver, const UnknownType(), true);
-      if (result.replacement != null) {
-        receiver = result.replacement;
-      }
-      receiverType = result.inferredType;
-    }
-    nullAwareReceiverVariable?.type = receiverType;
-    Name propertyName = propertyGet.name;
-    ObjectAccessTarget readTarget = findInterfaceMemberOrReport(receiverType,
-        propertyName, fileOffset, templateUndefinedGetter, expression,
-        includeExtensionMethods: true);
-    if (readTarget.isInstanceMember) {
-      if (instrumentation != null && receiverType == const DynamicType()) {
-        instrumentation.record(uriForInstrumentation, propertyGet.fileOffset,
-            'target', new InstrumentationValueForMember(readTarget.member));
-      }
-      propertyGet.interfaceTarget = readTarget.member;
-    }
-    DartType inferredType = getGetterType(readTarget, receiverType);
-    Expression replacedExpression = handlePropertyGetContravariance(receiver,
-        readTarget, propertyGet, expression, inferredType, fileOffset);
-    Expression replacement;
-    if (readTarget.isInstanceMember) {
-      Member member = readTarget.member;
-      if (member is Procedure && member.kind == ProcedureKind.Method) {
-        inferredType =
-            instantiateTearOff(inferredType, typeContext, replacedExpression);
-      }
-    } else if (readTarget.isExtensionMember) {
-      int fileOffset = expression.fileOffset;
-      switch (readTarget.extensionMethodKind) {
-        case ProcedureKind.Getter:
-          expression.parent.replaceChild(
-              expression,
-              replacement = expression = engine.forest.createStaticInvocation(
-                  fileOffset,
-                  readTarget.member,
-                  engine.forest.createArgumentsForExtensionMethod(
-                      fileOffset,
-                      readTarget.inferredExtensionTypeArguments.length,
-                      0,
-                      receiver,
-                      extensionTypeArguments:
-                          readTarget.inferredExtensionTypeArguments)));
-          break;
-        case ProcedureKind.Method:
-          expression.parent.replaceChild(
-              expression,
-              replacement = expression = engine.forest.createStaticInvocation(
-                  fileOffset,
-                  readTarget.tearoffTarget,
-                  engine.forest.createArgumentsForExtensionMethod(
-                      fileOffset,
-                      readTarget.inferredExtensionTypeArguments.length,
-                      0,
-                      receiver,
-                      extensionTypeArguments:
-                          readTarget.inferredExtensionTypeArguments)));
-          inferredType =
-              instantiateTearOff(inferredType, typeContext, expression);
-          break;
-        case ProcedureKind.Setter:
-        case ProcedureKind.Factory:
-        case ProcedureKind.Operator:
-          unhandled('$readTarget', "inferPropertyGet", null, null);
-          break;
-      }
-    }
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return initializer;
   }
 
   /// Performs the core type inference algorithm for super property get.
@@ -2418,15 +2236,13 @@
       DartType typeContext, ObjectAccessTarget readTarget) {
     DartType receiverType = thisType;
     DartType inferredType = getGetterType(readTarget, receiverType);
-    Expression replacement;
     if (readTarget.isInstanceMember) {
       Member member = readTarget.member;
       if (member is Procedure && member.kind == ProcedureKind.Method) {
-        inferredType =
-            instantiateTearOff(inferredType, typeContext, expression);
+        return instantiateTearOff(inferredType, typeContext, expression);
       }
     }
-    return new ExpressionInferenceResult(inferredType, replacement);
+    return new ExpressionInferenceResult(inferredType, expression);
   }
 
   /// Modifies a type as appropriate when inferring a closure return type.
@@ -2438,35 +2254,42 @@
   ///
   /// Derived classes should override this method with logic that dispatches on
   /// the statement type and calls the appropriate specialized "infer" method.
-  void inferStatement(Statement statement);
+  void inferStatement(Statement statement) {
+    registerIfUnreachableForTesting(statement);
+
+    // For full (non-top level) inference, we need access to the
+    // ExpressionGeneratorHelper so that we can perform error recovery.
+    if (!isTopLevel) assert(helper != null);
+    if (statement != null) {
+      statement.accept(new InferenceVisitor(this));
+    }
+  }
 
   /// Performs the type inference steps necessary to instantiate a tear-off
   /// (if necessary).
-  DartType instantiateTearOff(
+  ExpressionInferenceResult instantiateTearOff(
       DartType tearoffType, DartType context, Expression expression) {
     if (tearoffType is FunctionType &&
         context is FunctionType &&
         context.typeParameters.isEmpty) {
-      List<TypeParameter> typeParameters = tearoffType.typeParameters;
+      FunctionType functionType = tearoffType;
+      List<TypeParameter> typeParameters = functionType.typeParameters;
       if (typeParameters.isNotEmpty) {
         List<DartType> inferredTypes = new List<DartType>.filled(
             typeParameters.length, const UnknownType());
-        FunctionType instantiatedType = tearoffType.withoutTypeParameters;
+        FunctionType instantiatedType = functionType.withoutTypeParameters;
         typeSchemaEnvironment.inferGenericFunctionOrType(
             instantiatedType, typeParameters, [], [], context, inferredTypes);
         if (!isTopLevel) {
-          TreeNode parent = expression.parent;
-          parent.replaceChild(
-              expression,
-              new Instantiation(expression, inferredTypes)
-                ..fileOffset = expression.fileOffset);
+          expression = new Instantiation(expression, inferredTypes)
+            ..fileOffset = expression.fileOffset;
         }
         Substitution substitution =
             Substitution.fromPairs(typeParameters, inferredTypes);
-        return substitution.substituteType(instantiatedType);
+        tearoffType = substitution.substituteType(instantiatedType);
       }
     }
-    return tearoffType;
+    return new ExpressionInferenceResult(tearoffType, expression);
   }
 
   /// True if the returned [type] has non-covariant occurrences of any of
@@ -2587,16 +2410,6 @@
     return new InterfaceType(class_, <DartType>[type ?? const DynamicType()]);
   }
 
-  void _forEachArgument(
-      Arguments arguments, void callback(String name, Expression expression)) {
-    for (Expression expression in arguments.positional) {
-      callback(null, expression);
-    }
-    for (NamedExpression namedExpression in arguments.named) {
-      callback(namedExpression.name, namedExpression.value);
-    }
-  }
-
   Member _getInterfaceMember(
       Class class_, Name name, bool setter, int charOffset) {
     Member member = engine.hierarchyBuilder.getCombinedMemberSignatureKernel(
@@ -2666,6 +2479,115 @@
     }
     return false;
   }
+
+  Expression createMissingSuperIndexGet(int fileOffset, Expression index) {
+    if (isTopLevel) {
+      return engine.forest.createSuperMethodInvocation(fileOffset, indexGetName,
+          null, engine.forest.createArguments(fileOffset, <Expression>[index]));
+    } else {
+      return helper.buildProblem(
+          templateSuperclassHasNoMethod.withArguments(indexGetName.name),
+          fileOffset,
+          noLength);
+    }
+  }
+
+  Expression createMissingSuperIndexSet(
+      int fileOffset, Expression index, Expression value) {
+    if (isTopLevel) {
+      return engine.forest.createSuperMethodInvocation(
+          fileOffset,
+          indexSetName,
+          null,
+          engine.forest
+              .createArguments(fileOffset, <Expression>[index, value]));
+    } else {
+      return helper.buildProblem(
+          templateSuperclassHasNoMethod.withArguments(indexSetName.name),
+          fileOffset,
+          noLength);
+    }
+  }
+
+  Expression createMissingPropertyGet(int fileOffset, Expression receiver,
+      DartType receiverType, Name propertyName) {
+    if (isTopLevel) {
+      return engine.forest
+          .createPropertyGet(fileOffset, receiver, propertyName);
+    } else {
+      return helper.buildProblem(
+          templateUndefinedGetter.withArguments(
+              propertyName.name, resolveTypeParameter(receiverType)),
+          fileOffset,
+          propertyName.name.length);
+    }
+  }
+
+  Expression createMissingPropertySet(int fileOffset, Expression receiver,
+      DartType receiverType, Name propertyName, Expression value,
+      {bool forEffect}) {
+    assert(forEffect != null);
+    if (isTopLevel) {
+      return engine.forest.createPropertySet(
+          fileOffset, receiver, propertyName, value,
+          forEffect: forEffect);
+    } else {
+      return helper.buildProblem(
+          templateUndefinedSetter.withArguments(
+              propertyName.name, resolveTypeParameter(receiverType)),
+          fileOffset,
+          propertyName.name.length);
+    }
+  }
+
+  Expression createMissingIndexGet(int fileOffset, Expression receiver,
+      DartType receiverType, Expression index) {
+    if (isTopLevel) {
+      return engine.forest.createMethodInvocation(
+          fileOffset,
+          receiver,
+          indexGetName,
+          engine.forest.createArguments(fileOffset, <Expression>[index]));
+    } else {
+      return helper.buildProblem(
+          templateUndefinedMethod.withArguments(
+              indexGetName.name, resolveTypeParameter(receiverType)),
+          fileOffset,
+          noLength);
+    }
+  }
+
+  Expression createMissingIndexSet(int fileOffset, Expression receiver,
+      DartType receiverType, Expression index, Expression value) {
+    if (isTopLevel) {
+      return engine.forest.createMethodInvocation(
+          fileOffset,
+          receiver,
+          indexSetName,
+          engine.forest
+              .createArguments(fileOffset, <Expression>[index, value]));
+    } else {
+      return helper.buildProblem(
+          templateUndefinedMethod.withArguments(
+              indexSetName.name, resolveTypeParameter(receiverType)),
+          fileOffset,
+          noLength);
+    }
+  }
+
+  Expression createMissingBinary(int fileOffset, Expression left,
+      DartType leftType, Name binaryName, Expression right) {
+    if (isTopLevel) {
+      return engine.forest.createMethodInvocation(fileOffset, left, binaryName,
+          engine.forest.createArguments(fileOffset, <Expression>[right]));
+    } else {
+      return helper.buildProblem(
+          templateUndefinedMethod.withArguments(
+              binaryName.name, resolveTypeParameter(leftType)),
+          fileOffset,
+          binaryName.name.length);
+    }
+  }
 }
 
 abstract class MixinInferrer {
@@ -2816,10 +2738,108 @@
   /// The inferred type of the expression.
   final DartType inferredType;
 
-  /// If not-null, the [replacement] that replaced the inferred expression.
-  final Expression replacement;
+  /// The inferred expression.
+  final Expression expression;
 
-  const ExpressionInferenceResult(this.inferredType, [this.replacement]);
+  factory ExpressionInferenceResult.nullAware(
+      DartType inferredType, Expression expression,
+      [NullAwareGuard nullAwareGuard]) {
+    if (nullAwareGuard != null) {
+      return new NullAwareExpressionInferenceResult(
+          inferredType, nullAwareGuard, expression);
+    } else {
+      return new ExpressionInferenceResult(inferredType, expression);
+    }
+  }
+
+  ExpressionInferenceResult(this.inferredType, this.expression)
+      : assert(expression != null);
+
+  /// The guard used for null-aware access if the expression is part of a
+  /// null-shorting, and `null` otherwise.
+  NullAwareGuard get nullAwareGuard => null;
+
+  /// If the expression is part of a null-shorting, the action performed on
+  /// the variable in [nullAwareGuard]. Otherwise, this is the same as
+  /// [expression].
+  Expression get nullAwareAction => expression;
+
+  String toString() => 'ExpressionInferenceResult($inferredType,$expression)';
+}
+
+/// A guard used for creating null-shorting null-aware actions.
+class NullAwareGuard {
+  /// The variable used to guard the null-aware action.
+  final VariableDeclaration _nullAwareVariable;
+
+  /// The file offset used for the null-test.
+  int _nullAwareFileOffset;
+
+  /// The [Member] used for the == call.
+  final Member _nullAwareEquals;
+
+  NullAwareGuard(
+      this._nullAwareVariable, this._nullAwareFileOffset, this._nullAwareEquals)
+      : assert(_nullAwareVariable != null),
+        assert(_nullAwareFileOffset != null),
+        assert(_nullAwareEquals != null);
+
+  /// Creates the null-guarded application of [nullAwareAction] with the
+  /// [inferredType].
+  ///
+  /// For an null-aware action `v.e` on the [_nullAwareVariable] `v` the created
+  /// expression is
+  ///
+  ///     let v in v == null ? null : v.e
+  ///
+  Expression createExpression(
+      DartType inferredType, Expression nullAwareAction) {
+    MethodInvocation equalsNull = createEqualsNull(_nullAwareFileOffset,
+        createVariableGet(_nullAwareVariable), _nullAwareEquals);
+    ConditionalExpression condition = new ConditionalExpression(
+        equalsNull,
+        new NullLiteral()..fileOffset = _nullAwareFileOffset,
+        nullAwareAction,
+        inferredType);
+    return new Let(_nullAwareVariable, condition)
+      ..fileOffset = _nullAwareFileOffset;
+  }
+
+  String toString() =>
+      'NullAwareGuard($_nullAwareVariable,$_nullAwareFileOffset,'
+      '$_nullAwareEquals)';
+}
+
+/// The result of an expression inference that is guarded with a null aware
+/// variable.
+class NullAwareExpressionInferenceResult implements ExpressionInferenceResult {
+  /// The inferred type of the expression.
+  final DartType inferredType;
+
+  @override
+  final NullAwareGuard nullAwareGuard;
+
+  @override
+  final Expression nullAwareAction;
+
+  Expression _expression;
+
+  NullAwareExpressionInferenceResult(
+      this.inferredType, this.nullAwareGuard, this.nullAwareAction)
+      : assert(nullAwareGuard != null),
+        assert(nullAwareAction != null);
+
+  Expression get expression {
+    if (_expression == null) {
+      _expression ??=
+          nullAwareGuard.createExpression(inferredType, nullAwareAction);
+    }
+    return _expression;
+  }
+
+  String toString() =>
+      'NullAwareExpressionInferenceResult($inferredType,$nullAwareGuard,'
+      '$nullAwareAction)';
 }
 
 enum ObjectAccessTargetKind {
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 00f3516..d89869f 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
@@ -119,6 +119,9 @@
   DartType visitDynamicType(DynamicType node) => null;
 
   @override
+  DartType visitNeverType(NeverType node) => null;
+
+  @override
   DartType visitInvalidType(InvalidType node) => null;
 
   @override
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 8339567..eeecd4f 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
@@ -102,6 +102,8 @@
 
   Class get futureOrClass => coreTypes.futureOrClass;
 
+  Class get objectClass => coreTypes.objectClass;
+
   InterfaceType getLegacyLeastUpperBound(
       InterfaceType type1, InterfaceType type2) {
     return hierarchy.getLegacyLeastUpperBound(type1, type2, this.coreTypes);
@@ -122,11 +124,15 @@
     // TODO(paulberry): this matches what is defined in the spec.  It would be
     // nice if we could change kernel to match the spec and not have to
     // override.
-    if (type1 == coreTypes.intLegacyRawType) {
-      if (type2 == coreTypes.intLegacyRawType) return type2;
-      if (type2 == coreTypes.doubleLegacyRawType) return type2;
+    if (type1 is InterfaceType && type1.classNode == coreTypes.intClass) {
+      if (type2 is InterfaceType && type2.classNode == coreTypes.intClass) {
+        return type2;
+      }
+      if (type2 is InterfaceType && type2.classNode == coreTypes.doubleClass) {
+        return type2;
+      }
     }
-    return coreTypes.numLegacyRawType;
+    return coreTypes.numRawType(type1.nullability);
   }
 
   /// Infers a generic type, function, method, or list/map literal
diff --git a/pkg/front_end/lib/src/fasta/uri_translator.dart b/pkg/front_end/lib/src/fasta/uri_translator.dart
index bb2b025..41663d4 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator.dart
@@ -4,12 +4,13 @@
 
 library fasta.uri_translator;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:package_config/packages.dart' show Packages;
 
 import '../base/libraries_specification.dart' show TargetLibrariesSpecification;
 import 'compiler_context.dart' show CompilerContext;
 import 'fasta_codes.dart';
-import 'severity.dart' show Severity;
 
 class UriTranslator {
   final TargetLibrariesSpecification dartLibraries;
diff --git a/pkg/front_end/lib/src/fasta/util/link.dart b/pkg/front_end/lib/src/fasta/util/link.dart
deleted file mode 100644
index 3f7a204..0000000
--- a/pkg/front_end/lib/src/fasta/util/link.dart
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.util.link;
-
-import 'link_implementation.dart'
-    show LinkBuilderImplementation, LinkEntry, LinkIterator, MappedLinkIterable;
-
-class Link<T> implements Iterable<T> {
-  T get head => throw new StateError("no elements");
-  Link<T> get tail => null;
-
-  const Link();
-
-  Link<T> prepend(T element) {
-    return new LinkEntry<T>(element, this);
-  }
-
-  Iterator<T> get iterator => new LinkIterator<T>(this);
-
-  void printOn(StringBuffer buffer, [separatedBy]) {}
-
-  List<T> toList({bool growable: true}) {
-    List<T> result;
-    if (!growable) {
-      result = new List<T>(slowLength());
-    } else {
-      result = new List<T>();
-      result.length = slowLength();
-    }
-    int i = 0;
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      result[i++] = link.head;
-    }
-    return result;
-  }
-
-  /// Lazily maps over this linked list, returning an [Iterable].
-  Iterable<K> map<K>(K fn(T item)) {
-    return new MappedLinkIterable<T, K>(this, fn);
-  }
-
-  /// 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;
-    if (!growable) {
-      result = new List<E>(slowLength());
-    } else {
-      result = new List<E>();
-      result.length = slowLength();
-    }
-    int i = 0;
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      result[i++] = fn(link.head);
-    }
-    return result;
-  }
-
-  bool get isEmpty => true;
-  bool get isNotEmpty => false;
-
-  Link<T> reverse(Link<T> tail) => this;
-
-  Link<T> reversePrependAll(Link<T> from) {
-    if (from.isEmpty) return this;
-    return this.prepend(from.head).reversePrependAll(from.tail);
-  }
-
-  Link<T> skip(int n) {
-    if (n == 0) return this;
-    throw new RangeError('Index $n out of range');
-  }
-
-  void forEach(void f(T element)) {}
-
-  bool operator ==(other) {
-    if (other is! Link<T>) return false;
-    return other.isEmpty;
-  }
-
-  int get hashCode => throw new UnsupportedError('Link.hashCode');
-
-  String toString() => "[]";
-
-  get length {
-    throw new UnsupportedError('get:length');
-  }
-
-  int slowLength() => 0;
-
-  // TODO(ahe): Remove this method?
-  bool contains(Object element) {
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      if (link.head == element) return true;
-    }
-    return false;
-  }
-
-  // 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');
-    return head;
-  }
-
-  // TODO(ahe): Remove this method?
-  T get first {
-    if (isEmpty) throw new StateError('No elements');
-    return head;
-  }
-
-  /// Returns true if f returns true for all elements of this list.
-  ///
-  /// Returns true for the empty list.
-  bool every(bool f(T e)) {
-    for (Link<T> link = this; !link.isEmpty; link = link.tail) {
-      if (!f(link.head)) return false;
-    }
-    return true;
-  }
-
-  //
-  // Unsupported Iterable<T> methods.
-  //
-  bool any(bool f(T e)) => _unsupported('any');
-  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');
-  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');
-  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');
-  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');
-  Set<T> toSet() => _unsupported('toSet');
-  Iterable<T> whereType<T>() => _unsupported('whereType');
-  Iterable<T> where(bool f(T e)) => _unsupported('where');
-
-  _unsupported(String method) => throw new UnsupportedError(method);
-}
-
-/// Builder object for creating linked lists using [Link] or fixed-length [List]
-/// objects.
-abstract class LinkBuilder<T> {
-  factory LinkBuilder() = LinkBuilderImplementation<T>;
-
-  /// Prepends all elements added to the builder to [tail]. The resulting list
-  /// is returned and the builder is cleared.
-  Link<T> toLink(Link<T> tail);
-
-  /// Creates a new fixed length containing all added elements. The
-  /// resulting list is returned and the builder is cleared.
-  List<T> toList();
-
-  /// Adds the element [t] to the end of the list being built.
-  Link<T> addLast(T t);
-
-  /// Returns the first element in the list being built.
-  T get first;
-
-  /// Returns the number of elements in the list being built.
-  final int length;
-
-  /// Returns `true` if the list being built is empty.
-  final bool isEmpty;
-
-  /// Removes all added elements and resets the builder.
-  void clear();
-}
diff --git a/pkg/front_end/lib/src/fasta/util/link_implementation.dart b/pkg/front_end/lib/src/fasta/util/link_implementation.dart
deleted file mode 100644
index 091d055..0000000
--- a/pkg/front_end/lib/src/fasta/util/link_implementation.dart
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.util.link_implementation;
-
-import 'dart:collection' show IterableBase;
-
-import 'link.dart' show Link, LinkBuilder;
-
-class LinkIterator<T> implements Iterator<T> {
-  T _current;
-  Link<T> _link;
-
-  LinkIterator(this._link);
-
-  T get current => _current;
-
-  bool moveNext() {
-    if (_link.isEmpty) {
-      _current = null;
-      return false;
-    }
-    _current = _link.head;
-    _link = _link.tail;
-    return true;
-  }
-}
-
-typedef T Transformation<S, T>(S input);
-
-class MappedLinkIterator<S, T> extends Iterator<T> {
-  Transformation<S, T> _transformation;
-  Link<S> _link;
-  T _current;
-
-  MappedLinkIterator(this._link, this._transformation);
-
-  T get current => _current;
-
-  bool moveNext() {
-    if (_link.isEmpty) {
-      _current = null;
-      return false;
-    }
-    _current = _transformation(_link.head);
-    _link = _link.tail;
-    return true;
-  }
-}
-
-class MappedLinkIterable<S, T> extends IterableBase<T> {
-  Transformation<S, T> _transformation;
-  Link<S> _link;
-
-  MappedLinkIterable(this._link, this._transformation);
-
-  Iterator<T> get iterator {
-    return new MappedLinkIterator<S, T>(_link, _transformation);
-  }
-}
-
-class LinkEntry<T> extends Link<T> {
-  final T head;
-  Link<T> tail;
-
-  LinkEntry(this.head, [Link<T> tail]) : tail = tail ?? const Link<Null>();
-
-  Link<T> prepend(T element) {
-    // TODO(ahe): Use new Link<T>, but this cost 8% performance on VM.
-    return new LinkEntry<T>(element, this);
-  }
-
-  void printOn(StringBuffer buffer, [separatedBy]) {
-    buffer.write(head);
-    if (separatedBy == null) separatedBy = '';
-    for (Link<T> link = tail; link.isNotEmpty; link = link.tail) {
-      buffer.write(separatedBy);
-      buffer.write(link.head);
-    }
-  }
-
-  String toString() {
-    StringBuffer buffer = new StringBuffer();
-    buffer.write('[ ');
-    printOn(buffer, ', ');
-    buffer.write(' ]');
-    return buffer.toString();
-  }
-
-  @override
-  Link<T> reverse(Link<T> tail) {
-    Link<T> result = tail;
-    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
-      result = result.prepend(link.head);
-    }
-    return result;
-  }
-
-  Link<T> reversePrependAll(Link<T> from) {
-    Link<T> result;
-    for (result = this; from.isNotEmpty; from = from.tail) {
-      result = result.prepend(from.head);
-    }
-    return result;
-  }
-
-  Link<T> skip(int n) {
-    Link<T> link = this;
-    for (int i = 0; i < n; i++) {
-      if (link.isEmpty) {
-        throw new RangeError('Index $n out of range');
-      }
-      link = link.tail;
-    }
-    return link;
-  }
-
-  bool get isEmpty => false;
-  bool get isNotEmpty => true;
-
-  void forEach(void f(T element)) {
-    for (Link<T> link = this; link.isNotEmpty; link = link.tail) {
-      f(link.head);
-    }
-  }
-
-  bool operator ==(other) {
-    if (other is! Link<T>) return false;
-    Link<T> myElements = this;
-    while (myElements.isNotEmpty && other.isNotEmpty) {
-      if (myElements.head != other.head) {
-        return false;
-      }
-      myElements = myElements.tail;
-      other = other.tail;
-    }
-    return myElements.isEmpty && other.isEmpty;
-  }
-
-  int get hashCode => throw new UnsupportedError('LinkEntry.hashCode');
-
-  int slowLength() {
-    int length = 0;
-    for (Link<T> current = this; current.isNotEmpty; current = current.tail) {
-      ++length;
-    }
-    return length;
-  }
-}
-
-class LinkBuilderImplementation<T> implements LinkBuilder<T> {
-  LinkEntry<T> head = null;
-  LinkEntry<T> lastLink = null;
-  int length = 0;
-
-  LinkBuilderImplementation();
-
-  @override
-  Link<T> toLink(Link<T> tail) {
-    if (head == null) return tail;
-    lastLink.tail = tail;
-    Link<T> link = head;
-    lastLink = null;
-    head = null;
-    length = 0;
-    return link;
-  }
-
-  List<T> toList() {
-    if (length == 0) return new List<T>(0);
-    List<T> list = new List<T>(length);
-    int index = 0;
-    Link<T> link = head;
-    while (link.isNotEmpty) {
-      list[index] = link.head;
-      link = link.tail;
-      index++;
-    }
-    lastLink = null;
-    head = null;
-    length = 0;
-    return list;
-  }
-
-  Link<T> addLast(T t) {
-    length++;
-    LinkEntry<T> entry = new LinkEntry<T>(t, null);
-    if (head == null) {
-      head = entry;
-    } else {
-      lastLink.tail = entry;
-    }
-    lastLink = entry;
-    return entry;
-  }
-
-  bool get isEmpty => length == 0;
-
-  T get first {
-    if (head != null) {
-      return head.head;
-    }
-    throw new StateError("no elements");
-  }
-
-  void clear() {
-    head = null;
-    lastLink = null;
-    length = 0;
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/util/relativize.dart b/pkg/front_end/lib/src/fasta/util/relativize.dart
deleted file mode 100644
index df4f926..0000000
--- a/pkg/front_end/lib/src/fasta/util/relativize.dart
+++ /dev/null
@@ -1,73 +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.
-
-library fasta.util.relativize;
-
-import 'dart:math';
-
-String relativizeUri(Uri base, Uri uri, bool isWindows) {
-  bool equalsNCS(String a, String b) {
-    return a.toLowerCase() == b.toLowerCase();
-  }
-
-  if (!equalsNCS(base.scheme, uri.scheme) ||
-      equalsNCS(base.scheme, 'dart') ||
-      equalsNCS(base.scheme, 'package')) {
-    return uri.toString();
-  }
-
-  if (!equalsNCS(base.scheme, 'file')) {
-    isWindows = false;
-  }
-
-  String normalize(String path) {
-    if (isWindows) {
-      return path.toLowerCase();
-    } else {
-      return path;
-    }
-  }
-
-  if (base.userInfo == uri.userInfo &&
-      equalsNCS(base.host, uri.host) &&
-      base.port == uri.port &&
-      uri.query == "" &&
-      uri.fragment == "") {
-    if (normalize(uri.path).startsWith(normalize(base.path))) {
-      return uri.path.substring(base.path.lastIndexOf('/') + 1);
-    }
-
-    if (!base.path.startsWith('/') || !uri.path.startsWith('/')) {
-      return uri.toString();
-    }
-
-    List<String> uriParts = uri.path.split('/');
-    List<String> baseParts = base.path.split('/');
-    int common = 0;
-    int length = min(uriParts.length, baseParts.length);
-    while (common < length &&
-        normalize(uriParts[common]) == normalize(baseParts[common])) {
-      common++;
-    }
-    if (common == 1 || (isWindows && common == 2)) {
-      // The first part will always be an empty string because the
-      // paths are absolute. On Windows, we must also consider drive
-      // letters or hostnames.
-      if (baseParts.length > common + 1) {
-        // Avoid using '..' to go to the root, unless we are already there.
-        return uri.path;
-      }
-    }
-    StringBuffer sb = new StringBuffer();
-    for (int i = common + 1; i < baseParts.length; i++) {
-      sb.write('../');
-    }
-    for (int i = common; i < uriParts.length - 1; i++) {
-      sb.write('${uriParts[i]}/');
-    }
-    sb.write('${uriParts.last}');
-    return sb.toString();
-  }
-  return uri.toString();
-}
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 8240c92..956b470 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -7,7 +7,8 @@
 
 import 'dart:async' show Future;
 
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/kernel.dart' show Component, CanonicalName;
 
 import 'base/processed_options.dart' show ProcessedOptions;
@@ -20,6 +21,8 @@
 
 import 'fasta/fasta_codes.dart' show LocatedMessage;
 
+import 'fasta/kernel/kernel_api.dart';
+
 import 'fasta/kernel/kernel_target.dart' show KernelTarget;
 
 import 'fasta/kernel/utils.dart' show printComponentText, serializeComponent;
@@ -28,8 +31,6 @@
 
 import 'fasta/loader.dart' show Loader;
 
-import 'fasta/severity.dart' show Severity;
-
 import 'fasta/uri_translator.dart' show UriTranslator;
 
 import 'api_prototype/front_end.dart' show CompilerResult;
diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
deleted file mode 100644
index 2836434..0000000
--- a/pkg/front_end/lib/src/scanner/errors.dart
+++ /dev/null
@@ -1,193 +0,0 @@
-// 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.
-
-import '../base/errors.dart';
-import '../fasta/fasta_codes.dart';
-import '../fasta/scanner/error_token.dart';
-import 'token.dart' show Token, TokenType;
-import '../fasta/scanner/token_constants.dart';
-
-/**
- * The error codes used for errors detected by the scanner.
- */
-class ScannerErrorCode extends ErrorCode {
-  /**
-   * Parameters:
-   * 0: the token that was expected but not found
-   */
-  static const ScannerErrorCode EXPECTED_TOKEN =
-      const ScannerErrorCode('EXPECTED_TOKEN', "Expected to find '{0}'.");
-
-  /**
-   * Parameters:
-   * 0: the illegal character
-   */
-  static const ScannerErrorCode ILLEGAL_CHARACTER =
-      const ScannerErrorCode('ILLEGAL_CHARACTER', "Illegal character '{0}'.");
-
-  static const ScannerErrorCode MISSING_DIGIT =
-      const ScannerErrorCode('MISSING_DIGIT', "Decimal digit expected.");
-
-  static const ScannerErrorCode MISSING_HEX_DIGIT = const ScannerErrorCode(
-      'MISSING_HEX_DIGIT', "Hexadecimal digit expected.");
-
-  static const ScannerErrorCode MISSING_IDENTIFIER =
-      const ScannerErrorCode('MISSING_IDENTIFIER', "Expected an identifier.");
-
-  static const ScannerErrorCode MISSING_QUOTE =
-      const ScannerErrorCode('MISSING_QUOTE', "Expected quote (' or \").");
-
-  /**
-   * Parameters:
-   * 0: the path of the file that cannot be read
-   */
-  static const ScannerErrorCode UNABLE_GET_CONTENT = const ScannerErrorCode(
-      'UNABLE_GET_CONTENT', "Unable to get content of '{0}'.");
-
-  static const ScannerErrorCode UNEXPECTED_DOLLAR_IN_STRING =
-      const ScannerErrorCode(
-          'UNEXPECTED_DOLLAR_IN_STRING',
-          "A '\$' has special meaning inside a string, and must be followed by "
-              "an identifier or an expression in curly braces ({}).",
-          correction: "Try adding a backslash (\\) to escape the '\$'.");
-
-  /**
-   * Parameters:
-   * 0: the unsupported operator
-   */
-  static const ScannerErrorCode UNSUPPORTED_OPERATOR = const ScannerErrorCode(
-      'UNSUPPORTED_OPERATOR', "The '{0}' operator is not supported.");
-
-  static const ScannerErrorCode UNTERMINATED_MULTI_LINE_COMMENT =
-      const ScannerErrorCode(
-          'UNTERMINATED_MULTI_LINE_COMMENT', "Unterminated multi-line comment.",
-          correction: "Try terminating the comment with '*/', or "
-              "removing any unbalanced occurrences of '/*'"
-              " (because comments nest in Dart).");
-
-  static const ScannerErrorCode UNTERMINATED_STRING_LITERAL =
-      const ScannerErrorCode(
-          'UNTERMINATED_STRING_LITERAL', "Unterminated string literal.");
-
-  /**
-   * Initialize a newly created error code to have the given [name]. The message
-   * associated with the error will be created from the given [message]
-   * template. The correction associated with the error will be created from the
-   * given [correction] template.
-   */
-  const ScannerErrorCode(String name, String message, {String correction})
-      : super.temporary(name, message, correction: correction);
-
-  @override
-  ErrorSeverity get errorSeverity => ErrorSeverity.ERROR;
-
-  @override
-  ErrorType get type => ErrorType.SYNTACTIC_ERROR;
-}
-
-/**
- * Used to report a scan error at the given offset.
- * The [errorCode] is the error code indicating the nature of the error.
- * The [arguments] are any arguments needed to complete the error message.
- */
-typedef ReportError(
-    ScannerErrorCode errorCode, int offset, List<Object> arguments);
-
-/**
- *  Translates the given error [token] into an analyzer error and reports it
- *  using [reportError].
- */
-void translateErrorToken(ErrorToken token, ReportError reportError) {
-  int charOffset = token.charOffset;
-  // TODO(paulberry,ahe): why is endOffset sometimes null?
-  int endOffset = token.endOffset ?? charOffset;
-  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.
-      // TODO(paulberry,ahe): would it make sense to replicate this behavior
-      // in fasta, or move it elsewhere in analyzer?
-      charOffset--;
-    }
-    reportError(errorCode, charOffset, arguments);
-  }
-
-  Code<dynamic> errorCode = token.errorCode;
-  switch (errorCode.analyzerCodes?.first) {
-    case "UNTERMINATED_STRING_LITERAL":
-      // TODO(paulberry,ahe): Fasta reports the error location as the entire
-      // string; analyzer expects the end of the string.
-      reportError(
-          ScannerErrorCode.UNTERMINATED_STRING_LITERAL, endOffset - 1, null);
-      return;
-
-    case "UNTERMINATED_MULTI_LINE_COMMENT":
-      // TODO(paulberry,ahe): Fasta reports the error location as the entire
-      // comment; analyzer expects the end of the comment.
-      reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT,
-          endOffset - 1, null);
-      return;
-
-    case "MISSING_DIGIT":
-      // TODO(paulberry,ahe): Fasta reports the error location as the entire
-      // number; analyzer expects the end of the number.
-      charOffset = endOffset - 1;
-      return _makeError(ScannerErrorCode.MISSING_DIGIT, null);
-
-    case "MISSING_HEX_DIGIT":
-      // TODO(paulberry,ahe): Fasta reports the error location as the entire
-      // number; analyzer expects the end of the number.
-      charOffset = endOffset - 1;
-      return _makeError(ScannerErrorCode.MISSING_HEX_DIGIT, null);
-
-    case "ILLEGAL_CHARACTER":
-      return _makeError(ScannerErrorCode.ILLEGAL_CHARACTER, [token.character]);
-
-    case "UNSUPPORTED_OPERATOR":
-      return _makeError(ScannerErrorCode.UNSUPPORTED_OPERATOR,
-          [(token as UnsupportedOperator).token.lexeme]);
-
-    default:
-      if (errorCode == codeUnmatchedToken) {
-        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, ['}']);
-        }
-        if (type == TokenType.OPEN_SQUARE_BRACKET ||
-            type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET) {
-          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, [']']);
-        }
-        if (type == TokenType.OPEN_PAREN) {
-          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, [')']);
-        }
-        if (type == TokenType.LT) {
-          return _makeError(ScannerErrorCode.EXPECTED_TOKEN, ['>']);
-        }
-      } else if (errorCode == codeUnexpectedDollarInString) {
-        return _makeError(ScannerErrorCode.MISSING_IDENTIFIER, null);
-      }
-      throw new UnimplementedError(
-          '$errorCode "${errorCode.analyzerCodes?.first}"');
-  }
-}
-
-/**
- * Determines whether the given [charOffset], which came from the non-EOF token
- * [token], represents the end of the input.
- */
-bool _isAtEnd(Token token, int charOffset) {
-  while (true) {
-    // Skip to the next token.
-    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;
-    // If we've found a non-error token, then we know there is additional input
-    // text after [charOffset].
-    if (token.type.kind != BAD_INPUT_TOKEN) return false;
-    // Otherwise keep looking.
-  }
-}
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
deleted file mode 100644
index b74e169..0000000
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ /dev/null
@@ -1,1737 +0,0 @@
-// 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.
-
-/**
- * Defines the tokens that are produced by the scanner, used by the parser, and
- * referenced from the [AST structure](ast.dart).
- */
-import 'dart:collection';
-
-import '../base/syntactic_entity.dart';
-import '../fasta/scanner/token_constants.dart';
-import 'string_utilities.dart';
-
-const int NO_PRECEDENCE = 0;
-const int ASSIGNMENT_PRECEDENCE = 1;
-const int CASCADE_PRECEDENCE = 2;
-const int CONDITIONAL_PRECEDENCE = 3;
-const int IF_NULL_PRECEDENCE = 4;
-const int LOGICAL_OR_PRECEDENCE = 5;
-const int LOGICAL_AND_PRECEDENCE = 6;
-const int EQUALITY_PRECEDENCE = 7;
-const int RELATIONAL_PRECEDENCE = 8;
-const int BITWISE_OR_PRECEDENCE = 9;
-const int BITWISE_XOR_PRECEDENCE = 10;
-const int BITWISE_AND_PRECEDENCE = 11;
-const int SHIFT_PRECEDENCE = 12;
-const int ADDITIVE_PRECEDENCE = 13;
-const int MULTIPLICATIVE_PRECEDENCE = 14;
-const int PREFIX_PRECEDENCE = 15;
-const int POSTFIX_PRECEDENCE = 16;
-const int SELECTOR_PRECEDENCE = 17;
-
-/**
- * The opening half of a grouping pair of tokens. This is used for curly
- * brackets ('{'), parentheses ('('), and square brackets ('[').
- */
-class BeginToken extends SimpleToken {
-  /**
-   * The token that corresponds to this token.
-   */
-  Token endToken;
-
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset].
-   */
-  BeginToken(TokenType type, int offset, [CommentToken precedingComment])
-      : super(type, offset, precedingComment) {
-    assert(type == TokenType.LT ||
-        type == TokenType.OPEN_CURLY_BRACKET ||
-        type == TokenType.OPEN_PAREN ||
-        type == TokenType.OPEN_SQUARE_BRACKET ||
-        type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
-        type == TokenType.STRING_INTERPOLATION_EXPRESSION);
-  }
-
-  @override
-  Token copy() => new BeginToken(type, offset, copyComments(precedingComments));
-
-  @override
-  Token get endGroup => endToken;
-
-  /**
-   * Set the token that corresponds to this token.
-   */
-  set endGroup(Token token) {
-    endToken = token;
-  }
-}
-
-/**
- * A token representing a comment.
- */
-class CommentToken extends StringToken {
-  /**
-   * The token that contains this comment.
-   */
-  SimpleToken parent;
-
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  CommentToken(TokenType type, String value, int offset)
-      : super(type, value, offset);
-
-  @override
-  CommentToken copy() => new CommentToken(type, _value, offset);
-
-  /**
-   * Remove this comment token from the list.
-   *
-   * This is used when we decide to interpret the comment as syntax.
-   */
-  void remove() {
-    if (previous != null) {
-      previous.setNextWithoutSettingPrevious(next);
-      next?.previous = previous;
-    } else {
-      assert(parent.precedingComments == this);
-      parent.precedingComments = next;
-    }
-  }
-}
-
-/**
- * A documentation comment token.
- */
-class DocumentationCommentToken extends CommentToken {
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset].
-   */
-  DocumentationCommentToken(TokenType type, String value, int offset)
-      : super(type, value, offset);
-
-  @override
-  CommentToken copy() => new DocumentationCommentToken(type, _value, offset);
-}
-
-/**
- * The keywords in the Dart programming language.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-class Keyword extends TokenType {
-  static const Keyword ABSTRACT =
-      const Keyword("abstract", "ABSTRACT", isBuiltIn: true, isModifier: true);
-
-  static const Keyword AS = const Keyword("as", "AS",
-      precedence: RELATIONAL_PRECEDENCE, isBuiltIn: true);
-
-  static const Keyword ASSERT = const Keyword("assert", "ASSERT");
-
-  static const Keyword ASYNC = const Keyword("async", "ASYNC", isPseudo: true);
-
-  static const Keyword AWAIT = const Keyword("await", "AWAIT", isPseudo: true);
-
-  static const Keyword BREAK = const Keyword("break", "BREAK");
-
-  static const Keyword CASE = const Keyword("case", "CASE");
-
-  static const Keyword CATCH = const Keyword("catch", "CATCH");
-
-  static const Keyword CLASS =
-      const Keyword("class", "CLASS", isTopLevelKeyword: true);
-
-  static const Keyword CONST =
-      const Keyword("const", "CONST", isModifier: true);
-
-  static const Keyword CONTINUE = const Keyword("continue", "CONTINUE");
-
-  static const Keyword COVARIANT = const Keyword("covariant", "COVARIANT",
-      isBuiltIn: true, isModifier: true);
-
-  static const Keyword DEFAULT = const Keyword("default", "DEFAULT");
-
-  static const Keyword DEFERRED =
-      const Keyword("deferred", "DEFERRED", isBuiltIn: true);
-
-  static const Keyword DO = const Keyword("do", "DO");
-
-  static const Keyword DYNAMIC =
-      const Keyword("dynamic", "DYNAMIC", isBuiltIn: true);
-
-  static const Keyword ELSE = const Keyword("else", "ELSE");
-
-  static const Keyword ENUM =
-      const Keyword("enum", "ENUM", isTopLevelKeyword: true);
-
-  static const Keyword EXPORT = const Keyword("export", "EXPORT",
-      isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword EXTENDS = const Keyword("extends", "EXTENDS");
-
-  static const Keyword EXTENSION = const Keyword("extension", "EXTENSION",
-      isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword EXTERNAL =
-      const Keyword("external", "EXTERNAL", isBuiltIn: true, isModifier: true);
-
-  static const Keyword FACTORY =
-      const Keyword("factory", "FACTORY", isBuiltIn: true);
-
-  static const Keyword FALSE = const Keyword("false", "FALSE");
-
-  static const Keyword FINAL =
-      const Keyword("final", "FINAL", isModifier: true);
-
-  static const Keyword FINALLY = const Keyword("finally", "FINALLY");
-
-  static const Keyword FOR = const Keyword("for", "FOR");
-
-  static const Keyword FUNCTION =
-      const Keyword("Function", "FUNCTION", isPseudo: true);
-
-  static const Keyword GET = const Keyword("get", "GET", isBuiltIn: true);
-
-  static const Keyword HIDE = const Keyword("hide", "HIDE", isPseudo: true);
-
-  static const Keyword IF = const Keyword("if", "IF");
-
-  static const Keyword IMPLEMENTS =
-      const Keyword("implements", "IMPLEMENTS", isBuiltIn: true);
-
-  static const Keyword IMPORT = const Keyword("import", "IMPORT",
-      isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword IN = const Keyword("in", "IN");
-
-  static const Keyword INOUT = const Keyword("inout", "INOUT", isPseudo: true);
-
-  static const Keyword INTERFACE =
-      const Keyword("interface", "INTERFACE", isBuiltIn: true);
-
-  static const Keyword IS =
-      const Keyword("is", "IS", precedence: RELATIONAL_PRECEDENCE);
-
-  static const Keyword LATE =
-      const Keyword("late", "LATE", isModifier: true, isBuiltIn: true);
-
-  static const Keyword LIBRARY = const Keyword("library", "LIBRARY",
-      isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword MIXIN =
-      const Keyword("mixin", "MIXIN", isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword NATIVE =
-      const Keyword("native", "NATIVE", isPseudo: true);
-
-  static const Keyword NEW = const Keyword("new", "NEW");
-
-  static const Keyword NULL = const Keyword("null", "NULL");
-
-  static const Keyword OF = const Keyword("of", "OF", isPseudo: true);
-
-  static const Keyword ON = const Keyword("on", "ON", isPseudo: true);
-
-  static const Keyword OPERATOR =
-      const Keyword("operator", "OPERATOR", isBuiltIn: true);
-
-  static const Keyword OUT = const Keyword("out", "OUT", isPseudo: true);
-
-  static const Keyword PART =
-      const Keyword("part", "PART", isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword PATCH = const Keyword("patch", "PATCH", isPseudo: true);
-
-  static const Keyword REQUIRED =
-      const Keyword("required", "REQUIRED", isBuiltIn: true, isModifier: true);
-
-  static const Keyword RETHROW = const Keyword("rethrow", "RETHROW");
-
-  static const Keyword RETURN = const Keyword("return", "RETURN");
-
-  static const Keyword SET = const Keyword("set", "SET", isBuiltIn: true);
-
-  static const Keyword SHOW = const Keyword("show", "SHOW", isPseudo: true);
-
-  static const Keyword SOURCE =
-      const Keyword("source", "SOURCE", isPseudo: true);
-
-  static const Keyword STATIC =
-      const Keyword("static", "STATIC", isBuiltIn: true, isModifier: true);
-
-  static const Keyword SUPER = const Keyword("super", "SUPER");
-
-  static const Keyword SWITCH = const Keyword("switch", "SWITCH");
-
-  static const Keyword SYNC = const Keyword("sync", "SYNC", isPseudo: true);
-
-  static const Keyword THIS = const Keyword("this", "THIS");
-
-  static const Keyword THROW = const Keyword("throw", "THROW");
-
-  static const Keyword TRUE = const Keyword("true", "TRUE");
-
-  static const Keyword TRY = const Keyword("try", "TRY");
-
-  static const Keyword TYPEDEF = const Keyword("typedef", "TYPEDEF",
-      isBuiltIn: true, isTopLevelKeyword: true);
-
-  static const Keyword VAR = const Keyword("var", "VAR", isModifier: true);
-
-  static const Keyword VOID = const Keyword("void", "VOID");
-
-  static const Keyword WHILE = const Keyword("while", "WHILE");
-
-  static const Keyword WITH = const Keyword("with", "WITH");
-
-  static const Keyword YIELD = const Keyword("yield", "YIELD", isPseudo: true);
-
-  static const List<Keyword> values = const <Keyword>[
-    ABSTRACT,
-    AS,
-    ASSERT,
-    ASYNC,
-    AWAIT,
-    BREAK,
-    CASE,
-    CATCH,
-    CLASS,
-    CONST,
-    CONTINUE,
-    COVARIANT,
-    DEFAULT,
-    DEFERRED,
-    DO,
-    DYNAMIC,
-    ELSE,
-    ENUM,
-    EXPORT,
-    EXTENDS,
-    EXTENSION,
-    EXTERNAL,
-    FACTORY,
-    FALSE,
-    FINAL,
-    FINALLY,
-    FOR,
-    FUNCTION,
-    GET,
-    HIDE,
-    IF,
-    IMPLEMENTS,
-    IMPORT,
-    IN,
-    INOUT,
-    INTERFACE,
-    IS,
-    LATE,
-    LIBRARY,
-    MIXIN,
-    NATIVE,
-    NEW,
-    NULL,
-    OF,
-    ON,
-    OPERATOR,
-    OUT,
-    PART,
-    PATCH,
-    REQUIRED,
-    RETHROW,
-    RETURN,
-    SET,
-    SHOW,
-    SOURCE,
-    STATIC,
-    SUPER,
-    SWITCH,
-    SYNC,
-    THIS,
-    THROW,
-    TRUE,
-    TRY,
-    TYPEDEF,
-    VAR,
-    VOID,
-    WHILE,
-    WITH,
-    YIELD,
-  ];
-
-  /**
-   * A table mapping the lexemes of keywords to the corresponding keyword.
-   */
-  static final Map<String, Keyword> keywords = _createKeywordMap();
-
-  /**
-   * A flag indicating whether the keyword is "built-in" identifier.
-   */
-  @override
-  final bool isBuiltIn;
-
-  @override
-  final bool isPseudo;
-
-  /**
-   * Initialize a newly created keyword.
-   */
-  const Keyword(String lexeme, String name,
-      {this.isBuiltIn: false,
-      bool isModifier: false,
-      this.isPseudo: false,
-      bool isTopLevelKeyword: false,
-      int precedence: NO_PRECEDENCE})
-      : super(lexeme, name, precedence, KEYWORD_TOKEN,
-            isModifier: isModifier, isTopLevelKeyword: isTopLevelKeyword);
-
-  bool get isBuiltInOrPseudo => isBuiltIn || isPseudo;
-
-  /**
-   * A flag indicating whether the keyword is "built-in" identifier.
-   * This method exists for backward compatibility and will be removed.
-   * Use [isBuiltIn] instead.
-   */
-  @deprecated
-  bool get isPseudoKeyword => isBuiltIn; // TODO (danrubel): remove this
-
-  /**
-   * The name of the keyword type.
-   */
-  String get name => lexeme.toUpperCase();
-
-  /**
-   * The lexeme for the keyword.
-   *
-   * Deprecated - use [lexeme] instead.
-   */
-  @deprecated
-  String get syntax => lexeme;
-
-  @override
-  String toString() => name;
-
-  /**
-   * Create a table mapping the lexemes of keywords to the corresponding keyword
-   * and return the table that was created.
-   */
-  static Map<String, Keyword> _createKeywordMap() {
-    LinkedHashMap<String, Keyword> result =
-        new LinkedHashMap<String, Keyword>();
-    for (Keyword keyword in values) {
-      result[keyword.lexeme] = keyword;
-    }
-    return result;
-  }
-}
-
-/**
- * A token representing a keyword in the language.
- */
-class KeywordToken extends SimpleToken {
-  @override
-  final Keyword keyword;
-
-  /**
-   * Initialize a newly created token to represent the given [keyword] at the
-   * given [offset].
-   */
-  KeywordToken(this.keyword, int offset, [CommentToken precedingComment])
-      : super(keyword, offset, precedingComment);
-
-  @override
-  Token copy() =>
-      new KeywordToken(keyword, offset, copyComments(precedingComments));
-
-  @override
-  bool get isIdentifier => keyword.isPseudo || keyword.isBuiltIn;
-
-  @override
-  bool get isKeyword => true;
-
-  @override
-  bool get isKeywordOrIdentifier => true;
-
-  @override
-  Object value() => keyword;
-}
-
-/**
- * A token that was scanned from the input. Each token knows which tokens
- * precede and follow it, acting as a link in a doubly linked list of tokens.
- */
-class SimpleToken implements Token {
-  /**
-   * The type of the token.
-   */
-  @override
-  final TokenType type;
-
-  /**
-   * The offset from the beginning of the file to the first character in the
-   * token.
-   */
-  @override
-  int offset = 0;
-
-  /**
-   * The previous token in the token stream.
-   */
-  @override
-  Token previous;
-
-  @override
-  Token next;
-
-  /**
-   * The first comment in the list of comments that precede this token.
-   */
-  CommentToken _precedingComment;
-
-  /**
-   * Initialize a newly created token to have the given [type] and [offset].
-   */
-  SimpleToken(this.type, this.offset, [this._precedingComment]) {
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  int get charCount => length;
-
-  @override
-  int get charOffset => offset;
-
-  @override
-  int get charEnd => end;
-
-  @override
-  Token get beforeSynthetic => null;
-
-  @override
-  set beforeSynthetic(Token previous) {
-    // ignored
-  }
-
-  @override
-  int get end => offset + length;
-
-  @override
-  Token get endGroup => null;
-
-  @override
-  bool get isEof => type == TokenType.EOF;
-
-  @override
-  bool get isIdentifier => false;
-
-  @override
-  bool get isKeyword => false;
-
-  @override
-  bool get isKeywordOrIdentifier => isIdentifier;
-
-  @override
-  bool get isModifier => type.isModifier;
-
-  @override
-  bool get isOperator => type.isOperator;
-
-  @override
-  bool get isSynthetic => length == 0;
-
-  @override
-  bool get isTopLevelKeyword => type.isTopLevelKeyword;
-
-  @override
-  bool get isUserDefinableOperator => type.isUserDefinableOperator;
-
-  @override
-  Keyword get keyword => null;
-
-  @override
-  int get kind => type.kind;
-
-  @override
-  int get length => lexeme.length;
-
-  @override
-  String get lexeme => type.lexeme;
-
-  @override
-  CommentToken get precedingComments => _precedingComment;
-
-  void set precedingComments(CommentToken comment) {
-    _precedingComment = comment;
-    _setCommentParent(_precedingComment);
-  }
-
-  @override
-  String get stringValue => type.stringValue;
-
-  @override
-  Token copy() =>
-      new SimpleToken(type, offset, copyComments(precedingComments));
-
-  @override
-  Token copyComments(Token token) {
-    if (token == null) {
-      return null;
-    }
-    Token head = token.copy();
-    Token tail = head;
-    token = token.next;
-    while (token != null) {
-      tail = tail.setNext(token.copy());
-      token = token.next;
-    }
-    return head;
-  }
-
-  @override
-  bool matchesAny(List<TokenType> types) {
-    for (TokenType type in types) {
-      if (this.type == type) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  Token setNext(Token token) {
-    next = token;
-    token.previous = this;
-    token.beforeSynthetic = this;
-    return token;
-  }
-
-  @override
-  Token setNextWithoutSettingPrevious(Token token) {
-    next = token;
-    return token;
-  }
-
-  @override
-  String toString() => lexeme;
-
-  @override
-  Object value() => lexeme;
-
-  /**
-   * Sets the `parent` property to `this` for the given [comment] and all the
-   * next tokens.
-   */
-  void _setCommentParent(CommentToken comment) {
-    while (comment != null) {
-      comment.parent = this;
-      comment = comment.next;
-    }
-  }
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class StringToken extends SimpleToken {
-  /**
-   * The lexeme represented by this token.
-   */
-  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])
-      : super(type, offset, precedingComment) {
-    this._value = StringUtilities.intern(value);
-  }
-
-  @override
-  bool get isIdentifier => identical(kind, IDENTIFIER_TOKEN);
-
-  @override
-  String get lexeme => _value;
-
-  @override
-  Token copy() =>
-      new StringToken(type, _value, offset, copyComments(precedingComments));
-
-  @override
-  String value() => _value;
-}
-
-/**
- * A synthetic begin token.
- */
-class SyntheticBeginToken extends BeginToken {
-  /**
-   * Initialize a newly created token to have the given [type] at the given
-   * [offset].
-   */
-  SyntheticBeginToken(TokenType type, int offset,
-      [CommentToken precedingComment])
-      : super(type, offset, precedingComment);
-
-  @override
-  Token copy() =>
-      new SyntheticBeginToken(type, offset, copyComments(precedingComments));
-
-  @override
-  bool get isSynthetic => true;
-
-  @override
-  int get length => 0;
-}
-
-/**
- * A synthetic keyword token.
- */
-class SyntheticKeywordToken extends KeywordToken {
-  /**
-   * Initialize a newly created token to represent the given [keyword] at the
-   * given [offset].
-   */
-  SyntheticKeywordToken(Keyword keyword, int offset) : super(keyword, offset);
-
-  @override
-  int get length => 0;
-
-  @override
-  Token copy() => new SyntheticKeywordToken(keyword, offset);
-}
-
-/**
- * A token whose value is independent of it's type.
- */
-class SyntheticStringToken extends StringToken {
-  final int _length;
-
-  /**
-   * Initialize a newly created token to represent a token of the given [type]
-   * with the given [value] at the given [offset]. If the [length] is
-   * not specified, then it defaults to the length of [value].
-   */
-  SyntheticStringToken(TokenType type, String value, int offset, [this._length])
-      : super(type, value, offset);
-
-  @override
-  bool get isSynthetic => true;
-
-  @override
-  int get length => _length ?? super.length;
-
-  @override
-  Token copy() => new SyntheticStringToken(type, _value, offset, _length);
-}
-
-/**
- * A synthetic token.
- */
-class SyntheticToken extends SimpleToken {
-  SyntheticToken(TokenType type, int offset) : super(type, offset);
-
-  @override
-  Token beforeSynthetic;
-
-  @override
-  bool get isSynthetic => true;
-
-  @override
-  int get length => 0;
-
-  @override
-  Token copy() => new SyntheticToken(type, offset);
-}
-
-/**
- * A token that was scanned from the input. Each token knows which tokens
- * precede and follow it, acting as a link in a doubly linked list of tokens.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Token implements SyntacticEntity {
-  /**
-   * Initialize a newly created token to have the given [type] and [offset].
-   */
-  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]) {
-    Token eof = new SimpleToken(TokenType.EOF, offset, precedingComments);
-    // EOF points to itself so there's always infinite look-ahead.
-    eof.previous = eof;
-    eof.next = eof;
-    return eof;
-  }
-
-  /**
-   * The number of characters parsed by this token.
-   */
-  int get charCount;
-
-  /**
-   * The character offset of the start of this token within the source text.
-   */
-  int get charOffset;
-
-  /**
-   * The character offset of the end of this token within the source text.
-   */
-  int get charEnd;
-
-  /**
-   * The token before this synthetic token,
-   * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token.
-   */
-  Token get beforeSynthetic;
-
-  /**
-   * Set token before this synthetic `)`, `]`, `}`, or `>` token,
-   * and ignored otherwise.
-   */
-  set beforeSynthetic(Token previous);
-
-  @override
-  int get end;
-
-  /**
-   * 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;
-
-  /**
-   * Return `true` if this token represents an end of file.
-   */
-  bool get isEof;
-
-  /**
-   * True if this token is an identifier. Some keywords allowed as identifiers,
-   * see implementation in [KeywordToken].
-   */
-  bool get isIdentifier;
-
-  /**
-   * True if this token is a keyword. Some keywords allowed as identifiers,
-   * see implementation in [KeywordToken].
-   */
-  bool get isKeyword;
-
-  /**
-   * True if this token is a keyword or an identifier.
-   */
-  bool get isKeywordOrIdentifier;
-
-  /**
-   * Return `true` if this token is a modifier such as `abstract` or `const`.
-   */
-  bool get isModifier;
-
-  /**
-   * Return `true` if this token represents an operator.
-   */
-  bool get isOperator;
-
-  /**
-   * Return `true` if this token is a synthetic token. A synthetic token is a
-   * token that was introduced by the parser in order to recover from an error
-   * in the code.
-   */
-  bool get isSynthetic;
-
-  /**
-   * Return `true` if this token is a keyword starting a top level declaration
-   * such as `class`, `enum`, `import`, etc.
-   */
-  bool get isTopLevelKeyword;
-
-  /**
-   * Return `true` if this token represents an operator that can be defined by
-   * users.
-   */
-  bool get isUserDefinableOperator;
-
-  /**
-   * Return the keyword, if a keyword token, or `null` otherwise.
-   */
-  Keyword get keyword;
-
-  /**
-   * The kind enum of this token as determined by its [type].
-   */
-  int get kind;
-
-  @override
-  int get length;
-
-  /**
-   * Return the lexeme that represents this token.
-   *
-   * For [StringToken]s the [lexeme] includes the quotes, explicit escapes, etc.
-   */
-  String get lexeme;
-
-  /**
-   * Return the next token in the token stream.
-   */
-  Token get next;
-
-  /**
-   * Return the next token in the token stream.
-   */
-  void set next(Token next);
-
-  @override
-  int get offset;
-
-  /**
-   * Set the offset from the beginning of the file to the first character in
-   * the token to the given [offset].
-   */
-  void set offset(int offset);
-
-  /**
-   * Return the first comment in the list of comments that precede this token,
-   * or `null` if there are no comments preceding this token. Additional
-   * comments can be reached by following the token stream using [next] until
-   * `null` is returned.
-   *
-   * For example, if the original contents were `/* one */ /* two */ id`, then
-   * the first preceding comment token will have a lexeme of `/* one */` and
-   * the next comment token will have a lexeme of `/* two */`.
-   */
-  Token get precedingComments;
-
-  /**
-   * Return the previous token in the token stream.
-   */
-  Token get previous;
-
-  /**
-   * Set the previous token in the token stream to the given [token].
-   */
-  void set previous(Token token);
-
-  /**
-   * For symbol and keyword tokens, returns the string value represented by this
-   * token. For [StringToken]s this method returns [:null:].
-   *
-   * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
-   * constant originating in the [TokenType] or in the [Keyword] instance.
-   * This allows testing for keywords and symbols using [:identical:], e.g.,
-   * [:identical('class', token.value):].
-   *
-   * Note that returning [:null:] for string tokens is important to identify
-   * symbols and keywords, we cannot use [lexeme] instead. The string literal
-   *   "$a($b"
-   * produces ..., SymbolToken($), StringToken(a), StringToken((), ...
-   *
-   * After parsing the identifier 'a', the parser tests for a function
-   * declaration using [:identical(next.stringValue, '('):], which (rightfully)
-   * returns false because stringValue returns [:null:].
-   */
-  String get stringValue;
-
-  /**
-   * Return the type of the token.
-   */
-  TokenType get type;
-
-  /**
-   * Return a newly created token that is a copy of this tokens
-   * including any [preceedingComment] tokens,
-   * but that is not a part of any token stream.
-   */
-  Token copy();
-
-  /**
-   * Copy a linked list of comment tokens identical to the given comment tokens.
-   */
-  Token copyComments(Token token);
-
-  /**
-   * Return `true` if this token has any one of the given [types].
-   */
-  bool matchesAny(List<TokenType> types);
-
-  /**
-   * Set the next token in the token stream to the given [token]. This has the
-   * side-effect of setting this token to be the previous token for the given
-   * token. Return the token that was passed in.
-   */
-  Token setNext(Token token);
-
-  /**
-   * Set the next token in the token stream to the given token without changing
-   * which token is the previous token for the given token. Return the token
-   * that was passed in.
-   */
-  Token setNextWithoutSettingPrevious(Token token);
-
-  /**
-   * Returns a textual representation of this token to be used for debugging
-   * purposes. The resulting string might contain information about the
-   * structure of the token, for example 'StringToken(foo)' for the identifier
-   * token 'foo'.
-   *
-   * Use [lexeme] for the text actually parsed by the token.
-   */
-  @override
-  String toString();
-
-  /**
-   * Return the value of this token. For keyword tokens, this is the keyword
-   * associated with the token, for other tokens it is the lexeme associated
-   * with the token.
-   */
-  Object value();
-
-  /**
-   * Compare the given [tokens] to find the token that appears first in the
-   * source being parsed. That is, return the left-most of all of the tokens.
-   * The list must be non-`null`, but the elements of the list are allowed to be
-   * `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;
-    int offset = -1;
-    int length = tokens.length;
-    for (int i = 0; i < length; i++) {
-      Token token = tokens[i];
-      if (token != null && (offset < 0 || token.offset < offset)) {
-        first = token;
-        offset = token.offset;
-      }
-    }
-    return first;
-  }
-}
-
-/**
- * The classes (or groups) of tokens with a similar use.
- */
-class TokenClass {
-  /**
-   * A value used to indicate that the token type is not part of any specific
-   * class of token.
-   */
-  static const TokenClass NO_CLASS = const TokenClass('NO_CLASS');
-
-  /**
-   * A value used to indicate that the token type is an additive operator.
-   */
-  static const TokenClass ADDITIVE_OPERATOR =
-      const TokenClass('ADDITIVE_OPERATOR', ADDITIVE_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is an assignment operator.
-   */
-  static const TokenClass ASSIGNMENT_OPERATOR =
-      const TokenClass('ASSIGNMENT_OPERATOR', ASSIGNMENT_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-and operator.
-   */
-  static const TokenClass BITWISE_AND_OPERATOR =
-      const TokenClass('BITWISE_AND_OPERATOR', BITWISE_AND_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-or operator.
-   */
-  static const TokenClass BITWISE_OR_OPERATOR =
-      const TokenClass('BITWISE_OR_OPERATOR', BITWISE_OR_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a bitwise-xor operator.
-   */
-  static const TokenClass BITWISE_XOR_OPERATOR =
-      const TokenClass('BITWISE_XOR_OPERATOR', BITWISE_XOR_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a cascade operator.
-   */
-  static const TokenClass CASCADE_OPERATOR =
-      const TokenClass('CASCADE_OPERATOR', CASCADE_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a conditional operator.
-   */
-  static const TokenClass CONDITIONAL_OPERATOR =
-      const TokenClass('CONDITIONAL_OPERATOR', CONDITIONAL_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is an equality operator.
-   */
-  static const TokenClass EQUALITY_OPERATOR =
-      const TokenClass('EQUALITY_OPERATOR', EQUALITY_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is an if-null operator.
-   */
-  static const TokenClass IF_NULL_OPERATOR =
-      const TokenClass('IF_NULL_OPERATOR', IF_NULL_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a logical-and operator.
-   */
-  static const TokenClass LOGICAL_AND_OPERATOR =
-      const TokenClass('LOGICAL_AND_OPERATOR', LOGICAL_AND_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a logical-or operator.
-   */
-  static const TokenClass LOGICAL_OR_OPERATOR =
-      const TokenClass('LOGICAL_OR_OPERATOR', LOGICAL_OR_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a multiplicative operator.
-   */
-  static const TokenClass MULTIPLICATIVE_OPERATOR =
-      const TokenClass('MULTIPLICATIVE_OPERATOR', MULTIPLICATIVE_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a relational operator.
-   */
-  static const TokenClass RELATIONAL_OPERATOR =
-      const TokenClass('RELATIONAL_OPERATOR', RELATIONAL_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a shift operator.
-   */
-  static const TokenClass SHIFT_OPERATOR =
-      const TokenClass('SHIFT_OPERATOR', SHIFT_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a unary operator.
-   */
-  static const TokenClass UNARY_POSTFIX_OPERATOR =
-      const TokenClass('UNARY_POSTFIX_OPERATOR', POSTFIX_PRECEDENCE);
-
-  /**
-   * A value used to indicate that the token type is a unary operator.
-   */
-  static const TokenClass UNARY_PREFIX_OPERATOR =
-      const TokenClass('UNARY_PREFIX_OPERATOR', PREFIX_PRECEDENCE);
-
-  /**
-   * The name of the token class.
-   */
-  final String name;
-
-  /**
-   * The precedence of tokens of this class, or `0` if the such tokens do not
-   * represent an operator.
-   */
-  final int precedence;
-
-  /**
-   * Initialize a newly created class of tokens to have the given [name] and
-   * [precedence].
-   */
-  const TokenClass(this.name, [this.precedence = NO_PRECEDENCE]);
-
-  @override
-  String toString() => name;
-}
-
-/**
- * The types of tokens that can be returned by the scanner.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-class TokenType {
-  /**
-   * The type of the token that marks the start or end of the input.
-   */
-  static const TokenType EOF =
-      const TokenType('', 'EOF', NO_PRECEDENCE, EOF_TOKEN);
-
-  static const TokenType DOUBLE = const TokenType(
-      'double', 'DOUBLE', NO_PRECEDENCE, DOUBLE_TOKEN,
-      stringValue: null);
-
-  static const TokenType HEXADECIMAL = const TokenType(
-      'hexadecimal', 'HEXADECIMAL', NO_PRECEDENCE, HEXADECIMAL_TOKEN,
-      stringValue: null);
-
-  static const TokenType IDENTIFIER = const TokenType(
-      'identifier', 'IDENTIFIER', NO_PRECEDENCE, IDENTIFIER_TOKEN,
-      stringValue: null);
-
-  static const TokenType INT = const TokenType(
-      'int', 'INT', NO_PRECEDENCE, INT_TOKEN,
-      stringValue: null);
-
-  static const TokenType MULTI_LINE_COMMENT = const TokenType(
-      'comment', 'MULTI_LINE_COMMENT', NO_PRECEDENCE, COMMENT_TOKEN,
-      stringValue: null);
-
-  static const TokenType SCRIPT_TAG =
-      const TokenType('script', 'SCRIPT_TAG', NO_PRECEDENCE, SCRIPT_TOKEN);
-
-  static const TokenType SINGLE_LINE_COMMENT = const TokenType(
-      'comment', 'SINGLE_LINE_COMMENT', NO_PRECEDENCE, COMMENT_TOKEN,
-      stringValue: null);
-
-  static const TokenType STRING = const TokenType(
-      'string', 'STRING', NO_PRECEDENCE, STRING_TOKEN,
-      stringValue: null);
-
-  static const TokenType AMPERSAND = const TokenType(
-      '&', 'AMPERSAND', BITWISE_AND_PRECEDENCE, AMPERSAND_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType AMPERSAND_AMPERSAND = const TokenType('&&',
-      'AMPERSAND_AMPERSAND', LOGICAL_AND_PRECEDENCE, AMPERSAND_AMPERSAND_TOKEN,
-      isOperator: true);
-
-  // This is not yet part of the language and not supported by fasta
-  static const TokenType AMPERSAND_AMPERSAND_EQ = const TokenType(
-      '&&=',
-      'AMPERSAND_AMPERSAND_EQ',
-      ASSIGNMENT_PRECEDENCE,
-      AMPERSAND_AMPERSAND_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType AMPERSAND_EQ = const TokenType(
-      '&=', 'AMPERSAND_EQ', ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType AT =
-      const TokenType('@', 'AT', NO_PRECEDENCE, AT_TOKEN);
-
-  static const TokenType BANG = const TokenType(
-      '!', 'BANG', PREFIX_PRECEDENCE, BANG_TOKEN,
-      isOperator: true);
-
-  static const TokenType BANG_EQ = const TokenType(
-      '!=', 'BANG_EQ', EQUALITY_PRECEDENCE, BANG_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType BANG_EQ_EQ = const TokenType(
-      '!==', 'BANG_EQ_EQ', EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
-
-  static const TokenType BAR = const TokenType(
-      '|', 'BAR', BITWISE_OR_PRECEDENCE, BAR_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType BAR_BAR = const TokenType(
-      '||', 'BAR_BAR', LOGICAL_OR_PRECEDENCE, BAR_BAR_TOKEN,
-      isOperator: true);
-
-  // This is not yet part of the language and not supported by fasta
-  static const TokenType BAR_BAR_EQ = const TokenType(
-      '||=', 'BAR_BAR_EQ', ASSIGNMENT_PRECEDENCE, BAR_BAR_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType BAR_EQ = const TokenType(
-      '|=', 'BAR_EQ', ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType COLON =
-      const TokenType(':', 'COLON', NO_PRECEDENCE, COLON_TOKEN);
-
-  static const TokenType COMMA =
-      const TokenType(',', 'COMMA', NO_PRECEDENCE, COMMA_TOKEN);
-
-  static const TokenType CARET = const TokenType(
-      '^', 'CARET', BITWISE_XOR_PRECEDENCE, CARET_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType CARET_EQ = const TokenType(
-      '^=', 'CARET_EQ', ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType CLOSE_CURLY_BRACKET = const TokenType(
-      '}', 'CLOSE_CURLY_BRACKET', NO_PRECEDENCE, CLOSE_CURLY_BRACKET_TOKEN);
-
-  static const TokenType CLOSE_PAREN =
-      const TokenType(')', 'CLOSE_PAREN', NO_PRECEDENCE, CLOSE_PAREN_TOKEN);
-
-  static const TokenType CLOSE_SQUARE_BRACKET = const TokenType(
-      ']', 'CLOSE_SQUARE_BRACKET', NO_PRECEDENCE, CLOSE_SQUARE_BRACKET_TOKEN);
-
-  static const TokenType EQ = const TokenType(
-      '=', 'EQ', ASSIGNMENT_PRECEDENCE, EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType EQ_EQ = const TokenType(
-      '==', 'EQ_EQ', EQUALITY_PRECEDENCE, EQ_EQ_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  /// The `===` operator is not supported in the Dart language
-  /// but is parsed as such by the scanner to support better recovery
-  /// when a JavaScript code snippet is pasted into a Dart file.
-  static const TokenType EQ_EQ_EQ =
-      const TokenType('===', 'EQ_EQ_EQ', EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
-
-  static const TokenType FUNCTION =
-      const TokenType('=>', 'FUNCTION', NO_PRECEDENCE, FUNCTION_TOKEN);
-
-  static const TokenType GT = const TokenType(
-      '>', 'GT', RELATIONAL_PRECEDENCE, GT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType GT_EQ = const TokenType(
-      '>=', 'GT_EQ', RELATIONAL_PRECEDENCE, GT_EQ_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType GT_GT = const TokenType(
-      '>>', 'GT_GT', SHIFT_PRECEDENCE, GT_GT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType GT_GT_EQ = const TokenType(
-      '>>=', 'GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType GT_GT_GT = const TokenType(
-      '>>>', 'GT_GT_GT', SHIFT_PRECEDENCE, GT_GT_GT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType GT_GT_GT_EQ = const TokenType(
-      '>>>=', 'GT_GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_GT_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType HASH =
-      const TokenType('#', 'HASH', NO_PRECEDENCE, HASH_TOKEN);
-
-  static const TokenType INDEX = const TokenType(
-      '[]', 'INDEX', SELECTOR_PRECEDENCE, INDEX_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType INDEX_EQ = const TokenType(
-      '[]=', 'INDEX_EQ', NO_PRECEDENCE, INDEX_EQ_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType LT = const TokenType(
-      '<', 'LT', RELATIONAL_PRECEDENCE, LT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType LT_EQ = const TokenType(
-      '<=', 'LT_EQ', RELATIONAL_PRECEDENCE, LT_EQ_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType LT_LT = const TokenType(
-      '<<', 'LT_LT', SHIFT_PRECEDENCE, LT_LT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType LT_LT_EQ = const TokenType(
-      '<<=', 'LT_LT_EQ', ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType MINUS = const TokenType(
-      '-', 'MINUS', ADDITIVE_PRECEDENCE, MINUS_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType MINUS_EQ = const TokenType(
-      '-=', 'MINUS_EQ', ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType MINUS_MINUS = const TokenType(
-      '--', 'MINUS_MINUS', POSTFIX_PRECEDENCE, MINUS_MINUS_TOKEN,
-      isOperator: true);
-
-  static const TokenType OPEN_CURLY_BRACKET = const TokenType(
-      '{', 'OPEN_CURLY_BRACKET', NO_PRECEDENCE, OPEN_CURLY_BRACKET_TOKEN);
-
-  static const TokenType OPEN_PAREN =
-      const TokenType('(', 'OPEN_PAREN', SELECTOR_PRECEDENCE, OPEN_PAREN_TOKEN);
-
-  static const TokenType OPEN_SQUARE_BRACKET = const TokenType('[',
-      'OPEN_SQUARE_BRACKET', SELECTOR_PRECEDENCE, OPEN_SQUARE_BRACKET_TOKEN);
-
-  static const TokenType PERCENT = const TokenType(
-      '%', 'PERCENT', MULTIPLICATIVE_PRECEDENCE, PERCENT_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType PERCENT_EQ = const TokenType(
-      '%=', 'PERCENT_EQ', ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType PERIOD =
-      const TokenType('.', 'PERIOD', SELECTOR_PRECEDENCE, PERIOD_TOKEN);
-
-  static const TokenType PERIOD_PERIOD = const TokenType(
-      '..', 'PERIOD_PERIOD', CASCADE_PRECEDENCE, PERIOD_PERIOD_TOKEN,
-      isOperator: true);
-
-  static const TokenType PLUS = const TokenType(
-      '+', 'PLUS', ADDITIVE_PRECEDENCE, PLUS_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType PLUS_EQ = const TokenType(
-      '+=', 'PLUS_EQ', ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType PLUS_PLUS = const TokenType(
-      '++', 'PLUS_PLUS', POSTFIX_PRECEDENCE, PLUS_PLUS_TOKEN,
-      isOperator: true);
-
-  static const TokenType QUESTION = const TokenType(
-      '?', 'QUESTION', CONDITIONAL_PRECEDENCE, QUESTION_TOKEN,
-      isOperator: true);
-
-  static const TokenType QUESTION_PERIOD = const TokenType(
-      '?.', 'QUESTION_PERIOD', SELECTOR_PRECEDENCE, QUESTION_PERIOD_TOKEN,
-      isOperator: true);
-
-  static const TokenType QUESTION_QUESTION = const TokenType(
-      '??', 'QUESTION_QUESTION', IF_NULL_PRECEDENCE, QUESTION_QUESTION_TOKEN,
-      isOperator: true);
-
-  static const TokenType QUESTION_QUESTION_EQ = const TokenType('??=',
-      'QUESTION_QUESTION_EQ', ASSIGNMENT_PRECEDENCE, QUESTION_QUESTION_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType SEMICOLON =
-      const TokenType(';', 'SEMICOLON', NO_PRECEDENCE, SEMICOLON_TOKEN);
-
-  static const TokenType SLASH = const TokenType(
-      '/', 'SLASH', MULTIPLICATIVE_PRECEDENCE, SLASH_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType SLASH_EQ = const TokenType(
-      '/=', 'SLASH_EQ', ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType STAR = const TokenType(
-      '*', 'STAR', MULTIPLICATIVE_PRECEDENCE, STAR_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType STAR_EQ = const TokenType(
-      '*=', 'STAR_EQ', ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType STRING_INTERPOLATION_EXPRESSION = const TokenType(
-      '\${',
-      'STRING_INTERPOLATION_EXPRESSION',
-      NO_PRECEDENCE,
-      STRING_INTERPOLATION_TOKEN);
-
-  static const TokenType STRING_INTERPOLATION_IDENTIFIER = const TokenType(
-      '\$',
-      'STRING_INTERPOLATION_IDENTIFIER',
-      NO_PRECEDENCE,
-      STRING_INTERPOLATION_IDENTIFIER_TOKEN);
-
-  static const TokenType TILDE = const TokenType(
-      '~', 'TILDE', PREFIX_PRECEDENCE, TILDE_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType TILDE_SLASH = const TokenType(
-      '~/', 'TILDE_SLASH', MULTIPLICATIVE_PRECEDENCE, TILDE_SLASH_TOKEN,
-      isOperator: true, isUserDefinableOperator: true);
-
-  static const TokenType TILDE_SLASH_EQ = const TokenType(
-      '~/=', 'TILDE_SLASH_EQ', ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN,
-      isOperator: true);
-
-  static const TokenType BACKPING =
-      const TokenType('`', 'BACKPING', NO_PRECEDENCE, BACKPING_TOKEN);
-
-  static const TokenType BACKSLASH =
-      const TokenType('\\', 'BACKSLASH', NO_PRECEDENCE, BACKSLASH_TOKEN);
-
-  static const TokenType PERIOD_PERIOD_PERIOD = const TokenType(
-      '...', 'PERIOD_PERIOD_PERIOD', NO_PRECEDENCE, PERIOD_PERIOD_PERIOD_TOKEN);
-
-  static const TokenType PERIOD_PERIOD_PERIOD_QUESTION = const TokenType(
-      '...?',
-      'PERIOD_PERIOD_PERIOD_QUESTION',
-      NO_PRECEDENCE,
-      PERIOD_PERIOD_PERIOD_QUESTION_TOKEN);
-
-  static const TokenType QUESTION_PERIOD_OPEN_SQUARE_BRACKET = const TokenType(
-      '?.[',
-      'QUESTION_PERIOD_OPEN_SQUARE_BRACKET',
-      SELECTOR_PRECEDENCE,
-      QUESTION_PERIOD_OPEN_SQUARE_BRACKET_TOKEN);
-
-  static const TokenType QUESTION_PERIOD_PERIOD = const TokenType(
-      '?..',
-      'QUESTION_PERIOD_PERIOD',
-      CASCADE_PRECEDENCE,
-      QUESTION_PERIOD_PERIOD_TOKEN);
-
-  static const TokenType AS = Keyword.AS;
-
-  static const TokenType IS = Keyword.IS;
-
-  /**
-   * Token type used by error tokens.
-   */
-  static const TokenType BAD_INPUT = const TokenType(
-      'malformed input', 'BAD_INPUT', NO_PRECEDENCE, BAD_INPUT_TOKEN,
-      stringValue: null);
-
-  /**
-   * Token type used by synthetic tokens that are created during parser
-   * recovery (non-analyzer use case).
-   */
-  static const TokenType RECOVERY = const TokenType(
-      'recovery', 'RECOVERY', NO_PRECEDENCE, RECOVERY_TOKEN,
-      stringValue: null);
-
-  // TODO(danrubel): "all" is misleading
-  // because this list does not include all TokenType instances.
-  static const List<TokenType> all = const <TokenType>[
-    TokenType.EOF,
-    TokenType.DOUBLE,
-    TokenType.HEXADECIMAL,
-    TokenType.IDENTIFIER,
-    TokenType.INT,
-    TokenType.MULTI_LINE_COMMENT,
-    TokenType.SCRIPT_TAG,
-    TokenType.SINGLE_LINE_COMMENT,
-    TokenType.STRING,
-    TokenType.AMPERSAND,
-    TokenType.AMPERSAND_AMPERSAND,
-    TokenType.AMPERSAND_EQ,
-    TokenType.AT,
-    TokenType.BANG,
-    TokenType.BANG_EQ,
-    TokenType.BAR,
-    TokenType.BAR_BAR,
-    TokenType.BAR_EQ,
-    TokenType.COLON,
-    TokenType.COMMA,
-    TokenType.CARET,
-    TokenType.CARET_EQ,
-    TokenType.CLOSE_CURLY_BRACKET,
-    TokenType.CLOSE_PAREN,
-    TokenType.CLOSE_SQUARE_BRACKET,
-    TokenType.EQ,
-    TokenType.EQ_EQ,
-    TokenType.FUNCTION,
-    TokenType.GT,
-    TokenType.GT_EQ,
-    TokenType.GT_GT,
-    TokenType.GT_GT_EQ,
-    TokenType.HASH,
-    TokenType.INDEX,
-    TokenType.INDEX_EQ,
-    TokenType.LT,
-    TokenType.LT_EQ,
-    TokenType.LT_LT,
-    TokenType.LT_LT_EQ,
-    TokenType.MINUS,
-    TokenType.MINUS_EQ,
-    TokenType.MINUS_MINUS,
-    TokenType.OPEN_CURLY_BRACKET,
-    TokenType.OPEN_PAREN,
-    TokenType.OPEN_SQUARE_BRACKET,
-    TokenType.PERCENT,
-    TokenType.PERCENT_EQ,
-    TokenType.PERIOD,
-    TokenType.PERIOD_PERIOD,
-    TokenType.PLUS,
-    TokenType.PLUS_EQ,
-    TokenType.PLUS_PLUS,
-    TokenType.QUESTION,
-    TokenType.QUESTION_PERIOD,
-    TokenType.QUESTION_QUESTION,
-    TokenType.QUESTION_QUESTION_EQ,
-    TokenType.SEMICOLON,
-    TokenType.SLASH,
-    TokenType.SLASH_EQ,
-    TokenType.STAR,
-    TokenType.STAR_EQ,
-    TokenType.STRING_INTERPOLATION_EXPRESSION,
-    TokenType.STRING_INTERPOLATION_IDENTIFIER,
-    TokenType.TILDE,
-    TokenType.TILDE_SLASH,
-    TokenType.TILDE_SLASH_EQ,
-    TokenType.BACKPING,
-    TokenType.BACKSLASH,
-    TokenType.PERIOD_PERIOD_PERIOD,
-    TokenType.PERIOD_PERIOD_PERIOD_QUESTION,
-
-    // TODO(danrubel): Should these be added to the "all" list?
-    //TokenType.IS,
-    //TokenType.AS,
-
-    // These are not yet part of the language and not supported by fasta
-    //TokenType.AMPERSAND_AMPERSAND_EQ,
-    //TokenType.BAR_BAR_EQ,
-
-    // Supported by fasta but not part of the language
-    //TokenType.BANG_EQ_EQ,
-    //TokenType.EQ_EQ_EQ,
-
-    // Used by synthetic tokens generated during recovery
-    //TokenType.BAD_INPUT,
-    //TokenType.RECOVERY,
-  ];
-
-  final int kind;
-
-  /**
-   * `true` if this token type represents a modifier
-   * such as `abstract` or `const`.
-   */
-  final bool isModifier;
-
-  /**
-   * `true` if this token type represents an operator.
-   */
-  final bool isOperator;
-
-  /**
-   * `true` if this token type represents a keyword starting a top level
-   * declaration such as `class`, `enum`, `import`, etc.
-   */
-  final bool isTopLevelKeyword;
-
-  /**
-   * `true` if this token type represents an operator
-   * that can be defined by users.
-   */
-  final bool isUserDefinableOperator;
-
-  /**
-   * The lexeme that defines this type of token,
-   * or `null` if there is more than one possible lexeme for this type of token.
-   */
-  final String lexeme;
-
-  /**
-   * The name of the token type.
-   */
-  final String name;
-
-  /**
-   * The precedence of this type of token,
-   * or `0` if the token does not represent an operator.
-   */
-  final int precedence;
-
-  /**
-   * See [Token.stringValue] for an explanation.
-   */
-  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'})
-      : this.stringValue = stringValue == 'unspecified' ? lexeme : stringValue;
-
-  /**
-   * Return `true` if this type of token represents an additive operator.
-   */
-  bool get isAdditiveOperator => precedence == ADDITIVE_PRECEDENCE;
-
-  /**
-   * Return `true` if this type of token represents an assignment operator.
-   */
-  bool get isAssignmentOperator => precedence == ASSIGNMENT_PRECEDENCE;
-
-  /**
-   * Return `true` if this type of token represents an associative operator. An
-   * associative operator is an operator for which the following equality is
-   * true: `(a * b) * c == a * (b * c)`. In other words, if the result of
-   * applying the operator to multiple operands does not depend on the order in
-   * which those applications occur.
-   *
-   * Note: This method considers the logical-and and logical-or operators to be
-   * associative, even though the order in which the application of those
-   * operators can have an effect because evaluation of the right-hand operand
-   * is conditional.
-   */
-  bool get isAssociativeOperator =>
-      this == TokenType.AMPERSAND ||
-      this == TokenType.AMPERSAND_AMPERSAND ||
-      this == TokenType.BAR ||
-      this == TokenType.BAR_BAR ||
-      this == TokenType.CARET ||
-      this == TokenType.PLUS ||
-      this == TokenType.STAR;
-
-  /**
-   * A flag indicating whether the keyword is a "built-in" identifier.
-   */
-  bool get isBuiltIn => false;
-
-  /**
-   * Return `true` if this type of token represents an equality operator.
-   */
-  bool get isEqualityOperator =>
-      this == TokenType.BANG_EQ || this == TokenType.EQ_EQ;
-
-  /**
-   * Return `true` if this type of token represents an increment operator.
-   */
-  bool get isIncrementOperator =>
-      this == TokenType.PLUS_PLUS || this == TokenType.MINUS_MINUS;
-
-  /**
-   * Return `true` if this type of token is a keyword.
-   */
-  bool get isKeyword => kind == KEYWORD_TOKEN;
-
-  /**
-   * A flag indicating whether the keyword can be used as an identifier
-   * in some situations.
-   */
-  bool get isPseudo => false;
-
-  /**
-   * Return `true` if this type of token represents a multiplicative operator.
-   */
-  bool get isMultiplicativeOperator => precedence == MULTIPLICATIVE_PRECEDENCE;
-
-  /**
-   * Return `true` if this type of token represents a relational operator.
-   */
-  bool get isRelationalOperator =>
-      this == TokenType.LT ||
-      this == TokenType.LT_EQ ||
-      this == TokenType.GT ||
-      this == TokenType.GT_EQ;
-
-  /**
-   * Return `true` if this type of token represents a shift operator.
-   */
-  bool get isShiftOperator => precedence == SHIFT_PRECEDENCE;
-
-  /**
-   * Return `true` if this type of token represents a unary postfix operator.
-   */
-  bool get isUnaryPostfixOperator => precedence == POSTFIX_PRECEDENCE;
-
-  /**
-   * Return `true` if this type of token represents a unary prefix operator.
-   */
-  bool get isUnaryPrefixOperator =>
-      precedence == PREFIX_PRECEDENCE ||
-      this == TokenType.MINUS ||
-      this == TokenType.PLUS_PLUS ||
-      this == TokenType.MINUS_MINUS;
-
-  /**
-   * Return `true` if this type of token represents a selector operator
-   * (starting token of a selector).
-   */
-  bool get isSelectorOperator => precedence == SELECTOR_PRECEDENCE;
-
-  @override
-  String toString() => name;
-
-  /**
-   * Use [lexeme] instead of this method
-   */
-  @deprecated
-  String get value => lexeme;
-}
diff --git a/pkg/front_end/lib/src/testing/compiler_common.dart b/pkg/front_end/lib/src/testing/compiler_common.dart
index 58de336..7adb555 100644
--- a/pkg/front_end/lib/src/testing/compiler_common.dart
+++ b/pkg/front_end/lib/src/testing/compiler_common.dart
@@ -33,11 +33,12 @@
 ///
 /// Wraps [kernelForProgram] with some default testing options (see [setup]).
 Future<CompilerResult> compileScript(dynamic scriptOrSources,
-    {fileName: 'main.dart',
+    {String fileName: 'main.dart',
     List<String> inputSummaries: const [],
     List<String> linkedDependencies: const [],
     CompilerOptions options,
-    bool retainDataForTesting: false}) async {
+    bool retainDataForTesting: false,
+    bool requireMain: true}) async {
   options ??= new CompilerOptions();
   Map<String, dynamic> sources;
   if (scriptOrSources is String) {
@@ -49,7 +50,7 @@
   await setup(options, sources,
       inputSummaries: inputSummaries, linkedDependencies: linkedDependencies);
   return await kernelForProgramInternal(toTestUri(fileName), options,
-      retainDataForTesting: retainDataForTesting);
+      retainDataForTesting: retainDataForTesting, requireMain: requireMain);
 }
 
 /// Generate a component for a modular compilation unit.
diff --git a/pkg/front_end/lib/src/testing/features.dart b/pkg/front_end/lib/src/testing/features.dart
index 4fd6391..36e32d7 100644
--- a/pkg/front_end/lib/src/testing/features.dart
+++ b/pkg/front_end/lib/src/testing/features.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'id_testing.dart';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 
 /// Utility class for annotated testing representing a set of features.
 class Features {
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index a7be604..fabb54f 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.dart
@@ -2,8 +2,8 @@
 // for 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/testing/id.dart';
 import 'package:kernel/ast.dart';
-import 'id.dart';
 
 /// Compute a canonical [Id] for kernel-based nodes.
 Id computeMemberId(Member node) {
@@ -140,6 +140,14 @@
     return new NodeId(node.fileOffset, IdKind.moveNext);
   }
 
+  NodeId createExpressionStatementId(ExpressionStatement node) {
+    if (node.expression.fileOffset == TreeNode.noOffset) {
+      // TODO(johnniwinther): Find out why we something have no offset.
+      return null;
+    }
+    return new NodeId(node.expression.fileOffset, IdKind.stmt);
+  }
+
   NodeId createLabeledStatementId(LabeledStatement node) =>
       computeDefaultNodeId(node.body);
   NodeId createLoopId(TreeNode node) => computeDefaultNodeId(node);
@@ -206,7 +214,11 @@
       computeForNode(node, createUpdateId(node));
       super.visitMethodInvocation(node);
     } else {
-      computeForNode(node, createInvokeId(node));
+      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));
+      }
       super.visitMethodInvocation(node);
     }
   }
@@ -269,6 +281,30 @@
   }
 
   @override
+  visitExpressionStatement(ExpressionStatement node) {
+    computeForNode(node, createExpressionStatementId(node));
+    return super.visitExpressionStatement(node);
+  }
+
+  @override
+  visitIfStatement(IfStatement node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    return super.visitIfStatement(node);
+  }
+
+  @override
+  visitTryCatch(TryCatch node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    return super.visitTryCatch(node);
+  }
+
+  @override
+  visitTryFinally(TryFinally node) {
+    computeForNode(node, computeDefaultNodeId(node));
+    return super.visitTryFinally(node);
+  }
+
+  @override
   visitDoStatement(DoStatement node) {
     computeForNode(node, createLoopId(node));
     super.visitDoStatement(node);
@@ -464,4 +500,11 @@
         node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
     return super.visitArguments(node);
   }
+
+  @override
+  visitBlock(Block node) {
+    computeForNode(
+        node, computeDefaultNodeId(node, skipNodeWithNoOffset: true));
+    return super.visitBlock(node);
+  }
 }
diff --git a/pkg/front_end/lib/src/testing/id_testing.dart b/pkg/front_end/lib/src/testing/id_testing.dart
deleted file mode 100644
index 5b001ac..0000000
--- a/pkg/front_end/lib/src/testing/id_testing.dart
+++ /dev/null
@@ -1,657 +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:io';
-import 'annotated_code_helper.dart';
-import 'id.dart';
-import '../fasta/colors.dart' as colors;
-
-const String cfeMarker = 'cfe';
-const String cfeWithNnbdMarker = '$cfeMarker:nnbd';
-const String dart2jsMarker = 'dart2js';
-const String analyzerMarker = 'analyzer';
-
-/// Markers used in annotated tests shard by CFE, analyzer and dart2js.
-const List<String> sharedMarkers = [
-  cfeMarker,
-  dart2jsMarker,
-  analyzerMarker,
-];
-
-/// Markers used in annotated tests shard by CFE, analyzer and dart2js.
-const List<String> sharedMarkersWithNnbd = [
-  cfeMarker,
-  cfeWithNnbdMarker,
-  dart2jsMarker,
-  analyzerMarker,
-];
-
-/// `true` if ANSI colors are supported by stdout.
-bool useColors = stdout.supportsAnsiEscapes;
-
-/// Colorize a message [text], if ANSI colors are supported.
-String colorizeMessage(String text) {
-  if (useColors) {
-    return '${colors.YELLOW_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize a matching annotation [text], if ANSI colors are supported.
-String colorizeMatch(String text) {
-  if (useColors) {
-    return '${colors.BLUE_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize a single annotation [text], if ANSI colors are supported.
-String colorizeSingle(String text) {
-  if (useColors) {
-    return '${colors.GREEN_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize the actual annotation [text], if ANSI colors are supported.
-String colorizeActual(String text) {
-  if (useColors) {
-    return '${colors.RED_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize an expected annotation [text], if ANSI colors are supported.
-String colorizeExpected(String text) {
-  if (useColors) {
-    return '${colors.GREEN_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize delimiter [text], if ANSI colors are supported.
-String colorizeDelimiter(String text) {
-  if (useColors) {
-    return '${colors.YELLOW_COLOR}${text}${colors.DEFAULT_COLOR}';
-  } else {
-    return text;
-  }
-}
-
-/// Colorize diffs [expected] and [actual] and [delimiter], if ANSI colors are
-/// supported.
-String colorizeDiff(String expected, String delimiter, String actual) {
-  return '${colorizeExpected(expected)}'
-      '${colorizeDelimiter(delimiter)}${colorizeActual(actual)}';
-}
-
-/// Colorize annotation delimiters [start] and [end] surrounding [text], if
-/// ANSI colors are supported.
-String colorizeAnnotation(String start, String text, String end) {
-  return '${colorizeDelimiter(start)}$text${colorizeDelimiter(end)}';
-}
-
-/// Encapsulates the member data computed for each source file of interest.
-/// It's a glorified wrapper around a map of maps, but written this way to
-/// provide a little more information about what it's doing. [DataType] refers
-/// to the type this map is holding -- it is either [IdValue] or [ActualData].
-class MemberAnnotations<DataType> {
-  /// For each Uri, we create a map associating an element id with its
-  /// corresponding annotations.
-  final Map<Uri, Map<Id, DataType>> _computedDataForEachFile =
-      new Map<Uri, Map<Id, DataType>>();
-
-  /// Member or class annotations that don't refer to any of the user files.
-  final Map<Id, DataType> globalData = <Id, DataType>{};
-
-  void operator []=(Uri file, Map<Id, DataType> computedData) {
-    _computedDataForEachFile[file] = computedData;
-  }
-
-  void forEach(void f(Uri file, Map<Id, DataType> computedData)) {
-    _computedDataForEachFile.forEach(f);
-  }
-
-  Map<Id, DataType> operator [](Uri file) {
-    if (!_computedDataForEachFile.containsKey(file)) {
-      _computedDataForEachFile[file] = <Id, DataType>{};
-    }
-    return _computedDataForEachFile[file];
-  }
-
-  @override
-  String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb.write('MemberAnnotations(');
-    String comma = '';
-    if (_computedDataForEachFile.isNotEmpty &&
-        (_computedDataForEachFile.length > 1 ||
-            _computedDataForEachFile.values.single.isNotEmpty)) {
-      sb.write('data:{');
-      _computedDataForEachFile.forEach((Uri uri, Map<Id, DataType> data) {
-        sb.write(comma);
-        sb.write('$uri:');
-        sb.write(data);
-        comma = ',';
-      });
-      sb.write('}');
-    }
-    if (globalData.isNotEmpty) {
-      sb.write(comma);
-      sb.write('global:');
-      sb.write(globalData);
-    }
-    sb.write(')');
-    return sb.toString();
-  }
-}
-
-/// Compute a [MemberAnnotations] object from [code] for each marker in [maps]
-/// specifying the expected annotations.
-///
-/// If an annotation starts with a marker, it is only expected for the
-/// corresponding test configuration. Otherwise it is expected for all
-/// configurations.
-// TODO(johnniwinther): Support an empty marker set.
-void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
-    Map<String, MemberAnnotations<IdValue>> maps,
-    {void onFailure(String message)}) {
-  List<String> mapKeys = maps.keys.toList();
-  Map<String, AnnotatedCode> split = splitByPrefixes(code, mapKeys);
-
-  split.forEach((String marker, AnnotatedCode code) {
-    MemberAnnotations<IdValue> fileAnnotations = maps[marker];
-    assert(fileAnnotations != null, "No annotations for $marker in $maps");
-    Map<Id, IdValue> expectedValues = fileAnnotations[sourceUri];
-    for (Annotation annotation in code.annotations) {
-      String text = annotation.text;
-      IdValue idValue = IdValue.decode(sourceUri, annotation.offset, text);
-      if (idValue.id.isGlobal) {
-        if (fileAnnotations.globalData.containsKey(idValue.id)) {
-          onFailure("Error in test '$filename': "
-              "Duplicate annotations for ${idValue.id} in $marker: "
-              "${idValue} and ${fileAnnotations.globalData[idValue.id]}.");
-        }
-        fileAnnotations.globalData[idValue.id] = idValue;
-      } else {
-        if (expectedValues.containsKey(idValue.id)) {
-          onFailure("Error in test '$filename': "
-              "Duplicate annotations for ${idValue.id} in $marker: "
-              "${idValue} and ${expectedValues[idValue.id]}.");
-        }
-        expectedValues[idValue.id] = idValue;
-      }
-    }
-  });
-}
-
-/// Creates a [TestData] object for the annotated test in [testFile].
-///
-/// If [testFile] is a file, use that directly. If it's a directory include
-/// everything in that directory.
-///
-/// 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 createUriForFileName(String fileName),
-    void onFailure(String message)}) {
-  Uri entryPoint = createUriForFileName('main.dart');
-
-  String testName;
-  File mainTestFile;
-  Uri testFileUri = testFile.uri;
-  Map<String, File> additionalFiles;
-  if (testFile is File) {
-    testName = testFileUri.pathSegments.last;
-    mainTestFile = testFile;
-  } else if (testFile is Directory) {
-    testName = testFileUri.pathSegments[testFileUri.pathSegments.length - 2];
-    additionalFiles = new Map<String, File>();
-    for (FileSystemEntity entry in testFile.listSync(recursive: true)) {
-      if (entry is! File) continue;
-      if (entry.uri.pathSegments.last == "main.dart") {
-        mainTestFile = entry;
-      } else {
-        additionalFiles[entry.uri.path.substring(testFile.uri.path.length)] =
-            entry;
-      }
-    }
-    assert(
-        mainTestFile != null, "No 'main.dart' test file found for $testFile.");
-  }
-
-  String annotatedCode = new File.fromUri(mainTestFile.uri).readAsStringSync();
-  Map<Uri, AnnotatedCode> code = {
-    entryPoint:
-        new AnnotatedCode.fromText(annotatedCode, commentStart, commentEnd)
-  };
-  Map<String, MemberAnnotations<IdValue>> expectedMaps = {};
-  for (String testMarker in supportedMarkers) {
-    expectedMaps[testMarker] = new MemberAnnotations<IdValue>();
-  }
-  computeExpectedMap(entryPoint, testFile.uri.pathSegments.last,
-      code[entryPoint], expectedMaps,
-      onFailure: onFailure);
-  Map<String, String> memorySourceFiles = {
-    entryPoint.path: code[entryPoint].sourceCode
-  };
-
-  if (additionalFiles != null) {
-    for (MapEntry<String, File> additionalFileData in additionalFiles.entries) {
-      String libFileName = additionalFileData.key;
-      File libEntity = additionalFileData.value;
-      Uri libFileUri = createUriForFileName(libFileName);
-      String libCode = libEntity.readAsStringSync();
-      AnnotatedCode annotatedLibCode =
-          new AnnotatedCode.fromText(libCode, commentStart, commentEnd);
-      memorySourceFiles[libFileUri.path] = annotatedLibCode.sourceCode;
-      code[libFileUri] = annotatedLibCode;
-      computeExpectedMap(
-          libFileUri, libFileName, annotatedLibCode, expectedMaps,
-          onFailure: onFailure);
-    }
-  }
-
-  return new TestData(
-      testName, testFileUri, entryPoint, memorySourceFiles, code, expectedMaps);
-}
-
-/// Data for an annotated test.
-class TestData {
-  final String name;
-  final Uri testFileUri;
-  final Uri entryPoint;
-  final Map<String, String> memorySourceFiles;
-  final Map<Uri, AnnotatedCode> code;
-  final Map<String, MemberAnnotations<IdValue>> expectedMaps;
-
-  TestData(this.name, this.testFileUri, this.entryPoint, this.memorySourceFiles,
-      this.code, this.expectedMaps);
-}
-
-/// The actual result computed for an annotated test.
-abstract class CompiledData<T> {
-  final Uri mainUri;
-
-  /// For each Uri, a map associating an element id with the instrumentation
-  /// data we've collected for it.
-  final Map<Uri, Map<Id, ActualData<T>>> actualMaps;
-
-  /// Collected instrumentation data that doesn't refer to any of the user
-  /// files.  (E.g. information the test has collected about files in
-  /// `dart:core`).
-  final Map<Id, ActualData<T>> globalData;
-
-  CompiledData(this.mainUri, this.actualMaps, this.globalData);
-
-  Map<int, List<String>> computeAnnotations(Uri 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}';
-      annotations
-          .putIfAbsent(data.offset, () => [])
-          .add(colorizeActual(value1));
-    });
-    return annotations;
-  }
-
-  Map<int, List<String>> computeDiffAnnotationsAgainst(
-      Map<Id, ActualData<T>> thisMap, Map<Id, ActualData<T>> otherMap, Uri uri,
-      {bool includeMatches: false}) {
-    Map<int, List<String>> annotations = <int, List<String>>{};
-    thisMap.forEach((Id id, ActualData<T> thisData) {
-      ActualData<T> otherData = otherMap[id];
-      String thisValue = '${thisData.value}';
-      if (thisData.value != otherData?.value) {
-        String otherValue = '${otherData?.value ?? '---'}';
-        annotations
-            .putIfAbsent(thisData.offset, () => [])
-            .add(colorizeDiff(thisValue, ' | ', otherValue));
-      } else if (includeMatches) {
-        annotations
-            .putIfAbsent(thisData.offset, () => [])
-            .add(colorizeMatch(thisValue));
-      }
-    });
-    otherMap.forEach((Id id, ActualData<T> otherData) {
-      if (!thisMap.containsKey(id)) {
-        String thisValue = '---';
-        String otherValue = '${otherData.value}';
-        annotations
-            .putIfAbsent(otherData.offset, () => [])
-            .add(colorizeDiff(thisValue, ' | ', otherValue));
-      }
-    });
-    return annotations;
-  }
-
-  int getOffsetFromId(Id id, Uri uri);
-
-  void reportError(Uri uri, int offset, String message, {bool succinct: false});
-}
-
-/// Interface used for interpreting annotations.
-abstract class DataInterpreter<T> {
-  /// 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);
-
-  /// Returns `true` if [actualData] corresponds to empty data.
-  bool isEmpty(T actualData);
-
-  /// Returns a textual representation of [actualData].
-  String getText(T actualData);
-}
-
-/// Default data interpreter for string data.
-class StringDataInterpreter implements DataInterpreter<String> {
-  const StringDataInterpreter();
-
-  @override
-  String isAsExpected(String actualData, String expectedData) {
-    actualData ??= '';
-    expectedData ??= '';
-    if (actualData != expectedData) {
-      return "Expected $expectedData, found $actualData";
-    }
-    return null;
-  }
-
-  @override
-  bool isEmpty(String actualData) {
-    return actualData == '';
-  }
-
-  @override
-  String getText(String actualData) {
-    return actualData;
-  }
-}
-
-String withAnnotations(String sourceCode, Map<int, List<String>> annotations) {
-  StringBuffer sb = new StringBuffer();
-  int end = 0;
-  for (int offset in annotations.keys.toList()..sort()) {
-    if (offset >= sourceCode.length) {
-      sb.write('...');
-      return sb.toString();
-    }
-    if (offset > end) {
-      sb.write(sourceCode.substring(end, offset));
-    }
-    for (String annotation in annotations[offset]) {
-      sb.write(colorizeAnnotation('/*', annotation, '*/'));
-    }
-    end = offset;
-  }
-  if (end < sourceCode.length) {
-    sb.write(sourceCode.substring(end));
-  }
-  return sb.toString();
-}
-
-/// Computed and expected data for an annotated test. This is used for checking
-/// and displaying results of an annotated test.
-class IdData<T> {
-  final Map<Uri, AnnotatedCode> code;
-  final MemberAnnotations<IdValue> expectedMaps;
-  final CompiledData<T> _compiledData;
-  final MemberAnnotations<ActualData<T>> _actualMaps = new MemberAnnotations();
-
-  IdData(this.code, this.expectedMaps, this._compiledData) {
-    for (Uri uri in code.keys) {
-      _actualMaps[uri] = _compiledData.actualMaps[uri] ?? <Id, ActualData<T>>{};
-    }
-    _actualMaps.globalData.addAll(_compiledData.globalData);
-  }
-
-  Uri get mainUri => _compiledData.mainUri;
-  MemberAnnotations<ActualData<T>> get actualMaps => _actualMaps;
-
-  String actualCode(Uri uri) {
-    Map<int, List<String>> annotations = <int, List<String>>{};
-    actualMaps[uri].forEach((Id id, ActualData<T> data) {
-      annotations.putIfAbsent(data.offset, () => []).add('${data.value}');
-    });
-    return withAnnotations(code[uri].sourceCode, annotations);
-  }
-
-  String diffCode(Uri uri, DataInterpreter<T> dataValidator) {
-    Map<int, List<String>> annotations = <int, List<String>>{};
-    actualMaps[uri].forEach((Id id, ActualData<T> data) {
-      IdValue expectedValue = expectedMaps[uri][id];
-      T actualValue = data.value;
-      String unexpectedMessage =
-          dataValidator.isAsExpected(actualValue, expectedValue?.value);
-      if (unexpectedMessage != null) {
-        String expected = expectedValue?.toString() ?? '';
-        String actual = dataValidator.getText(actualValue);
-        int offset = getOffsetFromId(id, uri);
-        if (offset != null) {
-          String value1 = '${expected}';
-          String value2 = IdValue.idToString(id, '${actual}');
-          annotations
-              .putIfAbsent(offset, () => [])
-              .add(colorizeDiff(value1, ' | ', value2));
-        }
-      }
-    });
-    expectedMaps[uri].forEach((Id id, IdValue expected) {
-      if (!actualMaps[uri].containsKey(id)) {
-        int offset = getOffsetFromId(id, uri);
-        if (offset != null) {
-          String value1 = '${expected}';
-          String value2 = '---';
-          annotations
-              .putIfAbsent(offset, () => [])
-              .add(colorizeDiff(value1, ' | ', value2));
-        }
-      }
-    });
-    return withAnnotations(code[uri].sourceCode, annotations);
-  }
-
-  int getOffsetFromId(Id id, Uri uri) {
-    return _compiledData.getOffsetFromId(id, uri);
-  }
-}
-
-/// Checks [compiledData] against the expected data in [expectedMaps] derived
-/// from [code].
-Future<bool> checkCode<T>(
-    String modeName,
-    Uri mainFileUri,
-    Map<Uri, AnnotatedCode> code,
-    MemberAnnotations<IdValue> expectedMaps,
-    CompiledData<T> compiledData,
-    DataInterpreter<T> dataValidator,
-    {bool filterActualData(IdValue expected, ActualData<T> actualData),
-    bool fatalErrors: true,
-    bool succinct: false,
-    void onFailure(String message)}) async {
-  IdData<T> data = new IdData<T>(code, expectedMaps, compiledData);
-  bool hasFailure = false;
-  Set<Uri> neededDiffs = new Set<Uri>();
-
-  void checkActualMap(
-      Map<Id, ActualData<T>> actualMap, Map<Id, IdValue> expectedMap,
-      [Uri uri]) {
-    bool hasLocalFailure = false;
-    actualMap.forEach((Id id, ActualData<T> actualData) {
-      T actual = actualData.value;
-      String actualText = dataValidator.getText(actual);
-
-      if (!expectedMap.containsKey(id)) {
-        if (!dataValidator.isEmpty(actual)) {
-          String actualValueText = IdValue.idToString(id, actualText);
-          compiledData.reportError(
-              actualData.uri,
-              actualData.offset,
-              succinct
-                  ? 'EXTRA $modeName DATA for ${id.descriptor}'
-                  : 'EXTRA $modeName DATA for ${id.descriptor}:\n '
-                      'object   : ${actualData.objectText}\n '
-                      'actual   : ${colorizeActual(actualValueText)}\n '
-                      'Data was expected for these ids: ${expectedMap.keys}',
-              succinct: succinct);
-          if (filterActualData == null || filterActualData(null, actualData)) {
-            hasLocalFailure = true;
-          }
-        }
-      } else {
-        IdValue expected = expectedMap[id];
-        String unexpectedMessage =
-            dataValidator.isAsExpected(actual, expected.value);
-        if (unexpectedMessage != null) {
-          String actualValueText = IdValue.idToString(id, actualText);
-          compiledData.reportError(
-              actualData.uri,
-              actualData.offset,
-              succinct
-                  ? 'UNEXPECTED $modeName DATA for ${id.descriptor}'
-                  : 'UNEXPECTED $modeName DATA for ${id.descriptor}:\n '
-                      'detail  : ${colorizeMessage(unexpectedMessage)}\n '
-                      'object  : ${actualData.objectText}\n '
-                      'expected: ${colorizeExpected('$expected')}\n '
-                      'actual  : ${colorizeActual(actualValueText)}',
-              succinct: succinct);
-          if (filterActualData == null ||
-              filterActualData(expected, actualData)) {
-            hasLocalFailure = true;
-          }
-        }
-      }
-    });
-    if (hasLocalFailure) {
-      hasFailure = true;
-      if (uri != null) {
-        neededDiffs.add(uri);
-      }
-    }
-  }
-
-  data.actualMaps.forEach((Uri uri, Map<Id, ActualData<T>> actualMap) {
-    checkActualMap(actualMap, data.expectedMaps[uri], uri);
-  });
-  checkActualMap(data.actualMaps.globalData, data.expectedMaps.globalData);
-
-  Set<Id> missingIds = new Set<Id>();
-  void checkMissing(
-      Map<Id, IdValue> expectedMap, Map<Id, ActualData<T>> actualMap,
-      [Uri uri]) {
-    expectedMap.forEach((Id id, IdValue expected) {
-      if (!actualMap.containsKey(id)) {
-        missingIds.add(id);
-        String message = 'MISSING $modeName DATA for ${id.descriptor}: '
-            'Expected ${colorizeExpected('$expected')}';
-        if (uri != null) {
-          compiledData.reportError(
-              uri, compiledData.getOffsetFromId(id, uri), message,
-              succinct: succinct);
-        } else {
-          print(message);
-        }
-      }
-    });
-    if (missingIds.isNotEmpty && uri != null) {
-      neededDiffs.add(uri);
-    }
-  }
-
-  data.expectedMaps.forEach((Uri uri, Map<Id, IdValue> expectedMap) {
-    checkMissing(expectedMap, data.actualMaps[uri], uri);
-  });
-  checkMissing(data.expectedMaps.globalData, data.actualMaps.globalData);
-  if (!succinct) {
-    for (Uri uri in neededDiffs) {
-      print('--annotations diff [${uri.pathSegments.last}]-------------');
-      print(data.diffCode(uri, dataValidator));
-      print('----------------------------------------------------------');
-    }
-  }
-  if (missingIds.isNotEmpty) {
-    print("MISSING ids: ${missingIds}.");
-    hasFailure = true;
-  }
-  if (hasFailure && fatalErrors) {
-    onFailure('Errors found.');
-  }
-  return hasFailure;
-}
-
-typedef Future<bool> RunTestFunction(TestData testData,
-    {bool testAfterFailures, bool verbose, bool succinct, bool printCode});
-
-/// Check code for all tests in [dataDir] using [runTest].
-Future runTests(Directory dataDir,
-    {List<String> args: const <String>[],
-    int shards: 1,
-    int shardIndex: 0,
-    void onTest(Uri uri),
-    Iterable<String> supportedMarkers,
-    Uri createUriForFileName(String fileName),
-    void onFailure(String message),
-    RunTestFunction runTest}) async {
-  // TODO(johnniwinther): Support --show to show actual data for an input.
-  args = args.toList();
-  bool verbose = args.remove('-v');
-  bool succinct = args.remove('-s');
-  bool shouldContinue = args.remove('-c');
-  bool testAfterFailures = args.remove('-a');
-  bool printCode = args.remove('-p');
-  bool continued = false;
-  bool hasFailures = false;
-
-  String relativeDir = dataDir.uri.path.replaceAll(Uri.base.path, '');
-  print('Data dir: ${relativeDir}');
-  List<FileSystemEntity> entities = dataDir.listSync();
-  if (shards > 1) {
-    int start = entities.length * shardIndex ~/ shards;
-    int end = entities.length * (shardIndex + 1) ~/ shards;
-    entities = entities.sublist(start, end);
-  }
-  int testCount = 0;
-  for (FileSystemEntity entity in entities) {
-    String name = entity.uri.pathSegments.last;
-    if (entity is Directory) {
-      name = entity.uri.pathSegments[entity.uri.pathSegments.length - 2];
-    }
-    if (args.isNotEmpty && !args.contains(name) && !continued) continue;
-    if (shouldContinue) continued = true;
-    testCount++;
-
-    if (onTest != null) {
-      onTest(entity.uri);
-    }
-    print('----------------------------------------------------------------');
-
-    TestData testData = computeTestData(entity,
-        supportedMarkers: supportedMarkers,
-        createUriForFileName: createUriForFileName,
-        onFailure: onFailure);
-    print('Test: ${testData.testFileUri}');
-
-    if (await runTest(testData,
-        testAfterFailures: testAfterFailures,
-        verbose: verbose,
-        succinct: succinct,
-        printCode: printCode)) {
-      hasFailures = true;
-    }
-  }
-  if (hasFailures) {
-    onFailure('Errors found.');
-  }
-  if (testCount == 0) {
-    onFailure("No files were tested.");
-  }
-}
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 b6b91be..c95f2ec 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -2,21 +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:kernel/ast.dart';
-import '../api_prototype/compiler_options.dart'
-    show CompilerOptions, DiagnosticMessage;
-import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
-import '../api_prototype/terminal_color_support.dart'
-    show printDiagnosticMessage;
-import '../base/common.dart';
-import '../fasta/messages.dart' show FormattedMessage;
-import '../fasta/severity.dart' show Severity;
-import '../kernel_generator_impl.dart' show InternalCompilerResult;
-import 'compiler_common.dart' show compileScript, toTestUri;
-import 'id.dart'
+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;
-import 'id_extractor.dart' show DataExtractor;
-import 'id_testing.dart'
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show
         CompiledData,
         DataInterpreter,
@@ -26,6 +15,17 @@
         cfeMarker,
         cfeWithNnbdMarker,
         checkCode;
+import 'package:kernel/ast.dart';
+import '../api_prototype/compiler_options.dart'
+    show CompilerOptions, DiagnosticMessage;
+import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+import '../api_prototype/terminal_color_support.dart'
+    show printDiagnosticMessage;
+import '../base/common.dart';
+import '../fasta/messages.dart' show FormattedMessage;
+import '../kernel_generator_impl.dart' show InternalCompilerResult;
+import 'compiler_common.dart' show compileScript, toTestUri;
+import 'id_extractor.dart' show DataExtractor;
 import 'id_testing_utils.dart';
 
 export '../fasta/compiler_context.dart' show CompilerContext;
@@ -258,7 +258,8 @@
   InternalCompilerResult compilerResult = await compileScript(
       testData.memorySourceFiles,
       options: options,
-      retainDataForTesting: true);
+      retainDataForTesting: true,
+      requireMain: false);
 
   Component component = compilerResult.component;
   Map<Uri, Map<Id, ActualData<T>>> actualMaps = <Uri, Map<Id, ActualData<T>>>{};
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 2c5d963..7b85105 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -158,10 +158,9 @@
   if (classBuilder != null) {
     if (member is Constructor || member is Procedure && member.isFactory) {
       memberBuilder = classBuilder.constructors.local[memberName];
-    } else if (member is Procedure && member.isSetter) {
-      memberBuilder = classBuilder.scope.setters[memberName];
     } else {
-      memberBuilder = classBuilder.scope.local[memberName];
+      memberBuilder = classBuilder.scope.lookupLocalMember(memberName,
+          setter: member is Procedure && member.isSetter);
     }
   }
   if (memberBuilder == null && required) {
@@ -196,11 +195,12 @@
         required: required);
   } else {
     TypeParameterScopeBuilder libraryBuilder = lookupLibraryDeclarationBuilder(
-        compilerResult, member.enclosingLibrary);
+        compilerResult, member.enclosingLibrary,
+        required: required);
     if (member is Procedure && member.isSetter) {
-      memberBuilder = libraryBuilder.members[member.name.name];
-    } else {
       memberBuilder = libraryBuilder.setters[member.name.name];
+    } else {
+      memberBuilder = libraryBuilder.members[member.name.name];
     }
   }
   if (memberBuilder == null && required) {
@@ -222,11 +222,8 @@
       lookupExtensionBuilder(compilerResult, extension, required: required);
   MemberBuilder memberBuilder;
   if (extensionBuilder != null) {
-    if (isSetter) {
-      memberBuilder = extensionBuilder.scope.setters[memberName];
-    } else {
-      memberBuilder = extensionBuilder.scope.local[memberName];
-    }
+    memberBuilder =
+        extensionBuilder.scope.lookupLocalMember(memberName, setter: isSetter);
   }
   if (memberBuilder == null && required) {
     throw new ArgumentError("MemberBuilder for $member not found.");
@@ -236,17 +233,17 @@
 
 /// Returns a textual representation of the constant [node] to be used in
 /// testing.
-String constantToText(Constant node) {
+String constantToText(Constant node, {bool isNonNullableByDefault: false}) {
   StringBuffer sb = new StringBuffer();
-  new ConstantToTextVisitor(sb).visit(node);
+  new ConstantToTextVisitor(sb, isNonNullableByDefault).visit(node);
   return sb.toString();
 }
 
 /// Returns a textual representation of the type [node] to be used in
 /// testing.
-String typeToText(DartType node) {
+String typeToText(DartType node, {bool isNonNullableByDefault: false}) {
   StringBuffer sb = new StringBuffer();
-  new DartTypeToTextVisitor(sb).visit(node);
+  new DartTypeToTextVisitor(sb, isNonNullableByDefault).visit(node);
   return sb.toString();
 }
 
@@ -254,7 +251,8 @@
   final StringBuffer sb;
   final DartTypeToTextVisitor typeToText;
 
-  ConstantToTextVisitor(this.sb) : typeToText = new DartTypeToTextVisitor(sb);
+  ConstantToTextVisitor(this.sb, bool isNonNullableByDefault)
+      : typeToText = new DartTypeToTextVisitor(sb, isNonNullableByDefault);
 
   void visit(Constant node) => node.accept(this);
 
@@ -377,8 +375,9 @@
 
 class DartTypeToTextVisitor implements DartTypeVisitor<void> {
   final StringBuffer sb;
+  final bool isNonNullableByDefault;
 
-  DartTypeToTextVisitor(this.sb);
+  DartTypeToTextVisitor(this.sb, this.isNonNullableByDefault);
 
   void visit(DartType node) => node.accept(this);
 
@@ -410,6 +409,10 @@
     sb.write('<bottom>');
   }
 
+  void visitNeverType(NeverType node) {
+    sb.write('Never');
+  }
+
   void visitInterfaceType(InterfaceType node) {
     sb.write(node.classNode.name);
     if (node.typeArguments.isNotEmpty) {
@@ -418,7 +421,8 @@
       sb.write('>');
     }
     if (!isNull(node)) {
-      sb.write(nullabilityToText(node.nullability));
+      sb.write(nullabilityToText(node.nullability,
+          isNonNullableByDefault: isNonNullableByDefault));
     }
   }
 
@@ -450,14 +454,16 @@
       sb.write('}');
     }
     sb.write(')');
-    sb.write(nullabilityToText(node.nullability));
+    sb.write(nullabilityToText(node.nullability,
+        isNonNullableByDefault: isNonNullableByDefault));
     sb.write('->');
     visit(node.returnType);
   }
 
   void visitTypeParameterType(TypeParameterType node) {
     sb.write(node.parameter.name);
-    sb.write(nullabilityToText(node.nullability));
+    sb.write(nullabilityToText(node.nullability,
+        isNonNullableByDefault: isNonNullableByDefault));
     if (node.promotedBound != null) {
       sb.write(' extends ');
       visit(node.promotedBound);
@@ -471,7 +477,8 @@
       visitList(node.typeArguments);
       sb.write('>');
     }
-    sb.write(nullabilityToText(node.nullability));
+    sb.write(nullabilityToText(node.nullability,
+        isNonNullableByDefault: isNonNullableByDefault));
   }
 }
 
@@ -581,16 +588,18 @@
 }
 
 /// Returns a textual representation of [nullability] to be used in testing.
-String nullabilityToText(Nullability nullability) {
+String nullabilityToText(Nullability nullability,
+    {bool isNonNullableByDefault}) {
+  assert(isNonNullableByDefault != null);
   switch (nullability) {
     case Nullability.nonNullable:
-      return '!';
+      return isNonNullableByDefault ? '' : '!';
     case Nullability.nullable:
       return '?';
-    case Nullability.neither:
+    case Nullability.undetermined:
       return '%';
     case Nullability.legacy:
-      return '';
+      return isNonNullableByDefault ? '*' : '';
   }
   throw new UnsupportedError('Unexpected nullability: $nullability.');
 }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index de43c6a..59c95bc 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -25,7 +25,6 @@
 AsyncAsIdentifier/example: Fail
 AwaitAsIdentifier/example: Fail
 AwaitNotAsync/example: Fail
-BadTypeVariableInSupertype/analyzerCode: Fail
 BuiltInIdentifierAsType/example: Fail
 BuiltInIdentifierInDeclaration/example: Fail
 BytecodeLimitExceededTooManyArguments/analyzerCode: Fail
@@ -76,6 +75,7 @@
 ConstEvalDuplicateElement/example: Fail
 ConstEvalDuplicateKey/example: Fail
 ConstEvalElementImplementsEqual/example: Fail
+ConstEvalExtension/example: Fail
 ConstEvalFailedAssertion/example: Fail
 ConstEvalFailedAssertionWithMessage/example: Fail
 ConstEvalFreeTypeParameter/analyzerCode: Fail
@@ -344,6 +344,16 @@
 InvalidPackageUri/example: Fail
 InvalidSuperInInitializer/example: Fail
 InvalidThisInInitializer/example: Fail
+InvalidTypeVariableInSupertype/analyzerCode: Fail
+InvalidTypeVariableInSupertypeWithVariance/analyzerCode: Fail
+InvalidTypeVariableInSupertypeWithVariance/part_wrapped_script: Fail # Triggers multiple errors
+InvalidTypeVariableInSupertypeWithVariance/script: Fail # Triggers multiple errors
+InvalidTypeVariableVariancePosition/analyzerCode: Fail
+InvalidTypeVariableVariancePosition/part_wrapped_script: Fail # Triggers multiple errors
+InvalidTypeVariableVariancePosition/script: Fail # Triggers multiple errors
+InvalidTypeVariableVariancePositionInReturnType/analyzerCode: Fail
+InvalidTypeVariableVariancePositionInReturnType/part_wrapped_script: Fail # Triggers multiple errors
+InvalidTypeVariableVariancePositionInReturnType/script: Fail # Triggers multiple errors
 InvalidUseOfNullAwareAccess/example: Fail
 InvalidVoid/part_wrapped_script1: Fail
 InvalidVoid/part_wrapped_script2: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 290619a..fcdaead 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -182,6 +182,10 @@
   template: "Only maps can be used in spreads in constant maps."
   analyzerCode: CONST_SPREAD_EXPECTED_MAP
 
+ConstEvalExtension:
+  template: "Extension operations can't be used in constant expressions."
+  analyzerCode: NOT_CONSTANT_EXPRESSION
+
 ConstEvalUnevaluated:
   template: "Could not evaluate constant expression."
 
@@ -3615,12 +3619,34 @@
       <int>[...null];
     }
 
-BadTypeVariableInSupertype:
-  template: "Found unsupported uses of '#name' in supertype '#name2'."
+InvalidTypeVariableInSupertype:
+  template: "Can't use implicitly 'out' variable '#name' in an '#string2' position in supertype '#name2'."
   script: >
     class A<X> {}
     class B<Y> extends A<Function(Y)> {}
 
+InvalidTypeVariableInSupertypeWithVariance:
+  template: "Can't use '#string' type variable '#name' in an '#string2' position in supertype '#name2'."
+  script: >
+    class A<out X> {}
+    class B<out Y> extends A<Function(Y)> {}
+
+InvalidTypeVariableVariancePosition:
+  template: "Can't use '#string' type variable '#name' in an '#string2' position."
+  script: >
+    class A<out T> {
+      void method(T x) {}
+    }
+
+InvalidTypeVariableVariancePositionInReturnType:
+  template: "Can't use '#string' type variable '#name' in an '#string2' position in the return type."
+  script: >
+    class A<in T> {
+      T method() {
+        return null;
+      }
+    }
+
 IllegalRecursiveType:
   template: "Illegal recursive type '#type'."
   script: >
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart
new file mode 100644
index 0000000..19771e9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart
@@ -0,0 +1,3 @@
+main() async {
+  await for () {}
+}
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
new file mode 100644
index 0000000..2199837
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
@@ -0,0 +1,56 @@
+Problems reported:
+
+parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+  await for () {}
+             ^
+
+parser_test/error_recovery/empty_await_for:2:14: Expected 'in' before this.
+  await for () {}
+             ^
+
+parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+  await for () {}
+             ^
+
+parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+  await for () {}
+             ^
+
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(async, null)
+      beginBlockFunctionBody({)
+        beginForStatement(for)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          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 ')'., null, {token: )}], ), ))
+          beginForInExpression())
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+            handleIdentifier(, expression)
+            handleNoTypeArguments())
+            handleNoArguments())
+            handleSend(, ))
+          endForInExpression())
+          handleForInLoopParts(await, for, (, in)
+          beginForInBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForInBody(})
+        endForIn(})
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
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
new file mode 100644
index 0000000..5b35362
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
@@ -0,0 +1,91 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(async, null)
+          inPlainSync()
+        parseFunctionBody(async, false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, await)
+          parseStatement({)
+            parseStatementX({)
+              parseForStatement(await, await)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(await, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers((, (, null, null, null, true)
+                parseForLoopPartsMid((, await, for)
+                  parseExpression(()
+                    parsePrecedenceExpression((, 1, true)
+                      parseUnaryExpression((, true)
+                        parsePrimary((, expression)
+                          parseSend((, expression)
+                            ensureIdentifier((, expression)
+                              reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                              rewriter()
+                              listener: handleIdentifier(, expression)
+                            listener: handleNoTypeArguments())
+                            parseArgumentsOpt()
+                              listener: handleNoArguments())
+                            listener: handleSend(, ))
+                  listener: handleForInitializerExpressionStatement(, true)
+                  reportRecoverableError(), Message[ExpectedButGot, Expected 'in' before this., null, {string: in}])
+                    listener: handleRecoverableError(Message[ExpectedButGot, Expected 'in' before this., null, {string: in}], ), ))
+                parseForInRest(, await, for, ))
+                  parseForInLoopPartsRest(, await, for, ))
+                    reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                    listener: beginForInExpression())
+                    parseExpression(in)
+                      parsePrecedenceExpression(in, 1, true)
+                        parseUnaryExpression(in, true)
+                          parsePrimary(in, expression)
+                            parseSend(in, expression)
+                              ensureIdentifier(in, expression)
+                                reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                rewriter()
+                                listener: handleIdentifier(, expression)
+                              listener: handleNoTypeArguments())
+                              parseArgumentsOpt()
+                                listener: handleNoArguments())
+                              listener: handleSend(, ))
+                    ensureCloseParen(, ()
+                    listener: endForInExpression())
+                    listener: handleForInLoopParts(await, for, (, in)
+                  listener: beginForInBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForInBody(})
+                  listener: endForIn(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.parser.expect
new file mode 100644
index 0000000..981f0c9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+main() async {
+await for (in) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] async[KeywordToken] {[BeginToken]
+await[KeywordToken] for[KeywordToken] ([BeginToken][SyntheticStringToken]in[SyntheticKeywordToken][SyntheticStringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.scanner.expect
new file mode 100644
index 0000000..df66d85
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() async {
+await for () {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] async[KeywordToken] {[BeginToken]
+await[KeywordToken] for[KeywordToken] ([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart
new file mode 100644
index 0000000..3c33ee5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart
@@ -0,0 +1,3 @@
+main() {
+  for () {}
+}
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
new file mode 100644
index 0000000..63dc838
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
@@ -0,0 +1,55 @@
+Problems reported:
+
+parser_test/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
+  for () {}
+       ^
+
+parser_test/error_recovery/empty_for:2:8: Expected ';' after this.
+  for () {}
+       ^
+
+parser_test/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
+  for () {}
+       ^
+
+parser_test/error_recovery/empty_for:2:8: Expected ';' after this.
+  for () {}
+       ^
+
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginForStatement(for)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleIdentifier(, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(, ))
+          handleForInitializerExpressionStatement(, false)
+          handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleIdentifier(, expression)
+          handleNoTypeArguments())
+          handleNoArguments())
+          handleSend(, ))
+          handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+          handleExpressionStatement(;)
+          handleForLoopParts(for, (, ;, 0)
+          beginForStatementBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForStatementBody(})
+        endForStatement(})
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
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
new file mode 100644
index 0000000..96c0c6e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
@@ -0,0 +1,94 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, for)
+          parseStatement({)
+            parseStatementX({)
+              parseForStatement({, null)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(null, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers((, (, null, null, null, true)
+                parseForLoopPartsMid((, null, for)
+                  parseExpression(()
+                    parsePrecedenceExpression((, 1, true)
+                      parseUnaryExpression((, true)
+                        parsePrimary((, expression)
+                          parseSend((, expression)
+                            ensureIdentifier((, expression)
+                              reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                              rewriter()
+                              listener: handleIdentifier(, expression)
+                            listener: handleNoTypeArguments())
+                            parseArgumentsOpt()
+                              listener: handleNoArguments())
+                            listener: handleSend(, ))
+                  listener: handleForInitializerExpressionStatement(, false)
+                parseForRest(null, , for)
+                  parseForLoopPartsRest(, for, null)
+                    ensureSemicolon()
+                      reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                        listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+                      rewriter()
+                    parseExpressionStatement(;)
+                      parseExpression(;)
+                        parsePrecedenceExpression(;, 1, true)
+                          parseUnaryExpression(;, true)
+                            parsePrimary(;, expression)
+                              parseSend(;, expression)
+                                ensureIdentifier(;, expression)
+                                  reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                  rewriter()
+                                  listener: handleIdentifier(, expression)
+                                listener: handleNoTypeArguments())
+                                parseArgumentsOpt()
+                                  listener: handleNoArguments())
+                                listener: handleSend(, ))
+                      ensureSemicolon()
+                        reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                          listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+                        rewriter()
+                      listener: handleExpressionStatement(;)
+                    listener: handleForLoopParts(for, (, ;, 0)
+                  listener: beginForStatementBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForStatementBody(})
+                  listener: endForStatement(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.parser.expect
new file mode 100644
index 0000000..792bb5b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+main() {
+for (;;) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken][SyntheticStringToken];[SyntheticToken][SyntheticStringToken];[SyntheticToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.scanner.expect
new file mode 100644
index 0000000..d26ca13
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+for () {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart
new file mode 100644
index 0000000..c6672ff
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart
@@ -0,0 +1 @@
+f() { m(T<R(<Z
\ No newline at end of file
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
new file mode 100644
index 0000000..3f943f9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
@@ -0,0 +1,55 @@
+Problems reported:
+
+parser_test/error_recovery/issue_38415.crash:1:15: Expected '[' before this.
+f() { m(T<R(<Z
+              ^...
+
+parser_test/error_recovery/issue_38415.crash:1:15: Expected ';' after this.
+f() { m(T<R(<Z
+              ^...
+
+beginCompilationUnit(f)
+  beginMetadataStar(f)
+  endMetadataStar(0)
+  beginTopLevelMember(f)
+    beginTopLevelMethod(UnmatchedToken({), null)
+      handleNoType(UnmatchedToken({))
+      handleIdentifier(f, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(m, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+          handleIdentifier(T, expression)
+          handleNoTypeArguments(<)
+          handleNoArguments(<)
+          handleSend(T, <)
+          beginBinaryExpression(<)
+            handleIdentifier(R, expression)
+            handleNoTypeArguments(()
+            beginArguments(()
+              beginTypeArguments(<)
+                handleIdentifier(Z, typeReference)
+                handleNoTypeArguments())
+                handleType(Z, null)
+              endTypeArguments(1, <, >)
+              handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+              handleLiteralList(0, [, null, ])
+            endArguments(1, (, ))
+            handleSend(R, })
+          endBinaryExpression(<)
+        endArguments(1, (, ))
+        handleSend(m, })
+        handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(f, null, })
+  endTopLevelDeclaration()
+  handleErrorToken(UnmatchedToken(())
+  handleErrorToken(UnmatchedToken(<))
+  handleErrorToken(UnmatchedToken(())
+  handleErrorToken(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
new file mode 100644
index 0000000..de44d61b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.intertwined.expect
@@ -0,0 +1,113 @@
+parseUnit(UnmatchedToken(())
+  skipErrorTokens(UnmatchedToken(())
+  listener: beginCompilationUnit(f)
+  syntheticPreviousToken(f)
+  parseTopLevelDeclarationImpl(UnmatchedToken({), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken({))
+      listener: beginMetadataStar(f)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(UnmatchedToken({))
+      listener: beginTopLevelMember(f)
+      parseTopLevelMethod(UnmatchedToken({), null, UnmatchedToken({), Instance of 'NoType', null, f)
+        listener: beginTopLevelMethod(UnmatchedToken({), null)
+        listener: handleNoType(UnmatchedToken({))
+        ensureIdentifier(UnmatchedToken({), topLevelFunctionDeclaration)
+          listener: handleIdentifier(f, topLevelFunctionDeclaration)
+        parseMethodTypeVar(f)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(f, f, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(f, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, m)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(m)
+                parseExpressionStatement({)
+                  parseExpression({)
+                    parsePrecedenceExpression({, 1, true)
+                      parseUnaryExpression({, true)
+                        parsePrimary({, expression)
+                          parseSendOrFunctionLiteral({, expression)
+                            looksLikeFunctionBody(})
+                            parseSend({, expression)
+                              ensureIdentifier({, expression)
+                                listener: handleIdentifier(m, expression)
+                              listener: handleNoTypeArguments(()
+                              parseArgumentsOpt(m)
+                                parseArguments(m)
+                                  parseArgumentsRest(()
+                                    listener: beginArguments(()
+                                    parseExpression(()
+                                      parsePrecedenceExpression((, 1, true)
+                                        parseUnaryExpression((, true)
+                                          parsePrimary((, expression)
+                                            parseSendOrFunctionLiteral((, expression)
+                                              parseSend((, expression)
+                                                ensureIdentifier((, expression)
+                                                  listener: handleIdentifier(T, expression)
+                                                listener: handleNoTypeArguments(<)
+                                                parseArgumentsOpt(T)
+                                                  listener: handleNoArguments(<)
+                                                listener: handleSend(T, <)
+                                        listener: beginBinaryExpression(<)
+                                        parsePrecedenceExpression(<, 9, true)
+                                          parseUnaryExpression(<, true)
+                                            parsePrimary(<, expression)
+                                              parseSendOrFunctionLiteral(<, expression)
+                                                looksLikeFunctionBody(>)
+                                                parseSend(<, expression)
+                                                  ensureIdentifier(<, expression)
+                                                    listener: handleIdentifier(R, expression)
+                                                  listener: handleNoTypeArguments(()
+                                                  parseArgumentsOpt(R)
+                                                    parseArguments(R)
+                                                      parseArgumentsRest(()
+                                                        listener: beginArguments(()
+                                                        parseExpression(()
+                                                          parsePrecedenceExpression((, 1, true)
+                                                            parseUnaryExpression((, true)
+                                                              parsePrimary((, expression)
+                                                                parseLiteralListSetMapOrFunction((, null)
+                                                                  listener: beginTypeArguments(<)
+                                                                  listener: handleIdentifier(Z, typeReference)
+                                                                  listener: handleNoTypeArguments())
+                                                                  listener: handleType(Z, null)
+                                                                  listener: endTypeArguments(1, <, >)
+                                                                  reportRecoverableError(), Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
+                                                                    listener: handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], , )
+                                                                  rewriter()
+                                                                  parseLiteralListSuffix(>, null)
+                                                                    rewriteSquareBrackets(>)
+                                                                      link([, ])
+                                                                      rewriter()
+                                                                    listener: handleLiteralList(0, [, null, ])
+                                                        listener: endArguments(1, (, ))
+                                                  listener: handleSend(R, })
+                                        listener: endBinaryExpression(<)
+                                    ensureCloseParen(), ()
+                                      rewriter()
+                                    listener: endArguments(1, (, ))
+                              listener: handleSend(m, })
+                  ensureSemicolon())
+                    reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                      listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+                    rewriter()
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(f, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(<))
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken({))
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.parser.expect
new file mode 100644
index 0000000..a5946a9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+f() { m(T<R(<Z)>[]);}
+
+[UnmatchedToken][UnmatchedToken][UnmatchedToken][UnmatchedToken]f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] m[StringToken]([BeginToken]T[StringToken]<[BeginToken]R[StringToken]([BeginToken]<[BeginToken]Z[StringToken])[SyntheticToken]>[SyntheticToken][[SyntheticBeginToken]][SyntheticToken])[SyntheticToken];[SyntheticToken]}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.scanner.expect
new file mode 100644
index 0000000..74316ca
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { m(T<R(<Z)>)}
+
+[UnmatchedToken][UnmatchedToken][UnmatchedToken][UnmatchedToken]f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] m[StringToken]([BeginToken]T[StringToken]<[BeginToken]R[StringToken]([BeginToken]<[BeginToken]Z[StringToken])[SyntheticToken]>[SyntheticToken])[SyntheticToken]}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart
new file mode 100644
index 0000000..7094494
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart
@@ -0,0 +1 @@
+n<S e(
\ No newline at end of file
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
new file mode 100644
index 0000000..8edc8ca
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
@@ -0,0 +1,45 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39024.crash:1:3: Expected '>' after this.
+n<S e(
+  ^
+
+parser_test/error_recovery/issue_39024.crash:1:7: Expected an identifier, but got ''.
+n<S e(
+      ^...
+
+parser_test/error_recovery/issue_39024.crash:1:7: A function declaration needs an explicit list of parameters.
+n<S e(
+      ^...
+
+parser_test/error_recovery/issue_39024.crash:1:7: Expected a function body, but got ''.
+n<S e(
+      ^...
+
+beginCompilationUnit(n)
+  beginMetadataStar(n)
+  endMetadataStar(0)
+  beginTopLevelMember(n)
+    beginTopLevelMethod(UnmatchedToken(<), null)
+      handleIdentifier(n, typeReference)
+      beginTypeArguments(<)
+        handleIdentifier(S, typeReference)
+        handleNoTypeArguments(e)
+        handleType(S, null)
+        handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], S, S)
+      endTypeArguments(1, <, >)
+      handleType(n, null)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+      handleIdentifier(, topLevelFunctionDeclaration)
+      handleNoTypeVariables()
+      handleRecoverableError(MissingFunctionParameters, , )
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      handleRecoverableError(Message[ExpectedFunctionBody, Expected a function body, but got ''., null, {token: }], , )
+      handleInvalidFunctionBody({)
+    endTopLevelMethod(n, null, })
+  endTopLevelDeclaration()
+  handleErrorToken(UnmatchedToken(())
+  handleErrorToken(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
new file mode 100644
index 0000000..3dc962f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
@@ -0,0 +1,55 @@
+parseUnit(UnmatchedToken(())
+  skipErrorTokens(UnmatchedToken(())
+  listener: beginCompilationUnit(n)
+  syntheticPreviousToken(n)
+  parseTopLevelDeclarationImpl(UnmatchedToken(<), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken(<))
+      listener: beginMetadataStar(n)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(UnmatchedToken(<))
+      listener: beginTopLevelMember(n)
+      parseTopLevelMethod(UnmatchedToken(<), null, UnmatchedToken(<), Instance of 'ComplexTypeInfo', null, e)
+        listener: beginTopLevelMethod(UnmatchedToken(<), null)
+        ensureIdentifier(UnmatchedToken(<), typeReference)
+          listener: handleIdentifier(n, typeReference)
+        listener: beginTypeArguments(<)
+        listener: handleIdentifier(S, typeReference)
+        listener: handleNoTypeArguments(e)
+        listener: handleType(S, null)
+        reportRecoverableError(S, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
+          listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], S, S)
+        listener: endTypeArguments(1, <, >)
+        listener: handleType(n, null)
+        ensureIdentifier(>, topLevelFunctionDeclaration)
+          insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+            rewriter()
+          listener: handleIdentifier(, topLevelFunctionDeclaration)
+        parseMethodTypeVar()
+          listener: handleNoTypeVariables()
+        parseGetterOrFormalParameters(, , false, MemberKind.TopLevelMethod)
+          missingParameterMessage(MemberKind.TopLevelMethod)
+          reportRecoverableError(, MissingFunctionParameters)
+            listener: handleRecoverableError(MissingFunctionParameters, , )
+          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(n, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(<))
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.parser.expect
new file mode 100644
index 0000000..91d29ba
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+n<S e()>(){}
+
+[UnmatchedToken][UnmatchedToken]n[StringToken]<[BeginToken]S[StringToken] e[StringToken]([BeginToken])[SyntheticToken]>[SyntheticToken][SyntheticStringToken]([SyntheticBeginToken])[SyntheticToken]{[SyntheticBeginToken]}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.scanner.expect
new file mode 100644
index 0000000..25d92a2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+n<S e()>
+
+[UnmatchedToken][UnmatchedToken]n[StringToken]<[BeginToken]S[StringToken] e[StringToken]([BeginToken])[SyntheticToken]>[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart
new file mode 100644
index 0000000..9ec285b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart
@@ -0,0 +1,4 @@
+class A{
+    co <{
+    }
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect
new file mode 100644
index 0000000..01f26fa
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect
@@ -0,0 +1,46 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39026.crash:2:8: Operator declarations must be preceded by the keyword 'operator'.
+    co <{
+       ^
+
+parser_test/error_recovery/issue_39026.crash:2:8: A method declaration needs an explicit list of parameters.
+    co <{
+       ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(A, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, A)
+      handleNoType(A)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(co)
+        endMetadataStar(0)
+        beginMember()
+          handleRecoverableError(MissingOperatorKeyword, <, <)
+          beginMethod(null, null, null, null, null, operator)
+            handleIdentifier(co, typeReference)
+            handleNoTypeArguments(operator)
+            handleType(co, null)
+            handleOperatorName(operator, <)
+            handleNoTypeVariables({)
+            handleRecoverableError(MissingMethodParameters, <, <)
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+            endBlockFunctionBody(0, {, })
+          endClassMethod(null, co, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.intertwined.expect
new file mode 100644
index 0000000..51025d0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.intertwined.expect
@@ -0,0 +1,73 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(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(A, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, A)
+        parseClass(A, class, class, A)
+          parseClassHeaderOpt(A, class, class)
+            parseClassExtendsOpt(A)
+              listener: handleNoType(A)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(A)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(A)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(A, DeclarationKind.Class, A)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, co)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, A)
+              parseMetadataStar({)
+                listener: beginMetadataStar(co)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseInvalidOperatorDeclaration({, null, null, null, null, null, {, DeclarationKind.Class, A)
+                reportRecoverableError(<, MissingOperatorKeyword)
+                  listener: handleRecoverableError(MissingOperatorKeyword, <, <)
+                rewriter()
+                parseMethod({, null, null, null, null, null, {, Instance of 'SimpleType', null, operator, DeclarationKind.Class, A)
+                  listener: beginMethod(null, null, null, null, null, operator)
+                  listener: handleIdentifier(co, typeReference)
+                  listener: handleNoTypeArguments(operator)
+                  listener: handleType(co, null)
+                  parseOperatorName(co)
+                    listener: handleOperatorName(operator, <)
+                  parseMethodTypeVar(<)
+                    listener: handleNoTypeVariables({)
+                  parseGetterOrFormalParameters(<, operator, false, MemberKind.NonStaticMethod)
+                    missingParameterMessage(MemberKind.NonStaticMethod)
+                    reportRecoverableError(<, MissingMethodParameters)
+                      listener: handleRecoverableError(MissingMethodParameters, <, <)
+                    rewriter()
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                  parseInitializersOpt())
+                    listener: handleNoInitializers()
+                  parseAsyncModifierOpt())
+                    listener: handleAsyncModifier(null, null)
+                    inPlainSync()
+                  inPlainSync()
+                  parseFunctionBody(), false, true)
+                    listener: beginBlockFunctionBody({)
+                    notEofOrValue(}, })
+                    listener: endBlockFunctionBody(0, {, })
+                  listener: endClassMethod(null, co, (, null, })
+                listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.parser.expect
new file mode 100644
index 0000000..1265775
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+class A{
+co operator<(){
+}
+}
+
+class[KeywordToken] A[StringToken]{[BeginToken]
+co[StringToken] operator[SyntheticKeywordToken]<[BeginToken]([SyntheticBeginToken])[SyntheticToken]{[BeginToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.scanner.expect
new file mode 100644
index 0000000..8c73437
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.scanner.expect
@@ -0,0 +1,9 @@
+class A{
+co <{
+}
+}
+
+class[KeywordToken] A[StringToken]{[BeginToken]
+co[StringToken] <[BeginToken]{[BeginToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart
new file mode 100644
index 0000000..e5a6c50
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart
@@ -0,0 +1,4 @@
+class A{
+    co operator <{
+    }
+}
\ No newline at end of file
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect
new file mode 100644
index 0000000..93a5c86
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect
@@ -0,0 +1,41 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39026_prime.crash:2:17: A method declaration needs an explicit list of parameters.
+    co operator <{
+                ^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleIdentifier(A, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, A)
+      handleNoType(A)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(co)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, operator)
+            handleIdentifier(co, typeReference)
+            handleNoTypeArguments(operator)
+            handleType(co, null)
+            handleOperatorName(operator, <)
+            handleNoTypeVariables({)
+            handleRecoverableError(MissingMethodParameters, <, <)
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+            endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+            endBlockFunctionBody(0, {, })
+          endClassMethod(null, co, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.intertwined.expect
new file mode 100644
index 0000000..a52cd94
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.intertwined.expect
@@ -0,0 +1,69 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(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(A, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, A)
+        parseClass(A, class, class, A)
+          parseClassHeaderOpt(A, class, class)
+            parseClassExtendsOpt(A)
+              listener: handleNoType(A)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(A)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(A)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(A, DeclarationKind.Class, A)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, co)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, A)
+              parseMetadataStar({)
+                listener: beginMetadataStar(co)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, {, Instance of 'SimpleType', null, operator, DeclarationKind.Class, A)
+                listener: beginMethod(null, null, null, null, null, operator)
+                listener: handleIdentifier(co, typeReference)
+                listener: handleNoTypeArguments(operator)
+                listener: handleType(co, null)
+                parseOperatorName(co)
+                  listener: handleOperatorName(operator, <)
+                parseMethodTypeVar(<)
+                  listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(<, operator, false, MemberKind.NonStaticMethod)
+                  missingParameterMessage(MemberKind.NonStaticMethod)
+                  reportRecoverableError(<, MissingMethodParameters)
+                    listener: handleRecoverableError(MissingMethodParameters, <, <)
+                  rewriter()
+                  parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                    listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                    listener: endFormalParameters(0, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(0, {, })
+                listener: endClassMethod(null, co, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.parser.expect
new file mode 100644
index 0000000..3badd40
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+class A{
+co operator <(){
+}
+}
+
+class[KeywordToken] A[StringToken]{[BeginToken]
+co[StringToken] operator[KeywordToken] <[BeginToken]([SyntheticBeginToken])[SyntheticToken]{[BeginToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.scanner.expect
new file mode 100644
index 0000000..837ca71
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.scanner.expect
@@ -0,0 +1,9 @@
+class A{
+co operator <{
+}
+}
+
+class[KeywordToken] A[StringToken]{[BeginToken]
+co[StringToken] operator[KeywordToken] <[BeginToken]{[BeginToken]
+}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart
new file mode 100644
index 0000000..efd5943
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart
@@ -0,0 +1 @@
+typedef F<Glib.=
\ No newline at end of file
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
new file mode 100644
index 0000000..456c08a
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
@@ -0,0 +1,37 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39033.crash:1:11: Expected '>' after this.
+typedef F<Glib.=
+          ^^^^
+
+parser_test/error_recovery/issue_39033.crash:1:17: Expected a type, but got ''.
+typedef F<Glib.=
+                ^...
+
+parser_test/error_recovery/issue_39033.crash:1:17: Expected ';' after this.
+typedef F<Glib.=
+                ^...
+
+beginCompilationUnit(typedef)
+  beginMetadataStar(typedef)
+  endMetadataStar(0)
+  beginFunctionTypeAlias(typedef)
+    handleIdentifier(F, typedefDeclaration)
+    beginTypeVariables(<)
+      beginMetadataStar(Glib)
+      endMetadataStar(0)
+      handleIdentifier(Glib, typeVariableDeclaration)
+      beginTypeVariable(Glib)
+        handleTypeVariablesDefined(Glib, 1)
+        handleNoType(Glib)
+      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: }], , )
+    handleIdentifier(, typeReference)
+    handleNoTypeArguments()
+    handleType(, null)
+    handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+  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
new file mode 100644
index 0000000..cbcdcbf
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.intertwined.expect
@@ -0,0 +1,40 @@
+parseUnit(typedef)
+  skipErrorTokens(typedef)
+  listener: beginCompilationUnit(typedef)
+  syntheticPreviousToken(typedef)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(typedef)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, typedef, Instance of 'DirectiveContext')
+      parseTopLevelKeywordModifiers(, typedef)
+      parseTypedef(typedef)
+        listener: beginFunctionTypeAlias(typedef)
+        listener: handleIdentifier(F, typedefDeclaration)
+        listener: beginTypeVariables(<)
+        parseMetadataStar(<)
+          listener: beginMetadataStar(Glib)
+          listener: endMetadataStar(0)
+        ensureIdentifier(<, typeVariableDeclaration)
+          listener: handleIdentifier(Glib, typeVariableDeclaration)
+        listener: beginTypeVariable(Glib)
+        listener: handleTypeVariablesDefined(Glib, 1)
+        listener: handleNoType(Glib)
+        listener: endTypeVariable(., 0, null, null)
+        reportRecoverableError(Glib, Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}])
+          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: }], , )
+        rewriter()
+        listener: handleIdentifier(, typeReference)
+        listener: handleNoTypeArguments()
+        listener: handleType(, null)
+        ensureSemicolon()
+          reportRecoverableError(, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
+          rewriter()
+        listener: endFunctionTypeAlias(typedef, =, ;)
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(typedef)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.parser.expect
new file mode 100644
index 0000000..72d15cd
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+typedef F<Glib>.=;
+
+typedef[KeywordToken] F[StringToken]<[BeginToken]Glib[StringToken]>[SyntheticToken].[SimpleToken]=[SimpleToken][SyntheticStringToken];[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.scanner.expect
new file mode 100644
index 0000000..c422cf4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+typedef F<Glib.=
+
+typedef[KeywordToken] F[StringToken]<[BeginToken]Glib[StringToken].[SimpleToken]=[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart
new file mode 100644
index 0000000..7e8a2e8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart
@@ -0,0 +1 @@
+{<[](
\ No newline at end of file
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
new file mode 100644
index 0000000..c326fd9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
@@ -0,0 +1,27 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39058.crash:1:1: Expected a declaration, but got '{'.
+{<[](
+^
+
+beginCompilationUnit({)
+  beginMetadataStar({)
+  endMetadataStar(0)
+  beginTopLevelMember({)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+    beginBlock({, BlockKind(invalid))
+      beginTypeArguments(<)
+        handleIdentifier(, typeReference)
+        handleNoTypeArguments([])
+        handleType(, null)
+      endTypeArguments(1, <, >)
+      handleLiteralList(0, [, null, ])
+      handleExpressionStatement(;)
+    endBlock(1, {, }, BlockKind(invalid))
+    handleInvalidTopLevelBlock({)
+    handleInvalidTopLevelDeclaration(})
+  endTopLevelDeclaration()
+  handleErrorToken(UnmatchedToken(())
+  handleErrorToken(UnmatchedToken(<))
+  handleErrorToken(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
new file mode 100644
index 0000000..3c32b06
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.intertwined.expect
@@ -0,0 +1,56 @@
+parseUnit(UnmatchedToken(())
+  skipErrorTokens(UnmatchedToken(())
+  listener: beginCompilationUnit({)
+  syntheticPreviousToken({)
+  parseTopLevelDeclarationImpl(UnmatchedToken({), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken({))
+      listener: beginMetadataStar({)
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember({)
+    parseInvalidTopLevelDeclaration(UnmatchedToken({))
+      reportRecoverableErrorWithToken({, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+      parseInvalidBlock(UnmatchedToken({))
+        parseBlock(UnmatchedToken({), BlockKind(invalid))
+          ensureBlock(UnmatchedToken({), null, null)
+          listener: beginBlock({, BlockKind(invalid))
+          notEofOrValue(}, <)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(<)
+                  parseExpressionStatement({)
+                    parseExpression({)
+                      parsePrecedenceExpression({, 1, true)
+                        parseUnaryExpression({, true)
+                          parsePrimary({, expression)
+                            parseLiteralListSetMapOrFunction({, null)
+                              listener: beginTypeArguments(<)
+                              reportRecoverableErrorWithToken([], Instance of 'Template<(Token) => Message>')
+                              rewriter()
+                              listener: handleIdentifier(, typeReference)
+                              listener: handleNoTypeArguments([])
+                              listener: handleType(, null)
+                              listener: endTypeArguments(1, <, >)
+                              reportRecoverableError(}, Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
+                              rewriter()
+                              parseLiteralListSuffix(>, null)
+                                rewriteSquareBrackets(>)
+                                  link([, ])
+                                  rewriter()
+                                listener: handleLiteralList(0, [, null, ])
+                    ensureSemicolon(])
+                      reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                      rewriter()
+                    listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlock(1, {, }, BlockKind(invalid))
+        listener: handleInvalidTopLevelBlock({)
+      listener: handleInvalidTopLevelDeclaration(})
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(())
+    listener: handleErrorToken(UnmatchedToken(<))
+    listener: handleErrorToken(UnmatchedToken({))
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.parser.expect
new file mode 100644
index 0000000..9d79365
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.parser.expect
@@ -0,0 +1,5 @@
+NOTICE: Stream was rewritten by parser!
+
+{<[]()>[];}
+
+[UnmatchedToken][UnmatchedToken][UnmatchedToken]{[BeginToken]<[BeginToken][SyntheticStringToken][][SimpleToken]([BeginToken])[SyntheticToken]>[SyntheticToken][[SyntheticBeginToken]][SyntheticToken];[SyntheticToken]}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.scanner.expect
new file mode 100644
index 0000000..fc485fe
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.scanner.expect
@@ -0,0 +1,3 @@
+{<[]()>}
+
+[UnmatchedToken][UnmatchedToken][UnmatchedToken]{[BeginToken]<[BeginToken][][SimpleToken]([BeginToken])[SyntheticToken]>[SyntheticToken]}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart
new file mode 100644
index 0000000..e042400
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart
@@ -0,0 +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
new file mode 100644
index 0000000..fdabfa1
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
@@ -0,0 +1,24 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39058_prime.crash:1:1: Expected a declaration, but got '{'.
+{<[]()>}
+^
+
+beginCompilationUnit({)
+  beginMetadataStar({)
+  endMetadataStar(0)
+  beginTopLevelMember({)
+    handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+    beginBlock({, BlockKind(invalid))
+      beginTypeArguments(<)
+        handleIdentifier(, typeReference)
+        handleNoTypeArguments([])
+        handleType(, null)
+      endTypeArguments(1, <, >)
+      handleLiteralList(0, [, null, ])
+      handleExpressionStatement(;)
+    endBlock(1, {, }, BlockKind(invalid))
+    handleInvalidTopLevelBlock({)
+    handleInvalidTopLevelDeclaration(})
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
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
new file mode 100644
index 0000000..41508be
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.intertwined.expect
@@ -0,0 +1,53 @@
+parseUnit({)
+  skipErrorTokens({)
+  listener: beginCompilationUnit({)
+  syntheticPreviousToken({)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar({)
+      listener: endMetadataStar(0)
+    listener: beginTopLevelMember({)
+    parseInvalidTopLevelDeclaration()
+      reportRecoverableErrorWithToken({, Instance of 'Template<(Token) => Message>')
+        listener: handleRecoverableError(Message[ExpectedDeclaration, Expected a declaration, but got '{'., null, {token: {}], {, {)
+      parseInvalidBlock()
+        parseBlock(, BlockKind(invalid))
+          ensureBlock(, null, null)
+          listener: beginBlock({, BlockKind(invalid))
+          notEofOrValue(}, <)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(<)
+                  parseExpressionStatement({)
+                    parseExpression({)
+                      parsePrecedenceExpression({, 1, true)
+                        parseUnaryExpression({, true)
+                          parsePrimary({, expression)
+                            parseLiteralListSetMapOrFunction({, null)
+                              listener: beginTypeArguments(<)
+                              reportRecoverableErrorWithToken([], Instance of 'Template<(Token) => Message>')
+                              rewriter()
+                              listener: handleIdentifier(, typeReference)
+                              listener: handleNoTypeArguments([])
+                              listener: handleType(, null)
+                              listener: endTypeArguments(1, <, >)
+                              reportRecoverableError(}, Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
+                              rewriter()
+                              parseLiteralListSuffix(>, null)
+                                rewriteSquareBrackets(>)
+                                  link([, ])
+                                  rewriter()
+                                listener: handleLiteralList(0, [, null, ])
+                    ensureSemicolon(])
+                      reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                      rewriter()
+                    listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlock(1, {, }, BlockKind(invalid))
+        listener: handleInvalidTopLevelBlock({)
+      listener: handleInvalidTopLevelDeclaration(})
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens({)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.parser.expect
new file mode 100644
index 0000000..211d516
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.parser.expect
@@ -0,0 +1,7 @@
+NOTICE: Stream was rewritten by parser!
+
+{<[]()>[];}
+
+
+{[BeginToken]<[BeginToken][SyntheticStringToken][][SimpleToken]([BeginToken])[SimpleToken]>[SimpleToken][[SyntheticBeginToken]][SyntheticToken];[SyntheticToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.scanner.expect
new file mode 100644
index 0000000..b42881e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.scanner.expect
@@ -0,0 +1,5 @@
+{<[]()>}
+
+
+{[BeginToken]<[BeginToken][][SimpleToken]([BeginToken])[SimpleToken]>[SimpleToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart
new file mode 100644
index 0000000..b8fb0cdb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart
@@ -0,0 +1,3 @@
+main() {
+  {s A<}>
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..e6e34e2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
@@ -0,0 +1,58 @@
+Problems reported:
+
+parser_test/error_recovery/issue_39060:2:6: Expected ';' after this.
+  {s A<}>
+     ^
+
+parser_test/error_recovery/issue_39060:2:8: Expected a type, but got '}'.
+  {s A<}>
+       ^
+
+parser_test/error_recovery/issue_39060:3:1: Expected '[' before this.
+}
+^
+
+parser_test/error_recovery/issue_39060:3:1: Expected ';' after this.
+}
+^
+
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginBlock({, BlockKind(statement))
+          beginMetadataStar(s)
+          endMetadataStar(0)
+          handleIdentifier(s, typeReference)
+          handleNoTypeArguments(A)
+          handleType(s, null)
+          beginVariablesDeclaration(A, null, null)
+            handleIdentifier(A, localVariableDeclaration)
+            beginInitializedIdentifier(A)
+              handleNoVariableInitializer(<)
+            endInitializedIdentifier(A)
+            handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], A, A)
+          endVariablesDeclaration(1, ;)
+          beginTypeArguments(<)
+            handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {token: }}], }, })
+            handleIdentifier(, typeReference)
+            handleNoTypeArguments(})
+            handleType(, null)
+          endTypeArguments(1, <, >)
+          handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], }, })
+          handleLiteralList(0, [, null, ])
+          handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], }, })
+          handleExpressionStatement(;)
+        endBlock(2, {, }, BlockKind(statement))
+      endBlockFunctionBody(1, {, )
+    endTopLevelMethod(main, null, )
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
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
new file mode 100644
index 0000000..5a251df
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.intertwined.expect
@@ -0,0 +1,98 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, {)
+          parseStatement({)
+            parseStatementX({)
+              parseBlock({, BlockKind(statement))
+                ensureBlock({, null, null)
+                listener: beginBlock({, BlockKind(statement))
+                notEofOrValue(}, s)
+                parseStatement({)
+                  parseStatementX({)
+                    parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                      looksLikeLocalFunction(A)
+                      listener: beginMetadataStar(s)
+                      listener: endMetadataStar(0)
+                      listener: handleIdentifier(s, typeReference)
+                      listener: handleNoTypeArguments(A)
+                      listener: handleType(s, null)
+                      listener: beginVariablesDeclaration(A, null, null)
+                      parseVariablesDeclarationRest(s, true)
+                        parseOptionallyInitializedIdentifier(s)
+                          ensureIdentifier(s, localVariableDeclaration)
+                            listener: handleIdentifier(A, localVariableDeclaration)
+                          listener: beginInitializedIdentifier(A)
+                          parseVariableInitializerOpt(A)
+                            listener: handleNoVariableInitializer(<)
+                          listener: endInitializedIdentifier(A)
+                        ensureSemicolon(A)
+                          reportRecoverableError(A, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                            listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], A, A)
+                          rewriter()
+                        listener: endVariablesDeclaration(1, ;)
+                notEofOrValue(}, <)
+                parseStatement(;)
+                  parseStatementX(;)
+                    parseExpressionStatementOrDeclaration(;, false)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(<)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseLiteralListSetMapOrFunction(;, null)
+                                    listener: beginTypeArguments(<)
+                                    reportRecoverableErrorWithToken(}, Instance of 'Template<(Token) => Message>')
+                                      listener: handleRecoverableError(Message[ExpectedType, Expected a type, but got '}'., null, {token: }}], }, })
+                                    rewriter()
+                                    listener: handleIdentifier(, typeReference)
+                                    listener: handleNoTypeArguments(})
+                                    listener: handleType(, null)
+                                    listener: endTypeArguments(1, <, >)
+                                    reportRecoverableError(}, Message[ExpectedButGot, Expected '[' before this., null, {string: [}])
+                                      listener: handleRecoverableError(Message[ExpectedButGot, Expected '[' before this., null, {string: [}], }, })
+                                    rewriter()
+                                    parseLiteralListSuffix(>, null)
+                                      rewriteSquareBrackets(>)
+                                        link([, ])
+                                        rewriter()
+                                      listener: handleLiteralList(0, [, null, ])
+                          ensureSemicolon(])
+                            reportRecoverableError([, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                              listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], }, })
+                            rewriter()
+                          listener: handleExpressionStatement(;)
+                notEofOrValue(}, })
+                listener: endBlock(2, {, }, BlockKind(statement))
+          notEofOrValue(}, )
+          listener: endBlockFunctionBody(1, {, )
+        listener: endTopLevelMethod(main, null, )
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.parser.expect
new file mode 100644
index 0000000..2e5f3d3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.parser.expect
@@ -0,0 +1,9 @@
+NOTICE: Stream was rewritten by parser!
+
+main() {
+{s A;<}>
+[];}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+{[BeginToken]s[StringToken] A[StringToken];[SyntheticToken]<[BeginToken][SyntheticStringToken]}[SimpleToken]>[SimpleToken]
+[[SyntheticBeginToken]][SyntheticToken];[SyntheticToken]}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.scanner.expect
new file mode 100644
index 0000000..1363d86
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.scanner.expect
@@ -0,0 +1,7 @@
+main() {
+{s A<}>
+}
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+{[BeginToken]s[StringToken] A[StringToken]<[BeginToken]}[SimpleToken]>[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
index e58a125..a565916 100644
--- a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
@@ -1,3 +1,9 @@
+Problems reported:
+
+parser_test/extensions/covariant:6:12: Can't have modifier 'covariant' in an extension.
+  addChild(covariant A child) {}
+           ^^^^^^^^^
+
 beginCompilationUnit(class)
   beginMetadataStar(class)
   endMetadataStar(0)
@@ -51,7 +57,7 @@
               beginMetadataStar(covariant)
               endMetadataStar(0)
               handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
-              beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, null, null)
+              beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, covariant, null)
                 handleIdentifier(A, typeReference)
                 handleNoTypeArguments(child)
                 handleType(A, null)
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 ed90d20..25da1aa 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: 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: beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, null, null)
+                      listener: beginFormalParameter(covariant, MemberKind.ExtensionNonStaticMethod, null, covariant, null)
                       listener: handleIdentifier(A, typeReference)
                       listener: handleNoTypeArguments(child)
                       listener: handleType(A, null)
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.parser.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.parser.expect
new file mode 100644
index 0000000..11f5be6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.parser.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+addChild(covariant A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+addChild[StringToken]([BeginToken]covariant[KeywordToken] A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.scanner.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.scanner.expect
new file mode 100644
index 0000000..11f5be6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.scanner.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+addChild(covariant A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+addChild[StringToken]([BeginToken]covariant[KeywordToken] A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/not_covariant.dart.parser.expect b/pkg/front_end/parser_testcases/extensions/not_covariant.dart.parser.expect
new file mode 100644
index 0000000..a1941f2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/not_covariant.dart.parser.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+addChild(A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+addChild[StringToken]([BeginToken]A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/not_covariant.dart.scanner.expect b/pkg/front_end/parser_testcases/extensions/not_covariant.dart.scanner.expect
new file mode 100644
index 0000000..a1941f2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/not_covariant.dart.scanner.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+addChild(A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+addChild[StringToken]([BeginToken]A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/static.dart.parser.expect b/pkg/front_end/parser_testcases/extensions/static.dart.parser.expect
new file mode 100644
index 0000000..1814db5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/static.dart.parser.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+static addChild(A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+static[KeywordToken] addChild[StringToken]([BeginToken]A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/static.dart.scanner.expect b/pkg/front_end/parser_testcases/extensions/static.dart.scanner.expect
new file mode 100644
index 0000000..1814db5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/static.dart.scanner.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+static addChild(A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+static[KeywordToken] addChild[StringToken]([BeginToken]A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
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 434aa58..02f803f 100644
--- a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
@@ -1,3 +1,9 @@
+Problems reported:
+
+parser_test/extensions/static_covariant:6:19: Can't have modifier 'covariant' in an extension.
+  static addChild(covariant A child) {}
+                  ^^^^^^^^^
+
 beginCompilationUnit(class)
   beginMetadataStar(class)
   endMetadataStar(0)
@@ -51,7 +57,7 @@
               beginMetadataStar(covariant)
               endMetadataStar(0)
               handleRecoverableError(Message[ExtraneousModifierInExtension, Can't have modifier 'covariant' in an extension., Try removing 'covariant'., {token: covariant}], covariant, covariant)
-              beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, null, null)
+              beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, covariant, null)
                 handleIdentifier(A, typeReference)
                 handleNoTypeArguments(child)
                 handleType(A, null)
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 260abee..49e3f15 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: 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: beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, null, null)
+                      listener: beginFormalParameter(covariant, MemberKind.ExtensionStaticMethod, null, covariant, null)
                       listener: handleIdentifier(A, typeReference)
                       listener: handleNoTypeArguments(child)
                       listener: handleType(A, null)
diff --git a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.parser.expect b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.parser.expect
new file mode 100644
index 0000000..8c49d7c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.parser.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+static addChild(covariant A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+static[KeywordToken] addChild[StringToken]([BeginToken]covariant[KeywordToken] A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.scanner.expect b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.scanner.expect
new file mode 100644
index 0000000..8c49d7c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.scanner.expect
@@ -0,0 +1,17 @@
+class A {}
+
+class C extends A {}
+
+extension on C {
+static addChild(covariant A child) {}
+}
+
+
+class[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+class[KeywordToken] C[StringToken] extends[KeywordToken] A[StringToken] {[BeginToken]}[SimpleToken]
+
+extension[KeywordToken] on[KeywordToken] C[StringToken] {[BeginToken]
+static[KeywordToken] addChild[StringToken]([BeginToken]covariant[KeywordToken] A[StringToken] child[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for.dart b/pkg/front_end/parser_testcases/general/for.dart
new file mode 100644
index 0000000..ef3828f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for.dart
@@ -0,0 +1,3 @@
+main() {
+  for (int i = 0; i < 10; i++) {}
+}
diff --git a/pkg/front_end/parser_testcases/general/for.dart.expect b/pkg/front_end/parser_testcases/general/for.dart.expect
new file mode 100644
index 0000000..33fd303
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for.dart.expect
@@ -0,0 +1,50 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginForStatement(for)
+          beginMetadataStar(int)
+          endMetadataStar(0)
+          handleIdentifier(int, typeReference)
+          handleNoTypeArguments(i)
+          handleType(int, null)
+          beginVariablesDeclaration(i, null, null)
+            handleIdentifier(i, localVariableDeclaration)
+            beginInitializedIdentifier(i)
+              beginVariableInitializer(=)
+                handleLiteralInt(0)
+              endVariableInitializer(=)
+            endInitializedIdentifier(i)
+          endVariablesDeclaration(1, null)
+          handleForInitializerLocalVariableDeclaration(0, false)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(<)
+          handleNoArguments(<)
+          handleSend(i, <)
+          beginBinaryExpression(<)
+            handleLiteralInt(10)
+          endBinaryExpression(<)
+          handleExpressionStatement(;)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(++)
+          handleNoArguments(++)
+          handleSend(i, ++)
+          handleUnaryPostfixAssignmentExpression(++)
+          handleForLoopParts(for, (, ;, 1)
+          beginForStatementBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForStatementBody(})
+        endForStatement(})
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/for.dart.intertwined.expect
new file mode 100644
index 0000000..871903b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for.dart.intertwined.expect
@@ -0,0 +1,114 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, for)
+          parseStatement({)
+            parseStatementX({)
+              parseForStatement({, null)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(null, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers((, (, null, null, null, true)
+                      listener: beginMetadataStar(int)
+                      listener: endMetadataStar(0)
+                      listener: handleIdentifier(int, typeReference)
+                      listener: handleNoTypeArguments(i)
+                      listener: handleType(int, null)
+                      listener: beginVariablesDeclaration(i, null, null)
+                parseForLoopPartsMid(int, null, for)
+                  parseVariablesDeclarationRest(int, false)
+                    parseOptionallyInitializedIdentifier(int)
+                      ensureIdentifier(int, localVariableDeclaration)
+                        listener: handleIdentifier(i, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(i)
+                      parseVariableInitializerOpt(i)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseLiteralInt(=)
+                                  listener: handleLiteralInt(0)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(i)
+                    listener: endVariablesDeclaration(1, null)
+                  listener: handleForInitializerLocalVariableDeclaration(0, false)
+                parseForRest(null, 0, for)
+                  parseForLoopPartsRest(0, for, null)
+                    ensureSemicolon(0)
+                    parseExpressionStatement(;)
+                      parseExpression(;)
+                        parsePrecedenceExpression(;, 1, true)
+                          parseUnaryExpression(;, true)
+                            parsePrimary(;, expression)
+                              parseSendOrFunctionLiteral(;, expression)
+                                parseSend(;, expression)
+                                  ensureIdentifier(;, expression)
+                                    listener: handleIdentifier(i, expression)
+                                  listener: handleNoTypeArguments(<)
+                                  parseArgumentsOpt(i)
+                                    listener: handleNoArguments(<)
+                                  listener: handleSend(i, <)
+                          listener: beginBinaryExpression(<)
+                          parsePrecedenceExpression(<, 9, true)
+                            parseUnaryExpression(<, true)
+                              parsePrimary(<, expression)
+                                parseLiteralInt(<)
+                                  listener: handleLiteralInt(10)
+                          listener: endBinaryExpression(<)
+                      ensureSemicolon(10)
+                      listener: handleExpressionStatement(;)
+                    parseExpression(;)
+                      parsePrecedenceExpression(;, 1, true)
+                        parseUnaryExpression(;, true)
+                          parsePrimary(;, expression)
+                            parseSendOrFunctionLiteral(;, expression)
+                              parseSend(;, expression)
+                                ensureIdentifier(;, expression)
+                                  listener: handleIdentifier(i, expression)
+                                listener: handleNoTypeArguments(++)
+                                parseArgumentsOpt(i)
+                                  listener: handleNoArguments(++)
+                                listener: handleSend(i, ++)
+                        listener: handleUnaryPostfixAssignmentExpression(++)
+                    listener: handleForLoopParts(for, (, ;, 1)
+                  listener: beginForStatementBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForStatementBody(})
+                  listener: endForStatement(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for.dart.parser.expect b/pkg/front_end/parser_testcases/general/for.dart.parser.expect
new file mode 100644
index 0000000..09de2f5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+for (int i = 0; i < 10; i++) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken]int[StringToken] i[StringToken] =[SimpleToken] 0[StringToken];[SimpleToken] i[StringToken] <[BeginToken] 10[StringToken];[SimpleToken] i[StringToken]++[SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for.dart.scanner.expect b/pkg/front_end/parser_testcases/general/for.dart.scanner.expect
new file mode 100644
index 0000000..09de2f5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+for (int i = 0; i < 10; i++) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken]int[StringToken] i[StringToken] =[SimpleToken] 0[StringToken];[SimpleToken] i[StringToken] <[BeginToken] 10[StringToken];[SimpleToken] i[StringToken]++[SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_in.dart b/pkg/front_end/parser_testcases/general/for_in.dart
new file mode 100644
index 0000000..7825248
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in.dart
@@ -0,0 +1,3 @@
+main() {
+  for (var i in []) {}
+}
diff --git a/pkg/front_end/parser_testcases/general/for_in.dart.expect b/pkg/front_end/parser_testcases/general/for_in.dart.expect
new file mode 100644
index 0000000..b075cf9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in.dart.expect
@@ -0,0 +1,37 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginForStatement(for)
+          beginMetadataStar(var)
+          endMetadataStar(0)
+          handleNoType(var)
+          beginVariablesDeclaration(i, null, var)
+            handleIdentifier(i, localVariableDeclaration)
+            beginInitializedIdentifier(i)
+              handleNoVariableInitializer(in)
+            endInitializedIdentifier(i)
+          endVariablesDeclaration(1, null)
+          handleForInitializerLocalVariableDeclaration(i, true)
+          beginForInExpression([])
+            handleNoTypeArguments([])
+            handleLiteralList(0, [, null, ])
+          endForInExpression())
+          handleForInLoopParts(null, for, (, in)
+          beginForInBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForInBody(})
+        endForIn(})
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_in.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/for_in.dart.intertwined.expect
new file mode 100644
index 0000000..429e01e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in.dart.intertwined.expect
@@ -0,0 +1,82 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, for)
+          parseStatement({)
+            parseStatementX({)
+              parseForStatement({, null)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(null, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers(var, (, null, var, null, true)
+                      listener: beginMetadataStar(var)
+                      listener: endMetadataStar(0)
+                      listener: handleNoType(var)
+                      listener: beginVariablesDeclaration(i, null, var)
+                parseForLoopPartsMid(var, null, for)
+                  parseVariablesDeclarationRest(var, false)
+                    parseOptionallyInitializedIdentifier(var)
+                      ensureIdentifier(var, localVariableDeclaration)
+                        listener: handleIdentifier(i, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(i)
+                      parseVariableInitializerOpt(i)
+                        listener: handleNoVariableInitializer(in)
+                      listener: endInitializedIdentifier(i)
+                    listener: endVariablesDeclaration(1, null)
+                  listener: handleForInitializerLocalVariableDeclaration(i, true)
+                parseForInRest(i, null, for, i)
+                  parseForInLoopPartsRest(i, null, for, i)
+                    listener: beginForInExpression([])
+                    parseExpression(in)
+                      parsePrecedenceExpression(in, 1, true)
+                        parseUnaryExpression(in, true)
+                          parsePrimary(in, expression)
+                            listener: handleNoTypeArguments([])
+                            parseLiteralListSuffix(in, null)
+                              rewriteSquareBrackets(in)
+                                link([, ])
+                                rewriter()
+                              listener: handleLiteralList(0, [, null, ])
+                    ensureCloseParen(], ()
+                    listener: endForInExpression())
+                    listener: handleForInLoopParts(null, for, (, in)
+                  listener: beginForInBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForInBody(})
+                  listener: endForIn(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_in.dart.parser.expect b/pkg/front_end/parser_testcases/general/for_in.dart.parser.expect
new file mode 100644
index 0000000..894374e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+for (var i in []) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken]var[KeywordToken] i[StringToken] in[KeywordToken] [[BeginToken]][SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_in.dart.scanner.expect b/pkg/front_end/parser_testcases/general/for_in.dart.scanner.expect
new file mode 100644
index 0000000..84c367f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+for (var i in []) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+for[KeywordToken] ([BeginToken]var[KeywordToken] i[StringToken] in[KeywordToken] [][SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_in_no_decl.dart b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart
new file mode 100644
index 0000000..179c61d
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart
@@ -0,0 +1,4 @@
+main() {
+  var i;
+  for (i in []) {}
+}
diff --git a/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.expect b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.expect
new file mode 100644
index 0000000..e8e3110
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.expect
@@ -0,0 +1,41 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(var)
+        endMetadataStar(0)
+        handleNoType(var)
+        beginVariablesDeclaration(i, null, var)
+          handleIdentifier(i, localVariableDeclaration)
+          beginInitializedIdentifier(i)
+            handleNoVariableInitializer(;)
+          endInitializedIdentifier(i)
+        endVariablesDeclaration(1, ;)
+        beginForStatement(for)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(in)
+          handleNoArguments(in)
+          handleSend(i, in)
+          handleForInitializerExpressionStatement(i, true)
+          beginForInExpression([])
+            handleNoTypeArguments([])
+            handleLiteralList(0, [, null, ])
+          endForInExpression())
+          handleForInLoopParts(null, for, (, in)
+          beginForInBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForInBody(})
+        endForIn(})
+      endBlockFunctionBody(2, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.intertwined.expect
new file mode 100644
index 0000000..04c39fb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.intertwined.expect
@@ -0,0 +1,100 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, var)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers(var, {, null, var, null, false)
+                looksLikeLocalFunction(i)
+                listener: beginMetadataStar(var)
+                listener: endMetadataStar(0)
+                listener: handleNoType(var)
+                listener: beginVariablesDeclaration(i, null, var)
+                parseVariablesDeclarationRest(var, true)
+                  parseOptionallyInitializedIdentifier(var)
+                    ensureIdentifier(var, localVariableDeclaration)
+                      listener: handleIdentifier(i, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(i)
+                    parseVariableInitializerOpt(i)
+                      listener: handleNoVariableInitializer(;)
+                    listener: endInitializedIdentifier(i)
+                  ensureSemicolon(i)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, for)
+          parseStatement(;)
+            parseStatementX(;)
+              parseForStatement(;, null)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(null, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers((, (, null, null, null, true)
+                parseForLoopPartsMid((, null, for)
+                  parseExpression(()
+                    parsePrecedenceExpression((, 1, true)
+                      parseUnaryExpression((, true)
+                        parsePrimary((, expression)
+                          parseSendOrFunctionLiteral((, expression)
+                            parseSend((, expression)
+                              ensureIdentifier((, expression)
+                                listener: handleIdentifier(i, expression)
+                              listener: handleNoTypeArguments(in)
+                              parseArgumentsOpt(i)
+                                listener: handleNoArguments(in)
+                              listener: handleSend(i, in)
+                  listener: handleForInitializerExpressionStatement(i, true)
+                parseForInRest(i, null, for, i)
+                  parseForInLoopPartsRest(i, null, for, i)
+                    listener: beginForInExpression([])
+                    parseExpression(in)
+                      parsePrecedenceExpression(in, 1, true)
+                        parseUnaryExpression(in, true)
+                          parsePrimary(in, expression)
+                            listener: handleNoTypeArguments([])
+                            parseLiteralListSuffix(in, null)
+                              rewriteSquareBrackets(in)
+                                link([, ])
+                                rewriter()
+                              listener: handleLiteralList(0, [, null, ])
+                    ensureCloseParen(], ()
+                    listener: endForInExpression())
+                    listener: handleForInLoopParts(null, for, (, in)
+                  listener: beginForInBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForInBody(})
+                  listener: endForIn(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(2, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.parser.expect b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.parser.expect
new file mode 100644
index 0000000..b64fd37
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.parser.expect
@@ -0,0 +1,11 @@
+main() {
+var i;
+for (i in []) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] i[StringToken];[SimpleToken]
+for[KeywordToken] ([BeginToken]i[StringToken] in[KeywordToken] [[BeginToken]][SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.scanner.expect b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.scanner.expect
new file mode 100644
index 0000000..15d1094
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_in_no_decl.dart.scanner.expect
@@ -0,0 +1,11 @@
+main() {
+var i;
+for (i in []) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+var[KeywordToken] i[StringToken];[SimpleToken]
+for[KeywordToken] ([BeginToken]i[StringToken] in[KeywordToken] [][SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_no_decl.dart b/pkg/front_end/parser_testcases/general/for_no_decl.dart
new file mode 100644
index 0000000..2f511e9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_no_decl.dart
@@ -0,0 +1,4 @@
+main() {
+  int i;
+  for (i = 0; i < 10; i++) {}
+}
diff --git a/pkg/front_end/parser_testcases/general/for_no_decl.dart.expect b/pkg/front_end/parser_testcases/general/for_no_decl.dart.expect
new file mode 100644
index 0000000..8187b8f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_no_decl.dart.expect
@@ -0,0 +1,54 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        handleIdentifier(int, typeReference)
+        handleNoTypeArguments(i)
+        handleType(int, null)
+        beginVariablesDeclaration(i, null, null)
+          handleIdentifier(i, localVariableDeclaration)
+          beginInitializedIdentifier(i)
+            handleNoVariableInitializer(;)
+          endInitializedIdentifier(i)
+        endVariablesDeclaration(1, ;)
+        beginForStatement(for)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(=)
+          handleNoArguments(=)
+          handleSend(i, =)
+          handleLiteralInt(0)
+          handleAssignmentExpression(=)
+          handleForInitializerExpressionStatement(0, false)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(<)
+          handleNoArguments(<)
+          handleSend(i, <)
+          beginBinaryExpression(<)
+            handleLiteralInt(10)
+          endBinaryExpression(<)
+          handleExpressionStatement(;)
+          handleIdentifier(i, expression)
+          handleNoTypeArguments(++)
+          handleNoArguments(++)
+          handleSend(i, ++)
+          handleUnaryPostfixAssignmentExpression(++)
+          handleForLoopParts(for, (, ;, 1)
+          beginForStatementBody({)
+            beginBlock({, BlockKind(statement))
+            endBlock(0, {, }, BlockKind(statement))
+          endForStatementBody(})
+        endForStatement(})
+      endBlockFunctionBody(2, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_no_decl.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/for_no_decl.dart.intertwined.expect
new file mode 100644
index 0000000..b1cc14f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_no_decl.dart.intertwined.expect
@@ -0,0 +1,131 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, int)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(i)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(int, null)
+                listener: beginVariablesDeclaration(i, null, null)
+                parseVariablesDeclarationRest(int, true)
+                  parseOptionallyInitializedIdentifier(int)
+                    ensureIdentifier(int, localVariableDeclaration)
+                      listener: handleIdentifier(i, localVariableDeclaration)
+                    listener: beginInitializedIdentifier(i)
+                    parseVariableInitializerOpt(i)
+                      listener: handleNoVariableInitializer(;)
+                    listener: endInitializedIdentifier(i)
+                  ensureSemicolon(i)
+                  listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, for)
+          parseStatement(;)
+            parseStatementX(;)
+              parseForStatement(;, null)
+                listener: beginForStatement(for)
+                parseForLoopPartsStart(null, for)
+                  parseExpressionStatementOrDeclaration((, true)
+                    parseExpressionStatementOrDeclarationAfterModifiers((, (, null, null, null, true)
+                parseForLoopPartsMid((, null, for)
+                  parseExpression(()
+                    parsePrecedenceExpression((, 1, true)
+                      parseUnaryExpression((, true)
+                        parsePrimary((, expression)
+                          parseSendOrFunctionLiteral((, expression)
+                            parseSend((, expression)
+                              ensureIdentifier((, expression)
+                                listener: handleIdentifier(i, expression)
+                              listener: handleNoTypeArguments(=)
+                              parseArgumentsOpt(i)
+                                listener: handleNoArguments(=)
+                              listener: handleSend(i, =)
+                      parsePrecedenceExpression(=, 1, true)
+                        parseUnaryExpression(=, true)
+                          parsePrimary(=, expression)
+                            parseLiteralInt(=)
+                              listener: handleLiteralInt(0)
+                      listener: handleAssignmentExpression(=)
+                  listener: handleForInitializerExpressionStatement(0, false)
+                parseForRest(null, 0, for)
+                  parseForLoopPartsRest(0, for, null)
+                    ensureSemicolon(0)
+                    parseExpressionStatement(;)
+                      parseExpression(;)
+                        parsePrecedenceExpression(;, 1, true)
+                          parseUnaryExpression(;, true)
+                            parsePrimary(;, expression)
+                              parseSendOrFunctionLiteral(;, expression)
+                                parseSend(;, expression)
+                                  ensureIdentifier(;, expression)
+                                    listener: handleIdentifier(i, expression)
+                                  listener: handleNoTypeArguments(<)
+                                  parseArgumentsOpt(i)
+                                    listener: handleNoArguments(<)
+                                  listener: handleSend(i, <)
+                          listener: beginBinaryExpression(<)
+                          parsePrecedenceExpression(<, 9, true)
+                            parseUnaryExpression(<, true)
+                              parsePrimary(<, expression)
+                                parseLiteralInt(<)
+                                  listener: handleLiteralInt(10)
+                          listener: endBinaryExpression(<)
+                      ensureSemicolon(10)
+                      listener: handleExpressionStatement(;)
+                    parseExpression(;)
+                      parsePrecedenceExpression(;, 1, true)
+                        parseUnaryExpression(;, true)
+                          parsePrimary(;, expression)
+                            parseSendOrFunctionLiteral(;, expression)
+                              parseSend(;, expression)
+                                ensureIdentifier(;, expression)
+                                  listener: handleIdentifier(i, expression)
+                                listener: handleNoTypeArguments(++)
+                                parseArgumentsOpt(i)
+                                  listener: handleNoArguments(++)
+                                listener: handleSend(i, ++)
+                        listener: handleUnaryPostfixAssignmentExpression(++)
+                    listener: handleForLoopParts(for, (, ;, 1)
+                  listener: beginForStatementBody({)
+                  parseStatement())
+                    parseStatementX())
+                      parseBlock(), BlockKind(statement))
+                        ensureBlock(), null, null)
+                        listener: beginBlock({, BlockKind(statement))
+                        notEofOrValue(}, })
+                        listener: endBlock(0, {, }, BlockKind(statement))
+                  listener: endForStatementBody(})
+                  listener: endForStatement(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(2, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/for_no_decl.dart.parser.expect b/pkg/front_end/parser_testcases/general/for_no_decl.dart.parser.expect
new file mode 100644
index 0000000..f295eb9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_no_decl.dart.parser.expect
@@ -0,0 +1,11 @@
+main() {
+int i;
+for (i = 0; i < 10; i++) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+int[StringToken] i[StringToken];[SimpleToken]
+for[KeywordToken] ([BeginToken]i[StringToken] =[SimpleToken] 0[StringToken];[SimpleToken] i[StringToken] <[BeginToken] 10[StringToken];[SimpleToken] i[StringToken]++[SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/for_no_decl.dart.scanner.expect b/pkg/front_end/parser_testcases/general/for_no_decl.dart.scanner.expect
new file mode 100644
index 0000000..f295eb9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/for_no_decl.dart.scanner.expect
@@ -0,0 +1,11 @@
+main() {
+int i;
+for (i = 0; i < 10; i++) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+int[StringToken] i[StringToken];[SimpleToken]
+for[KeywordToken] ([BeginToken]i[StringToken] =[SimpleToken] 0[StringToken];[SimpleToken] i[StringToken] <[BeginToken] 10[StringToken];[SimpleToken] i[StringToken]++[SimpleToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/function_declaration.dart b/pkg/front_end/parser_testcases/general/function_declaration.dart
new file mode 100644
index 0000000..1c09a5f
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_declaration.dart
@@ -0,0 +1,3 @@
+main() {
+  local() {}
+}
diff --git a/pkg/front_end/parser_testcases/general/function_declaration.dart.expect b/pkg/front_end/parser_testcases/general/function_declaration.dart.expect
new file mode 100644
index 0000000..4b497e8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_declaration.dart.expect
@@ -0,0 +1,31 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(local)
+        endMetadataStar(0)
+        handleNoTypeVariables(()
+        beginLocalFunctionDeclaration(local)
+          handleNoType({)
+          beginFunctionName(local)
+            handleIdentifier(local, localFunctionDeclaration)
+          endFunctionName(local, ()
+          beginFormalParameters((, MemberKind.Local)
+          endFormalParameters(0, (, ), MemberKind.Local)
+          handleNoInitializers()
+          handleAsyncModifier(null, null)
+          beginBlockFunctionBody({)
+          endBlockFunctionBody(0, {, })
+        endLocalFunctionDeclaration(})
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/function_declaration.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/function_declaration.dart.intertwined.expect
new file mode 100644
index 0000000..83e3df0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_declaration.dart.intertwined.expect
@@ -0,0 +1,63 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, local)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                looksLikeLocalFunction(local)
+                listener: beginMetadataStar(local)
+                listener: endMetadataStar(0)
+                listener: handleNoTypeVariables(()
+                listener: beginLocalFunctionDeclaration(local)
+                listener: handleNoType({)
+                parseNamedFunctionRest({, local, local, false)
+                  listener: beginFunctionName(local)
+                  ensureIdentifier({, localFunctionDeclaration)
+                    listener: handleIdentifier(local, localFunctionDeclaration)
+                  listener: endFunctionName(local, ()
+                  parseFormalParametersRequiredOpt(local, MemberKind.Local)
+                    parseFormalParametersRest((, MemberKind.Local)
+                      listener: beginFormalParameters((, MemberKind.Local)
+                      listener: endFormalParameters(0, (, ), MemberKind.Local)
+                  parseInitializersOpt())
+                    listener: handleNoInitializers()
+                  parseAsyncOptBody(), false, false)
+                    parseAsyncModifierOpt())
+                      listener: handleAsyncModifier(null, null)
+                      inPlainSync()
+                    parseFunctionBody(), false, false)
+                      listener: beginBlockFunctionBody({)
+                      notEofOrValue(}, })
+                      listener: endBlockFunctionBody(0, {, })
+                  listener: endLocalFunctionDeclaration(})
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/function_declaration.dart.parser.expect b/pkg/front_end/parser_testcases/general/function_declaration.dart.parser.expect
new file mode 100644
index 0000000..8202677
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_declaration.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+local() {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+local[StringToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/function_declaration.dart.scanner.expect b/pkg/front_end/parser_testcases/general/function_declaration.dart.scanner.expect
new file mode 100644
index 0000000..8202677
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_declaration.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+local() {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+local[StringToken]([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/function_expression.dart b/pkg/front_end/parser_testcases/general/function_expression.dart
new file mode 100644
index 0000000..e043378
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_expression.dart
@@ -0,0 +1,3 @@
+main() {
+  () {};
+}
diff --git a/pkg/front_end/parser_testcases/general/function_expression.dart.expect b/pkg/front_end/parser_testcases/general/function_expression.dart.expect
new file mode 100644
index 0000000..2904ea3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_expression.dart.expect
@@ -0,0 +1,25 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleNoTypeVariables(()
+        beginFunctionExpression(()
+          beginFormalParameters((, MemberKind.Local)
+          endFormalParameters(0, (, ), MemberKind.Local)
+          handleAsyncModifier(null, null)
+          beginBlockFunctionBody({)
+          endBlockFunctionBody(0, {, })
+        endFunctionExpression((, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/function_expression.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/function_expression.dart.intertwined.expect
new file mode 100644
index 0000000..57d0bf4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_expression.dart.intertwined.expect
@@ -0,0 +1,63 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, ()
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(()
+                  parseExpressionStatement({)
+                    parseExpression({)
+                      parsePrecedenceExpression({, 1, true)
+                        parseUnaryExpression({, true)
+                          parsePrimary({, expression)
+                            parseParenthesizedExpressionOrFunctionLiteral({)
+                              listener: handleNoTypeVariables(()
+                              parseFunctionExpression({)
+                                listener: beginFunctionExpression(()
+                                parseFormalParametersRequiredOpt({, MemberKind.Local)
+                                  parseFormalParametersRest((, MemberKind.Local)
+                                    listener: beginFormalParameters((, MemberKind.Local)
+                                    listener: endFormalParameters(0, (, ), MemberKind.Local)
+                                parseAsyncOptBody(), true, false)
+                                  parseAsyncModifierOpt())
+                                    listener: handleAsyncModifier(null, null)
+                                    inPlainSync()
+                                  parseFunctionBody(), true, false)
+                                    listener: beginBlockFunctionBody({)
+                                    notEofOrValue(}, })
+                                    listener: endBlockFunctionBody(0, {, })
+                                listener: endFunctionExpression((, ;)
+                    ensureSemicolon(})
+                    listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/function_expression.dart.parser.expect b/pkg/front_end/parser_testcases/general/function_expression.dart.parser.expect
new file mode 100644
index 0000000..5aab062
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_expression.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+() {};
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/function_expression.dart.scanner.expect b/pkg/front_end/parser_testcases/general/function_expression.dart.scanner.expect
new file mode 100644
index 0000000..5aab062
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/function_expression.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+() {};
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+([BeginToken])[SimpleToken] {[BeginToken]}[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart
new file mode 100644
index 0000000..e99259c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart
@@ -0,0 +1,2 @@
+main() {
+  print("Hello, World!");
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
new file mode 100644
index 0000000..076e320
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.expect
@@ -0,0 +1,25 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(UnmatchedToken({), null)
+      handleNoType(UnmatchedToken({))
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        handleIdentifier(print, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+          beginLiteralString("Hello, World!")
+          endLiteralString(0, ))
+        endArguments(1, (, ))
+        handleSend(print, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+  handleErrorToken(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
new file mode 100644
index 0000000..6d5f4a8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.intertwined.expect
@@ -0,0 +1,66 @@
+parseUnit(UnmatchedToken({))
+  skipErrorTokens(UnmatchedToken({))
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(UnmatchedToken({), Instance of 'DirectiveContext')
+    parseMetadataStar(UnmatchedToken({))
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl(UnmatchedToken({))
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(UnmatchedToken({), null, UnmatchedToken({), Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(UnmatchedToken({), null)
+        listener: handleNoType(UnmatchedToken({))
+        ensureIdentifier(UnmatchedToken({), topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), 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)
+                                            parseLiteralString(()
+                                              parseSingleLiteralString(()
+                                                listener: beginLiteralString("Hello, World!")
+                                                listener: endLiteralString(0, ))
+                                    listener: endArguments(1, (, ))
+                              listener: handleSend(print, ;)
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(UnmatchedToken({))
+    listener: handleErrorToken(UnmatchedToken({))
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.parser.expect b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.parser.expect
new file mode 100644
index 0000000..69bcffa
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.parser.expect
@@ -0,0 +1,7 @@
+main() {
+print("Hello, World!");
+}
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"Hello, World!"[StringToken])[SimpleToken];[SimpleToken]
+}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.scanner.expect b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.scanner.expect
new file mode 100644
index 0000000..69bcffa
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/missing_end_bracket.dart.scanner.expect
@@ -0,0 +1,7 @@
+main() {
+print("Hello, World!");
+}
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"Hello, World!"[StringToken])[SimpleToken];[SimpleToken]
+}[SyntheticToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart
new file mode 100644
index 0000000..31587fb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart
@@ -0,0 +1,3 @@
+class operator {
+  operator^(int x) {}
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..c341804
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
@@ -0,0 +1,48 @@
+Problems reported:
+
+parser_test/general/operator_hat_class.crash:1:7: Can't use 'operator' as a name here.
+class operator {
+      ^^^^^^^^
+
+beginCompilationUnit(class)
+  beginMetadataStar(class)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(class)
+    handleRecoverableError(Message[BuiltInIdentifierInDeclaration, Can't use 'operator' as a name here., null, {token: operator}], operator, operator)
+    handleIdentifier(operator, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(class, null, operator)
+      handleNoType(operator)
+      handleClassExtends(null)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(class, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(operator)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, operator)
+            handleNoType({)
+            handleOperatorName(operator, ^)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+            endBlockFunctionBody(0, {, })
+          endClassConstructor(null, operator, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+    endClassDeclaration(class, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
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
new file mode 100644
index 0000000..51dc180
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.intertwined.expect
@@ -0,0 +1,78 @@
+parseUnit(class)
+  skipErrorTokens(class)
+  listener: beginCompilationUnit(class)
+  syntheticPreviousToken(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)
+          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: handleIdentifier(operator, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(class, null, operator)
+        parseClass(operator, class, class, operator)
+          parseClassHeaderOpt(operator, class, class)
+            parseClassExtendsOpt(operator)
+              listener: handleNoType(operator)
+              listener: handleClassExtends(null)
+            parseWithClauseOpt(operator)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(operator)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(class, class, null)
+          parseClassOrMixinOrExtensionBody(operator, DeclarationKind.Class, operator)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, operator)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, operator)
+              parseMetadataStar({)
+                listener: beginMetadataStar(operator)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, {, Instance of 'NoType', null, operator, DeclarationKind.Class, operator)
+                listener: beginMethod(null, null, null, null, null, operator)
+                listener: handleNoType({)
+                parseOperatorName({)
+                  listener: handleOperatorName(operator, ^)
+                parseMethodTypeVar(^)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(^, operator, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(^, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(0, {, })
+                listener: endClassConstructor(null, operator, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+          listener: endClassDeclaration(class, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(class)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.parser.expect b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.parser.expect
new file mode 100644
index 0000000..eb9727b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.parser.expect
@@ -0,0 +1,7 @@
+class operator {
+operator^(int x) {}
+}
+
+class[KeywordToken] operator[KeywordToken] {[BeginToken]
+operator[KeywordToken]^[SimpleToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.scanner.expect
new file mode 100644
index 0000000..eb9727b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.scanner.expect
@@ -0,0 +1,7 @@
+class operator {
+operator^(int x) {}
+}
+
+class[KeywordToken] operator[KeywordToken] {[BeginToken]
+operator[KeywordToken]^[SimpleToken]([BeginToken]int[StringToken] x[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/try_catch.dart b/pkg/front_end/parser_testcases/general/try_catch.dart
new file mode 100644
index 0000000..be5f4c2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_catch.dart
@@ -0,0 +1,3 @@
+main() {
+  try {} catch (e, s) {}
+}
diff --git a/pkg/front_end/parser_testcases/general/try_catch.dart.expect b/pkg/front_end/parser_testcases/general/try_catch.dart.expect
new file mode 100644
index 0000000..ce7a345
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_catch.dart.expect
@@ -0,0 +1,41 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginTryStatement(try)
+          beginBlock({, BlockKind(try statement))
+          endBlock(0, {, }, BlockKind(try statement))
+          beginCatchClause(catch)
+            beginFormalParameters((, MemberKind.Catch)
+              beginMetadataStar(e)
+              endMetadataStar(0)
+              beginFormalParameter(e, MemberKind.Catch, null, null, null)
+                handleNoType(()
+                handleIdentifier(e, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, e, null, null, FormalParameterKind.mandatory, MemberKind.Catch)
+              beginMetadataStar(s)
+              endMetadataStar(0)
+              beginFormalParameter(s, MemberKind.Catch, null, null, null)
+                handleNoType(,)
+                handleIdentifier(s, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, s, null, null, FormalParameterKind.mandatory, MemberKind.Catch)
+            endFormalParameters(2, (, ), MemberKind.Catch)
+          endCatchClause({)
+          beginBlock({, BlockKind(catch clause))
+          endBlock(0, {, }, BlockKind(catch clause))
+          handleCatchBlock(null, catch, ,)
+        endTryStatement(1, try, null)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/try_catch.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/try_catch.dart.intertwined.expect
new file mode 100644
index 0000000..3c5e427
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_catch.dart.intertwined.expect
@@ -0,0 +1,76 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, try)
+          parseStatement({)
+            parseStatementX({)
+              parseTryStatement({)
+                listener: beginTryStatement(try)
+                parseBlock(try, BlockKind(try statement))
+                  ensureBlock(try, null, try statement)
+                  listener: beginBlock({, BlockKind(try statement))
+                  notEofOrValue(}, })
+                  listener: endBlock(0, {, }, BlockKind(try statement))
+                listener: beginCatchClause(catch)
+                parseFormalParameters(catch, MemberKind.Catch)
+                  parseFormalParametersRest((, MemberKind.Catch)
+                    listener: beginFormalParameters((, MemberKind.Catch)
+                    parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.Catch)
+                      parseMetadataStar(()
+                        listener: beginMetadataStar(e)
+                        listener: endMetadataStar(0)
+                      listener: beginFormalParameter(e, MemberKind.Catch, null, null, null)
+                      listener: handleNoType(()
+                      ensureIdentifier((, formalParameterDeclaration)
+                        listener: handleIdentifier(e, formalParameterDeclaration)
+                      listener: handleFormalParameterWithoutValue(,)
+                      listener: endFormalParameter(null, null, e, null, null, FormalParameterKind.mandatory, MemberKind.Catch)
+                    parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.Catch)
+                      parseMetadataStar(,)
+                        listener: beginMetadataStar(s)
+                        listener: endMetadataStar(0)
+                      listener: beginFormalParameter(s, MemberKind.Catch, null, null, null)
+                      listener: handleNoType(,)
+                      ensureIdentifier(,, formalParameterDeclaration)
+                        listener: handleIdentifier(s, formalParameterDeclaration)
+                      listener: handleFormalParameterWithoutValue())
+                      listener: endFormalParameter(null, null, s, null, null, FormalParameterKind.mandatory, MemberKind.Catch)
+                    listener: endFormalParameters(2, (, ), MemberKind.Catch)
+                listener: endCatchClause({)
+                parseBlock(), BlockKind(catch clause))
+                  ensureBlock(), null, catch clause)
+                  listener: beginBlock({, BlockKind(catch clause))
+                  notEofOrValue(}, })
+                  listener: endBlock(0, {, }, BlockKind(catch clause))
+                listener: handleCatchBlock(null, catch, ,)
+                listener: endTryStatement(1, try, null)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/try_catch.dart.parser.expect b/pkg/front_end/parser_testcases/general/try_catch.dart.parser.expect
new file mode 100644
index 0000000..54e4666
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_catch.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+try {} catch (e, s) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+try[KeywordToken] {[BeginToken]}[SimpleToken] catch[KeywordToken] ([BeginToken]e[StringToken],[SimpleToken] s[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/try_catch.dart.scanner.expect b/pkg/front_end/parser_testcases/general/try_catch.dart.scanner.expect
new file mode 100644
index 0000000..54e4666
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_catch.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+try {} catch (e, s) {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+try[KeywordToken] {[BeginToken]}[SimpleToken] catch[KeywordToken] ([BeginToken]e[StringToken],[SimpleToken] s[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/try_finally.dart b/pkg/front_end/parser_testcases/general/try_finally.dart
new file mode 100644
index 0000000..88cf981
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_finally.dart
@@ -0,0 +1,3 @@
+main() {
+  try {} finally {}
+}
diff --git a/pkg/front_end/parser_testcases/general/try_finally.dart.expect b/pkg/front_end/parser_testcases/general/try_finally.dart.expect
new file mode 100644
index 0000000..8f0f03e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_finally.dart.expect
@@ -0,0 +1,23 @@
+beginCompilationUnit(main)
+  beginMetadataStar(main)
+  endMetadataStar(0)
+  beginTopLevelMember(main)
+    beginTopLevelMethod(, null)
+      handleNoType()
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginTryStatement(try)
+          beginBlock({, BlockKind(try statement))
+          endBlock(0, {, }, BlockKind(try statement))
+          beginBlock({, BlockKind(finally clause))
+          endBlock(0, {, }, BlockKind(finally clause))
+          handleFinallyBlock(finally)
+        endTryStatement(0, try, finally)
+      endBlockFunctionBody(1, {, })
+    endTopLevelMethod(main, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/try_finally.dart.intertwined.expect b/pkg/front_end/parser_testcases/general/try_finally.dart.intertwined.expect
new file mode 100644
index 0000000..be97a74
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_finally.dart.intertwined.expect
@@ -0,0 +1,50 @@
+parseUnit(main)
+  skipErrorTokens(main)
+  listener: beginCompilationUnit(main)
+  syntheticPreviousToken(main)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(main)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(main)
+      parseTopLevelMethod(, null, , Instance of 'NoType', null, main)
+        listener: beginTopLevelMethod(, null)
+        listener: handleNoType()
+        ensureIdentifier(, topLevelFunctionDeclaration)
+          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)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, try)
+          parseStatement({)
+            parseStatementX({)
+              parseTryStatement({)
+                listener: beginTryStatement(try)
+                parseBlock(try, BlockKind(try statement))
+                  ensureBlock(try, null, try statement)
+                  listener: beginBlock({, BlockKind(try statement))
+                  notEofOrValue(}, })
+                  listener: endBlock(0, {, }, BlockKind(try statement))
+                parseBlock(finally, BlockKind(finally clause))
+                  ensureBlock(finally, null, finally clause)
+                  listener: beginBlock({, BlockKind(finally clause))
+                  notEofOrValue(}, })
+                  listener: endBlock(0, {, }, BlockKind(finally clause))
+                listener: handleFinallyBlock(finally)
+                listener: endTryStatement(0, try, finally)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(1, {, })
+        listener: endTopLevelMethod(main, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(main)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/general/try_finally.dart.parser.expect b/pkg/front_end/parser_testcases/general/try_finally.dart.parser.expect
new file mode 100644
index 0000000..f02cdb8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_finally.dart.parser.expect
@@ -0,0 +1,9 @@
+main() {
+try {} finally {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+try[KeywordToken] {[BeginToken]}[SimpleToken] finally[KeywordToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/general/try_finally.dart.scanner.expect b/pkg/front_end/parser_testcases/general/try_finally.dart.scanner.expect
new file mode 100644
index 0000000..f02cdb8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/general/try_finally.dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+try {} finally {}
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+try[KeywordToken] {[BeginToken]}[SimpleToken] finally[KeywordToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/late_member.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/late_member.dart.parser.expect
new file mode 100644
index 0000000..7f5671b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/late_member.dart.parser.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.late;
+late();
+bar();
+new X().late();
+new Y().late;
+}
+
+late() {
+print("hello");
+}
+
+class X {
+late() {
+print("hello");
+}
+}
+
+class Y {
+int late = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] late[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/late_member.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/late_member.dart.scanner.expect
new file mode 100644
index 0000000..7f5671b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/late_member.dart.scanner.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.late;
+late();
+bar();
+new X().late();
+new Y().late;
+}
+
+late() {
+print("hello");
+}
+
+class X {
+late() {
+print("hello");
+}
+}
+
+class Y {
+int late = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] late[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.parser.expect
new file mode 100644
index 0000000..5dc83d6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.parser.expect
@@ -0,0 +1,55 @@
+main() {
+dynamic foo = new X();
+var bar = foo.late;
+late();
+bar();
+new X().late();
+new Y().late;
+
+
+late int foo;
+foo = 42;
+}
+
+late() {
+print("hello");
+}
+
+class X {
+late() {
+print("hello");
+}
+}
+
+class Y {
+int late = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+
+
+late[KeywordToken] int[StringToken] foo[StringToken];[SimpleToken]
+foo[StringToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] late[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.scanner.expect
new file mode 100644
index 0000000..5dc83d6
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/late_modifier.dart.scanner.expect
@@ -0,0 +1,55 @@
+main() {
+dynamic foo = new X();
+var bar = foo.late;
+late();
+bar();
+new X().late();
+new Y().late;
+
+
+late int foo;
+foo = 42;
+}
+
+late() {
+print("hello");
+}
+
+class X {
+late() {
+print("hello");
+}
+}
+
+class Y {
+int late = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]late[KeywordToken];[SimpleToken]
+
+
+late[KeywordToken] int[StringToken] foo[StringToken];[SimpleToken]
+foo[StringToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+late[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] late[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.parser.expect
new file mode 100644
index 0000000..61773e4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { foo.bar!.baz[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken].[SimpleToken]baz[StringToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.scanner.expect
new file mode 100644
index 0000000..61773e4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { foo.bar!.baz[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken].[SimpleToken]baz[StringToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.parser.expect
new file mode 100644
index 0000000..57f0f75
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { (foo.bar)!.baz[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken])[SimpleToken]![SimpleToken].[SimpleToken]baz[StringToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..57f0f75
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckBeforeIndex_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { (foo.bar)!.baz[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken])[SimpleToken]![SimpleToken].[SimpleToken]baz[StringToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.parser.expect
new file mode 100644
index 0000000..1d08481
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { obj![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] obj[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.scanner.expect
new file mode 100644
index 0000000..1d08481
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { obj![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] obj[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.parser.expect
new file mode 100644
index 0000000..e4eca21
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { obj![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] obj[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.scanner.expect
new file mode 100644
index 0000000..e4eca21
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { obj![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] obj[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.parser.expect
new file mode 100644
index 0000000..0becf96
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { (((obj!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]obj[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..0becf96
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex2_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { (((obj!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]obj[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.parser.expect
new file mode 100644
index 0000000..ed4a028
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { foo.bar![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.scanner.expect
new file mode 100644
index 0000000..ed4a028
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { foo.bar![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.parser.expect
new file mode 100644
index 0000000..dda7f8b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { (foo.bar)![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken])[SimpleToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..dda7f8b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex3_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { (foo.bar)![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken])[SimpleToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.parser.expect
new file mode 100644
index 0000000..6669daf
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { foo!.bar![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken]![SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.scanner.expect
new file mode 100644
index 0000000..6669daf
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { foo!.bar![arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken]![SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.parser.expect
new file mode 100644
index 0000000..8b9708e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { ((foo!).bar!)[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]foo[StringToken]![SimpleToken])[SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..8b9708e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex4_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { ((foo!).bar!)[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]foo[StringToken]![SimpleToken])[SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.parser.expect
new file mode 100644
index 0000000..df49626
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { foo.bar![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.scanner.expect
new file mode 100644
index 0000000..df49626
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { foo.bar![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.parser.expect
new file mode 100644
index 0000000..4457d0b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { (((foo.bar!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..4457d0b
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex5_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { (((foo.bar!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]foo[StringToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.parser.expect
new file mode 100644
index 0000000..21aa146
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { foo!.bar![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken]![SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.scanner.expect
new file mode 100644
index 0000000..21aa146
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { foo!.bar![arg]![arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] foo[StringToken]![SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken][[BeginToken]arg[StringToken]][SimpleToken]![SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.parser.expect
new file mode 100644
index 0000000..43ecf59
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { ((((foo!).bar!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]([BeginToken]foo[StringToken]![SimpleToken])[SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..43ecf59
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex6_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { ((((foo!).bar!)[arg])!)[arg2]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]([BeginToken]([BeginToken]([BeginToken]foo[StringToken]![SimpleToken])[SimpleToken].[SimpleToken]bar[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken])[SimpleToken]![SimpleToken])[SimpleToken][[BeginToken]arg2[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.parser.expect
new file mode 100644
index 0000000..70bbc26
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.parser.expect
@@ -0,0 +1,3 @@
+f() { (obj!)[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]obj[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.scanner.expect
new file mode 100644
index 0000000..70bbc26
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/nullCheckOnIndex_with_parens.dart.scanner.expect
@@ -0,0 +1,3 @@
+f() { (obj!)[arg]; }
+
+f[StringToken]([BeginToken])[SimpleToken] {[BeginToken] ([BeginToken]obj[StringToken]![SimpleToken])[SimpleToken][[BeginToken]arg[StringToken]][SimpleToken];[SimpleToken] }[SimpleToken][SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/required_member.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/required_member.dart.parser.expect
new file mode 100644
index 0000000..de0ccfb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/required_member.dart.parser.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.required;
+required();
+bar();
+new X().required();
+new Y().required;
+}
+
+required() {
+print("hello");
+}
+
+class X {
+required() {
+print("hello");
+}
+}
+
+class Y {
+int required = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] required[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/required_member.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/required_member.dart.scanner.expect
new file mode 100644
index 0000000..de0ccfb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/required_member.dart.scanner.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.required;
+required();
+bar();
+new X().required();
+new Y().required;
+}
+
+required() {
+print("hello");
+}
+
+class X {
+required() {
+print("hello");
+}
+}
+
+class Y {
+int required = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] required[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.parser.expect
new file mode 100644
index 0000000..9f492cb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.parser.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.required;
+required();
+bar();
+new X().required();
+new Y().required;
+}
+
+required({required int named}) {
+print("hello");
+}
+
+class X {
+required() {
+print("hello");
+}
+}
+
+class Y {
+int required = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+required[KeywordToken]([BeginToken]{[BeginToken]required[KeywordToken] int[StringToken] named[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] required[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.scanner.expect
new file mode 100644
index 0000000..9f492cb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/required_modifier.dart.scanner.expect
@@ -0,0 +1,47 @@
+main() {
+dynamic foo = new X();
+var bar = foo.required;
+required();
+bar();
+new X().required();
+new Y().required;
+}
+
+required({required int named}) {
+print("hello");
+}
+
+class X {
+required() {
+print("hello");
+}
+}
+
+class Y {
+int required = 42;
+}
+
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+dynamic[KeywordToken] foo[StringToken] =[SimpleToken] new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+var[KeywordToken] bar[StringToken] =[SimpleToken] foo[StringToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+bar[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] X[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken]([BeginToken])[SimpleToken];[SimpleToken]
+new[KeywordToken] Y[StringToken]([BeginToken])[SimpleToken].[SimpleToken]required[KeywordToken];[SimpleToken]
+}[SimpleToken]
+
+required[KeywordToken]([BeginToken]{[BeginToken]required[KeywordToken] int[StringToken] named[StringToken]}[SimpleToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] X[StringToken] {[BeginToken]
+required[KeywordToken]([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+
+class[KeywordToken] Y[StringToken] {[BeginToken]
+int[StringToken] required[KeywordToken] =[SimpleToken] 42[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 1272291..c326659 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,18 +1,19 @@
 name: front_end
 # Currently, front_end API is not stable and users should not
 # depend on semver semantics when depending on this package.
-version: 0.1.28
+version: 0.1.29
 author: Dart Team <misc@dartlang.org>
 description: Front end for compilation of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
 environment:
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
-  kernel: 0.3.27
+  _fe_analyzer_shared: 1.0.0
+  kernel: 0.3.29
   package_config: '^1.1.0'
   meta: ^1.0.2
 dev_dependencies:
-  analyzer: 0.38.5
+  analyzer: 0.39.1
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
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 f587774..bda78e9 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
@@ -10,7 +10,7 @@
 
 import 'package:kernel/kernel.dart' show Component;
 
-import '../incremental_load_from_dill_test.dart' show normalCompileToBytes;
+import '../incremental_load_from_dill_suite.dart' show normalCompileToBytes;
 
 main() async {
   List<int> bytes = await normalCompileToBytes(
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 5f30b25..706d0a6 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
@@ -4,11 +4,11 @@
 
 import 'dart:io' show File, Platform;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show DiagnosticMessage;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 import 'package:kernel/kernel.dart'
     show Class, Component, ConstantExpression, Field, IntConstant, Library;
 
@@ -16,7 +16,7 @@
 
 import 'binary_md_dill_reader.dart' show BinaryMdDillReader;
 
-import 'incremental_load_from_dill_test.dart'
+import 'incremental_load_from_dill_suite.dart'
     show getOptions, normalCompileToComponent;
 
 import 'utils/io_utils.dart' show computeRepoDir;
diff --git a/pkg/front_end/test/constants/constant_test.dart b/pkg/front_end/test/constants/constant_test.dart
index 6bba0a7..02958df 100644
--- a/pkg/front_end/test/constants/constant_test.dart
+++ b/pkg/front_end/test/constants/constant_test.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart'
+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;
-import 'package:front_end/src/testing/id_testing.dart';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart'
     show
         CfeDataExtractor,
@@ -22,7 +22,8 @@
 import 'package:kernel/ast.dart';
 
 main(List<String> args) async {
-  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
+  Directory dataDir = new Directory.fromUri(Platform.script
+      .resolve('../../../_fe_analyzer_shared/test/constants/data'));
   await runTests(dataDir,
       args: args,
       supportedMarkers: sharedMarkers,
diff --git a/pkg/front_end/test/deps_test.dart b/pkg/front_end/test/deps_test.dart
index 4d9bf2f..f92a759 100644
--- a/pkg/front_end/test/deps_test.dart
+++ b/pkg/front_end/test/deps_test.dart
@@ -1,12 +1,12 @@
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart';
 import 'package:expect/expect.dart' show Expect;
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/base/processed_options.dart';
 import 'package:front_end/src/fasta/compiler_context.dart';
 import 'package:front_end/src/fasta/dill/dill_target.dart';
 import 'package:front_end/src/fasta/kernel/kernel_target.dart';
-import 'package:front_end/src/fasta/severity.dart';
 import 'package:front_end/src/fasta/ticker.dart';
 import 'package:front_end/src/fasta/uri_translator.dart';
 import 'package:kernel/kernel.dart';
@@ -75,8 +75,10 @@
   Set<Uri> otherNonDartUris = new Set<Uri>();
   Set<Uri> frontEndUris = new Set<Uri>();
   Set<Uri> kernelUris = new Set<Uri>();
+  Set<Uri> feAnalyzerSharedUris = new Set<Uri>();
   Set<Uri> dartPlatformUris = new Set<Uri>();
   Uri kernelUri = repoDir.resolve("pkg/kernel/");
+  Uri feAnalyzerSharedUri = repoDir.resolve("pkg/_fe_analyzer_shared/");
   Uri platformUri1 = repoDir.resolve("sdk/lib/");
   Uri platformUri2 = repoDir.resolve("runtime/lib/");
   Uri platformUri3 = repoDir.resolve("runtime/bin/");
@@ -85,6 +87,8 @@
       frontEndUris.add(uri);
     } else if (uri.toString().startsWith(kernelUri.toString())) {
       kernelUris.add(uri);
+    } else if (uri.toString().startsWith(feAnalyzerSharedUri.toString())) {
+      feAnalyzerSharedUris.add(uri);
     } else if (uri.toString().startsWith(platformUri1.toString()) ||
         uri.toString().startsWith(platformUri2.toString()) ||
         uri.toString().startsWith(platformUri3.toString())) {
diff --git a/pkg/front_end/test/dill_round_trip_test.dart b/pkg/front_end/test/dill_round_trip_test.dart
index 424a3b1..a04c5e1 100644
--- a/pkg/front_end/test/dill_round_trip_test.dart
+++ b/pkg/front_end/test/dill_round_trip_test.dart
@@ -10,7 +10,7 @@
 
 import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;
 
-import 'incremental_load_from_dill_test.dart'
+import 'incremental_load_from_dill_suite.dart'
     show checkIsEqual, getOptions, normalCompilePlain;
 
 main() async {
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_test.dart
index cbedba9..89766bd 100644
--- a/pkg/front_end/test/explicit_creation_test.dart
+++ b/pkg/front_end/test/explicit_creation_test.dart
@@ -4,6 +4,8 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart' as api;
 import 'package:front_end/src/api_prototype/file_system.dart' as api;
 import 'package:front_end/src/base/processed_options.dart';
@@ -22,7 +24,6 @@
 import 'package:front_end/src/fasta/kernel/body_builder.dart';
 import 'package:front_end/src/fasta/kernel/constness.dart';
 import 'package:front_end/src/fasta/kernel/kernel_target.dart';
-import 'package:front_end/src/fasta/severity.dart';
 import 'package:front_end/src/fasta/scope.dart';
 import 'package:front_end/src/fasta/source/diet_listener.dart';
 import 'package:front_end/src/fasta/source/source_library_builder.dart';
@@ -32,7 +33,6 @@
 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
 import 'package:front_end/src/fasta/uri_translator.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
diff --git a/pkg/front_end/test/extensions/data/export_twice/lib1.dart b/pkg/front_end/test/extensions/data/export_twice/lib1.dart
new file mode 100644
index 0000000..4539cd4
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/export_twice/lib1.dart
@@ -0,0 +1,32 @@
+// 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.
+
+/*library: scope=[E]*/
+
+class A {}
+
+/*class: E:
+ builder-name=E,
+ builder-onType=A,
+ extension-members=[
+  foo=E|foo,
+  tearoff foo=E|get#foo],
+ extension-name=E,extension-onType=A
+*/
+extension E on A {
+  /*member: E|foo:
+   builder-name=foo,
+   builder-params=[#this],
+   member-name=E|foo,
+   member-params=[#this]
+  */
+  foo() {}
+
+  /*member: E|get#foo:
+   builder-name=foo,
+   builder-params=[#this],
+   member-name=E|get#foo,
+   member-params=[#this]
+  */
+}
diff --git a/pkg/front_end/test/extensions/data/export_twice/lib2.dart b/pkg/front_end/test/extensions/data/export_twice/lib2.dart
new file mode 100644
index 0000000..fee7eac
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/export_twice/lib2.dart
@@ -0,0 +1,5 @@
+// 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.
+
+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
new file mode 100644
index 0000000..1abeb48
--- /dev/null
+++ b/pkg/front_end/test/extensions/data/export_twice/main.dart
@@ -0,0 +1,12 @@
+// 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.
+
+/*library: scope=[lib1.dart.E]*/
+
+import 'lib1.dart';
+import 'lib2.dart';
+
+main() {
+  A().foo();
+}
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index d64295f..6f022ff 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -3,8 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
     show ExperimentalFlag;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 
 import 'package:front_end/src/fasta/builder/class_builder.dart';
 import 'package:front_end/src/fasta/builder/extension_builder.dart';
@@ -15,11 +19,7 @@
 import 'package:front_end/src/fasta/builder/type_builder.dart';
 import 'package:front_end/src/fasta/builder/type_variable_builder.dart';
 
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
 import 'package:front_end/src/testing/features.dart';
-import 'package:front_end/src/testing/id_testing.dart'
-    show DataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/fasta/ambiguous_export_test.dart b/pkg/front_end/test/fasta/ambiguous_export_test.dart
index b7f09ee..b3f49c0 100644
--- a/pkg/front_end/test/fasta/ambiguous_export_test.dart
+++ b/pkg/front_end/test/fasta/ambiguous_export_test.dart
@@ -32,7 +32,8 @@
       DillLibraryBuilder builder = target.loader.read(library.importUri, -1);
       await target.loader.buildOutline(builder);
       builder.markAsReadyToFinalizeExports();
-      var mainExport = builder.exportScope.local["main"];
+      var mainExport =
+          builder.exportScope.lookupLocalMember("main", setter: false);
       Expect.isTrue(mainExport is InvalidTypeDeclarationBuilder);
     });
   });
diff --git a/pkg/front_end/test/fasta/expression_suite.dart b/pkg/front_end/test/fasta/expression_suite.dart
new file mode 100644
index 0000000..87a0834
--- /dev/null
+++ b/pkg/front_end/test/fasta/expression_suite.dart
@@ -0,0 +1,438 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE.md file.
+
+library fasta.test.expression_test;
+
+import "dart:async" show Future;
+
+import "dart:convert" show JsonEncoder;
+
+import "dart:io" show File, IOSink;
+
+import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
+
+import "package:front_end/src/api_prototype/compiler_options.dart"
+    show CompilerOptions, DiagnosticMessage;
+
+import "package:front_end/src/api_prototype/memory_file_system.dart"
+    show MemoryFileSystem;
+
+import "package:front_end/src/api_prototype/terminal_color_support.dart"
+    show printDiagnosticMessage;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+import 'package:front_end/src/external_state_snapshot.dart'
+    show ExternalStateSnapshot;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
+import "package:kernel/ast.dart"
+    show Procedure, Component, DynamicType, DartType, TypeParameter;
+
+import 'package:kernel/target/targets.dart' show TargetFlags;
+
+import 'package:kernel/text/ast_to_text.dart' show Printer;
+
+import "package:testing/src/log.dart" show splitLines;
+
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import 'package:vm/target/vm.dart' show VmTarget;
+
+import "package:yaml/yaml.dart" show YamlMap, YamlList, loadYamlNode;
+
+import '../../lib/src/fasta/kernel/utils.dart'
+    show writeComponentToFile, serializeProcedure;
+
+import '../utils/kernel_chain.dart' show runDiff, openWrite;
+
+const JsonEncoder json = const JsonEncoder.withIndent("  ");
+
+class Context extends ChainContext {
+  final CompilerContext compilerContext;
+  final ExternalStateSnapshot snapshot;
+  final List<DiagnosticMessage> errors;
+
+  final List<Step> steps;
+
+  Context(
+      this.compilerContext, this.snapshot, this.errors, bool updateExpectations)
+      : steps = <Step>[
+          const ReadTest(),
+          const CompileExpression(),
+          new MatchProcedureExpectations(".expect",
+              updateExpectations: updateExpectations)
+        ];
+
+  ProcessedOptions get options => compilerContext.options;
+
+  MemoryFileSystem get fileSystem => options.fileSystem;
+
+  Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
+    return compilerContext.runInContext<T>(action);
+  }
+
+  void reset() {
+    errors.clear();
+    snapshot.restore();
+  }
+
+  List<DiagnosticMessage> takeErrors() {
+    List<DiagnosticMessage> result = new List<DiagnosticMessage>.from(errors);
+    errors.clear();
+    return result;
+  }
+}
+
+class CompilationResult {
+  Procedure compiledProcedure;
+  List<DiagnosticMessage> errors;
+  CompilationResult(this.compiledProcedure, this.errors);
+
+  String printResult(Uri entryPoint, Context context) {
+    StringBuffer buffer = new StringBuffer();
+    buffer.write("Errors: {\n");
+    for (var error in errors) {
+      for (String message in error.plainTextFormatted) {
+        for (String line in splitLines(message)) {
+          buffer.write("  ");
+          buffer.write(line);
+        }
+        buffer.write("\n");
+        // TODO(jensj): Ignore context for now.
+        // Remove once we have positions on type parameters.
+        break;
+      }
+    }
+    buffer.write("}\n");
+    if (compiledProcedure == null) {
+      buffer.write("<no procedure>");
+    } else {
+      new Printer(buffer).visitProcedure(compiledProcedure);
+    }
+    Uri base = entryPoint.resolve(".");
+    return "$buffer".replaceAll("$base", "org-dartlang-testcase:///");
+  }
+}
+
+class TestCase {
+  final TestDescription description;
+
+  final Uri entryPoint;
+
+  final Uri import;
+
+  final List<String> definitions;
+
+  final List<String> typeDefinitions;
+
+  final bool isStaticMethod;
+
+  final Uri library;
+
+  final String className;
+
+  String expression;
+
+  List<CompilationResult> results = [];
+
+  TestCase(
+      this.description,
+      this.entryPoint,
+      this.import,
+      this.definitions,
+      this.typeDefinitions,
+      this.isStaticMethod,
+      this.library,
+      this.className,
+      this.expression);
+
+  String toString() {
+    return "TestCase("
+        "$entryPoint, "
+        "$import, "
+        "$definitions, "
+        "$typeDefinitions,"
+        "$library, "
+        "$className, "
+        "static = $isStaticMethod)";
+  }
+
+  String validate() {
+    print(this);
+    if (entryPoint == null) {
+      return "No entryPoint.";
+    }
+    if (!(new File.fromUri(entryPoint)).existsSync()) {
+      return "Entry point $entryPoint doesn't exist.";
+    }
+    if (library == null) {
+      return "No enclosing node.";
+    }
+    if (expression == null) {
+      return "No expression to compile.";
+    }
+    return null;
+  }
+}
+
+class MatchProcedureExpectations extends Step<List<TestCase>, Null, Context> {
+  final String suffix;
+  final bool updateExpectations;
+
+  const MatchProcedureExpectations(this.suffix,
+      {this.updateExpectations: false});
+
+  String get name => "match expectations";
+
+  Future<Result<Null>> run(List<TestCase> tests, Context context) async {
+    String actual = "";
+    for (var test in tests) {
+      var primary = test.results.first.printResult(test.entryPoint, context);
+      actual += primary;
+      for (int i = 1; i < test.results.length; ++i) {
+        var secondary = test.results[i].printResult(test.entryPoint, context);
+        if (primary != secondary) {
+          return fail(
+              null,
+              "Multiple expectations don't match on $test:"
+              "\nFirst expectation:\n$actual\n"
+              "\nSecond expectation:\n$secondary\n");
+        }
+      }
+    }
+    var test = tests.first;
+    Uri testUri = test.description.uri;
+    File expectedFile = new File("${testUri.toFilePath()}$suffix");
+    if (await expectedFile.exists()) {
+      String expected = await expectedFile.readAsString();
+      if (expected.trim() != actual.trim()) {
+        if (!updateExpectations) {
+          String diff = await runDiff(expectedFile.uri, actual);
+          return fail(
+              null, "$testUri doesn't match ${expectedFile.uri}\n$diff");
+        }
+      } else {
+        return pass(null);
+      }
+    }
+    if (updateExpectations) {
+      await openWrite(expectedFile.uri, (IOSink sink) {
+        sink.writeln(actual.trim());
+      });
+      return pass(null);
+    } else {
+      return fail(null, """
+Please create file ${expectedFile.path} with this content:
+$actual""");
+    }
+  }
+}
+
+class ReadTest extends Step<TestDescription, List<TestCase>, Context> {
+  const ReadTest();
+
+  String get name => "read test";
+
+  Future<Result<List<TestCase>>> run(
+      TestDescription description, Context context) async {
+    context.reset();
+    Uri uri = description.uri;
+    String contents = await new File.fromUri(uri).readAsString();
+
+    Uri entryPoint;
+    Uri import;
+    List<String> definitions = <String>[];
+    List<String> typeDefinitions = <String>[];
+    bool isStaticMethod = false;
+    Uri library;
+    String className;
+    String expression;
+
+    dynamic maps = loadYamlNode(contents, sourceUrl: uri);
+    if (maps is YamlMap) maps = [maps];
+
+    final List<TestCase> tests = [];
+    for (YamlMap map in maps) {
+      for (var _key in map.keys) {
+        String key = _key;
+        var value = map[key];
+
+        if (key == "entry_point") {
+          entryPoint = description.uri.resolveUri(Uri.parse(value as String));
+        } else if (key == "import") {
+          import = description.uri.resolveUri(Uri.parse(value as String));
+        } else if (key == "position") {
+          Uri uri = description.uri.resolveUri(Uri.parse(value as String));
+          library = uri.removeFragment();
+          if (uri.fragment != null && uri.fragment != '') {
+            className = uri.fragment;
+          }
+        } else if (key == "definitions") {
+          definitions = (value as YamlList).map((x) => x as String).toList();
+        } else if (key == "type_definitions") {
+          typeDefinitions =
+              (value as YamlList).map((x) => x as String).toList();
+        } else if (key == "static") {
+          isStaticMethod = value;
+        } else if (key == "expression") {
+          expression = value;
+        }
+      }
+      var test = new TestCase(description, entryPoint, import, definitions,
+          typeDefinitions, isStaticMethod, library, className, expression);
+      var result = test.validate();
+      if (result != null) {
+        return new Result.fail(tests, result);
+      }
+      tests.add(test);
+    }
+    return new Result.pass(tests);
+  }
+}
+
+class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
+  const CompileExpression();
+
+  String get name => "compile expression";
+
+  // Compile [test.expression], update [test.errors] with results.
+  // As a side effect - verify that generated procedure can be serialized.
+  void compileExpression(TestCase test, IncrementalCompiler compiler,
+      Component component, Context context) async {
+    Map<String, DartType> definitions = {};
+    for (String name in test.definitions) {
+      definitions[name] = new DynamicType();
+    }
+    List<TypeParameter> typeParams = [];
+    for (String name in test.typeDefinitions) {
+      typeParams.add(new TypeParameter(name, new DynamicType()));
+    }
+
+    Procedure compiledProcedure = await compiler.compileExpression(
+        test.expression,
+        definitions,
+        typeParams,
+        "debugExpr",
+        test.library,
+        test.className,
+        test.isStaticMethod);
+    List<DiagnosticMessage> errors = context.takeErrors();
+    test.results.add(new CompilationResult(compiledProcedure, errors));
+    if (compiledProcedure != null) {
+      // Confirm we can serialize generated procedure.
+      component.computeCanonicalNames();
+      List<int> list = serializeProcedure(compiledProcedure);
+      assert(list.length > 0);
+    }
+  }
+
+  Future<Result<List<TestCase>>> run(
+      List<TestCase> tests, Context context) async {
+    for (var test in tests) {
+      context.fileSystem.entityForUri(test.entryPoint).writeAsBytesSync(
+          await new File.fromUri(test.entryPoint).readAsBytes());
+
+      if (test.import != null) {
+        context.fileSystem.entityForUri(test.import).writeAsBytesSync(
+            await new File.fromUri(test.import).readAsBytes());
+      }
+
+      var sourceCompiler = new IncrementalCompiler(context.compilerContext);
+      Component component =
+          await sourceCompiler.computeDelta(entryPoints: [test.entryPoint]);
+      var errors = context.takeErrors();
+      if (!errors.isEmpty) {
+        return fail(tests, "Couldn't compile entry-point: $errors");
+      }
+      Uri dillFileUri = new Uri(
+          scheme: test.entryPoint.scheme, path: test.entryPoint.path + ".dill");
+      File dillFile = new File.fromUri(dillFileUri);
+      if (!await dillFile.exists()) {
+        await writeComponentToFile(component, dillFileUri);
+        context.fileSystem.entityForUri(dillFileUri).writeAsBytesSync(
+            await new File.fromUri(dillFileUri).readAsBytes());
+      }
+      compileExpression(test, sourceCompiler, component, context);
+
+      var dillCompiler =
+          new IncrementalCompiler(context.compilerContext, dillFileUri);
+      component =
+          await dillCompiler.computeDelta(entryPoints: [test.entryPoint]);
+      component.computeCanonicalNames();
+      await dillFile.delete();
+
+      errors = context.takeErrors();
+      // Since it compiled successfully from source, the bootstrap-from-Dill
+      // should also succeed without errors.
+      assert(errors.isEmpty);
+      compileExpression(test, dillCompiler, component, context);
+    }
+    return new Result.pass(tests);
+  }
+}
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  final Uri base = Uri.parse("org-dartlang-test:///");
+
+  /// Unused because we supply entry points to [computeDelta] directly above.
+  final Uri entryPoint = base.resolve("nothing.dart");
+
+  /// The custom URI used to locate the dill file in the MemoryFileSystem.
+  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+
+  /// The actual location of the dill file.
+  final Uri sdkSummaryFile =
+      computePlatformBinariesLocation(forceBuildDir: true)
+          .resolve("vm_platform_strong.dill");
+
+  final MemoryFileSystem fs = new MemoryFileSystem(base);
+
+  fs
+      .entityForUri(sdkSummary)
+      .writeAsBytesSync(await new File.fromUri(sdkSummaryFile).readAsBytes());
+
+  final List<DiagnosticMessage> errors = <DiagnosticMessage>[];
+
+  final CompilerOptions optionBuilder = new CompilerOptions()
+    ..target = new VmTarget(new TargetFlags())
+    ..verbose = true
+    ..omitPlatform = true
+    ..fileSystem = fs
+    ..sdkSummary = sdkSummary
+    ..onDiagnostic = (DiagnosticMessage message) {
+      printDiagnosticMessage(message, print);
+      errors.add(message);
+    }
+    ..environmentDefines = const {};
+
+  final ProcessedOptions options =
+      new ProcessedOptions(options: optionBuilder, inputs: [entryPoint]);
+
+  final ExternalStateSnapshot snapshot =
+      new ExternalStateSnapshot(await options.loadSdkSummary(null));
+
+  final bool updateExpectations = environment["updateExpectations"] == "true";
+
+  final CompilerContext compilerContext = new CompilerContext(options);
+
+  // Disable colors to ensure that expectation files are the same across
+  // platforms and independent of stdin/stderr.
+  colors.enableColors = false;
+
+  return new Context(compilerContext, snapshot, errors, updateExpectations);
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/expression_test.dart b/pkg/front_end/test/fasta/expression_test.dart
deleted file mode 100644
index 8366fcb..0000000
--- a/pkg/front_end/test/fasta/expression_test.dart
+++ /dev/null
@@ -1,436 +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.md file.
-
-library fasta.test.incremental_test;
-
-import "dart:async" show Future;
-
-import "dart:convert" show JsonEncoder;
-
-import "dart:io" show File, IOSink;
-
-import "package:front_end/src/api_prototype/compiler_options.dart"
-    show CompilerOptions, DiagnosticMessage;
-
-import "package:front_end/src/api_prototype/memory_file_system.dart"
-    show MemoryFileSystem;
-
-import "package:front_end/src/api_prototype/terminal_color_support.dart"
-    show printDiagnosticMessage;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-
-import 'package:front_end/src/external_state_snapshot.dart'
-    show ExternalStateSnapshot;
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/incremental_compiler.dart'
-    show IncrementalCompiler;
-
-import "package:kernel/ast.dart"
-    show Procedure, Component, DynamicType, DartType, TypeParameter;
-
-import 'package:kernel/target/targets.dart' show TargetFlags;
-
-import 'package:kernel/text/ast_to_text.dart' show Printer;
-
-import "package:testing/src/log.dart" show splitLines;
-
-import "package:testing/testing.dart"
-    show Chain, ChainContext, Result, Step, TestDescription, runMe;
-
-import 'package:vm/target/vm.dart' show VmTarget;
-
-import "package:yaml/yaml.dart" show YamlMap, YamlList, loadYamlNode;
-
-import '../../lib/src/fasta/kernel/utils.dart'
-    show writeComponentToFile, serializeProcedure;
-
-import '../utils/kernel_chain.dart' show runDiff, openWrite;
-
-const JsonEncoder json = const JsonEncoder.withIndent("  ");
-
-class Context extends ChainContext {
-  final CompilerContext compilerContext;
-  final ExternalStateSnapshot snapshot;
-  final List<DiagnosticMessage> errors;
-
-  final List<Step> steps;
-
-  Context(
-      this.compilerContext, this.snapshot, this.errors, bool updateExpectations)
-      : steps = <Step>[
-          const ReadTest(),
-          const CompileExpression(),
-          new MatchProcedureExpectations(".expect",
-              updateExpectations: updateExpectations)
-        ];
-
-  ProcessedOptions get options => compilerContext.options;
-
-  MemoryFileSystem get fileSystem => options.fileSystem;
-
-  Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
-    return compilerContext.runInContext<T>(action);
-  }
-
-  void reset() {
-    errors.clear();
-    snapshot.restore();
-  }
-
-  List<DiagnosticMessage> takeErrors() {
-    List<DiagnosticMessage> result = new List<DiagnosticMessage>.from(errors);
-    errors.clear();
-    return result;
-  }
-}
-
-class CompilationResult {
-  Procedure compiledProcedure;
-  List<DiagnosticMessage> errors;
-  CompilationResult(this.compiledProcedure, this.errors);
-
-  String printResult(Uri entryPoint, Context context) {
-    StringBuffer buffer = new StringBuffer();
-    buffer.write("Errors: {\n");
-    for (var error in errors) {
-      for (String message in error.plainTextFormatted) {
-        for (String line in splitLines(message)) {
-          buffer.write("  ");
-          buffer.write(line);
-        }
-        buffer.write("\n");
-        // TODO(jensj): Ignore context for now.
-        // Remove once we have positions on type parameters.
-        break;
-      }
-    }
-    buffer.write("}\n");
-    if (compiledProcedure == null) {
-      buffer.write("<no procedure>");
-    } else {
-      new Printer(buffer).visitProcedure(compiledProcedure);
-    }
-    Uri base = entryPoint.resolve(".");
-    return "$buffer".replaceAll("$base", "org-dartlang-testcase:///");
-  }
-}
-
-class TestCase {
-  final TestDescription description;
-
-  final Uri entryPoint;
-
-  final Uri import;
-
-  final List<String> definitions;
-
-  final List<String> typeDefinitions;
-
-  final bool isStaticMethod;
-
-  final Uri library;
-
-  final String className;
-
-  String expression;
-
-  List<CompilationResult> results = [];
-
-  TestCase(
-      this.description,
-      this.entryPoint,
-      this.import,
-      this.definitions,
-      this.typeDefinitions,
-      this.isStaticMethod,
-      this.library,
-      this.className,
-      this.expression);
-
-  String toString() {
-    return "TestCase("
-        "$entryPoint, "
-        "$import, "
-        "$definitions, "
-        "$typeDefinitions,"
-        "$library, "
-        "$className, "
-        "static = $isStaticMethod)";
-  }
-
-  String validate() {
-    print(this);
-    if (entryPoint == null) {
-      return "No entryPoint.";
-    }
-    if (!(new File.fromUri(entryPoint)).existsSync()) {
-      return "Entry point $entryPoint doesn't exist.";
-    }
-    if (library == null) {
-      return "No enclosing node.";
-    }
-    if (expression == null) {
-      return "No expression to compile.";
-    }
-    return null;
-  }
-}
-
-class MatchProcedureExpectations extends Step<List<TestCase>, Null, Context> {
-  final String suffix;
-  final bool updateExpectations;
-
-  const MatchProcedureExpectations(this.suffix,
-      {this.updateExpectations: false});
-
-  String get name => "match expectations";
-
-  Future<Result<Null>> run(List<TestCase> tests, Context context) async {
-    String actual = "";
-    for (var test in tests) {
-      var primary = test.results.first.printResult(test.entryPoint, context);
-      actual += primary;
-      for (int i = 1; i < test.results.length; ++i) {
-        var secondary = test.results[i].printResult(test.entryPoint, context);
-        if (primary != secondary) {
-          return fail(
-              null,
-              "Multiple expectations don't match on $test:"
-              "\nFirst expectation:\n$actual\n"
-              "\nSecond expectation:\n$secondary\n");
-        }
-      }
-    }
-    var test = tests.first;
-    Uri testUri = test.description.uri;
-    File expectedFile = new File("${testUri.toFilePath()}$suffix");
-    if (await expectedFile.exists()) {
-      String expected = await expectedFile.readAsString();
-      if (expected.trim() != actual.trim()) {
-        if (!updateExpectations) {
-          String diff = await runDiff(expectedFile.uri, actual);
-          return fail(
-              null, "$testUri doesn't match ${expectedFile.uri}\n$diff");
-        }
-      } else {
-        return pass(null);
-      }
-    }
-    if (updateExpectations) {
-      await openWrite(expectedFile.uri, (IOSink sink) {
-        sink.writeln(actual.trim());
-      });
-      return pass(null);
-    } else {
-      return fail(null, """
-Please create file ${expectedFile.path} with this content:
-$actual""");
-    }
-  }
-}
-
-class ReadTest extends Step<TestDescription, List<TestCase>, Context> {
-  const ReadTest();
-
-  String get name => "read test";
-
-  Future<Result<List<TestCase>>> run(
-      TestDescription description, Context context) async {
-    context.reset();
-    Uri uri = description.uri;
-    String contents = await new File.fromUri(uri).readAsString();
-
-    Uri entryPoint;
-    Uri import;
-    List<String> definitions = <String>[];
-    List<String> typeDefinitions = <String>[];
-    bool isStaticMethod = false;
-    Uri library;
-    String className;
-    String expression;
-
-    dynamic maps = loadYamlNode(contents, sourceUrl: uri);
-    if (maps is YamlMap) maps = [maps];
-
-    final List<TestCase> tests = [];
-    for (YamlMap map in maps) {
-      for (var _key in map.keys) {
-        String key = _key;
-        var value = map[key];
-
-        if (key == "entry_point") {
-          entryPoint = description.uri.resolveUri(Uri.parse(value as String));
-        } else if (key == "import") {
-          import = description.uri.resolveUri(Uri.parse(value as String));
-        } else if (key == "position") {
-          Uri uri = description.uri.resolveUri(Uri.parse(value as String));
-          library = uri.removeFragment();
-          if (uri.fragment != null && uri.fragment != '') {
-            className = uri.fragment;
-          }
-        } else if (key == "definitions") {
-          definitions = (value as YamlList).map((x) => x as String).toList();
-        } else if (key == "type_definitions") {
-          typeDefinitions =
-              (value as YamlList).map((x) => x as String).toList();
-        } else if (key == "static") {
-          isStaticMethod = value;
-        } else if (key == "expression") {
-          expression = value;
-        }
-      }
-      var test = new TestCase(description, entryPoint, import, definitions,
-          typeDefinitions, isStaticMethod, library, className, expression);
-      var result = test.validate();
-      if (result != null) {
-        return new Result.fail(tests, result);
-      }
-      tests.add(test);
-    }
-    return new Result.pass(tests);
-  }
-}
-
-class CompileExpression extends Step<List<TestCase>, List<TestCase>, Context> {
-  const CompileExpression();
-
-  String get name => "compile expression";
-
-  // Compile [test.expression], update [test.errors] with results.
-  // As a side effect - verify that generated procedure can be serialized.
-  void compileExpression(TestCase test, IncrementalCompiler compiler,
-      Component component, Context context) async {
-    Map<String, DartType> definitions = {};
-    for (String name in test.definitions) {
-      definitions[name] = new DynamicType();
-    }
-    List<TypeParameter> typeParams = [];
-    for (String name in test.typeDefinitions) {
-      typeParams.add(new TypeParameter(name, new DynamicType()));
-    }
-
-    Procedure compiledProcedure = await compiler.compileExpression(
-        test.expression,
-        definitions,
-        typeParams,
-        "debugExpr",
-        test.library,
-        test.className,
-        test.isStaticMethod);
-    List<DiagnosticMessage> errors = context.takeErrors();
-    test.results.add(new CompilationResult(compiledProcedure, errors));
-    if (compiledProcedure != null) {
-      // Confirm we can serialize generated procedure.
-      component.computeCanonicalNames();
-      List<int> list = serializeProcedure(compiledProcedure);
-      assert(list.length > 0);
-    }
-  }
-
-  Future<Result<List<TestCase>>> run(
-      List<TestCase> tests, Context context) async {
-    for (var test in tests) {
-      context.fileSystem.entityForUri(test.entryPoint).writeAsBytesSync(
-          await new File.fromUri(test.entryPoint).readAsBytes());
-
-      if (test.import != null) {
-        context.fileSystem.entityForUri(test.import).writeAsBytesSync(
-            await new File.fromUri(test.import).readAsBytes());
-      }
-
-      var sourceCompiler = new IncrementalCompiler(context.compilerContext);
-      Component component =
-          await sourceCompiler.computeDelta(entryPoints: [test.entryPoint]);
-      var errors = context.takeErrors();
-      if (!errors.isEmpty) {
-        return fail(tests, "Couldn't compile entry-point: $errors");
-      }
-      Uri dillFileUri = new Uri(
-          scheme: test.entryPoint.scheme, path: test.entryPoint.path + ".dill");
-      File dillFile = new File.fromUri(dillFileUri);
-      if (!await dillFile.exists()) {
-        await writeComponentToFile(component, dillFileUri);
-        context.fileSystem.entityForUri(dillFileUri).writeAsBytesSync(
-            await new File.fromUri(dillFileUri).readAsBytes());
-      }
-      compileExpression(test, sourceCompiler, component, context);
-
-      var dillCompiler =
-          new IncrementalCompiler(context.compilerContext, dillFileUri);
-      component =
-          await dillCompiler.computeDelta(entryPoints: [test.entryPoint]);
-      component.computeCanonicalNames();
-      await dillFile.delete();
-
-      errors = context.takeErrors();
-      // Since it compiled successfully from source, the bootstrap-from-Dill
-      // should also succeed without errors.
-      assert(errors.isEmpty);
-      compileExpression(test, dillCompiler, component, context);
-    }
-    return new Result.pass(tests);
-  }
-}
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  final Uri base = Uri.parse("org-dartlang-test:///");
-
-  /// Unused because we supply entry points to [computeDelta] directly above.
-  final Uri entryPoint = base.resolve("nothing.dart");
-
-  /// The custom URI used to locate the dill file in the MemoryFileSystem.
-  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
-
-  /// The actual location of the dill file.
-  final Uri sdkSummaryFile =
-      computePlatformBinariesLocation(forceBuildDir: true)
-          .resolve("vm_platform_strong.dill");
-
-  final MemoryFileSystem fs = new MemoryFileSystem(base);
-
-  fs
-      .entityForUri(sdkSummary)
-      .writeAsBytesSync(await new File.fromUri(sdkSummaryFile).readAsBytes());
-
-  final List<DiagnosticMessage> errors = <DiagnosticMessage>[];
-
-  final CompilerOptions optionBuilder = new CompilerOptions()
-    ..target = new VmTarget(new TargetFlags())
-    ..verbose = true
-    ..omitPlatform = true
-    ..fileSystem = fs
-    ..sdkSummary = sdkSummary
-    ..onDiagnostic = (DiagnosticMessage message) {
-      printDiagnosticMessage(message, print);
-      errors.add(message);
-    }
-    ..environmentDefines = const {};
-
-  final ProcessedOptions options =
-      new ProcessedOptions(options: optionBuilder, inputs: [entryPoint]);
-
-  final ExternalStateSnapshot snapshot =
-      new ExternalStateSnapshot(await options.loadSdkSummary(null));
-
-  final bool updateExpectations = environment["updateExpectations"] == "true";
-
-  final CompilerContext compilerContext = new CompilerContext(options);
-
-  // Disable colors to ensure that expectation files are the same across
-  // platforms and independent of stdin/stderr.
-  compilerContext.disableColors();
-
-  return new Context(compilerContext, snapshot, errors, updateExpectations);
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/fast_strong_test.dart b/pkg/front_end/test/fasta/fast_strong_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/fast_strong_test.dart
rename to pkg/front_end/test/fasta/fast_strong_suite.dart
diff --git a/pkg/front_end/test/fasta/flow_analysis/assigned_variables_test.dart b/pkg/front_end/test/fasta/flow_analysis/assigned_variables_test.dart
deleted file mode 100644
index f3f9b1d..0000000
--- a/pkg/front_end/test/fasta/flow_analysis/assigned_variables_test.dart
+++ /dev/null
@@ -1,202 +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:front_end/src/fasta/flow_analysis/flow_analysis.dart';
-import 'package:test/test.dart';
-
-main() {
-  test('capturedAnywhere records assignments in closures', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    var v2 = _Variable('v2');
-    var v3 = _Variable('v3');
-    assignedVariables.declare(v1);
-    assignedVariables.declare(v2);
-    assignedVariables.declare(v3);
-    assignedVariables.write(v1);
-    assignedVariables.beginNode();
-    assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    assignedVariables.write(v3);
-    assignedVariables.finish();
-    expect(assignedVariables.capturedAnywhere, {v2});
-  });
-
-  test('capturedAnywhere does not record variables local to a closure', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    var v2 = _Variable('v2');
-    assignedVariables.declare(v1);
-    assignedVariables.beginNode();
-    assignedVariables.declare(v2);
-    assignedVariables.write(v1);
-    assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    assignedVariables.finish();
-    expect(assignedVariables.capturedAnywhere, {v1});
-  });
-
-  test('writtenAnywhere records all assignments', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    var v2 = _Variable('v2');
-    var v3 = _Variable('v3');
-    assignedVariables.declare(v1);
-    assignedVariables.declare(v2);
-    assignedVariables.declare(v3);
-    assignedVariables.write(v1);
-    assignedVariables.beginNode();
-    assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    assignedVariables.write(v3);
-    assignedVariables.finish();
-    expect(assignedVariables.writtenAnywhere, {v1, v2, v3});
-  });
-
-  test('writtenInNode ignores assignments outside the node', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    var v2 = _Variable('v2');
-    assignedVariables.declare(v1);
-    assignedVariables.declare(v2);
-    assignedVariables.write(v1);
-    assignedVariables.beginNode();
-    var node = _Node();
-    assignedVariables.endNode(node);
-    assignedVariables.write(v2);
-    assignedVariables.finish();
-    expect(assignedVariables.writtenInNode(node), isEmpty);
-  });
-
-  test('writtenInNode records assignments inside the node', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    assignedVariables.declare(v1);
-    assignedVariables.beginNode();
-    assignedVariables.write(v1);
-    var node = _Node();
-    assignedVariables.endNode(node);
-    assignedVariables.finish();
-    expect(assignedVariables.writtenInNode(node), {v1});
-  });
-
-  test('writtenInNode records assignments in a nested node', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    assignedVariables.declare(v1);
-    assignedVariables.beginNode();
-    assignedVariables.beginNode();
-    assignedVariables.write(v1);
-    assignedVariables.endNode(_Node());
-    var node = _Node();
-    assignedVariables.endNode(node);
-    assignedVariables.finish();
-    expect(assignedVariables.writtenInNode(node), {v1});
-  });
-
-  test('writtenInNode records assignments in a closure', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    assignedVariables.declare(v1);
-    assignedVariables.beginNode();
-    assignedVariables.write(v1);
-    var node = _Node();
-    assignedVariables.endNode(node, isClosure: true);
-    assignedVariables.finish();
-    expect(assignedVariables.writtenInNode(node), {v1});
-  });
-
-  test('capturedInNode ignores assignments in non-nested closures', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    var v2 = _Variable('v2');
-    assignedVariables.declare(v1);
-    assignedVariables.declare(v2);
-    assignedVariables.beginNode();
-    assignedVariables.write(v1);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    assignedVariables.beginNode();
-    var node = _Node();
-    assignedVariables.endNode(node);
-    assignedVariables.beginNode();
-    assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    assignedVariables.finish();
-    expect(assignedVariables.capturedInNode(node), isEmpty);
-  });
-
-  test('capturedInNode records assignments in nested closures', () {
-    var assignedVariables = AssignedVariables<_Node, _Variable>();
-    var v1 = _Variable('v1');
-    assignedVariables.declare(v1);
-    assignedVariables.beginNode();
-    assignedVariables.beginNode();
-    assignedVariables.write(v1);
-    assignedVariables.endNode(_Node(), isClosure: true);
-    var node = _Node();
-    assignedVariables.endNode(node);
-    assignedVariables.finish();
-    expect(assignedVariables.capturedInNode(node), {v1});
-  });
-
-  group('Variables do not percolate beyond the scope they were declared in',
-      () {
-    test('Non-closure scope', () {
-      var assignedVariables = AssignedVariables<_Node, _Variable>();
-      var v1 = _Variable('v1');
-      var v2 = _Variable('v2');
-      assignedVariables.beginNode();
-      assignedVariables.beginNode();
-      assignedVariables.declare(v1);
-      assignedVariables.declare(v2);
-      assignedVariables.write(v1);
-      assignedVariables.beginNode();
-      assignedVariables.write(v2);
-      assignedVariables.endNode(_Node(), isClosure: true);
-      var innerNode = _Node();
-      assignedVariables.endNode(innerNode, isClosure: false);
-      var outerNode = _Node();
-      assignedVariables.endNode(outerNode);
-      assignedVariables.finish();
-      expect(assignedVariables.writtenInNode(innerNode), isEmpty);
-      expect(assignedVariables.capturedInNode(innerNode), isEmpty);
-      expect(assignedVariables.writtenInNode(outerNode), isEmpty);
-      expect(assignedVariables.capturedInNode(outerNode), isEmpty);
-    });
-
-    test('Closure scope', () {
-      var assignedVariables = AssignedVariables<_Node, _Variable>();
-      var v1 = _Variable('v1');
-      var v2 = _Variable('v2');
-      assignedVariables.beginNode();
-      assignedVariables.beginNode();
-      assignedVariables.declare(v1);
-      assignedVariables.declare(v2);
-      assignedVariables.write(v1);
-      assignedVariables.beginNode();
-      assignedVariables.write(v2);
-      assignedVariables.endNode(_Node(), isClosure: true);
-      var innerNode = _Node();
-      assignedVariables.endNode(innerNode, isClosure: true);
-      var outerNode = _Node();
-      assignedVariables.endNode(outerNode);
-      assignedVariables.finish();
-      expect(assignedVariables.writtenInNode(innerNode), isEmpty);
-      expect(assignedVariables.capturedInNode(innerNode), isEmpty);
-      expect(assignedVariables.writtenInNode(outerNode), isEmpty);
-      expect(assignedVariables.capturedInNode(outerNode), isEmpty);
-    });
-  });
-}
-
-class _Node {}
-
-class _Variable {
-  final String name;
-
-  _Variable(this.name);
-
-  @override
-  String toString() => name;
-}
diff --git a/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart b/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
deleted file mode 100644
index 3e3b6cc..0000000
--- a/pkg/front_end/test/fasta/flow_analysis/flow_analysis_test.dart
+++ /dev/null
@@ -1,2085 +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:front_end/src/fasta/flow_analysis/flow_analysis.dart';
-import 'package:meta/meta.dart';
-import 'package:test/test.dart';
-
-main() {
-  group('API', () {
-    test('conditional_thenBegin promotes true branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.conditional_thenBegin(h.notNull(x)());
-        expect(flow.promotedType(x).type, 'int');
-        flow.conditional_elseBegin(_Expression());
-        expect(flow.promotedType(x), isNull);
-        flow.conditional_end(_Expression(), _Expression());
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('conditional_elseBegin promotes false branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.conditional_thenBegin(h.eqNull(x)());
-        expect(flow.promotedType(x), isNull);
-        flow.conditional_elseBegin(_Expression());
-        expect(flow.promotedType(x).type, 'int');
-        flow.conditional_end(_Expression(), _Expression());
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('conditional_end keeps promotions common to true and false branches',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        flow.conditional_thenBegin(_Expression());
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        flow.conditional_elseBegin(_Expression());
-        h.promote(x, 'int');
-        h.promote(z, 'int');
-        flow.conditional_end(_Expression(), _Expression());
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-      });
-    });
-
-    test('conditional joins true states', () {
-      // if (... ? (x != null && y != null) : (x != null && z != null)) {
-      //   promotes x, but not y or z
-      // }
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        h.if_(
-            h.conditional(h.expr, h.and(h.notNull(x), h.notNull(y)),
-                h.and(h.notNull(x), h.notNull(z))), () {
-          expect(flow.promotedType(x).type, 'int');
-          expect(flow.promotedType(y), isNull);
-          expect(flow.promotedType(z), isNull);
-        });
-      });
-    });
-
-    test('conditional joins false states', () {
-      // if (... ? (x == null || y == null) : (x == null || z == null)) {
-      // } else {
-      //   promotes x, but not y or z
-      // }
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        h.ifElse(
-            h.conditional(h.expr, h.or(h.eqNull(x), h.eqNull(y)),
-                h.or(h.eqNull(x), h.eqNull(z))),
-            () {}, () {
-          expect(flow.promotedType(x).type, 'int');
-          expect(flow.promotedType(y), isNull);
-          expect(flow.promotedType(z), isNull);
-        });
-      });
-    });
-
-    test('equalityOp(x != null) promotes true branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var varExpr = _Expression();
-        flow.variableRead(varExpr, x);
-        flow.equalityOp_rightBegin(varExpr);
-        var nullExpr = _Expression();
-        flow.nullLiteral(nullExpr);
-        var expr = _Expression();
-        flow.equalityOp_end(expr, nullExpr, notEqual: true);
-        flow.ifStatement_thenBegin(expr);
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.ifStatement_end(true);
-      });
-    });
-
-    test('equalityOp(x == null) promotes false branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var varExpr = _Expression();
-        flow.variableRead(varExpr, x);
-        flow.equalityOp_rightBegin(varExpr);
-        var nullExpr = _Expression();
-        flow.nullLiteral(nullExpr);
-        var expr = _Expression();
-        flow.equalityOp_end(expr, nullExpr, notEqual: false);
-        flow.ifStatement_thenBegin(expr);
-        expect(flow.promotedType(x), isNull);
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_end(true);
-      });
-    });
-
-    test('equalityOp(null != x) promotes true branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var nullExpr = _Expression();
-        flow.nullLiteral(nullExpr);
-        flow.equalityOp_rightBegin(nullExpr);
-        var varExpr = _Expression();
-        flow.variableRead(varExpr, x);
-        var expr = _Expression();
-        flow.equalityOp_end(expr, varExpr, notEqual: true);
-        flow.ifStatement_thenBegin(expr);
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.ifStatement_end(true);
-      });
-    });
-
-    test('equalityOp(null == x) promotes false branch', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var nullExpr = _Expression();
-        flow.nullLiteral(nullExpr);
-        flow.equalityOp_rightBegin(nullExpr);
-        var varExpr = _Expression();
-        flow.variableRead(varExpr, x);
-        var expr = _Expression();
-        flow.equalityOp_end(expr, varExpr, notEqual: false);
-        flow.ifStatement_thenBegin(expr);
-        expect(flow.promotedType(x), isNull);
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_end(true);
-      });
-    });
-
-    test('conditionEqNull() does not promote write-captured vars', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.if_(h.notNull(x), () {
-          expect(flow.promotedType(x).type, 'int');
-        });
-        h.function({x}, () {
-          flow.write(x);
-        });
-        h.if_(h.notNull(x), () {
-          expect(flow.promotedType(x), isNull);
-        });
-      });
-    });
-
-    test('doStatement_bodyBegin() un-promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.doStatement_bodyBegin(_Statement(), {x}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.doStatement_conditionBegin();
-        flow.doStatement_end(_Expression());
-      });
-    });
-
-    test('doStatement_bodyBegin() handles write captures in the loop', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.doStatement_bodyBegin(_Statement(), {x}, {x});
-        h.promote(x, 'int');
-        // The promotion should have no effect, because the second time through
-        // the loop, x has been write-captured.
-        expect(flow.promotedType(x), isNull);
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.doStatement_conditionBegin();
-        flow.doStatement_end(_Expression());
-      });
-    });
-
-    test('doStatement_conditionBegin() joins continue state', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var stmt = _Statement();
-        flow.doStatement_bodyBegin(stmt, {}, {});
-        h.if_(h.notNull(x), () {
-          flow.handleContinue(stmt);
-        });
-        flow.handleExit();
-        expect(flow.isReachable, false);
-        expect(flow.promotedType(x), isNull);
-        flow.doStatement_conditionBegin();
-        expect(flow.isReachable, true);
-        expect(flow.promotedType(x).type, 'int');
-        flow.doStatement_end(_Expression());
-      });
-    });
-
-    test('doStatement_end() promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.doStatement_bodyBegin(_Statement(), {}, {});
-        flow.doStatement_conditionBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.doStatement_end(h.eqNull(x)());
-        expect(flow.promotedType(x).type, 'int');
-      });
-    });
-
-    test('finish checks proper nesting', () {
-      var h = _Harness();
-      var expr = _Expression();
-      var flow = h.createFlow();
-      flow.ifStatement_thenBegin(expr);
-      expect(() => flow.finish(), _asserts);
-    });
-
-    test('for_conditionBegin() un-promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.for_conditionBegin({x}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.for_bodyBegin(_Statement(), _Expression());
-        flow.write(x);
-        flow.for_updaterBegin();
-        flow.for_end();
-      });
-    });
-
-    test('for_conditionBegin() handles write captures in the loop', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.for_conditionBegin({x}, {x});
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.for_bodyBegin(_Statement(), _Expression());
-        flow.for_updaterBegin();
-        flow.for_end();
-      });
-    });
-
-    test('for_conditionBegin() handles not-yet-seen variables', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.for_conditionBegin({x}, {});
-        flow.initialize(x);
-        flow.for_bodyBegin(_Statement(), _Expression());
-        flow.for_updaterBegin();
-        flow.for_end();
-      });
-    });
-
-    test('for_bodyBegin() handles empty condition', () {
-      var h = _Harness();
-      h.run((flow) {
-        flow.for_conditionBegin({}, {});
-        flow.for_bodyBegin(_Statement(), null);
-        flow.for_updaterBegin();
-        expect(flow.isReachable, isTrue);
-        flow.for_end();
-        expect(flow.isReachable, isFalse);
-      });
-    });
-
-    test('for_bodyBegin() promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.for_conditionBegin({}, {});
-        flow.for_bodyBegin(_Statement(), h.notNull(x)());
-        expect(flow.promotedType(x).type, 'int');
-        flow.for_updaterBegin();
-        flow.for_end();
-      });
-    });
-
-    test('for_bodyBegin() can be used with a null statement', () {
-      // This is needed for collection elements that are for-loops.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.for_conditionBegin({}, {});
-        flow.for_bodyBegin(null, h.notNull(x)());
-        flow.for_updaterBegin();
-        flow.for_end();
-      });
-    });
-
-    test('for_updaterBegin() joins current and continue states', () {
-      // To test that the states are properly joined, we have three variables:
-      // x, y, and z.  We promote x and y in the continue path, and x and z in
-      // the current path.  Inside the updater, only x should be promoted.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        var stmt = _Statement();
-        flow.for_conditionBegin({}, {});
-        flow.for_bodyBegin(stmt, h.expr());
-        h.if_(h.expr, () {
-          h.promote(x, 'int');
-          h.promote(y, 'int');
-          flow.handleContinue(stmt);
-        });
-        h.promote(x, 'int');
-        h.promote(z, 'int');
-        flow.for_updaterBegin();
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-        flow.for_end();
-      });
-    });
-
-    test('for_end() joins break and condition-false states', () {
-      // To test that the states are properly joined, we have three variables:
-      // x, y, and z.  We promote x and y in the break path, and x and z in the
-      // condition-false path.  After the loop, only x should be promoted.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        var stmt = _Statement();
-        flow.for_conditionBegin({}, {});
-        flow.for_bodyBegin(stmt, h.or(h.eqNull(x), h.eqNull(z))());
-        h.if_(h.expr, () {
-          h.promote(x, 'int');
-          h.promote(y, 'int');
-          flow.handleBreak(stmt);
-        });
-        flow.for_updaterBegin();
-        flow.for_end();
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-      });
-    });
-
-    test('forEach_bodyBegin() un-promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.forEach_bodyBegin({x}, {}, null);
-        expect(flow.promotedType(x), isNull);
-        flow.write(x);
-        flow.forEach_end();
-      });
-    });
-
-    test('forEach_bodyBegin() handles write captures in the loop', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.forEach_bodyBegin({x}, {x}, null);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.forEach_end();
-      });
-    });
-
-    test('forEach_bodyBegin() writes to loop variable', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: false);
-        expect(flow.isAssigned(x), false);
-        flow.forEach_bodyBegin({x}, {}, x);
-        expect(flow.isAssigned(x), true);
-        flow.forEach_end();
-        expect(flow.isAssigned(x), false);
-      });
-    });
-
-    test('forEach_end() restores state before loop', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.forEach_bodyBegin({}, {}, null);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.forEach_end();
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('functionExpression_begin() cancels promotions of self-captured vars',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_begin({x});
-        // x is unpromoted within the local function
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        flow.write(x);
-        h.promote(x, 'int');
-        flow.functionExpression_end();
-        // x is unpromoted after the local function too
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-      });
-    });
-
-    test('functionExpression_begin() cancels promotions of other-captured vars',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_begin({});
-        // x is unpromoted within the local function, because the write
-        // might have been captured by the time the local function executes.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        // And any effort to promote x fails, because there is no way of knowing
-        // when the captured write might occur.
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_end();
-        // x is still promoted after the local function, though, because the
-        // write hasn't been captured yet.
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_begin({x});
-        // x is unpromoted inside this local function too.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        flow.write(x);
-        flow.functionExpression_end();
-        // And since the second local function captured x, it remains
-        // unpromoted.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-      });
-    });
-
-    test('functionExpression_begin() cancels promotions of written vars', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_begin({});
-        // x is unpromoted within the local function, because the write
-        // might have happened by the time the local function executes.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        // But it can be re-promoted because the write isn't captured.
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.functionExpression_end();
-        // x is still promoted after the local function, though, because the
-        // write hasn't occurred yet.
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.write(x);
-        // x is unpromoted now.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-      });
-    });
-
-    test('functionExpression_begin() handles not-yet-seen variables', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.functionExpression_begin({x});
-        flow.functionExpression_end();
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('functionExpression_begin() handles not-yet-seen write-captured vars',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.functionExpression_begin({});
-        h.promote(x, 'int');
-        // Promotion should not occur, because x might be write-captured by the
-        // time this code is reached.
-        expect(flow.promotedType(x), isNull);
-        flow.functionExpression_end();
-        flow.functionExpression_begin({x});
-        h.declare(x, initialized: true);
-        flow.functionExpression_end();
-      });
-    });
-
-    test('ifStatement_end(false) keeps else branch if then branch exits', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.ifStatement_thenBegin(h.eqNull(x)());
-        flow.handleExit();
-        flow.ifStatement_end(false);
-        expect(flow.promotedType(x).type, 'int');
-      });
-    });
-
-    void _checkIs(String declaredType, String tryPromoteType,
-        String expectedPromotedType) {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var expr = _Expression();
-        flow.isExpression_end(expr, x, false, _Type(tryPromoteType));
-        flow.ifStatement_thenBegin(expr);
-        if (expectedPromotedType == null) {
-          expect(flow.promotedType(x), isNull);
-        } else {
-          expect(flow.promotedType(x).type, expectedPromotedType);
-        }
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.ifStatement_end(true);
-      });
-    }
-
-    test('isExpression_end promotes to a subtype', () {
-      _checkIs('int?', 'int', 'int');
-    });
-
-    test('isExpression_end does not promote to a supertype', () {
-      _checkIs('int', 'int?', null);
-    });
-
-    test('isExpression_end does not promote to an unrelated type', () {
-      _checkIs('int', 'String', null);
-    });
-
-    test('isExpression_end() does not promote write-captured vars', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.if_(h.isType(x, 'int'), () {
-          expect(flow.promotedType(x).type, 'int');
-        });
-        h.function({x}, () {
-          flow.write(x);
-        });
-        h.if_(h.isType(x, 'int'), () {
-          expect(flow.promotedType(x), isNull);
-        });
-      });
-    });
-
-    test('isExpression_end() handles not-yet-seen variables', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.if_(h.isType(x, 'int'), () {
-          expect(flow.promotedType(x).type, 'int');
-        });
-        h.declare(x, initialized: true);
-      });
-    });
-
-    test('logicalBinaryOp_rightBegin(isAnd: true) promotes in RHS', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.logicalBinaryOp_rightBegin(h.notNull(x)(), isAnd: true);
-        expect(flow.promotedType(x).type, 'int');
-        flow.logicalBinaryOp_end(_Expression(), _Expression(), isAnd: true);
-      });
-    });
-
-    test('logicalBinaryOp_rightEnd(isAnd: true) keeps promotions from RHS', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: true);
-        var wholeExpr = _Expression();
-        flow.logicalBinaryOp_end(wholeExpr, h.notNull(x)(), isAnd: true);
-        flow.ifStatement_thenBegin(wholeExpr);
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_end(false);
-      });
-    });
-
-    test('logicalBinaryOp_rightEnd(isAnd: false) keeps promotions from RHS',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: false);
-        var wholeExpr = _Expression();
-        flow.logicalBinaryOp_end(wholeExpr, h.eqNull(x)(), isAnd: false);
-        flow.ifStatement_thenBegin(wholeExpr);
-        flow.ifStatement_elseBegin();
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_end(true);
-      });
-    });
-
-    test('logicalBinaryOp_rightBegin(isAnd: false) promotes in RHS', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.logicalBinaryOp_rightBegin(h.eqNull(x)(), isAnd: false);
-        expect(flow.promotedType(x).type, 'int');
-        flow.logicalBinaryOp_end(_Expression(), _Expression(), isAnd: false);
-      });
-    });
-
-    test('logicalBinaryOp(isAnd: true) joins promotions', () {
-      // if (x != null && y != null) {
-      //   promotes x and y
-      // }
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.if_(h.and(h.notNull(x), h.notNull(y)), () {
-          expect(flow.promotedType(x).type, 'int');
-          expect(flow.promotedType(y).type, 'int');
-        });
-      });
-    });
-
-    test('logicalBinaryOp(isAnd: false) joins promotions', () {
-      // if (x == null || y == null) {} else {
-      //   promotes x and y
-      // }
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.ifElse(h.or(h.eqNull(x), h.eqNull(y)), () {}, () {
-          expect(flow.promotedType(x).type, 'int');
-          expect(flow.promotedType(y).type, 'int');
-        });
-      });
-    });
-
-    test('nonNullAssert_end(x) promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var varExpr = _Expression();
-        flow.variableRead(varExpr, x);
-        flow.nonNullAssert_end(varExpr);
-        expect(flow.promotedType(x).type, 'int');
-      });
-    });
-
-    test('parenthesizedExpression preserves promotion behaviors', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.if_(
-            h.parenthesized(h.notEqual(h.parenthesized(h.variableRead(x)),
-                h.parenthesized(h.nullLiteral))), () {
-          expect(flow.promotedType(x).type, 'int');
-        });
-      });
-    });
-
-    test('promotedType handles not-yet-seen variables', () {
-      // Note: this is needed for error recovery in the analyzer.
-      var h = _Harness();
-      var x = h.addVar('x', 'int');
-      h.run((flow) {
-        expect(flow.promotedType(x), isNull);
-        h.declare(x, initialized: true);
-      });
-    });
-
-    test('switchStatement_beginCase(false) restores previous promotions', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        flow.switchStatement_expressionEnd(_Statement());
-        flow.switchStatement_beginCase(false, {x}, {});
-        expect(flow.promotedType(x).type, 'int');
-        flow.write(x);
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_beginCase(false, {x}, {});
-        expect(flow.promotedType(x).type, 'int');
-        flow.write(x);
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_end(false);
-      });
-    });
-
-    test('switchStatement_beginCase(false) does not un-promote', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        flow.switchStatement_expressionEnd(_Statement());
-        flow.switchStatement_beginCase(false, {x}, {});
-        expect(flow.promotedType(x).type, 'int');
-        flow.write(x);
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_end(false);
-      });
-    });
-
-    test('switchStatement_beginCase(false) handles write captures in cases',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        flow.switchStatement_expressionEnd(_Statement());
-        flow.switchStatement_beginCase(false, {x}, {x});
-        expect(flow.promotedType(x).type, 'int');
-        h.function({x}, () {
-          flow.write(x);
-        });
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_end(false);
-      });
-    });
-
-    test('switchStatement_beginCase(true) un-promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        flow.switchStatement_expressionEnd(_Statement());
-        flow.switchStatement_beginCase(true, {x}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.write(x);
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_end(false);
-      });
-    });
-
-    test('switchStatement_beginCase(true) handles write captures in cases', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        flow.switchStatement_expressionEnd(_Statement());
-        flow.switchStatement_beginCase(true, {x}, {x});
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        h.function({x}, () {
-          flow.write(x);
-        });
-        expect(flow.promotedType(x), isNull);
-        flow.switchStatement_end(false);
-      });
-    });
-
-    test('switchStatement_end(false) joins break and default', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?', hasWrites: true);
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        h.promote(y, 'int');
-        h.promote(z, 'int');
-        var stmt = _Statement();
-        flow.switchStatement_expressionEnd(stmt);
-        flow.switchStatement_beginCase(false, {y}, {});
-        h.promote(x, 'int');
-        flow.write(y);
-        flow.handleBreak(stmt);
-        flow.switchStatement_end(false);
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z).type, 'int');
-      });
-    });
-
-    test('switchStatement_end(true) joins breaks', () {
-      var h = _Harness();
-      var w = h.addVar('w', 'int?');
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      var y = h.addVar('y', 'int?', hasWrites: true);
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(w, initialized: true);
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        h.promote(z, 'int');
-        var stmt = _Statement();
-        flow.switchStatement_expressionEnd(stmt);
-        flow.switchStatement_beginCase(false, {x, y}, {});
-        h.promote(w, 'int');
-        h.promote(y, 'int');
-        flow.write(x);
-        flow.handleBreak(stmt);
-        flow.switchStatement_beginCase(false, {x, y}, {});
-        h.promote(w, 'int');
-        h.promote(x, 'int');
-        flow.write(y);
-        flow.handleBreak(stmt);
-        flow.switchStatement_end(true);
-        expect(flow.promotedType(w).type, 'int');
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z).type, 'int');
-      });
-    });
-
-    test('switchStatement_end(true) allows fall-through of last case', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        var stmt = _Statement();
-        flow.switchStatement_expressionEnd(stmt);
-        flow.switchStatement_beginCase(false, {}, {});
-        h.promote(x, 'int');
-        flow.handleBreak(stmt);
-        flow.switchStatement_beginCase(false, {}, {});
-        flow.switchStatement_end(true);
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('tryCatchStatement_bodyEnd() restores pre-try state', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.tryCatchStatement_bodyBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryCatchStatement_bodyEnd({}, {});
-        flow.tryCatchStatement_catchBegin();
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-      });
-    });
-
-    test('tryCatchStatement_bodyEnd() un-promotes variables assigned in body',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryCatchStatement_bodyBegin();
-        flow.write(x);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryCatchStatement_bodyEnd({x}, {});
-        flow.tryCatchStatement_catchBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-      });
-    });
-
-    test('tryCatchStatement_bodyEnd() preserves write captures in body', () {
-      // Note: it's not necessary for the write capture to survive to the end of
-      // the try body, because an exception could occur at any time.  We check
-      // this by putting an exit in the try body.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryCatchStatement_bodyBegin();
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.handleExit();
-        flow.tryCatchStatement_bodyEnd({x}, {x});
-        flow.tryCatchStatement_catchBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-      });
-    });
-
-    test('tryCatchStatement_catchBegin() restores previous post-body state',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.tryCatchStatement_bodyBegin();
-        flow.tryCatchStatement_bodyEnd({}, {});
-        flow.tryCatchStatement_catchBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_catchBegin();
-        expect(flow.promotedType(x), isNull);
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-      });
-    });
-
-    test('tryCatchStatement_catchEnd() joins catch state with after-try state',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        flow.tryCatchStatement_bodyBegin();
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        flow.tryCatchStatement_bodyEnd({}, {});
-        flow.tryCatchStatement_catchBegin();
-        h.promote(x, 'int');
-        h.promote(z, 'int');
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-        // Only x should be promoted, because it's the only variable
-        // promoted in both the try body and the catch handler.
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-      });
-    });
-
-    test('tryCatchStatement_catchEnd() joins catch states', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        flow.tryCatchStatement_bodyBegin();
-        flow.handleExit();
-        flow.tryCatchStatement_bodyEnd({}, {});
-        flow.tryCatchStatement_catchBegin();
-        h.promote(x, 'int');
-        h.promote(y, 'int');
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_catchBegin();
-        h.promote(x, 'int');
-        h.promote(z, 'int');
-        flow.tryCatchStatement_catchEnd();
-        flow.tryCatchStatement_end();
-        // Only x should be promoted, because it's the only variable promoted
-        // in both catch handlers.
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-      });
-    });
-
-    test('tryFinallyStatement_finallyBegin() restores pre-try state', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.tryFinallyStatement_bodyBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryFinallyStatement_finallyBegin({}, {});
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryFinallyStatement_end({});
-      });
-    });
-
-    test(
-        'tryFinallyStatement_finallyBegin() un-promotes variables assigned in '
-        'body', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryFinallyStatement_bodyBegin();
-        flow.write(x);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryFinallyStatement_finallyBegin({x}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.tryFinallyStatement_end({});
-      });
-    });
-
-    test('tryFinallyStatement_finallyBegin() preserves write captures in body',
-        () {
-      // Note: it's not necessary for the write capture to survive to the end of
-      // the try body, because an exception could occur at any time.  We check
-      // this by putting an exit in the try body.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.tryFinallyStatement_bodyBegin();
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.handleExit();
-        flow.tryFinallyStatement_finallyBegin({x}, {x});
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        flow.tryFinallyStatement_end({});
-      });
-    });
-
-    test('tryFinallyStatement_end() restores promotions from try body', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        flow.tryFinallyStatement_bodyBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryFinallyStatement_finallyBegin({}, {});
-        expect(flow.promotedType(x), isNull);
-        h.promote(y, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryFinallyStatement_end({});
-        // Both x and y should now be promoted.
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y).type, 'int');
-      });
-    });
-
-    test(
-        'tryFinallyStatement_end() does not restore try body promotions for '
-        'variables assigned in finally', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true);
-      var y = h.addVar('y', 'int?', hasWrites: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        flow.tryFinallyStatement_bodyBegin();
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.tryFinallyStatement_finallyBegin({}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.write(x);
-        flow.write(y);
-        h.promote(y, 'int');
-        expect(flow.promotedType(y).type, 'int');
-        flow.tryFinallyStatement_end({x, 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.
-        expect(flow.promotedType(x), isNull);
-        expect(flow.promotedType(y).type, 'int');
-      });
-    });
-
-    test('whileStatement_conditionBegin() un-promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.whileStatement_conditionBegin({x}, {});
-        expect(flow.promotedType(x), isNull);
-        flow.whileStatement_bodyBegin(_Statement(), _Expression());
-        flow.whileStatement_end();
-      });
-    });
-
-    test('whileStatement_conditionBegin() handles write captures in the loop',
-        () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?', hasWrites: true, isCaptured: true);
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        flow.whileStatement_conditionBegin({x}, {x});
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-        h.function({x}, () {
-          flow.write(x);
-        });
-        flow.whileStatement_bodyBegin(_Statement(), _Expression());
-        flow.whileStatement_end();
-      });
-    });
-
-    test('whileStatement_conditionBegin() handles not-yet-seen variables', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      h.run((flow) {
-        h.declare(y, initialized: true);
-        h.promote(y, 'int');
-        flow.whileStatement_conditionBegin({x}, {});
-        flow.initialize(x);
-        flow.whileStatement_bodyBegin(_Statement(), _Expression());
-        flow.whileStatement_end();
-      });
-    });
-
-    test('whileStatement_bodyBegin() promotes', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        flow.whileStatement_conditionBegin({}, {});
-        flow.whileStatement_bodyBegin(_Statement(), h.notNull(x)());
-        expect(flow.promotedType(x).type, 'int');
-        flow.whileStatement_end();
-      });
-    });
-
-    test('whileStatement_end() joins break and condition-false states', () {
-      // To test that the states are properly joined, we have three variables:
-      // x, y, and z.  We promote x and y in the break path, and x and z in the
-      // condition-false path.  After the loop, only x should be promoted.
-      var h = _Harness();
-      var x = h.addVar('x', 'int?');
-      var y = h.addVar('y', 'int?');
-      var z = h.addVar('z', 'int?');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.declare(y, initialized: true);
-        h.declare(z, initialized: true);
-        var stmt = _Statement();
-        flow.whileStatement_conditionBegin({}, {});
-        flow.whileStatement_bodyBegin(stmt, h.or(h.eqNull(x), h.eqNull(z))());
-        h.if_(h.expr, () {
-          h.promote(x, 'int');
-          h.promote(y, 'int');
-          flow.handleBreak(stmt);
-        });
-        flow.whileStatement_end();
-        expect(flow.promotedType(x).type, 'int');
-        expect(flow.promotedType(y), isNull);
-        expect(flow.promotedType(z), isNull);
-      });
-    });
-
-    test('Infinite loop does not implicitly assign variables', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'int');
-      h.run((flow) {
-        h.declare(x, initialized: false);
-        var trueCondition = _Expression();
-        flow.whileStatement_conditionBegin({x}, {});
-        flow.booleanLiteral(trueCondition, true);
-        flow.whileStatement_bodyBegin(_Statement(), trueCondition);
-        flow.whileStatement_end();
-        expect(flow.isAssigned(x), false);
-      });
-    });
-
-    test('If(false) does not discard promotions', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'Object');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.promote(x, 'int');
-        expect(flow.promotedType(x).type, 'int');
-        // if (false) {
-        var falseExpression = _Expression();
-        flow.booleanLiteral(falseExpression, false);
-        flow.ifStatement_thenBegin(falseExpression);
-        expect(flow.promotedType(x).type, 'int');
-        flow.ifStatement_end(false);
-      });
-    });
-
-    test('Promotions do not occur when a variable is write-captured', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'Object');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.function({x}, () {});
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-
-    test('Promotion cancellation of write-captured vars survives join', () {
-      var h = _Harness();
-      var x = h.addVar('x', 'Object');
-      h.run((flow) {
-        h.declare(x, initialized: true);
-        h.ifElse(h.expr, () {
-          h.function({x}, () {});
-        }, () {
-          // Promotion should work here because the write capture is in the
-          // other branch.
-          h.promote(x, 'int');
-          expect(flow.promotedType(x).type, 'int');
-        });
-        // But the promotion should be cancelled now, after the join.
-        expect(flow.promotedType(x), isNull);
-        // And further attempts to promote should fail due to the write capture.
-        h.promote(x, 'int');
-        expect(flow.promotedType(x), isNull);
-      });
-    });
-  });
-
-  group('State', () {
-    var intVar = _Var('x', _Type('int'));
-    var intQVar = _Var('x', _Type('int?'));
-    var objectQVar = _Var('x', _Type('Object?'));
-    group('setReachable', () {
-      var unreachable = FlowModel<_Var, _Type>(false);
-      var reachable = FlowModel<_Var, _Type>(true);
-      test('unchanged', () {
-        expect(unreachable.setReachable(false), same(unreachable));
-        expect(reachable.setReachable(true), same(reachable));
-      });
-
-      test('changed', () {
-        void _check(FlowModel<_Var, _Type> initial, bool newReachability) {
-          var s = initial.setReachable(newReachability);
-          expect(s, isNot(same(initial)));
-          expect(s.reachable, newReachability);
-          expect(s.variableInfo, same(initial.variableInfo));
-        }
-
-        _check(unreachable, true);
-        _check(reachable, false);
-      });
-    });
-
-    group('promote', () {
-      test('unpromoted -> unchanged (same)', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.promote(h, intVar, _Type('int'));
-        expect(s2, same(s1));
-      });
-
-      test('unpromoted -> unchanged (supertype)', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.promote(h, intVar, _Type('Object'));
-        expect(s2, same(s1));
-      });
-
-      test('unpromoted -> unchanged (unrelated)', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.promote(h, intVar, _Type('String'));
-        expect(s2, same(s1));
-      });
-
-      test('unpromoted -> subtype', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.promote(h, intQVar, _Type('int'));
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(s2.variableInfo,
-              {intQVar: VariableModel<_Type>(_Type('int'), false, false)});
-        });
-      });
-
-      test('promoted -> unchanged (same)', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
-        var s2 = s1.promote(h, objectQVar, _Type('int'));
-        expect(s2, same(s1));
-      });
-
-      test('promoted -> unchanged (supertype)', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
-        var s2 = s1.promote(h, objectQVar, _Type('Object'));
-        expect(s2, same(s1));
-      });
-
-      test('promoted -> unchanged (unrelated)', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
-        var s2 = s1.promote(h, objectQVar, _Type('String'));
-        expect(s2, same(s1));
-      });
-
-      test('promoted -> subtype', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int?'));
-        var s2 = s1.promote(h, objectQVar, _Type('int'));
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(s2.variableInfo,
-              {objectQVar: VariableModel<_Type>(_Type('int'), false, false)});
-        });
-      });
-    });
-
-    group('write', () {
-      var objectQVar = _Var('x', _Type('Object?'));
-      test('unchanged', () {
-        var s1 = FlowModel<_Var, _Type>(true).write(objectQVar);
-        var s2 = s1.write(objectQVar);
-        expect(s2, same(s1));
-      });
-
-      test('marks as assigned', () {
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.write(objectQVar);
-        expect(s2.reachable, true);
-        expect(s2.infoFor(objectQVar), VariableModel<_Type>(null, true, false));
-      });
-
-      test('un-promotes', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
-            .write(objectQVar)
-            .promote(h, objectQVar, _Type('int'));
-        expect(s1.variableInfo, contains(objectQVar));
-        var s2 = s1.write(objectQVar);
-        expect(s2.reachable, true);
-        expect(s2.variableInfo,
-            {objectQVar: VariableModel<_Type>(null, true, false)});
-      });
-    });
-
-    group('markNonNullable', () {
-      test('unpromoted -> unchanged', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.markNonNullable(h, intVar);
-        expect(s2, same(s1));
-      });
-
-      test('unpromoted -> promoted', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
-        var s2 = s1.markNonNullable(h, intQVar);
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(
-              s2.infoFor(intQVar), VariableModel(_Type('int'), false, false));
-        });
-      });
-
-      test('promoted -> unchanged', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
-        var s2 = s1.markNonNullable(h, objectQVar);
-        expect(s2, same(s1));
-      });
-
-      test('promoted -> re-promoted', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int?'));
-        var s2 = s1.markNonNullable(h, objectQVar);
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(s2.variableInfo,
-              {objectQVar: VariableModel<_Type>(_Type('int'), false, false)});
-        });
-      });
-    });
-
-    group('removePromotedAll', () {
-      test('unchanged', () {
-        var h = _Harness();
-        var s1 =
-            FlowModel<_Var, _Type>(true).promote(h, objectQVar, _Type('int'));
-        var s2 = s1.removePromotedAll([intQVar], []);
-        expect(s2, same(s1));
-      });
-
-      test('written', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
-            .promote(h, objectQVar, _Type('int'))
-            .promote(h, intQVar, _Type('int'));
-        var s2 = s1.removePromotedAll([intQVar], []);
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(s2.variableInfo, {
-            objectQVar: VariableModel<_Type>(_Type('int'), false, false),
-            intQVar: VariableModel<_Type>(null, false, false)
-          });
-        });
-      });
-
-      test('write captured', () {
-        var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
-            .promote(h, objectQVar, _Type('int'))
-            .promote(h, intQVar, _Type('int'));
-        var s2 = s1.removePromotedAll([], [intQVar]);
-        expect(s2.reachable, true);
-        _Type.allowComparisons(() {
-          expect(s2.variableInfo, {
-            objectQVar: VariableModel<_Type>(_Type('int'), false, false),
-            intQVar: VariableModel<_Type>(null, false, true)
-          });
-        });
-      });
-    });
-
-    group('restrict', () {
-      test('reachability', () {
-        var h = _Harness();
-        var reachable = FlowModel<_Var, _Type>(true);
-        var unreachable = reachable.setReachable(false);
-        expect(reachable.restrict(h, reachable, Set()), same(reachable));
-        expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
-        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
-        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
-      });
-
-      test('assignments', () {
-        var h = _Harness();
-        var a = _Var('a', _Type('int'));
-        var b = _Var('b', _Type('int'));
-        var c = _Var('c', _Type('int'));
-        var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true);
-        var s1 = s0.write(a).write(b);
-        var s2 = s0.write(a).write(c);
-        var result = s1.restrict(h, s2, Set());
-        expect(result.infoFor(a).assigned, true);
-        expect(result.infoFor(b).assigned, true);
-        expect(result.infoFor(c).assigned, true);
-        expect(result.infoFor(d).assigned, false);
-      });
-
-      test('write captured', () {
-        var h = _Harness();
-        var a = _Var('a', _Type('int'));
-        var b = _Var('b', _Type('int'));
-        var c = _Var('c', _Type('int'));
-        var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true);
-        // In s1, a and b are write captured.  In s2, a and c are.
-        var s1 = s0.removePromotedAll([a, b], [a, b]);
-        var s2 = s0.removePromotedAll([a, c], [a, c]);
-        var result = s1.restrict(h, s2, Set());
-        expect(result.infoFor(a).writeCaptured, true);
-        expect(result.infoFor(b).writeCaptured, true);
-        expect(result.infoFor(c).writeCaptured, true);
-        expect(result.infoFor(d).writeCaptured, false);
-      });
-
-      test('promotion', () {
-        void _check(String thisType, String otherType, bool unsafe,
-            String expectedType) {
-          var h = _Harness();
-          var x = _Var('x', _Type('Object?'));
-          var s0 = FlowModel<_Var, _Type>(true).write(x);
-          var s1 = thisType == null ? s0 : s0.promote(h, x, _Type(thisType));
-          var s2 = otherType == null ? s0 : s0.promote(h, x, _Type(otherType));
-          var result = s1.restrict(h, s2, unsafe ? [x].toSet() : Set());
-          if (expectedType == null) {
-            expect(result.variableInfo, contains(x));
-            expect(result.infoFor(x).promotedType, isNull);
-          } else {
-            expect(result.infoFor(x).promotedType.type, expectedType);
-          }
-        }
-
-        _check(null, null, false, null);
-        _check(null, null, true, null);
-        _check('int', null, false, 'int');
-        _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');
-        _check('int', 'String', false, 'int');
-        _check('int?', 'int', true, 'int?');
-        _check('int', 'int?', true, 'int');
-        _check('int', 'String', true, 'int');
-      });
-
-      test('variable present in one state but not the other', () {
-        var h = _Harness();
-        var x = _Var('x', _Type('Object?'));
-        var s0 = FlowModel<_Var, _Type>(true);
-        var s1 = s0.write(x);
-        expect(s0.restrict(h, s1, {}), same(s1));
-        expect(s0.restrict(h, s1, {x}), same(s1));
-        expect(s1.restrict(h, s0, {}), same(s1));
-        expect(s1.restrict(h, s0, {x}), same(s1));
-      });
-    });
-  });
-
-  group('join', () {
-    var x = _Var('x', null);
-    var y = _Var('y', null);
-    var z = _Var('y', null);
-    var w = _Var('y', null);
-    var intType = _Type('int');
-    var intQType = _Type('int?');
-    var stringType = _Type('String');
-    const emptyMap = <Null, VariableModel<Null>>{};
-
-    VariableModel<_Type> model(_Type type) =>
-        VariableModel<_Type>(type, true, false);
-
-    group('without input reuse', () {
-      test('promoted with unpromoted', () {
-        var h = _Harness();
-        var p1 = {x: model(intType), y: model(null)};
-        var p2 = {x: model(null), y: model(intType)};
-        expect(FlowModel.joinVariableInfo(h, p1, p2),
-            {x: model(null), y: model(null)});
-      });
-    });
-    group('should re-use an input if possible', () {
-      test('identical inputs', () {
-        var h = _Harness();
-        var p = {x: model(intType), y: model(stringType)};
-        expect(FlowModel.joinVariableInfo(h, p, p), same(p));
-      });
-
-      test('one input empty', () {
-        var h = _Harness();
-        var p1 = {x: model(intType), y: model(stringType)};
-        var p2 = <_Var, VariableModel<_Type>>{};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), same(emptyMap));
-        expect(FlowModel.joinVariableInfo(h, p2, p1), same(emptyMap));
-      });
-
-      test('promoted with unpromoted', () {
-        var h = _Harness();
-        var p1 = {x: model(intType)};
-        var p2 = {x: model(null)};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), same(p2));
-        expect(FlowModel.joinVariableInfo(h, p2, p1), same(p2));
-      });
-
-      test('related types', () {
-        var h = _Harness();
-        var p1 = {x: model(intType)};
-        var p2 = {x: model(intQType)};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), same(p2));
-        expect(FlowModel.joinVariableInfo(h, p2, p1), same(p2));
-      });
-
-      test('unrelated types', () {
-        var h = _Harness();
-        var p1 = {x: model(intType)};
-        var p2 = {x: model(stringType)};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), {x: model(null)});
-        expect(FlowModel.joinVariableInfo(h, p2, p1), {x: model(null)});
-      });
-
-      test('sub-map', () {
-        var h = _Harness();
-        var xModel = model(intType);
-        var p1 = {x: xModel, y: model(stringType)};
-        var p2 = {x: xModel};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), same(p2));
-        expect(FlowModel.joinVariableInfo(h, p2, p1), same(p2));
-      });
-
-      test('sub-map with matched subtype', () {
-        var h = _Harness();
-        var p1 = {x: model(intType), y: model(stringType)};
-        var p2 = {x: model(intQType)};
-        expect(FlowModel.joinVariableInfo(h, p1, p2), same(p2));
-        expect(FlowModel.joinVariableInfo(h, p2, p1), same(p2));
-      });
-
-      test('sub-map with mismatched subtype', () {
-        var h = _Harness();
-        var p1 = {x: model(intQType), y: model(stringType)};
-        var p2 = {x: model(intType)};
-        var join12 = FlowModel.joinVariableInfo(h, p1, p2);
-        _Type.allowComparisons(() => expect(join12, {x: model(intQType)}));
-        var join21 = FlowModel.joinVariableInfo(h, p2, p1);
-        _Type.allowComparisons(() => expect(join21, {x: model(intQType)}));
-      });
-
-      test('assigned', () {
-        var h = _Harness();
-        var p1 = {
-          x: model(intQType).write(),
-          y: model(intQType).write(),
-          z: model(intQType),
-          w: model(intQType)
-        };
-        var p2 = {
-          x: model(intQType).write(),
-          y: model(intQType),
-          z: model(intQType).write(),
-          w: model(intQType)
-        };
-        var joined = FlowModel.joinVariableInfo(h, p1, p2);
-        _Type.allowComparisons(() => expect(joined, {
-              x: model(intQType).write(),
-              y: model(intQType).write(),
-              z: model(intQType).write(),
-              w: model(intQType)
-            }));
-      });
-
-      test('write captured', () {
-        var h = _Harness();
-        var p1 = {
-          x: model(intQType).writeCapture(),
-          y: model(intQType).writeCapture(),
-          z: model(intQType),
-          w: model(intQType)
-        };
-        var p2 = {
-          x: model(intQType).writeCapture(),
-          y: model(intQType),
-          z: model(intQType).writeCapture(),
-          w: model(intQType)
-        };
-        var joined = FlowModel.joinVariableInfo(h, p1, p2);
-        _Type.allowComparisons(() => expect(joined, {
-              x: model(intQType).writeCapture(),
-              y: model(intQType).writeCapture(),
-              z: model(intQType).writeCapture(),
-              w: model(intQType)
-            }));
-      });
-    });
-  });
-}
-
-/// Returns the appropriate matcher for expecting an assertion error to be
-/// thrown or not, based on whether assertions are enabled.
-Matcher get _asserts {
-  var matcher = throwsA(TypeMatcher<AssertionError>());
-  bool assertionsEnabled = false;
-  assert(assertionsEnabled = true);
-  if (!assertionsEnabled) {
-    matcher = isNot(matcher);
-  }
-  return matcher;
-}
-
-/// Representation of an expression to be visited by the test harness.  Calling
-/// the function causes the expression to be "visited" (in other words, the
-/// appropriate methods in [FlowAnalysis] are called in the appropriate order),
-/// and the [_Expression] object representing the whole expression is returned.
-///
-/// This is used by methods in [_Harness] as a lightweight way of building up
-/// complex sequences of calls to [FlowAnalysis] that represent large
-/// expressions.
-typedef _Expression LazyExpression();
-
-class _Expression {}
-
-class _Harness implements TypeOperations<_Var, _Type> {
-  FlowAnalysis<_Statement, _Expression, _Var, _Type> _flow;
-
-  final List<_Var> _variablesWrittenAnywhere = [];
-
-  final List<_Var> _variablesCapturedAnywhere = [];
-
-  /// Returns a [LazyExpression] representing an expression with now special
-  /// flow analysis semantics.
-  LazyExpression get expr => () => _Expression();
-
-  LazyExpression get nullLiteral => () {
-        var expr = _Expression();
-        _flow.nullLiteral(expr);
-        return expr;
-      };
-
-  _Var addVar(String name, String type,
-      {bool hasWrites: false, bool isCaptured: false}) {
-    assert(_flow == null);
-    var v = _Var(name, _Type(type));
-    if (hasWrites) {
-      _variablesWrittenAnywhere.add(v);
-    }
-    if (isCaptured) {
-      assert(hasWrites);
-      _variablesCapturedAnywhere.add(v);
-    }
-    return v;
-  }
-
-  /// Given two [LazyExpression]s, produces a new [LazyExpression] representing
-  /// the result of combining them with `&&`.
-  LazyExpression and(LazyExpression lhs, LazyExpression rhs) {
-    return () {
-      var expr = _Expression();
-      _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: true);
-      _flow.logicalBinaryOp_end(expr, rhs(), isAnd: true);
-      return expr;
-    };
-  }
-
-  /// Given three [LazyExpression]s, produces a new [LazyExpression]
-  /// representing the result of combining them with `?` and `:`.
-  LazyExpression conditional(
-      LazyExpression cond, LazyExpression ifTrue, LazyExpression ifFalse) {
-    return () {
-      var expr = _Expression();
-      _flow.conditional_thenBegin(cond());
-      _flow.conditional_elseBegin(ifTrue());
-      _flow.conditional_end(expr, ifFalse());
-      return expr;
-    };
-  }
-
-  FlowAnalysis<_Statement, _Expression, _Var, _Type> createFlow() =>
-      FlowAnalysis<_Statement, _Expression, _Var, _Type>(
-          this, _variablesWrittenAnywhere, _variablesCapturedAnywhere);
-
-  void declare(_Var v, {@required bool initialized}) {
-    if (initialized) {
-      _flow.initialize(v);
-    }
-  }
-
-  /// Creates a [LazyExpression] representing an `== null` check performed on
-  /// [variable].
-  LazyExpression eqNull(_Var variable) {
-    return () {
-      var varExpr = _Expression();
-      _flow.variableRead(varExpr, variable);
-      _flow.equalityOp_rightBegin(varExpr);
-      var nullExpr = _Expression();
-      _flow.nullLiteral(nullExpr);
-      var expr = _Expression();
-      _flow.equalityOp_end(expr, nullExpr, notEqual: false);
-      return expr;
-    };
-  }
-
-  /// Creates a [LazyExpression] representing an equality check between two
-  /// other expressions.
-  LazyExpression notEqual(LazyExpression lhs, LazyExpression rhs) {
-    return () {
-      var expr = _Expression();
-      _flow.equalityOp_rightBegin(lhs());
-      _flow.equalityOp_end(expr, rhs(), notEqual: true);
-      return expr;
-    };
-  }
-
-  /// Invokes flow analysis of a nested function.
-  void function(Iterable<_Var> writeCaptured, void body()) {
-    _flow.functionExpression_begin(writeCaptured);
-    body();
-    _flow.functionExpression_end();
-  }
-
-  /// Invokes flow analysis of an `if` statement with no `else` part.
-  void if_(LazyExpression cond, void ifTrue()) {
-    _flow.ifStatement_thenBegin(cond());
-    ifTrue();
-    _flow.ifStatement_end(false);
-  }
-
-  /// Invokes flow analysis of an `if` statement with an `else` part.
-  void ifElse(LazyExpression cond, void ifTrue(), void ifFalse()) {
-    _flow.ifStatement_thenBegin(cond());
-    ifTrue();
-    _flow.ifStatement_elseBegin();
-    ifFalse();
-    _flow.ifStatement_end(true);
-  }
-
-  /// Creates a [LazyExpression] representing an `is!` check, checking whether
-  /// [variable] has the given [type].
-  LazyExpression isNotType(_Var variable, String type) {
-    return () {
-      var expr = _Expression();
-      _flow.isExpression_end(expr, variable, true, _Type(type));
-      return expr;
-    };
-  }
-
-  @override
-  bool isSameType(_Type type1, _Type type2) {
-    return type1.type == type2.type;
-  }
-
-  @override
-  bool isSubtypeOf(_Type leftType, _Type rightType) {
-    const Map<String, bool> _subtypes = const {
-      'int <: int?': true,
-      'int <: Object': true,
-      'int <: Object?': true,
-      'int <: String': false,
-      'int? <: int': false,
-      'int? <: Object?': true,
-      'Object <: int': false,
-      'String <: int': false,
-      'String <: int?': false,
-      'String <: Object?': true,
-    };
-
-    if (leftType.type == rightType.type) return true;
-    var query = '$leftType <: $rightType';
-    return _subtypes[query] ?? fail('Unknown subtype query: $query');
-  }
-
-  /// Creates a [LazyExpression] representing an `is` check, checking whether
-  /// [variable] has the given [type].
-  LazyExpression isType(_Var variable, String type) {
-    return () {
-      var expr = _Expression();
-      _flow.isExpression_end(expr, variable, false, _Type(type));
-      return expr;
-    };
-  }
-
-  /// Creates a [LazyExpression] representing a `!= null` check performed on
-  /// [variable].
-  LazyExpression notNull(_Var variable) {
-    return () {
-      var varExpr = _Expression();
-      _flow.variableRead(varExpr, variable);
-      _flow.equalityOp_rightBegin(varExpr);
-      var nullExpr = _Expression();
-      _flow.nullLiteral(nullExpr);
-      var expr = _Expression();
-      _flow.equalityOp_end(expr, nullExpr, notEqual: true);
-      return expr;
-    };
-  }
-
-  /// Given two [LazyExpression]s, produces a new [LazyExpression] representing
-  /// the result of combining them with `||`.
-  LazyExpression or(LazyExpression lhs, LazyExpression rhs) {
-    return () {
-      var expr = _Expression();
-      _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: false);
-      _flow.logicalBinaryOp_end(expr, rhs(), isAnd: false);
-      return expr;
-    };
-  }
-
-  /// Creates a [LazyExpression] representing a parenthesized subexpression.
-  LazyExpression parenthesized(LazyExpression inner) {
-    return () {
-      var expr = _Expression();
-      _flow.parenthesizedExpression(expr, inner());
-      return expr;
-    };
-  }
-
-  /// Causes [variable] to be promoted to [type].
-  void promote(_Var variable, String type) {
-    if_(isNotType(variable, type), _flow.handleExit);
-  }
-
-  @override
-  _Type promoteToNonNull(_Type type) {
-    if (type.type.endsWith('?')) {
-      return _Type(type.type.substring(0, type.type.length - 1));
-    } else {
-      return type;
-    }
-  }
-
-  void run(
-      void callback(FlowAnalysis<_Statement, _Expression, _Var, _Type> flow)) {
-    assert(_flow == null);
-    _flow = createFlow();
-    callback(_flow);
-    _flow.finish();
-  }
-
-  LazyExpression variableRead(_Var variable) {
-    return () {
-      var expr = _Expression();
-      _flow.variableRead(expr, variable);
-      return expr;
-    };
-  }
-
-  @override
-  _Type variableType(_Var variable) {
-    return variable.type;
-  }
-}
-
-class _Statement {}
-
-class _Type {
-  static bool _allowingTypeComparisons = false;
-
-  final String type;
-
-  _Type(this.type);
-
-  @override
-  bool operator ==(Object other) {
-    if (_allowingTypeComparisons) {
-      return other is _Type && other.type == this.type;
-    } else {
-      // The flow analysis engine should not compare types using operator==.  It
-      // should compare them using TypeOperations.
-      fail('Unexpected use of operator== on types');
-    }
-  }
-
-  @override
-  String toString() => type;
-
-  static T allowComparisons<T>(T callback()) {
-    var oldAllowingTypeComparisons = _allowingTypeComparisons;
-    _allowingTypeComparisons = true;
-    try {
-      return callback();
-    } finally {
-      _allowingTypeComparisons = oldAllowingTypeComparisons;
-    }
-  }
-}
-
-class _Var {
-  final String name;
-
-  final _Type type;
-
-  _Var(this.name, this.type);
-
-  @override
-  String toString() => '$type $name';
-}
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 be1e524..f9e37c9 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -4,6 +4,9 @@
 
 /// Test of toString on generators.
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show Token, scanString;
+
 import 'package:expect/expect.dart' show Expect;
 
 import 'package:kernel/ast.dart'
@@ -47,8 +50,6 @@
 
 import 'package:front_end/src/fasta/kernel/body_builder.dart' show BodyBuilder;
 
-import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
-
 import 'package:front_end/src/fasta/source/source_library_builder.dart'
     show SourceLibraryBuilder;
 
@@ -99,7 +100,8 @@
         isDeclarationInstanceMember: false,
         uri: uri);
 
-    Generator generator = new ThisAccessGenerator(helper, token, false, false);
+    Generator generator =
+        new ThisAccessGenerator(helper, token, false, false, false);
 
     Library library = new Library(uri);
     Class cls = new Class();
@@ -127,21 +129,15 @@
         new VariableUseGenerator(helper, token, variable, type));
     check(
         "PropertyAccessGenerator(offset: 4,"
-        " receiver: expression, name: bar, getter: $uri::myGetter,"
-        " setter: $uri::mySetter)",
-        new PropertyAccessGenerator(
-            helper, token, expression, name, getter, setter));
-    check(
-        "ThisPropertyAccessGenerator(offset: 4, name: bar,"
-        " getter: $uri::myGetter, setter: $uri::mySetter)",
-        new ThisPropertyAccessGenerator(helper, token, name, getter, setter));
+        " receiver: expression, name: bar)",
+        new PropertyAccessGenerator(helper, token, expression, name));
+    check("ThisPropertyAccessGenerator(offset: 4, name: bar)",
+        new ThisPropertyAccessGenerator(helper, token, name));
     check(
         "NullAwarePropertyAccessGenerator(offset: 4,"
         " receiver: final dynamic #t1 = expression;\n,"
-        " receiverExpression: expression, name: bar, getter: $uri::myGetter,"
-        " setter: $uri::mySetter, type: void)",
-        new NullAwarePropertyAccessGenerator(
-            helper, token, expression, name, getter, setter, type));
+        " receiverExpression: expression, name: bar)",
+        new NullAwarePropertyAccessGenerator(helper, token, expression, name));
     check(
         "SuperPropertyAccessGenerator(offset: 4, name: bar,"
         " getter: $uri::myGetter, setter: $uri::mySetter)",
@@ -170,8 +166,9 @@
         new LoadLibraryGenerator(helper, token, loadLibraryBuilder));
     check(
         "ThisAccessGenerator(offset: 4, isInitializer: false, "
-        "inFieldInitializer: false, isSuper: false)",
-        new ThisAccessGenerator(helper, token, false, false));
+        "inFieldInitializer: false, inLateFieldInitializer: false, "
+        "isSuper: false)",
+        new ThisAccessGenerator(helper, token, false, false, false));
     check("IncompleteErrorGenerator(offset: 4, message: Unspecified)",
         new IncompleteErrorGenerator(helper, token, message));
     check("SendAccessGenerator(offset: 4, name: bar, arguments: (\"arg\"))",
@@ -183,7 +180,8 @@
         " prefixGenerator: PrefixUseGenerator("
         "offset: 4, prefix: myPrefix, deferred: false),"
         " suffixGenerator: ThisAccessGenerator(offset: 4, isInitializer: false,"
-        " inFieldInitializer: false, isSuper: false))",
+        " inFieldInitializer: false, inLateFieldInitializer: false,"
+        " isSuper: false))",
         new DeferredAccessGenerator(
             helper, token, prefixUseGenerator, generator));
     check(
@@ -207,7 +205,8 @@
     check(
         "UnexpectedQualifiedUseGenerator("
         "offset: 4, prefixGenerator: , isInitializer: false,"
-        " inFieldInitializer: false, isSuper: false)",
+        " inFieldInitializer: false, inLateFieldInitializer: false,"
+        " isSuper: false)",
         new UnexpectedQualifiedUseGenerator(helper, token, generator, false));
     return Future<void>.value();
   });
diff --git a/pkg/front_end/test/fasta/incremental_suite.dart b/pkg/front_end/test/fasta/incremental_suite.dart
new file mode 100644
index 0000000..a1403c3
--- /dev/null
+++ b/pkg/front_end/test/fasta/incremental_suite.dart
@@ -0,0 +1,248 @@
+// 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.md file.
+
+library fasta.test.incremental_test;
+
+import "dart:async" show Future;
+
+import "dart:convert" show JsonEncoder;
+
+import "dart:io" show File;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import "package:kernel/ast.dart" show Component;
+
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import "package:testing/src/log.dart" show splitLines;
+
+import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;
+
+import "package:front_end/src/api_prototype/compiler_options.dart"
+    show CompilerOptions, DiagnosticMessage;
+
+import "package:front_end/src/api_prototype/incremental_kernel_generator.dart"
+    show IncrementalKernelGenerator;
+
+import "package:front_end/src/api_prototype/memory_file_system.dart"
+    show MemoryFileSystem;
+
+import "package:front_end/src/api_prototype/terminal_color_support.dart"
+    show printDiagnosticMessage;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+import 'package:front_end/src/external_state_snapshot.dart'
+    show ExternalStateSnapshot;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
+import "incremental_expectations.dart"
+    show IncrementalExpectation, extractJsonExpectations;
+
+import "incremental_source_files.dart" show expandDiff, expandUpdates;
+
+const JsonEncoder json = const JsonEncoder.withIndent("  ");
+
+final Uri base = Uri.parse("org-dartlang-test:///");
+
+final Uri entryPoint = base.resolve("main.dart");
+
+class Context extends ChainContext {
+  final CompilerContext compilerContext;
+  final ExternalStateSnapshot snapshot;
+  final List<DiagnosticMessage> errors;
+
+  final List<Step> steps = const <Step>[
+    const ReadTest(),
+    const RunCompilations(),
+  ];
+
+  final IncrementalKernelGenerator compiler;
+
+  Context(this.compilerContext, this.snapshot, this.errors)
+      : compiler = new IncrementalCompiler(compilerContext);
+
+  ProcessedOptions get options => compilerContext.options;
+
+  MemoryFileSystem get fileSystem => options.fileSystem;
+
+  Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
+    return compilerContext.runInContext<T>(action);
+  }
+
+  void reset() {
+    errors.clear();
+    snapshot.restore();
+  }
+
+  List<DiagnosticMessage> takeErrors() {
+    List<DiagnosticMessage> result = new List<DiagnosticMessage>.from(errors);
+    errors.clear();
+    return result;
+  }
+}
+
+class ReadTest extends Step<TestDescription, TestCase, Context> {
+  const ReadTest();
+
+  String get name => "read test";
+
+  Future<Result<TestCase>> run(
+      TestDescription description, Context context) async {
+    context.reset();
+    Uri uri = description.uri;
+    String contents = await new File.fromUri(uri).readAsString();
+    Map<String, List<String>> sources = <String, List<String>>{};
+    List<IncrementalExpectation> expectations;
+    bool firstPatch = true;
+    YamlMap map = loadYamlNode(contents, sourceUrl: uri);
+    map.forEach((_fileName, _contents) {
+      String fileName = _fileName; // Strong mode hurray!
+      String contents = _contents; // Strong mode hurray!
+      if (fileName.endsWith(".patch")) {
+        fileName = fileName.substring(0, fileName.length - ".patch".length);
+        if (firstPatch) {
+          expectations = extractJsonExpectations(contents);
+        }
+        sources[fileName] = expandUpdates(expandDiff(contents));
+        firstPatch = false;
+      } else {
+        sources[fileName] = <String>[contents];
+      }
+    });
+    final TestCase test = new TestCase(description, sources, expectations);
+    return test.validate(this);
+  }
+}
+
+class RunCompilations extends Step<TestCase, TestCase, Context> {
+  const RunCompilations();
+
+  String get name => "run compilations";
+
+  Future<Result<TestCase>> run(TestCase test, Context context) async {
+    for (int edits = 0;; edits++) {
+      bool foundSources = false;
+      test.sources.forEach((String name, List<String> sources) {
+        if (edits < sources.length) {
+          String source = sources[edits];
+          Uri uri = base.resolve(name);
+          context.fileSystem.entityForUri(uri).writeAsStringSync(source);
+          foundSources = true;
+          context.compiler.invalidate(uri);
+          if (edits == 0) {
+            print("==> $uri <==");
+          } else {
+            print("==> $uri (edit #$edits) <==");
+          }
+          print(source.trimRight());
+        }
+      });
+      if (!foundSources) {
+        return edits == 0 ? fail(test, "No sources found") : pass(test);
+      }
+      var compiler = context.compiler;
+      Component component =
+          await compiler.computeDelta(entryPoints: [entryPoint]);
+      List<DiagnosticMessage> errors = context.takeErrors();
+      if (test.expectations[edits].hasCompileTimeError) {
+        if (errors.isEmpty) {
+          return fail(test, "Compile-time error expected, but none reported");
+        }
+      } else if (errors.isNotEmpty) {
+        String indentedErrors =
+            splitLines(errors.map((e) => e.ansiFormatted.join("\n")).join("\n"))
+                .join("  ");
+        return fail(test, "Unexpected compile-time errors:\n  $indentedErrors");
+      } else if (component.libraries.length < 1) {
+        return fail(test, "The compiler detected no changes");
+      }
+    }
+  }
+}
+
+class TestCase {
+  final TestDescription description;
+
+  final Map<String, List<String>> sources;
+
+  final List<IncrementalExpectation> expectations;
+
+  TestCase(this.description, this.sources, this.expectations);
+
+  String toString() {
+    return "TestCase(${json.convert(sources)}, ${json.convert(expectations)})";
+  }
+
+  Result<TestCase> validate(Step<dynamic, TestCase, ChainContext> step) {
+    print(this);
+    if (sources == null) {
+      return step.fail(this, "No sources.");
+    }
+    if (expectations == null || expectations.isEmpty) {
+      return step.fail(this, "No expectations.");
+    }
+    for (String name in sources.keys) {
+      List<String> versions = sources[name];
+      if (versions.length != 1 && versions.length != expectations.length) {
+        return step.fail(
+            this,
+            "Found ${versions.length} versions of $name,"
+            " but expected 1 or ${expectations.length}.");
+      }
+    }
+    return step.pass(this);
+  }
+}
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  /// The custom URI used to locate the dill file in the MemoryFileSystem.
+  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+
+  /// The actual location of the dill file.
+  final Uri sdkSummaryFile =
+      computePlatformBinariesLocation(forceBuildDir: true)
+          .resolve("vm_platform_strong.dill");
+
+  final MemoryFileSystem fs = new MemoryFileSystem(base);
+
+  fs
+      .entityForUri(sdkSummary)
+      .writeAsBytesSync(await new File.fromUri(sdkSummaryFile).readAsBytes());
+
+  final List<DiagnosticMessage> errors = <DiagnosticMessage>[];
+
+  final CompilerOptions optionBuilder = new CompilerOptions()
+    ..verbose = true
+    ..fileSystem = fs
+    ..sdkSummary = sdkSummary
+    ..onDiagnostic = (DiagnosticMessage message) {
+      printDiagnosticMessage(message, print);
+      if (message.severity == Severity.error) {
+        errors.add(message);
+      }
+    };
+
+  final ProcessedOptions options =
+      new ProcessedOptions(options: optionBuilder, inputs: [entryPoint]);
+
+  final ExternalStateSnapshot snapshot =
+      new ExternalStateSnapshot(await options.loadSdkSummary(null));
+
+  return new Context(new CompilerContext(options), snapshot, errors);
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/incremental_test.dart b/pkg/front_end/test/fasta/incremental_test.dart
deleted file mode 100644
index 3b22af2..0000000
--- a/pkg/front_end/test/fasta/incremental_test.dart
+++ /dev/null
@@ -1,248 +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.md file.
-
-library fasta.test.incremental_test;
-
-import "dart:async" show Future;
-
-import "dart:convert" show JsonEncoder;
-
-import "dart:io" show File;
-
-import "package:kernel/ast.dart" show Component;
-
-import "package:testing/testing.dart"
-    show Chain, ChainContext, Result, Step, TestDescription, runMe;
-
-import "package:testing/src/log.dart" show splitLines;
-
-import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;
-
-import "package:front_end/src/api_prototype/compiler_options.dart"
-    show CompilerOptions, DiagnosticMessage;
-
-import "package:front_end/src/api_prototype/incremental_kernel_generator.dart"
-    show IncrementalKernelGenerator;
-
-import "package:front_end/src/api_prototype/memory_file_system.dart"
-    show MemoryFileSystem;
-
-import "package:front_end/src/api_prototype/terminal_color_support.dart"
-    show printDiagnosticMessage;
-
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-
-import 'package:front_end/src/external_state_snapshot.dart'
-    show ExternalStateSnapshot;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/incremental_compiler.dart'
-    show IncrementalCompiler;
-
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
-import "incremental_expectations.dart"
-    show IncrementalExpectation, extractJsonExpectations;
-
-import "incremental_source_files.dart" show expandDiff, expandUpdates;
-
-const JsonEncoder json = const JsonEncoder.withIndent("  ");
-
-final Uri base = Uri.parse("org-dartlang-test:///");
-
-final Uri entryPoint = base.resolve("main.dart");
-
-class Context extends ChainContext {
-  final CompilerContext compilerContext;
-  final ExternalStateSnapshot snapshot;
-  final List<DiagnosticMessage> errors;
-
-  final List<Step> steps = const <Step>[
-    const ReadTest(),
-    const RunCompilations(),
-  ];
-
-  final IncrementalKernelGenerator compiler;
-
-  Context(this.compilerContext, this.snapshot, this.errors)
-      : compiler = new IncrementalCompiler(compilerContext);
-
-  ProcessedOptions get options => compilerContext.options;
-
-  MemoryFileSystem get fileSystem => options.fileSystem;
-
-  Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
-    return compilerContext.runInContext<T>(action);
-  }
-
-  void reset() {
-    errors.clear();
-    snapshot.restore();
-  }
-
-  List<DiagnosticMessage> takeErrors() {
-    List<DiagnosticMessage> result = new List<DiagnosticMessage>.from(errors);
-    errors.clear();
-    return result;
-  }
-}
-
-class ReadTest extends Step<TestDescription, TestCase, Context> {
-  const ReadTest();
-
-  String get name => "read test";
-
-  Future<Result<TestCase>> run(
-      TestDescription description, Context context) async {
-    context.reset();
-    Uri uri = description.uri;
-    String contents = await new File.fromUri(uri).readAsString();
-    Map<String, List<String>> sources = <String, List<String>>{};
-    List<IncrementalExpectation> expectations;
-    bool firstPatch = true;
-    YamlMap map = loadYamlNode(contents, sourceUrl: uri);
-    map.forEach((_fileName, _contents) {
-      String fileName = _fileName; // Strong mode hurray!
-      String contents = _contents; // Strong mode hurray!
-      if (fileName.endsWith(".patch")) {
-        fileName = fileName.substring(0, fileName.length - ".patch".length);
-        if (firstPatch) {
-          expectations = extractJsonExpectations(contents);
-        }
-        sources[fileName] = expandUpdates(expandDiff(contents));
-        firstPatch = false;
-      } else {
-        sources[fileName] = <String>[contents];
-      }
-    });
-    final TestCase test = new TestCase(description, sources, expectations);
-    return test.validate(this);
-  }
-}
-
-class RunCompilations extends Step<TestCase, TestCase, Context> {
-  const RunCompilations();
-
-  String get name => "run compilations";
-
-  Future<Result<TestCase>> run(TestCase test, Context context) async {
-    for (int edits = 0;; edits++) {
-      bool foundSources = false;
-      test.sources.forEach((String name, List<String> sources) {
-        if (edits < sources.length) {
-          String source = sources[edits];
-          Uri uri = base.resolve(name);
-          context.fileSystem.entityForUri(uri).writeAsStringSync(source);
-          foundSources = true;
-          context.compiler.invalidate(uri);
-          if (edits == 0) {
-            print("==> $uri <==");
-          } else {
-            print("==> $uri (edit #$edits) <==");
-          }
-          print(source.trimRight());
-        }
-      });
-      if (!foundSources) {
-        return edits == 0 ? fail(test, "No sources found") : pass(test);
-      }
-      var compiler = context.compiler;
-      Component component =
-          await compiler.computeDelta(entryPoints: [entryPoint]);
-      List<DiagnosticMessage> errors = context.takeErrors();
-      if (test.expectations[edits].hasCompileTimeError) {
-        if (errors.isEmpty) {
-          return fail(test, "Compile-time error expected, but none reported");
-        }
-      } else if (errors.isNotEmpty) {
-        String indentedErrors =
-            splitLines(errors.map((e) => e.ansiFormatted.join("\n")).join("\n"))
-                .join("  ");
-        return fail(test, "Unexpected compile-time errors:\n  $indentedErrors");
-      } else if (component.libraries.length < 1) {
-        return fail(test, "The compiler detected no changes");
-      }
-    }
-  }
-}
-
-class TestCase {
-  final TestDescription description;
-
-  final Map<String, List<String>> sources;
-
-  final List<IncrementalExpectation> expectations;
-
-  TestCase(this.description, this.sources, this.expectations);
-
-  String toString() {
-    return "TestCase(${json.convert(sources)}, ${json.convert(expectations)})";
-  }
-
-  Result<TestCase> validate(Step<dynamic, TestCase, ChainContext> step) {
-    print(this);
-    if (sources == null) {
-      return step.fail(this, "No sources.");
-    }
-    if (expectations == null || expectations.isEmpty) {
-      return step.fail(this, "No expectations.");
-    }
-    for (String name in sources.keys) {
-      List<String> versions = sources[name];
-      if (versions.length != 1 && versions.length != expectations.length) {
-        return step.fail(
-            this,
-            "Found ${versions.length} versions of $name,"
-            " but expected 1 or ${expectations.length}.");
-      }
-    }
-    return step.pass(this);
-  }
-}
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  /// The custom URI used to locate the dill file in the MemoryFileSystem.
-  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
-
-  /// The actual location of the dill file.
-  final Uri sdkSummaryFile =
-      computePlatformBinariesLocation(forceBuildDir: true)
-          .resolve("vm_platform_strong.dill");
-
-  final MemoryFileSystem fs = new MemoryFileSystem(base);
-
-  fs
-      .entityForUri(sdkSummary)
-      .writeAsBytesSync(await new File.fromUri(sdkSummaryFile).readAsBytes());
-
-  final List<DiagnosticMessage> errors = <DiagnosticMessage>[];
-
-  final CompilerOptions optionBuilder = new CompilerOptions()
-    ..verbose = true
-    ..fileSystem = fs
-    ..sdkSummary = sdkSummary
-    ..onDiagnostic = (DiagnosticMessage message) {
-      printDiagnosticMessage(message, print);
-      if (message.severity == Severity.error) {
-        errors.add(message);
-      }
-    };
-
-  final ProcessedOptions options =
-      new ProcessedOptions(options: optionBuilder, inputs: [entryPoint]);
-
-  final ExternalStateSnapshot snapshot =
-      new ExternalStateSnapshot(await options.loadSdkSummary(null));
-
-  return new Context(new CompilerContext(options), snapshot, errors);
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/link_test.dart b/pkg/front_end/test/fasta/link_test.dart
index 5fe7b42..1eec73e 100644
--- a/pkg/front_end/test/fasta/link_test.dart
+++ b/pkg/front_end/test/fasta/link_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.
 
-import 'package:front_end/src/fasta/util/link.dart' show Link, LinkBuilder;
+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
new file mode 100644
index 0000000..b849547
--- /dev/null
+++ b/pkg/front_end/test/fasta/messages_suite.dart
@@ -0,0 +1,682 @@
+// 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 "dart:async" show Future, Stream;
+
+import "dart:convert" show utf8;
+
+import "dart:io" show File;
+
+import "dart:typed_data" show Uint8List;
+
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, getMessageCodeObject;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart'
+    show Severity, severityEnumValues;
+
+import 'package:kernel/ast.dart' show Location, Source;
+
+import "package:kernel/target/targets.dart" show TargetFlags;
+
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import "package:vm/target/vm.dart" show VmTarget;
+
+import "package:yaml/yaml.dart" show YamlList, YamlMap, YamlNode, loadYamlNode;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show CompilerOptions;
+
+import 'package:front_end/src/api_prototype/memory_file_system.dart'
+    show MemoryFileSystem;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+import 'package:front_end/src/fasta/command_line_reporting.dart'
+    as command_line_reporting;
+
+import 'package:front_end/src/fasta/hybrid_file_system.dart'
+    show HybridFileSystem;
+
+import "../../tool/_fasta/entry_points.dart" show BatchCompiler;
+
+import '../spell_checking_utils.dart' as spell;
+
+class MessageTestDescription extends TestDescription {
+  @override
+  final Uri uri;
+
+  @override
+  final String shortName;
+
+  final String name;
+
+  final YamlMap data;
+
+  final Example example;
+
+  final String problem;
+
+  MessageTestDescription(this.uri, this.shortName, this.name, this.data,
+      this.example, this.problem);
+}
+
+class MessageTestSuite extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const Validate(),
+    const Compile(),
+  ];
+
+  final MemoryFileSystem fileSystem;
+
+  final BatchCompiler compiler;
+
+  final bool fastOnly;
+
+  MessageTestSuite(this.fastOnly)
+      : fileSystem = new MemoryFileSystem(Uri.parse("org-dartlang-fasta:///")),
+        compiler = new BatchCompiler(null);
+
+  /// Convert all the examples found in `messages.yaml` to a test
+  /// description. In addition, create a test description for each kind of
+  /// problem that a message can have. This problem will then be reported as a
+  /// failure by the [Validate] step that can be suppressed via the status
+  /// file.
+  Stream<MessageTestDescription> list(Chain suite) async* {
+    Uri uri = suite.uri.resolve("messages.yaml");
+    File file = new File.fromUri(uri);
+    String fileContent = file.readAsStringSync();
+    YamlMap messages = loadYamlNode(fileContent, sourceUrl: uri);
+    for (String name in messages.keys) {
+      YamlNode messageNode = messages.nodes[name];
+      var message = messageNode.value;
+      if (message is String) continue;
+
+      List<String> unknownKeys = <String>[];
+      List<Example> examples = <Example>[];
+      String externalTest;
+      bool frontendInternal = false;
+      List<String> analyzerCodes;
+      Severity severity;
+      YamlNode badSeverity;
+      YamlNode unnecessarySeverity;
+      List<String> badHasPublishedDocsValue = <String>[];
+      List<String> spellingMessages;
+      const String spellingPostMessage = "\nIf the word(s) look okay, update "
+          "'spell_checking_list_messages.txt' or "
+          "'spell_checking_list_common.txt'.";
+
+      Source source;
+      List<String> formatSpellingMistakes(
+          spell.SpellingResult spellResult, int offset, String message) {
+        if (source == null) {
+          List<int> bytes = file.readAsBytesSync();
+          List<int> lineStarts = new List<int>();
+          int indexOf = 0;
+          while (indexOf >= 0) {
+            lineStarts.add(indexOf);
+            indexOf = bytes.indexOf(10, indexOf + 1);
+          }
+          lineStarts.add(bytes.length);
+          source = new Source(lineStarts, bytes, uri, uri);
+        }
+        List<String> result = new List<String>();
+        for (int i = 0; i < spellResult.misspelledWords.length; i++) {
+          Location location = source.getLocation(
+              uri, offset + spellResult.misspelledWordsOffset[i]);
+          result.add(command_line_reporting.formatErrorMessage(
+              source.getTextLine(location.line),
+              location,
+              spellResult.misspelledWords[i].length,
+              relativize(uri),
+              "$message: '${spellResult.misspelledWords[i]}'."));
+        }
+        return result;
+      }
+
+      for (String key in message.keys) {
+        YamlNode node = message.nodes[key];
+        var value = node.value;
+        // When positions matter, use node.span.text.
+        // When using node.span.text, replace r"\n" with "\n\n" to replace two
+        // characters with two characters without actually having the string
+        // "backslash n".
+        switch (key) {
+          case "template":
+            spell.SpellingResult spellingResult = spell.spellcheckString(
+                node.span.text.replaceAll(r"\n", "\n\n"),
+                dictionaries: const [
+                  spell.Dictionaries.common,
+                  spell.Dictionaries.cfeMessages
+                ]);
+            if (spellingResult.misspelledWords != null) {
+              spellingMessages ??= new List<String>();
+              spellingMessages.addAll(formatSpellingMistakes(
+                  spellingResult,
+                  node.span.start.offset,
+                  "Template likely has the following spelling mistake"));
+            }
+            break;
+
+          case "tip":
+            spell.SpellingResult spellingResult = spell.spellcheckString(
+                node.span.text.replaceAll(r"\n", "\n\n"),
+                dictionaries: const [
+                  spell.Dictionaries.common,
+                  spell.Dictionaries.cfeMessages
+                ]);
+            if (spellingResult.misspelledWords != null) {
+              spellingMessages ??= new List<String>();
+              spellingMessages.addAll(formatSpellingMistakes(
+                  spellingResult,
+                  node.span.start.offset,
+                  "Tip likely has the following spelling mistake"));
+            }
+            break;
+
+          case "severity":
+            severity = severityEnumValues[value];
+            if (severity == null) {
+              badSeverity = node;
+            } else if (severity == Severity.error) {
+              unnecessarySeverity = node;
+            }
+            break;
+
+          case "frontendInternal":
+            frontendInternal = value;
+            break;
+
+          case "analyzerCode":
+            analyzerCodes = value is String
+                ? <String>[value]
+                : new List<String>.from(value);
+            break;
+
+          case "bytes":
+            YamlList list = node;
+            if (list.first is List) {
+              for (YamlList bytes in list.nodes) {
+                int i = 0;
+                examples.add(new BytesExample("bytes${++i}", name, bytes));
+              }
+            } else {
+              examples.add(new BytesExample("bytes", name, list));
+            }
+            break;
+
+          case "declaration":
+            if (node is YamlList) {
+              int i = 0;
+              for (YamlNode declaration in node.nodes) {
+                examples.add(new DeclarationExample(
+                    "declaration${++i}", name, declaration));
+              }
+            } else {
+              examples.add(new DeclarationExample("declaration", name, node));
+            }
+            break;
+
+          case "expression":
+            if (node is YamlList) {
+              int i = 0;
+              for (YamlNode expression in node.nodes) {
+                examples.add(new ExpressionExample(
+                    "expression${++i}", name, expression));
+              }
+            } else {
+              examples.add(new ExpressionExample("expression", name, node));
+            }
+            break;
+
+          case "script":
+            if (node is YamlList) {
+              int i = 0;
+              for (YamlNode script in node.nodes) {
+                examples
+                    .add(new ScriptExample("script${++i}", name, script, this));
+              }
+            } else {
+              examples.add(new ScriptExample("script", name, node, this));
+            }
+            break;
+
+          case "statement":
+            if (node is YamlList) {
+              int i = 0;
+              for (YamlNode statement in node.nodes) {
+                examples.add(
+                    new StatementExample("statement${++i}", name, statement));
+              }
+            } else {
+              examples.add(new StatementExample("statement", name, node));
+            }
+            break;
+
+          case "external":
+            externalTest = node.value;
+            break;
+
+          case "index":
+            // index is validated during generation
+            break;
+
+          case "hasPublishedDocs":
+            if (value != true) {
+              badHasPublishedDocsValue.add(name);
+            }
+            break;
+
+          default:
+            unknownKeys.add(key);
+        }
+      }
+
+      MessageTestDescription createDescription(
+          String subName, Example example, String problem,
+          {location}) {
+        String shortName = "$name/$subName";
+        if (problem != null) {
+          String filename = relativize(uri);
+          location ??= message.span.start;
+          int line = location.line + 1;
+          int column = location.column;
+          problem = "$filename:$line:$column: error:\n$problem";
+        }
+        return new MessageTestDescription(uri.resolve("#$shortName"), shortName,
+            name, messageNode, example, problem);
+      }
+
+      if (!fastOnly) {
+        for (Example example in examples) {
+          yield createDescription(example.name, example, null);
+        }
+        // "Wrap" example as a part.
+        for (Example example in examples) {
+          yield createDescription(
+              "part_wrapped_${example.name}",
+              new PartWrapExample(
+                  "part_wrapped_${example.name}", name, example),
+              null);
+        }
+      }
+
+      yield createDescription(
+          "knownKeys",
+          null,
+          unknownKeys.isNotEmpty
+              ? "Unknown keys: ${unknownKeys.join(' ')}."
+              : null);
+
+      yield createDescription(
+          'hasPublishedDocs',
+          null,
+          badHasPublishedDocsValue.isNotEmpty
+              ? "Bad hasPublishedDocs value (only 'true' supported) in:"
+                  " ${badHasPublishedDocsValue.join(', ')}"
+              : null);
+
+      yield createDescription(
+          "severity",
+          null,
+          badSeverity != null
+              ? "Unknown severity: '${badSeverity.value}'."
+              : null,
+          location: badSeverity?.span?.start);
+
+      yield createDescription(
+          "unnecessarySeverity",
+          null,
+          unnecessarySeverity != null
+              ? "The 'ERROR' severity is the default and not necessary."
+              : null,
+          location: unnecessarySeverity?.span?.start);
+
+      yield createDescription(
+          "spelling",
+          null,
+          spellingMessages != null
+              ? spellingMessages.join("\n") + spellingPostMessage
+              : null);
+
+      bool exampleAndAnalyzerCodeRequired = severity != Severity.context &&
+          severity != Severity.internalProblem &&
+          severity != Severity.ignored;
+
+      yield createDescription(
+          "externalExample",
+          null,
+          exampleAndAnalyzerCodeRequired &&
+                  externalTest != null &&
+                  !(new File.fromUri(suite.uri.resolve(externalTest))
+                      .existsSync())
+              ? "Given external example for $name points to a nonexisting file "
+                  "(${suite.uri.resolve(externalTest)})."
+              : null);
+
+      yield createDescription(
+          "example",
+          null,
+          exampleAndAnalyzerCodeRequired &&
+                  examples.isEmpty &&
+                  externalTest == null
+              ? "No example for $name, please add at least one example."
+              : null);
+
+      yield createDescription(
+          "analyzerCode",
+          null,
+          exampleAndAnalyzerCodeRequired &&
+                  !frontendInternal &&
+                  analyzerCodes == null
+              ? "No analyzer code for $name."
+                  "\nTry running"
+                  " <BUILDDIR>/dart-sdk/bin/dartanalyzer --format=machine"
+                  " on an example to find the code."
+                  " The code is printed just before the file name."
+              : null);
+    }
+  }
+
+  String formatProblems(
+      String message, Example example, List<DiagnosticMessage> messages) {
+    var span = example.node.span;
+    StringBuffer buffer = new StringBuffer();
+    buffer
+      ..write(relativize(span.sourceUrl))
+      ..write(":")
+      ..write(span.start.line + 1)
+      ..write(":")
+      ..write(span.start.column)
+      ..write(": error: ")
+      ..write(message);
+    buffer.write("\n${span.text}");
+    for (DiagnosticMessage message in messages) {
+      buffer.write("\nCode: ${getMessageCodeObject(message).name}");
+      buffer.write("\n  > ");
+      buffer.write(
+          message.plainTextFormatted.join("\n").replaceAll("\n", "\n  > "));
+    }
+
+    return "$buffer";
+  }
+}
+
+abstract class Example {
+  final String name;
+
+  final String expectedCode;
+
+  Example(this.name, this.expectedCode);
+
+  YamlNode get node;
+
+  Uint8List get bytes;
+
+  Map<String, Uint8List> get scripts {
+    return {mainFilename: bytes};
+  }
+
+  String get mainFilename => "main.dart";
+}
+
+class BytesExample extends Example {
+  @override
+  final YamlList node;
+
+  @override
+  final Uint8List bytes;
+
+  BytesExample(String name, String code, this.node)
+      : bytes = new Uint8List.fromList(node.cast<int>()),
+        super(name, code);
+}
+
+class DeclarationExample extends Example {
+  @override
+  final YamlNode node;
+
+  final String declaration;
+
+  DeclarationExample(String name, String code, this.node)
+      : declaration = node.value,
+        super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+$declaration
+
+main() {
+}
+"""));
+  }
+}
+
+class StatementExample extends Example {
+  @override
+  final YamlNode node;
+
+  final String statement;
+
+  StatementExample(String name, String code, this.node)
+      : statement = node.value,
+        super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+main() {
+  $statement
+}
+"""));
+  }
+}
+
+class ExpressionExample extends Example {
+  @override
+  final YamlNode node;
+
+  final String expression;
+
+  ExpressionExample(String name, String code, this.node)
+      : expression = node.value,
+        super(name, code);
+
+  @override
+  Uint8List get bytes {
+    return new Uint8List.fromList(utf8.encode("""
+main() {
+  $expression;
+}
+"""));
+  }
+}
+
+class ScriptExample extends Example {
+  @override
+  final YamlNode node;
+
+  final Object script;
+
+  ScriptExample(String name, String code, this.node, MessageTestSuite suite)
+      : script = node.value,
+        super(name, code) {
+    if (script is! String && script is! Map) {
+      throw suite.formatProblems(
+          "A script must be either a String or a Map in $code:",
+          this, <DiagnosticMessage>[]);
+    }
+  }
+
+  @override
+  Uint8List get bytes => throw "Unsupported: ScriptExample.bytes";
+
+  @override
+  Map<String, Uint8List> get scripts {
+    Object script = this.script;
+    if (script is Map) {
+      var scriptFiles = <String, Uint8List>{};
+      script.forEach((fileName, value) {
+        scriptFiles[fileName] = new Uint8List.fromList(utf8.encode(value));
+      });
+      return scriptFiles;
+    } else {
+      return {mainFilename: new Uint8List.fromList(utf8.encode(script))};
+    }
+  }
+}
+
+class PartWrapExample extends Example {
+  final Example example;
+  PartWrapExample(String name, String code, this.example) : super(name, code);
+
+  @override
+  Uint8List get bytes => throw "Unsupported: PartWrapExample.bytes";
+
+  @override
+  String get mainFilename => "main_wrapped.dart";
+
+  @override
+  Map<String, Uint8List> get scripts {
+    Map<String, Uint8List> wrapped = example.scripts;
+
+    var scriptFiles = <String, Uint8List>{};
+    scriptFiles.addAll(wrapped);
+
+    // Create a new main file
+    // TODO: Technically we should find a un-used name.
+    if (scriptFiles.containsKey(mainFilename)) {
+      throw "Framework failure: "
+          "Wanted to create wrapper file, but the file already exists!";
+    }
+    scriptFiles[mainFilename] = new Uint8List.fromList(utf8.encode("""
+      part "${example.mainFilename}";
+    """));
+
+    // Modify the original main file to be part of the wrapper and add lots of
+    // gunk so every actual position in the file is not a valid position in the
+    // wrapper.
+    scriptFiles[example.mainFilename] = new Uint8List.fromList(utf8.encode("""
+      part of "${mainFilename}";
+      // La la la la la la la la la la la la la.
+      // La la la la la la la la la la la la la.
+      // La la la la la la la la la la la la la.
+      // La la la la la la la la la la la la la.
+      // La la la la la la la la la la la la la.
+    """) + scriptFiles[example.mainFilename]);
+
+    return scriptFiles;
+  }
+
+  @override
+  YamlNode get node => example.node;
+}
+
+class Validate extends Step<MessageTestDescription, Example, MessageTestSuite> {
+  const Validate();
+
+  String get name => "validate";
+
+  Future<Result<Example>> run(
+      MessageTestDescription description, MessageTestSuite suite) async {
+    if (description.problem != null) {
+      return fail(null, description.problem);
+    } else {
+      return pass(description.example);
+    }
+  }
+}
+
+class Compile extends Step<Example, Null, MessageTestSuite> {
+  const Compile();
+
+  String get name => "compile";
+
+  Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
+    if (example == null) return pass(null);
+    String dir = "${example.expectedCode}/${example.name}";
+    example.scripts.forEach((String fileName, Uint8List bytes) {
+      Uri uri = suite.fileSystem.currentDirectory.resolve("$dir/$fileName");
+      suite.fileSystem.entityForUri(uri).writeAsBytesSync(bytes);
+    });
+    Uri main = suite.fileSystem.currentDirectory
+        .resolve("$dir/${example.mainFilename}");
+    Uri output =
+        suite.fileSystem.currentDirectory.resolve("$dir/main.dart.dill");
+
+    // Setup .packages if it doesn't exist.
+    Uri dotPackagesUri =
+        suite.fileSystem.currentDirectory.resolve("$dir/.packages");
+    if (!await suite.fileSystem.entityForUri(dotPackagesUri).exists()) {
+      suite.fileSystem.entityForUri(dotPackagesUri).writeAsBytesSync([]);
+    }
+
+    print("Compiling $main");
+    List<DiagnosticMessage> messages = <DiagnosticMessage>[];
+
+    await suite.compiler.batchCompile(
+        new CompilerOptions()
+          ..sdkSummary = computePlatformBinariesLocation(forceBuildDir: true)
+              .resolve("vm_platform_strong.dill")
+          ..target = new VmTarget(new TargetFlags())
+          ..fileSystem = new HybridFileSystem(suite.fileSystem)
+          ..packagesFileUri = dotPackagesUri
+          ..onDiagnostic = messages.add
+          ..environmentDefines = const {},
+        main,
+        output);
+
+    List<DiagnosticMessage> unexpectedMessages = <DiagnosticMessage>[];
+    for (DiagnosticMessage message in messages) {
+      if (getMessageCodeObject(message).name != example.expectedCode) {
+        unexpectedMessages.add(message);
+      }
+    }
+    if (unexpectedMessages.isEmpty) {
+      switch (messages.length) {
+        case 0:
+          return fail(
+              null,
+              suite.formatProblems("No message reported in ${example.name}:",
+                  example, messages));
+        case 1:
+          return pass(null);
+        default:
+          return fail(
+              null,
+              suite.formatProblems(
+                  "Message reported multiple times in ${example.name}:",
+                  example,
+                  messages));
+      }
+    }
+    return fail(
+        null,
+        suite.formatProblems("Too many messages reported in ${example.name}:",
+            example, messages));
+  }
+}
+
+Future<MessageTestSuite> createContext(
+    Chain suite, Map<String, String> environment) async {
+  final bool fastOnly = environment["fastOnly"] == "true";
+  return new MessageTestSuite(fastOnly);
+}
+
+String relativize(Uri uri) {
+  String base = "${Uri.base}";
+  String filename = "$uri";
+  if (filename.startsWith(base)) {
+    return filename.substring(base.length);
+  } else {
+    return filename;
+  }
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
deleted file mode 100644
index f749478..0000000
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ /dev/null
@@ -1,682 +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 "dart:async" show Future, Stream;
-
-import "dart:convert" show utf8;
-
-import "dart:io" show File;
-
-import "dart:typed_data" show Uint8List;
-
-import 'package:kernel/ast.dart' show Location, Source;
-
-import "package:kernel/target/targets.dart" show TargetFlags;
-
-import "package:testing/testing.dart"
-    show Chain, ChainContext, Result, Step, TestDescription, runMe;
-
-import "package:vm/target/vm.dart" show VmTarget;
-
-import "package:yaml/yaml.dart" show YamlList, YamlMap, YamlNode, loadYamlNode;
-
-import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
-
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, getMessageCodeObject;
-
-import 'package:front_end/src/api_prototype/memory_file_system.dart'
-    show MemoryFileSystem;
-
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-
-import 'package:front_end/src/fasta/command_line_reporting.dart'
-    as command_line_reporting;
-
-import 'package:front_end/src/fasta/severity.dart'
-    show Severity, severityEnumValues;
-
-import 'package:front_end/src/fasta/hybrid_file_system.dart'
-    show HybridFileSystem;
-
-import "../../tool/_fasta/entry_points.dart" show BatchCompiler;
-
-import '../spell_checking_utils.dart' as spell;
-
-class MessageTestDescription extends TestDescription {
-  @override
-  final Uri uri;
-
-  @override
-  final String shortName;
-
-  final String name;
-
-  final YamlMap data;
-
-  final Example example;
-
-  final String problem;
-
-  MessageTestDescription(this.uri, this.shortName, this.name, this.data,
-      this.example, this.problem);
-}
-
-class MessageTestSuite extends ChainContext {
-  final List<Step> steps = const <Step>[
-    const Validate(),
-    const Compile(),
-  ];
-
-  final MemoryFileSystem fileSystem;
-
-  final BatchCompiler compiler;
-
-  final bool fastOnly;
-
-  MessageTestSuite(this.fastOnly)
-      : fileSystem = new MemoryFileSystem(Uri.parse("org-dartlang-fasta:///")),
-        compiler = new BatchCompiler(null);
-
-  /// Convert all the examples found in `messages.yaml` to a test
-  /// description. In addition, create a test description for each kind of
-  /// problem that a message can have. This problem will then be reported as a
-  /// failure by the [Validate] step that can be suppressed via the status
-  /// file.
-  Stream<MessageTestDescription> list(Chain suite) async* {
-    Uri uri = suite.uri.resolve("messages.yaml");
-    File file = new File.fromUri(uri);
-    String fileContent = file.readAsStringSync();
-    YamlMap messages = loadYamlNode(fileContent, sourceUrl: uri);
-    for (String name in messages.keys) {
-      YamlNode messageNode = messages.nodes[name];
-      var message = messageNode.value;
-      if (message is String) continue;
-
-      List<String> unknownKeys = <String>[];
-      List<Example> examples = <Example>[];
-      String externalTest;
-      bool frontendInternal = false;
-      List<String> analyzerCodes;
-      Severity severity;
-      YamlNode badSeverity;
-      YamlNode unnecessarySeverity;
-      List<String> badHasPublishedDocsValue = <String>[];
-      List<String> spellingMessages;
-      const String spellingPostMessage = "\nIf the word(s) look okay, update "
-          "'spell_checking_list_messages.txt' or "
-          "'spell_checking_list_common.txt'.";
-
-      Source source;
-      List<String> formatSpellingMistakes(
-          spell.SpellingResult spellResult, int offset, String message) {
-        if (source == null) {
-          List<int> bytes = file.readAsBytesSync();
-          List<int> lineStarts = new List<int>();
-          int indexOf = 0;
-          while (indexOf >= 0) {
-            lineStarts.add(indexOf);
-            indexOf = bytes.indexOf(10, indexOf + 1);
-          }
-          lineStarts.add(bytes.length);
-          source = new Source(lineStarts, bytes, uri, uri);
-        }
-        List<String> result = new List<String>();
-        for (int i = 0; i < spellResult.misspelledWords.length; i++) {
-          Location location = source.getLocation(
-              uri, offset + spellResult.misspelledWordsOffset[i]);
-          result.add(command_line_reporting.formatErrorMessage(
-              source.getTextLine(location.line),
-              location,
-              spellResult.misspelledWords[i].length,
-              relativize(uri),
-              "$message: '${spellResult.misspelledWords[i]}'."));
-        }
-        return result;
-      }
-
-      for (String key in message.keys) {
-        YamlNode node = message.nodes[key];
-        var value = node.value;
-        // When positions matter, use node.span.text.
-        // When using node.span.text, replace r"\n" with "\n\n" to replace two
-        // characters with two characters without actually having the string
-        // "backslash n".
-        switch (key) {
-          case "template":
-            spell.SpellingResult spellingResult = spell.spellcheckString(
-                node.span.text.replaceAll(r"\n", "\n\n"),
-                dictionaries: const [
-                  spell.Dictionaries.common,
-                  spell.Dictionaries.cfeMessages
-                ]);
-            if (spellingResult.misspelledWords != null) {
-              spellingMessages ??= new List<String>();
-              spellingMessages.addAll(formatSpellingMistakes(
-                  spellingResult,
-                  node.span.start.offset,
-                  "Template likely has the following spelling mistake"));
-            }
-            break;
-
-          case "tip":
-            spell.SpellingResult spellingResult = spell.spellcheckString(
-                node.span.text.replaceAll(r"\n", "\n\n"),
-                dictionaries: const [
-                  spell.Dictionaries.common,
-                  spell.Dictionaries.cfeMessages
-                ]);
-            if (spellingResult.misspelledWords != null) {
-              spellingMessages ??= new List<String>();
-              spellingMessages.addAll(formatSpellingMistakes(
-                  spellingResult,
-                  node.span.start.offset,
-                  "Tip likely has the following spelling mistake"));
-            }
-            break;
-
-          case "severity":
-            severity = severityEnumValues[value];
-            if (severity == null) {
-              badSeverity = node;
-            } else if (severity == Severity.error) {
-              unnecessarySeverity = node;
-            }
-            break;
-
-          case "frontendInternal":
-            frontendInternal = value;
-            break;
-
-          case "analyzerCode":
-            analyzerCodes = value is String
-                ? <String>[value]
-                : new List<String>.from(value);
-            break;
-
-          case "bytes":
-            YamlList list = node;
-            if (list.first is List) {
-              for (YamlList bytes in list.nodes) {
-                int i = 0;
-                examples.add(new BytesExample("bytes${++i}", name, bytes));
-              }
-            } else {
-              examples.add(new BytesExample("bytes", name, list));
-            }
-            break;
-
-          case "declaration":
-            if (node is YamlList) {
-              int i = 0;
-              for (YamlNode declaration in node.nodes) {
-                examples.add(new DeclarationExample(
-                    "declaration${++i}", name, declaration));
-              }
-            } else {
-              examples.add(new DeclarationExample("declaration", name, node));
-            }
-            break;
-
-          case "expression":
-            if (node is YamlList) {
-              int i = 0;
-              for (YamlNode expression in node.nodes) {
-                examples.add(new ExpressionExample(
-                    "expression${++i}", name, expression));
-              }
-            } else {
-              examples.add(new ExpressionExample("expression", name, node));
-            }
-            break;
-
-          case "script":
-            if (node is YamlList) {
-              int i = 0;
-              for (YamlNode script in node.nodes) {
-                examples
-                    .add(new ScriptExample("script${++i}", name, script, this));
-              }
-            } else {
-              examples.add(new ScriptExample("script", name, node, this));
-            }
-            break;
-
-          case "statement":
-            if (node is YamlList) {
-              int i = 0;
-              for (YamlNode statement in node.nodes) {
-                examples.add(
-                    new StatementExample("statement${++i}", name, statement));
-              }
-            } else {
-              examples.add(new StatementExample("statement", name, node));
-            }
-            break;
-
-          case "external":
-            externalTest = node.value;
-            break;
-
-          case "index":
-            // index is validated during generation
-            break;
-
-          case "hasPublishedDocs":
-            if (value != true) {
-              badHasPublishedDocsValue.add(name);
-            }
-            break;
-
-          default:
-            unknownKeys.add(key);
-        }
-      }
-
-      MessageTestDescription createDescription(
-          String subName, Example example, String problem,
-          {location}) {
-        String shortName = "$name/$subName";
-        if (problem != null) {
-          String filename = relativize(uri);
-          location ??= message.span.start;
-          int line = location.line + 1;
-          int column = location.column;
-          problem = "$filename:$line:$column: error:\n$problem";
-        }
-        return new MessageTestDescription(uri.resolve("#$shortName"), shortName,
-            name, messageNode, example, problem);
-      }
-
-      if (!fastOnly) {
-        for (Example example in examples) {
-          yield createDescription(example.name, example, null);
-        }
-        // "Wrap" example as a part.
-        for (Example example in examples) {
-          yield createDescription(
-              "part_wrapped_${example.name}",
-              new PartWrapExample(
-                  "part_wrapped_${example.name}", name, example),
-              null);
-        }
-      }
-
-      yield createDescription(
-          "knownKeys",
-          null,
-          unknownKeys.isNotEmpty
-              ? "Unknown keys: ${unknownKeys.join(' ')}."
-              : null);
-
-      yield createDescription(
-          'hasPublishedDocs',
-          null,
-          badHasPublishedDocsValue.isNotEmpty
-              ? "Bad hasPublishedDocs value (only 'true' supported) in:"
-                  " ${badHasPublishedDocsValue.join(', ')}"
-              : null);
-
-      yield createDescription(
-          "severity",
-          null,
-          badSeverity != null
-              ? "Unknown severity: '${badSeverity.value}'."
-              : null,
-          location: badSeverity?.span?.start);
-
-      yield createDescription(
-          "unnecessarySeverity",
-          null,
-          unnecessarySeverity != null
-              ? "The 'ERROR' severity is the default and not necessary."
-              : null,
-          location: unnecessarySeverity?.span?.start);
-
-      yield createDescription(
-          "spelling",
-          null,
-          spellingMessages != null
-              ? spellingMessages.join("\n") + spellingPostMessage
-              : null);
-
-      bool exampleAndAnalyzerCodeRequired = severity != Severity.context &&
-          severity != Severity.internalProblem &&
-          severity != Severity.ignored;
-
-      yield createDescription(
-          "externalExample",
-          null,
-          exampleAndAnalyzerCodeRequired &&
-                  externalTest != null &&
-                  !(new File.fromUri(suite.uri.resolve(externalTest))
-                      .existsSync())
-              ? "Given external example for $name points to a nonexisting file "
-                  "(${suite.uri.resolve(externalTest)})."
-              : null);
-
-      yield createDescription(
-          "example",
-          null,
-          exampleAndAnalyzerCodeRequired &&
-                  examples.isEmpty &&
-                  externalTest == null
-              ? "No example for $name, please add at least one example."
-              : null);
-
-      yield createDescription(
-          "analyzerCode",
-          null,
-          exampleAndAnalyzerCodeRequired &&
-                  !frontendInternal &&
-                  analyzerCodes == null
-              ? "No analyzer code for $name."
-                  "\nTry running"
-                  " <BUILDDIR>/dart-sdk/bin/dartanalyzer --format=machine"
-                  " on an example to find the code."
-                  " The code is printed just before the file name."
-              : null);
-    }
-  }
-
-  String formatProblems(
-      String message, Example example, List<DiagnosticMessage> messages) {
-    var span = example.node.span;
-    StringBuffer buffer = new StringBuffer();
-    buffer
-      ..write(relativize(span.sourceUrl))
-      ..write(":")
-      ..write(span.start.line + 1)
-      ..write(":")
-      ..write(span.start.column)
-      ..write(": error: ")
-      ..write(message);
-    buffer.write("\n${span.text}");
-    for (DiagnosticMessage message in messages) {
-      buffer.write("\nCode: ${getMessageCodeObject(message).name}");
-      buffer.write("\n  > ");
-      buffer.write(
-          message.plainTextFormatted.join("\n").replaceAll("\n", "\n  > "));
-    }
-
-    return "$buffer";
-  }
-}
-
-abstract class Example {
-  final String name;
-
-  final String expectedCode;
-
-  Example(this.name, this.expectedCode);
-
-  YamlNode get node;
-
-  Uint8List get bytes;
-
-  Map<String, Uint8List> get scripts {
-    return {mainFilename: bytes};
-  }
-
-  String get mainFilename => "main.dart";
-}
-
-class BytesExample extends Example {
-  @override
-  final YamlList node;
-
-  @override
-  final Uint8List bytes;
-
-  BytesExample(String name, String code, this.node)
-      : bytes = new Uint8List.fromList(node.cast<int>()),
-        super(name, code);
-}
-
-class DeclarationExample extends Example {
-  @override
-  final YamlNode node;
-
-  final String declaration;
-
-  DeclarationExample(String name, String code, this.node)
-      : declaration = node.value,
-        super(name, code);
-
-  @override
-  Uint8List get bytes {
-    return new Uint8List.fromList(utf8.encode("""
-$declaration
-
-main() {
-}
-"""));
-  }
-}
-
-class StatementExample extends Example {
-  @override
-  final YamlNode node;
-
-  final String statement;
-
-  StatementExample(String name, String code, this.node)
-      : statement = node.value,
-        super(name, code);
-
-  @override
-  Uint8List get bytes {
-    return new Uint8List.fromList(utf8.encode("""
-main() {
-  $statement
-}
-"""));
-  }
-}
-
-class ExpressionExample extends Example {
-  @override
-  final YamlNode node;
-
-  final String expression;
-
-  ExpressionExample(String name, String code, this.node)
-      : expression = node.value,
-        super(name, code);
-
-  @override
-  Uint8List get bytes {
-    return new Uint8List.fromList(utf8.encode("""
-main() {
-  $expression;
-}
-"""));
-  }
-}
-
-class ScriptExample extends Example {
-  @override
-  final YamlNode node;
-
-  final Object script;
-
-  ScriptExample(String name, String code, this.node, MessageTestSuite suite)
-      : script = node.value,
-        super(name, code) {
-    if (script is! String && script is! Map) {
-      throw suite.formatProblems(
-          "A script must be either a String or a Map in $code:",
-          this, <DiagnosticMessage>[]);
-    }
-  }
-
-  @override
-  Uint8List get bytes => throw "Unsupported: ScriptExample.bytes";
-
-  @override
-  Map<String, Uint8List> get scripts {
-    Object script = this.script;
-    if (script is Map) {
-      var scriptFiles = <String, Uint8List>{};
-      script.forEach((fileName, value) {
-        scriptFiles[fileName] = new Uint8List.fromList(utf8.encode(value));
-      });
-      return scriptFiles;
-    } else {
-      return {mainFilename: new Uint8List.fromList(utf8.encode(script))};
-    }
-  }
-}
-
-class PartWrapExample extends Example {
-  final Example example;
-  PartWrapExample(String name, String code, this.example) : super(name, code);
-
-  @override
-  Uint8List get bytes => throw "Unsupported: PartWrapExample.bytes";
-
-  @override
-  String get mainFilename => "main_wrapped.dart";
-
-  @override
-  Map<String, Uint8List> get scripts {
-    Map<String, Uint8List> wrapped = example.scripts;
-
-    var scriptFiles = <String, Uint8List>{};
-    scriptFiles.addAll(wrapped);
-
-    // Create a new main file
-    // TODO: Technically we should find a un-used name.
-    if (scriptFiles.containsKey(mainFilename)) {
-      throw "Framework failure: "
-          "Wanted to create wrapper file, but the file already exists!";
-    }
-    scriptFiles[mainFilename] = new Uint8List.fromList(utf8.encode("""
-      part "${example.mainFilename}";
-    """));
-
-    // Modify the original main file to be part of the wrapper and add lots of
-    // gunk so every actual position in the file is not a valid position in the
-    // wrapper.
-    scriptFiles[example.mainFilename] = new Uint8List.fromList(utf8.encode("""
-      part of "${mainFilename}";
-      // La la la la la la la la la la la la la.
-      // La la la la la la la la la la la la la.
-      // La la la la la la la la la la la la la.
-      // La la la la la la la la la la la la la.
-      // La la la la la la la la la la la la la.
-    """) + scriptFiles[example.mainFilename]);
-
-    return scriptFiles;
-  }
-
-  @override
-  YamlNode get node => example.node;
-}
-
-class Validate extends Step<MessageTestDescription, Example, MessageTestSuite> {
-  const Validate();
-
-  String get name => "validate";
-
-  Future<Result<Example>> run(
-      MessageTestDescription description, MessageTestSuite suite) async {
-    if (description.problem != null) {
-      return fail(null, description.problem);
-    } else {
-      return pass(description.example);
-    }
-  }
-}
-
-class Compile extends Step<Example, Null, MessageTestSuite> {
-  const Compile();
-
-  String get name => "compile";
-
-  Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
-    if (example == null) return pass(null);
-    String dir = "${example.expectedCode}/${example.name}";
-    example.scripts.forEach((String fileName, Uint8List bytes) {
-      Uri uri = suite.fileSystem.currentDirectory.resolve("$dir/$fileName");
-      suite.fileSystem.entityForUri(uri).writeAsBytesSync(bytes);
-    });
-    Uri main = suite.fileSystem.currentDirectory
-        .resolve("$dir/${example.mainFilename}");
-    Uri output =
-        suite.fileSystem.currentDirectory.resolve("$dir/main.dart.dill");
-
-    // Setup .packages if it doesn't exist.
-    Uri dotPackagesUri =
-        suite.fileSystem.currentDirectory.resolve("$dir/.packages");
-    if (!await suite.fileSystem.entityForUri(dotPackagesUri).exists()) {
-      suite.fileSystem.entityForUri(dotPackagesUri).writeAsBytesSync([]);
-    }
-
-    print("Compiling $main");
-    List<DiagnosticMessage> messages = <DiagnosticMessage>[];
-
-    await suite.compiler.batchCompile(
-        new CompilerOptions()
-          ..sdkSummary = computePlatformBinariesLocation(forceBuildDir: true)
-              .resolve("vm_platform_strong.dill")
-          ..target = new VmTarget(new TargetFlags())
-          ..fileSystem = new HybridFileSystem(suite.fileSystem)
-          ..packagesFileUri = dotPackagesUri
-          ..onDiagnostic = messages.add
-          ..environmentDefines = const {},
-        main,
-        output);
-
-    List<DiagnosticMessage> unexpectedMessages = <DiagnosticMessage>[];
-    for (DiagnosticMessage message in messages) {
-      if (getMessageCodeObject(message).name != example.expectedCode) {
-        unexpectedMessages.add(message);
-      }
-    }
-    if (unexpectedMessages.isEmpty) {
-      switch (messages.length) {
-        case 0:
-          return fail(
-              null,
-              suite.formatProblems("No message reported in ${example.name}:",
-                  example, messages));
-        case 1:
-          return pass(null);
-        default:
-          return fail(
-              null,
-              suite.formatProblems(
-                  "Message reported multiple times in ${example.name}:",
-                  example,
-                  messages));
-      }
-    }
-    return fail(
-        null,
-        suite.formatProblems("Too many messages reported in ${example.name}:",
-            example, messages));
-  }
-}
-
-Future<MessageTestSuite> createContext(
-    Chain suite, Map<String, String> environment) async {
-  final bool fastOnly = environment["fastOnly"] == "true";
-  return new MessageTestSuite(fastOnly);
-}
-
-String relativize(Uri uri) {
-  String base = "${Uri.base}";
-  String filename = "$uri";
-  if (filename.startsWith(base)) {
-    return filename.substring(base.length);
-  } else {
-    return filename;
-  }
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/object_supertype_test.dart b/pkg/front_end/test/fasta/object_supertype_test.dart
index a3bc5bd..3d13824 100644
--- a/pkg/front_end/test/fasta/object_supertype_test.dart
+++ b/pkg/front_end/test/fasta/object_supertype_test.dart
@@ -4,6 +4,9 @@
 
 import "dart:convert" show json;
 
+import "package:_fe_analyzer_shared/src/messages/diagnostic_message.dart"
+    show DiagnosticMessage, getMessageCodeObject;
+
 import "package:async_helper/async_helper.dart" show asyncTest;
 
 import "package:expect/expect.dart" show Expect;
@@ -11,9 +14,6 @@
 import "package:front_end/src/api_prototype/compiler_options.dart"
     show CompilerOptions;
 
-import "package:front_end/src/api_prototype/diagnostic_message.dart"
-    show DiagnosticMessage, getMessageCodeObject;
-
 import "package:front_end/src/api_prototype/memory_file_system.dart"
     show MemoryFileSystem;
 
diff --git a/pkg/front_end/test/fasta/outline_test.dart b/pkg/front_end/test/fasta/outline_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/outline_test.dart
rename to pkg/front_end/test/fasta/outline_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 08b25f7..91d645b 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,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import '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';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/messages.dart';
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/async_modifier.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -984,12 +984,12 @@
   }
 
   @override
-  void handleForInitializerExpressionStatement(Token token) {
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
     calls.add('handleForInitializerExpressionStatement $token');
   }
 
   @override
-  void handleForInitializerLocalVariableDeclaration(Token token) {
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
     calls.add('handleForInitializerLocalVariableDeclaration $token');
   }
 
diff --git a/pkg/front_end/test/fasta/parser/parser_suite.dart b/pkg/front_end/test/fasta/parser/parser_suite.dart
index e2321af..1bcb148 100644
--- a/pkg/front_end/test/fasta/parser/parser_suite.dart
+++ b/pkg/front_end/test/fasta/parser/parser_suite.dart
@@ -2,7 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
 
-import 'package:front_end/src/fasta/parser.dart' show ParserError, parse;
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show ParserError, parse;
 
 import 'package:testing/testing.dart'
     show Chain, ChainContext, Future, Result, Step, runMe;
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 a4f4aa5..edca490 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,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/parser/token_stream_rewriter.dart';
-import 'package:front_end/src/fasta/scanner.dart'
+import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerResult, scanString;
-import 'package:front_end/src/fasta/scanner/token.dart';
-import 'package:front_end/src/scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
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 dc5203c..c3addc7 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+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';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' hide scanString;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as scanner;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/messages.dart';
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/type_info.dart';
-import 'package:front_end/src/fasta/parser/type_info_impl.dart';
-import 'package:front_end/src/fasta/scanner.dart' hide scanString;
-import 'package:front_end/src/fasta/scanner.dart' as scanner;
-import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/front_end/test/fasta/strong1_test.dart b/pkg/front_end/test/fasta/strong1_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/strong1_test.dart
rename to pkg/front_end/test/fasta/strong1_suite.dart
diff --git a/pkg/front_end/test/fasta/strong2_test.dart b/pkg/front_end/test/fasta/strong2_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/strong2_test.dart
rename to pkg/front_end/test/fasta/strong2_suite.dart
diff --git a/pkg/front_end/test/fasta/strong3_test.dart b/pkg/front_end/test/fasta/strong3_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/strong3_test.dart
rename to pkg/front_end/test/fasta/strong3_suite.dart
diff --git a/pkg/front_end/test/fasta/strong4_test.dart b/pkg/front_end/test/fasta/strong4_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/strong4_test.dart
rename to pkg/front_end/test/fasta/strong4_suite.dart
diff --git a/pkg/front_end/test/fasta/super_mixins_test.dart b/pkg/front_end/test/fasta/super_mixins_test.dart
index 03f30af..c776f0a 100644
--- a/pkg/front_end/test/fasta/super_mixins_test.dart
+++ b/pkg/front_end/test/fasta/super_mixins_test.dart
@@ -4,6 +4,15 @@
 
 library fasta.test.incremental_dynamic_test;
 
+import "package:_fe_analyzer_shared/src/messages/diagnostic_message.dart"
+    show
+        DiagnosticMessage,
+        DiagnosticMessageHandler,
+        getMessageCodeObject,
+        getMessageArguments;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:async_helper/async_helper.dart' show asyncTest;
 
 import 'package:expect/expect.dart' show Expect;
@@ -13,20 +22,11 @@
 import "package:front_end/src/api_prototype/compiler_options.dart"
     show CompilerOptions;
 
-import "package:front_end/src/api_prototype/diagnostic_message.dart"
-    show
-        DiagnosticMessage,
-        DiagnosticMessageHandler,
-        getMessageCodeObject,
-        getMessageArguments;
-
 import 'package:front_end/src/testing/compiler_common.dart' show compileScript;
 
 import 'package:front_end/src/fasta/fasta_codes.dart'
     show codeSuperclassHasNoMethod;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 /// A subclass of NoneTarget that enables Flutter style super-mixin semantics.
 ///
 /// See dartbug.com/31542 for details of the semantics.
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 3837eea..2265921 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -10,6 +10,8 @@
 
 import 'dart:io' show Directory, File, Platform;
 
+import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show
         CompilerOptions,
@@ -101,6 +103,10 @@
     "group": "Fail"
   },
   {
+    "name": "ExpectationFileMismatchSerialized",
+    "group": "Fail"
+  },
+  {
     "name": "ExpectationFileMissing",
     "group": "Fail"
   },
@@ -183,7 +189,11 @@
         ] {
     if (!ignoreExpectations) {
       steps.add(new MatchExpectation(
-          fullCompile ? ".strong.expect" : ".outline.expect"));
+          fullCompile ? ".strong.expect" : ".outline.expect",
+          serializeFirst: true));
+      steps.add(new MatchExpectation(
+          fullCompile ? ".strong.expect" : ".outline.expect",
+          serializeFirst: false));
     }
     steps.add(const TypeCheck());
     steps.add(const EnsureNoErrors());
@@ -193,9 +203,16 @@
     if (fullCompile) {
       steps.add(const Transform());
       if (!ignoreExpectations) {
-        steps.add(new MatchExpectation(fullCompile
-            ? ".strong.transformed.expect"
-            : ".outline.transformed.expect"));
+        steps.add(new MatchExpectation(
+            fullCompile
+                ? ".strong.transformed.expect"
+                : ".outline.transformed.expect",
+            serializeFirst: true));
+        steps.add(new MatchExpectation(
+            fullCompile
+                ? ".strong.transformed.expect"
+                : ".outline.transformed.expect",
+            serializeFirst: false));
       }
       steps.add(const EnsureNoErrors());
       if (!skipVm) {
@@ -393,7 +410,7 @@
     return await CompilerContext.runWithOptions(options, (_) async {
       // Disable colors to ensure that expectation files are the same across
       // platforms and independent of stdin/stderr.
-      CompilerContext.current.disableColors();
+      colors.enableColors = false;
       Component platform = await context.loadPlatform();
       Ticker ticker = new Ticker();
       DillTarget dillTarget = new DillTarget(
diff --git a/pkg/front_end/test/fasta/text_serialization_test.dart b/pkg/front_end/test/fasta/text_serialization_suite.dart
similarity index 100%
rename from pkg/front_end/test/fasta/text_serialization_test.dart
rename to pkg/front_end/test/fasta/text_serialization_suite.dart
diff --git a/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart b/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart
new file mode 100644
index 0000000..94e56f1
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_promotion_look_ahead_suite.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert' show jsonDecode;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+
+import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/fasta/builder/builder.dart';
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/messages.dart'
+    show LocatedMessage, templateUnspecified;
+
+import 'package:front_end/src/fasta/source/type_promotion_look_ahead_listener.dart'
+    show
+        TypePromotionLookAheadListener,
+        TypePromotionState,
+        UnspecifiedDeclaration;
+
+import 'package:kernel/ast.dart' show Source;
+
+import 'package:testing/testing.dart'
+    show Chain, ChainContext, ExpectationSet, Future, Result, Step, runMe;
+
+import '../utils/kernel_chain.dart' show MatchContext;
+
+import '../utils/scanner_chain.dart' show Read, Scan, ScannedFile;
+
+const String EXPECTATIONS = '''
+[
+  {
+    "name": "ExpectationFileMismatch",
+    "group": "Fail"
+  },
+  {
+    "name": "ExpectationFileMissing",
+    "group": "Fail"
+  }
+]
+''';
+
+Future<ChainContext> createContext(
+    Chain suite, Map<String, String> environment) async {
+  CompilerContext context =
+      await CompilerContext.runWithOptions<CompilerContext>(
+          new ProcessedOptions(),
+          (CompilerContext context) =>
+              new Future<CompilerContext>.value(context),
+          errorOnMissingInput: false);
+  colors.enableColors = false;
+  return new TypePromotionLookAheadContext(
+      context, environment["updateExpectations"] == "true");
+}
+
+class TypePromotionLookAheadContext extends ChainContext with MatchContext {
+  final CompilerContext context;
+
+  final List<Step> steps = const <Step>[
+    const Read(),
+    const Scan(),
+    const TypePromotionLookAheadStep(),
+    const CheckTypePromotionResult(),
+  ];
+
+  final bool updateExpectations;
+
+  final ExpectationSet expectationSet =
+      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
+
+  TypePromotionLookAheadContext(this.context, this.updateExpectations);
+}
+
+class TypePromotionLookAheadStep extends Step<ScannedFile, TypePromotionResult,
+    TypePromotionLookAheadContext> {
+  const TypePromotionLookAheadStep();
+
+  String get name => "Type Promotion Look Ahead";
+
+  Future<Result<TypePromotionResult>> run(
+      ScannedFile file, TypePromotionLookAheadContext context) async {
+    return context.context
+        .runInContext<Result<TypePromotionResult>>((CompilerContext c) async {
+      Uri uri = file.file.uri;
+      c.uriToSource[uri] =
+          new Source(file.result.lineStarts, file.file.bytes, uri, uri);
+      StringBuffer buffer = new StringBuffer();
+      Parser parser = new Parser(new TestListener(uri, buffer));
+      try {
+        parser.parseUnit(file.result.tokens);
+      } finally {
+        c.uriToSource.remove(uri);
+      }
+      return pass(new TypePromotionResult(uri, "$buffer"));
+    });
+  }
+}
+
+class TestState extends TypePromotionState {
+  final StringBuffer buffer;
+
+  TestState(Uri uri, this.buffer) : super(uri);
+
+  void note(String message, Token token) {
+    buffer.writeln(CompilerContext.current.format(
+        debugMessage(message, uri, token.charOffset, token.lexeme.length),
+        Severity.context));
+  }
+
+  @override
+  void checkEmpty(Token token) {
+    if (stack.isNotEmpty) {
+      throw CompilerContext.current.format(
+          debugMessage("Stack not empty", uri, token?.charOffset ?? -1,
+              token?.length ?? 1),
+          Severity.internalProblem);
+    }
+  }
+
+  @override
+  void declareIdentifier(Token token) {
+    super.declareIdentifier(token);
+    trace("Declared ${token.lexeme}", token);
+  }
+
+  @override
+  Builder nullValue(String name, Token token) {
+    return new DebugDeclaration(name, uri, token?.charOffset ?? -1);
+  }
+
+  @override
+  void registerWrite(UnspecifiedDeclaration declaration, Token token) {
+    note("Write to ${declaration.name}@${declaration.charOffset}", token);
+  }
+
+  @override
+  void registerPromotionCandidate(
+      UnspecifiedDeclaration declaration, Token token) {
+    note("Possible promotion of ${declaration.name}@${declaration.charOffset}",
+        token);
+  }
+
+  @override
+  void report(LocatedMessage message, Severity severity,
+      {List<LocatedMessage> context}) {
+    CompilerContext.current.report(message, severity, context: context);
+  }
+
+  @override
+  void trace(String message, Token token) {
+    report(
+        debugMessage(message, uri, token?.charOffset ?? -1, token?.length ?? 1),
+        Severity.warning);
+    for (Object o in stack) {
+      String s = "  $o";
+      int index = s.indexOf("\n");
+      if (index != -1) {
+        s = s.substring(0, index) + "...";
+      }
+      print(s);
+    }
+    print('------------------\n');
+  }
+}
+
+LocatedMessage debugMessage(String text, Uri uri, int offset, int length) {
+  return templateUnspecified
+      .withArguments(text)
+      .withLocation(uri, offset, length);
+}
+
+class TestListener extends TypePromotionLookAheadListener {
+  TestListener(Uri uri, StringBuffer buffer)
+      : super(new TestState(uri, buffer));
+
+  @override
+  void debugEvent(String name, Token token) {
+    state.trace(name, token);
+  }
+}
+
+class DebugDeclaration extends BuilderImpl {
+  final String name;
+
+  @override
+  final Uri fileUri;
+
+  @override
+  int charOffset;
+
+  DebugDeclaration(this.name, this.fileUri, this.charOffset);
+
+  Builder get parent => null;
+
+  String get fullNameForErrors => name;
+
+  String toString() => "<<$name@$charOffset>>";
+}
+
+class TypePromotionResult {
+  final Uri uri;
+
+  final String trace;
+
+  const TypePromotionResult(this.uri, this.trace);
+}
+
+class CheckTypePromotionResult
+    extends Step<TypePromotionResult, Null, TypePromotionLookAheadContext> {
+  const CheckTypePromotionResult();
+
+  String get name => "Check Type Promotion Result";
+
+  Future<Result<Null>> run(
+      TypePromotionResult result, TypePromotionLookAheadContext context) {
+    return context.match<Null>(
+        ".type_promotion.expect", result.trace, result.uri, null);
+  }
+}
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../../testing.json");
diff --git a/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart b/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
deleted file mode 100644
index d51c54d..0000000
--- a/pkg/front_end/test/fasta/type_promotion_look_ahead_test.dart
+++ /dev/null
@@ -1,230 +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 'dart:convert' show jsonDecode;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/fasta/builder/builder.dart';
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/messages.dart'
-    show LocatedMessage, templateUnspecified;
-
-import 'package:front_end/src/fasta/parser.dart' show Parser;
-
-import 'package:front_end/src/fasta/scanner.dart' show Token;
-
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
-import 'package:front_end/src/fasta/source/type_promotion_look_ahead_listener.dart'
-    show
-        TypePromotionLookAheadListener,
-        TypePromotionState,
-        UnspecifiedDeclaration;
-
-import 'package:kernel/ast.dart' show Source;
-
-import 'package:testing/testing.dart'
-    show Chain, ChainContext, ExpectationSet, Future, Result, Step, runMe;
-
-import '../utils/kernel_chain.dart' show MatchContext;
-
-import '../utils/scanner_chain.dart' show Read, Scan, ScannedFile;
-
-const String EXPECTATIONS = '''
-[
-  {
-    "name": "ExpectationFileMismatch",
-    "group": "Fail"
-  },
-  {
-    "name": "ExpectationFileMissing",
-    "group": "Fail"
-  }
-]
-''';
-
-Future<ChainContext> createContext(
-    Chain suite, Map<String, String> environment) async {
-  CompilerContext context =
-      await CompilerContext.runWithOptions<CompilerContext>(
-          new ProcessedOptions(),
-          (CompilerContext context) =>
-              new Future<CompilerContext>.value(context),
-          errorOnMissingInput: false);
-  context.disableColors();
-  return new TypePromotionLookAheadContext(
-      context, environment["updateExpectations"] == "true");
-}
-
-class TypePromotionLookAheadContext extends ChainContext with MatchContext {
-  final CompilerContext context;
-
-  final List<Step> steps = const <Step>[
-    const Read(),
-    const Scan(),
-    const TypePromotionLookAheadStep(),
-    const CheckTypePromotionResult(),
-  ];
-
-  final bool updateExpectations;
-
-  final ExpectationSet expectationSet =
-      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
-
-  TypePromotionLookAheadContext(this.context, this.updateExpectations);
-}
-
-class TypePromotionLookAheadStep extends Step<ScannedFile, TypePromotionResult,
-    TypePromotionLookAheadContext> {
-  const TypePromotionLookAheadStep();
-
-  String get name => "Type Promotion Look Ahead";
-
-  Future<Result<TypePromotionResult>> run(
-      ScannedFile file, TypePromotionLookAheadContext context) async {
-    return context.context
-        .runInContext<Result<TypePromotionResult>>((CompilerContext c) async {
-      Uri uri = file.file.uri;
-      c.uriToSource[uri] =
-          new Source(file.result.lineStarts, file.file.bytes, uri, uri);
-      StringBuffer buffer = new StringBuffer();
-      Parser parser = new Parser(new TestListener(uri, buffer));
-      try {
-        parser.parseUnit(file.result.tokens);
-      } finally {
-        c.uriToSource.remove(uri);
-      }
-      return pass(new TypePromotionResult(uri, "$buffer"));
-    });
-  }
-}
-
-class TestState extends TypePromotionState {
-  final StringBuffer buffer;
-
-  TestState(Uri uri, this.buffer) : super(uri);
-
-  void note(String message, Token token) {
-    buffer.writeln(CompilerContext.current.format(
-        debugMessage(message, uri, token.charOffset, token.lexeme.length),
-        Severity.context));
-  }
-
-  @override
-  void checkEmpty(Token token) {
-    if (stack.isNotEmpty) {
-      throw CompilerContext.current.format(
-          debugMessage("Stack not empty", uri, token?.charOffset ?? -1,
-              token?.length ?? 1),
-          Severity.internalProblem);
-    }
-  }
-
-  @override
-  void declareIdentifier(Token token) {
-    super.declareIdentifier(token);
-    trace("Declared ${token.lexeme}", token);
-  }
-
-  @override
-  Builder nullValue(String name, Token token) {
-    return new DebugDeclaration(name, uri, token?.charOffset ?? -1);
-  }
-
-  @override
-  void registerWrite(UnspecifiedDeclaration declaration, Token token) {
-    note("Write to ${declaration.name}@${declaration.charOffset}", token);
-  }
-
-  @override
-  void registerPromotionCandidate(
-      UnspecifiedDeclaration declaration, Token token) {
-    note("Possible promotion of ${declaration.name}@${declaration.charOffset}",
-        token);
-  }
-
-  @override
-  void report(LocatedMessage message, Severity severity,
-      {List<LocatedMessage> context}) {
-    CompilerContext.current.report(message, severity, context: context);
-  }
-
-  @override
-  void trace(String message, Token token) {
-    report(
-        debugMessage(message, uri, token?.charOffset ?? -1, token?.length ?? 1),
-        Severity.warning);
-    for (Object o in stack) {
-      String s = "  $o";
-      int index = s.indexOf("\n");
-      if (index != -1) {
-        s = s.substring(0, index) + "...";
-      }
-      print(s);
-    }
-    print('------------------\n');
-  }
-}
-
-LocatedMessage debugMessage(String text, Uri uri, int offset, int length) {
-  return templateUnspecified
-      .withArguments(text)
-      .withLocation(uri, offset, length);
-}
-
-class TestListener extends TypePromotionLookAheadListener {
-  TestListener(Uri uri, StringBuffer buffer)
-      : super(new TestState(uri, buffer));
-
-  @override
-  void debugEvent(String name, Token token) {
-    state.trace(name, token);
-  }
-}
-
-class DebugDeclaration extends BuilderImpl {
-  final String name;
-
-  @override
-  final Uri fileUri;
-
-  @override
-  int charOffset;
-
-  DebugDeclaration(this.name, this.fileUri, this.charOffset);
-
-  Builder get parent => null;
-
-  String get fullNameForErrors => name;
-
-  String toString() => "<<$name@$charOffset>>";
-}
-
-class TypePromotionResult {
-  final Uri uri;
-
-  final String trace;
-
-  const TypePromotionResult(this.uri, this.trace);
-}
-
-class CheckTypePromotionResult
-    extends Step<TypePromotionResult, Null, TypePromotionLookAheadContext> {
-  const CheckTypePromotionResult();
-
-  String get name => "Check Type Promotion Result";
-
-  Future<Result<Null>> run(
-      TypePromotionResult result, TypePromotionLookAheadContext context) {
-    return context.match<Null>(
-        ".type_promotion.expect", result.trace, result.uri, null);
-  }
-}
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../../testing.json");
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 4a8c9b5..c89dda7 100644
--- a/pkg/front_end/test/fasta/types/fasta_types_test.dart
+++ b/pkg/front_end/test/fasta/types/fasta_types_test.dart
@@ -75,9 +75,9 @@
     return environment.kernelFromParsedType(type_parser.parse(text).single);
   }
 
-  bool isSubtypeImpl(DartType subtype, DartType supertype) {
-    return hierarchy.types.isSubtypeOfKernel(
-        subtype, supertype, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isSubtypeImpl(DartType subtype, DartType supertype) {
+    return hierarchy.types
+        .performNullabilityAwareSubtypeCheck(subtype, supertype);
   }
 
   KernelEnvironment extend(String typeParameters) {
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser.dart b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
index ff98073..3ad30a1 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -13,6 +13,7 @@
         InterfaceType,
         Library,
         NamedType,
+        NeverType,
         Node,
         Nullability,
         Supertype,
@@ -156,6 +157,8 @@
       // Don't return a const object to ensure we test implementations that use
       // identical.
       return new BottomType();
+    } else if (name == "Never") {
+      return new NeverType(interpretParsedNullability(node.parsedNullability));
     }
     TreeNode declaration = environment[name];
     List<ParsedType> arguments = node.arguments;
@@ -257,7 +260,8 @@
             namedParameters: f.namedParameters,
             typeParameters: f.typeParameters,
             requiredParameterCount: f.requiredParameterCount,
-            typedefType: def.thisType);
+            typedefType: def.thisType,
+            nullability: Nullability.nonNullable);
       }
     }
     return def..type = type;
@@ -336,7 +340,8 @@
       TypeParameter typeParameter = typeParameters[i];
       if (bound == null) {
         typeParameter
-          ..bound = new InterfaceType(objectClass)
+          ..bound = new InterfaceType(
+              objectClass, const <DartType>[], Nullability.nullable)
           ..defaultType = const DynamicType();
       } else {
         DartType type =
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 3122299..b71ad46 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
@@ -12,8 +12,7 @@
 
 import "package:kernel/text/ast_to_text.dart" show Printer;
 
-import "package:kernel/type_environment.dart"
-    show SubtypeCheckMode, TypeEnvironment;
+import "package:kernel/type_environment.dart" show IsSubtypeOf, TypeEnvironment;
 
 import "kernel_type_parser.dart"
     show KernelEnvironment, KernelFromParsedType, parseLibrary;
@@ -25,44 +24,44 @@
 import "type_parser.dart" as type_parser show parse, parseTypeVariables;
 
 const String testSdk = """
-typedef Typedef<T> <S>(T*) ->* S*;
-typedef VoidFunction () ->* void;
-class DefaultTypes<S, T extends Object*, U extends List<S*>*, V extends List<T*>*, W extends Comparable<W*>*, X extends (W*) ->* void, Y extends () ->* W*>;
-typedef TestDefaultTypes () ->* DefaultTypes*;
-typedef Id<T> T*;
-typedef TestSorting ({int* c, int* b, int* a}) ->* void;
-class Super implements Comparable<Sub*>;
+typedef Typedef<T> <S>(T) -> S;
+typedef VoidFunction () -> void;
+class DefaultTypes<S, T extends Object, U extends List<S>, V extends List<T>, W extends Comparable<W>, X extends (W) -> void, Y extends () -> W>;
+typedef TestDefaultTypes () -> DefaultTypes;
+typedef Id<T> T;
+typedef TestSorting ({int c, int b, int a}) -> void;
+class Super implements Comparable<Sub>;
 class Sub extends Super;
-class FBound<T extends FBound<T*>*>;
-class MixinApplication extends Object with FBound<MixinApplication*>;
+class FBound<T extends FBound<T>>;
+class MixinApplication extends Object with FBound<MixinApplication>;
 """;
 
 const String expectedSdk = """
 library core;
 import self as self;
 
-typedef Typedef<T extends self::Object* = dynamic> = <S extends self::Object* = dynamic>(T*) →* S*;
-typedef VoidFunction = () →* void;
-typedef TestDefaultTypes = () →* self::DefaultTypes<dynamic, self::Object*, self::List<dynamic>*, self::List<self::Object*>*, self::Comparable<dynamic>*, (<BottomType>) →* void, () →* self::Comparable<dynamic>*>*;
-typedef Id<T extends self::Object* = dynamic> = T*;
-typedef TestSorting = ({a: self::int*, b: self::int*, c: self::int*}) →* void;
+typedef Typedef<T extends self::Object? = dynamic> = <S extends self::Object? = dynamic>(T%) → S%;
+typedef VoidFunction = () → void;
+typedef TestDefaultTypes = () → self::DefaultTypes<dynamic, self::Object, self::List<dynamic>, self::List<self::Object>, self::Comparable<dynamic>, (<BottomType>) → void, () → self::Comparable<dynamic>>;
+typedef Id<T extends self::Object? = dynamic> = T%;
+typedef TestSorting = ({a: self::int, b: self::int, c: self::int}) → void;
 class Object {
 }
-class Comparable<T extends self::Object* = dynamic> extends self::Object {
+class Comparable<T extends self::Object? = dynamic> extends self::Object {
 }
-class num extends self::Object implements self::Comparable<self::num*> {
+class num extends self::Object implements self::Comparable<self::num> {
 }
 class int extends self::num {
 }
 class double extends self::num {
 }
-class Iterable<T extends self::Object* = dynamic> extends self::Object {
+class Iterable<T extends self::Object? = dynamic> extends self::Object {
 }
-class List<T extends self::Object* = dynamic> extends self::Iterable<self::List::T*> {
+class List<T extends self::Object? = dynamic> extends self::Iterable<self::List::T%> {
 }
-class Future<T extends self::Object* = dynamic> extends self::Object {
+class Future<T extends self::Object? = dynamic> extends self::Object {
 }
-class FutureOr<T extends self::Object* = dynamic> extends self::Object {
+class FutureOr<T extends self::Object? = dynamic> extends self::Object {
 }
 class Null extends self::Object {
 }
@@ -72,15 +71,15 @@
 }
 class bool extends self::Object {
 }
-class DefaultTypes<S extends self::Object* = dynamic, T extends self::Object* = self::Object*, U extends self::List<self::DefaultTypes::S*>* = self::List<dynamic>*, V extends self::List<self::DefaultTypes::T*>* = self::List<self::Object*>*, W extends self::Comparable<self::DefaultTypes::W*>* = self::Comparable<dynamic>*, X extends (self::DefaultTypes::W*) →* void = (<BottomType>) →* void, Y extends () →* self::DefaultTypes::W* = () →* self::Comparable<dynamic>*> extends self::Object {
+class DefaultTypes<S extends self::Object? = dynamic, T extends self::Object = self::Object, U extends self::List<self::DefaultTypes::S%> = self::List<dynamic>, V extends self::List<self::DefaultTypes::T> = self::List<self::Object>, W extends self::Comparable<self::DefaultTypes::W> = self::Comparable<dynamic>, X extends (self::DefaultTypes::W) → void = (<BottomType>) → void, Y extends () → self::DefaultTypes::W = () → self::Comparable<dynamic>> extends self::Object {
 }
-class Super extends self::Object implements self::Comparable<self::Sub*> {
+class Super extends self::Object implements self::Comparable<self::Sub> {
 }
 class Sub extends self::Super {
 }
-class FBound<T extends self::FBound<self::FBound::T*>* = self::FBound<dynamic>*> extends self::Object {
+class FBound<T extends self::FBound<self::FBound::T> = self::FBound<dynamic>> extends self::Object {
 }
-class MixinApplication = self::Object with self::FBound<self::MixinApplication*> {
+class MixinApplication = self::Object with self::FBound<self::MixinApplication> {
 }
 """;
 
@@ -119,9 +118,9 @@
     return environment.kernelFromParsedType(type_parser.parse(text).single);
   }
 
-  bool isSubtypeImpl(DartType subtype, DartType supertype) {
-    return new TypeEnvironment(coreTypes, hierarchy).isSubtypeOf(
-        subtype, supertype, SubtypeCheckMode.ignoringNullabilities);
+  IsSubtypeOf isSubtypeImpl(DartType subtype, DartType supertype) {
+    return new TypeEnvironment(coreTypes, hierarchy)
+        .performNullabilityAwareSubtypeCheck(subtype, supertype);
   }
 
   KernelEnvironment extend(String typeParameters) {
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 7b13fe0..4d1aa06 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
@@ -68,8 +68,8 @@
   Future<void> test_getLegacyLeastUpperBound_expansive() async {
     await parseComponent("""
 class N<T>;
-class C1<T> extends N<N<C1<T>>>;
-class C2<T> extends N<N<C2<N<C2<T>>>>>;
+class C1<T> extends N<N<C1<T*>*>*>;
+class C2<T> extends N<N<C2<N<C2<T*>*>*>*>*>;
 """);
 
     Class N = getClass("N");
@@ -106,9 +106,9 @@
 class A;
 class B<T> implements A;
 class C<U> implements A;
-class D<T, U> implements B<T>, C<U>;
-class E implements D<int, double>;
-class F implements D<int, bool>;
+class D<T, U> implements B<T*>, C<U*>;
+class E implements D<int*, double*>;
+class F implements D<int*, bool*>;
 """);
 
     Class a = getClass("A");
diff --git a/pkg/front_end/test/fasta/types/mock_sdk.dart b/pkg/front_end/test/fasta/types/mock_sdk.dart
index 606ee4d..d4a937b 100644
--- a/pkg/front_end/test/fasta/types/mock_sdk.dart
+++ b/pkg/front_end/test/fasta/types/mock_sdk.dart
@@ -5,11 +5,11 @@
 const String mockSdk = """
 class Object;
 class Comparable<T>;
-class num implements Comparable<num*>;
+class num implements Comparable<num>;
 class int extends num;
 class double extends num;
 class Iterable<T>;
-class List<T> extends Iterable<T*>;
+class List<T> extends Iterable<T>;
 class Future<T>;
 class FutureOr<T>;
 class Null;
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 4a01bd2..dde84e42 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -4,13 +4,16 @@
 
 import "package:expect/expect.dart" show Expect;
 
+import "package:kernel/type_environment.dart";
+
 abstract class SubtypeTest<T, E> {
   void isSubtype(String subtypeString, String supertypeString,
       {String typeParameters}) {
     E environment = extend(typeParameters);
     T subtype = toType(subtypeString, environment);
     T supertype = toType(supertypeString, environment);
-    Expect.isTrue(isSubtypeImpl(subtype, supertype),
+    Expect.isTrue(
+        isSubtypeImpl(subtype, supertype).isSubtypeWhenUsingNullabilities(),
         "$subtypeString should be a subtype of $supertypeString.");
   }
 
@@ -19,30 +22,58 @@
     E environment = extend(typeParameters);
     T subtype = toType(subtypeString, environment);
     T supertype = toType(supertypeString, environment);
-    Expect.isFalse(isSubtypeImpl(subtype, supertype),
+    Expect.isFalse(
+        isSubtypeImpl(subtype, supertype).isSubtypeWhenIgnoringNullabilities(),
         "$subtypeString shouldn't be a subtype of $supertypeString.");
   }
 
+  /// Checks if a type is a subtype of the other ignoring nullability modifiers.
+  void isObliviousSubtype(String subtypeString, String supertypeString,
+      {String typeParameters}) {
+    E environment = extend(typeParameters);
+    T subtype = toType(subtypeString, environment);
+    T supertype = toType(supertypeString, environment);
+    Expect.isTrue(
+        isSubtypeImpl(subtype, supertype).isSubtypeWhenIgnoringNullabilities(),
+        "$subtypeString should be a subtype of $supertypeString "
+        "if the nullability modifiers are ignored.");
+  }
+
   bool get skipFutureOrPromotion => false;
 
   T toType(String text, E environment);
 
-  bool isSubtypeImpl(T subtype, T supertype);
+  IsSubtypeOf isSubtypeImpl(T subtype, T supertype);
 
   E extend(String typeParameters);
 
   void run() {
+    // Tests for subtypes and supertypes of num.
     isSubtype('int*', 'num*');
     isSubtype('int*', 'Comparable<num*>*');
     isSubtype('int*', 'Comparable<Object*>*');
     isSubtype('int*', 'Object*');
     isSubtype('double*', 'num*');
+    isSubtype('num', 'Object');
+    isSubtype('num*', 'Object');
+    isSubtype('Null?', 'num*');
+    isSubtype('Null?', 'num?');
+    isSubtype('Never', 'num');
+    isSubtype('Never', 'num*');
+    isSubtype('Never', 'num?');
+    isSubtype('bottom', 'num');
+    isSubtype('bottom', 'num*');
+    isSubtype('bottom', 'num?');
 
     isNotSubtype('int*', 'double*');
     isNotSubtype('int*', 'Comparable<int*>*');
     isNotSubtype('int*', 'Iterable<int*>*');
     isNotSubtype('Comparable<int*>*', 'Iterable<int*>*');
+    isObliviousSubtype('num?', 'Object');
+    isObliviousSubtype('Null?', 'num');
+    isNotSubtype('num', 'Never');
 
+    // Tests for subtypes and supertypes of List.
     isSubtype('List<int*>*', 'List<int*>*');
     isSubtype('List<int*>*', 'Iterable<int*>*');
     isSubtype('List<int*>*', 'List<num*>*');
@@ -53,32 +84,80 @@
     isSubtype('List<int*>*', 'List<Comparable<Object*>*>*');
     isSubtype('List<int*>*', 'List<Comparable<num*>*>*');
     isSubtype('List<int*>*', 'List<Comparable<Comparable<num*>*>*>*');
+    isSubtype('List<int*>', 'Object');
+    isSubtype('List<int*>*', 'Object');
+    isSubtype('Null?', 'List<int*>*');
+    isSubtype('Null?', 'List<int*>?');
+    isSubtype('Never', 'List<int*>');
+    isSubtype('Never', 'List<int*>*');
+    isSubtype('Never', 'List<int*>?');
+
+    isSubtype('List<int>', 'List<int>');
+    isSubtype('List<int>', 'List<int>*');
+    isSubtype('List<int>', 'List<int>?');
+    isSubtype('List<int>*', 'List<int>');
+    isSubtype('List<int>*', 'List<int>*');
+    isSubtype('List<int>*', 'List<int>?');
+    isObliviousSubtype('List<int>?', 'List<int>');
+    isSubtype('List<int>?', 'List<int>*');
+    isSubtype('List<int>?', 'List<int>?');
+
+    isSubtype('List<int>', 'List<int*>');
+    isSubtype('List<int>', 'List<int?>');
+    isSubtype('List<X & int>', 'List<X>', typeParameters: 'X extends Object?');
+    isSubtype('List<int*>', 'List<int>');
+    isSubtype('List<int*>', 'List<int*>');
+    isSubtype('List<int*>', 'List<int?>');
+    isObliviousSubtype('List<int?>', 'List<int>');
+    isSubtype('List<int?>', 'List<int*>');
+    isSubtype('List<int?>', 'List<int?>');
+    isSubtype('List<X & int?>', 'List<X>', typeParameters: 'X extends Object?');
 
     isNotSubtype('List<int*>*', 'List<double*>*');
     isNotSubtype('List<int*>*', 'Iterable<double*>*');
     isNotSubtype('List<int*>*', 'Comparable<int*>*');
     isNotSubtype('List<int*>*', 'List<Comparable<int*>*>*');
     isNotSubtype('List<int*>*', 'List<Comparable<Comparable<int*>*>*>*');
+    isObliviousSubtype('List<int*>?', 'Object');
+    isObliviousSubtype('Null?', 'List<int*>');
+    isNotSubtype('List<int*>', 'Never');
 
+    isObliviousSubtype('T?', 'List<int>',
+        typeParameters: 'T extends List<int>');
+
+    // Tests for non-generic one-argument function types.
     isSubtype('(num*) ->* num*', '(int*) ->* num*');
     isSubtype('(num*) ->* int*', '(num*) ->* num*');
     isSubtype('(num*) ->* int*', '(int*) ->* num*');
     isNotSubtype('(int*) ->* int*', '(num*) ->* num*');
     isSubtype('Null?', '(int*) ->* num*');
+    isSubtype('Null?', '(int*) ->? num*');
+    isSubtype('Never', '(int*) -> num*');
+    isSubtype('Never', '(int*) ->* num*');
+    isSubtype('Never', '(int*) ->? num*');
+    isSubtype('(num*) ->* num*', 'Object');
+    isSubtype('(num*) -> num*', 'Object');
+    isObliviousSubtype('(num*) ->? num*', 'Object');
+    isObliviousSubtype('Null?', '(int*) -> num*');
+    isNotSubtype('(int*) -> num*', 'Never');
 
+    // Tests for non-generic two-argument curried function types.
     isSubtype('(num*) ->* (num*) ->* num*', '(num*) ->* (int*) ->* num*');
     isNotSubtype('(num*) ->* (int*) ->* int*', '(num*) ->* (num*) ->* num*');
 
-    isSubtype('({num* x}) ->* num*', '({int* x}) ->* num*'); // named parameters
+    // Tests for non-generic one-argument function types with named parameters.
+    isSubtype('({num* x}) ->* num*', '({int* x}) ->* num*');
     isSubtype('(num*, {num* x}) ->* num*', '(int*, {int* x}) ->* num*');
     isSubtype('({num* x}) ->* int*', '({num* x}) ->* num*');
     isNotSubtype('({int* x}) ->* int*', '({num* x}) ->* num*');
 
-    isSubtype('<E>(E) ->* int*', '<E>(E) ->* num*'); // type parameters
+    // Tests for function types with type parameters.
+    isSubtype('<E>(E) ->* int*', '<E>(E) ->* num*');
     isSubtype('<E>(num*) ->* E', '<E>(int*) ->* E');
     isSubtype('<E>(E,num*) ->* E', '<E>(E,int*) ->* E');
     isNotSubtype('<E>(E,num*) ->* E', '<E>(E,E) ->* E');
 
+    // Tests for curried function types with type parameters.
     isSubtype('<E>(E) ->* (E) ->* E', '<F>(F) ->* (F) ->* F');
     isSubtype('<E>(E, (int*,E) ->* E) ->* E', '<E>(E, (int*,E) ->* E) ->* E');
     isSubtype('<E>(E, (int*,E) ->* E) ->* E', '<E>(E, (num*,E) ->* E) ->* E');
@@ -97,6 +176,7 @@
     isNotSubtype('<E>(int*) ->* int*', '(int*) ->* int*');
     isNotSubtype('<E,F>(int*) ->* int*', '<E>(int*) ->* int*');
 
+    // Tests for generic function types with bounded type parameters.
     isSubtype(
         '<E extends List<E*>*>(E*) ->* E*', '<F extends List<F*>*>(F*) ->* F*');
     isNotSubtype('<E extends Iterable<E*>*>(E*) ->* E*',
@@ -110,6 +190,7 @@
     isNotSubtype(
         '<E>(E,List<Object*>*) ->* E', '<F extends List<F*>*>(F*,F*) ->* void');
 
+    // Tests for FutureOr.
     isSubtype('int*', 'FutureOr<int*>*');
     isSubtype('int*', 'FutureOr<num*>*');
     isSubtype('Future<int*>*', 'FutureOr<int*>*');
@@ -118,6 +199,29 @@
     isSubtype('FutureOr<int*>*', 'FutureOr<int*>*');
     isSubtype('FutureOr<int*>*', 'FutureOr<num*>*');
     isSubtype('FutureOr<int*>*', 'Object*');
+
+    isSubtype('FutureOr<int>', 'Object');
+    isSubtype('FutureOr<int>', 'Object*');
+    isSubtype('FutureOr<int>', 'Object?');
+    isSubtype('FutureOr<int>*', 'Object');
+    isSubtype('FutureOr<int>*', 'Object*');
+    isSubtype('FutureOr<int>*', 'Object?');
+    isObliviousSubtype('FutureOr<int>?', 'Object');
+    isSubtype('FutureOr<int>?', 'Object*');
+    isSubtype('FutureOr<int>?', 'Object?');
+
+    isSubtype('FutureOr<int*>', 'Object');
+    isSubtype('FutureOr<int*>', 'Object*');
+    isSubtype('FutureOr<int*>', 'Object?');
+    isObliviousSubtype('FutureOr<int?>', 'Object');
+    isSubtype('FutureOr<int?>', 'Object*');
+    isSubtype('FutureOr<int?>', 'Object?');
+
+    isSubtype('FutureOr<Future<Object>>', 'Future<Object>');
+    isObliviousSubtype('FutureOr<Future<Object>>?', 'Future<Object>');
+    isObliviousSubtype('FutureOr<Future<Object>?>', 'Future<Object>');
+    isObliviousSubtype('FutureOr<Future<Object>?>?', 'Future<Object>');
+
     isNotSubtype('int*', 'FutureOr<double*>*');
     isNotSubtype('FutureOr<double*>*', 'int*');
     isNotSubtype('FutureOr<int*>*', 'Future<num*>*');
@@ -161,13 +265,56 @@
     isSubtype('Id<int*>*', 'FutureOr<num*>*');
     isNotSubtype('Id<num*>*', 'FutureOr<int*>*');
     isSubtype('FutureOr<Object*>*', 'FutureOr<FutureOr<Object*>*>*');
+    isSubtype('FutureOr<num>*', 'Object');
+    isSubtype('FutureOr<num>', 'Object');
+    isObliviousSubtype('FutureOr<num>?', 'Object');
+    isSubtype('Never', 'FutureOr<num>');
+    isSubtype('Never', 'FutureOr<num*>');
+    isSubtype('Never', 'FutureOr<num>*');
+    isSubtype('Never', 'FutureOr<num?>');
+    isSubtype('Never', 'FutureOr<num>?');
+    isNotSubtype('FutureOr<num>', 'Never');
 
+    // Testing bottom types against an intersection type.
+    isSubtype('Null?', 'T* & num*', typeParameters: 'T extends Object*');
+    isSubtype('Never', 'T* & num*', typeParameters: 'T extends Object*');
+    isObliviousSubtype('Null?', 'T & num', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null?', 'T & num?',
+        typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null?', 'T & num', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null?', 'T & S',
+        typeParameters: 'T extends Object?, S extends T');
+    isNotSubtype('T* & num*', 'Never', typeParameters: 'T extends Object*');
+    isSubtype('T', 'Never', typeParameters: 'T extends Never');
+    isSubtype('T & Never', 'Never', typeParameters: 'T extends Object');
+
+    // Testing bottom types against type-parameter types.
+    isSubtype('Null?', 'T?', typeParameters: 'T extends Object');
+    isSubtype('Null?', 'T?', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object?');
+    isSubtype('Never', 'T?', typeParameters: 'T extends Object');
+    isSubtype('Never', 'T?', typeParameters: 'T extends Object?');
+    isSubtype('Never', 'T', typeParameters: 'T extends Object');
+    isSubtype('Never', 'T', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Never?', 'T', typeParameters: 'T extends Object?');
+    isSubtype('T', 'Null?', typeParameters: 'T extends Null?');
+    isSubtype('T?', 'Null?', typeParameters: 'T extends Null?');
+    isNotSubtype('T', 'Null?', typeParameters: 'T extends Object');
+    isNotSubtype('T', 'Null?', typeParameters: 'T extends Object?');
+    isSubtype('T', 'Never', typeParameters: 'T extends Never');
+    isObliviousSubtype('T', 'Never', typeParameters: 'T extends Never?');
+    isObliviousSubtype('T?', 'Never', typeParameters: 'T extends Never');
+    isObliviousSubtype('T?', 'Never', typeParameters: 'T extends Never?');
+    isNotSubtype('T', 'Never', typeParameters: 'T extends Object');
+    isNotSubtype('T', 'Never', typeParameters: 'T extends Object?');
+
+    // Trivial tests for type-parameter types and intersection types.
     // T & B <: T & A if B <: A
     isSubtype('T & int*', 'T & int*', typeParameters: 'T');
     isSubtype('T & int*', 'T & num*', typeParameters: 'T');
     isSubtype('T & num*', 'T & num*', typeParameters: 'T');
     isNotSubtype('T & num*', 'T & int*', typeParameters: 'T');
-    isSubtype('Null?', 'T & num*', typeParameters: 'T');
 
     // T & B <: T extends A if B <: A
     // (Trivially satisfied since promoted bounds are always a isSubtype of the
@@ -198,8 +345,9 @@
 
     // S <: T extends S
     isNotSubtype('S', 'T', typeParameters: 'S, T extends S');
-    isSubtype('T', 'S', typeParameters: 'S, T extends S');
+    isObliviousSubtype('T', 'S', typeParameters: 'S, T extends S');
 
+    // Non-trivial tests for intersection types.
     // S & B <: A if B <: A, A is not S (or a promotion thereof)
     isSubtype('S & int*', 'int*', typeParameters: 'S');
     isSubtype('S & int*', 'num*', typeParameters: 'S');
@@ -207,50 +355,171 @@
     isNotSubtype('S & num*', 'int*', typeParameters: 'S');
     isNotSubtype('S & num*', 'T', typeParameters: 'S, T');
     isNotSubtype('S & num*', 'T & num*', typeParameters: 'S, T');
+    isSubtype('S & num', 'num', typeParameters: 'S extends Object?');
+    isObliviousSubtype('S & num?', 'num', typeParameters: 'S extends Object?');
+    isSubtype('S & num?', 'num?', typeParameters: 'S extends Object?');
+    isSubtype('S & num?', 'num*', typeParameters: 'S extends Object?');
 
     // S extends B <: A if B <: A, A is not S (or a promotion thereof)
     isSubtype('S*', 'int*', typeParameters: 'S extends int*');
     isSubtype('S*', 'num*', typeParameters: 'S extends int*');
     isSubtype('S*', 'num*', typeParameters: 'S extends num*');
+    isSubtype('S*', 'Object', typeParameters: 'S extends num*');
+    isSubtype('S', 'Object', typeParameters: 'S extends num');
     isNotSubtype('S*', 'int*', typeParameters: 'S extends num*');
     isNotSubtype('S*', 'T', typeParameters: 'S extends num*, T');
     isNotSubtype('S*', 'T & num*', typeParameters: 'S extends num*, T');
+    isObliviousSubtype('S?', 'Object', typeParameters: 'S extends num');
+    isObliviousSubtype('S', 'Object', typeParameters: 'S extends num?');
+    isObliviousSubtype('S?', 'Object', typeParameters: 'S extends num?');
 
+    isNotSubtype('dynamic', 'int');
     isNotSubtype('dynamic', 'int*');
+    isNotSubtype('dynamic', 'int?');
+    isNotSubtype('void', 'int');
     isNotSubtype('void', 'int*');
+    isNotSubtype('void', 'int?');
+    isNotSubtype('Object', 'int');
+    isNotSubtype('Object', 'int*');
+    isNotSubtype('Object', 'int?');
+    isNotSubtype('Object*', 'int');
+    isNotSubtype('Object*', 'int*');
+    isNotSubtype('Object*', 'int?');
+    isNotSubtype('Object?', 'int');
+    isNotSubtype('Object?', 'int*');
+    isNotSubtype('Object?', 'int?');
     isNotSubtype('() ->* int*', 'int*');
     isNotSubtype('Typedef<Object*>*', 'int*');
-    isSubtype('() ->* int*', 'Function*');
-    isSubtype('() ->* int*', 'Object*');
 
-    isNotSubtype('Null?', 'bottom');
-    isSubtype('Null?', 'Object*');
-    isSubtype('Null?', 'void');
-    isSubtype('Null?', 'dynamic');
+    isSubtype('() -> int*', 'Function');
+    isSubtype('() -> int*', 'Function*');
+    isSubtype('() -> int*', 'Function?');
+    isSubtype('() ->* int*', 'Function');
+    isSubtype('() ->* int*', 'Function*');
+    isSubtype('() ->* int*', 'Function?');
+    isObliviousSubtype('() ->? int*', 'Function');
+    isSubtype('() ->? int*', 'Function*');
+    isSubtype('() ->? int*', 'Function?');
+
+    isSubtype('() -> int*', 'Object');
+    isSubtype('() -> int*', 'Object*');
+    isSubtype('() -> int*', 'Object?');
+    isSubtype('() ->* int*', 'Object');
+    isSubtype('() ->* int*', 'Object*');
+    isSubtype('() ->* int*', 'Object?');
+    isObliviousSubtype('() ->? int*', 'Object');
+    isSubtype('() ->? int*', 'Object*');
+    isSubtype('() ->? int*', 'Object?');
+
+    // Tests for "Null?".
     isSubtype('Null?', 'double*');
     isSubtype('Null?', 'Comparable<Object*>*');
+    isSubtype('Null?', 'Comparable<Object*>?');
     isSubtype('Null?', 'Typedef<Object*>*');
+    isSubtype('Null?', 'Typedef<Object*>?');
     isSubtype('Null?', 'T', typeParameters: 'T extends Object*');
+    isSubtype('Null?', 'T?', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object?');
+    isObliviousSubtype('Null?', 'T', typeParameters: 'T extends Object');
+    isObliviousSubtype('Null?', 'Object');
 
+    // Tests for bottom and top types.
     isSubtype('Null?', 'Null?');
+    isNotSubtype('Null?', 'bottom');
+    isNotSubtype('Null?', 'Never');
+    isSubtype('bottom', 'Null?');
     isSubtype('bottom', 'bottom');
+    isSubtype('bottom', 'Never');
+    isSubtype('Never', 'Null?');
+    isNotSubtype('Never', 'bottom');
+    isSubtype('Never', 'Never');
+
+    isSubtype('Null?', 'Never?');
+    isSubtype('Never?', 'Null?');
+    isSubtype('Never', 'Never?');
+    isObliviousSubtype('Never?', 'Never');
+
     isSubtype('Object*', 'Object*');
     isSubtype('Object*', 'dynamic');
     isSubtype('Object*', 'void');
+    isSubtype('Object*', 'Object?');
     isSubtype('dynamic', 'Object*');
     isSubtype('dynamic', 'dynamic');
     isSubtype('dynamic', 'void');
+    isSubtype('dynamic', 'Object?');
     isSubtype('void', 'Object*');
     isSubtype('void', 'dynamic');
     isSubtype('void', 'void');
+    isSubtype('void', 'Object?');
+    isSubtype('Object?', 'Object*');
+    isSubtype('Object?', 'dynamic');
+    isSubtype('Object?', 'void');
+    isSubtype('Object?', 'Object?');
+
+    isSubtype('Never', 'Object?');
+    isSubtype('Never', 'Object*');
+    isSubtype('Never', 'dynamic');
+    isSubtype('Never', 'void');
+    isSubtype('bottom', 'Object?');
+    isSubtype('bottom', 'Object*');
+    isSubtype('bottom', 'dynamic');
+    isSubtype('bottom', 'void');
+    isSubtype('Null?', 'Object?');
+    isSubtype('Null?', 'Object*');
+    isSubtype('Null?', 'dynamic');
+    isSubtype('Null?', 'void');
+
+    isNotSubtype('Object?', 'Never');
+    isNotSubtype('Object?', 'bottom');
+    isNotSubtype('Object?', 'Null?');
+    isNotSubtype('Object*', 'Never');
+    isNotSubtype('Object*', 'bottom');
+    isNotSubtype('Object*', 'Null?');
+    isNotSubtype('dynamic', 'Never');
+    isNotSubtype('dynamic', 'bottom');
+    isNotSubtype('dynamic', 'Null?');
+    isNotSubtype('void', 'Never');
+    isNotSubtype('void', 'bottom');
+    isNotSubtype('void', 'Null?');
+
+    // Tests for Object against the top and the bottom types.
+    isSubtype('bottom', 'Object');
+    isSubtype('Never', 'Object');
+    isSubtype('Object', 'dynamic');
+    isSubtype('Object', 'void');
+    isSubtype('Object', 'Object?');
+    isSubtype('Object', 'Object*');
+    isSubtype('Object*', 'Object');
+
+    isNotSubtype('Object', 'bottom');
+    isNotSubtype('Object', 'Null?');
+    isNotSubtype('Object', 'Never');
+    isObliviousSubtype('dynamic', 'Object');
+    isObliviousSubtype('void', 'Object');
+    isObliviousSubtype('Object?', 'Object');
 
     // Check that the top types are equivalent.
-    isSubtype('<S extends Object*, T extends void>(S, T) ->* void',
-        '<U extends dynamic, V extends Object*>(U, V) ->* void');
+    isSubtype(
+        '<S extends Object*, T extends void, R extends Object?>'
+            '(S, T, R) ->* void',
+        '<U extends dynamic, V extends Object*, W extends void>'
+            '(U, V, W) ->* void');
 
     {
+      String d = '<T extends void>() ->* T';
+      String e = '<T extends Object?>() ->* T';
       String f = '<T extends dynamic>() ->* T';
       String g = '<T extends Object*>() ->* T*';
+
+      // d = e.
+      isSubtype(d, e);
+      isSubtype(e, d);
+
+      // e = f.
+      isSubtype(e, f);
+      isSubtype(f, e);
+
+      // f = g.
       isSubtype(f, g);
       isSubtype(g, f);
     }
@@ -259,14 +528,22 @@
       String h = '<T extends List<dynamic>*>() ->* T*';
       String i = '<T extends List<Object*>*>() ->* T*';
       String j = '<T extends List<void>*>() ->* T*';
+      String k = '<T extends List<Object?>*>() ->* T*';
       isSubtype(h, i);
       isSubtype(h, j);
+      isSubtype(h, k);
       isSubtype(i, h);
       isSubtype(i, j);
+      isSubtype(i, k);
       isSubtype(j, h);
       isSubtype(j, i);
+      isSubtype(j, k);
+      isSubtype(k, h);
+      isSubtype(k, i);
+      isSubtype(k, j);
     }
 
+    // Tests for checking function types against other kinds of types.
     isNotSubtype('dynamic', '() ->* dynamic');
     isNotSubtype('FutureOr<() ->* void>*', '() ->* void');
     isSubtype('T & () ->* void', '() ->* void', typeParameters: 'T');
@@ -296,6 +573,7 @@
         '() ->* void');
     isNotSubtype('void', '() ->* void');
 
+    // Tests for checking typedef-types against other kinds of types.
     isNotSubtype('dynamic', 'T', typeParameters: 'T');
     isNotSubtype('Iterable<T>*', 'T', typeParameters: 'T');
     isNotSubtype('() ->* void', 'T', typeParameters: 'T');
@@ -305,6 +583,7 @@
         typeParameters: 'T extends () ->* void');
     isNotSubtype('void', 'T', typeParameters: 'T extends void');
 
+    // Tests for checking typedef types against other kinds of types.
     isSubtype('dynamic', 'Id<dynamic>*');
     isNotSubtype('dynamic', 'Id<int*>*');
     isSubtype('() ->* void', 'Id<() ->* void>*');
@@ -315,6 +594,33 @@
     isSubtype('T & () ->* void', 'Id<() ->* void>*', typeParameters: 'T');
     isSubtype('T & () ->* void', 'Id<() ->* dynamic>*', typeParameters: 'T');
     isSubtype('T & () ->* void', 'Id<() ->* Object*>*', typeParameters: 'T');
+    isSubtype('Object', 'Id<Object>');
+    isSubtype('Id<Object>', 'Object');
+    isSubtype('Object*', 'Id<Object>');
+    isSubtype('Id<Object>', 'Object*');
+    isObliviousSubtype('dynamic', 'Id<Object>');
+    isSubtype('Id<Object>', 'dynamic');
+    isObliviousSubtype('void', 'Id<Object>');
+    isSubtype('Id<Object>', 'void');
+    isObliviousSubtype('Null?', 'Id<Object>');
+    isSubtype('Never', 'Id<Object>');
+    isSubtype('Never', 'Id<Never>');
+    isSubtype('Id<Never>', 'Never');
+    isNotSubtype('Null?', 'Id<Never>');
+    isSubtype('Id<Never>', 'Null?');
+    isNotSubtype('Id<Object>', 'Never');
+    isSubtype('Id<int>', 'num');
+    isObliviousSubtype('Id<int?>', 'num');
+    isObliviousSubtype('Id<int>?', 'num');
+    isObliviousSubtype('Id<int?>?', 'num');
+    isSubtype('Id<int>', 'num*');
+    isSubtype('Id<int?>', 'num*');
+    isSubtype('Id<int>?', 'num*');
+    isSubtype('Id<int?>?', 'num*');
+    isSubtype('Id<int>', 'num?');
+    isSubtype('Id<int?>', 'num?');
+    isSubtype('Id<int>?', 'num?');
+    isSubtype('Id<int?>?', 'num?');
 
     isSubtype('T & (void) ->* void', 'Id<(void) ->* void>*',
         typeParameters: 'T');
diff --git a/pkg/front_end/test/fasta/types/type_parser.dart b/pkg/front_end/test/fasta/types/type_parser.dart
index c9e0592..24881cd 100644
--- a/pkg/front_end/test/fasta/types/type_parser.dart
+++ b/pkg/front_end/test/fasta/types/type_parser.dart
@@ -2,14 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:kernel/ast.dart' show Nullability;
-
-import "package:front_end/src/fasta/scanner.dart" show scanString, Token;
-
-import "package:front_end/src/fasta/parser/type_info_impl.dart"
+import "package:_fe_analyzer_shared/src/parser/type_info_impl.dart"
     show splitCloser;
 
+import "package:_fe_analyzer_shared/src/scanner/scanner.dart"
+    show scanString, Token;
+
 import "package:front_end/src/fasta/problems.dart";
+
+import 'package:kernel/ast.dart' show Nullability;
 import 'package:kernel/text/text_serialization_verifier.dart';
 
 abstract class ParsedType {
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
index 40c5e2e..c3df660 100644
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -2,6 +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.
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, DiagnosticMessageHandler;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show Token, scanString;
+
 import 'package:expect/expect.dart' show Expect;
 
 import 'package:kernel/ast.dart' show Expression, ProcedureKind;
@@ -11,9 +19,6 @@
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions;
 
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler;
-
 import 'package:front_end/src/base/processed_options.dart'
     show ProcessedOptions;
 
@@ -31,10 +36,6 @@
 import 'package:front_end/src/fasta/kernel/unlinked_scope.dart'
     show UnlinkedScope;
 
-import 'package:front_end/src/fasta/parser.dart' show Parser;
-
-import 'package:front_end/src/fasta/scanner.dart' show Token, scanString;
-
 import 'package:front_end/src/fasta/scope.dart' show Scope;
 
 import 'package:front_end/src/fasta/source/source_library_builder.dart'
diff --git a/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart b/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
new file mode 100644
index 0000000..167365c
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
@@ -0,0 +1,152 @@
+// 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:io' show Directory, Platform;
+
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:_fe_analyzer_shared/src/testing/id.dart'
+    show ActualData, Id, IdKind;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+    show ExperimentalFlag;
+import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_loader.dart';
+
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart' hide Variance;
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/'
+      'data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const AssignedVariablesDataComputer(), [
+        new TestConfig(cfeMarker, 'cfe with nnbd',
+            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
+      ]),
+      skipList: [
+        'for.dart',
+        'for_element.dart',
+      ]);
+}
+
+class AssignedVariablesDataComputer extends DataComputer<_Data> {
+  const AssignedVariablesDataComputer();
+
+  @override
+  DataInterpreter<_Data> get dataValidator =>
+      const _AssignedVariablesDataInterpreter();
+
+  /// Function that computes a data mapping for [member].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeMemberData(InternalCompilerResult compilerResult, Member member,
+      Map<Id, ActualData<_Data>> actualMap,
+      {bool verbose}) {
+    MemberBuilderImpl memberBuilder =
+        lookupMemberBuilder(compilerResult, member);
+    AssignedVariablesForTesting<TreeNode, VariableDeclaration>
+        assignedVariables = memberBuilder
+            .dataForTesting.inferenceData.flowAnalysisResult.assignedVariables;
+    if (assignedVariables == null) return;
+    member.accept(new AssignedVariablesDataExtractor(
+        compilerResult, actualMap, assignedVariables));
+  }
+}
+
+class AssignedVariablesDataExtractor extends CfeDataExtractor<_Data> {
+  final SourceLoaderDataForTesting _sourceLoaderDataForTesting;
+  final AssignedVariablesForTesting<TreeNode, VariableDeclaration>
+      _assignedVariables;
+
+  AssignedVariablesDataExtractor(InternalCompilerResult compilerResult,
+      Map<Id, ActualData<_Data>> actualMap, this._assignedVariables)
+      : _sourceLoaderDataForTesting =
+            compilerResult.kernelTargetForTesting.loader.dataForTesting,
+        super(compilerResult, actualMap);
+
+  @override
+  _Data computeMemberValue(Id id, Member member) {
+    return new _Data(
+        _convertVars(_assignedVariables.declaredAtTopLevel),
+        _convertVars(_assignedVariables.writtenAnywhere),
+        _convertVars(_assignedVariables.capturedAnywhere));
+  }
+
+  Set<String> _convertVars(Iterable<VariableDeclaration> x) =>
+      x.map((e) => e.name).toSet();
+
+  @override
+  _Data computeNodeValue(Id id, TreeNode node) {
+    switch (id.kind) {
+      case IdKind.iterator:
+      case IdKind.current:
+      case IdKind.moveNext:
+        return null;
+      default:
+    }
+    TreeNode alias = _sourceLoaderDataForTesting.toOriginal(node);
+    if (!_assignedVariables.isTracked(alias)) return null;
+    return new _Data(
+        _convertVars(_assignedVariables.declaredInNode(alias)),
+        _convertVars(_assignedVariables.writtenInNode(alias)),
+        _convertVars(_assignedVariables.capturedInNode(alias)));
+  }
+}
+
+class _AssignedVariablesDataInterpreter implements DataInterpreter<_Data> {
+  const _AssignedVariablesDataInterpreter();
+
+  @override
+  String getText(_Data actualData) {
+    var parts = <String>[];
+    if (actualData.declared.isNotEmpty) {
+      parts.add('declared=${_setToString(actualData.declared)}');
+    }
+    if (actualData.assigned.isNotEmpty) {
+      parts.add('assigned=${_setToString(actualData.assigned)}');
+    }
+    if (actualData.captured.isNotEmpty) {
+      parts.add('captured=${_setToString(actualData.captured)}');
+    }
+    if (parts.isEmpty) return 'none';
+    return parts.join(', ');
+  }
+
+  @override
+  String isAsExpected(_Data actualData, String expectedData) {
+    var actualDataText = getText(actualData);
+    if (actualDataText == expectedData) {
+      return null;
+    } else {
+      return 'Expected "$expectedData", got "$actualDataText"';
+    }
+  }
+
+  @override
+  bool isEmpty(_Data actualData) =>
+      actualData.assigned.isEmpty && actualData.captured.isEmpty;
+
+  String _setToString(Set<String> values) {
+    List<String> sortedValues = values.toList()..sort();
+    return '{${sortedValues.join(', ')}}';
+  }
+}
+
+class _Data {
+  final Set<String> declared;
+
+  final Set<String> assigned;
+
+  final Set<String> captured;
+
+  _Data(this.declared, this.assigned, this.captured);
+}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/assert.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/assert.dart
deleted file mode 100644
index 27fab8f..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/assert.dart
+++ /dev/null
@@ -1,11 +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.
-
-f() {
-  late int v;
-  assert((v = 0) >= 0, v);
-  // TODO(paulberry): `v` should be considered unassigned here, because the
-  // assert statement doesn't execute in release mode.
-  v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/assignment.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/assignment.dart
deleted file mode 100644
index bd3472b..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/assignment.dart
+++ /dev/null
@@ -1,39 +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.
-
-leftExpression() {
-  late List<int> v;
-  /*unassigned*/ v[0] = (v = [1, 2])[1];
-  v;
-}
-
-leftLocal_compound() {
-  late int v;
-  /*unassigned*/ v += 1;
-}
-
-leftLocal_compound_assignInRight() {
-  late int v;
-  /*unassigned*/ v += (v = /*unassigned*/ v);
-}
-
-leftLocal_pure_eq() {
-  late int v;
-  v = 0;
-}
-
-leftLocal_pure_eq_self() {
-  late int v;
-  v = /*unassigned*/ v;
-}
-
-leftLocal_pure_questionEq() {
-  late int v;
-  /*unassigned*/ v ??= 0;
-}
-
-leftLocal_pure_questionEq_self() {
-  late int v;
-  /*unassigned*/ v ??= /*unassigned*/ v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/binary_expression.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/binary_expression.dart
deleted file mode 100644
index 370b2f8..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/binary_expression.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.
-
-ifNull_left() {
-  late int v;
-  (v = 0) ?? 0;
-  v;
-}
-
-ifNull_right(int a) {
-  late int v;
-  a ?? (v = 0);
-  /*unassigned*/ v;
-}
-
-logicalAnd_left(bool c) {
-  late int v;
-  ((v = 0) >= 0) && c;
-  v;
-}
-
-logicalAnd_right(bool c) {
-  late int v;
-  c && ((v = 0) >= 0);
-  /*unassigned*/ v;
-}
-
-logicalOr_left(bool c) {
-  late int v;
-  ((v = 0) >= 0) || c;
-  v;
-}
-
-logicalOr_right(bool c) {
-  late int v;
-  c || ((v = 0) >= 0);
-  /*unassigned*/ v;
-}
-
-plus_left() {
-  late int v;
-  (v = 0) + 1;
-  v;
-}
-
-plus_right() {
-  late int v;
-  1 + (v = 0);
-  v;
-}
-
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/do.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/do.dart
deleted file mode 100644
index 9b637e2..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/do.dart
+++ /dev/null
@@ -1,92 +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.
-
-break_afterAssignment(bool c) {
-  late int v;
-  do {
-    v = 0;
-    v;
-    if (c) break;
-  } while (c);
-  v;
-}
-
-break_beforeAssignment(bool c) {
-  late int v;
-  do {
-    if (c) break;
-    v = 0;
-  } while (c);
-  /*unassigned*/ v;
-}
-
-breakOuterFromInner(bool c) {
-  late int v1, v2, v3;
-  L1: do {
-    do {
-      v1 = 0;
-      if (c) break L1;
-      v2 = 0;
-      v3 = 0;
-    } while (c);
-    v2;
-  } while (c);
-  v1;
-  /*unassigned*/ v3;
-}
-
-condition() {
-  late int v1, v2;
-  do {
-    /*unassigned*/ v1; // assigned in the condition, but not yet
-  } while ((v1 = 0) + (v2 = 0) >= 0);
-  v2;
-}
-
-condition_break(bool c) {
-  late int v;
-  do {
-    if (c) break;
-  } while ((v = 0) >= 0);
-  /*unassigned*/ v;
-}
-
-condition_break_continue(bool c1, bool c2) {
-  late int v1, v2, v3, v4, v5, v6;
-  do {
-    v1 = 0; // visible outside, visible to the condition
-    if (c1) break;
-    v2 = 0; // not visible outside, visible to the condition
-    v3 = 0; // not visible outside, visible to the condition
-    if (c2) continue;
-    v4 = 0; // not visible
-    v5 = 0; // not visible
-  } while ((v6 = v1 + v2 + /*unassigned*/ v4) == 0); // has break => v6 is not visible outside
-  v1;
-  /*unassigned*/ v3;
-  /*unassigned*/ v5;
-  /*unassigned*/ v6;
-}
-
-condition_continue(bool c) {
-  late int v1, v2, v3, v4;
-  do {
-    v1 = 0; // visible outside, visible to the condition
-    if (c) continue;
-    v2 = 0; // not visible
-    v3 = 0; // not visible
-  } while ((v4 = v1 + /*unassigned*/ v2) == 0); // no break => v4 visible outside
-  v1;
-  /*unassigned*/ v3;
-  v4;
-}
-
-continue_beforeAssignment(bool c) {
-  late int v;
-  do {
-    if (c) continue;
-    v = 0;
-  } while (c);
-  /*unassigned*/ v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/for.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/for.dart
deleted file mode 100644
index 37d9284..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/for.dart
+++ /dev/null
@@ -1,125 +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.
-
-for_body(bool c) {
-  late int v;
-  for (; c;) {
-    v = 0;
-  }
-  /*unassigned*/ v;
-}
-
-for_break(bool c) {
-  late int v1, v2;
-  for (; c;) {
-    v1 = 0;
-    if (c) break;
-    v2 = 0;
-  }
-  /*unassigned*/ v1;
-  /*unassigned*/ v2;
-}
-
-for_break_updaters(bool c) {
-  late int v1, v2;
-  for (; c; v1 + v2) {
-    v1 = 0;
-    if (c) break;
-    v2 = 0;
-  }
-}
-
-for_condition() {
-  late int v;
-  for (; (v = 0) >= 0;) {
-    v;
-  }
-  v;
-}
-
-for_continue(bool c) {
-  late int v1, v2;
-  for (; c;) {
-    v1 = 0;
-    if (c) continue;
-    v2 = 0;
-  }
-  /*unassigned*/ v1;
-  /*unassigned*/ v2;
-}
-
-for_continue_updaters(bool c) {
-  late int v1, v2;
-  for (; c; v1 + /*unassigned*/ v2) {
-    v1 = 0;
-    if (c) continue;
-    v2 = 0;
-  }
-}
-
-for_initializer_expression() {
-  late int v;
-  for (v = 0;;) {
-    v;
-  }
-  v;
-}
-
-for_initializer_variable() {
-  late int v;
-  for (var t = (v = 0);;) {
-    v;
-  }
-  v;
-}
-
-for_updaters(bool c) {
-  late int v1, v2, v3, v4;
-  for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) {
-    /*unassigned*/ v1;
-  }
-  /*unassigned*/ v2;
-}
-
-for_updaters_afterBody(bool c) {
-  late int v;
-  for (; c; v) {
-    v = 0;
-  }
-}
-
-collection_for_body(bool c) {
-  late int v;
-  [for (; c;) (v = 0)];
-  /*unassigned*/ v;
-}
-
-collection_for_condition() {
-  late int v;
-  [for (; (v = 0) >= 0;) null];
-  v;
-}
-
-collection_for_initializer_expression() {
-  late int v;
-  [for (v = 0;;) v];
-  v;
-}
-
-collection_for_initializer_variable() {
-  late int v;
-  [for (var t = (v = 0);;) v];
-  v;
-}
-
-collection_for_updaters(bool c) {
-  late int v1, v2, v3, v4;
-  [for (; c; v1 = 0, v2 = 0, v3 = 0, /*unassigned*/ v4) /*unassigned*/ v1];
-  /*unassigned*/ v2;
-}
-
-collection_for_updaters_afterBody(bool c) {
-  late int v;
-  [for (; c; v) (v = 0)];
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/for_each.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/for_each.dart
deleted file mode 100644
index 7276903..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/for_each.dart
+++ /dev/null
@@ -1,65 +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.
-
-forEach() {
-  late Object v1, v2;
-  for (var _ in (v1 = [0, 1, 2])) {
-    v2 = 0;
-  }
-  v1;
-  /*unassigned*/ v2;
-}
-
-forEach_break(bool c) {
-  late int v1, v2;
-  for (var _ in [0, 1, 2]) {
-    v1 = 0;
-    if (c) break;
-    v2 = 0;
-  }
-  /*unassigned*/ v1;
-  /*unassigned*/ v2;
-}
-
-forEach_continue(bool c) {
-  late int v1, v2;
-  for (var _ in [0, 1, 2]) {
-    v1 = 0;
-    if (c) continue;
-    v2 = 0;
-  }
-  /*unassigned*/ v1;
-  /*unassigned*/ v2;
-}
-
-forEach_assigns_to_identifier() {
-  late int i;
-  for (i in [0, 1, 2]) {
-    i;
-  }
-  /*unassigned*/ i;
-}
-
-forEach_assigns_to_declared_var() {
-  for (int i in [0, 1, 2]) {
-    i;
-  }
-}
-
-collection_forEach() {
-  late Object v1, v2;
-  [for (var _ in (v1 = [0, 1, 2])) (v2 = 0)];
-  v1;
-  /*unassigned*/ v2;
-}
-
-collection_forEach_assigns_to_identifier() {
-  late int i;
-  [for (i in [0, 1, 2]) i];
-  /*unassigned*/ i;
-}
-
-collection_forEach_assigns_to_declared_var() {
-  [for (int i in [0, 1, 2]) i];
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/function_expression.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/function_expression.dart
deleted file mode 100644
index 68d706b..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/function_expression.dart
+++ /dev/null
@@ -1,72 +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.
-
-closure_read() {
-  late int v1, v2;
-  
-  v1 = 0;
-  
-  [0, 1, 2].forEach((t) {
-    v1;
-    /*unassigned*/ v2;
-  });
-}
-
-closure_write() {
-  late int v;
-  
-  [0, 1, 2].forEach((t) {
-    v = t;
-  });
-
-  /*unassigned*/ v;
-}
-
-localFunction_local() {
-  late int v;
-
-  v = 0;
-
-  void f() {
-    late int v;
-    /*unassigned*/ v;
-  }
-}
-
-localFunction_local2() {
-  late int v1;
-
-  v1 = 0;
-
-  void f() {
-    late int v2, v3;
-    v2 = 0;
-    v1;
-    v2;
-    /*unassigned*/ v3;
-  }
-}
-
-localFunction_read() {
-  late int v1, v2, v3;
-
-  v1 = 0;
-
-  void f() {
-    v1;
-    /*unassigned*/ v2;
-  }
-
-  v2 = 0;
-}
-
-localFunction_write() {
-  late int v;
-
-  void f() {
-    v = 0;
-  }
-
-  /*unassigned*/ v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/if.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/if.dart
deleted file mode 100644
index 6f4abca..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/if.dart
+++ /dev/null
@@ -1,89 +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.
-
-if_condition() {
-  late int v;
-  if ((v = 0) >= 0) {
-    v;
-  } else {
-    v;
-  }
-  v;
-}
-
-if_then(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-  }
-  /*unassigned*/ v;
-}
-
-if_thenElse_all(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-    v;
-  } else {
-    v = 0;
-    v;
-  }
-  v;
-}
-
-if_thenElse_else(bool c) {
-  late int v;
-  if (c) {
-    // not assigned
-  } else {
-    v = 0;
-  }
-  /*unassigned*/ v;
-}
-
-if_thenElse_then(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-  } else {
-    // not assigned
-  }
-  /*unassigned*/ v;
-}
-
-if_thenElse_then_exit_alwaysThrows(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-  } else {
-    foo();
-  }
-  // TODO(paulberry): flow analysis should understand that foo never returns, so
-  // `v` is definitely assigned here.
-  /*unassigned*/ v;
-}
-
-Never foo() {
-  throw Object();
-}
-
-if_thenElse_then_exit_return(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-  } else {
-    return;
-  }
-  v;
-}
-
-if_thenElse_then_exit_throw(bool c) {
-  late int v;
-  if (c) {
-    v = 0;
-  } else {
-    throw 42;
-  }
-  v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/switch.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/switch.dart
deleted file mode 100644
index 0c83ea0..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/switch.dart
+++ /dev/null
@@ -1,81 +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.
-
-case1_default(int e) {
-  late int v;
-  switch (e) {
-    case 1:
-      v = 0;
-      break;
-    case 2:
-      // not assigned
-      break;
-    default:
-      v = 0;
-  }
-  /*unassigned*/ v;
-}
-
-case2_default(int e) {
-  late int v1, v2;
-  switch (e) {
-    case 1:
-      v1 = 0;
-      v2 = 0;
-      v1;
-      break;
-    default:
-      v1 = 0;
-      v1;
-  }
-  v1;
-  /*unassigned*/ v2;
-}
-
-case_default_break(int e, bool c) {
-  late int v1, v2;
-  switch (e) {
-    case 1:
-      v1 = 0;
-      if (c) break;
-      v2 = 0;
-      break;
-    default:
-      v1 = 0;
-      if (c) break;
-      v2 = 0;
-  }
-  v1;
-  /*unassigned*/ v2;
-}
-
-case_default_continue(int e) {
-  late int v;
-  switch (e) {
-    L: case 1:
-      v = 0;
-      break;
-    case 2:
-      continue L;
-    default:
-      v = 0;
-  }
-  v;
-}
-
-case_noDefault(int e) {
-  late int v;
-  switch (e) {
-    case 1:
-      v = 0;
-      break;
-  }
-  /*unassigned*/ v;
-}
-
-condition() {
-  late int v;
-  switch (v = 0) {}
-  v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/data/while.dart b/pkg/front_end/test/flow_analysis/definite_assignment/data/while.dart
deleted file mode 100644
index 487d72b..0000000
--- a/pkg/front_end/test/flow_analysis/definite_assignment/data/while.dart
+++ /dev/null
@@ -1,123 +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.
-
-condition() {
-  late int v;
-  while ((v = 0) >= 0) {
-    v;
-  }
-  v;
-}
-
-condition_notTrue(bool c) {
-  late int v1, v2;
-  while (c) {
-    v1 = 0;
-    v2 = 0;
-    v1;
-  }
-  /*unassigned*/ v2;
-}
-
-true_break_afterAssignment(bool c) {
-  late int v1, v2;
-  while (true) {
-    v1 = 0;
-    v1;
-    if (c) break;
-    v1;
-    v2 = 0;
-    v2;
-  }
-  v1;
-}
-
-true_break_beforeAssignment(bool c) {
-  late int v1, v2;
-  while (true) {
-    if (c) break;
-    v1 = 0;
-    v2 = 0;
-    v2;
-  }
-  /*unassigned*/ v1;
-}
-
-true_break_if(bool c) {
-  late int v;
-  while (true) {
-    if (c) {
-      v = 0;
-      break;
-    } else {
-      v = 0;
-      break;
-    }
-    v;
-  }
-  v;
-}
-
-true_break_if2(bool c) {
-  late Object v;
-  while (true) {
-    if (c) {
-      break;
-    } else {
-      v = 0;
-    }
-    v;
-  }
-}
-
-true_break_if3(bool c) {
-  late int v1, v2;
-  while (true) {
-    if (c) {
-      v1 = 0;
-      v2 = 0;
-      if (c) break;
-    } else {
-      if (c) break;
-      v1 = 0;
-      v2 = 0;
-    }
-    v1;
-  }
-  /*unassigned*/ v2;
-}
-
-true_breakOuterFromInner(bool c) {
-  late int v1, v2, v3;
-  L1: while (true) {
-    L2: while (true) {
-      v1 = 0;
-      if (c) break L1;
-      v2 = 0;
-      v3 = 0;
-      if (c) break L2;
-    }
-    v2;
-  }
-  v1;
-  /*unassigned*/ v3;
-}
-
-true_continue(bool c) {
-  late int v;
-  while (true) {
-    if (c) continue;
-    v = 0;
-  }
-  /*unassigned*/ v;
-}
-
-true_noBreak(bool c) {
-  late int v;
-  while (true) {
-    // No assignment, but not break.
-    // So, we don't exit the loop.
-  }
-  /*unassigned*/ v;
-}
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart b/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
new file mode 100644
index 0000000..939b23d
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
@@ -0,0 +1,85 @@
+// 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: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'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+    show ExperimentalFlag;
+
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart' hide Variance;
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/'
+      'data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const DefiniteAssignmentDataComputer(), [
+        new TestConfig(cfeMarker, 'cfe with nnbd',
+            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
+      ]),
+      skipList: [
+        // TODO(dmitryas): Run all definite assignment tests.
+        'assert.dart',
+        'assignment.dart',
+        'binary_expression.dart',
+        'conditional_expression.dart',
+        'do.dart',
+        'for.dart',
+        'for_each.dart',
+        'function_expression.dart',
+        'if.dart',
+        'initialization.dart',
+        'switch.dart',
+        'try.dart',
+        'while.dart',
+      ]);
+}
+
+class DefiniteAssignmentDataComputer extends DataComputer<String> {
+  const DefiniteAssignmentDataComputer();
+
+  @override
+  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+
+  /// Function that computes a data mapping for [member].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeMemberData(InternalCompilerResult compilerResult, Member member,
+      Map<Id, ActualData<String>> actualMap,
+      {bool verbose}) {
+    MemberBuilderImpl memberBuilder =
+        lookupMemberBuilder(compilerResult, member);
+    member.accept(new DefiniteAssignmentDataExtractor(compilerResult, actualMap,
+        memberBuilder.dataForTesting.inferenceData.flowAnalysisResult));
+  }
+}
+
+class DefiniteAssignmentDataExtractor extends CfeDataExtractor<String> {
+  final FlowAnalysisResult _flowResult;
+
+  DefiniteAssignmentDataExtractor(InternalCompilerResult compilerResult,
+      Map<Id, ActualData<String>> actualMap, this._flowResult)
+      : super(compilerResult, actualMap);
+
+  @override
+  String computeNodeValue(Id id, TreeNode node) {
+    if (node is VariableGet) {
+      if (_flowResult.unassignedNodes.contains(node.variable)) {
+        return 'unassigned';
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/nullability/data/assign.dart b/pkg/front_end/test/flow_analysis/nullability/data/assign.dart
deleted file mode 100644
index f120d03..0000000
--- a/pkg/front_end/test/flow_analysis/nullability/data/assign.dart
+++ /dev/null
@@ -1,32 +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.
-
-void toNonNull(int? x) {
-  if (x != null) return;
-  x;
-  x = 0;
-  // TODO(paulberry): x should be known to be non-nullable now
-  x;
-}
-
-void toNull(int? x) {
-  if (x == null) return;
-  /*nonNullable*/ x;
-  x = null;
-  x;
-}
-
-void toUnknown_fromNotNull(int? a, int? b) {
-  if (a == null) return;
-  /*nonNullable*/ a;
-  a = b;
-  a;
-}
-
-void toUnknown_fromNull(int? a, int? b) {
-  if (a != null) return;
-  a;
-  a = b;
-  a;
-}
diff --git a/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart b/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
new file mode 100644
index 0000000..2f9f044
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
@@ -0,0 +1,73 @@
+// 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: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'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+    show ExperimentalFlag;
+
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:kernel/ast.dart' hide Variance;
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../../_fe_analyzer_shared/test/flow_analysis/nullability/data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const NullabilityDataComputer(), [
+        new TestConfig(cfeMarker, 'cfe with nnbd',
+            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
+      ]),
+      skipList: [
+        // TODO(dmitryas): Run all nullability tests.
+        'assign.dart',
+        'if.dart',
+        'is.dart',
+        'logical.dart',
+        'null_aware_access.dart',
+        'null_check.dart',
+        'potentially_mutated_in_closure.dart',
+        'try_finally.dart',
+        'while.dart',
+      ]);
+}
+
+class NullabilityDataComputer extends DataComputer<String> {
+  const NullabilityDataComputer();
+
+  @override
+  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+
+  /// Function that computes a data mapping for [member].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeMemberData(InternalCompilerResult compilerResult, Member member,
+      Map<Id, ActualData<String>> actualMap,
+      {bool verbose}) {
+    member.accept(new NullabilityDataExtractor(compilerResult, actualMap));
+  }
+}
+
+class NullabilityDataExtractor extends CfeDataExtractor<String> {
+  NullabilityDataExtractor(InternalCompilerResult compilerResult,
+      Map<Id, ActualData<String>> actualMap)
+      : super(compilerResult, actualMap);
+
+  @override
+  String computeNodeValue(Id id, TreeNode node) {
+    if (node is VariableGet && node.promotedType != null) {
+      if (node.variable.type.nullability != Nullability.nonNullable &&
+          node.promotedType.nullability == Nullability.nonNullable) {
+        return 'nonNullable';
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/early_exit.dart b/pkg/front_end/test/flow_analysis/reachability/data/early_exit.dart
deleted file mode 100644
index b244972..0000000
--- a/pkg/front_end/test/flow_analysis/reachability/data/early_exit.dart
+++ /dev/null
@@ -1,16 +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.
-
-/*member: beforeSplitStatement:doesNotComplete*/
-void beforeSplitStatement(bool b, int i) {
-  return;
-  /*stmt: unreachable*/ do {} while (b);
-  /*stmt: unreachable*/ for (;;) {}
-  /*stmt: unreachable*/ for (var _ in []) {}
-  /*stmt: unreachable*/ if (b) {}
-  /*stmt: unreachable*/ switch (i) {
-  }
-  /*stmt: unreachable*/ try {} finally {}
-  /*stmt: unreachable*/ while (b) {}
-}
diff --git a/pkg/front_end/test/flow_analysis/reachability/data/function_body.dart b/pkg/front_end/test/flow_analysis/reachability/data/function_body.dart
deleted file mode 100644
index 81c1e96..0000000
--- a/pkg/front_end/test/flow_analysis/reachability/data/function_body.dart
+++ /dev/null
@@ -1,12 +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.
-
-/*member: hasReturn:doesNotComplete*/
-int hasReturn() {
-  return 42;
-}
-
-void noReturn() {
-  1;
-}
diff --git a/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart b/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
new file mode 100644
index 0000000..7397b38
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
@@ -0,0 +1,138 @@
+// 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: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'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+    show ExperimentalFlag;
+
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart' hide Variance;
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../../_fe_analyzer_shared/test/flow_analysis/reachability/data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const ReachabilityDataComputer(), [
+        new TestConfig(cfeMarker, 'cfe with nnbd',
+            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
+      ]));
+}
+
+class ReachabilityDataComputer
+    extends DataComputer<Set<_ReachabilityAssertion>> {
+  const ReachabilityDataComputer();
+
+  @override
+  DataInterpreter<Set<_ReachabilityAssertion>> get dataValidator =>
+      const _ReachabilityDataInterpreter();
+
+  /// Function that computes a data mapping for [member].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeMemberData(InternalCompilerResult compilerResult, Member member,
+      Map<Id, ActualData<Set<_ReachabilityAssertion>>> actualMap,
+      {bool verbose}) {
+    MemberBuilderImpl memberBuilder =
+        lookupMemberBuilder(compilerResult, member);
+    member.accept(new ReachabilityDataExtractor(compilerResult, actualMap,
+        memberBuilder.dataForTesting.inferenceData.flowAnalysisResult));
+  }
+}
+
+class ReachabilityDataExtractor
+    extends CfeDataExtractor<Set<_ReachabilityAssertion>> {
+  final FlowAnalysisResult _flowResult;
+
+  ReachabilityDataExtractor(
+      InternalCompilerResult compilerResult,
+      Map<Id, ActualData<Set<_ReachabilityAssertion>>> actualMap,
+      this._flowResult)
+      : super(compilerResult, actualMap);
+
+  @override
+  Set<_ReachabilityAssertion> computeMemberValue(Id id, Member member) {
+    Set<_ReachabilityAssertion> result = {};
+    if (member.function != null) {
+      if (_flowResult.functionBodiesThatDontComplete
+          .contains(member.function.body)) {
+        result.add(_ReachabilityAssertion.doesNotComplete);
+      }
+    }
+    return result.isEmpty ? null : result;
+  }
+
+  @override
+  Set<_ReachabilityAssertion> computeNodeValue(Id id, TreeNode node) {
+    Set<_ReachabilityAssertion> result = {};
+    if (node is Expression && node.parent is ExpressionStatement) {
+      // The reachability of an expression statement and the statement it
+      // contains should always be the same.  We check this with an assert
+      // statement, and only annotate the expression statement, to reduce the
+      // amount of redundancy in the test files.
+      assert(_flowResult.unreachableNodes.contains(node) ==
+          _flowResult.unreachableNodes.contains(node.parent));
+    } else if (_flowResult.unreachableNodes.contains(node)) {
+      result.add(_ReachabilityAssertion.unreachable);
+    }
+    if (node is FunctionDeclaration) {
+      Statement body = node.function.body;
+      if (body != null &&
+          _flowResult.functionBodiesThatDontComplete.contains(body)) {
+        result.add(_ReachabilityAssertion.doesNotComplete);
+      }
+    }
+    return result.isEmpty ? null : result;
+  }
+}
+
+enum _ReachabilityAssertion {
+  doesNotComplete,
+  unreachable,
+}
+
+class _ReachabilityDataInterpreter
+    implements DataInterpreter<Set<_ReachabilityAssertion>> {
+  const _ReachabilityDataInterpreter();
+
+  @override
+  String getText(Set<_ReachabilityAssertion> actualData) =>
+      _sortedRepresentation(_toStrings(actualData));
+
+  @override
+  String isAsExpected(
+      Set<_ReachabilityAssertion> actualData, String expectedData) {
+    var actualStrings = _toStrings(actualData);
+    var actualSorted = _sortedRepresentation(actualStrings);
+    var expectedSorted = _sortedRepresentation(expectedData?.split(','));
+    if (actualSorted == expectedSorted) {
+      return null;
+    } else {
+      return 'Expected $expectedData, got $actualSorted';
+    }
+  }
+
+  @override
+  bool isEmpty(Set<_ReachabilityAssertion> actualData) => actualData.isEmpty;
+
+  String _sortedRepresentation(Iterable<String> values) {
+    var list = values == null || values.isEmpty ? ['none'] : values.toList();
+    list.sort();
+    return list.join(',');
+  }
+
+  List<String> _toStrings(Set<_ReachabilityAssertion> actualData) => actualData
+      .map((flowAssertion) => flowAssertion.toString().split('.')[1])
+      .toList();
+}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/assert.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/assert.dart
deleted file mode 100644
index 5695e66..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/assert.dart
+++ /dev/null
@@ -1,10 +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.
-
-void assertStatement(Object x) {
-  assert((x is int ? /*int*/ x : throw 'foo') == 0);
-  // TODO(paulberry): should not be promoted because the assertion won't execute
-  // in release mode.  See https://github.com/dart-lang/sdk/issues/38761.
-  /*int*/ x;
-}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/assignment.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/assignment.dart
deleted file mode 100644
index 5e1d384..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/assignment.dart
+++ /dev/null
@@ -1,10 +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.
-
-f(Object x) {
-  if (x is String) {
-    x = 42;
-    x;
-  }
-}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/conditional.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/conditional.dart
deleted file mode 100644
index d1bb106..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/conditional.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.
-
-void conditional_both(bool b, Object x) {
-  b ? ((x is num) || (throw 1)) : ((x is int) || (throw 2));
-  /*num*/ x;
-}
-
-void conditional_else(bool b, Object x) {
-  b ? 0 : ((x is int) || (throw 2));
-  x;
-}
-
-void conditional_then(bool b, Object x) {
-  b ? ((x is num) || (throw 1)) : 0;
-  x;
-}
-
-int conditional_in_expression_function_body(Object o) =>
-    o is int ? /*int*/ o : 0;
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/constructor_initializer.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/constructor_initializer.dart
deleted file mode 100644
index 4d37319..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/constructor_initializer.dart
+++ /dev/null
@@ -1,18 +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.
-
-class C {
-  int y;
-  C.normalInitializer(Object x) : y = x is int ? /*int*/ x : throw 'foo' {
-    /*int*/ x;
-  }
-  C.assertInitializer(Object x)
-      : y = 0,
-        assert((x is int ? /*int*/ x : throw 'foo') == 0) {
-    // TODO(paulberry): should not be promoted because the assertion won't
-    // execute in release mode.  See
-    // https://github.com/dart-lang/sdk/issues/38761
-    /*int*/ x;
-  }
-}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/for.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/for.dart
deleted file mode 100644
index 81e631f..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/for.dart
+++ /dev/null
@@ -1,145 +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.
-
-Object g() => Null;
-
-void for_declaredVar() {
-  for (Object x = g(); x is int; x = g()) {
-    /*int*/ x;
-  }
-}
-
-void for_outerIsType(bool b, Object x) {
-  if (x is String) {
-    for (; b;) {
-      /*String*/ x;
-    }
-    /*String*/ x;
-  }
-}
-
-void for_outerIsType_loopAssigned_body(bool b, Object x) {
-  if (x is String) {
-    for (; b;) {
-      x;
-      x = 42;
-    }
-    x;
-  }
-}
-
-void for_outerIsType_loopAssigned_body_emptyCondition(bool b, Object x) {
-  if (x is String) {
-    for (;;) {
-      if (!b) break;
-      x;
-      x = 42;
-    }
-    x;
-  }
-}
-
-void for_outerIsType_loopAssigned_condition(Object x) {
-  if (x is String) {
-    for (; (x = 42) > 0;) {
-      x;
-    }
-    x;
-  }
-}
-
-void for_outerIsType_loopAssigned_updaters(bool b, Object x) {
-  if (x is String) {
-    for (; b; x = 42) {
-      x;
-    }
-    x;
-  }
-}
-
-void for_outerIsType_loopAssigned_updaters_emptyCondition(bool b, Object x) {
-  if (x is String) {
-    for (;; x = 42) {
-      if (!b) break;
-      x;
-    }
-    x;
-  }
-}
-
-void forEach_outerIsType_loopAssigned(Object x) {
-  if (x is String) {
-    for (var _ in [0, 1, 2]) {
-      x;
-      x = 42;
-    }
-    x;
-  }
-}
-
-void collection_for_declaredVar() {
-  [for (Object x = g(); x is int; x = g()) /*int*/ x ];
-}
-
-void collection_for_outerIsType(bool b, Object x) {
-  if (x is String) {
-    [for (; b;) /*String*/ x ];
-    /*String*/ x;
-  }
-}
-
-void collection_for_outerIsType_loopAssigned_body(bool b, Object x) {
-  if (x is String) {
-    [
-      for (; b;) [x, (x = 42)]
-    ];
-    x;
-  }
-}
-
-void collection_for_outerIsType_loopAssigned_body_emptyCondition(Object x) {
-  if (x is String) {
-    [
-      for (;;) [x, (x = 42)]
-    ];
-    x;
-  }
-}
-
-void collection_for_outerIsType_loopAssigned_condition(Object x) {
-  if (x is String) {
-    [for (; (x = 42) > 0;) x];
-    x;
-  }
-}
-
-void collection_for_outerIsType_loopAssigned_updaters(bool b, Object x) {
-  if (x is String) {
-    [for (; b; x = 42) x];
-    x;
-  }
-}
-
-void collection_for_outerIsType_loopAssigned_updaters_emptyCondition(Object x) {
-  if (x is String) {
-    [for (;; x = 42) x];
-    x;
-  }
-}
-
-void collection_forEach_outerIsType_loopAssigned(Object x) {
-  if (x is String) {
-    [
-      for (var _ in [0, 1, 2]) [x, (x = 42)]
-    ];
-    x;
-  }
-}
-
-void assign_var_declared_in_loop() {
-  for (int x = 0; x < 10; x++) {
-    bool b = true;
-    b = false;
-  }
-}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/data/if.dart b/pkg/front_end/test/flow_analysis/type_promotion/data/if.dart
deleted file mode 100644
index 60d1eb6..0000000
--- a/pkg/front_end/test/flow_analysis/type_promotion/data/if.dart
+++ /dev/null
@@ -1,80 +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.
-
-combine_empty(bool b, Object v) {
-  if (b) {
-    v is int || (throw 1);
-  } else {
-    v is String || (throw 2);
-  }
-  v;
-}
-
-conditional_isNotType(bool b, Object v) {
-  if (b ? (v is! int) : (v is! num)) {
-    v;
-  } else {
-    /*num*/ v;
-  }
-  v;
-}
-
-conditional_isType(bool b, Object v) {
-  if (b ? (v is int) : (v is num)) {
-    /*num*/ v;
-  } else {
-    v;
-  }
-  v;
-}
-
-isNotType(v) {
-  if (v is! String) {
-    v;
-  } else {
-    /*String*/ v;
-  }
-  v;
-}
-
-isNotType_return(v) {
-  if (v is! String) return;
-  /*String*/ v;
-}
-
-isNotType_throw(v) {
-  if (v is! String) throw 42;
-  /*String*/ v;
-}
-
-isType(v) {
-  if (v is String) {
-    /*String*/ v;
-  } else {
-    v;
-  }
-  v;
-}
-
-isType_thenNonBoolean(Object x) {
-  if ((x is String) != 3) {
-    x;
-  }
-}
-
-logicalNot_isType(v) {
-  if (!(v is String)) {
-    v;
-  } else {
-    /*String*/ v;
-  }
-  v;
-}
-
-void isNotType_return2(bool b, Object x) {
-  if (b) {
-    if (x is! String) return;
-  }
-  x;
-}
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart b/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
new file mode 100644
index 0000000..68b4e14
--- /dev/null
+++ b/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
@@ -0,0 +1,110 @@
+// 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:io' show Directory, Platform;
+import 'package:front_end/src/api_prototype/experimental_flags.dart'
+    show ExperimentalFlag;
+
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
+import 'package:front_end/src/testing/id_testing_utils.dart';
+import 'package:kernel/ast.dart' hide Variance;
+
+main(List<String> args) async {
+  Directory dataDir = new Directory.fromUri(Platform.script.resolve(
+      '../../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/'
+      'data'));
+  await runTests(dataDir,
+      args: args,
+      supportedMarkers: sharedMarkers,
+      createUriForFileName: createUriForFileName,
+      onFailure: onFailure,
+      runTest: runTestFor(const TypePromotionDataComputer(), [
+        new TestConfig(cfeMarker, 'cfe with nnbd',
+            experimentalFlags: const {ExperimentalFlag.nonNullable: true})
+      ]),
+      skipList: [
+        // TODO(dmitryas): Run all type promotion tests.
+        'as.dart',
+        'assert.dart',
+        'assignment.dart',
+        'assignment_promoted.dart',
+        'assigned_anywhere.dart',
+        'binary.dart',
+        'bug39178.dart',
+        'conditional.dart',
+        'constructor_initializer.dart',
+        'do.dart',
+        'for.dart',
+        'function_expression.dart',
+        'if.dart',
+        'initialization.dart',
+        'inside_closure.dart',
+        'not_promoted.dart',
+        'null_aware_assignment.dart',
+        'null_check.dart',
+        'potentially_mutated.dart',
+        'switch.dart',
+        'try_catch.dart',
+        'try_catch_finally.dart',
+        'try_finally.dart',
+        'type_parameter.dart',
+        'while.dart',
+        'write_capture.dart',
+      ]);
+}
+
+class TypePromotionDataComputer extends DataComputer<DartType> {
+  const TypePromotionDataComputer();
+
+  @override
+  DataInterpreter<DartType> get dataValidator =>
+      const _TypePromotionDataInterpreter();
+
+  /// Function that computes a data mapping for [member].
+  ///
+  /// Fills [actualMap] with the data.
+  void computeMemberData(InternalCompilerResult compilerResult, Member member,
+      Map<Id, ActualData<DartType>> actualMap,
+      {bool verbose}) {
+    member.accept(new TypePromotionDataExtractor(compilerResult, actualMap));
+  }
+}
+
+class TypePromotionDataExtractor extends CfeDataExtractor<DartType> {
+  TypePromotionDataExtractor(InternalCompilerResult compilerResult,
+      Map<Id, ActualData<DartType>> actualMap)
+      : super(compilerResult, actualMap);
+
+  @override
+  DartType computeNodeValue(Id id, TreeNode node) {
+    if (node is VariableGet) {
+      return node.promotedType;
+    }
+    return null;
+  }
+}
+
+class _TypePromotionDataInterpreter implements DataInterpreter<DartType> {
+  const _TypePromotionDataInterpreter();
+
+  @override
+  String getText(DartType actualData) =>
+      typeToText(actualData, isNonNullableByDefault: true);
+
+  @override
+  String isAsExpected(DartType actualData, String expectedData) {
+    if (getText(actualData) == expectedData) {
+      return null;
+    } else {
+      return 'Expected $expectedData, got $actualData';
+    }
+  }
+
+  @override
+  bool isEmpty(DartType actualData) => actualData == null;
+}
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 92a4fb5..3bacf4c 100644
--- a/pkg/front_end/test/id_testing/id_testing_test.dart
+++ b/pkg/front_end/test/id_testing/id_testing_test.dart
@@ -2,12 +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:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
+    show DataInterpreter, StringDataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'dart:io' show Directory, Platform;
 import 'package:front_end/src/fasta/messages.dart' show FormattedMessage;
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart'
-    show DataInterpreter, StringDataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart'
     show
         CfeDataExtractor,
diff --git a/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart b/pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart
similarity index 100%
rename from pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart
rename to pkg/front_end/test/incremental_bulk_compiler_smoke_suite.dart
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 2b16989..70df064 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
@@ -16,7 +16,7 @@
 import 'package:kernel/kernel.dart' show Component;
 import 'package:kernel/target/targets.dart';
 
-import 'incremental_load_from_dill_test.dart'
+import 'incremental_load_from_dill_suite.dart'
     show checkIsEqual, getOptions, initializedCompile, normalCompile;
 
 Directory outDir;
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
new file mode 100644
index 0000000..82ed6bd
--- /dev/null
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -0,0 +1,1303 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async' show Future;
+
+import 'dart:io' show Directory, File;
+
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, getMessageCodeObject;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:expect/expect.dart' show Expect;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+    show CompilerOptions;
+
+import "package:front_end/src/api_prototype/memory_file_system.dart"
+    show MemoryFileSystem;
+
+import 'package:front_end/src/base/processed_options.dart'
+    show ProcessedOptions;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+    show computePlatformBinariesLocation;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
+import 'package:front_end/src/fasta/fasta_codes.dart'
+    show DiagnosticMessageFromJson, FormattedMessage;
+
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+    show IncrementalCompiler;
+
+import 'package:front_end/src/fasta/incremental_serializer.dart'
+    show IncrementalSerializer;
+
+import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
+
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
+import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
+
+import 'package:kernel/kernel.dart'
+    show
+        Class,
+        Component,
+        EmptyStatement,
+        Field,
+        Library,
+        LibraryDependency,
+        Name,
+        Procedure;
+
+import 'package:kernel/target/targets.dart'
+    show NoneTarget, Target, TargetFlags;
+
+import 'package:kernel/text/ast_to_text.dart' show componentToString;
+
+import "package:testing/testing.dart"
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import "package:vm/target/vm.dart" show VmTarget;
+
+import "package:yaml/yaml.dart" show YamlList, YamlMap, loadYamlNode;
+
+import 'binary_md_dill_reader.dart' show DillComparer;
+
+import "incremental_utils.dart" as util;
+
+import 'utils/io_utils.dart' show computeRepoDir;
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
+}
+
+class Context extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const ReadTest(),
+    const RunCompilations(),
+  ];
+
+  @override
+  Future<void> cleanUp(TestDescription description, Result result) async {
+    await cleanupHelper?.outDir?.delete(recursive: true);
+  }
+
+  TestData cleanupHelper;
+}
+
+class TestData {
+  YamlMap map;
+  Directory outDir;
+}
+
+class ReadTest extends Step<TestDescription, TestData, Context> {
+  const ReadTest();
+
+  String get name => "read test";
+
+  Future<Result<TestData>> run(
+      TestDescription description, Context context) async {
+    Uri uri = description.uri;
+    String contents = await new File.fromUri(uri).readAsString();
+    TestData data = new TestData();
+    data.map = loadYamlNode(contents, sourceUrl: uri);
+    data.outDir =
+        Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
+    context.cleanupHelper = data;
+    return pass(data);
+  }
+}
+
+class RunCompilations extends Step<TestData, TestData, Context> {
+  const RunCompilations();
+
+  String get name => "run compilations";
+
+  Future<Result<TestData>> run(TestData data, Context context) async {
+    YamlMap map = data.map;
+    Set<String> keys = new Set<String>.from(map.keys.cast<String>());
+    keys.remove("type");
+    switch (map["type"]) {
+      case "basic":
+        keys.removeAll(["sources", "entry", "invalidate"]);
+        await basicTest(
+          map["sources"],
+          map["entry"],
+          map["invalidate"],
+          data.outDir,
+        );
+        break;
+      case "newworld":
+        keys.removeAll([
+          "worlds",
+          "modules",
+          "omitPlatform",
+          "target",
+          "incrementalSerialization"
+        ]);
+        await newWorldTest(
+          map["worlds"],
+          map["modules"],
+          map["omitPlatform"],
+          map["target"],
+          map["incrementalSerialization"],
+        );
+        break;
+      default:
+        throw "Unexpected type: ${map['type']}";
+    }
+
+    if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys";
+    return pass(data);
+  }
+}
+
+Future<Null> basicTest(YamlMap sourceFiles, String entryPoint,
+    YamlList invalidate, Directory outDir) async {
+  Uri entryPointUri = outDir.uri.resolve(entryPoint);
+  Set<String> invalidateFilenames =
+      invalidate == null ? new Set<String>() : new Set<String>.from(invalidate);
+  List<Uri> invalidateUris = <Uri>[];
+  Uri packagesUri;
+  for (String filename in sourceFiles.keys) {
+    Uri uri = outDir.uri.resolve(filename);
+    if (invalidateFilenames.contains(filename)) {
+      invalidateUris.add(uri);
+      invalidateFilenames.remove(filename);
+    }
+    String source = sourceFiles[filename];
+    if (filename == ".packages") {
+      packagesUri = uri;
+    }
+    File file = new File.fromUri(uri);
+    await file.parent.create(recursive: true);
+    await file.writeAsString(source);
+  }
+  for (String invalidateFilename in invalidateFilenames) {
+    if (invalidateFilename.startsWith('package:')) {
+      invalidateUris.add(Uri.parse(invalidateFilename));
+    } else {
+      throw "Error in test yaml: $invalidateFilename was not recognized.";
+    }
+  }
+
+  Uri output = outDir.uri.resolve("full.dill");
+  Uri initializedOutput = outDir.uri.resolve("full_from_initialized.dill");
+
+  Stopwatch stopwatch = new Stopwatch()..start();
+  CompilerOptions options = getOptions();
+  if (packagesUri != null) {
+    options.packagesFileUri = packagesUri;
+  }
+  await normalCompile(entryPointUri, output, options: options);
+  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+
+  stopwatch.reset();
+  options = getOptions();
+  if (packagesUri != null) {
+    options.packagesFileUri = packagesUri;
+  }
+  bool initializedResult = await initializedCompile(
+      entryPointUri, initializedOutput, output, invalidateUris,
+      options: options);
+  print("Initialized compile(s) from ${output.pathSegments.last} "
+      "took ${stopwatch.elapsedMilliseconds} ms");
+  Expect.isTrue(initializedResult);
+
+  // Compare the two files.
+  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
+  List<int> initializedDillData =
+      new File.fromUri(initializedOutput).readAsBytesSync();
+  checkIsEqual(normalDillData, initializedDillData);
+}
+
+Future<Map<String, List<int>>> createModules(
+    Map module, final List<int> sdkSummaryData, String targetName) async {
+  final Uri base = Uri.parse("org-dartlang-test:///");
+  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+
+  MemoryFileSystem fs = new MemoryFileSystem(base);
+  fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
+
+  // Setup all sources
+  for (Map moduleSources in module.values) {
+    for (String filename in moduleSources.keys) {
+      String data = moduleSources[filename];
+      Uri uri = base.resolve(filename);
+      if (await fs.entityForUri(uri).exists()) {
+        throw "More than one entry for $filename";
+      }
+      fs.entityForUri(uri).writeAsStringSync(data);
+    }
+  }
+
+  Map<String, List<int>> moduleResult = new Map<String, List<int>>();
+
+  for (String moduleName in module.keys) {
+    List<Uri> moduleSources = new List<Uri>();
+    Uri packagesUri;
+    for (String filename in module[moduleName].keys) {
+      Uri uri = base.resolve(filename);
+      if (uri.pathSegments.last == ".packages") {
+        packagesUri = uri;
+      } else {
+        moduleSources.add(uri);
+      }
+    }
+    CompilerOptions options = getOptions(targetName: targetName);
+    options.fileSystem = fs;
+    options.sdkRoot = null;
+    options.sdkSummary = sdkSummary;
+    options.omitPlatform = true;
+    options.onDiagnostic = (DiagnosticMessage message) {
+      if (getMessageCodeObject(message)?.name == "InferredPackageUri") return;
+      throw message.ansiFormatted;
+    };
+    if (packagesUri != null) {
+      options.packagesFileUri = packagesUri;
+    }
+    TestIncrementalCompiler compiler =
+        new TestIncrementalCompiler(options, moduleSources.first, null);
+    Component c = await compiler.computeDelta(entryPoints: moduleSources);
+    c.computeCanonicalNames();
+    List<Library> wantedLibs = new List<Library>();
+    for (Library lib in c.libraries) {
+      if (moduleSources.contains(lib.importUri) ||
+          moduleSources.contains(lib.fileUri)) {
+        wantedLibs.add(lib);
+      }
+    }
+    if (wantedLibs.length != moduleSources.length) {
+      throw "Module probably not setup right.";
+    }
+    Component result = new Component(libraries: wantedLibs);
+    List<int> resultBytes = util.postProcess(result);
+    moduleResult[moduleName] = resultBytes;
+  }
+
+  return moduleResult;
+}
+
+Future<Null> newWorldTest(List worlds, Map modules, bool omitPlatform,
+    String targetName, bool incrementalSerialization) async {
+  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+  final Uri base = Uri.parse("org-dartlang-test:///");
+  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+  final Uri initializeFrom = base.resolve("initializeFrom.dill");
+  Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
+  final List<int> sdkSummaryData =
+      await new File.fromUri(platformUri).readAsBytes();
+
+  List<int> newestWholeComponentData;
+  Component newestWholeComponent;
+  MemoryFileSystem fs;
+  Map<String, String> sourceFiles;
+  CompilerOptions options;
+  TestIncrementalCompiler compiler;
+  IncrementalSerializer incrementalSerializer;
+
+  Map<String, List<int>> moduleData;
+  Map<String, Component> moduleComponents;
+  Component sdk;
+  if (modules != null) {
+    moduleData = await createModules(modules, sdkSummaryData, targetName);
+    sdk = newestWholeComponent = new Component();
+    new BinaryBuilder(sdkSummaryData, filename: null, disableLazyReading: false)
+        .readComponent(newestWholeComponent);
+  }
+
+  int worldNum = 0;
+  for (YamlMap world in worlds) {
+    worldNum++;
+    print("----------------");
+    print("World #$worldNum");
+    print("----------------");
+    List<Component> modulesToUse;
+    if (world["modules"] != null) {
+      moduleComponents ??= new Map<String, Component>();
+
+      sdk.adoptChildren();
+      for (Component c in moduleComponents.values) {
+        c.adoptChildren();
+      }
+
+      modulesToUse = new List<Component>();
+      for (String moduleName in world["modules"]) {
+        Component moduleComponent = moduleComponents[moduleName];
+        if (moduleComponent != null) {
+          modulesToUse.add(moduleComponent);
+        }
+      }
+      for (String moduleName in world["modules"]) {
+        Component moduleComponent = moduleComponents[moduleName];
+        if (moduleComponent == null) {
+          moduleComponent = new Component(nameRoot: sdk.root);
+          new BinaryBuilder(moduleData[moduleName],
+                  filename: null,
+                  disableLazyReading: false,
+                  alwaysCreateNewNamedNodes: true)
+              .readComponent(moduleComponent);
+          moduleComponents[moduleName] = moduleComponent;
+          modulesToUse.add(moduleComponent);
+        }
+      }
+    }
+
+    bool brandNewWorld = true;
+    if (world["worldType"] == "updated") {
+      brandNewWorld = false;
+    }
+    bool noFullComponent = false;
+    if (world["noFullComponent"] == true) {
+      noFullComponent = true;
+    }
+
+    if (brandNewWorld) {
+      fs = new MemoryFileSystem(base);
+    }
+    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
+    bool expectInitializeFromDill = false;
+    if (newestWholeComponentData != null &&
+        newestWholeComponentData.isNotEmpty) {
+      fs
+          .entityForUri(initializeFrom)
+          .writeAsBytesSync(newestWholeComponentData);
+      expectInitializeFromDill = true;
+    }
+    if (world["expectInitializeFromDill"] != null) {
+      expectInitializeFromDill = world["expectInitializeFromDill"];
+    }
+    if (brandNewWorld) {
+      sourceFiles = new Map<String, String>.from(world["sources"]);
+    } else {
+      sourceFiles.addAll(
+          new Map<String, String>.from(world["sources"] ?? <String, String>{}));
+    }
+    Uri packagesUri;
+    for (String filename in sourceFiles.keys) {
+      String data = sourceFiles[filename] ?? "";
+      Uri uri = base.resolve(filename);
+      if (filename == ".packages") {
+        packagesUri = uri;
+      }
+      fs.entityForUri(uri).writeAsStringSync(data);
+    }
+    if (world["dotPackagesFile"] != null) {
+      packagesUri = base.resolve(world["dotPackagesFile"]);
+    }
+
+    if (brandNewWorld) {
+      options = getOptions(targetName: targetName);
+      options.fileSystem = fs;
+      options.sdkRoot = null;
+      options.sdkSummary = sdkSummary;
+      options.omitPlatform = omitPlatform != false;
+    }
+    if (packagesUri != null) {
+      options.packagesFileUri = packagesUri;
+    }
+    bool gotError = false;
+    final Set<String> formattedErrors = Set<String>();
+    bool gotWarning = false;
+    final Set<String> formattedWarnings = Set<String>();
+
+    options.onDiagnostic = (DiagnosticMessage message) {
+      String stringId = message.ansiFormatted.join("\n");
+      if (message is FormattedMessage) {
+        stringId = message.toJsonString();
+      } else if (message is DiagnosticMessageFromJson) {
+        stringId = message.toJsonString();
+      }
+      if (message.severity == Severity.error) {
+        gotError = true;
+        if (!formattedErrors.add(stringId)) {
+          Expect.fail("Got the same message twice: ${stringId}");
+        }
+      } else if (message.severity == Severity.warning) {
+        gotWarning = true;
+        if (!formattedWarnings.add(stringId)) {
+          Expect.fail("Got the same message twice: ${stringId}");
+        }
+      }
+    };
+
+    List<Uri> entries;
+    if (world["entry"] is String) {
+      entries = [base.resolve(world["entry"])];
+    } else {
+      entries = new List<Uri>();
+      List<dynamic> entryList = world["entry"];
+      for (String entry in entryList) {
+        entries.add(base.resolve(entry));
+      }
+    }
+    bool outlineOnly = world["outlineOnly"] == true;
+    bool skipOutlineBodyCheck = world["skipOutlineBodyCheck"] == true;
+    if (brandNewWorld) {
+      if (incrementalSerialization == true) {
+        incrementalSerializer = new IncrementalSerializer();
+      }
+      if (world["fromComponent"] == true) {
+        compiler = new TestIncrementalCompiler.fromComponent(
+            options,
+            entries.first,
+            (modulesToUse != null) ? sdk : newestWholeComponent,
+            outlineOnly,
+            incrementalSerializer);
+      } else {
+        compiler = new TestIncrementalCompiler(options, entries.first,
+            initializeFrom, outlineOnly, incrementalSerializer);
+
+        if (modulesToUse != null) {
+          throw "You probably shouldn't do this! "
+              "Any modules will have another sdk loaded!";
+        }
+      }
+    }
+
+    List<Uri> invalidated = new List<Uri>();
+    if (world["invalidate"] != null) {
+      for (String filename in world["invalidate"]) {
+        Uri uri = base.resolve(filename);
+        invalidated.add(uri);
+        compiler.invalidate(uri);
+      }
+    }
+
+    if (modulesToUse != null) {
+      compiler.setModulesToLoadOnNextComputeDelta(modulesToUse);
+      compiler.invalidateAllSources();
+      compiler.trackNeededDillLibraries = true;
+    }
+
+    Stopwatch stopwatch = new Stopwatch()..start();
+    Component component = await compiler.computeDelta(
+        entryPoints: entries,
+        fullComponent: brandNewWorld ? false : (noFullComponent ? false : true),
+        simulateTransformer: world["simulateTransformer"]);
+    if (outlineOnly && !skipOutlineBodyCheck) {
+      for (Library lib in component.libraries) {
+        for (Class c in lib.classes) {
+          for (Procedure p in c.procedures) {
+            if (p.function.body != null && p.function.body is! EmptyStatement) {
+              throw "Got body (${p.function.body.runtimeType})";
+            }
+          }
+        }
+        for (Procedure p in lib.procedures) {
+          if (p.function.body != null && p.function.body is! EmptyStatement) {
+            throw "Got body (${p.function.body.runtimeType})";
+          }
+        }
+      }
+    }
+    performErrorAndWarningCheck(
+        world, gotError, formattedErrors, gotWarning, formattedWarnings);
+    util.throwOnEmptyMixinBodies(component);
+    util.throwOnInsufficientUriToSource(component);
+    print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+
+    checkExpectedContent(world, component);
+    checkNeededDillLibraries(world, compiler.neededDillLibraries, base);
+
+    if (!noFullComponent) {
+      Set<Library> allLibraries = new Set<Library>();
+      for (Library lib in component.libraries) {
+        computeAllReachableLibrariesFor(lib, allLibraries);
+      }
+      if (allLibraries.length != component.libraries.length) {
+        Expect.fail("Expected for the reachable stuff to be equal to "
+            "${component.libraries} but it was $allLibraries");
+      }
+      Set<Library> tooMany = allLibraries.toSet()
+        ..removeAll(component.libraries);
+      if (tooMany.isNotEmpty) {
+        Expect.fail("Expected for the reachable stuff to be equal to "
+            "${component.libraries} but these were there too: $tooMany "
+            "(and others were missing)");
+      }
+    }
+
+    newestWholeComponentData = util.postProcess(component);
+    newestWholeComponent = component;
+    print("*****\n\ncomponent:\n"
+        "${componentToStringSdkFiltered(component)}\n\n\n");
+
+    if (world["uriToSourcesDoesntInclude"] != null) {
+      for (String filename in world["uriToSourcesDoesntInclude"]) {
+        Uri uri = base.resolve(filename);
+        if (component.uriToSource[uri] != null) {
+          throw "Expected no uriToSource for $uri but found "
+              "${component.uriToSource[uri]}";
+        }
+      }
+    }
+    if (world["uriToSourcesOnlyIncludes"] != null) {
+      Set<Uri> allowed = {};
+      for (String filename in world["uriToSourcesOnlyIncludes"]) {
+        Uri uri = base.resolve(filename);
+        allowed.add(uri);
+      }
+      for (Uri uri in component.uriToSource.keys) {
+        // null is always there, so allow it implicitly.
+        // Dart scheme uris too.
+        if (uri == null || uri.scheme == "org-dartlang-sdk") continue;
+        if (!allowed.contains(uri)) {
+          throw "Expected no uriToSource for $uri but found "
+              "${component.uriToSource[uri]}";
+        }
+      }
+    }
+
+    int nonSyntheticLibraries = countNonSyntheticLibraries(component);
+    int nonSyntheticPlatformLibraries =
+        countNonSyntheticPlatformLibraries(component);
+    int syntheticLibraries = countSyntheticLibraries(component);
+    if (world["expectsPlatform"] == true) {
+      if (nonSyntheticPlatformLibraries < 5) {
+        throw "Expected to have at least 5 platform libraries "
+            "(actually, the entire sdk), "
+            "but got $nonSyntheticPlatformLibraries.";
+      }
+    } else {
+      if (nonSyntheticPlatformLibraries != 0) {
+        throw "Expected to have 0 platform libraries "
+            "but got $nonSyntheticPlatformLibraries.";
+      }
+    }
+    if (world["expectedLibraryCount"] != null) {
+      if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
+          world["expectedLibraryCount"]) {
+        throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
+            "libraries, got "
+            "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
+            "(not counting platform libraries)";
+      }
+    }
+    if (world["expectedSyntheticLibraryCount"] != null) {
+      if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
+        throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
+            "libraries, got ${syntheticLibraries}";
+      }
+    }
+    if (!noFullComponent) {
+      List<Library> entryLib = component.libraries
+          .where((Library lib) =>
+              entries.contains(lib.importUri) || entries.contains(lib.fileUri))
+          .toList();
+      if (entryLib.length != entries.length) {
+        throw "Expected the entries to become libraries. "
+            "Got ${entryLib.length} libraries for the expected "
+            "${entries.length} entries.";
+      }
+    }
+    if (compiler.initializedFromDill != expectInitializeFromDill) {
+      throw "Expected that initializedFromDill would be "
+          "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
+    }
+
+    if (incrementalSerialization == true && compiler.initializedFromDill) {
+      Expect.isTrue(compiler.initializedIncrementalSerializer);
+    } else {
+      Expect.isFalse(compiler.initializedIncrementalSerializer);
+    }
+
+    if (world["checkInvalidatedFiles"] != false) {
+      Set<Uri> filteredInvalidated =
+          compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
+      if (world["invalidate"] != null) {
+        Expect.equals(
+            world["invalidate"].length, filteredInvalidated?.length ?? 0);
+        List expectedInvalidatedUri = world["expectedInvalidatedUri"];
+        if (expectedInvalidatedUri != null) {
+          Expect.setEquals(expectedInvalidatedUri.map((s) => base.resolve(s)),
+              filteredInvalidated);
+        }
+      } else {
+        Expect.isNull(filteredInvalidated);
+        Expect.isNull(world["expectedInvalidatedUri"]);
+      }
+    }
+    List<int> incrementalSerializationBytes = checkIncrementalSerialization(
+        incrementalSerialization, component, incrementalSerializer, world);
+
+    Set<String> prevFormattedErrors = formattedErrors.toSet();
+    Set<String> prevFormattedWarnings = formattedWarnings.toSet();
+
+    clearPrevErrorsEtc() {
+      gotError = false;
+      formattedErrors.clear();
+      gotWarning = false;
+      formattedWarnings.clear();
+    }
+
+    if (!noFullComponent) {
+      clearPrevErrorsEtc();
+      Component component2 = await compiler.computeDelta(
+          entryPoints: entries,
+          fullComponent: true,
+          simulateTransformer: world["simulateTransformer"]);
+      performErrorAndWarningCheck(
+          world, gotError, formattedErrors, gotWarning, formattedWarnings);
+      List<int> thisWholeComponent = util.postProcess(component2);
+      print("*****\n\ncomponent2:\n"
+          "${componentToStringSdkFiltered(component2)}\n\n\n");
+      checkIsEqual(newestWholeComponentData, thisWholeComponent);
+      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
+          prevFormattedWarnings, formattedWarnings);
+
+      List<int> incrementalSerializationBytes2 = checkIncrementalSerialization(
+          incrementalSerialization, component2, incrementalSerializer, world);
+
+      if ((incrementalSerializationBytes == null &&
+              incrementalSerializationBytes2 != null) ||
+          (incrementalSerializationBytes != null &&
+              incrementalSerializationBytes2 == null)) {
+        throw "Incremental serialization gave results in one instance, "
+            "but not another.";
+      }
+
+      if (incrementalSerializationBytes != null) {
+        checkIsEqual(
+            incrementalSerializationBytes, incrementalSerializationBytes2);
+      }
+    }
+
+    if (world["expressionCompilation"] != null) {
+      Uri uri = base.resolve(world["expressionCompilation"]["uri"]);
+      String expression = world["expressionCompilation"]["expression"];
+      await compiler.compileExpression(expression, {}, [], "debugExpr", uri);
+    }
+
+    if (!noFullComponent && incrementalSerialization == true) {
+      // Do compile from scratch and compare.
+      clearPrevErrorsEtc();
+      TestIncrementalCompiler compilerFromScratch;
+
+      IncrementalSerializer incrementalSerializer2;
+      if (incrementalSerialization == true) {
+        incrementalSerializer2 = new IncrementalSerializer();
+      }
+
+      if (world["fromComponent"] == true || modulesToUse != null) {
+        compilerFromScratch = new TestIncrementalCompiler.fromComponent(
+            options, entries.first, sdk, outlineOnly, incrementalSerializer2);
+      } else {
+        compilerFromScratch = new TestIncrementalCompiler(
+            options, entries.first, null, outlineOnly, incrementalSerializer2);
+      }
+
+      if (modulesToUse != null) {
+        compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
+        compilerFromScratch.invalidateAllSources();
+        compilerFromScratch.trackNeededDillLibraries = true;
+      }
+
+      Stopwatch stopwatch = new Stopwatch()..start();
+      Component component3 = await compilerFromScratch.computeDelta(
+          entryPoints: entries,
+          simulateTransformer: world["simulateTransformer"]);
+      performErrorAndWarningCheck(
+          world, gotError, formattedErrors, gotWarning, formattedWarnings);
+      util.throwOnEmptyMixinBodies(component3);
+      util.throwOnInsufficientUriToSource(component3);
+      print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+
+      util.postProcess(component3);
+      print("*****\n\ncomponent3:\n"
+          "${componentToStringSdkFiltered(component3)}\n\n\n");
+      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
+          prevFormattedWarnings, formattedWarnings);
+
+      List<int> incrementalSerializationBytes3 = checkIncrementalSerialization(
+          incrementalSerialization, component3, incrementalSerializer2, world);
+
+      if ((incrementalSerializationBytes == null &&
+              incrementalSerializationBytes3 != null) ||
+          (incrementalSerializationBytes != null &&
+              incrementalSerializationBytes3 == null)) {
+        throw "Incremental serialization gave results in one instance, "
+            "but not another.";
+      }
+
+      if (incrementalSerializationBytes != null) {
+        if (world["brandNewIncrementalSerializationAllowDifferent"] == true) {
+          // Don't check for equality when we allow it to be different
+          // (e.g. when the old one contains more, and the new one doesn't).
+        } else {
+          checkIsEqual(
+              incrementalSerializationBytes, incrementalSerializationBytes3);
+        }
+        newestWholeComponentData = incrementalSerializationBytes;
+      }
+    }
+  }
+}
+
+void checkErrorsAndWarnings(
+    Set<String> prevFormattedErrors,
+    Set<String> formattedErrors,
+    Set<String> prevFormattedWarnings,
+    Set<String> formattedWarnings) {
+  if (prevFormattedErrors.length != formattedErrors.length) {
+    Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
+        "now had ${formattedErrors.length}.\n\n"
+        "Before:\n"
+        "${prevFormattedErrors.join("\n")}"
+        "\n\n"
+        "Now:\n"
+        "${formattedErrors.join("\n")}");
+  }
+  if ((prevFormattedErrors.toSet()..removeAll(formattedErrors)).isNotEmpty) {
+    Expect.fail("Previously got error messages $prevFormattedErrors, "
+        "now had ${formattedErrors}.");
+  }
+  if (prevFormattedWarnings.length != formattedWarnings.length) {
+    Expect.fail("Previously had ${prevFormattedWarnings.length} errors, "
+        "now had ${formattedWarnings.length}.");
+  }
+  if ((prevFormattedWarnings.toSet()..removeAll(formattedWarnings))
+      .isNotEmpty) {
+    Expect.fail("Previously got error messages $prevFormattedWarnings, "
+        "now had ${formattedWarnings}.");
+  }
+}
+
+List<int> checkIncrementalSerialization(
+    bool incrementalSerialization,
+    Component component,
+    IncrementalSerializer incrementalSerializer,
+    YamlMap world) {
+  if (incrementalSerialization == true) {
+    Component c = new Component(nameRoot: component.root);
+    c.libraries.addAll(component.libraries);
+    c.uriToSource.addAll(component.uriToSource);
+    Map<String, Set<String>> originalContent = buildMapOfContent(c);
+    ByteSink sink = new ByteSink();
+    int librariesBefore = c.libraries.length;
+    incrementalSerializer.writePackagesToSinkAndTrimComponent(c, sink);
+    int librariesAfter = c.libraries.length;
+    if (librariesAfter > librariesBefore) {
+      throw "Incremental serialization added libraries!";
+    }
+    if (librariesBefore == librariesAfter &&
+        world["incrementalSerializationDoesWork"] == true) {
+      throw "Incremental serialization didn't remove any libraries!";
+    }
+    if (librariesAfter < librariesBefore && sink.builder.isEmpty) {
+      throw "Incremental serialization din't output any bytes, "
+          "but did remove libraries";
+    } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) {
+      throw "Incremental serialization did output bytes, "
+          "but didn't remove libraries";
+    }
+    if (librariesAfter < librariesBefore) {
+      // If we actually did incremenally serialize anything, check the output!
+      // If we actually did incremenally serialize anything, check the output!
+      BinaryPrinter printer = new BinaryPrinter(sink);
+      printer.writeComponentFile(c);
+      List<int> bytes = sink.builder.takeBytes();
+
+      // Load the bytes back in.
+      Component loadedComponent = new Component();
+      new BinaryBuilder(bytes, filename: null).readComponent(loadedComponent);
+
+      // Check that it doesn't contain anything we said it shouldn't.
+      if (world["serializationShouldNotInclude"] is List) {
+        List serializationShouldNotInclude =
+            world["serializationShouldNotInclude"];
+        Set<Uri> includedImportUris =
+            loadedComponent.libraries.map((l) => l.importUri).toSet();
+        for (String uriString in serializationShouldNotInclude) {
+          Uri uri = Uri.parse(uriString);
+          if (includedImportUris.contains(uri)) {
+            throw "Incremental serialization shouldn't include "
+                "$uriString but did.";
+          }
+        }
+      }
+
+      // Check that it contains at least what we want.
+      Map<String, Set<String>> afterContent =
+          buildMapOfContent(loadedComponent);
+      // Remove any keys in afterContent not in the original as the written
+      // one is allowed to contain *more*.
+      Set<String> newKeys = afterContent.keys.toSet()
+        ..removeAll(originalContent.keys);
+      for (String key in newKeys) {
+        afterContent.remove(key);
+      }
+      checkExpectedContentData(afterContent, originalContent);
+
+      // Check that the result is self-contained.
+      checkSelfContained(loadedComponent);
+
+      return bytes;
+    }
+  }
+  return null;
+}
+
+void checkSelfContained(Component component) {
+  Set<Library> got = new Set<Library>.from(component.libraries);
+  for (Library lib in component.libraries) {
+    for (LibraryDependency dependency in lib.dependencies) {
+      if (dependency.importedLibraryReference.node == null ||
+          !got.contains(dependency.targetLibrary)) {
+        if (dependency.importedLibraryReference.canonicalName
+            .toString()
+            .startsWith("root::dart:")) {
+          continue;
+        }
+        throw "Component didn't contain ${dependency.importedLibraryReference} "
+            "and it should have.";
+      }
+    }
+  }
+}
+
+void computeAllReachableLibrariesFor(Library lib, Set<Library> allLibraries) {
+  Set<Library> libraries = new Set<Library>();
+  List<Library> workList = <Library>[];
+  allLibraries.add(lib);
+  libraries.add(lib);
+  workList.add(lib);
+  while (workList.isNotEmpty) {
+    Library library = workList.removeLast();
+    for (LibraryDependency dependency in library.dependencies) {
+      if (dependency.targetLibrary.importUri.scheme == "dart") continue;
+      if (libraries.add(dependency.targetLibrary)) {
+        workList.add(dependency.targetLibrary);
+        allLibraries.add(dependency.targetLibrary);
+      }
+    }
+  }
+}
+
+void checkExpectedContent(YamlMap world, Component component) {
+  if (world["expectedContent"] != null) {
+    Map<String, Set<String>> actualContent = buildMapOfContent(component);
+    Map expectedContent = world["expectedContent"];
+    checkExpectedContentData(actualContent, expectedContent);
+  }
+}
+
+void checkExpectedContentData(
+    Map<String, Set<String>> actualContent, Map expectedContent) {
+  doThrow() {
+    throw "Expected and actual content not the same.\n"
+        "Expected $expectedContent.\n"
+        "Got $actualContent";
+  }
+
+  if (actualContent.length != expectedContent.length) doThrow();
+  Set<String> missingKeys = actualContent.keys.toSet()
+    ..removeAll(expectedContent.keys);
+  if (missingKeys.isNotEmpty) doThrow();
+  for (String key in expectedContent.keys) {
+    Set<String> expected = new Set<String>.from(expectedContent[key]);
+    Set<String> actual = actualContent[key].toSet();
+    if (expected.length != actual.length) doThrow();
+    actual.removeAll(expected);
+    if (actual.isNotEmpty) doThrow();
+  }
+}
+
+Map<String, Set<String>> buildMapOfContent(Component component) {
+  Map<String, Set<String>> actualContent = new Map<String, Set<String>>();
+  for (Library lib in component.libraries) {
+    Set<String> libContent =
+        actualContent[lib.importUri.toString()] = new Set<String>();
+    for (Class c in lib.classes) {
+      libContent.add("Class ${c.name}");
+    }
+    for (Procedure p in lib.procedures) {
+      libContent.add("Procedure ${p.name}");
+    }
+    for (Field f in lib.fields) {
+      libContent.add("Field ${f.name}");
+    }
+  }
+  return actualContent;
+}
+
+void checkNeededDillLibraries(
+    YamlMap world, Set<Library> neededDillLibraries, Uri base) {
+  if (world["neededDillLibraries"] != null) {
+    List<Uri> actualContent = new List<Uri>();
+    for (Library lib in neededDillLibraries) {
+      if (lib.importUri.scheme == "dart") continue;
+      actualContent.add(lib.importUri);
+    }
+
+    List<Uri> expectedContent = new List<Uri>();
+    for (String entry in world["neededDillLibraries"]) {
+      expectedContent.add(base.resolve(entry));
+    }
+
+    doThrow() {
+      throw "Expected and actual content not the same.\n"
+          "Expected $expectedContent.\n"
+          "Got $actualContent";
+    }
+
+    if (actualContent.length != expectedContent.length) doThrow();
+    Set<Uri> notInExpected =
+        actualContent.toSet().difference(expectedContent.toSet());
+    Set<Uri> notInActual =
+        expectedContent.toSet().difference(actualContent.toSet());
+    if (notInExpected.isNotEmpty) doThrow();
+    if (notInActual.isNotEmpty) doThrow();
+  }
+}
+
+String componentToStringSdkFiltered(Component node) {
+  Component c = new Component();
+  List<Uri> dartUris = new List<Uri>();
+  for (Library lib in node.libraries) {
+    if (lib.importUri.scheme == "dart") {
+      dartUris.add(lib.importUri);
+    } else {
+      c.libraries.add(lib);
+    }
+  }
+
+  StringBuffer s = new StringBuffer();
+  s.write(componentToString(c));
+
+  if (dartUris.isNotEmpty) {
+    s.writeln("");
+    s.writeln("And ${dartUris.length} platform libraries:");
+    for (Uri uri in dartUris) {
+      s.writeln(" - $uri");
+    }
+  }
+
+  return s.toString();
+}
+
+int countNonSyntheticLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (!lib.isSynthetic) result++;
+  }
+  return result;
+}
+
+int countNonSyntheticPlatformLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (!lib.isSynthetic && lib.importUri.scheme == "dart") result++;
+  }
+  return result;
+}
+
+int countSyntheticLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (lib.isSynthetic) result++;
+  }
+  return result;
+}
+
+void performErrorAndWarningCheck(
+    YamlMap world,
+    bool gotError,
+    Set<String> formattedErrors,
+    bool gotWarning,
+    Set<String> formattedWarnings) {
+  if (world["errors"] == true && !gotError) {
+    throw "Expected error, but didn't get any.";
+  } else if (world["errors"] != true && gotError) {
+    throw "Got unexpected error(s): $formattedErrors.";
+  }
+  if (world["warnings"] == true && !gotWarning) {
+    throw "Expected warning, but didn't get any.";
+  } else if (world["warnings"] != true && gotWarning) {
+    throw "Got unexpected warnings(s): $formattedWarnings.";
+  }
+}
+
+void checkIsEqual(List<int> a, List<int> b) {
+  int length = a.length;
+  if (b.length < length) {
+    length = b.length;
+  }
+  for (int i = 0; i < length; ++i) {
+    if (a[i] != b[i]) {
+      print("Data differs at byte ${i + 1}.");
+
+      StringBuffer message = new StringBuffer();
+      message.writeln("Data differs at byte ${i + 1}.");
+      message.writeln("");
+      message.writeln("Will try to find more useful information:");
+
+      final String repoDir = computeRepoDir();
+      File binaryMd = new File("$repoDir/pkg/kernel/binary.md");
+      String binaryMdContent = binaryMd.readAsStringSync();
+
+      DillComparer dillComparer = new DillComparer();
+      if (dillComparer.compare(a, b, binaryMdContent, message)) {
+        message.writeln(
+            "Somehow the two different byte-lists compared to the same.");
+      }
+
+      Expect.fail(message.toString());
+    }
+  }
+  Expect.equals(a.length, b.length);
+}
+
+CompilerOptions getOptions({String targetName}) {
+  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+  Target target = new VmTarget(new TargetFlags());
+  if (targetName != null) {
+    if (targetName == "None") {
+      target = new NoneTarget(new TargetFlags());
+    } else if (targetName == "VM") {
+      // default.
+    } else {
+      throw "Unknown target name '$targetName'";
+    }
+  }
+  CompilerOptions options = new CompilerOptions()
+    ..sdkRoot = sdkRoot
+    ..target = target
+    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
+    ..omitPlatform = true
+    ..onDiagnostic = (DiagnosticMessage message) {
+      if (message.severity == Severity.error ||
+          message.severity == Severity.warning) {
+        Expect.fail(
+            "Unexpected error: ${message.plainTextFormatted.join('\n')}");
+      }
+    }
+    ..sdkSummary = sdkRoot.resolve("vm_platform_strong.dill")
+    ..environmentDefines = const {};
+  return options;
+}
+
+Future<bool> normalCompile(Uri input, Uri output,
+    {CompilerOptions options}) async {
+  options ??= getOptions();
+  TestIncrementalCompiler compiler =
+      new TestIncrementalCompiler(options, input);
+  List<int> bytes =
+      await normalCompileToBytes(input, options: options, compiler: compiler);
+  new File.fromUri(output).writeAsBytesSync(bytes);
+  return compiler.initializedFromDill;
+}
+
+Future<List<int>> normalCompileToBytes(Uri input,
+    {CompilerOptions options, IncrementalCompiler compiler}) async {
+  Component component = await normalCompileToComponent(input,
+      options: options, compiler: compiler);
+  return util.postProcess(component);
+}
+
+Future<Component> normalCompileToComponent(Uri input,
+    {CompilerOptions options, IncrementalCompiler compiler}) async {
+  Component component =
+      await normalCompilePlain(input, options: options, compiler: compiler);
+  util.throwOnEmptyMixinBodies(component);
+  util.throwOnInsufficientUriToSource(component);
+  return component;
+}
+
+Future<Component> normalCompilePlain(Uri input,
+    {CompilerOptions options, IncrementalCompiler compiler}) async {
+  options ??= getOptions();
+  compiler ??= new TestIncrementalCompiler(options, input);
+  return await compiler.computeDelta();
+}
+
+Future<bool> initializedCompile(
+    Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
+    {CompilerOptions options}) async {
+  options ??= getOptions();
+  TestIncrementalCompiler compiler =
+      new TestIncrementalCompiler(options, input, initializeWith);
+  for (Uri invalidateUri in invalidateUris) {
+    compiler.invalidate(invalidateUri);
+  }
+  Component initializedComponent = await compiler.computeDelta();
+  util.throwOnEmptyMixinBodies(initializedComponent);
+  util.throwOnInsufficientUriToSource(initializedComponent);
+  bool result = compiler.initializedFromDill;
+  new File.fromUri(output)
+      .writeAsBytesSync(util.postProcess(initializedComponent));
+  int actuallyInvalidatedCount = compiler
+          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
+          ?.length ??
+      0;
+  if (result && actuallyInvalidatedCount < invalidateUris.length) {
+    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
+        "got $actuallyInvalidatedCount");
+  }
+
+  Component initializedFullComponent =
+      await compiler.computeDelta(fullComponent: true);
+  util.throwOnEmptyMixinBodies(initializedFullComponent);
+  util.throwOnInsufficientUriToSource(initializedFullComponent);
+  Expect.equals(initializedComponent.libraries.length,
+      initializedFullComponent.libraries.length);
+  Expect.equals(initializedComponent.uriToSource.length,
+      initializedFullComponent.uriToSource.length);
+
+  for (Uri invalidateUri in invalidateUris) {
+    compiler.invalidate(invalidateUri);
+  }
+
+  Component partialComponent = await compiler.computeDelta();
+  util.throwOnEmptyMixinBodies(partialComponent);
+  util.throwOnInsufficientUriToSource(partialComponent);
+  actuallyInvalidatedCount = (compiler
+          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
+          ?.length ??
+      0);
+  if (actuallyInvalidatedCount < invalidateUris.length) {
+    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
+        "got $actuallyInvalidatedCount");
+  }
+
+  Component emptyComponent = await compiler.computeDelta();
+  util.throwOnEmptyMixinBodies(emptyComponent);
+  util.throwOnInsufficientUriToSource(emptyComponent);
+
+  List<Uri> fullLibUris =
+      initializedComponent.libraries.map((lib) => lib.importUri).toList();
+  List<Uri> partialLibUris =
+      partialComponent.libraries.map((lib) => lib.importUri).toList();
+  List<Uri> emptyLibUris =
+      emptyComponent.libraries.map((lib) => lib.importUri).toList();
+
+  Expect.isTrue(fullLibUris.length > partialLibUris.length ||
+      partialLibUris.length == invalidateUris.length);
+  Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);
+
+  Expect.isTrue(emptyLibUris.isEmpty);
+
+  return result;
+}
+
+class TestIncrementalCompiler extends IncrementalCompiler {
+  Set<Uri> invalidatedImportUrisForTesting;
+  final Uri entryPoint;
+
+  /// Filter out the automatically added entryPoint, unless it's explicitly
+  /// specified as being invalidated.
+  /// Also filter out uris with "nonexisting.dart" in the name as synthetic
+  /// libraries are invalidated automatically too.
+  /// This is not perfect, but works for what it's currently used for.
+  Set<Uri> getFilteredInvalidatedImportUrisForTesting(
+      List<Uri> invalidatedUris) {
+    if (invalidatedImportUrisForTesting == null) return null;
+
+    Set<String> invalidatedFilenames =
+        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 (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
+          invalidatedFilenames.contains(uri.pathSegments.last)) result.add(uri);
+    }
+
+    return result.isEmpty ? null : result;
+  }
+
+  TestIncrementalCompiler(CompilerOptions options, this.entryPoint,
+      [Uri initializeFrom,
+      bool outlineOnly,
+      IncrementalSerializer incrementalSerializer])
+      : super(
+            new CompilerContext(
+                new ProcessedOptions(options: options, inputs: [entryPoint])),
+            initializeFrom,
+            outlineOnly,
+            incrementalSerializer);
+
+  TestIncrementalCompiler.fromComponent(CompilerOptions options,
+      this.entryPoint, Component componentToInitializeFrom,
+      [bool outlineOnly, IncrementalSerializer incrementalSerializer])
+      : super.fromComponent(
+            new CompilerContext(
+                new ProcessedOptions(options: options, inputs: [entryPoint])),
+            componentToInitializeFrom,
+            outlineOnly,
+            incrementalSerializer);
+
+  @override
+  void recordInvalidatedImportUrisForTesting(List<Uri> uris) {
+    invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toSet();
+  }
+
+  @override
+  void recordNonFullComponentForTesting(Component component) {
+    // It should at least contain the sdk. Slight smoke test.
+    if (!component.libraries
+        .map((lib) => lib.importUri.toString())
+        .contains("dart:core")) {
+      throw "Loaders builder should contain the sdk, "
+          "but didn't even contain dart:core.";
+    }
+  }
+
+  @override
+  Future<Component> computeDelta(
+      {List<Uri> entryPoints,
+      bool fullComponent = false,
+      bool simulateTransformer}) async {
+    Component result = await super
+        .computeDelta(entryPoints: entryPoints, fullComponent: fullComponent);
+
+    // We should at least have the SDK builders available. Slight smoke test.
+    if (!dillLoadedData.loader.builders.keys
+        .map((uri) => uri.toString())
+        .contains("dart:core")) {
+      throw "Loaders builder should contain the sdk, "
+          "but didn't even contain dart:core.";
+    }
+
+    if (simulateTransformer == true) {
+      doSimulateTransformer(result);
+    }
+    return result;
+  }
+}
+
+void doSimulateTransformer(Component c) {
+  for (Library lib in c.libraries) {
+    if (lib.fields
+        .where((f) => f.name.name == "lalala_SimulateTransformer")
+        .toList()
+        .isNotEmpty) continue;
+    Name fieldName = new Name("lalala_SimulateTransformer");
+    Field field = new Field(fieldName,
+        isFinal: true,
+        reference: lib.reference.canonicalName
+            ?.getChildFromFieldWithName(fieldName)
+            ?.reference);
+    lib.addMember(field);
+    for (Class c in lib.classes) {
+      if (c.fields
+          .where((f) => f.name.name == "lalala_SimulateTransformer")
+          .toList()
+          .isNotEmpty) continue;
+      fieldName = new Name("lalala_SimulateTransformer");
+      field = new Field(fieldName,
+          isFinal: true,
+          reference: c.reference.canonicalName
+              ?.getChildFromFieldWithName(fieldName)
+              ?.reference);
+      c.addMember(field);
+    }
+  }
+}
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
deleted file mode 100644
index 903c589..0000000
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ /dev/null
@@ -1,1287 +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 'dart:async' show Future;
-
-import 'dart:io' show Directory, File;
-
-import 'package:expect/expect.dart' show Expect;
-
-import 'package:front_end/src/api_prototype/compiler_options.dart'
-    show CompilerOptions;
-
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, getMessageCodeObject;
-
-import "package:front_end/src/api_prototype/memory_file_system.dart"
-    show MemoryFileSystem;
-
-import 'package:front_end/src/base/processed_options.dart'
-    show ProcessedOptions;
-
-import 'package:front_end/src/compute_platform_binaries_location.dart'
-    show computePlatformBinariesLocation;
-
-import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-
-import 'package:front_end/src/fasta/fasta_codes.dart'
-    show DiagnosticMessageFromJson, FormattedMessage;
-
-import 'package:front_end/src/fasta/incremental_compiler.dart'
-    show IncrementalCompiler;
-
-import 'package:front_end/src/fasta/incremental_serializer.dart'
-    show IncrementalSerializer;
-
-import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
-
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
-import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-
-import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
-
-import 'package:kernel/kernel.dart'
-    show
-        Class,
-        Component,
-        EmptyStatement,
-        Field,
-        Library,
-        LibraryDependency,
-        Name,
-        Procedure;
-
-import 'package:kernel/target/targets.dart'
-    show NoneTarget, Target, TargetFlags;
-
-import 'package:kernel/text/ast_to_text.dart' show componentToString;
-
-import "package:testing/testing.dart"
-    show Chain, ChainContext, Result, Step, TestDescription, runMe;
-
-import "package:vm/target/vm.dart" show VmTarget;
-
-import "package:yaml/yaml.dart" show YamlList, YamlMap, loadYamlNode;
-
-import 'binary_md_dill_reader.dart' show DillComparer;
-
-import "incremental_utils.dart" as util;
-
-import 'utils/io_utils.dart' show computeRepoDir;
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../testing.json");
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  return new Context();
-}
-
-class Context extends ChainContext {
-  final List<Step> steps = const <Step>[
-    const ReadTest(),
-    const RunCompilations(),
-  ];
-
-  @override
-  Future<void> cleanUp(TestDescription description, Result result) async {
-    await cleanupHelper?.outDir?.delete(recursive: true);
-  }
-
-  TestData cleanupHelper;
-}
-
-class TestData {
-  YamlMap map;
-  Directory outDir;
-}
-
-class ReadTest extends Step<TestDescription, TestData, Context> {
-  const ReadTest();
-
-  String get name => "read test";
-
-  Future<Result<TestData>> run(
-      TestDescription description, Context context) async {
-    Uri uri = description.uri;
-    String contents = await new File.fromUri(uri).readAsString();
-    TestData data = new TestData();
-    data.map = loadYamlNode(contents, sourceUrl: uri);
-    data.outDir =
-        Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
-    context.cleanupHelper = data;
-    return pass(data);
-  }
-}
-
-class RunCompilations extends Step<TestData, TestData, Context> {
-  const RunCompilations();
-
-  String get name => "run compilations";
-
-  Future<Result<TestData>> run(TestData data, Context context) async {
-    YamlMap map = data.map;
-    Set<String> keys = new Set<String>.from(map.keys.cast<String>());
-    keys.remove("type");
-    switch (map["type"]) {
-      case "basic":
-        keys.removeAll(["sources", "entry", "invalidate"]);
-        await basicTest(
-          map["sources"],
-          map["entry"],
-          map["invalidate"],
-          data.outDir,
-        );
-        break;
-      case "newworld":
-        keys.removeAll([
-          "worlds",
-          "modules",
-          "omitPlatform",
-          "target",
-          "incrementalSerialization"
-        ]);
-        await newWorldTest(
-          map["worlds"],
-          map["modules"],
-          map["omitPlatform"],
-          map["target"],
-          map["incrementalSerialization"],
-        );
-        break;
-      default:
-        throw "Unexpected type: ${map['type']}";
-    }
-
-    if (keys.isNotEmpty) throw "Unknown toplevel keys: $keys";
-    return pass(data);
-  }
-}
-
-Future<Null> basicTest(YamlMap sourceFiles, String entryPoint,
-    YamlList invalidate, Directory outDir) async {
-  Uri entryPointUri = outDir.uri.resolve(entryPoint);
-  Set<String> invalidateFilenames =
-      invalidate == null ? new Set<String>() : new Set<String>.from(invalidate);
-  List<Uri> invalidateUris = <Uri>[];
-  Uri packagesUri;
-  for (String filename in sourceFiles.keys) {
-    Uri uri = outDir.uri.resolve(filename);
-    if (invalidateFilenames.contains(filename)) {
-      invalidateUris.add(uri);
-      invalidateFilenames.remove(filename);
-    }
-    String source = sourceFiles[filename];
-    if (filename == ".packages") {
-      packagesUri = uri;
-    }
-    File file = new File.fromUri(uri);
-    await file.parent.create(recursive: true);
-    await file.writeAsString(source);
-  }
-  for (String invalidateFilename in invalidateFilenames) {
-    if (invalidateFilename.startsWith('package:')) {
-      invalidateUris.add(Uri.parse(invalidateFilename));
-    } else {
-      throw "Error in test yaml: $invalidateFilename was not recognized.";
-    }
-  }
-
-  Uri output = outDir.uri.resolve("full.dill");
-  Uri initializedOutput = outDir.uri.resolve("full_from_initialized.dill");
-
-  Stopwatch stopwatch = new Stopwatch()..start();
-  CompilerOptions options = getOptions();
-  if (packagesUri != null) {
-    options.packagesFileUri = packagesUri;
-  }
-  await normalCompile(entryPointUri, output, options: options);
-  print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
-  stopwatch.reset();
-  options = getOptions();
-  if (packagesUri != null) {
-    options.packagesFileUri = packagesUri;
-  }
-  bool initializedResult = await initializedCompile(
-      entryPointUri, initializedOutput, output, invalidateUris,
-      options: options);
-  print("Initialized compile(s) from ${output.pathSegments.last} "
-      "took ${stopwatch.elapsedMilliseconds} ms");
-  Expect.isTrue(initializedResult);
-
-  // Compare the two files.
-  List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
-  List<int> initializedDillData =
-      new File.fromUri(initializedOutput).readAsBytesSync();
-  checkIsEqual(normalDillData, initializedDillData);
-}
-
-Future<Map<String, List<int>>> createModules(
-    Map module, final List<int> sdkSummaryData, String targetName) async {
-  final Uri base = Uri.parse("org-dartlang-test:///");
-  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
-
-  MemoryFileSystem fs = new MemoryFileSystem(base);
-  fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-
-  // Setup all sources
-  for (Map moduleSources in module.values) {
-    for (String filename in moduleSources.keys) {
-      String data = moduleSources[filename];
-      Uri uri = base.resolve(filename);
-      if (await fs.entityForUri(uri).exists()) {
-        throw "More than one entry for $filename";
-      }
-      fs.entityForUri(uri).writeAsStringSync(data);
-    }
-  }
-
-  Map<String, List<int>> moduleResult = new Map<String, List<int>>();
-
-  for (String moduleName in module.keys) {
-    List<Uri> moduleSources = new List<Uri>();
-    Uri packagesUri;
-    for (String filename in module[moduleName].keys) {
-      Uri uri = base.resolve(filename);
-      if (uri.pathSegments.last == ".packages") {
-        packagesUri = uri;
-      } else {
-        moduleSources.add(uri);
-      }
-    }
-    CompilerOptions options = getOptions(targetName: targetName);
-    options.fileSystem = fs;
-    options.sdkRoot = null;
-    options.sdkSummary = sdkSummary;
-    options.omitPlatform = true;
-    options.onDiagnostic = (DiagnosticMessage message) {
-      if (getMessageCodeObject(message)?.name == "InferredPackageUri") return;
-      throw message.ansiFormatted;
-    };
-    if (packagesUri != null) {
-      options.packagesFileUri = packagesUri;
-    }
-    TestIncrementalCompiler compiler =
-        new TestIncrementalCompiler(options, moduleSources.first, null);
-    Component c = await compiler.computeDelta(entryPoints: moduleSources);
-    c.computeCanonicalNames();
-    List<Library> wantedLibs = new List<Library>();
-    for (Library lib in c.libraries) {
-      if (moduleSources.contains(lib.importUri) ||
-          moduleSources.contains(lib.fileUri)) {
-        wantedLibs.add(lib);
-      }
-    }
-    if (wantedLibs.length != moduleSources.length) {
-      throw "Module probably not setup right.";
-    }
-    Component result = new Component(libraries: wantedLibs);
-    List<int> resultBytes = util.postProcess(result);
-    moduleResult[moduleName] = resultBytes;
-  }
-
-  return moduleResult;
-}
-
-Future<Null> newWorldTest(List worlds, Map modules, bool omitPlatform,
-    String targetName, bool incrementalSerialization) async {
-  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
-  final Uri base = Uri.parse("org-dartlang-test:///");
-  final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
-  final Uri initializeFrom = base.resolve("initializeFrom.dill");
-  Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
-  final List<int> sdkSummaryData =
-      await new File.fromUri(platformUri).readAsBytes();
-
-  List<int> newestWholeComponentData;
-  Component newestWholeComponent;
-  MemoryFileSystem fs;
-  Map<String, String> sourceFiles;
-  CompilerOptions options;
-  TestIncrementalCompiler compiler;
-  IncrementalSerializer incrementalSerializer;
-
-  Map<String, List<int>> moduleData;
-  Map<String, Component> moduleComponents;
-  Component sdk;
-  if (modules != null) {
-    moduleData = await createModules(modules, sdkSummaryData, targetName);
-    sdk = newestWholeComponent = new Component();
-    new BinaryBuilder(sdkSummaryData, filename: null, disableLazyReading: false)
-        .readComponent(newestWholeComponent);
-  }
-
-  int worldNum = 0;
-  for (YamlMap world in worlds) {
-    worldNum++;
-    print("----------------");
-    print("World #$worldNum");
-    print("----------------");
-    List<Component> modulesToUse;
-    if (world["modules"] != null) {
-      moduleComponents ??= new Map<String, Component>();
-
-      sdk.adoptChildren();
-      for (Component c in moduleComponents.values) {
-        c.adoptChildren();
-      }
-
-      modulesToUse = new List<Component>();
-      for (String moduleName in world["modules"]) {
-        Component moduleComponent = moduleComponents[moduleName];
-        if (moduleComponent != null) {
-          modulesToUse.add(moduleComponent);
-        }
-      }
-      for (String moduleName in world["modules"]) {
-        Component moduleComponent = moduleComponents[moduleName];
-        if (moduleComponent == null) {
-          moduleComponent = new Component(nameRoot: sdk.root);
-          new BinaryBuilder(moduleData[moduleName],
-                  filename: null,
-                  disableLazyReading: false,
-                  alwaysCreateNewNamedNodes: true)
-              .readComponent(moduleComponent);
-          moduleComponents[moduleName] = moduleComponent;
-          modulesToUse.add(moduleComponent);
-        }
-      }
-    }
-
-    bool brandNewWorld = true;
-    if (world["worldType"] == "updated") {
-      brandNewWorld = false;
-    }
-    bool noFullComponent = false;
-    if (world["noFullComponent"] == true) {
-      noFullComponent = true;
-    }
-
-    if (brandNewWorld) {
-      fs = new MemoryFileSystem(base);
-    }
-    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-    bool expectInitializeFromDill = false;
-    if (newestWholeComponentData != null &&
-        newestWholeComponentData.isNotEmpty) {
-      fs
-          .entityForUri(initializeFrom)
-          .writeAsBytesSync(newestWholeComponentData);
-      expectInitializeFromDill = true;
-    }
-    if (world["expectInitializeFromDill"] != null) {
-      expectInitializeFromDill = world["expectInitializeFromDill"];
-    }
-    if (brandNewWorld) {
-      sourceFiles = new Map<String, String>.from(world["sources"]);
-    } else {
-      sourceFiles.addAll(
-          new Map<String, String>.from(world["sources"] ?? <String, String>{}));
-    }
-    Uri packagesUri;
-    for (String filename in sourceFiles.keys) {
-      String data = sourceFiles[filename] ?? "";
-      Uri uri = base.resolve(filename);
-      if (filename == ".packages") {
-        packagesUri = uri;
-      }
-      fs.entityForUri(uri).writeAsStringSync(data);
-    }
-    if (world["dotPackagesFile"] != null) {
-      packagesUri = base.resolve(world["dotPackagesFile"]);
-    }
-
-    if (brandNewWorld) {
-      options = getOptions(targetName: targetName);
-      options.fileSystem = fs;
-      options.sdkRoot = null;
-      options.sdkSummary = sdkSummary;
-      options.omitPlatform = omitPlatform != false;
-    }
-    if (packagesUri != null) {
-      options.packagesFileUri = packagesUri;
-    }
-    bool gotError = false;
-    final Set<String> formattedErrors = Set<String>();
-    bool gotWarning = false;
-    final Set<String> formattedWarnings = Set<String>();
-
-    options.onDiagnostic = (DiagnosticMessage message) {
-      String stringId = message.ansiFormatted.join("\n");
-      if (message is FormattedMessage) {
-        stringId = message.toJsonString();
-      } else if (message is DiagnosticMessageFromJson) {
-        stringId = message.toJsonString();
-      }
-      if (message.severity == Severity.error) {
-        gotError = true;
-        if (!formattedErrors.add(stringId)) {
-          Expect.fail("Got the same message twice: ${stringId}");
-        }
-      } else if (message.severity == Severity.warning) {
-        gotWarning = true;
-        if (!formattedWarnings.add(stringId)) {
-          Expect.fail("Got the same message twice: ${stringId}");
-        }
-      }
-    };
-
-    List<Uri> entries;
-    if (world["entry"] is String) {
-      entries = [base.resolve(world["entry"])];
-    } else {
-      entries = new List<Uri>();
-      List<dynamic> entryList = world["entry"];
-      for (String entry in entryList) {
-        entries.add(base.resolve(entry));
-      }
-    }
-    bool outlineOnly = world["outlineOnly"] == true;
-    bool skipOutlineBodyCheck = world["skipOutlineBodyCheck"] == true;
-    if (brandNewWorld) {
-      if (incrementalSerialization == true) {
-        incrementalSerializer = new IncrementalSerializer();
-      }
-      if (world["fromComponent"] == true) {
-        compiler = new TestIncrementalCompiler.fromComponent(
-            options,
-            entries.first,
-            (modulesToUse != null) ? sdk : newestWholeComponent,
-            outlineOnly,
-            incrementalSerializer);
-      } else {
-        compiler = new TestIncrementalCompiler(options, entries.first,
-            initializeFrom, outlineOnly, incrementalSerializer);
-
-        if (modulesToUse != null) {
-          throw "You probably shouldn't do this! "
-              "Any modules will have another sdk loaded!";
-        }
-      }
-    }
-
-    List<Uri> invalidated = new List<Uri>();
-    if (world["invalidate"] != null) {
-      for (String filename in world["invalidate"]) {
-        Uri uri = base.resolve(filename);
-        invalidated.add(uri);
-        compiler.invalidate(uri);
-      }
-    }
-
-    if (modulesToUse != null) {
-      compiler.setModulesToLoadOnNextComputeDelta(modulesToUse);
-      compiler.invalidateAllSources();
-      compiler.trackNeededDillLibraries = true;
-    }
-
-    Stopwatch stopwatch = new Stopwatch()..start();
-    Component component = await compiler.computeDelta(
-        entryPoints: entries,
-        fullComponent: brandNewWorld ? false : (noFullComponent ? false : true),
-        simulateTransformer: world["simulateTransformer"]);
-    if (outlineOnly && !skipOutlineBodyCheck) {
-      for (Library lib in component.libraries) {
-        for (Class c in lib.classes) {
-          for (Procedure p in c.procedures) {
-            if (p.function.body != null && p.function.body is! EmptyStatement) {
-              throw "Got body (${p.function.body.runtimeType})";
-            }
-          }
-        }
-        for (Procedure p in lib.procedures) {
-          if (p.function.body != null && p.function.body is! EmptyStatement) {
-            throw "Got body (${p.function.body.runtimeType})";
-          }
-        }
-      }
-    }
-    performErrorAndWarningCheck(
-        world, gotError, formattedErrors, gotWarning, formattedWarnings);
-    util.throwOnEmptyMixinBodies(component);
-    util.throwOnInsufficientUriToSource(component);
-    print("Compile took ${stopwatch.elapsedMilliseconds} ms");
-
-    checkExpectedContent(world, component);
-    checkNeededDillLibraries(world, compiler.neededDillLibraries, base);
-
-    if (!noFullComponent) {
-      Set<Library> allLibraries = new Set<Library>();
-      for (Library lib in component.libraries) {
-        computeAllReachableLibrariesFor(lib, allLibraries);
-      }
-      if (allLibraries.length != component.libraries.length) {
-        Expect.fail("Expected for the reachable stuff to be equal to "
-            "${component.libraries} but it was $allLibraries");
-      }
-      Set<Library> tooMany = allLibraries.toSet()
-        ..removeAll(component.libraries);
-      if (tooMany.isNotEmpty) {
-        Expect.fail("Expected for the reachable stuff to be equal to "
-            "${component.libraries} but these were there too: $tooMany "
-            "(and others were missing)");
-      }
-    }
-
-    newestWholeComponentData = util.postProcess(component);
-    newestWholeComponent = component;
-    print("*****\n\ncomponent:\n"
-        "${componentToStringSdkFiltered(component)}\n\n\n");
-
-    if (world["uriToSourcesDoesntInclude"] != null) {
-      for (String filename in world["uriToSourcesDoesntInclude"]) {
-        Uri uri = base.resolve(filename);
-        if (component.uriToSource[uri] != null) {
-          throw "Expected no uriToSource for $uri but found "
-              "${component.uriToSource[uri]}";
-        }
-      }
-    }
-
-    int nonSyntheticLibraries = countNonSyntheticLibraries(component);
-    int nonSyntheticPlatformLibraries =
-        countNonSyntheticPlatformLibraries(component);
-    int syntheticLibraries = countSyntheticLibraries(component);
-    if (world["expectsPlatform"] == true) {
-      if (nonSyntheticPlatformLibraries < 5) {
-        throw "Expected to have at least 5 platform libraries "
-            "(actually, the entire sdk), "
-            "but got $nonSyntheticPlatformLibraries.";
-      }
-    } else {
-      if (nonSyntheticPlatformLibraries != 0) {
-        throw "Expected to have 0 platform libraries "
-            "but got $nonSyntheticPlatformLibraries.";
-      }
-    }
-    if (world["expectedLibraryCount"] != null) {
-      if (nonSyntheticLibraries - nonSyntheticPlatformLibraries !=
-          world["expectedLibraryCount"]) {
-        throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
-            "libraries, got "
-            "${nonSyntheticLibraries - nonSyntheticPlatformLibraries} "
-            "(not counting platform libraries)";
-      }
-    }
-    if (world["expectedSyntheticLibraryCount"] != null) {
-      if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
-        throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
-            "libraries, got ${syntheticLibraries}";
-      }
-    }
-    if (!noFullComponent) {
-      List<Library> entryLib = component.libraries
-          .where((Library lib) =>
-              entries.contains(lib.importUri) || entries.contains(lib.fileUri))
-          .toList();
-      if (entryLib.length != entries.length) {
-        throw "Expected the entries to become libraries. "
-            "Got ${entryLib.length} libraries for the expected "
-            "${entries.length} entries.";
-      }
-    }
-    if (compiler.initializedFromDill != expectInitializeFromDill) {
-      throw "Expected that initializedFromDill would be "
-          "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
-    }
-
-    if (incrementalSerialization == true && compiler.initializedFromDill) {
-      Expect.isTrue(compiler.initializedIncrementalSerializer);
-    } else {
-      Expect.isFalse(compiler.initializedIncrementalSerializer);
-    }
-
-    if (world["checkInvalidatedFiles"] != false) {
-      Set<Uri> filteredInvalidated =
-          compiler.getFilteredInvalidatedImportUrisForTesting(invalidated);
-      if (world["invalidate"] != null) {
-        Expect.equals(
-            world["invalidate"].length, filteredInvalidated?.length ?? 0);
-        List expectedInvalidatedUri = world["expectedInvalidatedUri"];
-        if (expectedInvalidatedUri != null) {
-          Expect.setEquals(expectedInvalidatedUri.map((s) => base.resolve(s)),
-              filteredInvalidated);
-        }
-      } else {
-        Expect.isNull(filteredInvalidated);
-        Expect.isNull(world["expectedInvalidatedUri"]);
-      }
-    }
-    List<int> incrementalSerializationBytes = checkIncrementalSerialization(
-        incrementalSerialization, component, incrementalSerializer, world);
-
-    Set<String> prevFormattedErrors = formattedErrors.toSet();
-    Set<String> prevFormattedWarnings = formattedWarnings.toSet();
-
-    clearPrevErrorsEtc() {
-      gotError = false;
-      formattedErrors.clear();
-      gotWarning = false;
-      formattedWarnings.clear();
-    }
-
-    if (!noFullComponent) {
-      clearPrevErrorsEtc();
-      Component component2 = await compiler.computeDelta(
-          entryPoints: entries,
-          fullComponent: true,
-          simulateTransformer: world["simulateTransformer"]);
-      performErrorAndWarningCheck(
-          world, gotError, formattedErrors, gotWarning, formattedWarnings);
-      List<int> thisWholeComponent = util.postProcess(component2);
-      print("*****\n\ncomponent2:\n"
-          "${componentToStringSdkFiltered(component2)}\n\n\n");
-      checkIsEqual(newestWholeComponentData, thisWholeComponent);
-      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
-          prevFormattedWarnings, formattedWarnings);
-
-      List<int> incrementalSerializationBytes2 = checkIncrementalSerialization(
-          incrementalSerialization, component2, incrementalSerializer, world);
-
-      if ((incrementalSerializationBytes == null &&
-              incrementalSerializationBytes2 != null) ||
-          (incrementalSerializationBytes != null &&
-              incrementalSerializationBytes2 == null)) {
-        throw "Incremental serialization gave results in one instance, "
-            "but not another.";
-      }
-
-      if (incrementalSerializationBytes != null) {
-        checkIsEqual(
-            incrementalSerializationBytes, incrementalSerializationBytes2);
-      }
-    }
-
-    if (world["expressionCompilation"] != null) {
-      Uri uri = base.resolve(world["expressionCompilation"]["uri"]);
-      String expression = world["expressionCompilation"]["expression"];
-      await compiler.compileExpression(expression, {}, [], "debugExpr", uri);
-    }
-
-    if (!noFullComponent && incrementalSerialization == true) {
-      // Do compile from scratch and compare.
-      clearPrevErrorsEtc();
-      TestIncrementalCompiler compilerFromScratch;
-
-      IncrementalSerializer incrementalSerializer2;
-      if (incrementalSerialization == true) {
-        incrementalSerializer2 = new IncrementalSerializer();
-      }
-
-      if (world["fromComponent"] == true || modulesToUse != null) {
-        compilerFromScratch = new TestIncrementalCompiler.fromComponent(
-            options, entries.first, sdk, outlineOnly, incrementalSerializer2);
-      } else {
-        compilerFromScratch = new TestIncrementalCompiler(
-            options, entries.first, null, outlineOnly, incrementalSerializer2);
-      }
-
-      if (modulesToUse != null) {
-        compilerFromScratch.setModulesToLoadOnNextComputeDelta(modulesToUse);
-        compilerFromScratch.invalidateAllSources();
-        compilerFromScratch.trackNeededDillLibraries = true;
-      }
-
-      Stopwatch stopwatch = new Stopwatch()..start();
-      Component component3 = await compilerFromScratch.computeDelta(
-          entryPoints: entries,
-          simulateTransformer: world["simulateTransformer"]);
-      performErrorAndWarningCheck(
-          world, gotError, formattedErrors, gotWarning, formattedWarnings);
-      util.throwOnEmptyMixinBodies(component3);
-      util.throwOnInsufficientUriToSource(component3);
-      print("Compile took ${stopwatch.elapsedMilliseconds} ms");
-
-      util.postProcess(component3);
-      print("*****\n\ncomponent3:\n"
-          "${componentToStringSdkFiltered(component3)}\n\n\n");
-      checkErrorsAndWarnings(prevFormattedErrors, formattedErrors,
-          prevFormattedWarnings, formattedWarnings);
-
-      List<int> incrementalSerializationBytes3 = checkIncrementalSerialization(
-          incrementalSerialization, component3, incrementalSerializer2, world);
-
-      if ((incrementalSerializationBytes == null &&
-              incrementalSerializationBytes3 != null) ||
-          (incrementalSerializationBytes != null &&
-              incrementalSerializationBytes3 == null)) {
-        throw "Incremental serialization gave results in one instance, "
-            "but not another.";
-      }
-
-      if (incrementalSerializationBytes != null) {
-        if (world["brandNewIncrementalSerializationAllowDifferent"] == true) {
-          // Don't check for equality when we allow it to be different
-          // (e.g. when the old one contains more, and the new one doesn't).
-        } else {
-          checkIsEqual(
-              incrementalSerializationBytes, incrementalSerializationBytes3);
-        }
-        newestWholeComponentData = incrementalSerializationBytes;
-      }
-    }
-  }
-}
-
-void checkErrorsAndWarnings(
-    Set<String> prevFormattedErrors,
-    Set<String> formattedErrors,
-    Set<String> prevFormattedWarnings,
-    Set<String> formattedWarnings) {
-  if (prevFormattedErrors.length != formattedErrors.length) {
-    Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
-        "now had ${formattedErrors.length}.\n\n"
-        "Before:\n"
-        "${prevFormattedErrors.join("\n")}"
-        "\n\n"
-        "Now:\n"
-        "${formattedErrors.join("\n")}");
-  }
-  if ((prevFormattedErrors.toSet()..removeAll(formattedErrors)).isNotEmpty) {
-    Expect.fail("Previously got error messages $prevFormattedErrors, "
-        "now had ${formattedErrors}.");
-  }
-  if (prevFormattedWarnings.length != formattedWarnings.length) {
-    Expect.fail("Previously had ${prevFormattedWarnings.length} errors, "
-        "now had ${formattedWarnings.length}.");
-  }
-  if ((prevFormattedWarnings.toSet()..removeAll(formattedWarnings))
-      .isNotEmpty) {
-    Expect.fail("Previously got error messages $prevFormattedWarnings, "
-        "now had ${formattedWarnings}.");
-  }
-}
-
-List<int> checkIncrementalSerialization(
-    bool incrementalSerialization,
-    Component component,
-    IncrementalSerializer incrementalSerializer,
-    YamlMap world) {
-  if (incrementalSerialization == true) {
-    Component c = new Component(nameRoot: component.root);
-    c.libraries.addAll(component.libraries);
-    c.uriToSource.addAll(component.uriToSource);
-    Map<String, Set<String>> originalContent = buildMapOfContent(c);
-    ByteSink sink = new ByteSink();
-    int librariesBefore = c.libraries.length;
-    incrementalSerializer.writePackagesToSinkAndTrimComponent(c, sink);
-    int librariesAfter = c.libraries.length;
-    if (librariesAfter > librariesBefore) {
-      throw "Incremental serialization added libraries!";
-    }
-    if (librariesBefore == librariesAfter &&
-        world["incrementalSerializationDoesWork"] == true) {
-      throw "Incremental serialization didn't remove any libraries!";
-    }
-    if (librariesAfter < librariesBefore && sink.builder.isEmpty) {
-      throw "Incremental serialization din't output any bytes, "
-          "but did remove libraries";
-    } else if (librariesAfter == librariesBefore && !sink.builder.isEmpty) {
-      throw "Incremental serialization did output bytes, "
-          "but didn't remove libraries";
-    }
-    if (librariesAfter < librariesBefore) {
-      // If we actually did incremenally serialize anything, check the output!
-      // If we actually did incremenally serialize anything, check the output!
-      BinaryPrinter printer = new BinaryPrinter(sink);
-      printer.writeComponentFile(c);
-      List<int> bytes = sink.builder.takeBytes();
-
-      // Load the bytes back in.
-      Component loadedComponent = new Component();
-      new BinaryBuilder(bytes, filename: null).readComponent(loadedComponent);
-
-      // Check that it doesn't contain anything we said it shouldn't.
-      if (world["serializationShouldNotInclude"] is List) {
-        List serializationShouldNotInclude =
-            world["serializationShouldNotInclude"];
-        Set<Uri> includedImportUris =
-            loadedComponent.libraries.map((l) => l.importUri).toSet();
-        for (String uriString in serializationShouldNotInclude) {
-          Uri uri = Uri.parse(uriString);
-          if (includedImportUris.contains(uri)) {
-            throw "Incremental serialization shouldn't include "
-                "$uriString but did.";
-          }
-        }
-      }
-
-      // Check that it contains at least what we want.
-      Map<String, Set<String>> afterContent =
-          buildMapOfContent(loadedComponent);
-      // Remove any keys in afterContent not in the original as the written
-      // one is allowed to contain *more*.
-      Set<String> newKeys = afterContent.keys.toSet()
-        ..removeAll(originalContent.keys);
-      for (String key in newKeys) {
-        afterContent.remove(key);
-      }
-      checkExpectedContentData(afterContent, originalContent);
-
-      // Check that the result is self-contained.
-      checkSelfContained(loadedComponent);
-
-      return bytes;
-    }
-  }
-  return null;
-}
-
-void checkSelfContained(Component component) {
-  Set<Library> got = new Set<Library>.from(component.libraries);
-  for (Library lib in component.libraries) {
-    for (LibraryDependency dependency in lib.dependencies) {
-      if (dependency.importedLibraryReference.node == null ||
-          !got.contains(dependency.targetLibrary)) {
-        if (dependency.importedLibraryReference.canonicalName
-            .toString()
-            .startsWith("root::dart:")) {
-          continue;
-        }
-        throw "Component didn't contain ${dependency.importedLibraryReference} "
-            "and it should have.";
-      }
-    }
-  }
-}
-
-void computeAllReachableLibrariesFor(Library lib, Set<Library> allLibraries) {
-  Set<Library> libraries = new Set<Library>();
-  List<Library> workList = <Library>[];
-  allLibraries.add(lib);
-  libraries.add(lib);
-  workList.add(lib);
-  while (workList.isNotEmpty) {
-    Library library = workList.removeLast();
-    for (LibraryDependency dependency in library.dependencies) {
-      if (dependency.targetLibrary.importUri.scheme == "dart") continue;
-      if (libraries.add(dependency.targetLibrary)) {
-        workList.add(dependency.targetLibrary);
-        allLibraries.add(dependency.targetLibrary);
-      }
-    }
-  }
-}
-
-void checkExpectedContent(YamlMap world, Component component) {
-  if (world["expectedContent"] != null) {
-    Map<String, Set<String>> actualContent = buildMapOfContent(component);
-    Map expectedContent = world["expectedContent"];
-    checkExpectedContentData(actualContent, expectedContent);
-  }
-}
-
-void checkExpectedContentData(
-    Map<String, Set<String>> actualContent, Map expectedContent) {
-  doThrow() {
-    throw "Expected and actual content not the same.\n"
-        "Expected $expectedContent.\n"
-        "Got $actualContent";
-  }
-
-  if (actualContent.length != expectedContent.length) doThrow();
-  Set<String> missingKeys = actualContent.keys.toSet()
-    ..removeAll(expectedContent.keys);
-  if (missingKeys.isNotEmpty) doThrow();
-  for (String key in expectedContent.keys) {
-    Set<String> expected = new Set<String>.from(expectedContent[key]);
-    Set<String> actual = actualContent[key].toSet();
-    if (expected.length != actual.length) doThrow();
-    actual.removeAll(expected);
-    if (actual.isNotEmpty) doThrow();
-  }
-}
-
-Map<String, Set<String>> buildMapOfContent(Component component) {
-  Map<String, Set<String>> actualContent = new Map<String, Set<String>>();
-  for (Library lib in component.libraries) {
-    Set<String> libContent =
-        actualContent[lib.importUri.toString()] = new Set<String>();
-    for (Class c in lib.classes) {
-      libContent.add("Class ${c.name}");
-    }
-    for (Procedure p in lib.procedures) {
-      libContent.add("Procedure ${p.name}");
-    }
-    for (Field f in lib.fields) {
-      libContent.add("Field ${f.name}");
-    }
-  }
-  return actualContent;
-}
-
-void checkNeededDillLibraries(
-    YamlMap world, Set<Library> neededDillLibraries, Uri base) {
-  if (world["neededDillLibraries"] != null) {
-    List<Uri> actualContent = new List<Uri>();
-    for (Library lib in neededDillLibraries) {
-      if (lib.importUri.scheme == "dart") continue;
-      actualContent.add(lib.importUri);
-    }
-
-    List<Uri> expectedContent = new List<Uri>();
-    for (String entry in world["neededDillLibraries"]) {
-      expectedContent.add(base.resolve(entry));
-    }
-
-    doThrow() {
-      throw "Expected and actual content not the same.\n"
-          "Expected $expectedContent.\n"
-          "Got $actualContent";
-    }
-
-    if (actualContent.length != expectedContent.length) doThrow();
-    Set<Uri> notInExpected =
-        actualContent.toSet().difference(expectedContent.toSet());
-    Set<Uri> notInActual =
-        expectedContent.toSet().difference(actualContent.toSet());
-    if (notInExpected.isNotEmpty) doThrow();
-    if (notInActual.isNotEmpty) doThrow();
-  }
-}
-
-String componentToStringSdkFiltered(Component node) {
-  Component c = new Component();
-  List<Uri> dartUris = new List<Uri>();
-  for (Library lib in node.libraries) {
-    if (lib.importUri.scheme == "dart") {
-      dartUris.add(lib.importUri);
-    } else {
-      c.libraries.add(lib);
-    }
-  }
-
-  StringBuffer s = new StringBuffer();
-  s.write(componentToString(c));
-
-  if (dartUris.isNotEmpty) {
-    s.writeln("");
-    s.writeln("And ${dartUris.length} platform libraries:");
-    for (Uri uri in dartUris) {
-      s.writeln(" - $uri");
-    }
-  }
-
-  return s.toString();
-}
-
-int countNonSyntheticLibraries(Component c) {
-  int result = 0;
-  for (Library lib in c.libraries) {
-    if (!lib.isSynthetic) result++;
-  }
-  return result;
-}
-
-int countNonSyntheticPlatformLibraries(Component c) {
-  int result = 0;
-  for (Library lib in c.libraries) {
-    if (!lib.isSynthetic && lib.importUri.scheme == "dart") result++;
-  }
-  return result;
-}
-
-int countSyntheticLibraries(Component c) {
-  int result = 0;
-  for (Library lib in c.libraries) {
-    if (lib.isSynthetic) result++;
-  }
-  return result;
-}
-
-void performErrorAndWarningCheck(
-    YamlMap world,
-    bool gotError,
-    Set<String> formattedErrors,
-    bool gotWarning,
-    Set<String> formattedWarnings) {
-  if (world["errors"] == true && !gotError) {
-    throw "Expected error, but didn't get any.";
-  } else if (world["errors"] != true && gotError) {
-    throw "Got unexpected error(s): $formattedErrors.";
-  }
-  if (world["warnings"] == true && !gotWarning) {
-    throw "Expected warning, but didn't get any.";
-  } else if (world["warnings"] != true && gotWarning) {
-    throw "Got unexpected warnings(s): $formattedWarnings.";
-  }
-}
-
-void checkIsEqual(List<int> a, List<int> b) {
-  int length = a.length;
-  if (b.length < length) {
-    length = b.length;
-  }
-  for (int i = 0; i < length; ++i) {
-    if (a[i] != b[i]) {
-      print("Data differs at byte ${i + 1}.");
-
-      StringBuffer message = new StringBuffer();
-      message.writeln("Data differs at byte ${i + 1}.");
-      message.writeln("");
-      message.writeln("Will try to find more useful information:");
-
-      final String repoDir = computeRepoDir();
-      File binaryMd = new File("$repoDir/pkg/kernel/binary.md");
-      String binaryMdContent = binaryMd.readAsStringSync();
-
-      DillComparer dillComparer = new DillComparer();
-      if (dillComparer.compare(a, b, binaryMdContent, message)) {
-        message.writeln(
-            "Somehow the two different byte-lists compared to the same.");
-      }
-
-      Expect.fail(message.toString());
-    }
-  }
-  Expect.equals(a.length, b.length);
-}
-
-CompilerOptions getOptions({String targetName}) {
-  final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
-  Target target = new VmTarget(new TargetFlags());
-  if (targetName != null) {
-    if (targetName == "None") {
-      target = new NoneTarget(new TargetFlags());
-    } else if (targetName == "VM") {
-      // default.
-    } else {
-      throw "Unknown target name '$targetName'";
-    }
-  }
-  CompilerOptions options = new CompilerOptions()
-    ..sdkRoot = sdkRoot
-    ..target = target
-    ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
-    ..omitPlatform = true
-    ..onDiagnostic = (DiagnosticMessage message) {
-      if (message.severity == Severity.error ||
-          message.severity == Severity.warning) {
-        Expect.fail(
-            "Unexpected error: ${message.plainTextFormatted.join('\n')}");
-      }
-    }
-    ..sdkSummary = sdkRoot.resolve("vm_platform_strong.dill")
-    ..environmentDefines = const {};
-  return options;
-}
-
-Future<bool> normalCompile(Uri input, Uri output,
-    {CompilerOptions options}) async {
-  options ??= getOptions();
-  TestIncrementalCompiler compiler =
-      new TestIncrementalCompiler(options, input);
-  List<int> bytes =
-      await normalCompileToBytes(input, options: options, compiler: compiler);
-  new File.fromUri(output).writeAsBytesSync(bytes);
-  return compiler.initializedFromDill;
-}
-
-Future<List<int>> normalCompileToBytes(Uri input,
-    {CompilerOptions options, IncrementalCompiler compiler}) async {
-  Component component = await normalCompileToComponent(input,
-      options: options, compiler: compiler);
-  return util.postProcess(component);
-}
-
-Future<Component> normalCompileToComponent(Uri input,
-    {CompilerOptions options, IncrementalCompiler compiler}) async {
-  Component component =
-      await normalCompilePlain(input, options: options, compiler: compiler);
-  util.throwOnEmptyMixinBodies(component);
-  util.throwOnInsufficientUriToSource(component);
-  return component;
-}
-
-Future<Component> normalCompilePlain(Uri input,
-    {CompilerOptions options, IncrementalCompiler compiler}) async {
-  options ??= getOptions();
-  compiler ??= new TestIncrementalCompiler(options, input);
-  return await compiler.computeDelta();
-}
-
-Future<bool> initializedCompile(
-    Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
-    {CompilerOptions options}) async {
-  options ??= getOptions();
-  TestIncrementalCompiler compiler =
-      new TestIncrementalCompiler(options, input, initializeWith);
-  for (Uri invalidateUri in invalidateUris) {
-    compiler.invalidate(invalidateUri);
-  }
-  Component initializedComponent = await compiler.computeDelta();
-  util.throwOnEmptyMixinBodies(initializedComponent);
-  util.throwOnInsufficientUriToSource(initializedComponent);
-  bool result = compiler.initializedFromDill;
-  new File.fromUri(output)
-      .writeAsBytesSync(util.postProcess(initializedComponent));
-  int actuallyInvalidatedCount = compiler
-          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
-          ?.length ??
-      0;
-  if (result && actuallyInvalidatedCount < invalidateUris.length) {
-    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
-        "got $actuallyInvalidatedCount");
-  }
-
-  Component initializedFullComponent =
-      await compiler.computeDelta(fullComponent: true);
-  util.throwOnEmptyMixinBodies(initializedFullComponent);
-  util.throwOnInsufficientUriToSource(initializedFullComponent);
-  Expect.equals(initializedComponent.libraries.length,
-      initializedFullComponent.libraries.length);
-  Expect.equals(initializedComponent.uriToSource.length,
-      initializedFullComponent.uriToSource.length);
-
-  for (Uri invalidateUri in invalidateUris) {
-    compiler.invalidate(invalidateUri);
-  }
-
-  Component partialComponent = await compiler.computeDelta();
-  util.throwOnEmptyMixinBodies(partialComponent);
-  util.throwOnInsufficientUriToSource(partialComponent);
-  actuallyInvalidatedCount = (compiler
-          .getFilteredInvalidatedImportUrisForTesting(invalidateUris)
-          ?.length ??
-      0);
-  if (actuallyInvalidatedCount < invalidateUris.length) {
-    Expect.fail("Expected at least ${invalidateUris.length} invalidated uris, "
-        "got $actuallyInvalidatedCount");
-  }
-
-  Component emptyComponent = await compiler.computeDelta();
-  util.throwOnEmptyMixinBodies(emptyComponent);
-  util.throwOnInsufficientUriToSource(emptyComponent);
-
-  List<Uri> fullLibUris =
-      initializedComponent.libraries.map((lib) => lib.importUri).toList();
-  List<Uri> partialLibUris =
-      partialComponent.libraries.map((lib) => lib.importUri).toList();
-  List<Uri> emptyLibUris =
-      emptyComponent.libraries.map((lib) => lib.importUri).toList();
-
-  Expect.isTrue(fullLibUris.length > partialLibUris.length ||
-      partialLibUris.length == invalidateUris.length);
-  Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);
-
-  Expect.isTrue(emptyLibUris.isEmpty);
-
-  return result;
-}
-
-class TestIncrementalCompiler extends IncrementalCompiler {
-  Set<Uri> invalidatedImportUrisForTesting;
-  final Uri entryPoint;
-
-  /// Filter out the automatically added entryPoint, unless it's explicitly
-  /// specified as being invalidated.
-  /// Also filter out uris with "nonexisting.dart" in the name as synthetic
-  /// libraries are invalidated automatically too.
-  /// This is not perfect, but works for what it's currently used for.
-  Set<Uri> getFilteredInvalidatedImportUrisForTesting(
-      List<Uri> invalidatedUris) {
-    if (invalidatedImportUrisForTesting == null) return null;
-
-    Set<String> invalidatedFilenames =
-        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 (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
-          invalidatedFilenames.contains(uri.pathSegments.last)) result.add(uri);
-    }
-
-    return result.isEmpty ? null : result;
-  }
-
-  TestIncrementalCompiler(CompilerOptions options, this.entryPoint,
-      [Uri initializeFrom,
-      bool outlineOnly,
-      IncrementalSerializer incrementalSerializer])
-      : super(
-            new CompilerContext(
-                new ProcessedOptions(options: options, inputs: [entryPoint])),
-            initializeFrom,
-            outlineOnly,
-            incrementalSerializer);
-
-  TestIncrementalCompiler.fromComponent(CompilerOptions options,
-      this.entryPoint, Component componentToInitializeFrom,
-      [bool outlineOnly, IncrementalSerializer incrementalSerializer])
-      : super.fromComponent(
-            new CompilerContext(
-                new ProcessedOptions(options: options, inputs: [entryPoint])),
-            componentToInitializeFrom,
-            outlineOnly,
-            incrementalSerializer);
-
-  @override
-  void recordInvalidatedImportUrisForTesting(List<Uri> uris) {
-    invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toSet();
-  }
-
-  @override
-  void recordNonFullComponentForTesting(Component component) {
-    // It should at least contain the sdk. Slight smoke test.
-    if (!component.libraries
-        .map((lib) => lib.importUri.toString())
-        .contains("dart:core")) {
-      throw "Loaders builder should contain the sdk, "
-          "but didn't even contain dart:core.";
-    }
-  }
-
-  @override
-  Future<Component> computeDelta(
-      {List<Uri> entryPoints,
-      bool fullComponent = false,
-      bool simulateTransformer}) async {
-    Component result = await super
-        .computeDelta(entryPoints: entryPoints, fullComponent: fullComponent);
-
-    // We should at least have the SDK builders available. Slight smoke test.
-    if (!dillLoadedData.loader.builders.keys
-        .map((uri) => uri.toString())
-        .contains("dart:core")) {
-      throw "Loaders builder should contain the sdk, "
-          "but didn't even contain dart:core.";
-    }
-
-    if (simulateTransformer == true) {
-      doSimulateTransformer(result);
-    }
-    return result;
-  }
-}
-
-void doSimulateTransformer(Component c) {
-  for (Library lib in c.libraries) {
-    if (lib.fields
-        .where((f) => f.name.name == "lalala_SimulateTransformer")
-        .toList()
-        .isNotEmpty) continue;
-    Name fieldName = new Name("lalala_SimulateTransformer");
-    Field field = new Field(fieldName,
-        isFinal: true,
-        reference: lib.reference.canonicalName
-            ?.getChildFromFieldWithName(fieldName)
-            ?.reference);
-    lib.addMember(field);
-    for (Class c in lib.classes) {
-      if (c.fields
-          .where((f) => f.name.name == "lalala_SimulateTransformer")
-          .toList()
-          .isNotEmpty) continue;
-      fieldName = new Name("lalala_SimulateTransformer");
-      field = new Field(fieldName,
-          isFinal: true,
-          reference: c.reference.canonicalName
-              ?.getChildFromFieldWithName(fieldName)
-              ?.reference);
-      c.addMember(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 f108317..ccd1823 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
@@ -6,6 +6,11 @@
 
 import 'dart:io' show File;
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, getMessageCodeObject;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:expect/expect.dart' show Expect;
 
 import 'package:front_end/src/api_prototype/compiler_options.dart'
@@ -14,9 +19,6 @@
 import "package:front_end/src/api_prototype/memory_file_system.dart"
     show MemoryFileSystem;
 
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, getMessageCodeObject;
-
 import 'package:front_end/src/base/processed_options.dart'
     show ProcessedOptions;
 
@@ -38,11 +40,9 @@
 
 import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 import 'package:kernel/kernel.dart' show Component, Library;
 
-import 'incremental_load_from_dill_test.dart' show getOptions;
+import 'incremental_load_from_dill_suite.dart' show getOptions;
 
 Future<Null> main() async {
   Tester tester = new Tester();
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 a387f9a..7b1f8d2 100644
--- a/pkg/front_end/test/language_versioning/language_versioning_test.dart
+++ b/pkg/front_end/test/language_versioning/language_versioning_test.dart
@@ -3,12 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 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'
+    show DataInterpreter, StringDataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/api_prototype/compiler_options.dart';
 import 'package:front_end/src/fasta/messages.dart' show FormattedMessage;
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart'
-    show DataInterpreter, StringDataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart'
     show
         CfeDataExtractor,
diff --git a/pkg/front_end/test/lint_suite.dart b/pkg/front_end/test/lint_suite.dart
new file mode 100644
index 0000000..57ddab9
--- /dev/null
+++ b/pkg/front_end/test/lint_suite.dart
@@ -0,0 +1,306 @@
+// 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:async' show Future;
+
+import 'dart:io' show Directory, File, FileSystemEntity;
+
+import 'dart:typed_data' show Uint8List;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show FormalParameterKind, MemberKind, Parser;
+
+import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
+    show Utf8BytesScanner;
+
+import 'package:front_end/src/fasta/command_line_reporting.dart'
+    as command_line_reporting;
+
+import 'package:kernel/kernel.dart';
+
+import 'package:package_config/packages.dart' show Packages;
+
+import 'package:package_config/discovery.dart' show loadPackagesFile;
+
+import 'package:testing/testing.dart'
+    show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
+}
+
+class LintTestDescription extends TestDescription {
+  final String shortName;
+  final Uri uri;
+  final LintTestCache cache;
+  final LintListener listener;
+
+  LintTestDescription(this.shortName, this.uri, this.cache, this.listener) {
+    this.listener.description = this;
+    this.listener.uri = uri;
+  }
+
+  String getErrorMessage(int offset, int squigglyLength, String message) {
+    cache.source ??= new Source(cache.lineStarts, cache.rawBytes, uri, uri);
+    Location location = cache.source.getLocation(uri, offset);
+    return command_line_reporting.formatErrorMessage(
+        cache.source.getTextLine(location.line),
+        location,
+        squigglyLength,
+        uri.toString(),
+        message);
+  }
+}
+
+class LintTestCache {
+  List<int> rawBytes;
+  List<int> lineStarts;
+  Source source;
+  Token firstToken;
+  Packages packages;
+}
+
+class Context extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const LintStep(),
+  ];
+
+  // Override special handling of negative tests.
+  @override
+  Result processTestResult(
+      TestDescription description, Result result, bool last) {
+    return result;
+  }
+
+  Stream<LintTestDescription> list(Chain suite) async* {
+    Directory testRoot = new Directory.fromUri(suite.uri);
+    if (await testRoot.exists()) {
+      Stream<FileSystemEntity> files =
+          testRoot.list(recursive: true, followLinks: false);
+      await for (FileSystemEntity entity in files) {
+        if (entity is! File) continue;
+        String path = entity.uri.path;
+        if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
+        if (suite.pattern.any((RegExp r) => path.contains(r))) {
+          Uri root = suite.uri;
+          String baseName = "${entity.uri}".substring("$root".length);
+          baseName = baseName.substring(0, baseName.length - ".dart".length);
+          LintTestCache cache = new LintTestCache();
+
+          yield new LintTestDescription(
+            "$baseName/ExplicitType",
+            entity.uri,
+            cache,
+            new ExplicitTypeLintListener(),
+          );
+
+          yield new LintTestDescription(
+            "$baseName/ImportsTwice",
+            entity.uri,
+            cache,
+            new ImportsTwiceLintListener(),
+          );
+
+          Uri apiUnstableUri =
+              Uri.base.resolve("pkg/front_end/lib/src/api_unstable/");
+          if (!entity.uri.toString().startsWith(apiUnstableUri.toString())) {
+            yield new LintTestDescription(
+              "$baseName/Exports",
+              entity.uri,
+              cache,
+              new ExportsLintListener(),
+            );
+          }
+        }
+      }
+    } else {
+      throw "${suite.uri} isn't a directory";
+    }
+  }
+}
+
+class LintStep extends Step<LintTestDescription, LintTestDescription, Context> {
+  const LintStep();
+
+  String get name => "lint";
+
+  Future<Result<LintTestDescription>> run(
+      LintTestDescription description, Context context) async {
+    if (description.cache.rawBytes == null) {
+      File f = new File.fromUri(description.uri);
+      description.cache.rawBytes = f.readAsBytesSync();
+
+      Uint8List bytes = new Uint8List(description.cache.rawBytes.length + 1);
+      bytes.setRange(
+          0, description.cache.rawBytes.length, description.cache.rawBytes);
+
+      Utf8BytesScanner scanner =
+          new Utf8BytesScanner(bytes, includeComments: true);
+      description.cache.firstToken = scanner.tokenize();
+      description.cache.lineStarts = scanner.lineStarts;
+
+      Uri dotPackages = description.uri.resolve(".packages");
+      while (true) {
+        if (new File.fromUri(dotPackages).existsSync()) {
+          break;
+        }
+        // Stupid bailout.
+        if (dotPackages.pathSegments.length < Uri.base.pathSegments.length) {
+          break;
+        }
+        dotPackages = dotPackages.resolve("../.packages");
+      }
+
+      File dotPackagesFile = new File.fromUri(dotPackages);
+      if (dotPackagesFile.existsSync()) {
+        description.cache.packages = await loadPackagesFile(dotPackages);
+      }
+    }
+
+    if (description.cache.firstToken == null) {
+      return crash(description, StackTrace.current);
+    }
+
+    Parser parser = new Parser(description.listener);
+    parser.parseUnit(description.cache.firstToken);
+
+    if (description.listener.problems.isEmpty) {
+      return pass(description);
+    }
+    return fail(description, description.listener.problems.join("\n\n"));
+  }
+}
+
+class LintListener extends Listener {
+  List<String> problems = new List<String>();
+  LintTestDescription description;
+  Uri uri;
+
+  onProblem(int offset, int squigglyLength, String message) {
+    problems.add(description.getErrorMessage(offset, squigglyLength, message));
+  }
+}
+
+class ExplicitTypeLintListener extends LintListener {
+  List<LatestType> _latestTypes = new List<LatestType>();
+
+  @override
+  void beginVariablesDeclaration(
+      Token token, Token lateToken, Token varFinalOrConst) {
+    if (!_latestTypes.last.type) {
+      onProblem(
+          varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
+    }
+  }
+
+  @override
+  void handleType(Token beginToken, Token questionMark) {
+    _latestTypes.add(new LatestType(beginToken, true));
+  }
+
+  @override
+  void handleNoType(Token lastConsumed) {
+    _latestTypes.add(new LatestType(lastConsumed, false));
+  }
+
+  @override
+  void endFunctionType(Token functionToken, Token questionMark) {
+    _latestTypes.add(new LatestType(functionToken, true));
+  }
+
+  void endTopLevelFields(
+      Token staticToken,
+      Token covariantToken,
+      Token lateToken,
+      Token varFinalOrConst,
+      int count,
+      Token beginToken,
+      Token endToken) {
+    if (!_latestTypes.last.type) {
+      onProblem(beginToken.offset, beginToken.length, "No explicit type.");
+    }
+    _latestTypes.removeLast();
+  }
+
+  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
+      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+    if (!_latestTypes.last.type) {
+      onProblem(
+          varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
+    }
+    _latestTypes.removeLast();
+  }
+
+  void endFormalParameter(
+      Token thisKeyword,
+      Token periodAfterThis,
+      Token nameToken,
+      Token initializerStart,
+      Token initializerEnd,
+      FormalParameterKind kind,
+      MemberKind memberKind) {
+    _latestTypes.removeLast();
+  }
+}
+
+class LatestType {
+  final Token token;
+  bool type;
+
+  LatestType(this.token, this.type);
+}
+
+class ImportsTwiceLintListener extends LintListener {
+  Set<Uri> seenImports = new Set<Uri>();
+
+  void endImport(Token importKeyword, Token semicolon) {
+    Token importUriToken = importKeyword.next;
+    String importUri = importUriToken.lexeme;
+    if (importUri.startsWith("r")) {
+      importUri = importUri.substring(2, importUri.length - 1);
+    } else {
+      importUri = importUri.substring(1, importUri.length - 1);
+    }
+    Uri resolved = uri.resolve(importUri);
+    if (resolved.scheme == "package") {
+      if (description.cache.packages != null) {
+        resolved = description.cache.packages.resolve(resolved);
+      }
+    }
+    if (!seenImports.add(resolved)) {
+      onProblem(importUriToken.offset, importUriToken.lexeme.length,
+          "Uri '$resolved' already imported once.");
+    }
+  }
+}
+
+class ExportsLintListener extends LintListener {
+  void endExport(Token exportKeyword, Token semicolon) {
+    Token exportUriToken = exportKeyword.next;
+    String exportUri = exportUriToken.lexeme;
+    if (exportUri.startsWith("r")) {
+      exportUri = exportUri.substring(2, exportUri.length - 1);
+    } else {
+      exportUri = exportUri.substring(1, exportUri.length - 1);
+    }
+    Uri resolved = uri.resolve(exportUri);
+    if (resolved.scheme == "package") {
+      if (description.cache.packages != null) {
+        resolved = description.cache.packages.resolve(resolved);
+      }
+    }
+    onProblem(exportUriToken.offset, exportUriToken.lexeme.length,
+        "Exports disallowed internally.");
+  }
+}
diff --git a/pkg/front_end/test/lint_test.dart b/pkg/front_end/test/lint_test.dart
deleted file mode 100644
index f674e25..0000000
--- a/pkg/front_end/test/lint_test.dart
+++ /dev/null
@@ -1,288 +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:async' show Future;
-
-import 'dart:io' show Directory, File, FileSystemEntity;
-
-import 'dart:typed_data' show Uint8List;
-
-import 'package:front_end/src/fasta/parser.dart' show Parser;
-
-import 'package:front_end/src/fasta/parser/listener.dart' show Listener;
-
-import 'package:front_end/src/fasta/command_line_reporting.dart'
-    as command_line_reporting;
-
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
-    show Utf8BytesScanner;
-
-import 'package:front_end/src/scanner/token.dart' show Token;
-
-import 'package:front_end/src/scanner/token.dart';
-
-import 'package:kernel/kernel.dart';
-
-import 'package:package_config/packages.dart' show Packages;
-
-import 'package:package_config/discovery.dart' show loadPackagesFile;
-
-import 'package:testing/testing.dart'
-    show Chain, ChainContext, Result, Step, TestDescription, runMe;
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../testing.json");
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  return new Context();
-}
-
-class LintTestDescription extends TestDescription {
-  final String shortName;
-  final Uri uri;
-  final LintTestCache cache;
-  final LintListener listener;
-
-  LintTestDescription(this.shortName, this.uri, this.cache, this.listener) {
-    this.listener.description = this;
-    this.listener.uri = uri;
-  }
-
-  String getErrorMessage(int offset, int squigglyLength, String message) {
-    cache.source ??= new Source(cache.lineStarts, cache.rawBytes, uri, uri);
-    Location location = cache.source.getLocation(uri, offset);
-    return command_line_reporting.formatErrorMessage(
-        cache.source.getTextLine(location.line),
-        location,
-        squigglyLength,
-        uri.toString(),
-        message);
-  }
-}
-
-class LintTestCache {
-  List<int> rawBytes;
-  List<int> lineStarts;
-  Source source;
-  Token firstToken;
-  Packages packages;
-}
-
-class Context extends ChainContext {
-  final List<Step> steps = const <Step>[
-    const LintStep(),
-  ];
-
-  // Override special handling of negative tests.
-  @override
-  Result processTestResult(
-      TestDescription description, Result result, bool last) {
-    return result;
-  }
-
-  Stream<LintTestDescription> list(Chain suite) async* {
-    Directory testRoot = new Directory.fromUri(suite.uri);
-    if (await testRoot.exists()) {
-      Stream<FileSystemEntity> files =
-          testRoot.list(recursive: true, followLinks: false);
-      await for (FileSystemEntity entity in files) {
-        if (entity is! File) continue;
-        String path = entity.uri.path;
-        if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
-        if (suite.pattern.any((RegExp r) => path.contains(r))) {
-          Uri root = suite.uri;
-          String baseName = "${entity.uri}".substring("$root".length);
-          baseName = baseName.substring(0, baseName.length - ".dart".length);
-          LintTestCache cache = new LintTestCache();
-
-          yield new LintTestDescription(
-            "$baseName/ExplicitType",
-            entity.uri,
-            cache,
-            new ExplicitTypeLintListener(),
-          );
-
-          yield new LintTestDescription(
-            "$baseName/ImportsTwice",
-            entity.uri,
-            cache,
-            new ImportsTwiceLintListener(),
-          );
-
-          Uri apiUnstableUri =
-              Uri.base.resolve("pkg/front_end/lib/src/api_unstable/");
-          if (!entity.uri.toString().startsWith(apiUnstableUri.toString())) {
-            yield new LintTestDescription(
-              "$baseName/Exports",
-              entity.uri,
-              cache,
-              new ExportsLintListener(),
-            );
-          }
-        }
-      }
-    } else {
-      throw "${suite.uri} isn't a directory";
-    }
-  }
-}
-
-class LintStep extends Step<LintTestDescription, LintTestDescription, Context> {
-  const LintStep();
-
-  String get name => "lint";
-
-  Future<Result<LintTestDescription>> run(
-      LintTestDescription description, Context context) async {
-    if (description.cache.rawBytes == null) {
-      File f = new File.fromUri(description.uri);
-      description.cache.rawBytes = f.readAsBytesSync();
-
-      Uint8List bytes = new Uint8List(description.cache.rawBytes.length + 1);
-      bytes.setRange(
-          0, description.cache.rawBytes.length, description.cache.rawBytes);
-
-      Utf8BytesScanner scanner =
-          new Utf8BytesScanner(bytes, includeComments: true);
-      description.cache.firstToken = scanner.tokenize();
-      description.cache.lineStarts = scanner.lineStarts;
-
-      Uri dotPackages = description.uri.resolve(".packages");
-      while (true) {
-        if (new File.fromUri(dotPackages).existsSync()) {
-          break;
-        }
-        // Stupid bailout.
-        if (dotPackages.pathSegments.length < Uri.base.pathSegments.length) {
-          break;
-        }
-        dotPackages = dotPackages.resolve("../.packages");
-      }
-
-      File dotPackagesFile = new File.fromUri(dotPackages);
-      if (dotPackagesFile.existsSync()) {
-        description.cache.packages = await loadPackagesFile(dotPackages);
-      }
-    }
-
-    if (description.cache.firstToken == null) {
-      return crash(description, StackTrace.current);
-    }
-
-    Parser parser = new Parser(description.listener);
-    parser.parseUnit(description.cache.firstToken);
-
-    if (description.listener.problems.isEmpty) {
-      return pass(description);
-    }
-    return fail(description, description.listener.problems.join("\n\n"));
-  }
-}
-
-class LintListener extends Listener {
-  List<String> problems = new List<String>();
-  LintTestDescription description;
-  Uri uri;
-
-  onProblem(int offset, int squigglyLength, String message) {
-    problems.add(description.getErrorMessage(offset, squigglyLength, message));
-  }
-}
-
-class ExplicitTypeLintListener extends LintListener {
-  LatestType _latestType;
-
-  @override
-  void beginVariablesDeclaration(
-      Token token, Token lateToken, Token varFinalOrConst) {
-    if (!_latestType.type) {
-      onProblem(
-          varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
-    }
-  }
-
-  @override
-  void handleType(Token beginToken, Token questionMark) {
-    _latestType = new LatestType(beginToken, true);
-  }
-
-  @override
-  void handleNoType(Token lastConsumed) {
-    _latestType = new LatestType(lastConsumed, false);
-  }
-
-  void endTopLevelFields(
-      Token staticToken,
-      Token covariantToken,
-      Token lateToken,
-      Token varFinalOrConst,
-      int count,
-      Token beginToken,
-      Token endToken) {
-    if (!_latestType.type) {
-      onProblem(
-          varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
-    }
-  }
-
-  void endClassFields(Token staticToken, Token covariantToken, Token lateToken,
-      Token varFinalOrConst, int count, Token beginToken, Token endToken) {
-    if (!_latestType.type) {
-      onProblem(
-          varFinalOrConst.offset, varFinalOrConst.length, "No explicit type.");
-    }
-  }
-}
-
-class LatestType {
-  final Token token;
-  bool type;
-
-  LatestType(this.token, this.type);
-}
-
-class ImportsTwiceLintListener extends LintListener {
-  Set<Uri> seenImports = new Set<Uri>();
-
-  void endImport(Token importKeyword, Token semicolon) {
-    Token importUriToken = importKeyword.next;
-    String importUri = importUriToken.lexeme;
-    if (importUri.startsWith("r")) {
-      importUri = importUri.substring(2, importUri.length - 1);
-    } else {
-      importUri = importUri.substring(1, importUri.length - 1);
-    }
-    Uri resolved = uri.resolve(importUri);
-    if (resolved.scheme == "package") {
-      if (description.cache.packages != null) {
-        resolved = description.cache.packages.resolve(resolved);
-      }
-    }
-    if (!seenImports.add(resolved)) {
-      onProblem(importUriToken.offset, importUriToken.lexeme.length,
-          "Uri '$resolved' already imported once.");
-    }
-  }
-}
-
-class ExportsLintListener extends LintListener {
-  void endExport(Token exportKeyword, Token semicolon) {
-    Token exportUriToken = exportKeyword.next;
-    String exportUri = exportUriToken.lexeme;
-    if (exportUri.startsWith("r")) {
-      exportUri = exportUri.substring(2, exportUri.length - 1);
-    } else {
-      exportUri = exportUri.substring(1, exportUri.length - 1);
-    }
-    Uri resolved = uri.resolve(exportUri);
-    if (resolved.scheme == "package") {
-      if (description.cache.packages != null) {
-        resolved = description.cache.packages.resolve(resolved);
-      }
-    }
-    onProblem(exportUriToken.offset, exportUriToken.lexeme.length,
-        "Exports disallowed internally.");
-  }
-}
diff --git a/pkg/front_end/test/lint_test.status b/pkg/front_end/test/lint_test.status
index fb582ff..f4d0a40 100644
--- a/pkg/front_end/test/lint_test.status
+++ b/pkg/front_end/test/lint_test.status
@@ -21,6 +21,7 @@
 src/api_prototype/constant_evaluator/Exports: Fail
 src/api_prototype/front_end/Exports: Fail
 src/api_prototype/incremental_kernel_generator/Exports: Fail
+src/fasta/fasta_codes/Exports: Fail
 src/fasta/kernel/constant_evaluator/ExplicitType: Pass
 src/fasta/kernel/kernel_api/Exports: Fail
 src/fasta/kernel/kernel_ast_api/Exports: Fail
diff --git a/pkg/front_end/test/messages_json_test.dart b/pkg/front_end/test/messages_json_test.dart
index 0756f80..f2a9cf2 100644
--- a/pkg/front_end/test/messages_json_test.dart
+++ b/pkg/front_end/test/messages_json_test.dart
@@ -2,14 +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.
 
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, getMessageUri;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:front_end/src/fasta/fasta_codes.dart'
     show DiagnosticMessageFromJson, FormattedMessage, LocatedMessage;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 /// Test that turning a message into json and back again retains the wanted
 /// information.
 main() {
diff --git a/pkg/front_end/test/old_dill_suite.dart b/pkg/front_end/test/old_dill_suite.dart
new file mode 100644
index 0000000..7e70850
--- /dev/null
+++ b/pkg/front_end/test/old_dill_suite.dart
@@ -0,0 +1,139 @@
+// 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:async' show Future;
+
+import 'dart:io';
+
+import 'package:kernel/binary/tag.dart' show Tag;
+
+import 'package:testing/testing.dart'
+    show ChainContext, Result, Step, TestDescription, Chain, runMe;
+
+Future<Null> main([List<String> arguments = const []]) async {
+  if (arguments.length == 1 && arguments[0] == "--generate") {
+    print("Should now generate a dill of dart2js.");
+    await generateDill();
+    return null;
+  } else if (arguments.length == 1 && arguments[0] == "--checkDill") {
+    await checkDill();
+    return null;
+  }
+  await runMe(arguments, createContext, configurationPath: "../testing.json");
+  await checkDill();
+}
+
+String get dartVm => Platform.resolvedExecutable;
+
+Uri generateOutputUri(int binaryVersion, int compileNumber) {
+  return Uri.base.resolve("pkg/front_end/testcases/old_dills/dills/"
+      "dart2js"
+      ".version.$binaryVersion"
+      ".compile.$compileNumber"
+      ".dill");
+}
+
+verifyNotUsingCheckedInDart() {
+  String vm = dartVm.replaceAll(r"\", "/");
+  if (vm.contains("tools/sdks/dart-sdk/bin/dart")) {
+    throw "Running with checked-in VM which is not supported";
+  }
+}
+
+Future<Null> checkDill() async {
+  Uri uri = generateOutputUri(Tag.BinaryFormatVersion, 1);
+  if (!new File.fromUri(uri).existsSync()) {
+    print("File $uri doesn't exist. Generate running script");
+    print("${Platform.script.toFilePath()} --generate");
+    exit(1);
+  }
+}
+
+Future<Null> generateDill() async {
+  Uri fastaCompile = Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart");
+  if (!new File.fromUri(fastaCompile).existsSync()) {
+    throw "compile.dart from fasta tools couldn't be found";
+  }
+
+  Uri dart2js = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+  if (!new File.fromUri(dart2js).existsSync()) {
+    throw "dart2js couldn't be found";
+  }
+
+  int compileNumber = 0;
+  Uri output;
+  do {
+    compileNumber++;
+    output = generateOutputUri(Tag.BinaryFormatVersion, compileNumber);
+  } while (new File.fromUri(output).existsSync());
+
+  ProcessResult result = await Process.run(
+      dartVm,
+      [
+        fastaCompile.toFilePath(),
+        "sdkroot:/pkg/compiler/bin/dart2js.dart",
+        "-o",
+        output.toFilePath(),
+        "--target=vm",
+        "--single-root-base=${Uri.base.toFilePath()}",
+        "--single-root-scheme=sdkroot",
+      ],
+      workingDirectory: Uri.base.toFilePath());
+  if (result.exitCode != 0) {
+    print("stdout: ${result.stdout}");
+    print("stderr: ${result.stderr}");
+    print("Exit code: ${result.exitCode}");
+    throw "Got exit code ${result.exitCode}";
+  } else {
+    print("File generated.");
+    print("");
+    print("You should now upload via CIPD:");
+    print("");
+    print("cipd create -name dart/cfe/dart2js_dills "
+        "-in pkg/front_end/testcases/old_dills/dills/ "
+        "-install-mode copy "
+        "-tag \"binary_version:${Tag.BinaryFormatVersion}\"");
+    print("");
+    print("And update the DEPS file to say "
+        "binary_version:${Tag.BinaryFormatVersion} "
+        "under /pkg/front_end/testcases/old_dills/dills");
+  }
+}
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context();
+}
+
+class Context extends ChainContext {
+  final List<Step> steps = const <Step>[
+    const RunDill(),
+  ];
+}
+
+class RunDill extends Step<TestDescription, TestDescription, Context> {
+  const RunDill();
+
+  String get name => "RunDill";
+
+  Future<Result<TestDescription>> run(
+      TestDescription description, Context context) async {
+    verifyNotUsingCheckedInDart();
+    ProcessResult result = await Process.run(
+        dartVm,
+        [
+          "--compile_all",
+          description.uri.toFilePath(),
+          "-h",
+        ],
+        workingDirectory: Uri.base.toFilePath());
+    print("stdout: ${result.stdout}");
+    print("stderr: ${result.stderr}");
+    print("Exit code: ${result.exitCode}");
+    if (result.exitCode != 0) {
+      return fail(description, "Got exit code ${result.exitCode}");
+    }
+    return pass(description);
+  }
+}
diff --git a/pkg/front_end/test/old_dill_test.dart b/pkg/front_end/test/old_dill_test.dart
deleted file mode 100644
index f8b22f8..0000000
--- a/pkg/front_end/test/old_dill_test.dart
+++ /dev/null
@@ -1,128 +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:async' show Future;
-
-import 'dart:io';
-
-import 'package:kernel/binary/tag.dart' show Tag;
-
-import 'package:testing/testing.dart'
-    show ChainContext, Result, Step, TestDescription, Chain, runMe;
-
-Future<Null> main([List<String> arguments = const []]) async {
-  if (arguments.length == 1 && arguments[0] == "--generate") {
-    print("Should now generate a dill of dart2js.");
-    await generateDill();
-    return null;
-  } else if (arguments.length == 1 && arguments[0] == "--checkDill") {
-    await checkDill();
-    return null;
-  }
-  await runMe(arguments, createContext, configurationPath: "../testing.json");
-  await checkDill();
-}
-
-String get dartVm => Platform.resolvedExecutable;
-
-Uri generateOutputUri(int binaryVersion, int compileNumber) {
-  return Uri.base.resolve("pkg/front_end/testcases/old_dills/"
-      "dart2js"
-      ".version.$binaryVersion"
-      ".compile.$compileNumber"
-      ".dill");
-}
-
-verifyNotUsingCheckedInDart() {
-  String vm = dartVm.replaceAll(r"\", "/");
-  if (vm.contains("tools/sdks/dart-sdk/bin/dart")) {
-    throw "Running with checked-in VM which is not supported";
-  }
-}
-
-Future<Null> checkDill() async {
-  Uri uri = generateOutputUri(Tag.BinaryFormatVersion, 1);
-  if (!new File.fromUri(uri).existsSync()) {
-    print("File $uri doesn't exist. Generate running script");
-    print("${Platform.script.toFilePath()} --generate");
-    exit(1);
-  }
-}
-
-Future<Null> generateDill() async {
-  Uri fastaCompile = Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart");
-  if (!new File.fromUri(fastaCompile).existsSync()) {
-    throw "compile.dart from fasta tools couldn't be found";
-  }
-
-  Uri dart2js = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
-  if (!new File.fromUri(dart2js).existsSync()) {
-    throw "dart2js couldn't be found";
-  }
-
-  int compileNumber = 0;
-  Uri output;
-  do {
-    compileNumber++;
-    output = generateOutputUri(Tag.BinaryFormatVersion, compileNumber);
-  } while (new File.fromUri(output).existsSync());
-
-  ProcessResult result = await Process.run(
-      dartVm,
-      [
-        fastaCompile.toFilePath(),
-        "sdkroot:/pkg/compiler/bin/dart2js.dart",
-        "-o",
-        output.toFilePath(),
-        "--target=vm",
-        "--single-root-base=${Uri.base.toFilePath()}",
-        "--single-root-scheme=sdkroot",
-      ],
-      workingDirectory: Uri.base.toFilePath());
-  if (result.exitCode != 0) {
-    print("stdout: ${result.stdout}");
-    print("stderr: ${result.stderr}");
-    print("Exit code: ${result.exitCode}");
-    throw "Got exit code ${result.exitCode}";
-  } else {
-    print("File generated.");
-  }
-}
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  return new Context();
-}
-
-class Context extends ChainContext {
-  final List<Step> steps = const <Step>[
-    const RunDill(),
-  ];
-}
-
-class RunDill extends Step<TestDescription, TestDescription, Context> {
-  const RunDill();
-
-  String get name => "RunDill";
-
-  Future<Result<TestDescription>> run(
-      TestDescription description, Context context) async {
-    verifyNotUsingCheckedInDart();
-    ProcessResult result = await Process.run(
-        dartVm,
-        [
-          "--compile_all",
-          description.uri.toFilePath(),
-          "-h",
-        ],
-        workingDirectory: Uri.base.toFilePath());
-    print("stdout: ${result.stdout}");
-    print("stderr: ${result.stderr}");
-    print("Exit code: ${result.exitCode}");
-    if (result.exitCode != 0) {
-      return fail(description, "Got exit code ${result.exitCode}");
-    }
-    return pass(description);
-  }
-}
diff --git a/pkg/front_end/test/packages_format_error_test.dart b/pkg/front_end/test/packages_format_error_test.dart
index 0962a74..14f97c8 100644
--- a/pkg/front_end/test/packages_format_error_test.dart
+++ b/pkg/front_end/test/packages_format_error_test.dart
@@ -2,6 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, getMessageCodeObject;
+
 import 'package:async_helper/async_helper.dart' show asyncTest;
 
 import 'package:expect/expect.dart' show Expect;
@@ -9,9 +12,6 @@
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions;
 
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, getMessageCodeObject;
-
 import 'package:front_end/src/api_prototype/memory_file_system.dart'
     show MemoryFileSystem;
 
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
new file mode 100644
index 0000000..5eb2b73
--- /dev/null
+++ b/pkg/front_end/test/parser_suite.dart
@@ -0,0 +1,322 @@
+// 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:async' show Future;
+
+import 'dart:convert' show jsonDecode;
+
+import 'dart:io' show File;
+
+import 'dart:typed_data' show Uint8List;
+
+import 'package:front_end/src/fasta/command_line_reporting.dart'
+    as command_line_reporting;
+
+import 'package:front_end/src/fasta/messages.dart' show Message;
+
+import 'package:_fe_analyzer_shared/src/parser/parser.dart'
+    show Parser, lengthOfSpan;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show ErrorToken, ScannerConfiguration, Token, Utf8BytesScanner;
+
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
+    show Utf8BytesScanner;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
+import 'package:front_end/src/fasta/source/stack_listener.dart'
+    show offsetForToken;
+
+import 'package:kernel/ast.dart';
+
+import 'package:testing/testing.dart'
+    show
+        Chain,
+        ChainContext,
+        ExpectationSet,
+        Result,
+        Step,
+        TestDescription,
+        runMe;
+
+import 'utils/kernel_chain.dart' show MatchContext;
+
+import 'parser_test_listener.dart' show ParserTestListener;
+
+import 'parser_test_parser.dart' show TestParser;
+
+const String EXPECTATIONS = '''
+[
+  {
+    "name": "ExpectationFileMismatch",
+    "group": "Fail"
+  },
+  {
+    "name": "ExpectationFileMissing",
+    "group": "Fail"
+  }
+]
+''';
+
+main([List<String> arguments = const []]) =>
+    runMe(arguments, createContext, configurationPath: "../testing.json");
+
+Future<Context> createContext(
+    Chain suite, Map<String, String> environment) async {
+  return new Context(suite.name, environment["updateExpectations"] == "true",
+      environment["trace"] == "true");
+}
+
+ScannerConfiguration scannerConfiguration = new ScannerConfiguration(
+    enableTripleShift: true,
+    enableExtensionMethods: true,
+    enableNonNullable: true);
+
+class Context extends ChainContext with MatchContext {
+  final bool updateExpectations;
+  final bool addTrace;
+  final String suiteName;
+
+  Context(this.suiteName, this.updateExpectations, this.addTrace);
+
+  final List<Step> steps = const <Step>[
+    const TokenStep(true, ".scanner.expect"),
+    const TokenStep(false, ".parser.expect"),
+    const ListenerStep(),
+    const IntertwinedStep(),
+  ];
+
+  final ExpectationSet expectationSet =
+      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
+}
+
+class ListenerStep extends Step<TestDescription, TestDescription, Context> {
+  const ListenerStep();
+
+  String get name => "listener";
+
+  Future<Result<TestDescription>> run(
+      TestDescription description, Context context) {
+    List<int> lineStarts = new List<int>();
+    Token firstToken = scanUri(description.uri, lineStarts: lineStarts);
+
+    if (firstToken == null) {
+      return Future.value(crash(description, StackTrace.current));
+    }
+
+    File f = new File.fromUri(description.uri);
+    List<int> rawBytes = f.readAsBytesSync();
+    Source source =
+        new Source(lineStarts, rawBytes, description.uri, description.uri);
+
+    String shortName = "${context.suiteName}/${description.shortName}";
+
+    ParserTestListenerWithMessageFormatting parserTestListener =
+        new ParserTestListenerWithMessageFormatting(
+            context.addTrace, source, shortName);
+    Parser parser = new Parser(parserTestListener);
+    parser.parseUnit(firstToken);
+
+    String errors = "";
+    if (parserTestListener.errors.isNotEmpty) {
+      errors = "Problems reported:\n\n"
+          "${parserTestListener.errors.join("\n\n")}\n\n";
+    }
+
+    return context.match<TestDescription>(".expect",
+        "${errors}${parserTestListener.sb}", description.uri, description);
+  }
+}
+
+class IntertwinedStep extends Step<TestDescription, TestDescription, Context> {
+  const IntertwinedStep();
+
+  String get name => "intertwined";
+
+  Future<Result<TestDescription>> run(
+      TestDescription description, Context context) {
+    Token firstToken = scanUri(description.uri);
+
+    if (firstToken == null) {
+      return Future.value(crash(description, StackTrace.current));
+    }
+
+    ParserTestListenerForIntertwined parserTestListener =
+        new ParserTestListenerForIntertwined(context.addTrace);
+    TestParser parser = new TestParser(parserTestListener, context.addTrace);
+    parserTestListener.parser = parser;
+    parser.sb = parserTestListener.sb;
+    parser.parseUnit(firstToken);
+
+    return context.match<TestDescription>(
+        ".intertwined.expect", "${parser.sb}", description.uri, description);
+  }
+}
+
+class TokenStep extends Step<TestDescription, TestDescription, Context> {
+  final bool onlyScanner;
+  final String suffix;
+
+  const TokenStep(this.onlyScanner, this.suffix);
+
+  String get name => "token";
+
+  Future<Result<TestDescription>> run(
+      TestDescription description, Context context) {
+    List<int> lineStarts = new List<int>();
+    Token firstToken = scanUri(description.uri, lineStarts: lineStarts);
+
+    if (firstToken == null) {
+      return Future.value(crash(description, StackTrace.current));
+    }
+
+    StringBuffer beforeParser = tokenStreamToString(firstToken, lineStarts);
+    StringBuffer beforeParserWithTypes =
+        tokenStreamToString(firstToken, lineStarts, addTypes: true);
+    if (onlyScanner) {
+      return context.match<TestDescription>(
+          suffix,
+          "${beforeParser}\n\n${beforeParserWithTypes}",
+          description.uri,
+          description);
+    }
+
+    ParserTestListener parserTestListener =
+        new ParserTestListener(context.addTrace);
+    Parser parser = new Parser(parserTestListener);
+    bool parserCrashed = false;
+    dynamic parserCrashedE;
+    StackTrace parserCrashedSt;
+    try {
+      parser.parseUnit(firstToken);
+    } catch (e, st) {
+      parserCrashed = true;
+      parserCrashedE = e;
+      parserCrashedSt = st;
+    }
+
+    StringBuffer afterParser = tokenStreamToString(firstToken, lineStarts);
+    StringBuffer afterParserWithTypes =
+        tokenStreamToString(firstToken, lineStarts, addTypes: true);
+
+    bool rewritten = beforeParser.toString() != afterParser.toString();
+    String rewrittenString =
+        rewritten ? "NOTICE: Stream was rewritten by parser!\n\n" : "";
+
+    Future<Result<TestDescription>> result = context.match<TestDescription>(
+        suffix,
+        "${rewrittenString}${afterParser}\n\n${afterParserWithTypes}",
+        description.uri,
+        description);
+    return result.then((result) {
+      if (parserCrashed) {
+        return crash("Parser crashed: $parserCrashedE", parserCrashedSt);
+      } else {
+        return result;
+      }
+    });
+  }
+
+  StringBuffer tokenStreamToString(Token firstToken, List<int> lineStarts,
+      {bool addTypes: false}) {
+    StringBuffer sb = new StringBuffer();
+    Token token = firstToken;
+    bool printed = false;
+    int endOfLast = -1;
+    int lineStartsIteratorLine = 1;
+    Iterator<int> lineStartsIterator = lineStarts.iterator;
+    lineStartsIterator.moveNext();
+    lineStartsIterator.moveNext();
+    lineStartsIteratorLine++;
+    while (token != null) {
+      int prevLine = lineStartsIteratorLine;
+      while (token.offset >= lineStartsIterator.current &&
+          lineStartsIterator.moveNext()) {
+        lineStartsIteratorLine++;
+      }
+      if (printed &&
+          (token.offset > endOfLast || prevLine < lineStartsIteratorLine)) {
+        if (prevLine < lineStartsIteratorLine) {
+          for (int i = prevLine; i < lineStartsIteratorLine; i++) {
+            sb.write("\n");
+          }
+        } else {
+          sb.write(" ");
+        }
+      }
+      if (token is! ErrorToken) {
+        sb.write(token.lexeme);
+      }
+      if (addTypes) {
+        sb.write("[${token.runtimeType}]");
+      }
+      printed = true;
+      endOfLast = token.end;
+      if (token == token.next) break;
+      token = token.next;
+    }
+    return sb;
+  }
+}
+
+Token scanUri(Uri uri, {List<int> lineStarts}) {
+  File f = new File.fromUri(uri);
+  List<int> rawBytes = f.readAsBytesSync();
+
+  Uint8List bytes = new Uint8List(rawBytes.length + 1);
+  bytes.setRange(0, rawBytes.length, rawBytes);
+
+  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
+      includeComments: true, configuration: scannerConfiguration);
+  Token firstToken = scanner.tokenize();
+  if (lineStarts != null) {
+    lineStarts.addAll(scanner.lineStarts);
+  }
+  return firstToken;
+}
+
+class ParserTestListenerWithMessageFormatting extends ParserTestListener {
+  final Source source;
+  final String shortName;
+  final List<String> errors = new List<String>();
+
+  ParserTestListenerWithMessageFormatting(
+      bool trace, this.source, this.shortName)
+      : super(trace);
+
+  void handleRecoverableError(
+      Message message, Token startToken, Token endToken) {
+    if (source != null) {
+      Location location =
+          source.getLocation(source.fileUri, offsetForToken(startToken));
+      int length = lengthOfSpan(startToken, endToken);
+      if (length <= 0) length = 1;
+      errors.add(command_line_reporting.formatErrorMessage(
+          source.getTextLine(location.line),
+          location,
+          length,
+          shortName,
+          message.message));
+    } else {
+      errors.add(message.message);
+    }
+
+    super.handleRecoverableError(message, startToken, endToken);
+  }
+}
+
+class ParserTestListenerForIntertwined
+    extends ParserTestListenerWithMessageFormatting {
+  TestParser parser;
+
+  ParserTestListenerForIntertwined(bool trace) : super(trace, null, null);
+
+  void doPrint(String s) {
+    int prevIndent = super.indent;
+    super.indent = parser.indent;
+    super.doPrint("listener: " + s);
+    super.indent = prevIndent;
+  }
+}
diff --git a/pkg/front_end/test/parser_test.dart b/pkg/front_end/test/parser_test.dart
deleted file mode 100644
index 420d9fd..0000000
--- a/pkg/front_end/test/parser_test.dart
+++ /dev/null
@@ -1,154 +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:async' show Future;
-
-import 'dart:convert' show jsonDecode;
-
-import 'dart:io' show File;
-
-import 'dart:typed_data' show Uint8List;
-
-import 'package:front_end/src/fasta/parser.dart' show Parser;
-import 'package:front_end/src/fasta/scanner.dart';
-
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
-    show Utf8BytesScanner;
-
-import 'package:front_end/src/scanner/token.dart' show Token;
-
-import 'package:testing/testing.dart'
-    show
-        Chain,
-        ChainContext,
-        ExpectationSet,
-        Result,
-        Step,
-        TestDescription,
-        runMe;
-
-import 'utils/kernel_chain.dart' show MatchContext;
-
-import 'parser_test_listener.dart' show ParserTestListener;
-
-import 'parser_test_parser.dart' show TestParser;
-
-const String EXPECTATIONS = '''
-[
-  {
-    "name": "ExpectationFileMismatch",
-    "group": "Fail"
-  },
-  {
-    "name": "ExpectationFileMissing",
-    "group": "Fail"
-  }
-]
-''';
-
-main([List<String> arguments = const []]) =>
-    runMe(arguments, createContext, configurationPath: "../testing.json");
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  return new Context(environment["updateExpectations"] == "true",
-      environment["trace"] == "true");
-}
-
-ScannerConfiguration scannerConfiguration = new ScannerConfiguration(
-    enableTripleShift: true,
-    enableExtensionMethods: true,
-    enableNonNullable: true);
-
-class Context extends ChainContext with MatchContext {
-  final bool updateExpectations;
-  final bool addTrace;
-
-  Context(this.updateExpectations, this.addTrace);
-
-  final List<Step> steps = const <Step>[
-    const ListenerStep(),
-    const IntertwinedStep(),
-  ];
-
-  final ExpectationSet expectationSet =
-      new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
-}
-
-class ListenerStep extends Step<TestDescription, TestDescription, Context> {
-  const ListenerStep();
-
-  String get name => "listener";
-
-  Future<Result<TestDescription>> run(
-      TestDescription description, Context context) async {
-    File f = new File.fromUri(description.uri);
-    List<int> rawBytes = f.readAsBytesSync();
-
-    Uint8List bytes = new Uint8List(rawBytes.length + 1);
-    bytes.setRange(0, rawBytes.length, rawBytes);
-
-    Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
-        includeComments: true, configuration: scannerConfiguration);
-    Token firstToken = scanner.tokenize();
-
-    if (firstToken == null) {
-      return crash(description, StackTrace.current);
-    }
-
-    ParserTestListener parserTestListener =
-        new ParserTestListener(context.addTrace);
-    Parser parser = new Parser(parserTestListener);
-    parser.parseUnit(firstToken);
-
-    return context.match<TestDescription>(
-        ".expect", "${parserTestListener.sb}", description.uri, description);
-  }
-}
-
-class IntertwinedStep extends Step<TestDescription, TestDescription, Context> {
-  const IntertwinedStep();
-
-  String get name => "intertwined";
-
-  Future<Result<TestDescription>> run(
-      TestDescription description, Context context) async {
-    File f = new File.fromUri(description.uri);
-    List<int> rawBytes = f.readAsBytesSync();
-
-    Uint8List bytes = new Uint8List(rawBytes.length + 1);
-    bytes.setRange(0, rawBytes.length, rawBytes);
-
-    Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
-        includeComments: true, configuration: scannerConfiguration);
-    Token firstToken = scanner.tokenize();
-
-    if (firstToken == null) {
-      return crash(description, StackTrace.current);
-    }
-
-    ParserTestListener2 parserTestListener =
-        new ParserTestListener2(context.addTrace);
-    TestParser parser = new TestParser(parserTestListener, context.addTrace);
-    parserTestListener.parser = parser;
-    parser.sb = parserTestListener.sb;
-    parser.parseUnit(firstToken);
-
-    return context.match<TestDescription>(
-        ".intertwined.expect", "${parser.sb}", description.uri, description);
-  }
-}
-
-class ParserTestListener2 extends ParserTestListener {
-  TestParser parser;
-
-  ParserTestListener2(bool trace) : super(trace);
-
-  void doPrint(String s) {
-    int prevIndent = super.indent;
-    super.indent = parser.indent;
-    super.doPrint("listener: " + s);
-    super.indent = prevIndent;
-  }
-}
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index e3e83de..b7ea368 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -2,15 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import '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';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart';
+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';
 import 'package:front_end/src/fasta/messages.dart';
-import 'package:front_end/src/fasta/parser/assert.dart';
-import 'package:front_end/src/fasta/parser/declaration_kind.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/identifier_context.dart';
-import 'package:front_end/src/fasta/parser/listener.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/scanner/error_token.dart';
-import 'package:front_end/src/scanner/token.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
 
@@ -82,14 +83,15 @@
         '$errorCode)');
   }
 
-  void beginBlock(Token token) {
-    doPrint('beginBlock(' '$token)');
+  void beginBlock(Token token, BlockKind blockKind) {
+    doPrint('beginBlock(' '$token, ' '$blockKind)');
     indent++;
   }
 
-  void endBlock(int count, Token beginToken, Token endToken) {
+  void endBlock(
+      int count, Token beginToken, Token endToken, BlockKind blockKind) {
     indent--;
-    doPrint('endBlock(' '$count, ' '$beginToken, ' '$endToken)');
+    doPrint('endBlock(' '$count, ' '$beginToken, ' '$endToken, ' '$blockKind)');
   }
 
   void handleInvalidTopLevelBlock(Token token) {
@@ -448,12 +450,13 @@
     doPrint('handleForInitializerEmptyStatement(' '$token)');
   }
 
-  void handleForInitializerExpressionStatement(Token token) {
-    doPrint('handleForInitializerExpressionStatement(' '$token)');
+  void handleForInitializerExpressionStatement(Token token, bool forIn) {
+    doPrint('handleForInitializerExpressionStatement(' '$token, ' '$forIn)');
   }
 
-  void handleForInitializerLocalVariableDeclaration(Token token) {
-    doPrint('handleForInitializerLocalVariableDeclaration(' '$token)');
+  void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
+    doPrint(
+        'handleForInitializerLocalVariableDeclaration(' '$token, ' '$forIn)');
   }
 
   void beginForStatement(Token token) {
diff --git a/pkg/front_end/test/parser_test_listener_creator.dart b/pkg/front_end/test/parser_test_listener_creator.dart
index 5afed41..4042166 100644
--- a/pkg/front_end/test/parser_test_listener_creator.dart
+++ b/pkg/front_end/test/parser_test_listener_creator.dart
@@ -5,12 +5,12 @@
 import 'dart:io';
 import 'dart:typed_data';
 
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/listener.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart';
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart';
+import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
 StringSink out;
@@ -37,15 +37,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import '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';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart';
+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';
 import 'package:front_end/src/fasta/messages.dart';
-import 'package:front_end/src/fasta/parser/assert.dart';
-import 'package:front_end/src/fasta/parser/declaration_kind.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/identifier_context.dart';
-import 'package:front_end/src/fasta/parser/listener.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/scanner/error_token.dart';
-import 'package:front_end/src/scanner/token.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_listener_creator.dart'
 
@@ -82,7 +83,12 @@
   out.writeln("}");
 
   if (out is StringBuffer) {
-    stdout.write(new DartFormatter().format("$out"));
+    String text = new DartFormatter().format("$out");
+    if (args.isNotEmpty) {
+      new File(args.first).writeAsStringSync(text);
+    } else {
+      stdout.write(text);
+    }
   }
 }
 
diff --git a/pkg/front_end/test/parser_test_parser.dart b/pkg/front_end/test/parser_test_parser.dart
index f5b5aae..4615ee2 100644
--- a/pkg/front_end/test/parser_test_parser.dart
+++ b/pkg/front_end/test/parser_test_parser.dart
@@ -2,19 +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:front_end/src/fasta/parser/listener.dart' show Listener;
-import 'package:front_end/src/fasta/parser/parser.dart' show Parser;
-import 'package:front_end/src/scanner/token.dart';
+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';
+import 'package:_fe_analyzer_shared/src/parser/directive_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener;
+import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
+import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart';
+import 'package:_fe_analyzer_shared/src/parser/type_info.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/parser/assert.dart';
-import 'package:front_end/src/fasta/parser/declaration_kind.dart';
-import 'package:front_end/src/fasta/parser/directive_context.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/identifier_context.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/parser/token_stream_rewriter.dart';
-import 'package:front_end/src/fasta/parser/type_info.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_parser_creator.dart'
 
@@ -797,11 +798,13 @@
     return result;
   }
 
-  Token ensureBlock(Token token,
-      Template<Message Function(Token token)> template, String blockKind) {
-    doPrint('ensureBlock(' '$token, ' '$template, ' '$blockKind)');
+  Token ensureBlock(
+      Token token,
+      Template<Message Function(Token token)> template,
+      String missingBlockName) {
+    doPrint('ensureBlock(' '$token, ' '$template, ' '$missingBlockName)');
     indent++;
-    var result = super.ensureBlock(token, template, blockKind);
+    var result = super.ensureBlock(token, template, missingBlockName);
     indent--;
     return result;
   }
@@ -1705,7 +1708,7 @@
     return result;
   }
 
-  Token parseBlock(Token token, String blockKind) {
+  Token parseBlock(Token token, BlockKind blockKind) {
     doPrint('parseBlock(' '$token, ' '$blockKind)');
     indent++;
     var result = super.parseBlock(token, blockKind);
@@ -1864,7 +1867,8 @@
       Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
-      DeclarationKind kind) {
+      DeclarationKind kind,
+      String enclosingDeclarationName) {
     doPrint('parseInvalidOperatorDeclaration('
         '$beforeStart, '
         '$externalToken, '
@@ -1873,7 +1877,8 @@
         '$lateToken, '
         '$varFinalOrConst, '
         '$beforeType, '
-        '$kind)');
+        '$kind, '
+        '$enclosingDeclarationName)');
     indent++;
     var result = super.parseInvalidOperatorDeclaration(
         beforeStart,
@@ -1883,7 +1888,8 @@
         lateToken,
         varFinalOrConst,
         beforeType,
-        kind);
+        kind,
+        enclosingDeclarationName);
     indent--;
     return result;
   }
diff --git a/pkg/front_end/test/parser_test_parser_creator.dart b/pkg/front_end/test/parser_test_parser_creator.dart
index f4e4ebe..8e9121c 100644
--- a/pkg/front_end/test/parser_test_parser_creator.dart
+++ b/pkg/front_end/test/parser_test_parser_creator.dart
@@ -5,12 +5,12 @@
 import 'dart:io';
 import 'dart:typed_data';
 
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/listener.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart';
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart';
+import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
 StringSink out;
@@ -37,19 +37,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:front_end/src/fasta/parser/listener.dart' show Listener;
-import 'package:front_end/src/fasta/parser/parser.dart' show Parser;
-import 'package:front_end/src/scanner/token.dart';
+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';
+import 'package:_fe_analyzer_shared/src/parser/directive_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
+import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener;
+import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
+import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser;
+import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart';
+import 'package:_fe_analyzer_shared/src/parser/type_info.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/parser/assert.dart';
-import 'package:front_end/src/fasta/parser/declaration_kind.dart';
-import 'package:front_end/src/fasta/parser/directive_context.dart';
-import 'package:front_end/src/fasta/parser/formal_parameter_kind.dart';
-import 'package:front_end/src/fasta/parser/identifier_context.dart';
-import 'package:front_end/src/fasta/parser/member_kind.dart';
-import 'package:front_end/src/fasta/parser/token_stream_rewriter.dart';
-import 'package:front_end/src/fasta/parser/type_info.dart';
 
 // THIS FILE IS AUTO GENERATED BY 'test/parser_test_parser_creator.dart'
 
@@ -88,7 +89,12 @@
   out.writeln("}");
 
   if (out is StringBuffer) {
-    stdout.write(new DartFormatter().format("$out"));
+    String text = new DartFormatter().format("$out");
+    if (args.isNotEmpty) {
+      new File(args.first).writeAsStringSync(text);
+    } else {
+      stdout.write(text);
+    }
   }
 }
 
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index d8759ea..68b33fd 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -4,14 +4,14 @@
 
 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'
+    show DataInterpreter, runTests;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:front_end/src/fasta/builder/builder.dart';
 import 'package:front_end/src/fasta/builder/class_builder.dart';
 
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
 import 'package:front_end/src/testing/features.dart';
-import 'package:front_end/src/testing/id_testing.dart'
-    show DataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_helper.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/precedence_info_test.dart b/pkg/front_end/test/precedence_info_test.dart
index 80fd8a4..61244aa 100644
--- a/pkg/front_end/test/precedence_info_test.dart
+++ b/pkg/front_end/test/precedence_info_test.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/scanner/abstract_scanner.dart'
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner;
-import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
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 cc738f1..8b9c6d3 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
@@ -10,7 +10,7 @@
 
 import 'binary_md_dill_reader.dart' show BinaryMdDillReader;
 
-import 'incremental_load_from_dill_test.dart'
+import 'incremental_load_from_dill_suite.dart'
     show getOptions, normalCompileToBytes;
 
 import 'utils/io_utils.dart' show computeRepoDir;
diff --git a/pkg/front_end/test/relativize_test.dart b/pkg/front_end/test/relativize_test.dart
index d7b92a9..bc8a132 100644
--- a/pkg/front_end/test/relativize_test.dart
+++ b/pkg/front_end/test/relativize_test.dart
@@ -2,8 +2,8 @@
 // for 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/util/relativize.dart';
 import 'package:test/test.dart';
-import 'package:front_end/src/fasta/util/relativize.dart';
 
 void main() {
   test('test relativeUri', () {
diff --git a/pkg/front_end/test/resolve_input_uri_test.dart b/pkg/front_end/test/resolve_input_uri_test.dart
index 1084424..f8eda33 100644
--- a/pkg/front_end/test/resolve_input_uri_test.dart
+++ b/pkg/front_end/test/resolve_input_uri_test.dart
@@ -2,8 +2,8 @@
 // for 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/util/relativize.dart';
 import 'package:expect/expect.dart' show Expect;
-
 import 'package:front_end/src/fasta/resolve_input_uri.dart';
 
 test() {
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index c9ae5b2..10a6dc6 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -1,18 +1,21 @@
 // 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 'dart:convert';
 
+import 'package:_fe_analyzer_shared/src/scanner/error_token.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    as usedForFuzzTesting;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/string_scanner.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart' as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
+    as fasta;
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/fasta/scanner.dart' as usedForFuzzTesting;
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/string_scanner.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/token_constants.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart' as fasta;
-import 'package:front_end/src/scanner/errors.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index c05d86b..a523793 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/scanner.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/token.dart' as fasta;
-import 'package:front_end/src/fasta/scanner/error_token.dart' as fasta;
-import 'package:front_end/src/scanner/token.dart' as analyzer;
-import 'package:front_end/src/scanner/errors.dart'
+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;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' as analyzer;
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
     show ScannerErrorCode, translateErrorToken;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index bb052b5..6f7156a 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -2,12 +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:front_end/src/base/errors.dart';
-import 'package:front_end/src/fasta/scanner/abstract_scanner.dart'
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
     show AbstractScanner, ScannerConfiguration;
-import 'package:front_end/src/scanner/errors.dart';
-import 'package:front_end/src/scanner/reader.dart';
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/errors.dart';
+import 'package:_fe_analyzer_shared/src/scanner/reader.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/front_end/test/severity_index_test.dart b/pkg/front_end/test/severity_index_test.dart
index fd7964b..2077e6d 100644
--- a/pkg/front_end/test/severity_index_test.dart
+++ b/pkg/front_end/test/severity_index_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.
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
 /// Test that Severity has the expected indexes. Note that this is important
 /// and shouldn't be changed lightly because we use it in serialization!
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 8b4cd40..56504e3 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -246,6 +246,7 @@
 doc
 docs
 dom
+dont
 doubles
 downcasts
 downloaded
@@ -646,6 +647,8 @@
 ranges
 ranked
 ratio
+rb
+rc
 re
 reach
 react
@@ -839,6 +842,7 @@
 tester
 tex
 th
+thought
 ti
 tick
 ticker
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 188bf4d..82ad053 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -29,6 +29,7 @@
 accepts
 access
 accessed
+accesses
 accessible
 accessing
 accessor
@@ -45,6 +46,7 @@
 act
 acting
 action
+actions
 active
 actual
 actually
@@ -97,6 +99,7 @@
 alpha
 already
 also
+alternate
 alternating
 alternative
 alternatively
@@ -174,6 +177,7 @@
 asks
 aspects
 assert
+asserted
 assertion
 assertions
 asserts
@@ -183,6 +187,7 @@
 assigned
 assignment
 assignments
+assistance
 associate
 associated
 associates
@@ -193,6 +198,7 @@
 assumes
 assuming
 assumption
+asymmetric
 async
 asynchronous
 at
@@ -300,6 +306,7 @@
 breaking
 breakpoint
 breaks
+briefly
 brittle
 broken
 browser
@@ -358,8 +365,10 @@
 care
 careful
 cares
+carries
 carry
 cascade
+cascaded
 cascading
 case
 cases
@@ -368,6 +377,7 @@
 catches
 categories
 category
+caveats
 caught
 cause
 caused
@@ -376,6 +386,7 @@
 certain
 chain
 chained
+chains
 chance
 chances
 change
@@ -585,6 +596,7 @@
 contravariance
 contravariant
 contravariantly
+contributes
 control
 controller
 convenience
@@ -597,6 +609,7 @@
 converting
 converts
 cookie
+cope
 copied
 copier
 copies
@@ -617,6 +630,7 @@
 couldn't
 count
 counter
+counterpart
 counting
 counts
 couple
@@ -639,6 +653,7 @@
 curly
 current
 currently
+curried
 custom
 customize
 cyan
@@ -650,6 +665,7 @@
 dartdevc
 data
 date
+de
 dead
 deal
 dealing
@@ -658,8 +674,10 @@
 debugging
 decide
 decided
+decides
 deciding
 decimal
+decision
 declarable
 declarated
 declaration
@@ -696,6 +714,7 @@
 definitions
 degenerate
 degrade
+delay
 delayed
 delegate
 delegates
@@ -707,6 +726,10 @@
 delimiter
 delimiters
 delta
+demoted
+demoting
+demotion
+demotions
 denote
 denoted
 denotes
@@ -720,6 +743,7 @@
 depends
 deprecate
 deprecated
+depromotes
 depth
 derivation
 derive
@@ -785,6 +809,7 @@
 disabling
 disambiguate
 disambiguated
+disappear
 discard
 discarded
 discarding
@@ -859,6 +884,7 @@
 editor
 effect
 effective
+effectively
 efficiency
 effort
 either
@@ -905,6 +931,7 @@
 enhancing
 enough
 ensure
+ensured
 ensures
 ensuring
 entails
@@ -938,6 +965,7 @@
 escaping
 especially
 essence
+essentially
 essentials
 etc
 evaluate
@@ -982,6 +1010,7 @@
 exists
 exit
 exited
+exits
 expand
 expanding
 expect
@@ -1008,6 +1037,7 @@
 exporting
 exports
 exposed
+exposes
 expression
 expressions
 extend
@@ -1187,6 +1217,7 @@
 goes
 going
 good
+gone
 got
 gotten
 governed
@@ -1198,6 +1229,7 @@
 greatly
 green
 grounded
+grounds
 group
 grouping
 groups
@@ -1206,6 +1238,7 @@
 guaranteed
 guarantees
 guard
+guarding
 guards
 guess
 guide
@@ -1262,6 +1295,7 @@
 holds
 hood
 hooks
+horribly
 host
 hostnames
 how
@@ -1278,6 +1312,7 @@
 identify
 identity
 if
+ignorant
 ignore
 ignored
 ignores
@@ -1418,6 +1453,7 @@
 interceptors
 interest
 interesting
+interests
 interface
 interfaces
 interferes
@@ -1454,6 +1490,7 @@
 invert
 inverted
 investigate
+invisible
 invocation
 invocation's
 invocations
@@ -1478,6 +1515,7 @@
 items
 iterable
 iterate
+iterates
 iteration
 iterator
 its
@@ -1831,6 +1869,7 @@
 object
 object's
 objects
+oblivious
 observation
 observed
 obtain
@@ -1843,6 +1882,7 @@
 occurring
 occurs
 odd
+odds
 of
 off
 offset
@@ -1960,6 +2000,7 @@
 parts
 pass
 passed
+passes
 passing
 past
 pasted
@@ -1973,6 +2014,7 @@
 pending
 percent
 percolate
+percolates
 perfect
 perform
 performance
@@ -1992,6 +2034,7 @@
 physical
 pick
 picked
+piece
 pipeline
 piping
 pivot
@@ -2017,6 +2060,7 @@
 pop
 popping
 pops
+populate
 populated
 port
 portion
@@ -2036,6 +2080,7 @@
 potentially
 practice
 practices
+preamble
 precede
 preceded
 precedence
@@ -2047,6 +2092,7 @@
 precision
 preclude
 precondition
+preconditions
 predefined
 predicate
 preemptively
@@ -2188,6 +2234,7 @@
 realigned
 realized
 really
+reassign
 reason
 reasonable
 reasoning
@@ -2223,6 +2270,7 @@
 reduce
 reduced
 reduces
+redundancy
 redundant
 refactor
 refer
@@ -2335,6 +2383,7 @@
 restricted
 restrictive
 result
+resulted
 resulting
 results
 resume
@@ -2346,6 +2395,7 @@
 retrieve
 retrieved
 retrieves
+retry
 return
 returned
 returning
@@ -2370,6 +2420,7 @@
 rightfully
 rights
 rise
+roles
 roll
 root
 roots
@@ -2404,6 +2455,7 @@
 scanner's
 scanners
 scanning
+scenario
 schema
 scheme
 schemes
@@ -2420,6 +2472,7 @@
 second
 section
 see
+seeing
 seem
 seems
 seen
@@ -2477,7 +2530,12 @@
 shift
 short
 shortcut
+shorted
 shorten
+shortened
+shorter
+shorting
+shorts
 should
 shouldn't
 show
@@ -2487,6 +2545,7 @@
 side
 sign
 signal
+signaled
 signals
 signature
 signatures
@@ -2526,6 +2585,7 @@
 small
 smaller
 smallest
+smarter
 snapshot
 snapshots
 snippet
@@ -2620,6 +2680,7 @@
 structure
 stuff
 style
+subchain
 subclass
 subclassed
 subclasses
@@ -2785,6 +2846,7 @@
 time
 timeline
 times
+timing
 tip
 to
 today
@@ -2881,7 +2943,9 @@
 underlying
 underscore
 understand
+understands
 understood
+undetermined
 unevaluated
 unexpected
 unfinished
@@ -2923,6 +2987,7 @@
 unserializable
 unsigned
 unsized
+unskip
 unsorted
 unspecified
 unsplit
@@ -3064,6 +3129,7 @@
 worklist
 works
 world
+worth
 would
 wouldn't
 wrap
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 3eaeba6..ff871b9 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -63,6 +63,7 @@
 charcode
 charset
 checkout
+cipd
 circular
 cli
 cloneable
@@ -318,6 +319,7 @@
 spans
 spell
 spellcheck
+spelled
 spelling
 spent
 splitting
@@ -365,9 +367,11 @@
 typeparambounds
 unawaited
 unbreak
+unpacked
 unregistered
 untransformed
 untrimmed
+upload
 uppercase
 upward
 uses8
diff --git a/pkg/front_end/test/spell_checking_utils.dart b/pkg/front_end/test/spell_checking_utils.dart
index 479effa..26e9959 100644
--- a/pkg/front_end/test/spell_checking_utils.dart
+++ b/pkg/front_end/test/spell_checking_utils.dart
@@ -21,19 +21,26 @@
   ensureDictionariesLoaded(dictionaries);
 
   List<String> wrongWords;
+  List<List<String>> wrongWordsAlternatives;
   List<int> wrongWordsOffset;
   List<bool> wrongWordBlacklisted;
   List<int> wordOffsets = new List<int>();
   List<String> words =
       splitStringIntoWords(s, wordOffsets, splitAsCode: splitAsCode);
+  List<Set<String>> dictionariesUnpacked = [];
+  for (int j = 0; j < dictionaries.length; j++) {
+    Dictionaries dictionaryType = dictionaries[j];
+    if (dictionaryType == Dictionaries.blacklist) continue;
+    Set<String> dictionary = loadedDictionaries[dictionaryType];
+    dictionariesUnpacked.add(dictionary);
+  }
   for (int i = 0; i < words.length; i++) {
     String word = words[i].toLowerCase();
     int offset = wordOffsets[i];
     bool found = false;
-    for (int j = 0; j < dictionaries.length; j++) {
-      Dictionaries dictionaryType = dictionaries[j];
-      if (dictionaryType == Dictionaries.blacklist) continue;
-      Set<String> dictionary = loadedDictionaries[dictionaryType];
+
+    for (int j = 0; j < dictionariesUnpacked.length; j++) {
+      Set<String> dictionary = dictionariesUnpacked[j];
       if (dictionary.contains(word)) {
         found = true;
         break;
@@ -42,6 +49,8 @@
     if (!found) {
       wrongWords ??= new List<String>();
       wrongWords.add(word);
+      wrongWordsAlternatives ??= new List<List<String>>();
+      wrongWordsAlternatives.add(findAlternatives(word, dictionariesUnpacked));
       wrongWordsOffset ??= new List<int>();
       wrongWordsOffset.add(offset);
       wrongWordBlacklisted ??= new List<bool>();
@@ -50,16 +59,59 @@
     }
   }
 
-  return new SpellingResult(wrongWords, wrongWordsOffset, wrongWordBlacklisted);
+  return new SpellingResult(wrongWords, wrongWordsOffset, wrongWordBlacklisted,
+      wrongWordsAlternatives);
+}
+
+List<String> findAlternatives(String word, List<Set<String>> dictionaries) {
+  List<String> result;
+
+  bool check(String w) {
+    for (int j = 0; j < dictionaries.length; j++) {
+      Set<String> dictionary = dictionaries[j];
+      if (dictionary.contains(w)) return true;
+    }
+    return false;
+  }
+
+  void ok(String w) {
+    result ??= new List<String>();
+    result.add(w);
+  }
+
+  // Delete a letter, insert a letter or change a letter and lookup.
+  for (int i = 0; i < word.length; i++) {
+    String before = word.substring(0, i);
+    String after = word.substring(i + 1);
+    String afterIncluding = word.substring(i);
+
+    {
+      String deletedLetter = before + after;
+      if (check(deletedLetter)) ok(deletedLetter);
+    }
+    for (int j = 0; j < 25; j++) {
+      String c = new String.fromCharCode(97 + j);
+      String insertedLetter = before + c + afterIncluding;
+      if (check(insertedLetter)) ok(insertedLetter);
+    }
+    for (int j = 0; j < 25; j++) {
+      String c = new String.fromCharCode(97 + j);
+      String replacedLetter = before + c + after;
+      if (check(replacedLetter)) ok(replacedLetter);
+    }
+  }
+
+  return result;
 }
 
 class SpellingResult {
   final List<String> misspelledWords;
   final List<int> misspelledWordsOffset;
   final List<bool> misspelledWordsBlacklisted;
+  final List<List<String>> misspelledWordsAlternatives;
 
   SpellingResult(this.misspelledWords, this.misspelledWordsOffset,
-      this.misspelledWordsBlacklisted);
+      this.misspelledWordsBlacklisted, this.misspelledWordsAlternatives);
 }
 
 void ensureDictionariesLoaded(List<Dictionaries> dictionaries) {
@@ -135,9 +187,9 @@
   String regExpStringInner = r"\s-=\|\/,";
   if (splitAsCode) {
     // If splitting as code also split by "_", ":", ".", "(", ")", "<", ">",
-    // "[", "]", "{", "}", "@", "&", "#", "?", "%".
+    // "[", "]", "{", "}", "@", "&", "#", "?", "%", "`".
     // (As well as doing stuff to camel casing further below).
-    regExpStringInner = "${regExpStringInner}_:\\.\\(\\)<>\\[\\]\{\}@&#\\?%";
+    regExpStringInner = "${regExpStringInner}_:\\.\\(\\)<>\\[\\]\{\}@&#\\?%`";
   }
   // Match one or more of the characters specified above.
   String regExp = "[$regExpStringInner]+";
diff --git a/pkg/front_end/test/spell_checking_utils_test.dart b/pkg/front_end/test/spell_checking_utils_test.dart
index ed6bb7c..3b5616e 100644
--- a/pkg/front_end/test/spell_checking_utils_test.dart
+++ b/pkg/front_end/test/spell_checking_utils_test.dart
@@ -80,6 +80,10 @@
   expectSplit("foo%bar", false, ["foo%bar"], [0]);
   expectSplit("foo%bar", true, ["foo", "bar"], [0, 4]);
 
+  expectAlternative(
+      "explicitley", ["explicitly"], {"foo", "explicitly", "bar"});
+  expectAlternative("explicitlqqqqy", null, {"foo", "explicitly", "bar"});
+
   print("OK");
 }
 
@@ -88,15 +92,26 @@
   List<int> actualOffsets = new List<int>();
   List<String> actualWords =
       splitStringIntoWords(s, actualOffsets, splitAsCode: splitAsCode);
-  if (actualWords.length != expectedWords.length) {
-    throw "Not the same ($actualWords vs $expectedWords)";
+  compareLists(actualWords, expectedWords);
+  compareLists(actualOffsets, expectedOffsets);
+}
+
+void compareLists(List<dynamic> actual, List<dynamic> expected) {
+  if (actual == null && expected == null) return;
+  if (actual == null) throw "Got null, expected $expected";
+  if (expected == null) throw "Expected null, got $actual";
+  if (actual.length != expected.length) {
+    throw "Not the same ($actual vs $expected)";
   }
-  for (int i = 0; i < actualWords.length; i++) {
-    if (actualWords[i] != expectedWords[i]) {
-      throw "Not the same ($actualWords vs $expectedWords)";
-    }
-    if (actualOffsets[i] != expectedOffsets[i]) {
-      throw "Not the same ($actualOffsets vs $expectedOffsets)";
+  for (int i = 0; i < actual.length; i++) {
+    if (actual[i] != expected[i]) {
+      throw "Not the same ($actual vs $expected)";
     }
   }
 }
+
+void expectAlternative(
+    String word, List<String> expected, Set<String> dictionary) {
+  List<String> alternatives = findAlternatives(word, [dictionary]);
+  compareLists(alternatives, expected);
+}
diff --git a/pkg/front_end/test/spelling_test_base.dart b/pkg/front_end/test/spelling_test_base.dart
index ac96efe..605bdeb 100644
--- a/pkg/front_end/test/spelling_test_base.dart
+++ b/pkg/front_end/test/spelling_test_base.dart
@@ -8,18 +8,18 @@
 
 import 'dart:typed_data' show Uint8List;
 
-import 'package:front_end/src/fasta/command_line_reporting.dart'
-    as command_line_reporting;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show ErrorToken;
 
-import 'package:front_end/src/fasta/scanner.dart' show ErrorToken;
-
-import 'package:front_end/src/fasta/scanner/utf8_bytes_scanner.dart'
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
     show Utf8BytesScanner;
 
-import 'package:front_end/src/scanner/token.dart'
+import 'package:_fe_analyzer_shared/src/scanner/token.dart'
     show Token, KeywordToken, BeginToken;
 
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+
+import 'package:front_end/src/fasta/command_line_reporting.dart'
+    as command_line_reporting;
 
 import 'package:kernel/kernel.dart';
 
@@ -67,13 +67,33 @@
     List<String> errors;
     Source source = new Source(
         scanner.lineStarts, rawBytes, description.uri, description.uri);
-    void addErrorMessage(int offset, int squigglyLength, String message) {
+    void addErrorMessage(
+        int offset, String word, bool blacklisted, List<String> alternatives) {
       errors ??= new List<String>();
+      String message;
+      if (blacklisted) {
+        message = "Misspelled word: '$word' has explicitly been blacklisted.";
+      } else {
+        message = "The word '$word' is not in our dictionary.";
+      }
+      if (alternatives != null && alternatives.isNotEmpty) {
+        message += "\n\nThe following word(s) was 'close' "
+            "and in our dictionary: "
+            "${alternatives.join(", ")}\n";
+      }
+      if (context.dictionaries.isNotEmpty) {
+        String dictionaryPathString = context.dictionaries
+            .map((d) => spell.dictionaryToUri(d).toString())
+            .join("\n- ");
+        message += "\n\nIf the word is correctly spelled please add "
+            "it to one of these files:\n"
+            "- $dictionaryPathString\n";
+      }
       Location location = source.getLocation(description.uri, offset);
       errors.add(command_line_reporting.formatErrorMessage(
           source.getTextLine(location.line),
           location,
-          squigglyLength,
+          word.length,
           description.uri.toString(),
           message));
     }
@@ -96,8 +116,8 @@
               if (context.onlyBlacklisted && !blacklisted) continue;
               int offset =
                   comment.offset + spellingResult.misspelledWordsOffset[i];
-              String word = spellingResult.misspelledWords[i];
-              addErrorMessage(offset, word.length, "Misspelled word '$word'.");
+              addErrorMessage(offset, spellingResult.misspelledWords[i],
+                  blacklisted, spellingResult.misspelledWordsAlternatives[i]);
             }
           }
           comment = comment.next;
@@ -113,8 +133,8 @@
             bool blacklisted = spellingResult.misspelledWordsBlacklisted[i];
             if (context.onlyBlacklisted && !blacklisted) continue;
             int offset = token.offset + spellingResult.misspelledWordsOffset[i];
-            String word = spellingResult.misspelledWords[i];
-            addErrorMessage(offset, word.length, "Misspelled word '$word'.");
+            addErrorMessage(offset, spellingResult.misspelledWords[i],
+                blacklisted, spellingResult.misspelledWordsAlternatives[i]);
           }
         }
       } else if (token is KeywordToken || token is BeginToken) {
diff --git a/pkg/front_end/test/spelling_test_not_src_test.dart b/pkg/front_end/test/spelling_test_not_src_suite.dart
similarity index 100%
rename from pkg/front_end/test/spelling_test_not_src_test.dart
rename to pkg/front_end/test/spelling_test_not_src_suite.dart
diff --git a/pkg/front_end/test/spelling_test_src_test.dart b/pkg/front_end/test/spelling_test_src_suite.dart
similarity index 100%
rename from pkg/front_end/test/spelling_test_src_test.dart
rename to pkg/front_end/test/spelling_test_src_suite.dart
diff --git a/pkg/front_end/test/split_dill_test.dart b/pkg/front_end/test/split_dill_test.dart
index 828dae4..dee8bf3 100644
--- a/pkg/front_end/test/split_dill_test.dart
+++ b/pkg/front_end/test/split_dill_test.dart
@@ -16,7 +16,7 @@
 
 import "package:vm/target/vm.dart" show VmTarget;
 
-import 'incremental_load_from_dill_test.dart'
+import 'incremental_load_from_dill_suite.dart'
     show getOptions, normalCompileToComponent;
 
 import 'utils/io_utils.dart' show computeRepoDir;
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 83ff887..398d9dc 100644
--- a/pkg/front_end/test/static_types/data/prefix_postfix.dart
+++ b/pkg/front_end/test/static_types/data/prefix_postfix.dart
@@ -10,22 +10,28 @@
 dynamic dynamicTopLevel = /*int*/ 0;
 
 testTopLevel() {
-  /*update: num*/
+  /*cfe|dart2js.update: num*/
+  /*cfe:nnbd.update: num!*/
   /*cfe|dart2js.num*/
   /*cfe:nnbd.num!*/
-  numTopLevel /*invoke: num*/ /*int*/ ++;
+  numTopLevel /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
 
-  /*update: num*/
+  /*cfe|dart2js.update: num*/
+  /*cfe:nnbd.update: num!*/
   /*cfe|dart2js.num*/
   /*cfe:nnbd.num!*/
-  numTopLevel /*invoke: num*/ /*int*/ --;
+  numTopLevel /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
 
-  /*invoke: num*/ /*int*/ ++ /*update: num*/
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+      /*cfe|dart2js.update: num*/
+      /*cfe:nnbd.update: num!*/
       /*cfe|dart2js.num*/
       /*cfe:nnbd.num!*/
       numTopLevel;
 
-  /*invoke: num*/ /*int*/ -- /*update: num*/
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+      /*cfe|dart2js.update: num*/
+      /*cfe:nnbd.update: num!*/
       /*cfe|dart2js.num*/
       /*cfe:nnbd.num!*/
       numTopLevel;
@@ -85,22 +91,28 @@
   dynamic dynamicInstance = /*int*/ 0;
 
   testInstance() {
-    /*update: num*/
+    /*cfe|dart2js.update: num*/
+    /*cfe:nnbd.update: num!*/
     /*cfe|dart2js.num*/
     /*cfe:nnbd.num!*/
-    numInstance /*invoke: num*/ /*int*/ ++;
+    numInstance /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
 
-    /*update: num*/
+    /*cfe|dart2js.update: num*/
+    /*cfe:nnbd.update: num!*/
     /*cfe|dart2js.num*/
     /*cfe:nnbd.num!*/
-    numInstance /*invoke: num*/ /*int*/ --;
+    numInstance /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
 
-    /*invoke: num*/ /*int*/ ++ /*update: num*/
+    /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+        /*cfe|dart2js.update: num*/
+        /*cfe:nnbd.update: num!*/
         /*cfe|dart2js.num*/
         /*cfe:nnbd.num!*/
         numInstance;
 
-    /*invoke: num*/ /*int*/ -- /*update: num*/
+    /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+        /*cfe|dart2js.update: num*/
+        /*cfe:nnbd.update: num!*/
         /*cfe|dart2js.num*/
         /*cfe:nnbd.num!*/
         numInstance;
@@ -155,27 +167,33 @@
 testInstanceOnClass(Class c) {
   /*cfe|dart2js.Class*/
   /*cfe:nnbd.Class!*/
-  c. /*update: num*/
-      /*cfe|dart2js.num*/
-      /*cfe:nnbd.num!*/
-      numInstance /*invoke: num*/ /*int*/ ++;
+  c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
+          /*cfe|dart2js.num*/
+          /*cfe:nnbd.num!*/
+          numInstance
+      /*cfe|dart2js.invoke: num*/
+      /*cfe:nnbd.invoke: num!*/
+      /*int*/ ++;
   /*cfe|dart2js.Class*/
   /*cfe:nnbd.Class!*/
-  c. /*update: num*/
-      /*cfe|dart2js.num*/
-      /*cfe:nnbd.num!*/
-      numInstance /*invoke: num*/ /*int*/ --;
-  /*invoke: num*/ /*int*/ ++
+  c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
+          /*cfe|dart2js.num*/
+          /*cfe:nnbd.num!*/
+          numInstance
+      /*cfe|dart2js.invoke: num*/
+      /*cfe:nnbd.invoke: num!*/
+      /*int*/ --;
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
       /*cfe|dart2js.Class*/
       /*cfe:nnbd.Class!*/
-      c. /*update: num*/
+      c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
           /*cfe|dart2js.num*/
           /*cfe:nnbd.num!*/
           numInstance;
-  /*invoke: num*/ /*int*/ --
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
       /*cfe|dart2js.Class*/
       /*cfe:nnbd.Class!*/
-      c. /*update: num*/
+      c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
           /*cfe|dart2js.num*/
           /*cfe:nnbd.num!*/
           numInstance;
@@ -288,22 +306,28 @@
   /// ignore: unused_local_variable
   dynamic dynamicLocal = /*int*/ 0;
 
-  /*update: num*/
+  /*cfe|dart2js.update: num*/
+  /*cfe:nnbd.update: num!*/
   /*cfe|dart2js.num*/
   /*cfe:nnbd.num!*/
-  numLocal /*invoke: num*/ /*int*/ ++;
+  numLocal /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
 
-  /*update: num*/
+  /*cfe|dart2js.update: num*/
+  /*cfe:nnbd.update: num!*/
   /*cfe|dart2js.num*/
   /*cfe:nnbd.num!*/
-  numLocal /*invoke: num*/ /*int*/ --;
+  numLocal /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
 
-  /*invoke: num*/ /*int*/ ++ /*update: num*/
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+      /*cfe|dart2js.update: num*/
+      /*cfe:nnbd.update: num!*/
       /*cfe|dart2js.num*/
       /*cfe:nnbd.num!*/
       numLocal;
 
-  /*invoke: num*/ /*int*/ -- /*update: num*/
+  /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+      /*cfe|dart2js.update: num*/
+      /*cfe:nnbd.update: num!*/
       /*cfe|dart2js.num*/
       /*cfe:nnbd.num!*/
       numLocal;
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 139b423..91e66a0 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -3,11 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' show Directory, Platform;
-import 'package:front_end/src/fasta/kernel/kernel_api.dart';
-import 'package:front_end/src/testing/id.dart' show ActualData, Id;
-import 'package:front_end/src/testing/id_testing.dart'
+import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing.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:kernel/ast.dart';
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index 6ab5a00..d1d2a03 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/scanner.dart'
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerConfiguration, scanString;
-import 'package:front_end/src/scanner/token.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
new file mode 100644
index 0000000..ebc86c0
--- /dev/null
+++ b/pkg/front_end/test/unit_test_suites.dart
@@ -0,0 +1,320 @@
+// 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.
+
+import 'dart:async' show Timer;
+import 'dart:convert' show jsonEncode;
+import 'dart:io' show File, Platform, exitCode;
+import 'dart:isolate' show Isolate, ReceivePort, SendPort;
+
+import 'package:args/args.dart' show ArgParser;
+
+import 'package:testing/src/chain.dart' show CreateContext, Result, Step;
+import 'package:testing/src/expectation.dart' show Expectation;
+import 'package:testing/src/log.dart' show Logger;
+import 'package:testing/src/run.dart' show runMe;
+import 'package:testing/src/suite.dart' as testing show Suite;
+import 'package:testing/src/test_description.dart' show TestDescription;
+
+import 'fasta/expression_suite.dart' as expression show createContext;
+import 'fasta/outline_suite.dart' as outline show createContext;
+import 'fasta/fast_strong_suite.dart' as fast_strong show createContext;
+import 'fasta/incremental_suite.dart' as incremental show createContext;
+import 'fasta/messages_suite.dart' as messages show createContext;
+import 'fasta/strong_tester.dart' as strong show createContext;
+import 'fasta/text_serialization_suite.dart' as text_serialization
+    show createContext;
+import 'fasta/type_promotion_look_ahead_suite.dart' as type_promotion
+    show createContext;
+import 'incremental_bulk_compiler_smoke_suite.dart' as incremental_bulk_compiler
+    show createContext;
+import 'incremental_load_from_dill_suite.dart' as incremental_load
+    show createContext;
+import 'lint_suite.dart' as lint show createContext;
+import 'old_dill_suite.dart' as old_dill show createContext;
+import 'parser_suite.dart' as parser show createContext;
+import 'spelling_test_not_src_suite.dart' as spelling_not_src
+    show createContext;
+import 'spelling_test_src_suite.dart' as spelling_src show createContext;
+
+class Options {
+  final String configurationName;
+  final bool verbose;
+  final Uri outputDirectory;
+
+  Options(this.configurationName, this.verbose, this.outputDirectory);
+
+  static Options parse(List<String> args) {
+    var parser = new ArgParser()
+      ..addOption("named-configuration",
+          abbr: "n",
+          help: "configuration name to use for emitting json result files")
+      ..addOption("output-directory",
+          help: "directory to which results.json and logs.json are written")
+      ..addFlag("verbose",
+          abbr: "v", help: "print additional information", defaultsTo: false);
+    var parsedArguments = parser.parse(args);
+    String outputPath = parsedArguments["output-directory"] ?? ".";
+    Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
+    return Options(parsedArguments["named-configuration"],
+        parsedArguments["verbose"], outputDirectory);
+  }
+}
+
+class ResultLogger implements Logger {
+  final String suiteName;
+  final String prefix;
+  final bool verbose;
+  final SendPort resultsPort;
+  final SendPort logsPort;
+  final Map<String, Stopwatch> stopwatches = {};
+  final String configurationName;
+  final Set<String> seenTests = {};
+
+  ResultLogger(this.suiteName, this.prefix, this.resultsPort, this.logsPort,
+      this.verbose, this.configurationName);
+
+  String getTestName(TestDescription description) {
+    return "$prefix/${description.shortName}";
+  }
+
+  @override
+  void logMessage(Object message) {}
+
+  @override
+  void logNumberedLines(String text) {}
+
+  @override
+  void logProgress(String message) {}
+
+  @override
+  void logStepComplete(int completed, int failed, int total,
+      testing.Suite suite, TestDescription description, Step step) {}
+
+  @override
+  void logStepStart(int completed, int failed, int total, testing.Suite suite,
+      TestDescription description, Step step) {}
+
+  @override
+  void logSuiteStarted(testing.Suite suite) {}
+
+  @override
+  void logSuiteComplete(testing.Suite suite) {}
+
+  handleTestResult(TestDescription testDescription, Result result,
+      String fullSuiteName, bool matchedExpectations) {
+    String testName = getTestName(testDescription);
+    String suite = "pkg";
+    String shortTestName = testName.substring(suite.length + 1);
+    resultsPort.send(jsonEncode({
+      "name": testName,
+      "configuration": configurationName,
+      "suite": suite,
+      "test_name": shortTestName,
+      "time_ms": stopwatches[testName].elapsedMilliseconds,
+      "expected": "Pass",
+      "result": matchedExpectations ? "Pass" : "Fail",
+      "matches": matchedExpectations,
+    }));
+    if (!matchedExpectations) {
+      String failureLog = result.log;
+      if (result.error != null) {
+        failureLog = "$failureLog\n\n${result.error}";
+      }
+      if (result.trace != null) {
+        failureLog = "$failureLog\n\n${result.trace}";
+      }
+      String outcome = "${result.outcome}";
+      logsPort.send(jsonEncode({
+        "name": testName,
+        "configuration": configurationName,
+        "result": outcome,
+        "log": failureLog,
+      }));
+    }
+    if (verbose) {
+      String result = matchedExpectations ? "PASS" : "FAIL";
+      print("${testName}: ${result}");
+    }
+  }
+
+  void logTestStart(int completed, int failed, int total, testing.Suite suite,
+      TestDescription description) {
+    String name = getTestName(description);
+    stopwatches[name] = Stopwatch()..start();
+  }
+
+  @override
+  void logTestComplete(int completed, int failed, int total,
+      testing.Suite suite, TestDescription description) {}
+
+  @override
+  void logUncaughtError(error, StackTrace stackTrace) {}
+
+  void logExpectedResult(testing.Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes) {
+    handleTestResult(description, result, prefix, true);
+  }
+
+  @override
+  void logUnexpectedResult(testing.Suite suite, TestDescription description,
+      Result result, Set<Expectation> expectedOutcomes) {
+    // The test framework (pkg/testing) calls the logger with an unexpected
+    // results a second time to create a summary. We ignore the second call
+    // here.
+    String testName = getTestName(description);
+    if (seenTests.contains(testName)) return;
+    seenTests.add(testName);
+    handleTestResult(description, result, prefix, false);
+  }
+}
+
+class Suite {
+  final String name;
+  final CreateContext createContext;
+  final String testingRootPath;
+  final String path;
+  final int shardCount;
+  final int shard;
+
+  const Suite(this.name, this.createContext, this.testingRootPath,
+      {this.path, this.shardCount: 1, this.shard: 0});
+}
+
+final List<Suite> suites = [
+  const Suite(
+      "fasta/expression", expression.createContext, "../../testing.json"),
+  const Suite("fasta/outline", outline.createContext, "../../testing.json"),
+  const Suite(
+      "fasta/fast_strong", fast_strong.createContext, "../../testing.json"),
+  const Suite(
+      "fasta/incremental", incremental.createContext, "../../testing.json"),
+  const Suite("fasta/messages", messages.createContext, "../../testing.json"),
+  const Suite("fasta/text_serialization", text_serialization.createContext,
+      "../../testing.json"),
+  const Suite("fasta/strong1", strong.createContext, "../../testing.json",
+      path: "fasta/strong_tester.dart", shardCount: 4, shard: 0),
+  const Suite("fasta/strong2", strong.createContext, "../../testing.json",
+      path: "fasta/strong_tester.dart", shardCount: 4, shard: 1),
+  const Suite("fasta/strong3", strong.createContext, "../../testing.json",
+      path: "fasta/strong_tester.dart", shardCount: 4, shard: 2),
+  const Suite("fasta/strong4", strong.createContext, "../../testing.json",
+      path: "fasta/strong_tester.dart", shardCount: 4, shard: 3),
+  const Suite("fasta/type_promotion_look_ahead", type_promotion.createContext,
+      "../../testing.json"),
+  const Suite("incremental_bulk_compiler_smoke",
+      incremental_bulk_compiler.createContext, "../testing.json"),
+  const Suite("incremental_load_from_dill", incremental_load.createContext,
+      "../testing.json"),
+  const Suite("lint", lint.createContext, "../testing.json"),
+  const Suite("old_dill", old_dill.createContext, "../testing.json"),
+  const Suite("parser", parser.createContext, "../testing.json"),
+  const Suite("spelling_test_not_src", spelling_not_src.createContext,
+      "../testing.json"),
+  const Suite(
+      "spelling_test_src", spelling_src.createContext, "../testing.json"),
+];
+
+const Duration timeoutDuration = Duration(minutes: 10);
+
+class SuiteConfiguration {
+  final String name;
+  final SendPort resultsPort;
+  final SendPort logsPort;
+  final bool verbose;
+  final String configurationName;
+  const SuiteConfiguration(this.name, this.resultsPort, this.logsPort,
+      this.verbose, this.configurationName);
+}
+
+void runSuite(SuiteConfiguration configuration) {
+  Suite suite = suites.where((s) => s.name == configuration.name).single;
+  String name = suite.name;
+  String fullSuiteName = "pkg/front_end/test/$name";
+  Uri suiteUri = Platform.script.resolve(suite.path ?? "${name}_suite.dart");
+  ResultLogger logger = ResultLogger(
+      name,
+      fullSuiteName,
+      configuration.resultsPort,
+      configuration.logsPort,
+      configuration.verbose,
+      configuration.configurationName);
+  runMe(<String>[], suite.createContext,
+      me: suiteUri,
+      configurationPath: suite.testingRootPath,
+      logger: logger,
+      shards: suite.shardCount,
+      shard: suite.shard);
+}
+
+void writeLinesToFile(Uri uri, List<String> lines) async {
+  await File.fromUri(uri).writeAsString(lines.map((line) => "$line\n").join());
+}
+
+main([List<String> arguments = const <String>[]]) async {
+  List<String> results = [];
+  List<String> logs = [];
+  Options options = Options.parse(arguments);
+  ReceivePort resultsPort = new ReceivePort()
+    ..listen((resultEntry) => results.add(resultEntry));
+  ReceivePort logsPort = new ReceivePort()
+    ..listen((logEntry) => logs.add(logEntry));
+  List<Future<bool>> futures = [];
+  // Run test suites and record the results and possible failure logs.
+  for (Suite suite in suites) {
+    // Start the test suite in a new isolate.
+    ReceivePort exitPort = new ReceivePort();
+    String name = suite.name;
+    SuiteConfiguration configuration = SuiteConfiguration(
+        name,
+        resultsPort.sendPort,
+        logsPort.sendPort,
+        options.verbose,
+        options.configurationName);
+    Future future = Future<bool>(() async {
+      Stopwatch stopwatch = Stopwatch()..start();
+      print("Running suite $name");
+      // TODO(karlklose): Implement --filter to select tests to run
+      // to implement deflaking (dartbug.com/38607).
+      Isolate isolate = await Isolate.spawn<SuiteConfiguration>(
+          runSuite, configuration,
+          onExit: exitPort.sendPort);
+      bool timedOut = false;
+      Timer timer = Timer(timeoutDuration, () {
+        timedOut = true;
+        print("Suite $name timed out after "
+            "${timeoutDuration.inMilliseconds}ms");
+        isolate.kill(priority: Isolate.immediate);
+      });
+      await exitPort.first;
+      timer.cancel();
+      if (!timedOut) {
+        print(
+            "Suite $name finished (took ${stopwatch.elapsedMilliseconds}ms).");
+      }
+      return timedOut;
+    });
+    futures.add(future);
+  }
+  // Wait for isolates to terminate and clean up.
+  Iterable<bool> timeouts = await Future.wait(futures);
+  resultsPort.close();
+  logsPort.close();
+  // Write results.json and logs.json.
+  Uri resultJsonUri = options.outputDirectory.resolve("results.json");
+  Uri logsJsonUri = options.outputDirectory.resolve("logs.json");
+  await writeLinesToFile(resultJsonUri, results);
+  await writeLinesToFile(logsJsonUri, logs);
+  print("Log files written to ${resultJsonUri.toFilePath()} and"
+      " ${logsJsonUri.toFilePath()}");
+  // Return with exit code 1 if at least one suite timed out.
+  bool timeout = timeouts.any((timeout) => timeout);
+  if (timeout) {
+    exitCode = 1;
+  } else {
+    // The testing framework (pkg/testing) sets the exitCode to 1 if any test
+    // failed, so we reset it here to indicate that the test runner was
+    // successful.
+    exitCode = 0;
+  }
+}
diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart
index 7b44127..b6de873 100644
--- a/pkg/front_end/test/utils/kernel_chain.dart
+++ b/pkg/front_end/test/utils/kernel_chain.dart
@@ -6,11 +6,13 @@
 
 import 'dart:async' show Future;
 
-import 'dart:io' show Directory, File, IOSink;
-import 'dart:io';
+import 'dart:io' show Directory, File, IOSink, Platform;
 
 import 'dart:typed_data' show Uint8List;
 
+import 'package:_fe_analyzer_shared/src/util/relativize.dart'
+    show isWindows, relativizeUri;
+
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions, DiagnosticMessage;
 
@@ -25,16 +27,16 @@
 import 'package:front_end/src/fasta/fasta_codes.dart'
     show templateInternalProblemUnhandled, templateUnspecified;
 
+import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
+
 import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
 
 import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
 
-import 'package:front_end/src/fasta/resolve_input_uri.dart' show isWindows;
-
-import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
-
 import 'package:kernel/ast.dart' show Component, Library;
 
+import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
+
 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
 
 import 'package:kernel/error_formatter.dart' show ErrorFormatter;
@@ -66,15 +68,14 @@
   Expectation get expectationFileMismatch =>
       expectationSet["ExpectationFileMismatch"];
 
+  Expectation get expectationFileMismatchSerialized =>
+      expectationSet["ExpectationFileMismatchSerialized"];
+
   Expectation get expectationFileMissing =>
       expectationSet["ExpectationFileMissing"];
 
-  Future<Result<O>> match<O>(
-    String suffix,
-    String actual,
-    Uri uri,
-    O output,
-  ) async {
+  Future<Result<O>> match<O>(String suffix, String actual, Uri uri, O output,
+      {Expectation onMismatch}) async {
     actual = actual.trim();
     if (actual.isNotEmpty) {
       actual += "\n";
@@ -87,7 +88,8 @@
           return updateExpectationFile<O>(expectedFile.uri, actual, output);
         }
         String diff = await runDiff(expectedFile.uri, actual);
-        return new Result<O>(output, expectationFileMismatch,
+        onMismatch ??= expectationFileMismatch;
+        return new Result<O>(output, onMismatch,
             "$uri doesn't match ${expectedFile.uri}\n$diff", null);
       } else {
         return new Result<O>.pass(output);
@@ -208,17 +210,49 @@
 
 class MatchExpectation extends Step<Component, Component, MatchContext> {
   final String suffix;
+  final bool serializeFirst;
 
-  const MatchExpectation(this.suffix);
+  /// Check if a textual representation of the component matches the expectation
+  /// located at [suffix]. If [serializeFirst] is true, the input component will
+  /// be serialized, deserialized, and the textual representation of that is
+  /// compared. It is still the original component that is returned though.
+  const MatchExpectation(this.suffix, {this.serializeFirst: false});
 
   String get name => "match expectations";
 
   Future<Result<Component>> run(Component component, MatchContext context) {
+    Component componentToText = component;
+    if (serializeFirst) {
+      component.computeCanonicalNames();
+      List<Library> sdkLibraries = component.libraries
+          .where((l) => l.importUri.scheme == "dart")
+          .toList();
+
+      ByteSink sink = new ByteSink();
+      Component writeMe = new Component(
+          libraries: component.libraries
+              .where((l) => l.importUri.scheme != "dart")
+              .toList());
+      writeMe.uriToSource.addAll(component.uriToSource);
+      if (component.problemsAsJson != null) {
+        writeMe.problemsAsJson =
+            new List<String>.from(component.problemsAsJson);
+      }
+      BinaryPrinter binaryPrinter = new BinaryPrinter(sink);
+      binaryPrinter.writeComponentFile(writeMe);
+      List<int> bytes = sink.builder.takeBytes();
+
+      BinaryBuilder binaryBuilder = new BinaryBuilder(bytes);
+      componentToText = new Component(libraries: sdkLibraries);
+      binaryBuilder.readComponent(componentToText);
+      component.adoptChildren();
+    }
+
     StringBuffer messages =
         (context as dynamic).componentToDiagnostics[component];
     Uri uri =
         component.uriToSource.keys.firstWhere((uri) => uri?.scheme == "file");
-    Iterable<Library> libraries = component.libraries.where(
+    Iterable<Library> libraries = componentToText.libraries.where(
         ((Library library) =>
             library.importUri.scheme != "dart" &&
             library.importUri.scheme != "package"));
@@ -227,12 +261,13 @@
     StringBuffer buffer = new StringBuffer();
     messages.clear();
     Printer printer = new Printer(buffer)
-      ..writeProblemsAsJson("Problems in component", component.problemsAsJson);
+      ..writeProblemsAsJson(
+          "Problems in component", componentToText.problemsAsJson);
     libraries.forEach((Library library) {
       printer.writeLibraryFile(library);
       printer.endLine();
     });
-    printer.writeConstantTable(component);
+    printer.writeConstantTable(componentToText);
     String actual = "$buffer";
     String binariesPath =
         relativizeUri(Uri.base, platformBinariesLocation, isWindows);
@@ -246,7 +281,10 @@
     actual = actual.replaceAll("$base", "org-dartlang-testcase:///");
     actual = actual.replaceAll("$dartBase", "org-dartlang-testcase-sdk:///");
     actual = actual.replaceAll("\\n", "\n");
-    return context.match<Component>(suffix, actual, uri, component);
+    return context.match<Component>(suffix, actual, uri, component,
+        onMismatch: serializeFirst
+            ? context.expectationFileMismatchSerialized
+            : context.expectationFileMismatch);
   }
 }
 
diff --git a/pkg/front_end/test/utils/scanner_chain.dart b/pkg/front_end/test/utils/scanner_chain.dart
index 3dbdd99..7f014e4 100644
--- a/pkg/front_end/test/utils/scanner_chain.dart
+++ b/pkg/front_end/test/utils/scanner_chain.dart
@@ -4,9 +4,10 @@
 
 library fasta.testing.scanner_chain;
 
-import 'package:front_end/src/fasta/scanner.dart' show ScannerResult, scan;
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show ScannerResult, scan;
 
-import 'package:front_end/src/fasta/scanner/io.dart' show readBytesFromFile;
+import 'package:_fe_analyzer_shared/src/scanner/io.dart' show readBytesFromFile;
 
 import 'package:testing/testing.dart'
     show ChainContext, Future, Result, Step, TestDescription;
diff --git a/pkg/front_end/test/utils/validating_instrumentation.dart b/pkg/front_end/test/utils/validating_instrumentation.dart
index 741876c..8214637 100644
--- a/pkg/front_end/test/utils/validating_instrumentation.dart
+++ b/pkg/front_end/test/utils/validating_instrumentation.dart
@@ -8,6 +8,16 @@
 
 import 'dart:io' show File;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
+import 'package:_fe_analyzer_shared/src/scanner/io.dart' show readBytesFromFile;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+    show ScannerResult, Token, scan;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' as analyzer
+    show Token;
+
 import 'package:front_end/src/base/instrumentation.dart'
     show Instrumentation, InstrumentationValue;
 
@@ -16,15 +26,6 @@
 import 'package:front_end/src/fasta/messages.dart'
     show noLength, templateUnspecified;
 
-import 'package:front_end/src/fasta/scanner.dart'
-    show ScannerResult, Token, scan;
-
-import 'package:front_end/src/fasta/scanner/io.dart' show readBytesFromFile;
-
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
-import 'package:front_end/src/scanner/token.dart' as analyzer show Token;
-
 /// Implementation of [Instrumentation] which checks property/value pairs
 /// against expectations encoded in source files using "/*@...*/" comments.
 class ValidatingInstrumentation implements Instrumentation {
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart b/pkg/front_end/testcases/extensions/builtin_identifiers.dart
new file mode 100644
index 0000000..ada520d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart
@@ -0,0 +1,11 @@
+// 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.
+
+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.outline.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.outline.expect
new file mode 100644
index 0000000..deff425
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:5:11: Error: Can't use 'mixin' as a name here.
+// extension mixin on int {}
+//           ^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:7:11: Error: Can't use 'extension' as a name here.
+// extension extension on int {}
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:9:11: Error: Can't use 'as' as a name here.
+// extension as on int {}
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension mixin on core::int* {
+}
+extension extension on core::int* {
+}
+extension as on core::int* {
+}
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.expect
new file mode 100644
index 0000000..dba880e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:5:11: Error: Can't use 'mixin' as a name here.
+// extension mixin on int {}
+//           ^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:7:11: Error: Can't use 'extension' as a name here.
+// extension extension on int {}
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:9:11: Error: Can't use 'as' as a name here.
+// extension as on int {}
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension mixin on core::int* {
+}
+extension extension on core::int* {
+}
+extension as on core::int* {
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.transformed.expect
new file mode 100644
index 0000000..dba880e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:5:11: Error: Can't use 'mixin' as a name here.
+// extension mixin on int {}
+//           ^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:7:11: Error: Can't use 'extension' as a name here.
+// extension extension on int {}
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/builtin_identifiers.dart:9:11: Error: Can't use 'as' as a name here.
+// extension as on int {}
+//           ^^
+//
+import self as self;
+import "dart:core" as core;
+
+extension mixin on core::int* {
+}
+extension extension on core::int* {
+}
+extension as on core::int* {
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart b/pkg/front_end/testcases/extensions/compounds.dart
index 812e0c9..a84d095 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart
+++ b/pkg/front_end/testcases/extensions/compounds.dart
@@ -24,9 +24,10 @@
       throw new ArgumentError('$other');
     }
   }
-  Number operator -(Object other)  {
+
+  Number operator -(Object other) {
     if (other is int) {
-     return new Number(value - other);
+      return new Number(value - other);
     } else if (other is Number) {
       return new Number(value - other.value);
     } else {
@@ -86,13 +87,69 @@
   }
 }
 
+class IntClass {
+  int field;
+
+  IntClass(this.field);
+}
+
+extension IntClassExtension on IntClass {
+  int get property => field;
+  void set property(int value) {
+    field = value;
+  }
+
+  testImplicitProperties() {
+    int n0 = 0;
+    int n1 = 1;
+    int n2 = 2;
+
+    expect(n0, property);
+    expect(n1, property += n1);
+    expect(n2, property += n1);
+    expect(n0, property -= n2);
+    expect(n1, property += n1);
+    expect(n0, property -= n1);
+    expect(n1, ++property);
+    expect(n0, --property);
+    expect(n0, property++);
+    expect(n1, property--);
+    expect(n0, property);
+
+    expect(n0, property);
+    property += n1;
+    expect(n1, property);
+    property += n1;
+    expect(n2, property);
+    property -= n2;
+    expect(n0, property);
+    property += n1;
+    expect(n1, property);
+    property -= n1;
+    expect(n0, property);
+    ++property;
+    expect(n1, property);
+    --property;
+    expect(n0, property);
+    property++;
+    expect(n1, property);
+    property--;
+    expect(n0, property);
+  }
+}
+
 main() {
   testLocals();
   testProperties();
+  testIntProperties();
   testExplicitProperties();
+  testExplicitIntProperties();
   testExplicitNullAwareProperties(null);
   testExplicitNullAwareProperties(new Class(new Number(0)));
+  testExplicitNullAwareIntProperties(null);
+  testExplicitNullAwareIntProperties(new IntClass(0));
   new Class(new Number(0)).testImplicitProperties();
+  new IntClass(0).testImplicitProperties();
 }
 
 testLocals() {
@@ -203,6 +260,76 @@
   expect(n0, v.property);
 }
 
+testIntProperties() {
+  int n0 = 0;
+  int n1 = 1;
+  int n2 = 2;
+  IntClass v = new IntClass(n0);
+  expect(n0, v.field);
+  expect(n1, v.field += n1);
+  expect(n2, v.field += n1);
+  expect(n0, v.field -= n2);
+  expect(n1, v.field += n1);
+  expect(n0, v.field -= n1);
+  expect(n1, ++v.field);
+  expect(n0, --v.field);
+  expect(n0, v.field++);
+  expect(n1, v.field--);
+  expect(n0, v.field);
+
+  expect(n0, v.field);
+  v.field += n1;
+  expect(n1, v.field);
+  v.field += n1;
+  expect(n2, v.field);
+  v.field -= n2;
+  expect(n0, v.field);
+  v.field += n1;
+  expect(n1, v.field);
+  v.field -= n1;
+  expect(n0, v.field);
+  ++v.field;
+  expect(n1, v.field);
+  --v.field;
+  expect(n0, v.field);
+  v.field++;
+  expect(n1, v.field);
+  v.field--;
+  expect(n0, v.field);
+
+  expect(n0, v.property);
+  expect(n1, v.property += n1);
+  expect(n2, v.property += n1);
+  expect(n0, v.property -= n2);
+  expect(n1, v.property += n1);
+  expect(n0, v.property -= n1);
+  expect(n1, ++v.property);
+  expect(n0, --v.property);
+  expect(n0, v.property++);
+  expect(n1, v.property--);
+  expect(n0, v.property);
+
+  expect(n0, v.property);
+  v.property += n1;
+  expect(n1, v.property);
+  v.property += n1;
+  expect(n2, v.property);
+  v.property -= n2;
+  expect(n0, v.property);
+  v.property += n1;
+  expect(n1, v.property);
+  v.property -= n1;
+  expect(n0, v.property);
+  ++v.property;
+  expect(n1, v.property);
+  --v.property;
+  expect(n0, v.property);
+  v.property++;
+  expect(n1, v.property);
+  v.property--;
+  expect(n0, v.property);
+}
+
 testExplicitProperties() {
   Number n0 = new Number(0);
   Number n1 = new Number(1);
@@ -242,6 +369,45 @@
   expect(n0, ClassExtension(v).property);
 }
 
+testExplicitIntProperties() {
+  int n0 = 0;
+  int n1 = 1;
+  int n2 = 2;
+  IntClass v = new IntClass(n0);
+
+  expect(n0, IntClassExtension(v).property);
+  expect(n1, IntClassExtension(v).property += n1);
+  expect(n2, IntClassExtension(v).property += n1);
+  expect(n0, IntClassExtension(v).property -= n2);
+  expect(n1, IntClassExtension(v).property += n1);
+  expect(n0, IntClassExtension(v).property -= n1);
+  expect(n1, ++IntClassExtension(v).property);
+  expect(n0, --IntClassExtension(v).property);
+  expect(n0, IntClassExtension(v).property++);
+  expect(n1, IntClassExtension(v).property--);
+  expect(n0, IntClassExtension(v).property);
+
+  expect(n0, IntClassExtension(v).property);
+  IntClassExtension(v).property += n1;
+  expect(n1, IntClassExtension(v).property);
+  IntClassExtension(v).property += n1;
+  expect(n2, IntClassExtension(v).property);
+  IntClassExtension(v).property -= n2;
+  expect(n0, IntClassExtension(v).property);
+  IntClassExtension(v).property += n1;
+  expect(n1, IntClassExtension(v).property);
+  IntClassExtension(v).property -= n1;
+  expect(n0, IntClassExtension(v).property);
+  ++IntClassExtension(v).property;
+  expect(n1, IntClassExtension(v).property);
+  --IntClassExtension(v).property;
+  expect(n0, IntClassExtension(v).property);
+  IntClassExtension(v).property++;
+  expect(n1, IntClassExtension(v).property);
+  IntClassExtension(v).property--;
+  expect(n0, IntClassExtension(v).property);
+}
+
 testExplicitNullAwareProperties(Class v) {
   Number n0 = new Number(0);
   Number n1 = new Number(1);
@@ -280,6 +446,44 @@
   expect(n0, ClassExtension(v)?.property, v == null);
 }
 
+testExplicitNullAwareIntProperties(IntClass v) {
+  int n0 = 0;
+  int n1 = 1;
+  int n2 = 2;
+
+  expect(n0, IntClassExtension(v)?.property, v == null);
+  expect(n1, IntClassExtension(v)?.property += n1, v == null);
+  expect(n2, IntClassExtension(v)?.property += n1, v == null);
+  expect(n0, IntClassExtension(v)?.property -= n2, v == null);
+  expect(n1, IntClassExtension(v)?.property += n1, v == null);
+  expect(n0, IntClassExtension(v)?.property -= n1, v == null);
+  expect(n1, ++IntClassExtension(v)?.property, v == null);
+  expect(n0, --IntClassExtension(v)?.property, v == null);
+  expect(n0, IntClassExtension(v)?.property++, v == null);
+  expect(n1, IntClassExtension(v)?.property--, v == null);
+  expect(n0, IntClassExtension(v)?.property, v == null);
+
+  expect(n0, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property += n1;
+  expect(n1, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property += n1;
+  expect(n2, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property -= n2;
+  expect(n0, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property += n1;
+  expect(n1, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property -= n1;
+  expect(n0, IntClassExtension(v)?.property, v == null);
+  ++IntClassExtension(v)?.property;
+  expect(n1, IntClassExtension(v)?.property, v == null);
+  --IntClassExtension(v)?.property;
+  expect(n0, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property++;
+  expect(n1, IntClassExtension(v)?.property, v == null);
+  IntClassExtension(v)?.property--;
+  expect(n0, IntClassExtension(v)?.property, v == null);
+}
+
 expect(expected, actual, [expectNull = false]) {
   if (expectNull) {
     expected = null;
@@ -287,4 +491,4 @@
   if (expected != actual) {
     throw 'Mismatch: expected=$expected, actual=$actual';
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.outline.expect b/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
index 42ab3e2..07927ac 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.outline.expect
@@ -18,6 +18,11 @@
   constructor •(self::Number* field) → self::Class*
     ;
 }
+class IntClass extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::IntClass*
+    ;
+}
 extension NumberExtension on self::Number* {
   operator + = self::NumberExtension|+;
   operator - = self::NumberExtension|-;
@@ -28,6 +33,12 @@
   tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
+extension IntClassExtension on self::IntClass* {
+  get property = self::IntClassExtension|get#property;
+  method testImplicitProperties = self::IntClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::IntClassExtension|get#testImplicitProperties;
+  set property = self::IntClassExtension|set#property;
+}
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number*
   ;
 static method NumberExtension|-(final self::Number* #this, core::Object* other) → self::Number*
@@ -40,15 +51,29 @@
   ;
 static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
   return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
+static method IntClassExtension|get#property(final self::IntClass* #this) → core::int*
+  ;
+static method IntClassExtension|set#property(final self::IntClass* #this, core::int* value) → void
+  ;
+static method IntClassExtension|testImplicitProperties(final self::IntClass* #this) → dynamic
+  ;
+static method IntClassExtension|get#testImplicitProperties(final self::IntClass* #this) → () →* dynamic
+  return () → dynamic => self::IntClassExtension|testImplicitProperties(#this);
 static method main() → dynamic
   ;
 static method testLocals() → dynamic
   ;
 static method testProperties() → dynamic
   ;
+static method testIntProperties() → dynamic
+  ;
 static method testExplicitProperties() → dynamic
   ;
+static method testExplicitIntProperties() → dynamic
+  ;
 static method testExplicitNullAwareProperties(self::Class* v) → dynamic
   ;
+static method testExplicitNullAwareIntProperties(self::IntClass* v) → dynamic
+  ;
 static method expect(dynamic expected, dynamic actual, [dynamic expectNull]) → dynamic
   ;
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
index e0e9cdf..24d7f52 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.expect
@@ -20,6 +20,12 @@
     : self::Class::field = field, super core::Object::•()
     ;
 }
+class IntClass extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::IntClass*
+    : self::IntClass::field = field, super core::Object::•()
+    ;
+}
 extension NumberExtension on self::Number* {
   operator + = self::NumberExtension|+;
   operator - = self::NumberExtension|-;
@@ -30,6 +36,12 @@
   tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
+extension IntClassExtension on self::IntClass* {
+  get property = self::IntClassExtension|get#property;
+  method testImplicitProperties = self::IntClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::IntClassExtension|get#testImplicitProperties;
+  set property = self::IntClassExtension|set#property;
+}
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number* {
   if(other is core::int*) {
     return new self::Number::•(#this.{self::Number::value}.{core::num::+}(other{core::int*}));
@@ -96,13 +108,60 @@
 }
 static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
   return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
+static method IntClassExtension|get#property(final self::IntClass* #this) → core::int*
+  return #this.{self::IntClass::field};
+static method IntClassExtension|set#property(final self::IntClass* #this, core::int* value) → void {
+  #this.{self::IntClass::field} = value;
+}
+static method IntClassExtension|testImplicitProperties(final self::IntClass* #this) → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::expect(n1, let final core::int* #t23 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t24 = self::IntClassExtension|set#property(#this, #t23) in #t23);
+  self::expect(n2, let final core::int* #t25 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t26 = self::IntClassExtension|set#property(#this, #t25) in #t25);
+  self::expect(n0, let final core::int* #t27 = self::IntClassExtension|get#property(#this).{core::num::-}(n2) in let final void #t28 = self::IntClassExtension|set#property(#this, #t27) in #t27);
+  self::expect(n1, let final core::int* #t29 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t30 = self::IntClassExtension|set#property(#this, #t29) in #t29);
+  self::expect(n0, let final core::int* #t31 = self::IntClassExtension|get#property(#this).{core::num::-}(n1) in let final void #t32 = self::IntClassExtension|set#property(#this, #t31) in #t31);
+  self::expect(n1, let final core::int* #t33 = self::IntClassExtension|get#property(#this).{core::num::+}(1) in let final void #t34 = self::IntClassExtension|set#property(#this, #t33) in #t33);
+  self::expect(n0, let final core::int* #t35 = self::IntClassExtension|get#property(#this).{core::num::-}(1) in let final void #t36 = self::IntClassExtension|set#property(#this, #t35) in #t35);
+  self::expect(n0, let final core::int* #t37 = self::IntClassExtension|get#property(#this) in let final core::int* #t38 = self::IntClassExtension|set#property(#this, #t37.{core::num::+}(1)) in #t37);
+  self::expect(n1, let final core::int* #t39 = self::IntClassExtension|get#property(#this) in let final core::int* #t40 = self::IntClassExtension|set#property(#this, #t39.{core::num::-}(1)) in #t39);
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  let final core::int* #t41 = self::IntClassExtension|get#property(#this).{core::num::+}(1) in let final void #t42 = self::IntClassExtension|set#property(#this, #t41) in #t41;
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  let final core::int* #t43 = self::IntClassExtension|get#property(#this).{core::num::-}(1) in let final void #t44 = self::IntClassExtension|set#property(#this, #t43) in #t43;
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+}
+static method IntClassExtension|get#testImplicitProperties(final self::IntClass* #this) → () →* dynamic
+  return () → dynamic => self::IntClassExtension|testImplicitProperties(#this);
 static method main() → dynamic {
   self::testLocals();
   self::testProperties();
+  self::testIntProperties();
   self::testExplicitProperties();
+  self::testExplicitIntProperties();
   self::testExplicitNullAwareProperties(null);
   self::testExplicitNullAwareProperties(new self::Class::•(new self::Number::•(0)));
+  self::testExplicitNullAwareIntProperties(null);
+  self::testExplicitNullAwareIntProperties(new self::IntClass::•(0));
   self::ClassExtension|testImplicitProperties(new self::Class::•(new self::Number::•(0)));
+  self::IntClassExtension|testImplicitProperties(new self::IntClass::•(0));
 }
 static method testLocals() → dynamic {
   self::Number* n0 = new self::Number::•(0);
@@ -117,8 +176,8 @@
   self::expect(n0, v = self::NumberExtension|-(v, n1));
   self::expect(n1, v = self::NumberExtension|+(v, 1));
   self::expect(n0, v = self::NumberExtension|-(v, 1));
-  self::expect(n0, let final self::Number* #t23 = v in let final self::Number* #t24 = v = self::NumberExtension|+(#t23, 1) in #t23);
-  self::expect(n1, let final self::Number* #t25 = v in let final self::Number* #t26 = v = self::NumberExtension|-(#t25, 1) in #t25);
+  self::expect(n0, let final self::Number* #t45 = v in let final self::Number* #t46 = v = self::NumberExtension|+(#t45, 1) in #t45);
+  self::expect(n1, let final self::Number* #t47 = v in let final self::Number* #t48 = v = self::NumberExtension|-(#t47, 1) in #t47);
   self::expect(n0, v);
   self::expect(n0, v);
   v = self::NumberExtension|+(v, n1);
@@ -146,136 +205,273 @@
   self::Number* n2 = new self::Number::•(2);
   self::Class* v = new self::Class::•(n0);
   self::expect(n0, v.{self::Class::field});
-  self::expect(n1, let final self::Class* #t27 = v in #t27.{self::Class::field} = self::NumberExtension|+(#t27.{self::Class::field}, n1));
-  self::expect(n2, let final self::Class* #t28 = v in #t28.{self::Class::field} = self::NumberExtension|+(#t28.{self::Class::field}, n1));
-  self::expect(n0, let final self::Class* #t29 = v in #t29.{self::Class::field} = self::NumberExtension|-(#t29.{self::Class::field}, n2));
-  self::expect(n1, let final self::Class* #t30 = v in #t30.{self::Class::field} = self::NumberExtension|+(#t30.{self::Class::field}, n1));
-  self::expect(n0, let final self::Class* #t31 = v in #t31.{self::Class::field} = self::NumberExtension|-(#t31.{self::Class::field}, n1));
-  self::expect(n1, let final self::Class* #t32 = v in #t32.{self::Class::field} = self::NumberExtension|+(#t32.{self::Class::field}, 1));
-  self::expect(n0, let final self::Class* #t33 = v in #t33.{self::Class::field} = self::NumberExtension|-(#t33.{self::Class::field}, 1));
-  self::expect(n0, let final self::Class* #t34 = v in let final self::Number* #t35 = #t34.{self::Class::field} in let final self::Number* #t36 = #t34.{self::Class::field} = self::NumberExtension|+(#t35, 1) in #t35);
-  self::expect(n1, let final self::Class* #t37 = v in let final self::Number* #t38 = #t37.{self::Class::field} in let final self::Number* #t39 = #t37.{self::Class::field} = self::NumberExtension|-(#t38, 1) in #t38);
+  self::expect(n1, let final self::Class* #t49 = v in #t49.{self::Class::field} = self::NumberExtension|+(#t49.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t50 = v in #t50.{self::Class::field} = self::NumberExtension|+(#t50.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t51 = v in #t51.{self::Class::field} = self::NumberExtension|-(#t51.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t52 = v in #t52.{self::Class::field} = self::NumberExtension|+(#t52.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t53 = v in #t53.{self::Class::field} = self::NumberExtension|-(#t53.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t54 = v in #t54.{self::Class::field} = self::NumberExtension|+(#t54.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t55 = v in #t55.{self::Class::field} = self::NumberExtension|-(#t55.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t56 = v in let final self::Number* #t57 = #t56.{self::Class::field} in let final self::Number* #t58 = #t56.{self::Class::field} = self::NumberExtension|+(#t57, 1) in #t57);
+  self::expect(n1, let final self::Class* #t59 = v in let final self::Number* #t60 = #t59.{self::Class::field} in let final self::Number* #t61 = #t59.{self::Class::field} = self::NumberExtension|-(#t60, 1) in #t60);
   self::expect(n0, v.{self::Class::field});
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t40 = v in #t40.{self::Class::field} = self::NumberExtension|+(#t40.{self::Class::field}, n1);
+  let final self::Class* #t62 = v in #t62.{self::Class::field} = self::NumberExtension|+(#t62.{self::Class::field}, n1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t41 = v in #t41.{self::Class::field} = self::NumberExtension|+(#t41.{self::Class::field}, n1);
+  let final self::Class* #t63 = v in #t63.{self::Class::field} = self::NumberExtension|+(#t63.{self::Class::field}, n1);
   self::expect(n2, v.{self::Class::field});
-  let final self::Class* #t42 = v in #t42.{self::Class::field} = self::NumberExtension|-(#t42.{self::Class::field}, n2);
+  let final self::Class* #t64 = v in #t64.{self::Class::field} = self::NumberExtension|-(#t64.{self::Class::field}, n2);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t43 = v in #t43.{self::Class::field} = self::NumberExtension|+(#t43.{self::Class::field}, n1);
+  let final self::Class* #t65 = v in #t65.{self::Class::field} = self::NumberExtension|+(#t65.{self::Class::field}, n1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t44 = v in #t44.{self::Class::field} = self::NumberExtension|-(#t44.{self::Class::field}, n1);
+  let final self::Class* #t66 = v in #t66.{self::Class::field} = self::NumberExtension|-(#t66.{self::Class::field}, n1);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t45 = v in #t45.{self::Class::field} = self::NumberExtension|+(#t45.{self::Class::field}, 1);
+  let final self::Class* #t67 = v in #t67.{self::Class::field} = self::NumberExtension|+(#t67.{self::Class::field}, 1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t46 = v in #t46.{self::Class::field} = self::NumberExtension|-(#t46.{self::Class::field}, 1);
+  let final self::Class* #t68 = v in #t68.{self::Class::field} = self::NumberExtension|-(#t68.{self::Class::field}, 1);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t47 = v in #t47.{self::Class::field} = self::NumberExtension|+(#t47.{self::Class::field}, 1);
+  let final self::Class* #t69 = v in #t69.{self::Class::field} = self::NumberExtension|+(#t69.{self::Class::field}, 1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t48 = v in #t48.{self::Class::field} = self::NumberExtension|-(#t48.{self::Class::field}, 1);
+  let final self::Class* #t70 = v in #t70.{self::Class::field} = self::NumberExtension|-(#t70.{self::Class::field}, 1);
   self::expect(n0, v.{self::Class::field});
   self::expect(n0, self::ClassExtension|get#property(v));
-  self::expect(n1, let final self::Class* #t49 = v in let final self::Class* #t50 = #t49 in let final self::Number* #t51 = self::NumberExtension|+(self::ClassExtension|get#property(#t49), n1) in let final void #t52 = self::ClassExtension|set#property(#t50, #t51) in #t51);
-  self::expect(n2, let final self::Class* #t53 = v in let final self::Class* #t54 = #t53 in let final self::Number* #t55 = self::NumberExtension|+(self::ClassExtension|get#property(#t53), n1) in let final void #t56 = self::ClassExtension|set#property(#t54, #t55) in #t55);
-  self::expect(n0, let final self::Class* #t57 = v in let final self::Class* #t58 = #t57 in let final self::Number* #t59 = self::NumberExtension|-(self::ClassExtension|get#property(#t57), n2) in let final void #t60 = self::ClassExtension|set#property(#t58, #t59) in #t59);
-  self::expect(n1, let final self::Class* #t61 = v in let final self::Class* #t62 = #t61 in let final self::Number* #t63 = self::NumberExtension|+(self::ClassExtension|get#property(#t61), n1) in let final void #t64 = self::ClassExtension|set#property(#t62, #t63) in #t63);
-  self::expect(n0, let final self::Class* #t65 = v in let final self::Class* #t66 = #t65 in let final self::Number* #t67 = self::NumberExtension|-(self::ClassExtension|get#property(#t65), n1) in let final void #t68 = self::ClassExtension|set#property(#t66, #t67) in #t67);
-  self::expect(n1, let final self::Class* #t69 = v in let final self::Class* #t70 = #t69 in let final self::Number* #t71 = self::NumberExtension|+(self::ClassExtension|get#property(#t69), 1) in let final void #t72 = self::ClassExtension|set#property(#t70, #t71) in #t71);
-  self::expect(n0, let final self::Class* #t73 = v in let final self::Class* #t74 = #t73 in let final self::Number* #t75 = self::NumberExtension|-(self::ClassExtension|get#property(#t73), 1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
-  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::ClassExtension|get#property(#t77) in let final self::Number* #t79 = self::ClassExtension|set#property(#t77, self::NumberExtension|+(#t78, 1)) in #t78);
-  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::ClassExtension|get#property(#t80) in let final self::Number* #t82 = self::ClassExtension|set#property(#t80, self::NumberExtension|-(#t81, 1)) in #t81);
+  self::expect(n1, let final self::Class* #t71 = v in let final self::Number* #t72 = self::NumberExtension|+(self::ClassExtension|get#property(#t71), n1) in let final void #t73 = self::ClassExtension|set#property(#t71, #t72) in #t72);
+  self::expect(n2, let final self::Class* #t74 = v in let final self::Number* #t75 = self::NumberExtension|+(self::ClassExtension|get#property(#t74), n1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
+  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::NumberExtension|-(self::ClassExtension|get#property(#t77), n2) in let final void #t79 = self::ClassExtension|set#property(#t77, #t78) in #t78);
+  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::NumberExtension|+(self::ClassExtension|get#property(#t80), n1) in let final void #t82 = self::ClassExtension|set#property(#t80, #t81) in #t81);
+  self::expect(n0, let final self::Class* #t83 = v in let final self::Number* #t84 = self::NumberExtension|-(self::ClassExtension|get#property(#t83), n1) in let final void #t85 = self::ClassExtension|set#property(#t83, #t84) in #t84);
+  self::expect(n1, let final self::Class* #t86 = v in let final self::Number* #t87 = self::NumberExtension|+(self::ClassExtension|get#property(#t86), 1) in let final void #t88 = self::ClassExtension|set#property(#t86, #t87) in #t87);
+  self::expect(n0, let final self::Class* #t89 = v in let final self::Number* #t90 = self::NumberExtension|-(self::ClassExtension|get#property(#t89), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90);
+  self::expect(n0, let final self::Class* #t92 = v in let final self::Number* #t93 = self::ClassExtension|get#property(#t92) in let final self::Number* #t94 = self::ClassExtension|set#property(#t92, self::NumberExtension|+(#t93, 1)) in #t93);
+  self::expect(n1, let final self::Class* #t95 = v in let final self::Number* #t96 = self::ClassExtension|get#property(#t95) in let final self::Number* #t97 = self::ClassExtension|set#property(#t95, self::NumberExtension|-(#t96, 1)) in #t96);
   self::expect(n0, self::ClassExtension|get#property(v));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t83 = v in self::ClassExtension|set#property(#t83, self::NumberExtension|+(self::ClassExtension|get#property(#t83), n1));
+  let final self::Class* #t98 = v in self::ClassExtension|set#property(#t98, self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t84 = v in self::ClassExtension|set#property(#t84, self::NumberExtension|+(self::ClassExtension|get#property(#t84), n1));
+  let final self::Class* #t99 = v in self::ClassExtension|set#property(#t99, self::NumberExtension|+(self::ClassExtension|get#property(#t99), n1));
   self::expect(n2, self::ClassExtension|get#property(v));
-  let final self::Class* #t85 = v in self::ClassExtension|set#property(#t85, self::NumberExtension|-(self::ClassExtension|get#property(#t85), n2));
+  let final self::Class* #t100 = v in self::ClassExtension|set#property(#t100, self::NumberExtension|-(self::ClassExtension|get#property(#t100), n2));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t86 = v in self::ClassExtension|set#property(#t86, self::NumberExtension|+(self::ClassExtension|get#property(#t86), n1));
+  let final self::Class* #t101 = v in self::ClassExtension|set#property(#t101, self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t87 = v in self::ClassExtension|set#property(#t87, self::NumberExtension|-(self::ClassExtension|get#property(#t87), n1));
+  let final self::Class* #t102 = v in self::ClassExtension|set#property(#t102, self::NumberExtension|-(self::ClassExtension|get#property(#t102), n1));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t88 = v in let final self::Class* #t89 = #t88 in let final self::Number* #t90 = self::NumberExtension|+(self::ClassExtension|get#property(#t88), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90;
+  let final self::Class* #t103 = v in let final self::Number* #t104 = self::NumberExtension|+(self::ClassExtension|get#property(#t103), 1) in let final void #t105 = self::ClassExtension|set#property(#t103, #t104) in #t104;
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t92 = v in let final self::Class* #t93 = #t92 in let final self::Number* #t94 = self::NumberExtension|-(self::ClassExtension|get#property(#t92), 1) in let final void #t95 = self::ClassExtension|set#property(#t93, #t94) in #t94;
+  let final self::Class* #t106 = v in let final self::Number* #t107 = self::NumberExtension|-(self::ClassExtension|get#property(#t106), 1) in let final void #t108 = self::ClassExtension|set#property(#t106, #t107) in #t107;
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t96 = v in self::ClassExtension|set#property(#t96, self::NumberExtension|+(self::ClassExtension|get#property(#t96), 1));
+  let final self::Class* #t109 = v in self::ClassExtension|set#property(#t109, self::NumberExtension|+(self::ClassExtension|get#property(#t109), 1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t97 = v in self::ClassExtension|set#property(#t97, self::NumberExtension|-(self::ClassExtension|get#property(#t97), 1));
+  let final self::Class* #t110 = v in self::ClassExtension|set#property(#t110, self::NumberExtension|-(self::ClassExtension|get#property(#t110), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
+static method testIntProperties() → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::IntClass* v = new self::IntClass::•(n0);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n1, let final self::IntClass* #t111 = v in #t111.{self::IntClass::field} = #t111.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n2, let final self::IntClass* #t112 = v in #t112.{self::IntClass::field} = #t112.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n0, let final self::IntClass* #t113 = v in #t113.{self::IntClass::field} = #t113.{self::IntClass::field}.{core::num::-}(n2));
+  self::expect(n1, let final self::IntClass* #t114 = v in #t114.{self::IntClass::field} = #t114.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n0, let final self::IntClass* #t115 = v in #t115.{self::IntClass::field} = #t115.{self::IntClass::field}.{core::num::-}(n1));
+  self::expect(n1, let final self::IntClass* #t116 = v in #t116.{self::IntClass::field} = #t116.{self::IntClass::field}.{core::num::+}(1));
+  self::expect(n0, let final self::IntClass* #t117 = v in #t117.{self::IntClass::field} = #t117.{self::IntClass::field}.{core::num::-}(1));
+  self::expect(n0, let final self::IntClass* #t118 = v in let final core::int* #t119 = #t118.{self::IntClass::field} in let final core::int* #t120 = #t118.{self::IntClass::field} = #t119.{core::num::+}(1) in #t119);
+  self::expect(n1, let final self::IntClass* #t121 = v in let final core::int* #t122 = #t121.{self::IntClass::field} in let final core::int* #t123 = #t121.{self::IntClass::field} = #t122.{core::num::-}(1) in #t122);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t124 = v in #t124.{self::IntClass::field} = #t124.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t125 = v in #t125.{self::IntClass::field} = #t125.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n2, v.{self::IntClass::field});
+  let final self::IntClass* #t126 = v in #t126.{self::IntClass::field} = #t126.{self::IntClass::field}.{core::num::-}(n2);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t127 = v in #t127.{self::IntClass::field} = #t127.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t128 = v in #t128.{self::IntClass::field} = #t128.{self::IntClass::field}.{core::num::-}(n1);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t129 = v in #t129.{self::IntClass::field} = #t129.{self::IntClass::field}.{core::num::+}(1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t130 = v in #t130.{self::IntClass::field} = #t130.{self::IntClass::field}.{core::num::-}(1);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t131 = v in #t131.{self::IntClass::field} = #t131.{self::IntClass::field}.{core::num::+}(1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t132 = v in #t132.{self::IntClass::field} = #t132.{self::IntClass::field}.{core::num::-}(1);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n1, let final self::IntClass* #t133 = v in let final core::int* #t134 = self::IntClassExtension|get#property(#t133).{core::num::+}(n1) in let final void #t135 = self::IntClassExtension|set#property(#t133, #t134) in #t134);
+  self::expect(n2, let final self::IntClass* #t136 = v in let final core::int* #t137 = self::IntClassExtension|get#property(#t136).{core::num::+}(n1) in let final void #t138 = self::IntClassExtension|set#property(#t136, #t137) in #t137);
+  self::expect(n0, let final self::IntClass* #t139 = v in let final core::int* #t140 = self::IntClassExtension|get#property(#t139).{core::num::-}(n2) in let final void #t141 = self::IntClassExtension|set#property(#t139, #t140) in #t140);
+  self::expect(n1, let final self::IntClass* #t142 = v in let final core::int* #t143 = self::IntClassExtension|get#property(#t142).{core::num::+}(n1) in let final void #t144 = self::IntClassExtension|set#property(#t142, #t143) in #t143);
+  self::expect(n0, let final self::IntClass* #t145 = v in let final core::int* #t146 = self::IntClassExtension|get#property(#t145).{core::num::-}(n1) in let final void #t147 = self::IntClassExtension|set#property(#t145, #t146) in #t146);
+  self::expect(n1, let final self::IntClass* #t148 = v in let final core::int* #t149 = self::IntClassExtension|get#property(#t148).{core::num::+}(1) in let final void #t150 = self::IntClassExtension|set#property(#t148, #t149) in #t149);
+  self::expect(n0, let final self::IntClass* #t151 = v in let final core::int* #t152 = self::IntClassExtension|get#property(#t151).{core::num::-}(1) in let final void #t153 = self::IntClassExtension|set#property(#t151, #t152) in #t152);
+  self::expect(n0, let final self::IntClass* #t154 = v in let final core::int* #t155 = self::IntClassExtension|get#property(#t154) in let final core::int* #t156 = self::IntClassExtension|set#property(#t154, #t155.{core::num::+}(1)) in #t155);
+  self::expect(n1, let final self::IntClass* #t157 = v in let final core::int* #t158 = self::IntClassExtension|get#property(#t157) in let final core::int* #t159 = self::IntClassExtension|set#property(#t157, #t158.{core::num::-}(1)) in #t158);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t160 = v in self::IntClassExtension|set#property(#t160, self::IntClassExtension|get#property(#t160).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t161 = v in self::IntClassExtension|set#property(#t161, self::IntClassExtension|get#property(#t161).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t162 = v in self::IntClassExtension|set#property(#t162, self::IntClassExtension|get#property(#t162).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t163 = v in self::IntClassExtension|set#property(#t163, self::IntClassExtension|get#property(#t163).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t164 = v in self::IntClassExtension|set#property(#t164, self::IntClassExtension|get#property(#t164).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t165 = v in let final core::int* #t166 = self::IntClassExtension|get#property(#t165).{core::num::+}(1) in let final void #t167 = self::IntClassExtension|set#property(#t165, #t166) in #t166;
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t168 = v in let final core::int* #t169 = self::IntClassExtension|get#property(#t168).{core::num::-}(1) in let final void #t170 = self::IntClassExtension|set#property(#t168, #t169) in #t169;
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t171 = v in self::IntClassExtension|set#property(#t171, self::IntClassExtension|get#property(#t171).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t172 = v in self::IntClassExtension|set#property(#t172, self::IntClassExtension|get#property(#t172).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+}
 static method testExplicitProperties() → dynamic {
   self::Number* n0 = new self::Number::•(0);
   self::Number* n1 = new self::Number::•(1);
   self::Number* n2 = new self::Number::•(2);
   self::Class* v = new self::Class::•(n0);
   self::expect(n0, self::ClassExtension|get#property(v));
-  self::expect(n1, let final self::Class* #t98 = v in let final self::Number* #t99 = self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1) in let final void #t100 = self::ClassExtension|set#property(#t98, #t99) in #t99);
-  self::expect(n2, let final self::Class* #t101 = v in let final self::Number* #t102 = self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1) in let final void #t103 = self::ClassExtension|set#property(#t101, #t102) in #t102);
-  self::expect(n0, let final self::Class* #t104 = v in let final self::Number* #t105 = self::NumberExtension|-(self::ClassExtension|get#property(#t104), n2) in let final void #t106 = self::ClassExtension|set#property(#t104, #t105) in #t105);
-  self::expect(n1, let final self::Class* #t107 = v in let final self::Number* #t108 = self::NumberExtension|+(self::ClassExtension|get#property(#t107), n1) in let final void #t109 = self::ClassExtension|set#property(#t107, #t108) in #t108);
-  self::expect(n0, let final self::Class* #t110 = v in let final self::Number* #t111 = self::NumberExtension|-(self::ClassExtension|get#property(#t110), n1) in let final void #t112 = self::ClassExtension|set#property(#t110, #t111) in #t111);
-  self::expect(n1, let final self::Class* #t113 = v in let final self::Number* #t114 = self::NumberExtension|+(self::ClassExtension|get#property(#t113), 1) in let final void #t115 = self::ClassExtension|set#property(#t113, #t114) in #t114);
-  self::expect(n0, let final self::Class* #t116 = v in let final self::Number* #t117 = self::NumberExtension|-(self::ClassExtension|get#property(#t116), 1) in let final void #t118 = self::ClassExtension|set#property(#t116, #t117) in #t117);
-  self::expect(n0, let final self::Class* #t119 = v in let final self::Number* #t120 = self::ClassExtension|get#property(#t119) in let final self::Number* #t121 = let final self::Number* #t122 = self::NumberExtension|+(#t120, 1) in let final void #t123 = self::ClassExtension|set#property(#t119, #t122) in #t122 in #t120);
-  self::expect(n1, let final self::Class* #t124 = v in let final self::Number* #t125 = self::ClassExtension|get#property(#t124) in let final self::Number* #t126 = let final self::Number* #t127 = self::NumberExtension|-(#t125, 1) in let final void #t128 = self::ClassExtension|set#property(#t124, #t127) in #t127 in #t125);
+  self::expect(n1, let final self::Class* #t173 = v in let final self::Number* #t174 = self::NumberExtension|+(self::ClassExtension|get#property(#t173), n1) in let final void #t175 = self::ClassExtension|set#property(#t173, #t174) in #t174);
+  self::expect(n2, let final self::Class* #t176 = v in let final self::Number* #t177 = self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1) in let final void #t178 = self::ClassExtension|set#property(#t176, #t177) in #t177);
+  self::expect(n0, let final self::Class* #t179 = v in let final self::Number* #t180 = self::NumberExtension|-(self::ClassExtension|get#property(#t179), n2) in let final void #t181 = self::ClassExtension|set#property(#t179, #t180) in #t180);
+  self::expect(n1, let final self::Class* #t182 = v in let final self::Number* #t183 = self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1) in let final void #t184 = self::ClassExtension|set#property(#t182, #t183) in #t183);
+  self::expect(n0, let final self::Class* #t185 = v in let final self::Number* #t186 = self::NumberExtension|-(self::ClassExtension|get#property(#t185), n1) in let final void #t187 = self::ClassExtension|set#property(#t185, #t186) in #t186);
+  self::expect(n1, let final self::Class* #t188 = v in let final self::Number* #t189 = self::NumberExtension|+(self::ClassExtension|get#property(#t188), 1) in let final void #t190 = self::ClassExtension|set#property(#t188, #t189) in #t189);
+  self::expect(n0, let final self::Class* #t191 = v in let final self::Number* #t192 = self::NumberExtension|-(self::ClassExtension|get#property(#t191), 1) in let final void #t193 = self::ClassExtension|set#property(#t191, #t192) in #t192);
+  self::expect(n0, let final self::Class* #t194 = v in let final self::Number* #t195 = self::ClassExtension|get#property(#t194) in let final self::Number* #t196 = let final self::Number* #t197 = self::NumberExtension|+(#t195, 1) in let final void #t198 = self::ClassExtension|set#property(#t194, #t197) in #t197 in #t195);
+  self::expect(n1, let final self::Class* #t199 = v in let final self::Number* #t200 = self::ClassExtension|get#property(#t199) in let final self::Number* #t201 = let final self::Number* #t202 = self::NumberExtension|-(#t200, 1) in let final void #t203 = self::ClassExtension|set#property(#t199, #t202) in #t202 in #t200);
   self::expect(n0, self::ClassExtension|get#property(v));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t129 = v in self::ClassExtension|set#property(#t129, self::NumberExtension|+(self::ClassExtension|get#property(#t129), n1));
+  let final self::Class* #t204 = v in self::ClassExtension|set#property(#t204, self::NumberExtension|+(self::ClassExtension|get#property(#t204), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t130 = v in self::ClassExtension|set#property(#t130, self::NumberExtension|+(self::ClassExtension|get#property(#t130), n1));
+  let final self::Class* #t205 = v in self::ClassExtension|set#property(#t205, self::NumberExtension|+(self::ClassExtension|get#property(#t205), n1));
   self::expect(n2, self::ClassExtension|get#property(v));
-  let final self::Class* #t131 = v in self::ClassExtension|set#property(#t131, self::NumberExtension|-(self::ClassExtension|get#property(#t131), n2));
+  let final self::Class* #t206 = v in self::ClassExtension|set#property(#t206, self::NumberExtension|-(self::ClassExtension|get#property(#t206), n2));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t132 = v in self::ClassExtension|set#property(#t132, self::NumberExtension|+(self::ClassExtension|get#property(#t132), n1));
+  let final self::Class* #t207 = v in self::ClassExtension|set#property(#t207, self::NumberExtension|+(self::ClassExtension|get#property(#t207), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t133 = v in self::ClassExtension|set#property(#t133, self::NumberExtension|-(self::ClassExtension|get#property(#t133), n1));
+  let final self::Class* #t208 = v in self::ClassExtension|set#property(#t208, self::NumberExtension|-(self::ClassExtension|get#property(#t208), n1));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t134 = v in let final self::Number* #t135 = self::NumberExtension|+(self::ClassExtension|get#property(#t134), 1) in let final void #t136 = self::ClassExtension|set#property(#t134, #t135) in #t135;
+  let final self::Class* #t209 = v in let final self::Number* #t210 = self::NumberExtension|+(self::ClassExtension|get#property(#t209), 1) in let final void #t211 = self::ClassExtension|set#property(#t209, #t210) in #t210;
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t137 = v in let final self::Number* #t138 = self::NumberExtension|-(self::ClassExtension|get#property(#t137), 1) in let final void #t139 = self::ClassExtension|set#property(#t137, #t138) in #t138;
+  let final self::Class* #t212 = v in let final self::Number* #t213 = self::NumberExtension|-(self::ClassExtension|get#property(#t212), 1) in let final void #t214 = self::ClassExtension|set#property(#t212, #t213) in #t213;
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t140 = v in self::ClassExtension|set#property(#t140, self::NumberExtension|+(self::ClassExtension|get#property(#t140), 1));
+  let final self::Class* #t215 = v in self::ClassExtension|set#property(#t215, self::NumberExtension|+(self::ClassExtension|get#property(#t215), 1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t141 = v in self::ClassExtension|set#property(#t141, self::NumberExtension|-(self::ClassExtension|get#property(#t141), 1));
+  let final self::Class* #t216 = v in self::ClassExtension|set#property(#t216, self::NumberExtension|-(self::ClassExtension|get#property(#t216), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
+static method testExplicitIntProperties() → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::IntClass* v = new self::IntClass::•(n0);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n1, let final self::IntClass* #t217 = v in let final core::int* #t218 = self::IntClassExtension|get#property(#t217).{core::num::+}(n1) in let final void #t219 = self::IntClassExtension|set#property(#t217, #t218) in #t218);
+  self::expect(n2, let final self::IntClass* #t220 = v in let final core::int* #t221 = self::IntClassExtension|get#property(#t220).{core::num::+}(n1) in let final void #t222 = self::IntClassExtension|set#property(#t220, #t221) in #t221);
+  self::expect(n0, let final self::IntClass* #t223 = v in let final core::int* #t224 = self::IntClassExtension|get#property(#t223).{core::num::-}(n2) in let final void #t225 = self::IntClassExtension|set#property(#t223, #t224) in #t224);
+  self::expect(n1, let final self::IntClass* #t226 = v in let final core::int* #t227 = self::IntClassExtension|get#property(#t226).{core::num::+}(n1) in let final void #t228 = self::IntClassExtension|set#property(#t226, #t227) in #t227);
+  self::expect(n0, let final self::IntClass* #t229 = v in let final core::int* #t230 = self::IntClassExtension|get#property(#t229).{core::num::-}(n1) in let final void #t231 = self::IntClassExtension|set#property(#t229, #t230) in #t230);
+  self::expect(n1, let final self::IntClass* #t232 = v in let final core::int* #t233 = self::IntClassExtension|get#property(#t232).{core::num::+}(1) in let final void #t234 = self::IntClassExtension|set#property(#t232, #t233) in #t233);
+  self::expect(n0, let final self::IntClass* #t235 = v in let final core::int* #t236 = self::IntClassExtension|get#property(#t235).{core::num::-}(1) in let final void #t237 = self::IntClassExtension|set#property(#t235, #t236) in #t236);
+  self::expect(n0, let final self::IntClass* #t238 = v in let final core::int* #t239 = self::IntClassExtension|get#property(#t238) in let final core::int* #t240 = let final core::int* #t241 = #t239.{core::num::+}(1) in let final void #t242 = self::IntClassExtension|set#property(#t238, #t241) in #t241 in #t239);
+  self::expect(n1, let final self::IntClass* #t243 = v in let final core::int* #t244 = self::IntClassExtension|get#property(#t243) in let final core::int* #t245 = let final core::int* #t246 = #t244.{core::num::-}(1) in let final void #t247 = self::IntClassExtension|set#property(#t243, #t246) in #t246 in #t244);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t248 = v in self::IntClassExtension|set#property(#t248, self::IntClassExtension|get#property(#t248).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t249 = v in self::IntClassExtension|set#property(#t249, self::IntClassExtension|get#property(#t249).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t250 = v in self::IntClassExtension|set#property(#t250, self::IntClassExtension|get#property(#t250).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t251 = v in self::IntClassExtension|set#property(#t251, self::IntClassExtension|get#property(#t251).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t252 = v in self::IntClassExtension|set#property(#t252, self::IntClassExtension|get#property(#t252).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t253 = v in let final core::int* #t254 = self::IntClassExtension|get#property(#t253).{core::num::+}(1) in let final void #t255 = self::IntClassExtension|set#property(#t253, #t254) in #t254;
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t256 = v in let final core::int* #t257 = self::IntClassExtension|get#property(#t256).{core::num::-}(1) in let final void #t258 = self::IntClassExtension|set#property(#t256, #t257) in #t257;
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t259 = v in self::IntClassExtension|set#property(#t259, self::IntClassExtension|get#property(#t259).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t260 = v in self::IntClassExtension|set#property(#t260, self::IntClassExtension|get#property(#t260).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+}
 static method testExplicitNullAwareProperties(self::Class* v) → dynamic {
   self::Number* n0 = new self::Number::•(0);
   self::Number* n1 = new self::Number::•(1);
   self::Number* n2 = new self::Number::•(2);
-  self::expect(n0, let final self::Class* #t142 = v in #t142.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t142), v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t143 = v in #t143.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t144 = self::NumberExtension|+(self::ClassExtension|get#property(#t143), n1) in let final void #t145 = self::ClassExtension|set#property(#t143, #t144) in #t144, v.{core::Object::==}(null));
-  self::expect(n2, let final self::Class* #t146 = v in #t146.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t147 = self::NumberExtension|+(self::ClassExtension|get#property(#t146), n1) in let final void #t148 = self::ClassExtension|set#property(#t146, #t147) in #t147, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t149 = v in #t149.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t150 = self::NumberExtension|-(self::ClassExtension|get#property(#t149), n2) in let final void #t151 = self::ClassExtension|set#property(#t149, #t150) in #t150, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t152 = v in #t152.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t153 = self::NumberExtension|+(self::ClassExtension|get#property(#t152), n1) in let final void #t154 = self::ClassExtension|set#property(#t152, #t153) in #t153, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t155 = v in #t155.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t156 = self::NumberExtension|-(self::ClassExtension|get#property(#t155), n1) in let final void #t157 = self::ClassExtension|set#property(#t155, #t156) in #t156, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t158 = v in #t158.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t159 = self::NumberExtension|+(self::ClassExtension|get#property(#t158), 1) in let final void #t160 = self::ClassExtension|set#property(#t158, #t159) in #t159, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t161 = v in #t161.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t162 = self::NumberExtension|-(self::ClassExtension|get#property(#t161), 1) in let final void #t163 = self::ClassExtension|set#property(#t161, #t162) in #t162, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t164 = v in #t164.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t165 = self::ClassExtension|get#property(#t164) in let final self::Number* #t166 = let final self::Number* #t167 = self::NumberExtension|+(#t165, 1) in let final void #t168 = self::ClassExtension|set#property(#t164, #t167) in #t167 in #t165, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t169 = v in #t169.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t170 = self::ClassExtension|get#property(#t169) in let final self::Number* #t171 = let final self::Number* #t172 = self::NumberExtension|-(#t170, 1) in let final void #t173 = self::ClassExtension|set#property(#t169, #t172) in #t172 in #t170, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t174 = v in #t174.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t174), v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t175 = v in #t175.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t175), v.{core::Object::==}(null));
-  let final self::Class* #t176 = v in #t176.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t176, self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1));
-  self::expect(n1, let final self::Class* #t177 = v in #t177.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t177), v.{core::Object::==}(null));
-  let final self::Class* #t178 = v in #t178.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t178, self::NumberExtension|+(self::ClassExtension|get#property(#t178), n1));
-  self::expect(n2, let final self::Class* #t179 = v in #t179.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t179), v.{core::Object::==}(null));
-  let final self::Class* #t180 = v in #t180.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t180, self::NumberExtension|-(self::ClassExtension|get#property(#t180), n2));
-  self::expect(n0, let final self::Class* #t181 = v in #t181.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t181), v.{core::Object::==}(null));
-  let final self::Class* #t182 = v in #t182.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t182, self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1));
-  self::expect(n1, let final self::Class* #t183 = v in #t183.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t183), v.{core::Object::==}(null));
-  let final self::Class* #t184 = v in #t184.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t184, self::NumberExtension|-(self::ClassExtension|get#property(#t184), n1));
-  self::expect(n0, let final self::Class* #t185 = v in #t185.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t185), v.{core::Object::==}(null));
-  let final self::Class* #t186 = v in #t186.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t187 = self::NumberExtension|+(self::ClassExtension|get#property(#t186), 1) in let final void #t188 = self::ClassExtension|set#property(#t186, #t187) in #t187;
-  self::expect(n1, let final self::Class* #t189 = v in #t189.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t189), v.{core::Object::==}(null));
-  let final self::Class* #t190 = v in #t190.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t191 = self::NumberExtension|-(self::ClassExtension|get#property(#t190), 1) in let final void #t192 = self::ClassExtension|set#property(#t190, #t191) in #t191;
-  self::expect(n0, let final self::Class* #t193 = v in #t193.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t193), v.{core::Object::==}(null));
-  let final self::Class* #t194 = v in #t194.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t194, self::NumberExtension|+(self::ClassExtension|get#property(#t194), 1));
-  self::expect(n1, let final self::Class* #t195 = v in #t195.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t195), v.{core::Object::==}(null));
-  let final self::Class* #t196 = v in #t196.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t196, self::NumberExtension|-(self::ClassExtension|get#property(#t196), 1));
-  self::expect(n0, let final self::Class* #t197 = v in #t197.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t197), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t261 = v in #t261.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t261), v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t262 = v in #t262.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t263 = self::NumberExtension|+(self::ClassExtension|get#property(#t262), n1) in let final void #t264 = self::ClassExtension|set#property(#t262, #t263) in #t263, v.{core::Object::==}(null));
+  self::expect(n2, let final self::Class* #t265 = v in #t265.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t266 = self::NumberExtension|+(self::ClassExtension|get#property(#t265), n1) in let final void #t267 = self::ClassExtension|set#property(#t265, #t266) in #t266, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t268 = v in #t268.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t269 = self::NumberExtension|-(self::ClassExtension|get#property(#t268), n2) in let final void #t270 = self::ClassExtension|set#property(#t268, #t269) in #t269, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t271 = v in #t271.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t272 = self::NumberExtension|+(self::ClassExtension|get#property(#t271), n1) in let final void #t273 = self::ClassExtension|set#property(#t271, #t272) in #t272, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t274 = v in #t274.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t275 = self::NumberExtension|-(self::ClassExtension|get#property(#t274), n1) in let final void #t276 = self::ClassExtension|set#property(#t274, #t275) in #t275, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t277 = v in #t277.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t278 = self::NumberExtension|+(self::ClassExtension|get#property(#t277), 1) in let final void #t279 = self::ClassExtension|set#property(#t277, #t278) in #t278, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t280 = v in #t280.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t281 = self::NumberExtension|-(self::ClassExtension|get#property(#t280), 1) in let final void #t282 = self::ClassExtension|set#property(#t280, #t281) in #t281, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t283 = v in #t283.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t284 = self::ClassExtension|get#property(#t283) in let final self::Number* #t285 = let final self::Number* #t286 = self::NumberExtension|+(#t284, 1) in let final void #t287 = self::ClassExtension|set#property(#t283, #t286) in #t286 in #t284, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t288 = v in #t288.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t289 = self::ClassExtension|get#property(#t288) in let final self::Number* #t290 = let final self::Number* #t291 = self::NumberExtension|-(#t289, 1) in let final void #t292 = self::ClassExtension|set#property(#t288, #t291) in #t291 in #t289, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t293 = v in #t293.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t293), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t294 = v in #t294.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t294), v.{core::Object::==}(null));
+  let final self::Class* #t295 = v in #t295.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t295, self::NumberExtension|+(self::ClassExtension|get#property(#t295), n1));
+  self::expect(n1, let final self::Class* #t296 = v in #t296.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t296), v.{core::Object::==}(null));
+  let final self::Class* #t297 = v in #t297.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t297, self::NumberExtension|+(self::ClassExtension|get#property(#t297), n1));
+  self::expect(n2, let final self::Class* #t298 = v in #t298.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t298), v.{core::Object::==}(null));
+  let final self::Class* #t299 = v in #t299.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t299, self::NumberExtension|-(self::ClassExtension|get#property(#t299), n2));
+  self::expect(n0, let final self::Class* #t300 = v in #t300.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t300), v.{core::Object::==}(null));
+  let final self::Class* #t301 = v in #t301.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t301, self::NumberExtension|+(self::ClassExtension|get#property(#t301), n1));
+  self::expect(n1, let final self::Class* #t302 = v in #t302.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t302), v.{core::Object::==}(null));
+  let final self::Class* #t303 = v in #t303.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t303, self::NumberExtension|-(self::ClassExtension|get#property(#t303), n1));
+  self::expect(n0, let final self::Class* #t304 = v in #t304.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t304), v.{core::Object::==}(null));
+  let final self::Class* #t305 = v in #t305.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t306 = self::NumberExtension|+(self::ClassExtension|get#property(#t305), 1) in let final void #t307 = self::ClassExtension|set#property(#t305, #t306) in #t306;
+  self::expect(n1, let final self::Class* #t308 = v in #t308.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t308), v.{core::Object::==}(null));
+  let final self::Class* #t309 = v in #t309.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t310 = self::NumberExtension|-(self::ClassExtension|get#property(#t309), 1) in let final void #t311 = self::ClassExtension|set#property(#t309, #t310) in #t310;
+  self::expect(n0, let final self::Class* #t312 = v in #t312.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t312), v.{core::Object::==}(null));
+  let final self::Class* #t313 = v in #t313.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t313, self::NumberExtension|+(self::ClassExtension|get#property(#t313), 1));
+  self::expect(n1, let final self::Class* #t314 = v in #t314.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t314), v.{core::Object::==}(null));
+  let final self::Class* #t315 = v in #t315.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t315, self::NumberExtension|-(self::ClassExtension|get#property(#t315), 1));
+  self::expect(n0, let final self::Class* #t316 = v in #t316.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t316), v.{core::Object::==}(null));
+}
+static method testExplicitNullAwareIntProperties(self::IntClass* v) → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::expect(n0, let final self::IntClass* #t317 = v in #t317.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t317), v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t318 = v in #t318.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t319 = self::IntClassExtension|get#property(#t318).{core::num::+}(n1) in let final void #t320 = self::IntClassExtension|set#property(#t318, #t319) in #t319, v.{core::Object::==}(null));
+  self::expect(n2, let final self::IntClass* #t321 = v in #t321.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t322 = self::IntClassExtension|get#property(#t321).{core::num::+}(n1) in let final void #t323 = self::IntClassExtension|set#property(#t321, #t322) in #t322, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t324 = v in #t324.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t325 = self::IntClassExtension|get#property(#t324).{core::num::-}(n2) in let final void #t326 = self::IntClassExtension|set#property(#t324, #t325) in #t325, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t327 = v in #t327.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t328 = self::IntClassExtension|get#property(#t327).{core::num::+}(n1) in let final void #t329 = self::IntClassExtension|set#property(#t327, #t328) in #t328, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t330 = v in #t330.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t331 = self::IntClassExtension|get#property(#t330).{core::num::-}(n1) in let final void #t332 = self::IntClassExtension|set#property(#t330, #t331) in #t331, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t333 = v in #t333.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t334 = self::IntClassExtension|get#property(#t333).{core::num::+}(1) in let final void #t335 = self::IntClassExtension|set#property(#t333, #t334) in #t334, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t336 = v in #t336.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t337 = self::IntClassExtension|get#property(#t336).{core::num::-}(1) in let final void #t338 = self::IntClassExtension|set#property(#t336, #t337) in #t337, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t339 = v in #t339.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t340 = self::IntClassExtension|get#property(#t339) in let final core::int* #t341 = let final core::int* #t342 = #t340.{core::num::+}(1) in let final void #t343 = self::IntClassExtension|set#property(#t339, #t342) in #t342 in #t340, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t344 = v in #t344.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t345 = self::IntClassExtension|get#property(#t344) in let final core::int* #t346 = let final core::int* #t347 = #t345.{core::num::-}(1) in let final void #t348 = self::IntClassExtension|set#property(#t344, #t347) in #t347 in #t345, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t349 = v in #t349.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t349), v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t350 = v in #t350.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t350), v.{core::Object::==}(null));
+  let final self::IntClass* #t351 = v in #t351.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t351, self::IntClassExtension|get#property(#t351).{core::num::+}(n1));
+  self::expect(n1, let final self::IntClass* #t352 = v in #t352.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t352), v.{core::Object::==}(null));
+  let final self::IntClass* #t353 = v in #t353.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t353, self::IntClassExtension|get#property(#t353).{core::num::+}(n1));
+  self::expect(n2, let final self::IntClass* #t354 = v in #t354.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t354), v.{core::Object::==}(null));
+  let final self::IntClass* #t355 = v in #t355.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t355, self::IntClassExtension|get#property(#t355).{core::num::-}(n2));
+  self::expect(n0, let final self::IntClass* #t356 = v in #t356.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t356), v.{core::Object::==}(null));
+  let final self::IntClass* #t357 = v in #t357.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t357, self::IntClassExtension|get#property(#t357).{core::num::+}(n1));
+  self::expect(n1, let final self::IntClass* #t358 = v in #t358.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t358), v.{core::Object::==}(null));
+  let final self::IntClass* #t359 = v in #t359.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t359, self::IntClassExtension|get#property(#t359).{core::num::-}(n1));
+  self::expect(n0, let final self::IntClass* #t360 = v in #t360.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t360), v.{core::Object::==}(null));
+  let final self::IntClass* #t361 = v in #t361.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t362 = self::IntClassExtension|get#property(#t361).{core::num::+}(1) in let final void #t363 = self::IntClassExtension|set#property(#t361, #t362) in #t362;
+  self::expect(n1, let final self::IntClass* #t364 = v in #t364.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t364), v.{core::Object::==}(null));
+  let final self::IntClass* #t365 = v in #t365.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t366 = self::IntClassExtension|get#property(#t365).{core::num::-}(1) in let final void #t367 = self::IntClassExtension|set#property(#t365, #t366) in #t366;
+  self::expect(n0, let final self::IntClass* #t368 = v in #t368.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t368), v.{core::Object::==}(null));
+  let final self::IntClass* #t369 = v in #t369.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t369, self::IntClassExtension|get#property(#t369).{core::num::+}(1));
+  self::expect(n1, let final self::IntClass* #t370 = v in #t370.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t370), v.{core::Object::==}(null));
+  let final self::IntClass* #t371 = v in #t371.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t371, self::IntClassExtension|get#property(#t371).{core::num::-}(1));
+  self::expect(n0, let final self::IntClass* #t372 = v in #t372.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t372), v.{core::Object::==}(null));
 }
 static method expect(dynamic expected, dynamic actual, [dynamic expectNull = #C1]) → dynamic {
   if(expectNull as{TypeError} core::bool*) {
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
index e0e9cdf..24d7f52 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.strong.transformed.expect
@@ -20,6 +20,12 @@
     : self::Class::field = field, super core::Object::•()
     ;
 }
+class IntClass extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::IntClass*
+    : self::IntClass::field = field, super core::Object::•()
+    ;
+}
 extension NumberExtension on self::Number* {
   operator + = self::NumberExtension|+;
   operator - = self::NumberExtension|-;
@@ -30,6 +36,12 @@
   tearoff testImplicitProperties = self::ClassExtension|get#testImplicitProperties;
   set property = self::ClassExtension|set#property;
 }
+extension IntClassExtension on self::IntClass* {
+  get property = self::IntClassExtension|get#property;
+  method testImplicitProperties = self::IntClassExtension|testImplicitProperties;
+  tearoff testImplicitProperties = self::IntClassExtension|get#testImplicitProperties;
+  set property = self::IntClassExtension|set#property;
+}
 static method NumberExtension|+(final self::Number* #this, core::Object* other) → self::Number* {
   if(other is core::int*) {
     return new self::Number::•(#this.{self::Number::value}.{core::num::+}(other{core::int*}));
@@ -96,13 +108,60 @@
 }
 static method ClassExtension|get#testImplicitProperties(final self::Class* #this) → () →* dynamic
   return () → dynamic => self::ClassExtension|testImplicitProperties(#this);
+static method IntClassExtension|get#property(final self::IntClass* #this) → core::int*
+  return #this.{self::IntClass::field};
+static method IntClassExtension|set#property(final self::IntClass* #this, core::int* value) → void {
+  #this.{self::IntClass::field} = value;
+}
+static method IntClassExtension|testImplicitProperties(final self::IntClass* #this) → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::expect(n1, let final core::int* #t23 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t24 = self::IntClassExtension|set#property(#this, #t23) in #t23);
+  self::expect(n2, let final core::int* #t25 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t26 = self::IntClassExtension|set#property(#this, #t25) in #t25);
+  self::expect(n0, let final core::int* #t27 = self::IntClassExtension|get#property(#this).{core::num::-}(n2) in let final void #t28 = self::IntClassExtension|set#property(#this, #t27) in #t27);
+  self::expect(n1, let final core::int* #t29 = self::IntClassExtension|get#property(#this).{core::num::+}(n1) in let final void #t30 = self::IntClassExtension|set#property(#this, #t29) in #t29);
+  self::expect(n0, let final core::int* #t31 = self::IntClassExtension|get#property(#this).{core::num::-}(n1) in let final void #t32 = self::IntClassExtension|set#property(#this, #t31) in #t31);
+  self::expect(n1, let final core::int* #t33 = self::IntClassExtension|get#property(#this).{core::num::+}(1) in let final void #t34 = self::IntClassExtension|set#property(#this, #t33) in #t33);
+  self::expect(n0, let final core::int* #t35 = self::IntClassExtension|get#property(#this).{core::num::-}(1) in let final void #t36 = self::IntClassExtension|set#property(#this, #t35) in #t35);
+  self::expect(n0, let final core::int* #t37 = self::IntClassExtension|get#property(#this) in let final core::int* #t38 = self::IntClassExtension|set#property(#this, #t37.{core::num::+}(1)) in #t37);
+  self::expect(n1, let final core::int* #t39 = self::IntClassExtension|get#property(#this) in let final core::int* #t40 = self::IntClassExtension|set#property(#this, #t39.{core::num::-}(1)) in #t39);
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  let final core::int* #t41 = self::IntClassExtension|get#property(#this).{core::num::+}(1) in let final void #t42 = self::IntClassExtension|set#property(#this, #t41) in #t41;
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  let final core::int* #t43 = self::IntClassExtension|get#property(#this).{core::num::-}(1) in let final void #t44 = self::IntClassExtension|set#property(#this, #t43) in #t43;
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(#this));
+  self::IntClassExtension|set#property(#this, self::IntClassExtension|get#property(#this).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(#this));
+}
+static method IntClassExtension|get#testImplicitProperties(final self::IntClass* #this) → () →* dynamic
+  return () → dynamic => self::IntClassExtension|testImplicitProperties(#this);
 static method main() → dynamic {
   self::testLocals();
   self::testProperties();
+  self::testIntProperties();
   self::testExplicitProperties();
+  self::testExplicitIntProperties();
   self::testExplicitNullAwareProperties(null);
   self::testExplicitNullAwareProperties(new self::Class::•(new self::Number::•(0)));
+  self::testExplicitNullAwareIntProperties(null);
+  self::testExplicitNullAwareIntProperties(new self::IntClass::•(0));
   self::ClassExtension|testImplicitProperties(new self::Class::•(new self::Number::•(0)));
+  self::IntClassExtension|testImplicitProperties(new self::IntClass::•(0));
 }
 static method testLocals() → dynamic {
   self::Number* n0 = new self::Number::•(0);
@@ -117,8 +176,8 @@
   self::expect(n0, v = self::NumberExtension|-(v, n1));
   self::expect(n1, v = self::NumberExtension|+(v, 1));
   self::expect(n0, v = self::NumberExtension|-(v, 1));
-  self::expect(n0, let final self::Number* #t23 = v in let final self::Number* #t24 = v = self::NumberExtension|+(#t23, 1) in #t23);
-  self::expect(n1, let final self::Number* #t25 = v in let final self::Number* #t26 = v = self::NumberExtension|-(#t25, 1) in #t25);
+  self::expect(n0, let final self::Number* #t45 = v in let final self::Number* #t46 = v = self::NumberExtension|+(#t45, 1) in #t45);
+  self::expect(n1, let final self::Number* #t47 = v in let final self::Number* #t48 = v = self::NumberExtension|-(#t47, 1) in #t47);
   self::expect(n0, v);
   self::expect(n0, v);
   v = self::NumberExtension|+(v, n1);
@@ -146,136 +205,273 @@
   self::Number* n2 = new self::Number::•(2);
   self::Class* v = new self::Class::•(n0);
   self::expect(n0, v.{self::Class::field});
-  self::expect(n1, let final self::Class* #t27 = v in #t27.{self::Class::field} = self::NumberExtension|+(#t27.{self::Class::field}, n1));
-  self::expect(n2, let final self::Class* #t28 = v in #t28.{self::Class::field} = self::NumberExtension|+(#t28.{self::Class::field}, n1));
-  self::expect(n0, let final self::Class* #t29 = v in #t29.{self::Class::field} = self::NumberExtension|-(#t29.{self::Class::field}, n2));
-  self::expect(n1, let final self::Class* #t30 = v in #t30.{self::Class::field} = self::NumberExtension|+(#t30.{self::Class::field}, n1));
-  self::expect(n0, let final self::Class* #t31 = v in #t31.{self::Class::field} = self::NumberExtension|-(#t31.{self::Class::field}, n1));
-  self::expect(n1, let final self::Class* #t32 = v in #t32.{self::Class::field} = self::NumberExtension|+(#t32.{self::Class::field}, 1));
-  self::expect(n0, let final self::Class* #t33 = v in #t33.{self::Class::field} = self::NumberExtension|-(#t33.{self::Class::field}, 1));
-  self::expect(n0, let final self::Class* #t34 = v in let final self::Number* #t35 = #t34.{self::Class::field} in let final self::Number* #t36 = #t34.{self::Class::field} = self::NumberExtension|+(#t35, 1) in #t35);
-  self::expect(n1, let final self::Class* #t37 = v in let final self::Number* #t38 = #t37.{self::Class::field} in let final self::Number* #t39 = #t37.{self::Class::field} = self::NumberExtension|-(#t38, 1) in #t38);
+  self::expect(n1, let final self::Class* #t49 = v in #t49.{self::Class::field} = self::NumberExtension|+(#t49.{self::Class::field}, n1));
+  self::expect(n2, let final self::Class* #t50 = v in #t50.{self::Class::field} = self::NumberExtension|+(#t50.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t51 = v in #t51.{self::Class::field} = self::NumberExtension|-(#t51.{self::Class::field}, n2));
+  self::expect(n1, let final self::Class* #t52 = v in #t52.{self::Class::field} = self::NumberExtension|+(#t52.{self::Class::field}, n1));
+  self::expect(n0, let final self::Class* #t53 = v in #t53.{self::Class::field} = self::NumberExtension|-(#t53.{self::Class::field}, n1));
+  self::expect(n1, let final self::Class* #t54 = v in #t54.{self::Class::field} = self::NumberExtension|+(#t54.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t55 = v in #t55.{self::Class::field} = self::NumberExtension|-(#t55.{self::Class::field}, 1));
+  self::expect(n0, let final self::Class* #t56 = v in let final self::Number* #t57 = #t56.{self::Class::field} in let final self::Number* #t58 = #t56.{self::Class::field} = self::NumberExtension|+(#t57, 1) in #t57);
+  self::expect(n1, let final self::Class* #t59 = v in let final self::Number* #t60 = #t59.{self::Class::field} in let final self::Number* #t61 = #t59.{self::Class::field} = self::NumberExtension|-(#t60, 1) in #t60);
   self::expect(n0, v.{self::Class::field});
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t40 = v in #t40.{self::Class::field} = self::NumberExtension|+(#t40.{self::Class::field}, n1);
+  let final self::Class* #t62 = v in #t62.{self::Class::field} = self::NumberExtension|+(#t62.{self::Class::field}, n1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t41 = v in #t41.{self::Class::field} = self::NumberExtension|+(#t41.{self::Class::field}, n1);
+  let final self::Class* #t63 = v in #t63.{self::Class::field} = self::NumberExtension|+(#t63.{self::Class::field}, n1);
   self::expect(n2, v.{self::Class::field});
-  let final self::Class* #t42 = v in #t42.{self::Class::field} = self::NumberExtension|-(#t42.{self::Class::field}, n2);
+  let final self::Class* #t64 = v in #t64.{self::Class::field} = self::NumberExtension|-(#t64.{self::Class::field}, n2);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t43 = v in #t43.{self::Class::field} = self::NumberExtension|+(#t43.{self::Class::field}, n1);
+  let final self::Class* #t65 = v in #t65.{self::Class::field} = self::NumberExtension|+(#t65.{self::Class::field}, n1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t44 = v in #t44.{self::Class::field} = self::NumberExtension|-(#t44.{self::Class::field}, n1);
+  let final self::Class* #t66 = v in #t66.{self::Class::field} = self::NumberExtension|-(#t66.{self::Class::field}, n1);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t45 = v in #t45.{self::Class::field} = self::NumberExtension|+(#t45.{self::Class::field}, 1);
+  let final self::Class* #t67 = v in #t67.{self::Class::field} = self::NumberExtension|+(#t67.{self::Class::field}, 1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t46 = v in #t46.{self::Class::field} = self::NumberExtension|-(#t46.{self::Class::field}, 1);
+  let final self::Class* #t68 = v in #t68.{self::Class::field} = self::NumberExtension|-(#t68.{self::Class::field}, 1);
   self::expect(n0, v.{self::Class::field});
-  let final self::Class* #t47 = v in #t47.{self::Class::field} = self::NumberExtension|+(#t47.{self::Class::field}, 1);
+  let final self::Class* #t69 = v in #t69.{self::Class::field} = self::NumberExtension|+(#t69.{self::Class::field}, 1);
   self::expect(n1, v.{self::Class::field});
-  let final self::Class* #t48 = v in #t48.{self::Class::field} = self::NumberExtension|-(#t48.{self::Class::field}, 1);
+  let final self::Class* #t70 = v in #t70.{self::Class::field} = self::NumberExtension|-(#t70.{self::Class::field}, 1);
   self::expect(n0, v.{self::Class::field});
   self::expect(n0, self::ClassExtension|get#property(v));
-  self::expect(n1, let final self::Class* #t49 = v in let final self::Class* #t50 = #t49 in let final self::Number* #t51 = self::NumberExtension|+(self::ClassExtension|get#property(#t49), n1) in let final void #t52 = self::ClassExtension|set#property(#t50, #t51) in #t51);
-  self::expect(n2, let final self::Class* #t53 = v in let final self::Class* #t54 = #t53 in let final self::Number* #t55 = self::NumberExtension|+(self::ClassExtension|get#property(#t53), n1) in let final void #t56 = self::ClassExtension|set#property(#t54, #t55) in #t55);
-  self::expect(n0, let final self::Class* #t57 = v in let final self::Class* #t58 = #t57 in let final self::Number* #t59 = self::NumberExtension|-(self::ClassExtension|get#property(#t57), n2) in let final void #t60 = self::ClassExtension|set#property(#t58, #t59) in #t59);
-  self::expect(n1, let final self::Class* #t61 = v in let final self::Class* #t62 = #t61 in let final self::Number* #t63 = self::NumberExtension|+(self::ClassExtension|get#property(#t61), n1) in let final void #t64 = self::ClassExtension|set#property(#t62, #t63) in #t63);
-  self::expect(n0, let final self::Class* #t65 = v in let final self::Class* #t66 = #t65 in let final self::Number* #t67 = self::NumberExtension|-(self::ClassExtension|get#property(#t65), n1) in let final void #t68 = self::ClassExtension|set#property(#t66, #t67) in #t67);
-  self::expect(n1, let final self::Class* #t69 = v in let final self::Class* #t70 = #t69 in let final self::Number* #t71 = self::NumberExtension|+(self::ClassExtension|get#property(#t69), 1) in let final void #t72 = self::ClassExtension|set#property(#t70, #t71) in #t71);
-  self::expect(n0, let final self::Class* #t73 = v in let final self::Class* #t74 = #t73 in let final self::Number* #t75 = self::NumberExtension|-(self::ClassExtension|get#property(#t73), 1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
-  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::ClassExtension|get#property(#t77) in let final self::Number* #t79 = self::ClassExtension|set#property(#t77, self::NumberExtension|+(#t78, 1)) in #t78);
-  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::ClassExtension|get#property(#t80) in let final self::Number* #t82 = self::ClassExtension|set#property(#t80, self::NumberExtension|-(#t81, 1)) in #t81);
+  self::expect(n1, let final self::Class* #t71 = v in let final self::Number* #t72 = self::NumberExtension|+(self::ClassExtension|get#property(#t71), n1) in let final void #t73 = self::ClassExtension|set#property(#t71, #t72) in #t72);
+  self::expect(n2, let final self::Class* #t74 = v in let final self::Number* #t75 = self::NumberExtension|+(self::ClassExtension|get#property(#t74), n1) in let final void #t76 = self::ClassExtension|set#property(#t74, #t75) in #t75);
+  self::expect(n0, let final self::Class* #t77 = v in let final self::Number* #t78 = self::NumberExtension|-(self::ClassExtension|get#property(#t77), n2) in let final void #t79 = self::ClassExtension|set#property(#t77, #t78) in #t78);
+  self::expect(n1, let final self::Class* #t80 = v in let final self::Number* #t81 = self::NumberExtension|+(self::ClassExtension|get#property(#t80), n1) in let final void #t82 = self::ClassExtension|set#property(#t80, #t81) in #t81);
+  self::expect(n0, let final self::Class* #t83 = v in let final self::Number* #t84 = self::NumberExtension|-(self::ClassExtension|get#property(#t83), n1) in let final void #t85 = self::ClassExtension|set#property(#t83, #t84) in #t84);
+  self::expect(n1, let final self::Class* #t86 = v in let final self::Number* #t87 = self::NumberExtension|+(self::ClassExtension|get#property(#t86), 1) in let final void #t88 = self::ClassExtension|set#property(#t86, #t87) in #t87);
+  self::expect(n0, let final self::Class* #t89 = v in let final self::Number* #t90 = self::NumberExtension|-(self::ClassExtension|get#property(#t89), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90);
+  self::expect(n0, let final self::Class* #t92 = v in let final self::Number* #t93 = self::ClassExtension|get#property(#t92) in let final self::Number* #t94 = self::ClassExtension|set#property(#t92, self::NumberExtension|+(#t93, 1)) in #t93);
+  self::expect(n1, let final self::Class* #t95 = v in let final self::Number* #t96 = self::ClassExtension|get#property(#t95) in let final self::Number* #t97 = self::ClassExtension|set#property(#t95, self::NumberExtension|-(#t96, 1)) in #t96);
   self::expect(n0, self::ClassExtension|get#property(v));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t83 = v in self::ClassExtension|set#property(#t83, self::NumberExtension|+(self::ClassExtension|get#property(#t83), n1));
+  let final self::Class* #t98 = v in self::ClassExtension|set#property(#t98, self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t84 = v in self::ClassExtension|set#property(#t84, self::NumberExtension|+(self::ClassExtension|get#property(#t84), n1));
+  let final self::Class* #t99 = v in self::ClassExtension|set#property(#t99, self::NumberExtension|+(self::ClassExtension|get#property(#t99), n1));
   self::expect(n2, self::ClassExtension|get#property(v));
-  let final self::Class* #t85 = v in self::ClassExtension|set#property(#t85, self::NumberExtension|-(self::ClassExtension|get#property(#t85), n2));
+  let final self::Class* #t100 = v in self::ClassExtension|set#property(#t100, self::NumberExtension|-(self::ClassExtension|get#property(#t100), n2));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t86 = v in self::ClassExtension|set#property(#t86, self::NumberExtension|+(self::ClassExtension|get#property(#t86), n1));
+  let final self::Class* #t101 = v in self::ClassExtension|set#property(#t101, self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t87 = v in self::ClassExtension|set#property(#t87, self::NumberExtension|-(self::ClassExtension|get#property(#t87), n1));
+  let final self::Class* #t102 = v in self::ClassExtension|set#property(#t102, self::NumberExtension|-(self::ClassExtension|get#property(#t102), n1));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t88 = v in let final self::Class* #t89 = #t88 in let final self::Number* #t90 = self::NumberExtension|+(self::ClassExtension|get#property(#t88), 1) in let final void #t91 = self::ClassExtension|set#property(#t89, #t90) in #t90;
+  let final self::Class* #t103 = v in let final self::Number* #t104 = self::NumberExtension|+(self::ClassExtension|get#property(#t103), 1) in let final void #t105 = self::ClassExtension|set#property(#t103, #t104) in #t104;
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t92 = v in let final self::Class* #t93 = #t92 in let final self::Number* #t94 = self::NumberExtension|-(self::ClassExtension|get#property(#t92), 1) in let final void #t95 = self::ClassExtension|set#property(#t93, #t94) in #t94;
+  let final self::Class* #t106 = v in let final self::Number* #t107 = self::NumberExtension|-(self::ClassExtension|get#property(#t106), 1) in let final void #t108 = self::ClassExtension|set#property(#t106, #t107) in #t107;
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t96 = v in self::ClassExtension|set#property(#t96, self::NumberExtension|+(self::ClassExtension|get#property(#t96), 1));
+  let final self::Class* #t109 = v in self::ClassExtension|set#property(#t109, self::NumberExtension|+(self::ClassExtension|get#property(#t109), 1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t97 = v in self::ClassExtension|set#property(#t97, self::NumberExtension|-(self::ClassExtension|get#property(#t97), 1));
+  let final self::Class* #t110 = v in self::ClassExtension|set#property(#t110, self::NumberExtension|-(self::ClassExtension|get#property(#t110), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
+static method testIntProperties() → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::IntClass* v = new self::IntClass::•(n0);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n1, let final self::IntClass* #t111 = v in #t111.{self::IntClass::field} = #t111.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n2, let final self::IntClass* #t112 = v in #t112.{self::IntClass::field} = #t112.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n0, let final self::IntClass* #t113 = v in #t113.{self::IntClass::field} = #t113.{self::IntClass::field}.{core::num::-}(n2));
+  self::expect(n1, let final self::IntClass* #t114 = v in #t114.{self::IntClass::field} = #t114.{self::IntClass::field}.{core::num::+}(n1));
+  self::expect(n0, let final self::IntClass* #t115 = v in #t115.{self::IntClass::field} = #t115.{self::IntClass::field}.{core::num::-}(n1));
+  self::expect(n1, let final self::IntClass* #t116 = v in #t116.{self::IntClass::field} = #t116.{self::IntClass::field}.{core::num::+}(1));
+  self::expect(n0, let final self::IntClass* #t117 = v in #t117.{self::IntClass::field} = #t117.{self::IntClass::field}.{core::num::-}(1));
+  self::expect(n0, let final self::IntClass* #t118 = v in let final core::int* #t119 = #t118.{self::IntClass::field} in let final core::int* #t120 = #t118.{self::IntClass::field} = #t119.{core::num::+}(1) in #t119);
+  self::expect(n1, let final self::IntClass* #t121 = v in let final core::int* #t122 = #t121.{self::IntClass::field} in let final core::int* #t123 = #t121.{self::IntClass::field} = #t122.{core::num::-}(1) in #t122);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t124 = v in #t124.{self::IntClass::field} = #t124.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t125 = v in #t125.{self::IntClass::field} = #t125.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n2, v.{self::IntClass::field});
+  let final self::IntClass* #t126 = v in #t126.{self::IntClass::field} = #t126.{self::IntClass::field}.{core::num::-}(n2);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t127 = v in #t127.{self::IntClass::field} = #t127.{self::IntClass::field}.{core::num::+}(n1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t128 = v in #t128.{self::IntClass::field} = #t128.{self::IntClass::field}.{core::num::-}(n1);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t129 = v in #t129.{self::IntClass::field} = #t129.{self::IntClass::field}.{core::num::+}(1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t130 = v in #t130.{self::IntClass::field} = #t130.{self::IntClass::field}.{core::num::-}(1);
+  self::expect(n0, v.{self::IntClass::field});
+  let final self::IntClass* #t131 = v in #t131.{self::IntClass::field} = #t131.{self::IntClass::field}.{core::num::+}(1);
+  self::expect(n1, v.{self::IntClass::field});
+  let final self::IntClass* #t132 = v in #t132.{self::IntClass::field} = #t132.{self::IntClass::field}.{core::num::-}(1);
+  self::expect(n0, v.{self::IntClass::field});
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n1, let final self::IntClass* #t133 = v in let final core::int* #t134 = self::IntClassExtension|get#property(#t133).{core::num::+}(n1) in let final void #t135 = self::IntClassExtension|set#property(#t133, #t134) in #t134);
+  self::expect(n2, let final self::IntClass* #t136 = v in let final core::int* #t137 = self::IntClassExtension|get#property(#t136).{core::num::+}(n1) in let final void #t138 = self::IntClassExtension|set#property(#t136, #t137) in #t137);
+  self::expect(n0, let final self::IntClass* #t139 = v in let final core::int* #t140 = self::IntClassExtension|get#property(#t139).{core::num::-}(n2) in let final void #t141 = self::IntClassExtension|set#property(#t139, #t140) in #t140);
+  self::expect(n1, let final self::IntClass* #t142 = v in let final core::int* #t143 = self::IntClassExtension|get#property(#t142).{core::num::+}(n1) in let final void #t144 = self::IntClassExtension|set#property(#t142, #t143) in #t143);
+  self::expect(n0, let final self::IntClass* #t145 = v in let final core::int* #t146 = self::IntClassExtension|get#property(#t145).{core::num::-}(n1) in let final void #t147 = self::IntClassExtension|set#property(#t145, #t146) in #t146);
+  self::expect(n1, let final self::IntClass* #t148 = v in let final core::int* #t149 = self::IntClassExtension|get#property(#t148).{core::num::+}(1) in let final void #t150 = self::IntClassExtension|set#property(#t148, #t149) in #t149);
+  self::expect(n0, let final self::IntClass* #t151 = v in let final core::int* #t152 = self::IntClassExtension|get#property(#t151).{core::num::-}(1) in let final void #t153 = self::IntClassExtension|set#property(#t151, #t152) in #t152);
+  self::expect(n0, let final self::IntClass* #t154 = v in let final core::int* #t155 = self::IntClassExtension|get#property(#t154) in let final core::int* #t156 = self::IntClassExtension|set#property(#t154, #t155.{core::num::+}(1)) in #t155);
+  self::expect(n1, let final self::IntClass* #t157 = v in let final core::int* #t158 = self::IntClassExtension|get#property(#t157) in let final core::int* #t159 = self::IntClassExtension|set#property(#t157, #t158.{core::num::-}(1)) in #t158);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t160 = v in self::IntClassExtension|set#property(#t160, self::IntClassExtension|get#property(#t160).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t161 = v in self::IntClassExtension|set#property(#t161, self::IntClassExtension|get#property(#t161).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t162 = v in self::IntClassExtension|set#property(#t162, self::IntClassExtension|get#property(#t162).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t163 = v in self::IntClassExtension|set#property(#t163, self::IntClassExtension|get#property(#t163).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t164 = v in self::IntClassExtension|set#property(#t164, self::IntClassExtension|get#property(#t164).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t165 = v in let final core::int* #t166 = self::IntClassExtension|get#property(#t165).{core::num::+}(1) in let final void #t167 = self::IntClassExtension|set#property(#t165, #t166) in #t166;
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t168 = v in let final core::int* #t169 = self::IntClassExtension|get#property(#t168).{core::num::-}(1) in let final void #t170 = self::IntClassExtension|set#property(#t168, #t169) in #t169;
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t171 = v in self::IntClassExtension|set#property(#t171, self::IntClassExtension|get#property(#t171).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t172 = v in self::IntClassExtension|set#property(#t172, self::IntClassExtension|get#property(#t172).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+}
 static method testExplicitProperties() → dynamic {
   self::Number* n0 = new self::Number::•(0);
   self::Number* n1 = new self::Number::•(1);
   self::Number* n2 = new self::Number::•(2);
   self::Class* v = new self::Class::•(n0);
   self::expect(n0, self::ClassExtension|get#property(v));
-  self::expect(n1, let final self::Class* #t98 = v in let final self::Number* #t99 = self::NumberExtension|+(self::ClassExtension|get#property(#t98), n1) in let final void #t100 = self::ClassExtension|set#property(#t98, #t99) in #t99);
-  self::expect(n2, let final self::Class* #t101 = v in let final self::Number* #t102 = self::NumberExtension|+(self::ClassExtension|get#property(#t101), n1) in let final void #t103 = self::ClassExtension|set#property(#t101, #t102) in #t102);
-  self::expect(n0, let final self::Class* #t104 = v in let final self::Number* #t105 = self::NumberExtension|-(self::ClassExtension|get#property(#t104), n2) in let final void #t106 = self::ClassExtension|set#property(#t104, #t105) in #t105);
-  self::expect(n1, let final self::Class* #t107 = v in let final self::Number* #t108 = self::NumberExtension|+(self::ClassExtension|get#property(#t107), n1) in let final void #t109 = self::ClassExtension|set#property(#t107, #t108) in #t108);
-  self::expect(n0, let final self::Class* #t110 = v in let final self::Number* #t111 = self::NumberExtension|-(self::ClassExtension|get#property(#t110), n1) in let final void #t112 = self::ClassExtension|set#property(#t110, #t111) in #t111);
-  self::expect(n1, let final self::Class* #t113 = v in let final self::Number* #t114 = self::NumberExtension|+(self::ClassExtension|get#property(#t113), 1) in let final void #t115 = self::ClassExtension|set#property(#t113, #t114) in #t114);
-  self::expect(n0, let final self::Class* #t116 = v in let final self::Number* #t117 = self::NumberExtension|-(self::ClassExtension|get#property(#t116), 1) in let final void #t118 = self::ClassExtension|set#property(#t116, #t117) in #t117);
-  self::expect(n0, let final self::Class* #t119 = v in let final self::Number* #t120 = self::ClassExtension|get#property(#t119) in let final self::Number* #t121 = let final self::Number* #t122 = self::NumberExtension|+(#t120, 1) in let final void #t123 = self::ClassExtension|set#property(#t119, #t122) in #t122 in #t120);
-  self::expect(n1, let final self::Class* #t124 = v in let final self::Number* #t125 = self::ClassExtension|get#property(#t124) in let final self::Number* #t126 = let final self::Number* #t127 = self::NumberExtension|-(#t125, 1) in let final void #t128 = self::ClassExtension|set#property(#t124, #t127) in #t127 in #t125);
+  self::expect(n1, let final self::Class* #t173 = v in let final self::Number* #t174 = self::NumberExtension|+(self::ClassExtension|get#property(#t173), n1) in let final void #t175 = self::ClassExtension|set#property(#t173, #t174) in #t174);
+  self::expect(n2, let final self::Class* #t176 = v in let final self::Number* #t177 = self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1) in let final void #t178 = self::ClassExtension|set#property(#t176, #t177) in #t177);
+  self::expect(n0, let final self::Class* #t179 = v in let final self::Number* #t180 = self::NumberExtension|-(self::ClassExtension|get#property(#t179), n2) in let final void #t181 = self::ClassExtension|set#property(#t179, #t180) in #t180);
+  self::expect(n1, let final self::Class* #t182 = v in let final self::Number* #t183 = self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1) in let final void #t184 = self::ClassExtension|set#property(#t182, #t183) in #t183);
+  self::expect(n0, let final self::Class* #t185 = v in let final self::Number* #t186 = self::NumberExtension|-(self::ClassExtension|get#property(#t185), n1) in let final void #t187 = self::ClassExtension|set#property(#t185, #t186) in #t186);
+  self::expect(n1, let final self::Class* #t188 = v in let final self::Number* #t189 = self::NumberExtension|+(self::ClassExtension|get#property(#t188), 1) in let final void #t190 = self::ClassExtension|set#property(#t188, #t189) in #t189);
+  self::expect(n0, let final self::Class* #t191 = v in let final self::Number* #t192 = self::NumberExtension|-(self::ClassExtension|get#property(#t191), 1) in let final void #t193 = self::ClassExtension|set#property(#t191, #t192) in #t192);
+  self::expect(n0, let final self::Class* #t194 = v in let final self::Number* #t195 = self::ClassExtension|get#property(#t194) in let final self::Number* #t196 = let final self::Number* #t197 = self::NumberExtension|+(#t195, 1) in let final void #t198 = self::ClassExtension|set#property(#t194, #t197) in #t197 in #t195);
+  self::expect(n1, let final self::Class* #t199 = v in let final self::Number* #t200 = self::ClassExtension|get#property(#t199) in let final self::Number* #t201 = let final self::Number* #t202 = self::NumberExtension|-(#t200, 1) in let final void #t203 = self::ClassExtension|set#property(#t199, #t202) in #t202 in #t200);
   self::expect(n0, self::ClassExtension|get#property(v));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t129 = v in self::ClassExtension|set#property(#t129, self::NumberExtension|+(self::ClassExtension|get#property(#t129), n1));
+  let final self::Class* #t204 = v in self::ClassExtension|set#property(#t204, self::NumberExtension|+(self::ClassExtension|get#property(#t204), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t130 = v in self::ClassExtension|set#property(#t130, self::NumberExtension|+(self::ClassExtension|get#property(#t130), n1));
+  let final self::Class* #t205 = v in self::ClassExtension|set#property(#t205, self::NumberExtension|+(self::ClassExtension|get#property(#t205), n1));
   self::expect(n2, self::ClassExtension|get#property(v));
-  let final self::Class* #t131 = v in self::ClassExtension|set#property(#t131, self::NumberExtension|-(self::ClassExtension|get#property(#t131), n2));
+  let final self::Class* #t206 = v in self::ClassExtension|set#property(#t206, self::NumberExtension|-(self::ClassExtension|get#property(#t206), n2));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t132 = v in self::ClassExtension|set#property(#t132, self::NumberExtension|+(self::ClassExtension|get#property(#t132), n1));
+  let final self::Class* #t207 = v in self::ClassExtension|set#property(#t207, self::NumberExtension|+(self::ClassExtension|get#property(#t207), n1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t133 = v in self::ClassExtension|set#property(#t133, self::NumberExtension|-(self::ClassExtension|get#property(#t133), n1));
+  let final self::Class* #t208 = v in self::ClassExtension|set#property(#t208, self::NumberExtension|-(self::ClassExtension|get#property(#t208), n1));
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t134 = v in let final self::Number* #t135 = self::NumberExtension|+(self::ClassExtension|get#property(#t134), 1) in let final void #t136 = self::ClassExtension|set#property(#t134, #t135) in #t135;
+  let final self::Class* #t209 = v in let final self::Number* #t210 = self::NumberExtension|+(self::ClassExtension|get#property(#t209), 1) in let final void #t211 = self::ClassExtension|set#property(#t209, #t210) in #t210;
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t137 = v in let final self::Number* #t138 = self::NumberExtension|-(self::ClassExtension|get#property(#t137), 1) in let final void #t139 = self::ClassExtension|set#property(#t137, #t138) in #t138;
+  let final self::Class* #t212 = v in let final self::Number* #t213 = self::NumberExtension|-(self::ClassExtension|get#property(#t212), 1) in let final void #t214 = self::ClassExtension|set#property(#t212, #t213) in #t213;
   self::expect(n0, self::ClassExtension|get#property(v));
-  let final self::Class* #t140 = v in self::ClassExtension|set#property(#t140, self::NumberExtension|+(self::ClassExtension|get#property(#t140), 1));
+  let final self::Class* #t215 = v in self::ClassExtension|set#property(#t215, self::NumberExtension|+(self::ClassExtension|get#property(#t215), 1));
   self::expect(n1, self::ClassExtension|get#property(v));
-  let final self::Class* #t141 = v in self::ClassExtension|set#property(#t141, self::NumberExtension|-(self::ClassExtension|get#property(#t141), 1));
+  let final self::Class* #t216 = v in self::ClassExtension|set#property(#t216, self::NumberExtension|-(self::ClassExtension|get#property(#t216), 1));
   self::expect(n0, self::ClassExtension|get#property(v));
 }
+static method testExplicitIntProperties() → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::IntClass* v = new self::IntClass::•(n0);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n1, let final self::IntClass* #t217 = v in let final core::int* #t218 = self::IntClassExtension|get#property(#t217).{core::num::+}(n1) in let final void #t219 = self::IntClassExtension|set#property(#t217, #t218) in #t218);
+  self::expect(n2, let final self::IntClass* #t220 = v in let final core::int* #t221 = self::IntClassExtension|get#property(#t220).{core::num::+}(n1) in let final void #t222 = self::IntClassExtension|set#property(#t220, #t221) in #t221);
+  self::expect(n0, let final self::IntClass* #t223 = v in let final core::int* #t224 = self::IntClassExtension|get#property(#t223).{core::num::-}(n2) in let final void #t225 = self::IntClassExtension|set#property(#t223, #t224) in #t224);
+  self::expect(n1, let final self::IntClass* #t226 = v in let final core::int* #t227 = self::IntClassExtension|get#property(#t226).{core::num::+}(n1) in let final void #t228 = self::IntClassExtension|set#property(#t226, #t227) in #t227);
+  self::expect(n0, let final self::IntClass* #t229 = v in let final core::int* #t230 = self::IntClassExtension|get#property(#t229).{core::num::-}(n1) in let final void #t231 = self::IntClassExtension|set#property(#t229, #t230) in #t230);
+  self::expect(n1, let final self::IntClass* #t232 = v in let final core::int* #t233 = self::IntClassExtension|get#property(#t232).{core::num::+}(1) in let final void #t234 = self::IntClassExtension|set#property(#t232, #t233) in #t233);
+  self::expect(n0, let final self::IntClass* #t235 = v in let final core::int* #t236 = self::IntClassExtension|get#property(#t235).{core::num::-}(1) in let final void #t237 = self::IntClassExtension|set#property(#t235, #t236) in #t236);
+  self::expect(n0, let final self::IntClass* #t238 = v in let final core::int* #t239 = self::IntClassExtension|get#property(#t238) in let final core::int* #t240 = let final core::int* #t241 = #t239.{core::num::+}(1) in let final void #t242 = self::IntClassExtension|set#property(#t238, #t241) in #t241 in #t239);
+  self::expect(n1, let final self::IntClass* #t243 = v in let final core::int* #t244 = self::IntClassExtension|get#property(#t243) in let final core::int* #t245 = let final core::int* #t246 = #t244.{core::num::-}(1) in let final void #t247 = self::IntClassExtension|set#property(#t243, #t246) in #t246 in #t244);
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t248 = v in self::IntClassExtension|set#property(#t248, self::IntClassExtension|get#property(#t248).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t249 = v in self::IntClassExtension|set#property(#t249, self::IntClassExtension|get#property(#t249).{core::num::+}(n1));
+  self::expect(n2, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t250 = v in self::IntClassExtension|set#property(#t250, self::IntClassExtension|get#property(#t250).{core::num::-}(n2));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t251 = v in self::IntClassExtension|set#property(#t251, self::IntClassExtension|get#property(#t251).{core::num::+}(n1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t252 = v in self::IntClassExtension|set#property(#t252, self::IntClassExtension|get#property(#t252).{core::num::-}(n1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t253 = v in let final core::int* #t254 = self::IntClassExtension|get#property(#t253).{core::num::+}(1) in let final void #t255 = self::IntClassExtension|set#property(#t253, #t254) in #t254;
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t256 = v in let final core::int* #t257 = self::IntClassExtension|get#property(#t256).{core::num::-}(1) in let final void #t258 = self::IntClassExtension|set#property(#t256, #t257) in #t257;
+  self::expect(n0, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t259 = v in self::IntClassExtension|set#property(#t259, self::IntClassExtension|get#property(#t259).{core::num::+}(1));
+  self::expect(n1, self::IntClassExtension|get#property(v));
+  let final self::IntClass* #t260 = v in self::IntClassExtension|set#property(#t260, self::IntClassExtension|get#property(#t260).{core::num::-}(1));
+  self::expect(n0, self::IntClassExtension|get#property(v));
+}
 static method testExplicitNullAwareProperties(self::Class* v) → dynamic {
   self::Number* n0 = new self::Number::•(0);
   self::Number* n1 = new self::Number::•(1);
   self::Number* n2 = new self::Number::•(2);
-  self::expect(n0, let final self::Class* #t142 = v in #t142.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t142), v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t143 = v in #t143.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t144 = self::NumberExtension|+(self::ClassExtension|get#property(#t143), n1) in let final void #t145 = self::ClassExtension|set#property(#t143, #t144) in #t144, v.{core::Object::==}(null));
-  self::expect(n2, let final self::Class* #t146 = v in #t146.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t147 = self::NumberExtension|+(self::ClassExtension|get#property(#t146), n1) in let final void #t148 = self::ClassExtension|set#property(#t146, #t147) in #t147, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t149 = v in #t149.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t150 = self::NumberExtension|-(self::ClassExtension|get#property(#t149), n2) in let final void #t151 = self::ClassExtension|set#property(#t149, #t150) in #t150, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t152 = v in #t152.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t153 = self::NumberExtension|+(self::ClassExtension|get#property(#t152), n1) in let final void #t154 = self::ClassExtension|set#property(#t152, #t153) in #t153, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t155 = v in #t155.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t156 = self::NumberExtension|-(self::ClassExtension|get#property(#t155), n1) in let final void #t157 = self::ClassExtension|set#property(#t155, #t156) in #t156, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t158 = v in #t158.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t159 = self::NumberExtension|+(self::ClassExtension|get#property(#t158), 1) in let final void #t160 = self::ClassExtension|set#property(#t158, #t159) in #t159, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t161 = v in #t161.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t162 = self::NumberExtension|-(self::ClassExtension|get#property(#t161), 1) in let final void #t163 = self::ClassExtension|set#property(#t161, #t162) in #t162, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t164 = v in #t164.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t165 = self::ClassExtension|get#property(#t164) in let final self::Number* #t166 = let final self::Number* #t167 = self::NumberExtension|+(#t165, 1) in let final void #t168 = self::ClassExtension|set#property(#t164, #t167) in #t167 in #t165, v.{core::Object::==}(null));
-  self::expect(n1, let final self::Class* #t169 = v in #t169.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t170 = self::ClassExtension|get#property(#t169) in let final self::Number* #t171 = let final self::Number* #t172 = self::NumberExtension|-(#t170, 1) in let final void #t173 = self::ClassExtension|set#property(#t169, #t172) in #t172 in #t170, v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t174 = v in #t174.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t174), v.{core::Object::==}(null));
-  self::expect(n0, let final self::Class* #t175 = v in #t175.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t175), v.{core::Object::==}(null));
-  let final self::Class* #t176 = v in #t176.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t176, self::NumberExtension|+(self::ClassExtension|get#property(#t176), n1));
-  self::expect(n1, let final self::Class* #t177 = v in #t177.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t177), v.{core::Object::==}(null));
-  let final self::Class* #t178 = v in #t178.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t178, self::NumberExtension|+(self::ClassExtension|get#property(#t178), n1));
-  self::expect(n2, let final self::Class* #t179 = v in #t179.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t179), v.{core::Object::==}(null));
-  let final self::Class* #t180 = v in #t180.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t180, self::NumberExtension|-(self::ClassExtension|get#property(#t180), n2));
-  self::expect(n0, let final self::Class* #t181 = v in #t181.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t181), v.{core::Object::==}(null));
-  let final self::Class* #t182 = v in #t182.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t182, self::NumberExtension|+(self::ClassExtension|get#property(#t182), n1));
-  self::expect(n1, let final self::Class* #t183 = v in #t183.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t183), v.{core::Object::==}(null));
-  let final self::Class* #t184 = v in #t184.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t184, self::NumberExtension|-(self::ClassExtension|get#property(#t184), n1));
-  self::expect(n0, let final self::Class* #t185 = v in #t185.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t185), v.{core::Object::==}(null));
-  let final self::Class* #t186 = v in #t186.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t187 = self::NumberExtension|+(self::ClassExtension|get#property(#t186), 1) in let final void #t188 = self::ClassExtension|set#property(#t186, #t187) in #t187;
-  self::expect(n1, let final self::Class* #t189 = v in #t189.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t189), v.{core::Object::==}(null));
-  let final self::Class* #t190 = v in #t190.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t191 = self::NumberExtension|-(self::ClassExtension|get#property(#t190), 1) in let final void #t192 = self::ClassExtension|set#property(#t190, #t191) in #t191;
-  self::expect(n0, let final self::Class* #t193 = v in #t193.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t193), v.{core::Object::==}(null));
-  let final self::Class* #t194 = v in #t194.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t194, self::NumberExtension|+(self::ClassExtension|get#property(#t194), 1));
-  self::expect(n1, let final self::Class* #t195 = v in #t195.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t195), v.{core::Object::==}(null));
-  let final self::Class* #t196 = v in #t196.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t196, self::NumberExtension|-(self::ClassExtension|get#property(#t196), 1));
-  self::expect(n0, let final self::Class* #t197 = v in #t197.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t197), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t261 = v in #t261.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t261), v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t262 = v in #t262.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t263 = self::NumberExtension|+(self::ClassExtension|get#property(#t262), n1) in let final void #t264 = self::ClassExtension|set#property(#t262, #t263) in #t263, v.{core::Object::==}(null));
+  self::expect(n2, let final self::Class* #t265 = v in #t265.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t266 = self::NumberExtension|+(self::ClassExtension|get#property(#t265), n1) in let final void #t267 = self::ClassExtension|set#property(#t265, #t266) in #t266, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t268 = v in #t268.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t269 = self::NumberExtension|-(self::ClassExtension|get#property(#t268), n2) in let final void #t270 = self::ClassExtension|set#property(#t268, #t269) in #t269, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t271 = v in #t271.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t272 = self::NumberExtension|+(self::ClassExtension|get#property(#t271), n1) in let final void #t273 = self::ClassExtension|set#property(#t271, #t272) in #t272, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t274 = v in #t274.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t275 = self::NumberExtension|-(self::ClassExtension|get#property(#t274), n1) in let final void #t276 = self::ClassExtension|set#property(#t274, #t275) in #t275, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t277 = v in #t277.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t278 = self::NumberExtension|+(self::ClassExtension|get#property(#t277), 1) in let final void #t279 = self::ClassExtension|set#property(#t277, #t278) in #t278, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t280 = v in #t280.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t281 = self::NumberExtension|-(self::ClassExtension|get#property(#t280), 1) in let final void #t282 = self::ClassExtension|set#property(#t280, #t281) in #t281, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t283 = v in #t283.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t284 = self::ClassExtension|get#property(#t283) in let final self::Number* #t285 = let final self::Number* #t286 = self::NumberExtension|+(#t284, 1) in let final void #t287 = self::ClassExtension|set#property(#t283, #t286) in #t286 in #t284, v.{core::Object::==}(null));
+  self::expect(n1, let final self::Class* #t288 = v in #t288.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t289 = self::ClassExtension|get#property(#t288) in let final self::Number* #t290 = let final self::Number* #t291 = self::NumberExtension|-(#t289, 1) in let final void #t292 = self::ClassExtension|set#property(#t288, #t291) in #t291 in #t289, v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t293 = v in #t293.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t293), v.{core::Object::==}(null));
+  self::expect(n0, let final self::Class* #t294 = v in #t294.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t294), v.{core::Object::==}(null));
+  let final self::Class* #t295 = v in #t295.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t295, self::NumberExtension|+(self::ClassExtension|get#property(#t295), n1));
+  self::expect(n1, let final self::Class* #t296 = v in #t296.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t296), v.{core::Object::==}(null));
+  let final self::Class* #t297 = v in #t297.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t297, self::NumberExtension|+(self::ClassExtension|get#property(#t297), n1));
+  self::expect(n2, let final self::Class* #t298 = v in #t298.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t298), v.{core::Object::==}(null));
+  let final self::Class* #t299 = v in #t299.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t299, self::NumberExtension|-(self::ClassExtension|get#property(#t299), n2));
+  self::expect(n0, let final self::Class* #t300 = v in #t300.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t300), v.{core::Object::==}(null));
+  let final self::Class* #t301 = v in #t301.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t301, self::NumberExtension|+(self::ClassExtension|get#property(#t301), n1));
+  self::expect(n1, let final self::Class* #t302 = v in #t302.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t302), v.{core::Object::==}(null));
+  let final self::Class* #t303 = v in #t303.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t303, self::NumberExtension|-(self::ClassExtension|get#property(#t303), n1));
+  self::expect(n0, let final self::Class* #t304 = v in #t304.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t304), v.{core::Object::==}(null));
+  let final self::Class* #t305 = v in #t305.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t306 = self::NumberExtension|+(self::ClassExtension|get#property(#t305), 1) in let final void #t307 = self::ClassExtension|set#property(#t305, #t306) in #t306;
+  self::expect(n1, let final self::Class* #t308 = v in #t308.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t308), v.{core::Object::==}(null));
+  let final self::Class* #t309 = v in #t309.{core::Object::==}(null) ?{self::Number*} null : let final self::Number* #t310 = self::NumberExtension|-(self::ClassExtension|get#property(#t309), 1) in let final void #t311 = self::ClassExtension|set#property(#t309, #t310) in #t310;
+  self::expect(n0, let final self::Class* #t312 = v in #t312.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t312), v.{core::Object::==}(null));
+  let final self::Class* #t313 = v in #t313.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t313, self::NumberExtension|+(self::ClassExtension|get#property(#t313), 1));
+  self::expect(n1, let final self::Class* #t314 = v in #t314.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t314), v.{core::Object::==}(null));
+  let final self::Class* #t315 = v in #t315.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|set#property(#t315, self::NumberExtension|-(self::ClassExtension|get#property(#t315), 1));
+  self::expect(n0, let final self::Class* #t316 = v in #t316.{core::Object::==}(null) ?{self::Number*} null : self::ClassExtension|get#property(#t316), v.{core::Object::==}(null));
+}
+static method testExplicitNullAwareIntProperties(self::IntClass* v) → dynamic {
+  core::int* n0 = 0;
+  core::int* n1 = 1;
+  core::int* n2 = 2;
+  self::expect(n0, let final self::IntClass* #t317 = v in #t317.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t317), v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t318 = v in #t318.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t319 = self::IntClassExtension|get#property(#t318).{core::num::+}(n1) in let final void #t320 = self::IntClassExtension|set#property(#t318, #t319) in #t319, v.{core::Object::==}(null));
+  self::expect(n2, let final self::IntClass* #t321 = v in #t321.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t322 = self::IntClassExtension|get#property(#t321).{core::num::+}(n1) in let final void #t323 = self::IntClassExtension|set#property(#t321, #t322) in #t322, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t324 = v in #t324.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t325 = self::IntClassExtension|get#property(#t324).{core::num::-}(n2) in let final void #t326 = self::IntClassExtension|set#property(#t324, #t325) in #t325, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t327 = v in #t327.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t328 = self::IntClassExtension|get#property(#t327).{core::num::+}(n1) in let final void #t329 = self::IntClassExtension|set#property(#t327, #t328) in #t328, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t330 = v in #t330.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t331 = self::IntClassExtension|get#property(#t330).{core::num::-}(n1) in let final void #t332 = self::IntClassExtension|set#property(#t330, #t331) in #t331, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t333 = v in #t333.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t334 = self::IntClassExtension|get#property(#t333).{core::num::+}(1) in let final void #t335 = self::IntClassExtension|set#property(#t333, #t334) in #t334, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t336 = v in #t336.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t337 = self::IntClassExtension|get#property(#t336).{core::num::-}(1) in let final void #t338 = self::IntClassExtension|set#property(#t336, #t337) in #t337, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t339 = v in #t339.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t340 = self::IntClassExtension|get#property(#t339) in let final core::int* #t341 = let final core::int* #t342 = #t340.{core::num::+}(1) in let final void #t343 = self::IntClassExtension|set#property(#t339, #t342) in #t342 in #t340, v.{core::Object::==}(null));
+  self::expect(n1, let final self::IntClass* #t344 = v in #t344.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t345 = self::IntClassExtension|get#property(#t344) in let final core::int* #t346 = let final core::int* #t347 = #t345.{core::num::-}(1) in let final void #t348 = self::IntClassExtension|set#property(#t344, #t347) in #t347 in #t345, v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t349 = v in #t349.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t349), v.{core::Object::==}(null));
+  self::expect(n0, let final self::IntClass* #t350 = v in #t350.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t350), v.{core::Object::==}(null));
+  let final self::IntClass* #t351 = v in #t351.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t351, self::IntClassExtension|get#property(#t351).{core::num::+}(n1));
+  self::expect(n1, let final self::IntClass* #t352 = v in #t352.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t352), v.{core::Object::==}(null));
+  let final self::IntClass* #t353 = v in #t353.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t353, self::IntClassExtension|get#property(#t353).{core::num::+}(n1));
+  self::expect(n2, let final self::IntClass* #t354 = v in #t354.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t354), v.{core::Object::==}(null));
+  let final self::IntClass* #t355 = v in #t355.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t355, self::IntClassExtension|get#property(#t355).{core::num::-}(n2));
+  self::expect(n0, let final self::IntClass* #t356 = v in #t356.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t356), v.{core::Object::==}(null));
+  let final self::IntClass* #t357 = v in #t357.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t357, self::IntClassExtension|get#property(#t357).{core::num::+}(n1));
+  self::expect(n1, let final self::IntClass* #t358 = v in #t358.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t358), v.{core::Object::==}(null));
+  let final self::IntClass* #t359 = v in #t359.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t359, self::IntClassExtension|get#property(#t359).{core::num::-}(n1));
+  self::expect(n0, let final self::IntClass* #t360 = v in #t360.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t360), v.{core::Object::==}(null));
+  let final self::IntClass* #t361 = v in #t361.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t362 = self::IntClassExtension|get#property(#t361).{core::num::+}(1) in let final void #t363 = self::IntClassExtension|set#property(#t361, #t362) in #t362;
+  self::expect(n1, let final self::IntClass* #t364 = v in #t364.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t364), v.{core::Object::==}(null));
+  let final self::IntClass* #t365 = v in #t365.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t366 = self::IntClassExtension|get#property(#t365).{core::num::-}(1) in let final void #t367 = self::IntClassExtension|set#property(#t365, #t366) in #t366;
+  self::expect(n0, let final self::IntClass* #t368 = v in #t368.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t368), v.{core::Object::==}(null));
+  let final self::IntClass* #t369 = v in #t369.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t369, self::IntClassExtension|get#property(#t369).{core::num::+}(1));
+  self::expect(n1, let final self::IntClass* #t370 = v in #t370.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t370), v.{core::Object::==}(null));
+  let final self::IntClass* #t371 = v in #t371.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|set#property(#t371, self::IntClassExtension|get#property(#t371).{core::num::-}(1));
+  self::expect(n0, let final self::IntClass* #t372 = v in #t372.{core::Object::==}(null) ?{core::int*} null : self::IntClassExtension|get#property(#t372), v.{core::Object::==}(null));
 }
 static method expect(dynamic expected, dynamic actual, [dynamic expectNull = #C1]) → dynamic {
   if(expectNull as{TypeError} core::bool*) {
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
index ffaf9b8..9a61489 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.type_promotion.expect
@@ -7,66 +7,66 @@
 pkg/front_end/testcases/extensions/compounds.dart:21:22: Context: Possible promotion of other@501
     } else if (other is Number) {
                      ^^
-pkg/front_end/testcases/extensions/compounds.dart:28:15: Context: Possible promotion of other@501
+pkg/front_end/testcases/extensions/compounds.dart:29:15: Context: Possible promotion of other@501
     if (other is int) {
               ^^
-pkg/front_end/testcases/extensions/compounds.dart:30:22: Context: Possible promotion of other@501
+pkg/front_end/testcases/extensions/compounds.dart:31:22: Context: Possible promotion of other@501
     } else if (other is Number) {
                      ^^
-pkg/front_end/testcases/extensions/compounds.dart:104:16: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:161:16: Context: Write to v@3587
   expect(n1, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:105:16: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:162:16: Context: Write to v@3587
   expect(n2, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:106:16: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:163:16: Context: Write to v@3587
   expect(n0, v -= n2);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:107:16: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:164:16: Context: Write to v@3587
   expect(n1, v += n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:108:16: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:165:16: Context: Write to v@3587
   expect(n0, v -= n1);
                ^^
-pkg/front_end/testcases/extensions/compounds.dart:109:14: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:166:14: Context: Write to v@3587
   expect(n1, ++v);
              ^^
-pkg/front_end/testcases/extensions/compounds.dart:110:14: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:167:14: Context: Write to v@3587
   expect(n0, --v);
              ^^
-pkg/front_end/testcases/extensions/compounds.dart:111:15: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:168:15: Context: Write to v@3587
   expect(n0, v++);
               ^^
-pkg/front_end/testcases/extensions/compounds.dart:112:15: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:169:15: Context: Write to v@3587
   expect(n1, v--);
               ^^
-pkg/front_end/testcases/extensions/compounds.dart:116:5: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:173:5: Context: Write to v@3587
   v += n1;
     ^^
-pkg/front_end/testcases/extensions/compounds.dart:118:5: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:175:5: Context: Write to v@3587
   v += n1;
     ^^
-pkg/front_end/testcases/extensions/compounds.dart:120:5: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:177:5: Context: Write to v@3587
   v -= n2;
     ^^
-pkg/front_end/testcases/extensions/compounds.dart:122:5: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:179:5: Context: Write to v@3587
   v += n1;
     ^^
-pkg/front_end/testcases/extensions/compounds.dart:124:5: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:181:5: Context: Write to v@3587
   v -= n1;
     ^^
-pkg/front_end/testcases/extensions/compounds.dart:126:3: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:183:3: Context: Write to v@3587
   ++v;
   ^^
-pkg/front_end/testcases/extensions/compounds.dart:128:3: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:185:3: Context: Write to v@3587
   --v;
   ^^
-pkg/front_end/testcases/extensions/compounds.dart:130:4: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:187:4: Context: Write to v@3587
   v++;
    ^^
-pkg/front_end/testcases/extensions/compounds.dart:132:4: Context: Write to v@2369
+pkg/front_end/testcases/extensions/compounds.dart:189:4: Context: Write to v@3587
   v--;
    ^^
-pkg/front_end/testcases/extensions/compounds.dart:285:14: Context: Write to expected@7409
+pkg/front_end/testcases/extensions/compounds.dart:489:14: Context: Write to expected@13239
     expected = null;
              ^
diff --git a/pkg/front_end/testcases/extensions/export_twice.dart b/pkg/front_end/testcases/extensions/export_twice.dart
new file mode 100644
index 0000000..6fdc20a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice.dart
@@ -0,0 +1,10 @@
+// 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 'export_twice_lib1.dart';
+import 'export_twice_lib2.dart';
+
+main() {
+  new Class().method();
+}
diff --git a/pkg/front_end/testcases/extensions/export_twice.dart.outline.expect b/pkg/front_end/testcases/extensions/export_twice.dart.outline.expect
new file mode 100644
index 0000000..f65b867
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice.dart.outline.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///export_twice_lib1.dart";
+import "org-dartlang-testcase:///export_twice_lib2.dart";
+
+static method main() → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self2::Class*
+    ;
+}
+extension Extension on self2::Class* {
+  method method = self2::Extension|method;
+  tearoff method = self2::Extension|get#method;
+}
+static method Extension|method(final self2::Class* #this) → dynamic
+  ;
+static method Extension|get#method(final self2::Class* #this) → () →* dynamic
+  return () → dynamic => self2::Extension|method(#this);
+
+library;
+import self as self3;
+import "export_twice_lib1.dart" as self2;
+additionalExports = (self2::Extension)
+
+export "org-dartlang-testcase:///export_twice_lib1.dart";
diff --git a/pkg/front_end/testcases/extensions/export_twice.dart.strong.expect b/pkg/front_end/testcases/extensions/export_twice.dart.strong.expect
new file mode 100644
index 0000000..b1703fd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice.dart.strong.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "export_twice_lib1.dart" as exp;
+
+import "org-dartlang-testcase:///export_twice_lib1.dart";
+import "org-dartlang-testcase:///export_twice_lib2.dart";
+
+static method main() → dynamic {
+  exp::Extension|method(new exp::Class::•());
+}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → exp::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on exp::Class* {
+  method method = exp::Extension|method;
+  tearoff method = exp::Extension|get#method;
+}
+static method Extension|method(final exp::Class* #this) → dynamic {}
+static method Extension|get#method(final exp::Class* #this) → () →* dynamic
+  return () → dynamic => exp::Extension|method(#this);
+
+library;
+import self as self2;
+import "export_twice_lib1.dart" as exp;
+additionalExports = (exp::Extension)
+
+export "org-dartlang-testcase:///export_twice_lib1.dart";
diff --git a/pkg/front_end/testcases/extensions/export_twice.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/export_twice.dart.strong.transformed.expect
new file mode 100644
index 0000000..b1703fd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "export_twice_lib1.dart" as exp;
+
+import "org-dartlang-testcase:///export_twice_lib1.dart";
+import "org-dartlang-testcase:///export_twice_lib2.dart";
+
+static method main() → dynamic {
+  exp::Extension|method(new exp::Class::•());
+}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → exp::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on exp::Class* {
+  method method = exp::Extension|method;
+  tearoff method = exp::Extension|get#method;
+}
+static method Extension|method(final exp::Class* #this) → dynamic {}
+static method Extension|get#method(final exp::Class* #this) → () →* dynamic
+  return () → dynamic => exp::Extension|method(#this);
+
+library;
+import self as self2;
+import "export_twice_lib1.dart" as exp;
+additionalExports = (exp::Extension)
+
+export "org-dartlang-testcase:///export_twice_lib1.dart";
diff --git a/pkg/front_end/testcases/extensions/export_twice_lib1.dart b/pkg/front_end/testcases/extensions/export_twice_lib1.dart
new file mode 100644
index 0000000..1004de0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice_lib1.dart
@@ -0,0 +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.
+
+class Class {}
+
+extension Extension on Class {
+  method() {}
+}
diff --git a/pkg/front_end/testcases/extensions/export_twice_lib2.dart b/pkg/front_end/testcases/extensions/export_twice_lib2.dart
new file mode 100644
index 0000000..adeca01
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/export_twice_lib2.dart
@@ -0,0 +1,5 @@
+// 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.
+
+export 'export_twice_lib1.dart' show Extension;
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
index 0eb2783..bcdd19f 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.expect
@@ -90,111 +90,111 @@
   self::expect(null, c.{self::Class::field});
   self::Extension|set#simpleSetter(c, 0);
   self::expect(0, c.{self::Class::field});
-  self::expect(1, let final self::Class* #t13 = c in let final core::int* #t14 = 1 in let final void #t15 = self::Extension|set#simpleSetter(#t13, #t14) in #t14);
+  self::expect(1, let final core::int* #t13 = 1 in let final void #t14 = self::Extension|set#simpleSetter(c, #t13) in #t13);
   self::Extension|set#simpleSetter(c, 2);
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t16 = c in let final core::int* #t17 = 3 in let final void #t18 = self::Extension|set#simpleSetter(#t16, #t17) in #t17);
+  self::expect(3, let final self::Class* #t15 = c in let final core::int* #t16 = 3 in let final void #t17 = self::Extension|set#simpleSetter(#t15, #t16) in #t16);
   self::Extension|set#mutatingSetter(c, 0);
   self::expect(1, c.{self::Class::field});
-  self::expect(2, let final self::Class* #t19 = c in let final core::int* #t20 = 2 in let final void #t21 = self::Extension|set#mutatingSetter(#t19, #t20) in #t20);
+  self::expect(2, let final core::int* #t18 = 2 in let final void #t19 = self::Extension|set#mutatingSetter(c, #t18) in #t18);
   self::expect(3, c.{self::Class::field});
   self::Extension|set#mutatingSetter(c, 4);
   self::expect(5, c.{self::Class::field});
-  self::expect(6, let final self::Class* #t22 = c in let final core::int* #t23 = 6 in let final void #t24 = self::Extension|set#mutatingSetter(#t22, #t23) in #t23);
+  self::expect(6, let final self::Class* #t20 = c in let final core::int* #t21 = 6 in let final void #t22 = self::Extension|set#mutatingSetter(#t20, #t21) in #t21);
   self::expect(7, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 1);
   self::expect(1, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 2.{core::int::unary-}());
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t25 = c in let final core::int* #t26 = 3 in let final void #t27 = self::Extension|set#setterWithReturn(#t25, #t26) in #t26);
+  self::expect(3, let final core::int* #t23 = 3 in let final void #t24 = self::Extension|set#setterWithReturn(c, #t23) in #t23);
   self::expect(3, c.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = 4.{core::int::unary-}() in let final void #t30 = self::Extension|set#setterWithReturn(#t28, #t29) in #t29);
+  self::expect(4.{core::int::unary-}(), let final core::int* #t25 = 4.{core::int::unary-}() in let final void #t26 = self::Extension|set#setterWithReturn(c, #t25) in #t25);
   self::expect(4, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 5);
   self::expect(5, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
   self::expect(6, c.{self::Class::field});
-  self::expect(7, let final self::Class* #t31 = c in let final core::int* #t32 = 7 in let final void #t33 = self::Extension|set#setterWithReturn(#t31, #t32) in #t32);
+  self::expect(7, let final self::Class* #t27 = c in let final core::int* #t28 = 7 in let final void #t29 = self::Extension|set#setterWithReturn(#t27, #t28) in #t28);
   self::expect(7, c.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t34 = c in let final core::int* #t35 = 8.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithReturn(#t34, #t35) in #t35);
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t30 = c in let final core::int* #t31 = 8.{core::int::unary-}() in let final void #t32 = self::Extension|set#setterWithReturn(#t30, #t31) in #t31);
   self::expect(8, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 1);
   self::expect(1, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 2.{core::int::unary-}());
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t37 = c in let final core::int* #t38 = 3 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
+  self::expect(3, let final core::int* #t33 = 3 in let final void #t34 = self::Extension|set#setterWithClosure(c, #t33) in #t33);
   self::expect(3, c.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 4.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
+  self::expect(4.{core::int::unary-}(), let final core::int* #t35 = 4.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithClosure(c, #t35) in #t35);
   self::expect(4, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 5);
   self::expect(5, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
   self::expect(6, c.{self::Class::field});
-  self::expect(7, let final self::Class* #t43 = c in let final core::int* #t44 = 7 in let final void #t45 = self::Extension|set#setterWithClosure(#t43, #t44) in #t44);
+  self::expect(7, let final self::Class* #t37 = c in let final core::int* #t38 = 7 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
   self::expect(7, c.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t46 = c in let final core::int* #t47 = 8.{core::int::unary-}() in let final void #t48 = self::Extension|set#setterWithClosure(#t46, #t47) in #t47);
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 8.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
   self::expect(8, c.{self::Class::field});
   self::Extension|set#simpleSetter(c, 0);
-  self::expect(0, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : #t49.{self::Class::field});
-  self::expect(1, let final self::Class* #t50 = c in #t50.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t51 = 1 in let final void #t52 = self::Extension|set#simpleSetter(#t50, #t51) in #t51);
+  self::expect(0, let final self::Class* #t43 = c in #t43.{core::Object::==}(null) ?{core::int*} null : #t43.{self::Class::field});
+  self::expect(1, let final self::Class* #t44 = c in #t44.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t45 = 1 in let final void #t46 = self::Extension|set#simpleSetter(#t44, #t45) in #t45);
   self::Extension|set#simpleSetter(c, 2);
-  self::expect(2, let final self::Class* #t53 = c in #t53.{core::Object::==}(null) ?{core::int*} null : #t53.{self::Class::field});
-  self::expect(3, let final self::Class* #t54 = c in let final core::int* #t55 = 3 in let final void #t56 = self::Extension|set#simpleSetter(#t54, #t55) in #t55);
+  self::expect(2, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : #t47.{self::Class::field});
+  self::expect(3, let final self::Class* #t48 = c in let final core::int* #t49 = 3 in let final void #t50 = self::Extension|set#simpleSetter(#t48, #t49) in #t49);
   self::Extension|set#mutatingSetter(c, 0);
-  self::expect(1, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : #t57.{self::Class::field});
-  self::expect(2, let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t59 = 2 in let final void #t60 = self::Extension|set#mutatingSetter(#t58, #t59) in #t59);
-  self::expect(3, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : #t61.{self::Class::field});
+  self::expect(1, let final self::Class* #t51 = c in #t51.{core::Object::==}(null) ?{core::int*} null : #t51.{self::Class::field});
+  self::expect(2, let final self::Class* #t52 = c in #t52.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t53 = 2 in let final void #t54 = self::Extension|set#mutatingSetter(#t52, #t53) in #t53);
+  self::expect(3, let final self::Class* #t55 = c in #t55.{core::Object::==}(null) ?{core::int*} null : #t55.{self::Class::field});
   self::Extension|set#mutatingSetter(c, 4);
-  self::expect(5, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
-  self::expect(6, let final self::Class* #t63 = c in let final core::int* #t64 = 6 in let final void #t65 = self::Extension|set#mutatingSetter(#t63, #t64) in #t64);
-  self::expect(7, let final self::Class* #t66 = c in #t66.{core::Object::==}(null) ?{core::int*} null : #t66.{self::Class::field});
-  let final self::Class* #t67 = c in #t67.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t67, 1);
-  self::expect(1, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
-  let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t69, 2.{core::int::unary-}());
-  self::expect(2, let final self::Class* #t70 = c in #t70.{core::Object::==}(null) ?{core::int*} null : #t70.{self::Class::field});
-  self::expect(3, let final self::Class* #t71 = c in #t71.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t72 = 3 in let final void #t73 = self::Extension|set#setterWithReturn(#t71, #t72) in #t72);
-  self::expect(3, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t75 = c in #t75.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t76 = 4.{core::int::unary-}() in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
-  self::expect(4, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::expect(5, let final self::Class* #t56 = c in #t56.{core::Object::==}(null) ?{core::int*} null : #t56.{self::Class::field});
+  self::expect(6, let final self::Class* #t57 = c in let final core::int* #t58 = 6 in let final void #t59 = self::Extension|set#mutatingSetter(#t57, #t58) in #t58);
+  self::expect(7, let final self::Class* #t60 = c in #t60.{core::Object::==}(null) ?{core::int*} null : #t60.{self::Class::field});
+  let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t61, 1);
+  self::expect(1, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
+  let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t63, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::int*} null : #t64.{self::Class::field});
+  self::expect(3, let final self::Class* #t65 = c in #t65.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t66 = 3 in let final void #t67 = self::Extension|set#setterWithReturn(#t65, #t66) in #t66);
+  self::expect(3, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t70 = 4.{core::int::unary-}() in let final void #t71 = self::Extension|set#setterWithReturn(#t69, #t70) in #t70);
+  self::expect(4, let final self::Class* #t72 = c in #t72.{core::Object::==}(null) ?{core::int*} null : #t72.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 5);
-  self::expect(5, let final self::Class* #t79 = c in #t79.{core::Object::==}(null) ?{core::int*} null : #t79.{self::Class::field});
+  self::expect(5, let final self::Class* #t73 = c in #t73.{core::Object::==}(null) ?{core::int*} null : #t73.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
-  self::expect(6, let final self::Class* #t80 = c in #t80.{core::Object::==}(null) ?{core::int*} null : #t80.{self::Class::field});
-  self::expect(7, let final self::Class* #t81 = c in let final core::int* #t82 = 7 in let final void #t83 = self::Extension|set#setterWithReturn(#t81, #t82) in #t82);
-  self::expect(7, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t85 = c in let final core::int* #t86 = 8.{core::int::unary-}() in let final void #t87 = self::Extension|set#setterWithReturn(#t85, #t86) in #t86);
-  self::expect(8, let final self::Class* #t88 = c in #t88.{core::Object::==}(null) ?{core::int*} null : #t88.{self::Class::field});
-  let final self::Class* #t89 = c in #t89.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t89, 1);
-  self::expect(1, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
-  let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t91, 2.{core::int::unary-}());
-  self::expect(2, let final self::Class* #t92 = c in #t92.{core::Object::==}(null) ?{core::int*} null : #t92.{self::Class::field});
-  self::expect(3, let final self::Class* #t93 = c in #t93.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t94 = 3 in let final void #t95 = self::Extension|set#setterWithClosure(#t93, #t94) in #t94);
-  self::expect(3, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t97 = c in #t97.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t98 = 4.{core::int::unary-}() in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
-  self::expect(4, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::expect(6, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
+  self::expect(7, let final self::Class* #t75 = c in let final core::int* #t76 = 7 in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
+  self::expect(7, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t79 = c in let final core::int* #t80 = 8.{core::int::unary-}() in let final void #t81 = self::Extension|set#setterWithReturn(#t79, #t80) in #t80);
+  self::expect(8, let final self::Class* #t82 = c in #t82.{core::Object::==}(null) ?{core::int*} null : #t82.{self::Class::field});
+  let final self::Class* #t83 = c in #t83.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t83, 1);
+  self::expect(1, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
+  let final self::Class* #t85 = c in #t85.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t85, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t86 = c in #t86.{core::Object::==}(null) ?{core::int*} null : #t86.{self::Class::field});
+  self::expect(3, let final self::Class* #t87 = c in #t87.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t88 = 3 in let final void #t89 = self::Extension|set#setterWithClosure(#t87, #t88) in #t88);
+  self::expect(3, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t92 = 4.{core::int::unary-}() in let final void #t93 = self::Extension|set#setterWithClosure(#t91, #t92) in #t92);
+  self::expect(4, let final self::Class* #t94 = c in #t94.{core::Object::==}(null) ?{core::int*} null : #t94.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 5);
-  self::expect(5, let final self::Class* #t101 = c in #t101.{core::Object::==}(null) ?{core::int*} null : #t101.{self::Class::field});
+  self::expect(5, let final self::Class* #t95 = c in #t95.{core::Object::==}(null) ?{core::int*} null : #t95.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
-  self::expect(6, let final self::Class* #t102 = c in #t102.{core::Object::==}(null) ?{core::int*} null : #t102.{self::Class::field});
-  self::expect(7, let final self::Class* #t103 = c in let final core::int* #t104 = 7 in let final void #t105 = self::Extension|set#setterWithClosure(#t103, #t104) in #t104);
-  self::expect(7, let final self::Class* #t106 = c in #t106.{core::Object::==}(null) ?{core::int*} null : #t106.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t107 = c in let final core::int* #t108 = 8.{core::int::unary-}() in let final void #t109 = self::Extension|set#setterWithClosure(#t107, #t108) in #t108);
-  self::expect(8, let final self::Class* #t110 = c in #t110.{core::Object::==}(null) ?{core::int*} null : #t110.{self::Class::field});
+  self::expect(6, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
+  self::expect(7, let final self::Class* #t97 = c in let final core::int* #t98 = 7 in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
+  self::expect(7, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t101 = c in let final core::int* #t102 = 8.{core::int::unary-}() in let final void #t103 = self::Extension|set#setterWithClosure(#t101, #t102) in #t102);
+  self::expect(8, let final self::Class* #t104 = c in #t104.{core::Object::==}(null) ?{core::int*} null : #t104.{self::Class::field});
   c.{self::Class::field} = null;
-  let final self::Class* #t111 = c in self::Extension|get#simpleSetter(#t111).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t111, 1) : null;
+  let final self::Class* #t105 = c in self::Extension|get#simpleSetter(#t105).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t105, 1) : null;
   self::expect(1, c.{self::Class::field});
-  self::expect(1, let final self::Class* #t112 = c in let final core::int* #t113 = self::Extension|get#simpleSetter(#t112) in #t113.{core::num::==}(null) ?{core::int*} let final self::Class* #t114 = #t112 in let final core::int* #t115 = 2 in let final void #t116 = self::Extension|set#simpleSetter(#t114, #t115) in #t115 : #t113);
+  self::expect(1, let final self::Class* #t106 = c in let final core::int* #t107 = self::Extension|get#simpleSetter(#t106) in #t107.{core::num::==}(null) ?{core::int*} let final core::int* #t108 = 2 in let final void #t109 = self::Extension|set#simpleSetter(#t106, #t108) in #t108 : #t107);
   c.{self::Class::field} = null;
-  self::expect(2, let final self::Class* #t117 = c in let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final self::Class* #t119 = #t117 in let final core::int* #t120 = 2 in let final void #t121 = self::Extension|set#simpleSetter(#t119, #t120) in #t120 : #t118);
-  let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::Null?} null : #t122.{self::Class::field} = null;
-  let final self::Class* #t123 = c in #t123.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t123).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t123, 1) : null;
-  self::expect(1, let final self::Class* #t124 = c in #t124.{core::Object::==}(null) ?{core::int*} null : #t124.{self::Class::field});
-  self::expect(1, let final self::Class* #t125 = c in #t125.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t126 = self::Extension|get#simpleSetter(#t125) in #t126.{core::num::==}(null) ?{core::int*} let final core::int* #t127 = 2 in let final void #t128 = self::Extension|set#simpleSetter(#t125, #t127) in #t127 : #t126);
-  let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
-  self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
+  self::expect(2, let final self::Class* #t110 = c in let final core::int* #t111 = self::Extension|get#simpleSetter(#t110) in #t111.{core::num::==}(null) ?{core::int*} let final core::int* #t112 = 2 in let final void #t113 = self::Extension|set#simpleSetter(#t110, #t112) in #t112 : #t111);
+  let final self::Class* #t114 = c in #t114.{core::Object::==}(null) ?{core::Null?} null : #t114.{self::Class::field} = null;
+  let final self::Class* #t115 = c in #t115.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t115).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t115, 1) : null;
+  self::expect(1, let final self::Class* #t116 = c in #t116.{core::Object::==}(null) ?{core::int*} null : #t116.{self::Class::field});
+  self::expect(1, let final self::Class* #t117 = c in #t117.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final core::int* #t119 = 2 in let final void #t120 = self::Extension|set#simpleSetter(#t117, #t119) in #t119 : #t118);
+  let final self::Class* #t121 = c in #t121.{core::Object::==}(null) ?{core::Null?} null : #t121.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t123 = self::Extension|get#simpleSetter(#t122) in #t123.{core::num::==}(null) ?{core::int*} let final core::int* #t124 = 2 in let final void #t125 = self::Extension|set#simpleSetter(#t122, #t124) in #t124 : #t123);
   self::Extension|testInternal(new self::Class::•());
   self::GenericClass<core::int*>* genericClass = new self::GenericClass::•<core::int*>();
-  self::expect(1, let final self::GenericClass<core::int*>* #t134 = genericClass in let final core::int* #t135 = 1 in let final void #t136 = self::GenericExtension|set#setter<core::int*>(#t134, #t135) in #t135);
+  self::expect(1, let final self::GenericClass<core::int*>* #t126 = genericClass in let final core::int* #t127 = 1 in let final void #t128 = self::GenericExtension|set#setter<core::int*>(#t126, #t127) in #t127);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
index 0eb2783..bcdd19f 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
@@ -90,111 +90,111 @@
   self::expect(null, c.{self::Class::field});
   self::Extension|set#simpleSetter(c, 0);
   self::expect(0, c.{self::Class::field});
-  self::expect(1, let final self::Class* #t13 = c in let final core::int* #t14 = 1 in let final void #t15 = self::Extension|set#simpleSetter(#t13, #t14) in #t14);
+  self::expect(1, let final core::int* #t13 = 1 in let final void #t14 = self::Extension|set#simpleSetter(c, #t13) in #t13);
   self::Extension|set#simpleSetter(c, 2);
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t16 = c in let final core::int* #t17 = 3 in let final void #t18 = self::Extension|set#simpleSetter(#t16, #t17) in #t17);
+  self::expect(3, let final self::Class* #t15 = c in let final core::int* #t16 = 3 in let final void #t17 = self::Extension|set#simpleSetter(#t15, #t16) in #t16);
   self::Extension|set#mutatingSetter(c, 0);
   self::expect(1, c.{self::Class::field});
-  self::expect(2, let final self::Class* #t19 = c in let final core::int* #t20 = 2 in let final void #t21 = self::Extension|set#mutatingSetter(#t19, #t20) in #t20);
+  self::expect(2, let final core::int* #t18 = 2 in let final void #t19 = self::Extension|set#mutatingSetter(c, #t18) in #t18);
   self::expect(3, c.{self::Class::field});
   self::Extension|set#mutatingSetter(c, 4);
   self::expect(5, c.{self::Class::field});
-  self::expect(6, let final self::Class* #t22 = c in let final core::int* #t23 = 6 in let final void #t24 = self::Extension|set#mutatingSetter(#t22, #t23) in #t23);
+  self::expect(6, let final self::Class* #t20 = c in let final core::int* #t21 = 6 in let final void #t22 = self::Extension|set#mutatingSetter(#t20, #t21) in #t21);
   self::expect(7, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 1);
   self::expect(1, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 2.{core::int::unary-}());
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t25 = c in let final core::int* #t26 = 3 in let final void #t27 = self::Extension|set#setterWithReturn(#t25, #t26) in #t26);
+  self::expect(3, let final core::int* #t23 = 3 in let final void #t24 = self::Extension|set#setterWithReturn(c, #t23) in #t23);
   self::expect(3, c.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t28 = c in let final core::int* #t29 = 4.{core::int::unary-}() in let final void #t30 = self::Extension|set#setterWithReturn(#t28, #t29) in #t29);
+  self::expect(4.{core::int::unary-}(), let final core::int* #t25 = 4.{core::int::unary-}() in let final void #t26 = self::Extension|set#setterWithReturn(c, #t25) in #t25);
   self::expect(4, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 5);
   self::expect(5, c.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
   self::expect(6, c.{self::Class::field});
-  self::expect(7, let final self::Class* #t31 = c in let final core::int* #t32 = 7 in let final void #t33 = self::Extension|set#setterWithReturn(#t31, #t32) in #t32);
+  self::expect(7, let final self::Class* #t27 = c in let final core::int* #t28 = 7 in let final void #t29 = self::Extension|set#setterWithReturn(#t27, #t28) in #t28);
   self::expect(7, c.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t34 = c in let final core::int* #t35 = 8.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithReturn(#t34, #t35) in #t35);
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t30 = c in let final core::int* #t31 = 8.{core::int::unary-}() in let final void #t32 = self::Extension|set#setterWithReturn(#t30, #t31) in #t31);
   self::expect(8, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 1);
   self::expect(1, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 2.{core::int::unary-}());
   self::expect(2, c.{self::Class::field});
-  self::expect(3, let final self::Class* #t37 = c in let final core::int* #t38 = 3 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
+  self::expect(3, let final core::int* #t33 = 3 in let final void #t34 = self::Extension|set#setterWithClosure(c, #t33) in #t33);
   self::expect(3, c.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 4.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
+  self::expect(4.{core::int::unary-}(), let final core::int* #t35 = 4.{core::int::unary-}() in let final void #t36 = self::Extension|set#setterWithClosure(c, #t35) in #t35);
   self::expect(4, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 5);
   self::expect(5, c.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
   self::expect(6, c.{self::Class::field});
-  self::expect(7, let final self::Class* #t43 = c in let final core::int* #t44 = 7 in let final void #t45 = self::Extension|set#setterWithClosure(#t43, #t44) in #t44);
+  self::expect(7, let final self::Class* #t37 = c in let final core::int* #t38 = 7 in let final void #t39 = self::Extension|set#setterWithClosure(#t37, #t38) in #t38);
   self::expect(7, c.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t46 = c in let final core::int* #t47 = 8.{core::int::unary-}() in let final void #t48 = self::Extension|set#setterWithClosure(#t46, #t47) in #t47);
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t40 = c in let final core::int* #t41 = 8.{core::int::unary-}() in let final void #t42 = self::Extension|set#setterWithClosure(#t40, #t41) in #t41);
   self::expect(8, c.{self::Class::field});
   self::Extension|set#simpleSetter(c, 0);
-  self::expect(0, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : #t49.{self::Class::field});
-  self::expect(1, let final self::Class* #t50 = c in #t50.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t51 = 1 in let final void #t52 = self::Extension|set#simpleSetter(#t50, #t51) in #t51);
+  self::expect(0, let final self::Class* #t43 = c in #t43.{core::Object::==}(null) ?{core::int*} null : #t43.{self::Class::field});
+  self::expect(1, let final self::Class* #t44 = c in #t44.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t45 = 1 in let final void #t46 = self::Extension|set#simpleSetter(#t44, #t45) in #t45);
   self::Extension|set#simpleSetter(c, 2);
-  self::expect(2, let final self::Class* #t53 = c in #t53.{core::Object::==}(null) ?{core::int*} null : #t53.{self::Class::field});
-  self::expect(3, let final self::Class* #t54 = c in let final core::int* #t55 = 3 in let final void #t56 = self::Extension|set#simpleSetter(#t54, #t55) in #t55);
+  self::expect(2, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : #t47.{self::Class::field});
+  self::expect(3, let final self::Class* #t48 = c in let final core::int* #t49 = 3 in let final void #t50 = self::Extension|set#simpleSetter(#t48, #t49) in #t49);
   self::Extension|set#mutatingSetter(c, 0);
-  self::expect(1, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : #t57.{self::Class::field});
-  self::expect(2, let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t59 = 2 in let final void #t60 = self::Extension|set#mutatingSetter(#t58, #t59) in #t59);
-  self::expect(3, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : #t61.{self::Class::field});
+  self::expect(1, let final self::Class* #t51 = c in #t51.{core::Object::==}(null) ?{core::int*} null : #t51.{self::Class::field});
+  self::expect(2, let final self::Class* #t52 = c in #t52.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t53 = 2 in let final void #t54 = self::Extension|set#mutatingSetter(#t52, #t53) in #t53);
+  self::expect(3, let final self::Class* #t55 = c in #t55.{core::Object::==}(null) ?{core::int*} null : #t55.{self::Class::field});
   self::Extension|set#mutatingSetter(c, 4);
-  self::expect(5, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
-  self::expect(6, let final self::Class* #t63 = c in let final core::int* #t64 = 6 in let final void #t65 = self::Extension|set#mutatingSetter(#t63, #t64) in #t64);
-  self::expect(7, let final self::Class* #t66 = c in #t66.{core::Object::==}(null) ?{core::int*} null : #t66.{self::Class::field});
-  let final self::Class* #t67 = c in #t67.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t67, 1);
-  self::expect(1, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
-  let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t69, 2.{core::int::unary-}());
-  self::expect(2, let final self::Class* #t70 = c in #t70.{core::Object::==}(null) ?{core::int*} null : #t70.{self::Class::field});
-  self::expect(3, let final self::Class* #t71 = c in #t71.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t72 = 3 in let final void #t73 = self::Extension|set#setterWithReturn(#t71, #t72) in #t72);
-  self::expect(3, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t75 = c in #t75.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t76 = 4.{core::int::unary-}() in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
-  self::expect(4, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::expect(5, let final self::Class* #t56 = c in #t56.{core::Object::==}(null) ?{core::int*} null : #t56.{self::Class::field});
+  self::expect(6, let final self::Class* #t57 = c in let final core::int* #t58 = 6 in let final void #t59 = self::Extension|set#mutatingSetter(#t57, #t58) in #t58);
+  self::expect(7, let final self::Class* #t60 = c in #t60.{core::Object::==}(null) ?{core::int*} null : #t60.{self::Class::field});
+  let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t61, 1);
+  self::expect(1, let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::int*} null : #t62.{self::Class::field});
+  let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithReturn(#t63, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::int*} null : #t64.{self::Class::field});
+  self::expect(3, let final self::Class* #t65 = c in #t65.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t66 = 3 in let final void #t67 = self::Extension|set#setterWithReturn(#t65, #t66) in #t66);
+  self::expect(3, let final self::Class* #t68 = c in #t68.{core::Object::==}(null) ?{core::int*} null : #t68.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t69 = c in #t69.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t70 = 4.{core::int::unary-}() in let final void #t71 = self::Extension|set#setterWithReturn(#t69, #t70) in #t70);
+  self::expect(4, let final self::Class* #t72 = c in #t72.{core::Object::==}(null) ?{core::int*} null : #t72.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 5);
-  self::expect(5, let final self::Class* #t79 = c in #t79.{core::Object::==}(null) ?{core::int*} null : #t79.{self::Class::field});
+  self::expect(5, let final self::Class* #t73 = c in #t73.{core::Object::==}(null) ?{core::int*} null : #t73.{self::Class::field});
   self::Extension|set#setterWithReturn(c, 6.{core::int::unary-}());
-  self::expect(6, let final self::Class* #t80 = c in #t80.{core::Object::==}(null) ?{core::int*} null : #t80.{self::Class::field});
-  self::expect(7, let final self::Class* #t81 = c in let final core::int* #t82 = 7 in let final void #t83 = self::Extension|set#setterWithReturn(#t81, #t82) in #t82);
-  self::expect(7, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t85 = c in let final core::int* #t86 = 8.{core::int::unary-}() in let final void #t87 = self::Extension|set#setterWithReturn(#t85, #t86) in #t86);
-  self::expect(8, let final self::Class* #t88 = c in #t88.{core::Object::==}(null) ?{core::int*} null : #t88.{self::Class::field});
-  let final self::Class* #t89 = c in #t89.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t89, 1);
-  self::expect(1, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
-  let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t91, 2.{core::int::unary-}());
-  self::expect(2, let final self::Class* #t92 = c in #t92.{core::Object::==}(null) ?{core::int*} null : #t92.{self::Class::field});
-  self::expect(3, let final self::Class* #t93 = c in #t93.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t94 = 3 in let final void #t95 = self::Extension|set#setterWithClosure(#t93, #t94) in #t94);
-  self::expect(3, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
-  self::expect(4.{core::int::unary-}(), let final self::Class* #t97 = c in #t97.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t98 = 4.{core::int::unary-}() in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
-  self::expect(4, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::expect(6, let final self::Class* #t74 = c in #t74.{core::Object::==}(null) ?{core::int*} null : #t74.{self::Class::field});
+  self::expect(7, let final self::Class* #t75 = c in let final core::int* #t76 = 7 in let final void #t77 = self::Extension|set#setterWithReturn(#t75, #t76) in #t76);
+  self::expect(7, let final self::Class* #t78 = c in #t78.{core::Object::==}(null) ?{core::int*} null : #t78.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t79 = c in let final core::int* #t80 = 8.{core::int::unary-}() in let final void #t81 = self::Extension|set#setterWithReturn(#t79, #t80) in #t80);
+  self::expect(8, let final self::Class* #t82 = c in #t82.{core::Object::==}(null) ?{core::int*} null : #t82.{self::Class::field});
+  let final self::Class* #t83 = c in #t83.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t83, 1);
+  self::expect(1, let final self::Class* #t84 = c in #t84.{core::Object::==}(null) ?{core::int*} null : #t84.{self::Class::field});
+  let final self::Class* #t85 = c in #t85.{core::Object::==}(null) ?{core::int*} null : self::Extension|set#setterWithClosure(#t85, 2.{core::int::unary-}());
+  self::expect(2, let final self::Class* #t86 = c in #t86.{core::Object::==}(null) ?{core::int*} null : #t86.{self::Class::field});
+  self::expect(3, let final self::Class* #t87 = c in #t87.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t88 = 3 in let final void #t89 = self::Extension|set#setterWithClosure(#t87, #t88) in #t88);
+  self::expect(3, let final self::Class* #t90 = c in #t90.{core::Object::==}(null) ?{core::int*} null : #t90.{self::Class::field});
+  self::expect(4.{core::int::unary-}(), let final self::Class* #t91 = c in #t91.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t92 = 4.{core::int::unary-}() in let final void #t93 = self::Extension|set#setterWithClosure(#t91, #t92) in #t92);
+  self::expect(4, let final self::Class* #t94 = c in #t94.{core::Object::==}(null) ?{core::int*} null : #t94.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 5);
-  self::expect(5, let final self::Class* #t101 = c in #t101.{core::Object::==}(null) ?{core::int*} null : #t101.{self::Class::field});
+  self::expect(5, let final self::Class* #t95 = c in #t95.{core::Object::==}(null) ?{core::int*} null : #t95.{self::Class::field});
   self::Extension|set#setterWithClosure(c, 6.{core::int::unary-}());
-  self::expect(6, let final self::Class* #t102 = c in #t102.{core::Object::==}(null) ?{core::int*} null : #t102.{self::Class::field});
-  self::expect(7, let final self::Class* #t103 = c in let final core::int* #t104 = 7 in let final void #t105 = self::Extension|set#setterWithClosure(#t103, #t104) in #t104);
-  self::expect(7, let final self::Class* #t106 = c in #t106.{core::Object::==}(null) ?{core::int*} null : #t106.{self::Class::field});
-  self::expect(8.{core::int::unary-}(), let final self::Class* #t107 = c in let final core::int* #t108 = 8.{core::int::unary-}() in let final void #t109 = self::Extension|set#setterWithClosure(#t107, #t108) in #t108);
-  self::expect(8, let final self::Class* #t110 = c in #t110.{core::Object::==}(null) ?{core::int*} null : #t110.{self::Class::field});
+  self::expect(6, let final self::Class* #t96 = c in #t96.{core::Object::==}(null) ?{core::int*} null : #t96.{self::Class::field});
+  self::expect(7, let final self::Class* #t97 = c in let final core::int* #t98 = 7 in let final void #t99 = self::Extension|set#setterWithClosure(#t97, #t98) in #t98);
+  self::expect(7, let final self::Class* #t100 = c in #t100.{core::Object::==}(null) ?{core::int*} null : #t100.{self::Class::field});
+  self::expect(8.{core::int::unary-}(), let final self::Class* #t101 = c in let final core::int* #t102 = 8.{core::int::unary-}() in let final void #t103 = self::Extension|set#setterWithClosure(#t101, #t102) in #t102);
+  self::expect(8, let final self::Class* #t104 = c in #t104.{core::Object::==}(null) ?{core::int*} null : #t104.{self::Class::field});
   c.{self::Class::field} = null;
-  let final self::Class* #t111 = c in self::Extension|get#simpleSetter(#t111).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t111, 1) : null;
+  let final self::Class* #t105 = c in self::Extension|get#simpleSetter(#t105).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t105, 1) : null;
   self::expect(1, c.{self::Class::field});
-  self::expect(1, let final self::Class* #t112 = c in let final core::int* #t113 = self::Extension|get#simpleSetter(#t112) in #t113.{core::num::==}(null) ?{core::int*} let final self::Class* #t114 = #t112 in let final core::int* #t115 = 2 in let final void #t116 = self::Extension|set#simpleSetter(#t114, #t115) in #t115 : #t113);
+  self::expect(1, let final self::Class* #t106 = c in let final core::int* #t107 = self::Extension|get#simpleSetter(#t106) in #t107.{core::num::==}(null) ?{core::int*} let final core::int* #t108 = 2 in let final void #t109 = self::Extension|set#simpleSetter(#t106, #t108) in #t108 : #t107);
   c.{self::Class::field} = null;
-  self::expect(2, let final self::Class* #t117 = c in let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final self::Class* #t119 = #t117 in let final core::int* #t120 = 2 in let final void #t121 = self::Extension|set#simpleSetter(#t119, #t120) in #t120 : #t118);
-  let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::Null?} null : #t122.{self::Class::field} = null;
-  let final self::Class* #t123 = c in #t123.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t123).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t123, 1) : null;
-  self::expect(1, let final self::Class* #t124 = c in #t124.{core::Object::==}(null) ?{core::int*} null : #t124.{self::Class::field});
-  self::expect(1, let final self::Class* #t125 = c in #t125.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t126 = self::Extension|get#simpleSetter(#t125) in #t126.{core::num::==}(null) ?{core::int*} let final core::int* #t127 = 2 in let final void #t128 = self::Extension|set#simpleSetter(#t125, #t127) in #t127 : #t126);
-  let final self::Class* #t129 = c in #t129.{core::Object::==}(null) ?{core::Null?} null : #t129.{self::Class::field} = null;
-  self::expect(2, let final self::Class* #t130 = c in #t130.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t131 = self::Extension|get#simpleSetter(#t130) in #t131.{core::num::==}(null) ?{core::int*} let final core::int* #t132 = 2 in let final void #t133 = self::Extension|set#simpleSetter(#t130, #t132) in #t132 : #t131);
+  self::expect(2, let final self::Class* #t110 = c in let final core::int* #t111 = self::Extension|get#simpleSetter(#t110) in #t111.{core::num::==}(null) ?{core::int*} let final core::int* #t112 = 2 in let final void #t113 = self::Extension|set#simpleSetter(#t110, #t112) in #t112 : #t111);
+  let final self::Class* #t114 = c in #t114.{core::Object::==}(null) ?{core::Null?} null : #t114.{self::Class::field} = null;
+  let final self::Class* #t115 = c in #t115.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#simpleSetter(#t115).{core::num::==}(null) ?{core::int*} self::Extension|set#simpleSetter(#t115, 1) : null;
+  self::expect(1, let final self::Class* #t116 = c in #t116.{core::Object::==}(null) ?{core::int*} null : #t116.{self::Class::field});
+  self::expect(1, let final self::Class* #t117 = c in #t117.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t118 = self::Extension|get#simpleSetter(#t117) in #t118.{core::num::==}(null) ?{core::int*} let final core::int* #t119 = 2 in let final void #t120 = self::Extension|set#simpleSetter(#t117, #t119) in #t119 : #t118);
+  let final self::Class* #t121 = c in #t121.{core::Object::==}(null) ?{core::Null?} null : #t121.{self::Class::field} = null;
+  self::expect(2, let final self::Class* #t122 = c in #t122.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t123 = self::Extension|get#simpleSetter(#t122) in #t123.{core::num::==}(null) ?{core::int*} let final core::int* #t124 = 2 in let final void #t125 = self::Extension|set#simpleSetter(#t122, #t124) in #t124 : #t123);
   self::Extension|testInternal(new self::Class::•());
   self::GenericClass<core::int*>* genericClass = new self::GenericClass::•<core::int*>();
-  self::expect(1, let final self::GenericClass<core::int*>* #t134 = genericClass in let final core::int* #t135 = 1 in let final void #t136 = self::GenericExtension|set#setter<core::int*>(#t134, #t135) in #t135);
+  self::expect(1, let final self::GenericClass<core::int*>* #t126 = genericClass in let final core::int* #t127 = 1 in let final void #t128 = self::GenericExtension|set#setter<core::int*>(#t126, #t127) in #t127);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
index 895ddb7..afdb95d 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.expect
@@ -92,35 +92,35 @@
   self::expect(89, self::Extension1|genericMethod<core::num*>(c1, 88));
   self::expect(0, self::Extension1|get#property(c0));
   self::expect(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t2));
-  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::Extension1|set#property(#t3, #t4) in #t4);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::Extension1|set#property(c0, #t3) in #t3);
   self::expect(1, self::Extension1|get#property(c1));
-  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::Extension1|set#property(#t6, #t7) in #t7);
-  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::Extension1|set#property(#t11, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(#t9, #t10) in #t10);
-  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::Extension1|set#property(#t17, #t18) in #t18 in let final void #t20 = self::Extension1|set#property(#t15, #t16) in #t16);
-  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::Extension1|set#property(#t25, #t26) in #t26 in let final void #t28 = self::Extension1|set#property(#t23, #t24) in #t24 in let final void #t29 = self::Extension1|set#property(#t21, #t22) in #t22);
-  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::Extension1|set#property(#t34, #t35) in #t35 in let final void #t37 = self::Extension1|set#property(#t32, #t33) in #t33 in let final void #t38 = self::Extension1|set#property(#t30, #t31) in #t31);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::Extension1|set#property(c0, #t5) in #t5);
+  self::expect(27, let final core::int* #t7 = let final core::int* #t8 = 27 in let final void #t9 = self::Extension1|set#property(c1, #t8) in #t8 in let final void #t10 = self::Extension1|set#property(c0, #t7) in #t7);
+  self::expect(37, let final core::int* #t11 = let final core::int* #t12 = 37 in let final void #t13 = self::Extension1|set#property(c0, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(c1, #t11) in #t11);
+  self::expect(77, let final core::int* #t15 = let final core::int* #t16 = let final core::int* #t17 = 77 in let final void #t18 = self::Extension1|set#property(c1, #t17) in #t17 in let final void #t19 = self::Extension1|set#property(c0, #t16) in #t16 in let final void #t20 = self::Extension1|set#property(c1, #t15) in #t15);
+  self::expect(67, let final core::int* #t21 = let final core::int* #t22 = let final core::int* #t23 = 67 in let final void #t24 = self::Extension1|set#property(c0, #t23) in #t23 in let final void #t25 = self::Extension1|set#property(c1, #t22) in #t22 in let final void #t26 = self::Extension1|set#property(c0, #t21) in #t21);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::Extension2|method(c0));
-  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t39));
+  self::expect(3, let final self::Class2* #t27 = c0 in #t27.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t27));
   self::expect(4, self::Extension2|method(c1));
   self::expect(46, self::Extension2|genericMethod<core::int*>(c0, 42));
   self::expect(47, self::Extension2|genericMethod<core::num*>(c0, 43));
   self::expect(92, self::Extension2|genericMethod<core::int*>(c1, 87));
   self::expect(93, self::Extension2|genericMethod<core::num*>(c1, 88));
   self::expect(5, self::Extension2|get#property(c0));
-  self::expect(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t40));
-  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::Extension2|set#property(#t41, #t42) in #t42);
+  self::expect(5, let final self::Class2* #t28 = c0 in #t28.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t28));
+  self::expect(42, let final core::int* #t29 = 42 in let final void #t30 = self::Extension2|set#property(c0, #t29) in #t29);
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
-  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::Extension2|set#property(#t44, #t45) in #t45);
+  self::expect(43, let final core::int* #t31 = 43 in let final void #t32 = self::Extension2|set#property(c1, #t31) in #t31);
   self::expect(49, self::Extension2|get#property(c1));
-  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::Extension2|get#property(c1) in let final void #t49 = self::Extension2|set#property(#t47, #t48) in #t48);
-  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::Extension2|get#property(c0) in let final void #t52 = self::Extension2|set#property(#t50, #t51) in #t51);
-  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::Extension2|get#property(c1) in let final void #t57 = self::Extension2|set#property(#t55, #t56) in #t56 in let final void #t58 = self::Extension2|set#property(#t53, #t54) in #t54);
-  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::Extension2|get#property(c0) in let final void #t63 = self::Extension2|set#property(#t61, #t62) in #t62 in let final void #t64 = self::Extension2|set#property(#t59, #t60) in #t60);
+  self::expect(49, let final core::int* #t33 = self::Extension2|get#property(c1) in let final void #t34 = self::Extension2|set#property(c0, #t33) in #t33);
+  self::expect(55, let final core::int* #t35 = self::Extension2|get#property(c0) in let final void #t36 = self::Extension2|set#property(c1, #t35) in #t35);
+  self::expect(61, let final core::int* #t37 = let final core::int* #t38 = self::Extension2|get#property(c1) in let final void #t39 = self::Extension2|set#property(c0, #t38) in #t38 in let final void #t40 = self::Extension2|set#property(c1, #t37) in #t37);
+  self::expect(67, let final core::int* #t41 = let final core::int* #t42 = self::Extension2|get#property(c0) in let final void #t43 = self::Extension2|set#property(c1, #t42) in #t42 in let final void #t44 = self::Extension2|set#property(c0, #t41) in #t41);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
index 895ddb7..afdb95d 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
@@ -92,35 +92,35 @@
   self::expect(89, self::Extension1|genericMethod<core::num*>(c1, 88));
   self::expect(0, self::Extension1|get#property(c0));
   self::expect(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::Extension1|get#property(#t2));
-  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::Extension1|set#property(#t3, #t4) in #t4);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::Extension1|set#property(c0, #t3) in #t3);
   self::expect(1, self::Extension1|get#property(c1));
-  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::Extension1|set#property(#t6, #t7) in #t7);
-  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::Extension1|set#property(#t11, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(#t9, #t10) in #t10);
-  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::Extension1|set#property(#t17, #t18) in #t18 in let final void #t20 = self::Extension1|set#property(#t15, #t16) in #t16);
-  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::Extension1|set#property(#t25, #t26) in #t26 in let final void #t28 = self::Extension1|set#property(#t23, #t24) in #t24 in let final void #t29 = self::Extension1|set#property(#t21, #t22) in #t22);
-  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::Extension1|set#property(#t34, #t35) in #t35 in let final void #t37 = self::Extension1|set#property(#t32, #t33) in #t33 in let final void #t38 = self::Extension1|set#property(#t30, #t31) in #t31);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::Extension1|set#property(c0, #t5) in #t5);
+  self::expect(27, let final core::int* #t7 = let final core::int* #t8 = 27 in let final void #t9 = self::Extension1|set#property(c1, #t8) in #t8 in let final void #t10 = self::Extension1|set#property(c0, #t7) in #t7);
+  self::expect(37, let final core::int* #t11 = let final core::int* #t12 = 37 in let final void #t13 = self::Extension1|set#property(c0, #t12) in #t12 in let final void #t14 = self::Extension1|set#property(c1, #t11) in #t11);
+  self::expect(77, let final core::int* #t15 = let final core::int* #t16 = let final core::int* #t17 = 77 in let final void #t18 = self::Extension1|set#property(c1, #t17) in #t17 in let final void #t19 = self::Extension1|set#property(c0, #t16) in #t16 in let final void #t20 = self::Extension1|set#property(c1, #t15) in #t15);
+  self::expect(67, let final core::int* #t21 = let final core::int* #t22 = let final core::int* #t23 = 67 in let final void #t24 = self::Extension1|set#property(c0, #t23) in #t23 in let final void #t25 = self::Extension1|set#property(c1, #t22) in #t22 in let final void #t26 = self::Extension1|set#property(c0, #t21) in #t21);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::Extension2|method(c0));
-  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t39));
+  self::expect(3, let final self::Class2* #t27 = c0 in #t27.{core::Object::==}(null) ?{core::int*} null : self::Extension2|method(#t27));
   self::expect(4, self::Extension2|method(c1));
   self::expect(46, self::Extension2|genericMethod<core::int*>(c0, 42));
   self::expect(47, self::Extension2|genericMethod<core::num*>(c0, 43));
   self::expect(92, self::Extension2|genericMethod<core::int*>(c1, 87));
   self::expect(93, self::Extension2|genericMethod<core::num*>(c1, 88));
   self::expect(5, self::Extension2|get#property(c0));
-  self::expect(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t40));
-  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::Extension2|set#property(#t41, #t42) in #t42);
+  self::expect(5, let final self::Class2* #t28 = c0 in #t28.{core::Object::==}(null) ?{core::int*} null : self::Extension2|get#property(#t28));
+  self::expect(42, let final core::int* #t29 = 42 in let final void #t30 = self::Extension2|set#property(c0, #t29) in #t29);
   self::expect(48, self::Extension2|get#property(c0));
   self::expect(6, self::Extension2|get#property(c1));
-  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::Extension2|set#property(#t44, #t45) in #t45);
+  self::expect(43, let final core::int* #t31 = 43 in let final void #t32 = self::Extension2|set#property(c1, #t31) in #t31);
   self::expect(49, self::Extension2|get#property(c1));
-  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::Extension2|get#property(c1) in let final void #t49 = self::Extension2|set#property(#t47, #t48) in #t48);
-  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::Extension2|get#property(c0) in let final void #t52 = self::Extension2|set#property(#t50, #t51) in #t51);
-  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::Extension2|get#property(c1) in let final void #t57 = self::Extension2|set#property(#t55, #t56) in #t56 in let final void #t58 = self::Extension2|set#property(#t53, #t54) in #t54);
-  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::Extension2|get#property(c0) in let final void #t63 = self::Extension2|set#property(#t61, #t62) in #t62 in let final void #t64 = self::Extension2|set#property(#t59, #t60) in #t60);
+  self::expect(49, let final core::int* #t33 = self::Extension2|get#property(c1) in let final void #t34 = self::Extension2|set#property(c0, #t33) in #t33);
+  self::expect(55, let final core::int* #t35 = self::Extension2|get#property(c0) in let final void #t36 = self::Extension2|set#property(c1, #t35) in #t35);
+  self::expect(61, let final core::int* #t37 = let final core::int* #t38 = self::Extension2|get#property(c1) in let final void #t39 = self::Extension2|set#property(c0, #t38) in #t38 in let final void #t40 = self::Extension2|set#property(c1, #t37) in #t37);
+  self::expect(67, let final core::int* #t41 = let final core::int* #t42 = self::Extension2|get#property(c0) in let final void #t43 = self::Extension2|set#property(c1, #t42) in #t42 in let final void #t44 = self::Extension2|set#property(c0, #t41) in #t41);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect
index 0225e55..46d8f5f 100644
--- a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.expect
@@ -23,14 +23,14 @@
 static method _extension#1|get#property2(final self::Class* #this) → core::int*
   return #this.{self::Class::field};
 static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
-  return let final self::Class* #t1 = #this in let final core::int* #t2 = value in let final void #t3 = self::_extension#0|set#property1(#t1, #t2) in #t2;
+  return let final core::int* #t1 = value in let final void #t2 = self::_extension#0|set#property1(#this, #t1) in #t1;
 static method main() → dynamic {
   self::Class* c = new self::Class::•();
   self::expect(null, self::_extension#0|get#property1(c));
   self::expect(null, self::_extension#1|get#property2(c));
-  self::expect(42, let final self::Class* #t4 = c in let final core::int* #t5 = 42 in let final void #t6 = self::_extension#0|set#property1(#t4, #t5) in #t5);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::_extension#0|set#property1(c, #t3) in #t3);
   self::expect(42, self::_extension#1|get#property2(c));
-  self::expect(87, let final self::Class* #t7 = c in let final core::int* #t8 = 87 in let final void #t9 = self::_extension#1|set#property2(#t7, #t8) in #t8);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::_extension#1|set#property2(c, #t5) in #t5);
   self::expect(87, self::_extension#0|get#property1(c));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
index 0225e55..46d8f5f 100644
--- a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
@@ -23,14 +23,14 @@
 static method _extension#1|get#property2(final self::Class* #this) → core::int*
   return #this.{self::Class::field};
 static method _extension#1|set#property2(final self::Class* #this, core::int* value) → void
-  return let final self::Class* #t1 = #this in let final core::int* #t2 = value in let final void #t3 = self::_extension#0|set#property1(#t1, #t2) in #t2;
+  return let final core::int* #t1 = value in let final void #t2 = self::_extension#0|set#property1(#this, #t1) in #t1;
 static method main() → dynamic {
   self::Class* c = new self::Class::•();
   self::expect(null, self::_extension#0|get#property1(c));
   self::expect(null, self::_extension#1|get#property2(c));
-  self::expect(42, let final self::Class* #t4 = c in let final core::int* #t5 = 42 in let final void #t6 = self::_extension#0|set#property1(#t4, #t5) in #t5);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::_extension#0|set#property1(c, #t3) in #t3);
   self::expect(42, self::_extension#1|get#property2(c));
-  self::expect(87, let final self::Class* #t7 = c in let final core::int* #t8 = 87 in let final void #t9 = self::_extension#1|set#property2(#t7, #t8) in #t8);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::_extension#1|set#property2(c, #t5) in #t5);
   self::expect(87, self::_extension#0|get#property1(c));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart b/pkg/front_end/testcases/extensions/missing_toplevel.dart
new file mode 100644
index 0000000..2844255
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart
@@ -0,0 +1,15 @@
+// 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.
+
+class 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.outline.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.outline.expect
new file mode 100644
index 0000000..f11fb72
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class* {
+  set setter = self::Extension|set#setter;
+}
+static field self::Class* c;
+static field dynamic missingGetter;
+static method Extension|set#setter(final self::Class* #this, core::int* value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.expect
new file mode 100644
index 0000000..65f4bbd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.expect
@@ -0,0 +1,29 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/missing_toplevel.dart:13:23: Error: The getter 'setter' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'setter'.
+// var missingGetter = c.setter += 42;
+//                       ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  set setter = self::Extension|set#setter;
+}
+static field self::Class* c = new self::Class::•();
+static field dynamic missingGetter = let final self::Class* #t1 = self::c in let final dynamic #t2 = invalid-expression "pkg/front_end/testcases/extensions/missing_toplevel.dart:13:23: Error: The getter 'setter' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/missing_toplevel.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'setter'.
+var missingGetter = c.setter += 42;
+                      ^^^^^^".+(42) as{TypeError} core::int* in let final void #t3 = self::Extension|set#setter(#t1, #t2) in #t2;
+static method Extension|set#setter(final self::Class* #this, core::int* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.transformed.expect
new file mode 100644
index 0000000..d5c36de
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/missing_toplevel.dart:13:23: Error: The getter 'setter' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/extensions/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'setter'.
+// var missingGetter = c.setter += 42;
+//                       ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class* {
+  set setter = self::Extension|set#setter;
+}
+static field self::Class* c = new self::Class::•();
+static field dynamic missingGetter = let final self::Class* #t1 = self::c in let final core::int* #t2 = invalid-expression "pkg/front_end/testcases/extensions/missing_toplevel.dart:13:23: Error: The getter 'setter' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/extensions/missing_toplevel.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'setter'.
+var missingGetter = c.setter += 42;
+                      ^^^^^^".+(42) as{TypeError} core::int* in let final void #t3 = self::Extension|set#setter(#t1, #t2) in #t2;
+static method Extension|set#setter(final self::Class* #this, core::int* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect b/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
index 6d32899..c5a31af 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.expect
@@ -50,24 +50,24 @@
   self::expect(42, let final self::Class* #t26 = c in #t26.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t27 = 42 in let final void #t28 = self::Extension|set#property(#t26, #t27) in #t27);
   let final self::Class* #t29 = c in #t29.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t29, null);
   self::expect(null, let final self::Class* #t30 = c in #t30.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t30));
-  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final self::Class* #t33 = #t31 in let final core::int* #t34 = 42 in let final void #t35 = self::Extension|set#property(#t33, #t34) in #t34 : #t32);
-  self::expect(42, let final self::Class* #t36 = c in let final core::int* #t37 = self::Extension|get#property(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final self::Class* #t38 = #t36 in let final core::int* #t39 = 87 in let final void #t40 = self::Extension|set#property(#t38, #t39) in #t39 : #t37);
-  self::expect(null, let final self::Class* #t41 = c in #t41.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t42 = null in let final void #t43 = self::Extension|set#property(#t41, #t42) in #t42);
-  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 42) : null;
+  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final core::int* #t33 = 42 in let final void #t34 = self::Extension|set#property(#t31, #t33) in #t33 : #t32);
+  self::expect(42, let final self::Class* #t35 = c in let final core::int* #t36 = self::Extension|get#property(#t35) in #t36.{core::num::==}(null) ?{core::int*} let final core::int* #t37 = 87 in let final void #t38 = self::Extension|set#property(#t35, #t37) in #t37 : #t36);
+  self::expect(null, let final self::Class* #t39 = c in #t39.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t40 = null in let final void #t41 = self::Extension|set#property(#t39, #t40) in #t40);
+  let final self::Class* #t42 = c in self::Extension|get#property(#t42).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t42, 42) : null;
+  self::expect(42, let final self::Class* #t43 = c in #t43.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t43));
+  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 87) : null;
   self::expect(42, let final self::Class* #t45 = c in #t45.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t45));
-  let final self::Class* #t46 = c in self::Extension|get#property(#t46).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t46, 87) : null;
-  self::expect(42, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
-  let final self::Class* #t48 = c in #t48.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t48, null);
-  self::expect(null, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t49));
-  self::expect(42, let final self::Class* #t50 = c in let final core::int* #t51 = self::Extension|get#property(#t50) in #t51.{core::num::==}(null) ?{core::int*} let final core::int* #t52 = 42 in let final void #t53 = self::Extension|set#property(#t50, #t52) in #t52 : #t51);
-  self::expect(42, let final self::Class* #t54 = c in let final core::int* #t55 = self::Extension|get#property(#t54) in #t55.{core::num::==}(null) ?{core::int*} let final core::int* #t56 = 87 in let final void #t57 = self::Extension|set#property(#t54, #t56) in #t56 : #t55);
-  let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t58, null);
-  self::expect(null, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
-  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 42) : null;
+  let final self::Class* #t46 = c in #t46.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t46, null);
+  self::expect(null, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
+  self::expect(42, let final self::Class* #t48 = c in let final core::int* #t49 = self::Extension|get#property(#t48) in #t49.{core::num::==}(null) ?{core::int*} let final core::int* #t50 = 42 in let final void #t51 = self::Extension|set#property(#t48, #t50) in #t50 : #t49);
+  self::expect(42, let final self::Class* #t52 = c in let final core::int* #t53 = self::Extension|get#property(#t52) in #t53.{core::num::==}(null) ?{core::int*} let final core::int* #t54 = 87 in let final void #t55 = self::Extension|set#property(#t52, #t54) in #t54 : #t53);
+  let final self::Class* #t56 = c in #t56.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t56, null);
+  self::expect(null, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t57));
+  let final self::Class* #t58 = c in self::Extension|get#property(#t58).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t58, 42) : null;
+  self::expect(42, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
+  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 87) : null;
   self::expect(42, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t61));
-  let final self::Class* #t62 = c in self::Extension|get#property(#t62).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t62, 87) : null;
-  self::expect(42, let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t63));
-  let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t64, null);
+  let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t62, null);
   self::Extension|testImplicitThis(c);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
index 6d32899..c5a31af 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
@@ -50,24 +50,24 @@
   self::expect(42, let final self::Class* #t26 = c in #t26.{core::Object::==}(null) ?{core::int*} null : let final core::int* #t27 = 42 in let final void #t28 = self::Extension|set#property(#t26, #t27) in #t27);
   let final self::Class* #t29 = c in #t29.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t29, null);
   self::expect(null, let final self::Class* #t30 = c in #t30.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t30));
-  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final self::Class* #t33 = #t31 in let final core::int* #t34 = 42 in let final void #t35 = self::Extension|set#property(#t33, #t34) in #t34 : #t32);
-  self::expect(42, let final self::Class* #t36 = c in let final core::int* #t37 = self::Extension|get#property(#t36) in #t37.{core::num::==}(null) ?{core::int*} let final self::Class* #t38 = #t36 in let final core::int* #t39 = 87 in let final void #t40 = self::Extension|set#property(#t38, #t39) in #t39 : #t37);
-  self::expect(null, let final self::Class* #t41 = c in #t41.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t42 = null in let final void #t43 = self::Extension|set#property(#t41, #t42) in #t42);
-  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 42) : null;
+  self::expect(42, let final self::Class* #t31 = c in let final core::int* #t32 = self::Extension|get#property(#t31) in #t32.{core::num::==}(null) ?{core::int*} let final core::int* #t33 = 42 in let final void #t34 = self::Extension|set#property(#t31, #t33) in #t33 : #t32);
+  self::expect(42, let final self::Class* #t35 = c in let final core::int* #t36 = self::Extension|get#property(#t35) in #t36.{core::num::==}(null) ?{core::int*} let final core::int* #t37 = 87 in let final void #t38 = self::Extension|set#property(#t35, #t37) in #t37 : #t36);
+  self::expect(null, let final self::Class* #t39 = c in #t39.{core::Object::==}(null) ?{core::Null?} null : let final core::Null? #t40 = null in let final void #t41 = self::Extension|set#property(#t39, #t40) in #t40);
+  let final self::Class* #t42 = c in self::Extension|get#property(#t42).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t42, 42) : null;
+  self::expect(42, let final self::Class* #t43 = c in #t43.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t43));
+  let final self::Class* #t44 = c in self::Extension|get#property(#t44).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t44, 87) : null;
   self::expect(42, let final self::Class* #t45 = c in #t45.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t45));
-  let final self::Class* #t46 = c in self::Extension|get#property(#t46).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t46, 87) : null;
-  self::expect(42, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
-  let final self::Class* #t48 = c in #t48.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t48, null);
-  self::expect(null, let final self::Class* #t49 = c in #t49.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t49));
-  self::expect(42, let final self::Class* #t50 = c in let final core::int* #t51 = self::Extension|get#property(#t50) in #t51.{core::num::==}(null) ?{core::int*} let final core::int* #t52 = 42 in let final void #t53 = self::Extension|set#property(#t50, #t52) in #t52 : #t51);
-  self::expect(42, let final self::Class* #t54 = c in let final core::int* #t55 = self::Extension|get#property(#t54) in #t55.{core::num::==}(null) ?{core::int*} let final core::int* #t56 = 87 in let final void #t57 = self::Extension|set#property(#t54, #t56) in #t56 : #t55);
-  let final self::Class* #t58 = c in #t58.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t58, null);
-  self::expect(null, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
-  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 42) : null;
+  let final self::Class* #t46 = c in #t46.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t46, null);
+  self::expect(null, let final self::Class* #t47 = c in #t47.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t47));
+  self::expect(42, let final self::Class* #t48 = c in let final core::int* #t49 = self::Extension|get#property(#t48) in #t49.{core::num::==}(null) ?{core::int*} let final core::int* #t50 = 42 in let final void #t51 = self::Extension|set#property(#t48, #t50) in #t50 : #t49);
+  self::expect(42, let final self::Class* #t52 = c in let final core::int* #t53 = self::Extension|get#property(#t52) in #t53.{core::num::==}(null) ?{core::int*} let final core::int* #t54 = 87 in let final void #t55 = self::Extension|set#property(#t52, #t54) in #t54 : #t53);
+  let final self::Class* #t56 = c in #t56.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t56, null);
+  self::expect(null, let final self::Class* #t57 = c in #t57.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t57));
+  let final self::Class* #t58 = c in self::Extension|get#property(#t58).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t58, 42) : null;
+  self::expect(42, let final self::Class* #t59 = c in #t59.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t59));
+  let final self::Class* #t60 = c in self::Extension|get#property(#t60).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t60, 87) : null;
   self::expect(42, let final self::Class* #t61 = c in #t61.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t61));
-  let final self::Class* #t62 = c in self::Extension|get#property(#t62).{core::num::==}(null) ?{core::int*} self::Extension|set#property(#t62, 87) : null;
-  self::expect(42, let final self::Class* #t63 = c in #t63.{core::Object::==}(null) ?{core::int*} null : self::Extension|get#property(#t63));
-  let final self::Class* #t64 = c in #t64.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t64, null);
+  let final self::Class* #t62 = c in #t62.{core::Object::==}(null) ?{core::Null?} null : self::Extension|set#property(#t62, null);
   self::Extension|testImplicitThis(c);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
index 157b936..86383f9 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.expect
@@ -8,18 +8,18 @@
 //   nonStruct.method();
 //             ^^^^^^
 //
-// pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:13: Error: The setter 'property' isn't defined for the class 'NonStruct'.
-//  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
-//   nonStruct.property = nonStruct.property;
-//             ^^^^^^^^
-//
 // pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:34: Error: The getter 'property' isn't defined for the class 'NonStruct'.
 //  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
 //   nonStruct.property = nonStruct.property;
 //                                  ^^^^^^^^
 //
+// pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:13: Error: The setter 'property' isn't defined for the class 'NonStruct'.
+//  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+//   nonStruct.property = nonStruct.property;
+//             ^^^^^^^^
+//
 // pkg/front_end/testcases/extensions/on_type_variable_inference.dart:46:19: Error: The method 'method' isn't defined for the class 'NonStruct'.
 //  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
 // Try correcting the name to the name of an existing method, or defining a method named 'method'.
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
index 157b936..86383f9 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.strong.transformed.expect
@@ -8,18 +8,18 @@
 //   nonStruct.method();
 //             ^^^^^^
 //
-// pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:13: Error: The setter 'property' isn't defined for the class 'NonStruct'.
-//  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
-//   nonStruct.property = nonStruct.property;
-//             ^^^^^^^^
-//
 // pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:34: Error: The getter 'property' isn't defined for the class 'NonStruct'.
 //  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
 // Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
 //   nonStruct.property = nonStruct.property;
 //                                  ^^^^^^^^
 //
+// pkg/front_end/testcases/extensions/on_type_variable_inference.dart:45:13: Error: The setter 'property' isn't defined for the class 'NonStruct'.
+//  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+//   nonStruct.property = nonStruct.property;
+//             ^^^^^^^^
+//
 // pkg/front_end/testcases/extensions/on_type_variable_inference.dart:46:19: Error: The method 'method' isn't defined for the class 'NonStruct'.
 //  - 'NonStruct' is from 'pkg/front_end/testcases/extensions/on_type_variable_inference.dart'.
 // Try correcting the name to the name of an existing method, or defining a method named 'method'.
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
index ee67c10..2e08d1f 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.expect
@@ -92,35 +92,35 @@
   self::expect(89, self::_extension#0|genericMethod<core::num*>(c1, 88));
   self::expect(0, self::_extension#0|get#property(c0));
   self::expect(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t2));
-  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::_extension#0|set#property(#t3, #t4) in #t4);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::_extension#0|set#property(c0, #t3) in #t3);
   self::expect(1, self::_extension#0|get#property(c1));
-  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::_extension#0|set#property(#t6, #t7) in #t7);
-  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::_extension#0|set#property(#t11, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(#t9, #t10) in #t10);
-  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::_extension#0|set#property(#t17, #t18) in #t18 in let final void #t20 = self::_extension#0|set#property(#t15, #t16) in #t16);
-  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::_extension#0|set#property(#t25, #t26) in #t26 in let final void #t28 = self::_extension#0|set#property(#t23, #t24) in #t24 in let final void #t29 = self::_extension#0|set#property(#t21, #t22) in #t22);
-  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::_extension#0|set#property(#t34, #t35) in #t35 in let final void #t37 = self::_extension#0|set#property(#t32, #t33) in #t33 in let final void #t38 = self::_extension#0|set#property(#t30, #t31) in #t31);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::_extension#0|set#property(c0, #t5) in #t5);
+  self::expect(27, let final core::int* #t7 = let final core::int* #t8 = 27 in let final void #t9 = self::_extension#0|set#property(c1, #t8) in #t8 in let final void #t10 = self::_extension#0|set#property(c0, #t7) in #t7);
+  self::expect(37, let final core::int* #t11 = let final core::int* #t12 = 37 in let final void #t13 = self::_extension#0|set#property(c0, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(c1, #t11) in #t11);
+  self::expect(77, let final core::int* #t15 = let final core::int* #t16 = let final core::int* #t17 = 77 in let final void #t18 = self::_extension#0|set#property(c1, #t17) in #t17 in let final void #t19 = self::_extension#0|set#property(c0, #t16) in #t16 in let final void #t20 = self::_extension#0|set#property(c1, #t15) in #t15);
+  self::expect(67, let final core::int* #t21 = let final core::int* #t22 = let final core::int* #t23 = 67 in let final void #t24 = self::_extension#0|set#property(c0, #t23) in #t23 in let final void #t25 = self::_extension#0|set#property(c1, #t22) in #t22 in let final void #t26 = self::_extension#0|set#property(c0, #t21) in #t21);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::_extension#1|method(c0));
-  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t39));
+  self::expect(3, let final self::Class2* #t27 = c0 in #t27.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t27));
   self::expect(4, self::_extension#1|method(c1));
   self::expect(46, self::_extension#1|genericMethod<core::int*>(c0, 42));
   self::expect(47, self::_extension#1|genericMethod<core::num*>(c0, 43));
   self::expect(92, self::_extension#1|genericMethod<core::int*>(c1, 87));
   self::expect(93, self::_extension#1|genericMethod<core::num*>(c1, 88));
   self::expect(5, self::_extension#1|get#property(c0));
-  self::expect(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t40));
-  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::_extension#1|set#property(#t41, #t42) in #t42);
+  self::expect(5, let final self::Class2* #t28 = c0 in #t28.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t28));
+  self::expect(42, let final core::int* #t29 = 42 in let final void #t30 = self::_extension#1|set#property(c0, #t29) in #t29);
   self::expect(48, self::_extension#1|get#property(c0));
   self::expect(6, self::_extension#1|get#property(c1));
-  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::_extension#1|set#property(#t44, #t45) in #t45);
+  self::expect(43, let final core::int* #t31 = 43 in let final void #t32 = self::_extension#1|set#property(c1, #t31) in #t31);
   self::expect(49, self::_extension#1|get#property(c1));
-  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::_extension#1|get#property(c1) in let final void #t49 = self::_extension#1|set#property(#t47, #t48) in #t48);
-  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::_extension#1|get#property(c0) in let final void #t52 = self::_extension#1|set#property(#t50, #t51) in #t51);
-  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::_extension#1|get#property(c1) in let final void #t57 = self::_extension#1|set#property(#t55, #t56) in #t56 in let final void #t58 = self::_extension#1|set#property(#t53, #t54) in #t54);
-  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::_extension#1|get#property(c0) in let final void #t63 = self::_extension#1|set#property(#t61, #t62) in #t62 in let final void #t64 = self::_extension#1|set#property(#t59, #t60) in #t60);
+  self::expect(49, let final core::int* #t33 = self::_extension#1|get#property(c1) in let final void #t34 = self::_extension#1|set#property(c0, #t33) in #t33);
+  self::expect(55, let final core::int* #t35 = self::_extension#1|get#property(c0) in let final void #t36 = self::_extension#1|set#property(c1, #t35) in #t35);
+  self::expect(61, let final core::int* #t37 = let final core::int* #t38 = self::_extension#1|get#property(c1) in let final void #t39 = self::_extension#1|set#property(c0, #t38) in #t38 in let final void #t40 = self::_extension#1|set#property(c1, #t37) in #t37);
+  self::expect(67, let final core::int* #t41 = let final core::int* #t42 = self::_extension#1|get#property(c0) in let final void #t43 = self::_extension#1|set#property(c1, #t42) in #t42 in let final void #t44 = self::_extension#1|set#property(c0, #t41) in #t41);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
index ee67c10..2e08d1f 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
@@ -92,35 +92,35 @@
   self::expect(89, self::_extension#0|genericMethod<core::num*>(c1, 88));
   self::expect(0, self::_extension#0|get#property(c0));
   self::expect(0, let final self::Class1* #t2 = c0 in #t2.{core::Object::==}(null) ?{core::int*} null : self::_extension#0|get#property(#t2));
-  self::expect(42, let final self::Class1* #t3 = c0 in let final core::int* #t4 = 42 in let final void #t5 = self::_extension#0|set#property(#t3, #t4) in #t4);
+  self::expect(42, let final core::int* #t3 = 42 in let final void #t4 = self::_extension#0|set#property(c0, #t3) in #t3);
   self::expect(1, self::_extension#0|get#property(c1));
-  self::expect(87, let final self::Class1* #t6 = c0 in let final core::int* #t7 = 87 in let final void #t8 = self::_extension#0|set#property(#t6, #t7) in #t7);
-  self::expect(27, let final self::Class1* #t9 = c0 in let final core::int* #t10 = let final self::Class1* #t11 = c1 in let final core::int* #t12 = 27 in let final void #t13 = self::_extension#0|set#property(#t11, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(#t9, #t10) in #t10);
-  self::expect(37, let final self::Class1* #t15 = c1 in let final core::int* #t16 = let final self::Class1* #t17 = c0 in let final core::int* #t18 = 37 in let final void #t19 = self::_extension#0|set#property(#t17, #t18) in #t18 in let final void #t20 = self::_extension#0|set#property(#t15, #t16) in #t16);
-  self::expect(77, let final self::Class1* #t21 = c1 in let final core::int* #t22 = let final self::Class1* #t23 = c0 in let final core::int* #t24 = let final self::Class1* #t25 = c1 in let final core::int* #t26 = 77 in let final void #t27 = self::_extension#0|set#property(#t25, #t26) in #t26 in let final void #t28 = self::_extension#0|set#property(#t23, #t24) in #t24 in let final void #t29 = self::_extension#0|set#property(#t21, #t22) in #t22);
-  self::expect(67, let final self::Class1* #t30 = c0 in let final core::int* #t31 = let final self::Class1* #t32 = c1 in let final core::int* #t33 = let final self::Class1* #t34 = c0 in let final core::int* #t35 = 67 in let final void #t36 = self::_extension#0|set#property(#t34, #t35) in #t35 in let final void #t37 = self::_extension#0|set#property(#t32, #t33) in #t33 in let final void #t38 = self::_extension#0|set#property(#t30, #t31) in #t31);
+  self::expect(87, let final core::int* #t5 = 87 in let final void #t6 = self::_extension#0|set#property(c0, #t5) in #t5);
+  self::expect(27, let final core::int* #t7 = let final core::int* #t8 = 27 in let final void #t9 = self::_extension#0|set#property(c1, #t8) in #t8 in let final void #t10 = self::_extension#0|set#property(c0, #t7) in #t7);
+  self::expect(37, let final core::int* #t11 = let final core::int* #t12 = 37 in let final void #t13 = self::_extension#0|set#property(c0, #t12) in #t12 in let final void #t14 = self::_extension#0|set#property(c1, #t11) in #t11);
+  self::expect(77, let final core::int* #t15 = let final core::int* #t16 = let final core::int* #t17 = 77 in let final void #t18 = self::_extension#0|set#property(c1, #t17) in #t17 in let final void #t19 = self::_extension#0|set#property(c0, #t16) in #t16 in let final void #t20 = self::_extension#0|set#property(c1, #t15) in #t15);
+  self::expect(67, let final core::int* #t21 = let final core::int* #t22 = let final core::int* #t23 = 67 in let final void #t24 = self::_extension#0|set#property(c0, #t23) in #t23 in let final void #t25 = self::_extension#0|set#property(c1, #t22) in #t22 in let final void #t26 = self::_extension#0|set#property(c0, #t21) in #t21);
 }
 static method testExtension2() → dynamic {
   self::Class2* c0 = new self::Class2::•(0);
   self::Class2* c1 = new self::Class2::•(1);
   self::expect(3, self::_extension#1|method(c0));
-  self::expect(3, let final self::Class2* #t39 = c0 in #t39.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t39));
+  self::expect(3, let final self::Class2* #t27 = c0 in #t27.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|method(#t27));
   self::expect(4, self::_extension#1|method(c1));
   self::expect(46, self::_extension#1|genericMethod<core::int*>(c0, 42));
   self::expect(47, self::_extension#1|genericMethod<core::num*>(c0, 43));
   self::expect(92, self::_extension#1|genericMethod<core::int*>(c1, 87));
   self::expect(93, self::_extension#1|genericMethod<core::num*>(c1, 88));
   self::expect(5, self::_extension#1|get#property(c0));
-  self::expect(5, let final self::Class2* #t40 = c0 in #t40.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t40));
-  self::expect(42, let final self::Class2* #t41 = c0 in let final core::int* #t42 = 42 in let final void #t43 = self::_extension#1|set#property(#t41, #t42) in #t42);
+  self::expect(5, let final self::Class2* #t28 = c0 in #t28.{core::Object::==}(null) ?{core::int*} null : self::_extension#1|get#property(#t28));
+  self::expect(42, let final core::int* #t29 = 42 in let final void #t30 = self::_extension#1|set#property(c0, #t29) in #t29);
   self::expect(48, self::_extension#1|get#property(c0));
   self::expect(6, self::_extension#1|get#property(c1));
-  self::expect(43, let final self::Class2* #t44 = c1 in let final core::int* #t45 = 43 in let final void #t46 = self::_extension#1|set#property(#t44, #t45) in #t45);
+  self::expect(43, let final core::int* #t31 = 43 in let final void #t32 = self::_extension#1|set#property(c1, #t31) in #t31);
   self::expect(49, self::_extension#1|get#property(c1));
-  self::expect(49, let final self::Class2* #t47 = c0 in let final core::int* #t48 = self::_extension#1|get#property(c1) in let final void #t49 = self::_extension#1|set#property(#t47, #t48) in #t48);
-  self::expect(55, let final self::Class2* #t50 = c1 in let final core::int* #t51 = self::_extension#1|get#property(c0) in let final void #t52 = self::_extension#1|set#property(#t50, #t51) in #t51);
-  self::expect(61, let final self::Class2* #t53 = c1 in let final core::int* #t54 = let final self::Class2* #t55 = c0 in let final core::int* #t56 = self::_extension#1|get#property(c1) in let final void #t57 = self::_extension#1|set#property(#t55, #t56) in #t56 in let final void #t58 = self::_extension#1|set#property(#t53, #t54) in #t54);
-  self::expect(67, let final self::Class2* #t59 = c0 in let final core::int* #t60 = let final self::Class2* #t61 = c1 in let final core::int* #t62 = self::_extension#1|get#property(c0) in let final void #t63 = self::_extension#1|set#property(#t61, #t62) in #t62 in let final void #t64 = self::_extension#1|set#property(#t59, #t60) in #t60);
+  self::expect(49, let final core::int* #t33 = self::_extension#1|get#property(c1) in let final void #t34 = self::_extension#1|set#property(c0, #t33) in #t33);
+  self::expect(55, let final core::int* #t35 = self::_extension#1|get#property(c0) in let final void #t36 = self::_extension#1|set#property(c1, #t35) in #t35);
+  self::expect(61, let final core::int* #t37 = let final core::int* #t38 = self::_extension#1|get#property(c1) in let final void #t39 = self::_extension#1|set#property(c0, #t38) in #t38 in let final void #t40 = self::_extension#1|set#property(c1, #t37) in #t37);
+  self::expect(67, let final core::int* #t41 = let final core::int* #t42 = self::_extension#1|get#property(c0) in let final void #t43 = self::_extension#1|set#property(c1, #t42) in #t42 in let final void #t44 = self::_extension#1|set#property(c0, #t41) in #t41);
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
   if(!expected.{core::Object::==}(actual)) {
diff --git a/pkg/front_end/testcases/general/assign_to_initializing_formal.dart b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart
new file mode 100644
index 0000000..dd3d5b3
--- /dev/null
+++ b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart
@@ -0,0 +1,17 @@
+// 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:expect/expect.dart";
+
+class A {
+  var x, y;
+  // This should cause an error because `x` is final when accessed as an
+  // initializing formal.
+  A(this.x)
+      : y = (() {
+          x = 3;
+        });
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.outline.expect b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.outline.expect
new file mode 100644
index 0000000..5834746
--- /dev/null
+++ b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  field dynamic x;
+  field dynamic y;
+  constructor •(dynamic x) → self::A*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.expect b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.expect
new file mode 100644
index 0000000..952e217
--- /dev/null
+++ b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/assign_to_initializing_formal.dart:13:11: Error: Setter not found: 'x'.
+//           x = 3;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  field dynamic x;
+  field dynamic y;
+  constructor •(dynamic x) → self::A*
+    : self::A::x = x, self::A::y = () → core::Null? {
+      invalid-expression "pkg/front_end/testcases/general/assign_to_initializing_formal.dart:13:11: Error: Setter not found: 'x'.
+          x = 3;
+          ^";
+    }, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.transformed.expect b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.transformed.expect
new file mode 100644
index 0000000..952e217
--- /dev/null
+++ b/pkg/front_end/testcases/general/assign_to_initializing_formal.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/assign_to_initializing_formal.dart:13:11: Error: Setter not found: 'x'.
+//           x = 3;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  field dynamic x;
+  field dynamic y;
+  constructor •(dynamic x) → self::A*
+    : self::A::x = x, self::A::y = () → core::Null? {
+      invalid-expression "pkg/front_end/testcases/general/assign_to_initializing_formal.dart:13:11: Error: Setter not found: 'x'.
+          x = 3;
+          ^";
+    }, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
index 7949f03..50f5128 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -2,111 +2,111 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> extends A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Bc<T> extends A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Bi<T> extends A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class C<T> implements A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Cc<T> implements A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ci<T> implements A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class D<T> = Object with A<Function(T)>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Dc<T> = Object with A<ContravariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Di<T> = Object with A<InvariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class E<T> = A<Function(T)> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Ec<T> = A<ContravariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ei<T> = A<InvariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class F<T> extends Object with A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Fc<T> extends Object with A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Fi<T> extends Object with A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class G<T> extends A<Function(T)> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Gc<T> extends A<ContravariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Gi<T> extends A<InvariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfff<T> extends A<Function(Function(Function(T)))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccc<T>
 //       ^
 //
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
index efccee2..74cbe0c 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -2,111 +2,111 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> extends A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Bc<T> extends A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Bi<T> extends A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class C<T> implements A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Cc<T> implements A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ci<T> implements A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class D<T> = Object with A<Function(T)>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Dc<T> = Object with A<ContravariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Di<T> = Object with A<InvariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class E<T> = A<Function(T)> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Ec<T> = A<ContravariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ei<T> = A<InvariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class F<T> extends Object with A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Fc<T> extends Object with A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Fi<T> extends Object with A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class G<T> extends A<Function(T)> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Gc<T> extends A<ContravariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Gi<T> extends A<InvariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfff<T> extends A<Function(Function(Function(T)))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccc<T>
 //       ^
 //
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index 8a0566b..84a6515 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -2,111 +2,111 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> extends A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Bc<T> extends A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Bi<T> extends A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class C<T> implements A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Cc<T> implements A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ci<T> implements A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class D<T> = Object with A<Function(T)>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Dc<T> = Object with A<ContravariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Di<T> = Object with A<InvariantUse<T>>;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class E<T> = A<Function(T)> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Ec<T> = A<ContravariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Ei<T> = A<InvariantUse<T>> with Empty;
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class F<T> extends Object with A<Function(T)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Fc<T> extends Object with A<ContravariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Fi<T> extends Object with A<InvariantUse<T>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class G<T> extends A<Function(T)> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Gc<T> extends A<ContravariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Gi<T> extends A<InvariantUse<T>> with Empty {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Can't use implicitly 'out' variable 'T' in an 'inout' position in supertype 'A'.
 // class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfff<T> extends A<Function(Function(Function(T)))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
 //       ^
 //
-// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class Jccc<T>
 //       ^
 //
diff --git a/pkg/front_end/testcases/general/bug33206.dart.strong.expect b/pkg/front_end/testcases/general/bug33206.dart.strong.expect
index 9135f7d..89809db 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.strong.expect
@@ -29,7 +29,7 @@
   return 3;
 }
 static method foo() → asy::Future<self::X*>* async {
-  return new self::X::•(let final self::Y* #t1 = new self::Y::•() in let final dynamic #t2 = #t1.{self::Y::f}(await self::f1()) in let final dynamic #t3 = #t1.{self::Y::f}(self::f2()) in #t1, await self::f3());
+  return new self::X::•(let final self::Y* #t1 = new self::Y::•() in let final void #t2 = #t1.{self::Y::f}(await self::f1()) in let final void #t3 = #t1.{self::Y::f}(self::f2()) in #t1, await self::f3());
 }
 static method main() → asy::Future<void>* async {
   core::print(await self::foo());
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 2e15c12..6e31cf5 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
@@ -91,8 +91,8 @@
       {
         final self::Y* #t1 = new self::Y::•();
         [yield] let dynamic #t2 = asy::_awaitHelper(self::f1(), :async_op_then, :async_op_error, :async_op) in null;
-        final dynamic #t3 = #t1.{self::Y::f}(:result);
-        final dynamic #t4 = #t1.{self::Y::f}(self::f2());
+        final void #t3 = #t1.{self::Y::f}(:result);
+        final void #t4 = #t1.{self::Y::f}(self::f2());
         [yield] let dynamic #t5 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
         :return_value = new self::X::•(#t1, :result);
         break #L3;
diff --git a/pkg/front_end/testcases/general/cascade.dart.strong.expect b/pkg/front_end/testcases/general/cascade.dart.strong.expect
index 808b5ca..1536d20 100644
--- a/pkg/front_end/testcases/general/cascade.dart.strong.expect
+++ b/pkg/front_end/testcases/general/cascade.dart.strong.expect
@@ -26,22 +26,22 @@
 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 let final dynamic #t2 = #t1.{core::List::add}(2) in let final dynamic #t3 = #t1.{core::List::add}(3) in let final dynamic #t4 = #t1.{core::List::addAll}(<core::int*>[4, 5]) in #t1;
+  core::List<core::int*>* list = let final core::List<core::int*>* #t1 = <core::int*>[1] in let final void #t2 = #t1.{core::List::add}(2) in let final void #t3 = #t1.{core::List::add}(3) in let final void #t4 = #t1.{core::List::addAll}(<core::int*>[4, 5]) in #t1;
   core::print(list);
-  let final core::List<core::int*>* #t5 = list in let final dynamic #t6 = #t5.{core::List::add}(2) in let final dynamic #t7 = #t5.{core::List::length} in let final dynamic #t8 = #t5.{core::List::length} = 0 in #t5;
+  let final core::List<core::int*>* #t5 = list in let final void #t6 = #t5.{core::List::add}(2) in let final void #t7 = #t5.{core::List::length} in let final void #t8 = #t5.{core::List::length} = 0 in #t5;
   core::print(list);
-  let final core::List<core::int*>* #t9 = list in let final dynamic #t10 = #t9.{core::List::add}(2) in let final dynamic #t11 = #t9.{core::List::[]}(0) in let final dynamic #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
+  let final core::List<core::int*>* #t9 = list in let final void #t10 = #t9.{core::List::add}(2) in let final void #t11 = #t9.{core::List::[]}(0) in let final void #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
   core::print(list);
   list = let final core::List<core::int*>* #t13 = <core::int*>[let final<BottomType> #t14 = 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 let final dynamic #t15 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'int'.
+    ^" in <core::int*>[1] as{TypeError} core::int*] in let final void #t15 = 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()
-            ^^^^".{core::Object::toString}() in let final dynamic #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
+            ^^^^".{core::Object::toString}() in let final void #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
 Try correcting the name to the name of an existing method, or defining a method named '[]'.
     ..first[0].toString()
-           ^^".{core::Object::toString}() in let final dynamic #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
+           ^^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: 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'.
     ..[0].last.toString();
           ^^^^".{core::Object::toString}() in #t13;
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 a6369df..1536d20 100644
--- a/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
@@ -28,20 +28,20 @@
 static method main() → dynamic {
   core::List<core::int*>* list = let final core::List<core::int*>* #t1 = <core::int*>[1] in let final void #t2 = #t1.{core::List::add}(2) in let final void #t3 = #t1.{core::List::add}(3) in let final void #t4 = #t1.{core::List::addAll}(<core::int*>[4, 5]) in #t1;
   core::print(list);
-  let final core::List<core::int*>* #t5 = list in let final void #t6 = #t5.{core::List::add}(2) in let final core::int* #t7 = #t5.{core::List::length} in let final core::int* #t8 = #t5.{core::List::length} = 0 in #t5;
+  let final core::List<core::int*>* #t5 = list in let final void #t6 = #t5.{core::List::add}(2) in let final void #t7 = #t5.{core::List::length} in let final void #t8 = #t5.{core::List::length} = 0 in #t5;
   core::print(list);
-  let final core::List<core::int*>* #t9 = list in let final void #t10 = #t9.{core::List::add}(2) in let final core::int* #t11 = #t9.{core::List::[]}(0) in let final void #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
+  let final core::List<core::int*>* #t9 = list in let final void #t10 = #t9.{core::List::add}(2) in let final void #t11 = #t9.{core::List::[]}(0) in let final void #t12 = #t9.{core::List::[]=}(0, 87) in #t9;
   core::print(list);
   list = let final core::List<core::int*>* #t13 = <core::int*>[let final<BottomType> #t14 = 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 let final core::String* #t15 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:28:13: Error: The getter 'last' isn't defined for the class 'int'.
+    ^" in <core::int*>[1] as{TypeError} core::int*] in let final void #t15 = 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()
-            ^^^^".{core::Object::toString}() in let final core::String* #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
+            ^^^^".{core::Object::toString}() in let final void #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
 Try correcting the name to the name of an existing method, or defining a method named '[]'.
     ..first[0].toString()
-           ^^".{core::Object::toString}() in let final core::String* #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
+           ^^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: 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'.
     ..[0].last.toString();
           ^^^^".{core::Object::toString}() in #t13;
diff --git a/pkg/front_end/testcases/general/expressions.dart.strong.expect b/pkg/front_end/testcases/general/expressions.dart.strong.expect
index 7826eeb..3a13247 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.expect
@@ -74,7 +74,7 @@
   });
   core::print(core::int*.{core::Object::toString}());
   core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in let final dynamic #t6 = #t5.{core::Object::toString}() in #t5);
+  core::print(let final core::Type* #t5 = core::int* in let final void #t6 = #t5.{core::Object::toString}() in #t5);
   try {
     core::print(invalid-expression "pkg/front_end/testcases/general/expressions.dart:74:16: Error: Method not found: 'int.toString'.
     print(int?.toString());
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 d50717a..2f75ab9 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
@@ -74,7 +74,7 @@
   });
   core::print(core::int*.{core::Object::toString}());
   core::print(core::int*);
-  core::print(let final core::Type* #t5 = core::int* in let final core::String* #t6 = #t5.{core::Object::toString}() in #t5);
+  core::print(let final core::Type* #t5 = core::int* in let final void #t6 = #t5.{core::Object::toString}() in #t5);
   try {
     core::print(invalid-expression "pkg/front_end/testcases/general/expressions.dart:74:16: Error: Method not found: 'int.toString'.
     print(int?.toString());
diff --git a/pkg/front_end/testcases/general/fallthrough.dart.strong.expect b/pkg/front_end/testcases/general/fallthrough.dart.strong.expect
index b4eb852..75e6040 100644
--- a/pkg/front_end/testcases/general/fallthrough.dart.strong.expect
+++ b/pkg/front_end/testcases/general/fallthrough.dart.strong.expect
@@ -1,45 +1,36 @@
-// Formatted problems:
-//
-// pkg/front_end/testcases/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
-//     case 3:
-//     ^
-//
-// pkg/front_end/testcases/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
-//     case 6:
-//     ^
-
-// Unhandled errors:
-//
-// pkg/front_end/testcases/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
-//     case 3:
-//     ^
-//
-// pkg/front_end/testcases/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
-//     case 6:
-//     ^
-
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/general/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
+//     case 6:
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
-static method main(core::List<core::String> args) → void {
-  core::int x = args.{core::List::length};
+static method main(core::List<core::String*>* args) → void {
+  core::int* x = args.{core::List::length};
   #L1:
   switch(x) {
     #L2:
-    case 3:
+    case #C1:
       {
         x = 4;
         throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 8);
       }
     #L3:
-    case 5:
+    case #C2:
       {
         break #L1;
       }
     #L4:
-    case 6:
-    case 7:
+    case #C3:
+    case #C4:
       {
         if(args.{core::List::[]}(0).{core::String::==}("")) {
           break #L1;
@@ -50,9 +41,15 @@
         throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 12);
       }
     #L5:
-    case 4:
-      {
-        break #L1;
-      }
+    case #C5:
+      {}
   }
 }
+
+constants  {
+  #C1 = 3
+  #C2 = 5
+  #C3 = 6
+  #C4 = 7
+  #C5 = 4
+}
diff --git a/pkg/front_end/testcases/general/fallthrough.dart.strong.transformed.expect b/pkg/front_end/testcases/general/fallthrough.dart.strong.transformed.expect
new file mode 100644
index 0000000..75e6040
--- /dev/null
+++ b/pkg/front_end/testcases/general/fallthrough.dart.strong.transformed.expect
@@ -0,0 +1,55 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/fallthrough.dart:8:5: Error: Switch case may fall through to the next case.
+//     case 3:
+//     ^
+//
+// pkg/front_end/testcases/general/fallthrough.dart:12:5: Error: Switch case may fall through to the next case.
+//     case 6:
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method main(core::List<core::String*>* args) → void {
+  core::int* x = args.{core::List::length};
+  #L1:
+  switch(x) {
+    #L2:
+    case #C1:
+      {
+        x = 4;
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 8);
+      }
+    #L3:
+    case #C2:
+      {
+        break #L1;
+      }
+    #L4:
+    case #C3:
+    case #C4:
+      {
+        if(args.{core::List::[]}(0).{core::String::==}("")) {
+          break #L1;
+        }
+        else {
+          return;
+        }
+        throw new core::FallThroughError::_create("org-dartlang-testcase:///fallthrough.dart", 12);
+      }
+    #L5:
+    case #C5:
+      {}
+  }
+}
+
+constants  {
+  #C1 = 3
+  #C2 = 5
+  #C3 = 6
+  #C4 = 7
+  #C5 = 4
+}
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
index fe5752c..6916586 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
@@ -52,11 +52,11 @@
 //     for (unresolved in []) {}
 //          ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:21: Error: The setter 'foo' isn't defined for the class 'C'.
+// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: The getter 'unresolved' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
 //     for (unresolved.foo in []) {}
-//                     ^^^
+//          ^^^^^^^^^^
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:39:12: Error: The setter 'unresolved' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
@@ -130,11 +130,11 @@
          ^^^^^^^^^^";
     }
     for (final dynamic #t14 in <dynamic>[]) {
-      invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:38:21: Error: The setter 'foo' isn't defined for the class 'C'.
+      invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: The getter 'unresolved' isn't defined for the class 'C'.
  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
     for (unresolved.foo in []) {}
-                    ^^^";
+         ^^^^^^^^^^".foo = #t14;
     }
     for (final dynamic #t15 in <dynamic>[]) {
       invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:39:12: Error: The setter 'unresolved' isn't defined for the class 'C'.
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 fe5752c..6916586 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
@@ -52,11 +52,11 @@
 //     for (unresolved in []) {}
 //          ^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:21: Error: The setter 'foo' isn't defined for the class 'C'.
+// pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: The getter 'unresolved' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
-// Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
 //     for (unresolved.foo in []) {}
-//                     ^^^
+//          ^^^^^^^^^^
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:39:12: Error: The setter 'unresolved' isn't defined for the class 'C'.
 //  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
@@ -130,11 +130,11 @@
          ^^^^^^^^^^";
     }
     for (final dynamic #t14 in <dynamic>[]) {
-      invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:38:21: Error: The setter 'foo' isn't defined for the class 'C'.
+      invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:38:10: Error: The getter 'unresolved' isn't defined for the class 'C'.
  - 'C' is from 'pkg/front_end/testcases/general/for_in_without_declaration.dart'.
-Try correcting the name to the name of an existing setter, or defining a setter or field named 'foo'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'unresolved'.
     for (unresolved.foo in []) {}
-                    ^^^";
+         ^^^^^^^^^^".foo = #t14;
     }
     for (final dynamic #t15 in <dynamic>[]) {
       invalid-expression "pkg/front_end/testcases/general/for_in_without_declaration.dart:39:12: Error: The setter 'unresolved' isn't defined for the class 'C'.
diff --git a/pkg/front_end/testcases/general/if_null_in_cascade.dart b/pkg/front_end/testcases/general/if_null_in_cascade.dart
new file mode 100644
index 0000000..edf5993
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_cascade.dart
@@ -0,0 +1,14 @@
+// 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.
+
+class Class {
+  method() {}
+}
+
+main() {
+  Class a;
+  Class b = new Class();
+  a ?? b
+    ..method();
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_cascade.dart.outline.expect b/pkg/front_end/testcases/general/if_null_in_cascade.dart.outline.expect
new file mode 100644
index 0000000..4d61e58
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_cascade.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  method method() → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.expect b/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.expect
new file mode 100644
index 0000000..09f340a
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method method() → dynamic {}
+}
+static method main() → dynamic {
+  self::Class* a;
+  self::Class* b = new self::Class::•();
+  let final self::Class* #t1 = let final self::Class* #t2 = a in #t2.{core::Object::==}(null) ?{self::Class*} b : #t2 in let final void #t3 = #t1.{self::Class::method}() in #t1;
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.transformed.expect
new file mode 100644
index 0000000..09f340a
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_cascade.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method method() → dynamic {}
+}
+static method main() → dynamic {
+  self::Class* a;
+  self::Class* b = new self::Class::•();
+  let final self::Class* #t1 = let final self::Class* #t2 = a in #t2.{core::Object::==}(null) ?{self::Class*} b : #t2 in let final void #t3 = #t1.{self::Class::method}() in #t1;
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_list_literal.dart b/pkg/front_end/testcases/general/if_null_in_list_literal.dart
new file mode 100644
index 0000000..5127c27
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_list_literal.dart
@@ -0,0 +1,8 @@
+// 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() {
+  Object a, b;
+  return [a ?? b];
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_list_literal.dart.outline.expect b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.expect b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.expect
new file mode 100644
index 0000000..0cc41e9
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+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];
+}
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
new file mode 100644
index 0000000..0cc41e9
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_list_literal.dart.strong.transformed.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+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];
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_set_literal.dart b/pkg/front_end/testcases/general/if_null_in_set_literal.dart
new file mode 100644
index 0000000..f1d0b2a
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_set_literal.dart
@@ -0,0 +1,8 @@
+// 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() {
+  Object a, b;
+  return {a ?? b};
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_set_literal.dart.outline.expect b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.outline.expect
new file mode 100644
index 0000000..6a28c0d
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.expect b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.expect
new file mode 100644
index 0000000..c644985
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method main() → dynamic {
+  core::Object* a;
+  core::Object* b;
+  return let final core::Set<core::Object*>* #t1 = col::LinkedHashSet::•<core::Object*>() in let final dynamic #t2 = #t1.{core::Set::add}(let final core::Object* #t3 = a in #t3.{core::Object::==}(null) ?{core::Object*} b : #t3) in #t1;
+}
diff --git a/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.transformed.expect b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.transformed.expect
new file mode 100644
index 0000000..9468fbe
--- /dev/null
+++ b/pkg/front_end/testcases/general/if_null_in_set_literal.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method main() → dynamic {
+  core::Object* a;
+  core::Object* b;
+  return let final core::Set<core::Object*>* #t1 = col::LinkedHashSet::•<core::Object*>() in let final core::bool* #t2 = #t1.{core::Set::add}(let final core::Object* #t3 = a in #t3.{core::Object::==}(null) ?{core::Object*} b : #t3) in #t1;
+}
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
index 17ceeb6..2847dab 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.outline.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
index e612779..a20af80 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
index e612779..a20af80 100644
--- a/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_contravariant_from_class.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_contravariant_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
index 174bfb1..f95aad1 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.outline.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
index b21225c..416ac77 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
index b21225c..416ac77 100644
--- a/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantImpl_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
index 61cb63d..6b0a4c2 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.outline.expect
@@ -2,19 +2,19 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> implements A<F<T>> {
 //       ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // abstract class I<T> implements A<F<T>> {
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
index 3257f5f..d247e10 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.expect
@@ -2,19 +2,19 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> implements A<F<T>> {
 //       ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // abstract class I<T> implements A<F<T>> {
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
index 3257f5f..d247e10 100644
--- a/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart.strong.transformed.expect
@@ -2,19 +2,19 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:13:7: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // class B<T> implements A<F<T>> {
 //       ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:17:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'A'.
 // abstract class I<T> implements A<F<T>> {
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'B'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
-// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// pkg/front_end/testcases/general/interface_covariantInterface_from_class.dart:21:16: Error: Can't use implicitly 'out' variable 'T' in an 'in' position in supertype 'I'.
 // abstract class C<T> extends B<F<T>> implements I<F<T>> {}
 //                ^
 //
diff --git a/pkg/front_end/testcases/general/issue38938.dart b/pkg/front_end/testcases/general/issue38938.dart
new file mode 100644
index 0000000..3ce4f66
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38938.dart
@@ -0,0 +1,10 @@
+// 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.
+
+class A {
+  int v;
+  int v;
+  A(this.v);
+  A.second();
+}
diff --git a/pkg/front_end/testcases/general/issue38938.dart.outline.expect b/pkg/front_end/testcases/general/issue38938.dart.outline.expect
new file mode 100644
index 0000000..e00e6f6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38938.dart.outline.expect
@@ -0,0 +1,21 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38938.dart:7:7: Error: 'v' is already declared in this scope.
+//   int v;
+//       ^
+// pkg/front_end/testcases/general/issue38938.dart:6:7: Context: Previous declaration of 'v'.
+//   int v;
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int* v;
+  constructor •(core::int* v) → self::A*
+    ;
+  constructor second() → self::A*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38938.dart.strong.expect b/pkg/front_end/testcases/general/issue38938.dart.strong.expect
new file mode 100644
index 0000000..908eef1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38938.dart.strong.expect
@@ -0,0 +1,29 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38938.dart:7:7: Error: 'v' is already declared in this scope.
+//   int v;
+//       ^
+// pkg/front_end/testcases/general/issue38938.dart:6:7: Context: Previous declaration of 'v'.
+//   int v;
+//       ^
+//
+// pkg/front_end/testcases/general/issue38938.dart:8:10: Error: Can't use 'v' because it is declared more than once.
+//   A(this.v);
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int* v = null;
+  constructor •(core::int* v) → self::A*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue38938.dart:8:10: Error: Can't use 'v' because it is declared more than once.
+  A(this.v);
+         ^", super core::Object::•()
+    ;
+  constructor second() → self::A*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38938.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38938.dart.strong.transformed.expect
new file mode 100644
index 0000000..908eef1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38938.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38938.dart:7:7: Error: 'v' is already declared in this scope.
+//   int v;
+//       ^
+// pkg/front_end/testcases/general/issue38938.dart:6:7: Context: Previous declaration of 'v'.
+//   int v;
+//       ^
+//
+// pkg/front_end/testcases/general/issue38938.dart:8:10: Error: Can't use 'v' because it is declared more than once.
+//   A(this.v);
+//          ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int* v = null;
+  constructor •(core::int* v) → self::A*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/issue38938.dart:8:10: Error: Can't use 'v' because it is declared more than once.
+  A(this.v);
+         ^", super core::Object::•()
+    ;
+  constructor second() → self::A*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38943.dart b/pkg/front_end/testcases/general/issue38943.dart
new file mode 100644
index 0000000..1d86b19
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38943.dart
@@ -0,0 +1,12 @@
+// 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.
+
+class D<X extends void Function()> {
+  factory D.foo() => new D._();
+  D._() {}
+}
+
+main() {
+  print(new D.foo());
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue38943.dart.outline.expect b/pkg/front_end/testcases/general/issue38943.dart.outline.expect
new file mode 100644
index 0000000..c625b56
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38943.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class D<X extends () →* void = () →* void> extends core::Object {
+  constructor _() → self::D<self::D::X*>*
+    ;
+  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue38943.dart.strong.expect b/pkg/front_end/testcases/general/issue38943.dart.strong.expect
new file mode 100644
index 0000000..94d489d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38943.dart.strong.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class D<X extends () →* void = () →* void> extends core::Object {
+  constructor _() → self::D<self::D::X*>*
+    : super core::Object::•() {}
+  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+    return new self::D::_<self::D::foo::X*>();
+}
+static method main() → dynamic {
+  core::print(self::D::foo<() →* void>());
+}
diff --git a/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect
new file mode 100644
index 0000000..94d489d
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38943.dart.strong.transformed.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class D<X extends () →* void = () →* void> extends core::Object {
+  constructor _() → self::D<self::D::X*>*
+    : super core::Object::•() {}
+  static factory foo<X extends () →* void = dynamic>() → self::D<self::D::foo::X*>*
+    return new self::D::_<self::D::foo::X*>();
+}
+static method main() → dynamic {
+  core::print(self::D::foo<() →* void>());
+}
diff --git a/pkg/front_end/testcases/general/issue38944.dart b/pkg/front_end/testcases/general/issue38944.dart
new file mode 100644
index 0000000..a0b7f42
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38944.dart
@@ -0,0 +1,6 @@
+// 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.
+
+class A<Q> {}
+class B<X> extends Object with A<void Function<Y extends X>()> {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/issue38944.dart.outline.expect b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
new file mode 100644
index 0000000..a4f2168
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38944.dart:6:7: Error: Can't use implicitly 'out' variable 'X' in an 'inout' position in supertype 'A'.
+// class B<X> extends Object with A<void Function<Y extends X>()> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<Q extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::Q*>*
+    ;
+}
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends self::_B&Object&A<self::B::X*> {
+  synthetic constructor •() → self::B<self::B::X*>*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
new file mode 100644
index 0000000..06fa503
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38944.dart:6:7: Error: Can't use implicitly 'out' variable 'X' in an 'inout' position in supertype 'A'.
+// class B<X> extends Object with A<void Function<Y extends X>()> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<Q extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::Q*>*
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends self::_B&Object&A<self::B::X*> {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super self::_B&Object&A::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
new file mode 100644
index 0000000..06fa503
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38944.dart:6:7: Error: Can't use implicitly 'out' variable 'X' in an 'inout' position in supertype 'A'.
+// class B<X> extends Object with A<void Function<Y extends X>()> {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<Q extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::Q*>*
+    : super core::Object::•()
+    ;
+}
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object {
+  const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
+    : super core::Object::•()
+    ;
+}
+class B<X extends core::Object* = dynamic> extends self::_B&Object&A<self::B::X*> {
+  synthetic constructor •() → self::B<self::B::X*>*
+    : super self::_B&Object&A::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38961.dart b/pkg/front_end/testcases/general/issue38961.dart
new file mode 100644
index 0000000..b98ae94
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38961.dart
@@ -0,0 +1,8 @@
+// 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.
+
+class C {
+  dynamic x = this;
+  var x = this;
+}
diff --git a/pkg/front_end/testcases/general/issue38961.dart.outline.expect b/pkg/front_end/testcases/general/issue38961.dart.outline.expect
new file mode 100644
index 0000000..63d2ac1
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38961.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38961.dart:7:7: Error: 'x' is already declared in this scope.
+//   var x = this;
+//       ^
+// pkg/front_end/testcases/general/issue38961.dart:6:11: Context: Previous declaration of 'x'.
+//   dynamic x = this;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic x;
+  synthetic constructor •() → self::C*
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38961.dart.strong.expect b/pkg/front_end/testcases/general/issue38961.dart.strong.expect
new file mode 100644
index 0000000..88a38b2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38961.dart.strong.expect
@@ -0,0 +1,28 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38961.dart:7:7: Error: 'x' is already declared in this scope.
+//   var x = this;
+//       ^
+// pkg/front_end/testcases/general/issue38961.dart:6:11: Context: Previous declaration of 'x'.
+//   dynamic x = this;
+//           ^
+//
+// pkg/front_end/testcases/general/issue38961.dart:6:15: Error: Can't access 'this' in a field initializer.
+//   dynamic x = this;
+//               ^^^^
+//
+// pkg/front_end/testcases/general/issue38961.dart:7:11: Error: Can't access 'this' in a field initializer.
+//   var x = this;
+//           ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic x = null;
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/issue38961.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38961.dart.strong.transformed.expect
new file mode 100644
index 0000000..88a38b2
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue38961.dart.strong.transformed.expect
@@ -0,0 +1,28 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue38961.dart:7:7: Error: 'x' is already declared in this scope.
+//   var x = this;
+//       ^
+// pkg/front_end/testcases/general/issue38961.dart:6:11: Context: Previous declaration of 'x'.
+//   dynamic x = this;
+//           ^
+//
+// pkg/front_end/testcases/general/issue38961.dart:6:15: Error: Can't access 'this' in a field initializer.
+//   dynamic x = this;
+//               ^^^^
+//
+// pkg/front_end/testcases/general/issue38961.dart:7:11: Error: Can't access 'this' in a field initializer.
+//   var x = this;
+//           ^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field dynamic x = null;
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/general/long_chain_of_typedefs.dart b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart
new file mode 100644
index 0000000..6a3864c
--- /dev/null
+++ b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart
@@ -0,0 +1,28 @@
+// 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.
+
+// Test for potentially slow compilation of long typedef dependency chains.
+
+typedef Foo01<X, Y, Z> = void Function(Null);
+typedef Foo02<X, Y, Z> = void Function(Foo01<X, Y, Z>);
+typedef Foo03<X, Y, Z> = void Function(Foo02<X, Y, Z>);
+typedef Foo04<X, Y, Z> = void Function(Foo03<X, Y, Z>);
+typedef Foo05<X, Y, Z> = void Function(Foo04<X, Y, Z>);
+typedef Foo06<X, Y, Z> = void Function(Foo05<X, Y, Z>);
+typedef Foo07<X, Y, Z> = void Function(Foo06<X, Y, Z>);
+typedef Foo08<X, Y, Z> = void Function(Foo07<X, Y, Z>);
+typedef Foo09<X, Y, Z> = void Function(Foo08<X, Y, Z>);
+typedef Foo10<X, Y, Z> = void Function(Foo09<X, Y, Z>);
+typedef Foo11<X, Y, Z> = void Function(Foo10<X, Y, Z>);
+typedef Foo12<X, Y, Z> = void Function(Foo11<X, Y, Z>);
+typedef Foo13<X, Y, Z> = void Function(Foo12<X, Y, Z>);
+typedef Foo14<X, Y, Z> = void Function(Foo13<X, Y, Z>);
+typedef Foo15<X, Y, Z> = void Function(Foo14<X, Y, Z>);
+typedef Foo16<X, Y, Z> = void Function(Foo15<X, Y, Z>);
+typedef Foo17<X, Y, Z> = void Function(Foo16<X, Y, Z>);
+typedef Foo18<X, Y, Z> = void Function(Foo17<X, Y, Z>);
+typedef Foo19<X, Y, Z> = void Function(Foo18<X, Y, Z>);
+typedef Foo20<X, Y, Z> = void Function(Foo19<X, Y, Z>);
+
+main() {}
diff --git a/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.outline.expect b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.outline.expect
new file mode 100644
index 0000000..1883ef1
--- /dev/null
+++ b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Foo01<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (core::Null?) →* void;
+typedef Foo02<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((core::Null?) →* void) →* void;
+typedef Foo03<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((core::Null?) →* void) →* void) →* void;
+typedef Foo04<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((core::Null?) →* void) →* void) →* void) →* void;
+typedef Foo05<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((core::Null?) →* void) →* void) →* void) →* void) →* void;
+typedef Foo06<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo07<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo08<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo09<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo10<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo11<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo12<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo13<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo14<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo15<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo16<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo17<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo18<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo19<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo20<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.expect b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.expect
new file mode 100644
index 0000000..e62ba24
--- /dev/null
+++ b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Foo01<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (core::Null?) →* void;
+typedef Foo02<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((core::Null?) →* void) →* void;
+typedef Foo03<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((core::Null?) →* void) →* void) →* void;
+typedef Foo04<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((core::Null?) →* void) →* void) →* void) →* void;
+typedef Foo05<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((core::Null?) →* void) →* void) →* void) →* void) →* void;
+typedef Foo06<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo07<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo08<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo09<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo10<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo11<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo12<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo13<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo14<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo15<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo16<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo17<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo18<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo19<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo20<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.transformed.expect b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.transformed.expect
new file mode 100644
index 0000000..e62ba24
--- /dev/null
+++ b/pkg/front_end/testcases/general/long_chain_of_typedefs.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Foo01<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (core::Null?) →* void;
+typedef Foo02<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((core::Null?) →* void) →* void;
+typedef Foo03<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((core::Null?) →* void) →* void) →* void;
+typedef Foo04<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((core::Null?) →* void) →* void) →* void) →* void;
+typedef Foo05<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((core::Null?) →* void) →* void) →* void) →* void) →* void;
+typedef Foo06<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo07<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo08<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo09<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo10<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo11<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo12<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo13<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo14<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo15<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo16<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo17<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo18<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo19<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = (((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+typedef Foo20<unrelated X extends core::Object* = dynamic, unrelated Y extends core::Object* = dynamic, unrelated Z extends core::Object* = dynamic> = ((((((((((((((((((((core::Null?) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void) →* void;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/missing_toplevel.dart b/pkg/front_end/testcases/general/missing_toplevel.dart
new file mode 100644
index 0000000..4e63188
--- /dev/null
+++ b/pkg/front_end/testcases/general/missing_toplevel.dart
@@ -0,0 +1,33 @@
+// 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.
+
+class EmptyClass {}
+
+var emptyClass = new EmptyClass();
+
+class ClassWithProperty {
+  EmptyClass property;
+}
+
+var classWithProperty = new ClassWithProperty();
+
+class ClassWithIndexSet {
+  operator []=(int index, int value) {}
+}
+
+var classWithIndexSet = new ClassWithIndexSet();
+
+class ClassWithIndexGet {
+  int operator [](int index) => 42;
+}
+
+var classWithIndexGet = new ClassWithIndexGet();
+
+var missingBinary = classWithProperty.property += 2;
+var missingIndexGet = classWithIndexSet[0] ??= 2;
+var missingIndexSet = classWithIndexGet[0] ??= 2;
+var missingPropertyGet = emptyClass.property;
+var missingPropertySet = emptyClass.property = 42;
+
+main() {}
diff --git a/pkg/front_end/testcases/general/missing_toplevel.dart.outline.expect b/pkg/front_end/testcases/general/missing_toplevel.dart.outline.expect
new file mode 100644
index 0000000..cd82bd6
--- /dev/null
+++ b/pkg/front_end/testcases/general/missing_toplevel.dart.outline.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class EmptyClass extends core::Object {
+  synthetic constructor •() → self::EmptyClass*
+    ;
+}
+class ClassWithProperty extends core::Object {
+  field self::EmptyClass* property;
+  synthetic constructor •() → self::ClassWithProperty*
+    ;
+}
+class ClassWithIndexSet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexSet*
+    ;
+  operator []=(core::int* index, core::int* value) → void
+    ;
+}
+class ClassWithIndexGet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexGet*
+    ;
+  operator [](core::int* index) → core::int*
+    ;
+}
+static field self::EmptyClass* emptyClass;
+static field self::ClassWithProperty* classWithProperty;
+static field self::ClassWithIndexSet* classWithIndexSet;
+static field self::ClassWithIndexGet* classWithIndexGet;
+static field dynamic missingBinary;
+static field dynamic missingIndexGet;
+static field core::int* missingIndexSet;
+static field dynamic missingPropertyGet;
+static field core::int* missingPropertySet;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/missing_toplevel.dart.strong.expect b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.expect
new file mode 100644
index 0000000..f1b93c3
--- /dev/null
+++ b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.expect
@@ -0,0 +1,91 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:27:48: Error: The method '+' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+// var missingBinary = classWithProperty.property += 2;
+//                                                ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:28:40: Error: The method '[]' isn't defined for the class 'ClassWithIndexSet'.
+//  - 'ClassWithIndexSet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '[]'.
+// var missingIndexGet = classWithIndexSet[0] ??= 2;
+//                                        ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:29:40: Error: The method '[]=' isn't defined for the class 'ClassWithIndexGet'.
+//  - 'ClassWithIndexGet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '[]='.
+// var missingIndexSet = classWithIndexGet[0] ??= 2;
+//                                        ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:30:37: Error: The getter 'property' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
+// var missingPropertyGet = emptyClass.property;
+//                                     ^^^^^^^^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:31:37: Error: The setter 'property' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+// var missingPropertySet = emptyClass.property = 42;
+//                                     ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class EmptyClass extends core::Object {
+  synthetic constructor •() → self::EmptyClass*
+    : super core::Object::•()
+    ;
+}
+class ClassWithProperty extends core::Object {
+  field self::EmptyClass* property = null;
+  synthetic constructor •() → self::ClassWithProperty*
+    : super core::Object::•()
+    ;
+}
+class ClassWithIndexSet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexSet*
+    : super core::Object::•()
+    ;
+  operator []=(core::int* index, core::int* value) → void {}
+}
+class ClassWithIndexGet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexGet*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return 42;
+}
+static field self::EmptyClass* emptyClass = new self::EmptyClass::•();
+static field self::ClassWithProperty* classWithProperty = new self::ClassWithProperty::•();
+static field self::ClassWithIndexSet* classWithIndexSet = new self::ClassWithIndexSet::•();
+static field self::ClassWithIndexGet* classWithIndexGet = new self::ClassWithIndexGet::•();
+static field dynamic missingBinary = let final self::ClassWithProperty* #t1 = self::classWithProperty in #t1.{self::ClassWithProperty::property} = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:27:48: Error: The method '+' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '+'.
+var missingBinary = classWithProperty.property += 2;
+                                               ^" as{TypeError} self::EmptyClass*;
+static field dynamic missingIndexGet = let final self::ClassWithIndexSet* #t2 = self::classWithIndexSet in let final core::int* #t3 = 0 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:28:40: Error: The method '[]' isn't defined for the class 'ClassWithIndexSet'.
+ - 'ClassWithIndexSet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '[]'.
+var missingIndexGet = classWithIndexSet[0] ??= 2;
+                                       ^" in #t4.{core::Object::==}(null) ?{dynamic} let final core::int* #t5 = 2 in let final void #t6 = #t2.{self::ClassWithIndexSet::[]=}(#t3, #t5) in #t5 : #t4;
+static field core::int* missingIndexSet = let final self::ClassWithIndexGet* #t7 = self::classWithIndexGet in let final core::int* #t8 = 0 in let final core::int* #t9 = #t7.{self::ClassWithIndexGet::[]}(#t8) in #t9.{core::num::==}(null) ?{core::int*} let final core::int* #t10 = 2 in let final void #t11 = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:29:40: Error: The method '[]=' isn't defined for the class 'ClassWithIndexGet'.
+ - 'ClassWithIndexGet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '[]='.
+var missingIndexSet = classWithIndexGet[0] ??= 2;
+                                       ^" in #t10 : #t9;
+static field dynamic missingPropertyGet = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:30:37: Error: The getter 'property' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
+var missingPropertyGet = emptyClass.property;
+                                    ^^^^^^^^";
+static field core::int* missingPropertySet = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:31:37: Error: The setter 'property' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+var missingPropertySet = emptyClass.property = 42;
+                                    ^^^^^^^^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect
new file mode 100644
index 0000000..f1b93c3
--- /dev/null
+++ b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect
@@ -0,0 +1,91 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:27:48: Error: The method '+' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '+'.
+// var missingBinary = classWithProperty.property += 2;
+//                                                ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:28:40: Error: The method '[]' isn't defined for the class 'ClassWithIndexSet'.
+//  - 'ClassWithIndexSet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '[]'.
+// var missingIndexGet = classWithIndexSet[0] ??= 2;
+//                                        ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:29:40: Error: The method '[]=' isn't defined for the class 'ClassWithIndexGet'.
+//  - 'ClassWithIndexGet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing method, or defining a method named '[]='.
+// var missingIndexSet = classWithIndexGet[0] ??= 2;
+//                                        ^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:30:37: Error: The getter 'property' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
+// var missingPropertyGet = emptyClass.property;
+//                                     ^^^^^^^^
+//
+// pkg/front_end/testcases/general/missing_toplevel.dart:31:37: Error: The setter 'property' isn't defined for the class 'EmptyClass'.
+//  - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+// var missingPropertySet = emptyClass.property = 42;
+//                                     ^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class EmptyClass extends core::Object {
+  synthetic constructor •() → self::EmptyClass*
+    : super core::Object::•()
+    ;
+}
+class ClassWithProperty extends core::Object {
+  field self::EmptyClass* property = null;
+  synthetic constructor •() → self::ClassWithProperty*
+    : super core::Object::•()
+    ;
+}
+class ClassWithIndexSet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexSet*
+    : super core::Object::•()
+    ;
+  operator []=(core::int* index, core::int* value) → void {}
+}
+class ClassWithIndexGet extends core::Object {
+  synthetic constructor •() → self::ClassWithIndexGet*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return 42;
+}
+static field self::EmptyClass* emptyClass = new self::EmptyClass::•();
+static field self::ClassWithProperty* classWithProperty = new self::ClassWithProperty::•();
+static field self::ClassWithIndexSet* classWithIndexSet = new self::ClassWithIndexSet::•();
+static field self::ClassWithIndexGet* classWithIndexGet = new self::ClassWithIndexGet::•();
+static field dynamic missingBinary = let final self::ClassWithProperty* #t1 = self::classWithProperty in #t1.{self::ClassWithProperty::property} = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:27:48: Error: The method '+' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '+'.
+var missingBinary = classWithProperty.property += 2;
+                                               ^" as{TypeError} self::EmptyClass*;
+static field dynamic missingIndexGet = let final self::ClassWithIndexSet* #t2 = self::classWithIndexSet in let final core::int* #t3 = 0 in let final dynamic #t4 = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:28:40: Error: The method '[]' isn't defined for the class 'ClassWithIndexSet'.
+ - 'ClassWithIndexSet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '[]'.
+var missingIndexGet = classWithIndexSet[0] ??= 2;
+                                       ^" in #t4.{core::Object::==}(null) ?{dynamic} let final core::int* #t5 = 2 in let final void #t6 = #t2.{self::ClassWithIndexSet::[]=}(#t3, #t5) in #t5 : #t4;
+static field core::int* missingIndexSet = let final self::ClassWithIndexGet* #t7 = self::classWithIndexGet in let final core::int* #t8 = 0 in let final core::int* #t9 = #t7.{self::ClassWithIndexGet::[]}(#t8) in #t9.{core::num::==}(null) ?{core::int*} let final core::int* #t10 = 2 in let final void #t11 = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:29:40: Error: The method '[]=' isn't defined for the class 'ClassWithIndexGet'.
+ - 'ClassWithIndexGet' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing method, or defining a method named '[]='.
+var missingIndexSet = classWithIndexGet[0] ??= 2;
+                                       ^" in #t10 : #t9;
+static field dynamic missingPropertyGet = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:30:37: Error: The getter 'property' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing getter, or defining a getter or field named 'property'.
+var missingPropertyGet = emptyClass.property;
+                                    ^^^^^^^^";
+static field core::int* missingPropertySet = invalid-expression "pkg/front_end/testcases/general/missing_toplevel.dart:31:37: Error: The setter 'property' isn't defined for the class 'EmptyClass'.
+ - 'EmptyClass' is from 'pkg/front_end/testcases/general/missing_toplevel.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'property'.
+var missingPropertySet = emptyClass.property = 42;
+                                    ^^^^^^^^";
+static method main() → dynamic {}
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 2e3a3bf..d304cbd 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
@@ -2,125 +2,125 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
-//   foo() {}
-//   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
-//   foo([x]) {}
-//   ^
-// pkg/front_end/testcases/mixin_application_override.dart:21:7: Context: Override was introduced in the mixin application class 'A0'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:21:7: Error: The mixin application class 'A0' introduces an erroneous override of 'foo'.
 // class A0 = S with M;
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:22:7: Context: Override was introduced in the mixin application class 'A1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:22:7: Error: The mixin application class 'A1' introduces an erroneous override of 'foo'.
 // class A1 = S with M1, M;
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:23:7: Context: Override was introduced in the mixin application class 'A2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:23:7: Error: The mixin application class 'A2' introduces an erroneous override of 'foo'.
 // class A2 = S with M1, M2, M;
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:25:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:25:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class A0X = S with M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:26:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:26:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class A1X = S with M1, M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:27:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:27:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class A2X = S with M1, M2, M, MX;
 //       ^^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:29:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:29:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class B0 extends S with M {}
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:31:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:31:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class B1 extends S with M1, M {}
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:33:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:33:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class B2 extends S with M1, M2, M {}
 //       ^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:35:7: Context: Override was introduced when the mixin 'M' was applied to 'S'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:35:7: Error: Applying the mixin 'M' to 'S' introduces an erroneous override of 'foo'.
 // class B0X extends S with M, MX {}
 //       ^^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:37:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:37:7: Error: Applying the mixin 'M' to 'S with M1' introduces an erroneous override of 'foo'.
 // class B1X extends S with M1, M, MX {}
 //       ^^^
-//
-// pkg/front_end/testcases/mixin_application_override.dart:12:3: Error: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
 //   foo() {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
 //   foo([x]) {}
 //   ^
-// pkg/front_end/testcases/mixin_application_override.dart:39:7: Context: Override was introduced when the mixin 'M' was applied to 'S with M1, M2'.
+//
+// pkg/front_end/testcases/general/mixin_application_override.dart:39:7: Error: Applying the mixin 'M' to 'S with M1, M2' introduces an erroneous override of 'foo'.
 // class B2X extends S with M1, M2, M, MX {}
 //       ^^^
+// pkg/front_end/testcases/general/mixin_application_override.dart:12:3: Context: The method 'M.foo' has fewer positional arguments than those of overridden method 'S.foo'.
+//   foo() {}
+//   ^
+// pkg/front_end/testcases/general/mixin_application_override.dart:8:3: Context: This is the overridden method ('foo').
+//   foo([x]) {}
+//   ^
 //
 import self as self;
 import "dart:core" as core;
@@ -129,7 +129,7 @@
   synthetic constructor •() → self::S*
     : super core::Object::•()
     ;
-  method foo([dynamic x = null]) → dynamic {}
+  method foo([dynamic x = #C1]) → dynamic {}
 }
 class M extends core::Object {
   synthetic constructor •() → self::M*
@@ -156,7 +156,7 @@
   synthetic constructor •() → self::A0*
     : super self::S::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _A1&S&M1 = self::S with self::M1 {
   synthetic constructor •() → self::_A1&S&M1*
@@ -167,7 +167,7 @@
   synthetic constructor •() → self::A1*
     : super self::_A1&S&M1::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _A2&S&M1 = self::S with self::M1 {
   synthetic constructor •() → self::_A2&S&M1*
@@ -183,13 +183,13 @@
   synthetic constructor •() → self::A2*
     : super self::_A2&S&M1&M2::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _A0X&S&M = self::S with self::M {
   synthetic constructor •() → self::_A0X&S&M*
     : super self::S::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class A0X = self::_A0X&S&M with self::MX {
   synthetic constructor •() → self::A0X*
@@ -205,7 +205,7 @@
   synthetic constructor •() → self::_A1X&S&M1&M*
     : super self::_A1X&S&M1::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class A1X = self::_A1X&S&M1&M with self::MX {
   synthetic constructor •() → self::A1X*
@@ -226,7 +226,7 @@
   synthetic constructor •() → self::_A2X&S&M1&M2&M*
     : super self::_A2X&S&M1&M2::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class A2X = self::_A2X&S&M1&M2&M with self::MX {
   synthetic constructor •() → self::A2X*
@@ -237,7 +237,7 @@
   synthetic constructor •() → self::_B0&S&M*
     : super self::S::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class B0 extends self::_B0&S&M {
   synthetic constructor •() → self::B0*
@@ -253,7 +253,7 @@
   synthetic constructor •() → self::_B1&S&M1&M*
     : super self::_B1&S&M1::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class B1 extends self::_B1&S&M1&M {
   synthetic constructor •() → self::B1*
@@ -274,7 +274,7 @@
   synthetic constructor •() → self::_B2&S&M1&M2&M*
     : super self::_B2&S&M1&M2::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 class B2 extends self::_B2&S&M1&M2&M {
   synthetic constructor •() → self::B2*
@@ -285,7 +285,7 @@
   synthetic constructor •() → self::_B0X&S&M*
     : super self::S::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _B0X&S&M&MX = self::_B0X&S&M with self::MX {
   synthetic constructor •() → self::_B0X&S&M&MX*
@@ -306,7 +306,7 @@
   synthetic constructor •() → self::_B1X&S&M1&M*
     : super self::_B1X&S&M1::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _B1X&S&M1&M&MX = self::_B1X&S&M1&M with self::MX {
   synthetic constructor •() → self::_B1X&S&M1&M&MX*
@@ -332,7 +332,7 @@
   synthetic constructor •() → self::_B2X&S&M1&M2&M*
     : super self::_B2X&S&M1&M2::•()
     ;
-  abstract forwarding-stub method foo([dynamic x = null]) → dynamic;
+  abstract forwarding-stub method foo([dynamic x = #C1]) → dynamic;
 }
 abstract class _B2X&S&M1&M2&M&MX = self::_B2X&S&M1&M2&M with self::MX {
   synthetic constructor •() → self::_B2X&S&M1&M2&M&MX*
@@ -345,3 +345,7 @@
     ;
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/native_as_name.dart.strong.expect b/pkg/front_end/testcases/general/native_as_name.dart.strong.expect
index 4fba92c..9e20099 100644
--- a/pkg/front_end/testcases/general/native_as_name.dart.strong.expect
+++ b/pkg/front_end/testcases/general/native_as_name.dart.strong.expect
@@ -41,7 +41,7 @@
   core::print(new self::W::•().{self::W::native});
   core::print(new self::X::•().{self::X::native}());
   core::print(new self::Y2::•().{self::Y2::native});
-  core::print((let final self::Z* #t1 = new self::Z::•() in let final dynamic #t2 = #t1.{self::Z::native} = "setter" in #t1).{self::Z::f});
+  core::print((let final self::Z* #t1 = new self::Z::•() in let final void #t2 = #t1.{self::Z::native} = "setter" in #t1).{self::Z::f});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/native_as_name.dart.strong.transformed.expect b/pkg/front_end/testcases/general/native_as_name.dart.strong.transformed.expect
index 067e6d7..9e20099 100644
--- a/pkg/front_end/testcases/general/native_as_name.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/native_as_name.dart.strong.transformed.expect
@@ -41,7 +41,7 @@
   core::print(new self::W::•().{self::W::native});
   core::print(new self::X::•().{self::X::native}());
   core::print(new self::Y2::•().{self::Y2::native});
-  core::print((let final self::Z* #t1 = new self::Z::•() in let final core::String* #t2 = #t1.{self::Z::native} = "setter" in #t1).{self::Z::f});
+  core::print((let final self::Z* #t1 = new self::Z::•() in let final void #t2 = #t1.{self::Z::native} = "setter" in #t1).{self::Z::f});
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
index 8eafc0b..3c5f989 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
@@ -169,7 +169,7 @@
 //  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 // Try correcting the name to the name of an existing method, or defining a method named '[]='.
 //   print(foo[2] = 2);
-//            ^^^
+//            ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:30:12: Error: The method '[]' isn't defined for the class 'Foo'.
 //  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
@@ -279,7 +279,7 @@
  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 Try correcting the name to the name of an existing method, or defining a method named '[]='.
   print(foo[2] = 2);
-           ^^^" in #t3);
+           ^" in #t3);
   core::print(invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:30:12: Error: The method '[]' isn't defined for the class 'Foo'.
  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 Try correcting the name to the name of an existing method, or defining a method named '[]'.
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 8eafc0b..3c5f989 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
@@ -169,7 +169,7 @@
 //  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 // Try correcting the name to the name of an existing method, or defining a method named '[]='.
 //   print(foo[2] = 2);
-//            ^^^
+//            ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:30:12: Error: The method '[]' isn't defined for the class 'Foo'.
 //  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
@@ -279,7 +279,7 @@
  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 Try correcting the name to the name of an existing method, or defining a method named '[]='.
   print(foo[2] = 2);
-           ^^^" in #t3);
+           ^" in #t3);
   core::print(invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:30:12: Error: The method '[]' isn't defined for the class 'Foo'.
  - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
 Try correcting the name to the name of an existing method, or defining a method named '[]'.
diff --git a/pkg/front_end/testcases/general/three_typedefs_loop.dart b/pkg/front_end/testcases/general/three_typedefs_loop.dart
new file mode 100644
index 0000000..d4f0110
--- /dev/null
+++ b/pkg/front_end/testcases/general/three_typedefs_loop.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// The test for recursive typedef declaration involving multiple typedefs.
+
+typedef Foo<T> = void Function(Bar<T>);
+typedef Bar<T> = void Function(Baz<T>);
+typedef Baz<T> = void Function(Foo<T>);
+
+main() {}
diff --git a/pkg/front_end/testcases/general/three_typedefs_loop.dart.outline.expect b/pkg/front_end/testcases/general/three_typedefs_loop.dart.outline.expect
new file mode 100644
index 0000000..12b78a9
--- /dev/null
+++ b/pkg/front_end/testcases/general/three_typedefs_loop.dart.outline.expect
@@ -0,0 +1,20 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:8:9: Error: The typedef 'Bar' has a reference to itself.
+// typedef Bar<T> = void Function(Baz<T>);
+//         ^^^
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:7:9: Error: The typedef 'Foo' has a reference to itself.
+// typedef Foo<T> = void Function(Bar<T>);
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef Foo<unrelated T extends core::Object* = dynamic> = (((invalid-type) →* void) →* void) →* void;
+typedef Bar<unrelated T extends core::Object* = dynamic> = ((invalid-type) →* void) →* void;
+typedef Baz<unrelated T extends core::Object* = dynamic> = (invalid-type) →* void;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.expect b/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.expect
new file mode 100644
index 0000000..3773b6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:8:9: Error: The typedef 'Bar' has a reference to itself.
+// typedef Bar<T> = void Function(Baz<T>);
+//         ^^^
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:7:9: Error: The typedef 'Foo' has a reference to itself.
+// typedef Foo<T> = void Function(Bar<T>);
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef Foo<unrelated T extends core::Object* = dynamic> = (((invalid-type) →* void) →* void) →* void;
+typedef Bar<unrelated T extends core::Object* = dynamic> = ((invalid-type) →* void) →* void;
+typedef Baz<unrelated T extends core::Object* = dynamic> = (invalid-type) →* void;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.transformed.expect b/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.transformed.expect
new file mode 100644
index 0000000..3773b6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/three_typedefs_loop.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:8:9: Error: The typedef 'Bar' has a reference to itself.
+// typedef Bar<T> = void Function(Baz<T>);
+//         ^^^
+//
+// pkg/front_end/testcases/general/three_typedefs_loop.dart:7:9: Error: The typedef 'Foo' has a reference to itself.
+// typedef Foo<T> = void Function(Bar<T>);
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef Foo<unrelated T extends core::Object* = dynamic> = (((invalid-type) →* void) →* void) →* void;
+typedef Bar<unrelated T extends core::Object* = dynamic> = ((invalid-type) →* void) →* void;
+typedef Baz<unrelated T extends core::Object* = dynamic> = (invalid-type) →* void;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart b/pkg/front_end/testcases/general/type_literal_as_metadata.dart
new file mode 100644
index 0000000..1eafeef
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart
@@ -0,0 +1,12 @@
+// 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.
+
+class A {
+  const A();
+}
+
+@A
+class B {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
new file mode 100644
index 0000000..2b697f3
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
@@ -0,0 +1,25 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+// @A
+//  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  const constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+@let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+@A
+ ^" in self::A*
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect
new file mode 100644
index 0000000..422552b
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+// @A
+//  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  const constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+@invalid-expression "pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+@A
+ ^"
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect
new file mode 100644
index 0000000..422552b
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+// @A
+//  ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  const constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+@invalid-expression "pkg/front_end/testcases/general/type_literal_as_metadata.dart:9:2: Error: This can't be used as metadata; metadata should be a reference to a compile-time constant variable, or a call to a constant constructor.
+@A
+ ^"
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
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 2dd976f..3bde972 100644
--- a/pkg/front_end/testcases/general/void_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/general/void_methods.dart.strong.expect
@@ -3,14 +3,14 @@
 import "dart:core" as core;
 
 class Foo extends core::Object {
-  field core::List<dynamic> list = <dynamic>[1, 2, 3];
-  synthetic constructor •() → self::Foo
+  field core::List<dynamic>* list = <dynamic>[1, 2, 3];
+  synthetic constructor •() → self::Foo*
     : super core::Object::•()
     ;
   set first(dynamic x) → void
-    this.list.[]=(0, x);
+    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
-    this.list.[]=(x, y);
+    return let final core::List<dynamic>* #t5 = this.{self::Foo::list} in let final dynamic #t6 = x as{TypeError} 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}();
 }
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
new file mode 100644
index 0000000..9f36d60
--- /dev/null
+++ b/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object {
+  field core::List<dynamic>* list = <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} 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}();
+}
+static method main() → dynamic {
+  new self::Foo::•().{self::Foo::first} = 4;
+  new self::Foo::•().{self::Foo::[]=}(3, 4);
+  new self::Foo::•().{self::Foo::clear}();
+}
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
new file mode 100644
index 0000000..3cf6bc9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalid_part_uri_01.yaml
@@ -0,0 +1,27 @@
+# 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.
+
+# Create part URI that is invalid. This has previously caused a crash.
+
+type: newworld
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        // The space makes the scheme invalid -- this causes Uri.parse to throw.
+        part ' package:foo/bar.dart';
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    errors: false
+    worldType: updated
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        main() {}
+    expectInitializeFromDill: false
+    expectedLibraryCount: 1
+    uriToSourcesOnlyIncludes:
+      - main.dart
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.expect
index f8657ce..303cc21 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.expect
@@ -20,7 +20,7 @@
   core::num* y;
   self::C<core::int*>* c_int = new self::C::•<core::int*>(y as{TypeError} core::int*);
   self::C<core::num*>* c_num = new self::C::•<core::num*>(123);
-  self::C<core::num*>* c_num2 = let final self::C<core::num*>* #t1 = new self::C::•<core::num*>(456) in let final dynamic #t2 = #t1.{self::C::t} = 1.0 in #t1;
+  self::C<core::num*>* c_num2 = let final self::C<core::num*>* #t1 = new self::C::•<core::num*>(456) in let final void #t2 = #t1.{self::C::t} = 1.0 in #t1;
   self::C<dynamic>* c_dynamic = new self::C::•<dynamic>(42);
   x.{self::C::t} = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart:26:56: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   x. /*@target=C::t*/ t = /*error:INVALID_ASSIGNMENT*/ 'hello';
diff --git a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.transformed.expect
index 3bc4490..303cc21 100644
--- a/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
   core::num* y;
   self::C<core::int*>* c_int = new self::C::•<core::int*>(y as{TypeError} core::int*);
   self::C<core::num*>* c_num = new self::C::•<core::num*>(123);
-  self::C<core::num*>* c_num2 = let final self::C<core::num*>* #t1 = new self::C::•<core::num*>(456) in let final core::double* #t2 = #t1.{self::C::t} = 1.0 in #t1;
+  self::C<core::num*>* c_num2 = let final self::C<core::num*>* #t1 = new self::C::•<core::num*>(456) in let final void #t2 = #t1.{self::C::t} = 1.0 in #t1;
   self::C<dynamic>* c_dynamic = new self::C::•<dynamic>(42);
   x.{self::C::t} = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/constructors_infer_from_arguments.dart:26:56: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
   x. /*@target=C::t*/ t = /*error:INVALID_ASSIGNMENT*/ 'hello';
diff --git a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.expect
index ad0588e..2bf5f20 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.expect
@@ -13,6 +13,6 @@
     : super core::Object::•()
     ;
 }
-static field self::A* t1 = let final self::A* #t1 = new self::A::•() in let final dynamic #t2 = #t1.{self::A::b} = new self::B::•<core::int*>(1) in #t1;
+static field self::A* t1 = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::b} = new self::B::•<core::int*>(1) in #t1;
 static field core::List<self::B<core::int*>*>* t2 = <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.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_inside_top_level.dart.strong.transformed.expect
index 2d9066f..2bf5f20 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
@@ -13,6 +13,6 @@
     : super core::Object::•()
     ;
 }
-static field self::A* t1 = let final self::A* #t1 = new self::A::•() in let final self::B<core::int*>* #t2 = #t1.{self::A::b} = new self::B::•<core::int*>(1) in #t1;
+static field self::A* t1 = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::b} = new self::B::•<core::int*>(1) in #t1;
 static field core::List<self::B<core::int*>*>* t2 = <self::B<core::int*>*>[new self::B::•<core::int*>(2)];
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
index 43326c3..f239b76 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, contravariant T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
 class DartType extends core::Object {
   synthetic constructor •() → self::DartType*
     : super core::Object::•()
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 43326c3..f239b76 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
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, contravariant T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
 class DartType extends core::Object {
   synthetic constructor •() → self::DartType*
     : super core::Object::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
index 90e061b..bd37b92 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
index 90e061b..bd37b92 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 import self as self;
 import "dart:core" as core;
 
-typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
 class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
   synthetic constructor •() → self::C<self::C::T*>*
     : super self::D::•()
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
index 8880525..5aa60b1 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.expect
@@ -99,7 +99,7 @@
                                  ^"];
 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 let final dynamic #t2 = #t1.{self::A::x} = 3 in #t1;
+static field self::A* e = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::x} = 3 in #t1;
 static field core::int* f = 2.{core::num::+}(3);
 static field core::int* g = 3.{core::int::unary-}();
 static field self::B* h = new self::A::•().{self::A::+}(3);
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 4db29402..5aa60b1 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
@@ -99,7 +99,7 @@
                                  ^"];
 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 let final core::int* #t2 = #t1.{self::A::x} = 3 in #t1;
+static field self::A* e = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::x} = 3 in #t1;
 static field core::int* f = 2.{core::num::+}(3);
 static field core::int* g = 3.{core::int::unary-}();
 static field self::B* h = new self::A::•().{self::A::+}(3);
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 568f782..ff72bcf 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
@@ -7,8 +7,8 @@
     : super core::Object::•()
     ;
   abstract method f(core::int* x, core::int* y) → core::int*;
-  abstract method g(core::int* x, [core::int* y = null]) → core::int*;
-  abstract method h(core::int* x, {core::int* y = null}) → 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 class B extends core::Object {
   synthetic constructor •() → self::B*
@@ -23,7 +23,11 @@
     : super core::Object::•()
     ;
   abstract method f(core::int* x, core::int* y) → core::int*;
-  abstract method g(core::int* x, [core::int* y = null]) → core::int*;
-  abstract method h(core::int* x, {core::int* y = null}) → 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*;
 }
 static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect
index 1ad3fde..91c3721 100644
--- a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.expect
@@ -10,5 +10,5 @@
     ;
   method m() → void {}
 }
-static field self::A* v = let final self::A* #t1 = new self::A::•() in let final dynamic #t2 = #t1.{self::A::a} = 1 in let final dynamic #t3 = #t1.{self::A::b}.{core::List::add}(2) in let final dynamic #t4 = #t1.{self::A::m}() in #t1;
+static field self::A* v = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::a} = 1 in let final void #t3 = #t1.{self::A::b}.{core::List::add}(2) in let final void #t4 = #t1.{self::A::m}() in #t1;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.transformed.expect
index 551c402..91c3721 100644
--- a/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_cascade.dart.strong.transformed.expect
@@ -10,5 +10,5 @@
     ;
   method m() → void {}
 }
-static field self::A* v = let final self::A* #t1 = new self::A::•() in let final core::int* #t2 = #t1.{self::A::a} = 1 in let final void #t3 = #t1.{self::A::b}.{core::List::add}(2) in let final void #t4 = #t1.{self::A::m}() in #t1;
+static field self::A* v = let final self::A* #t1 = new self::A::•() in let final void #t2 = #t1.{self::A::a} = 1 in let final void #t3 = #t1.{self::A::b}.{core::List::add}(2) in let final void #t4 = #t1.{self::A::m}() in #t1;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/late.dart b/pkg/front_end/testcases/nnbd/late.dart
index d98c122..7942899 100644
--- a/pkg/front_end/testcases/nnbd/late.dart
+++ b/pkg/front_end/testcases/nnbd/late.dart
@@ -2,20 +2,67 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-late int lateStaticField;
-late final int finalLateStaticField;
+late int lateTopLevelField;
+late final int lateFinalTopLevelField;
+late final int lateFinalTopLevelFieldWithInit = 0;
 
 class Class {
   late int lateInstanceField;
-  late final int finalLateInstanceField = 0;
+  late final int lateFinalInstanceField1;
+  late final int lateFinalInstanceField2;
+  late final int lateFinalInstanceFieldWithInit = 0;
+
+  late Class lateInstanceFieldThis = this;
+  late final Class lateFinalInstanceFieldThis = this;
 
   static late int lateStaticField;
-  static late final int finalLateStaticField = 0;
+  static late final int lateFinalStaticField1;
+  static late final int lateFinalStaticField2;
+  static late final int lateFinalStaticFieldWithInit = 0;
 
   method() {
     late int lateVariable;
-    late final int lateFinalVariable = 0;
+    late final int lateFinalVariable;
+    late final int lateFinalVariableWithInit = 0;
+
+    lateVariable = 0;
+    lateFinalVariable = 0;
+
+    lateInstanceField = 0;
+    lateFinalInstanceField1 = 0;
+
+    lateStaticField = 0;
+    lateFinalStaticField1 = 0;
+  }
+
+  methodWithErrors() {
+    late final int lateFinalVariableWithInit = 0;
+    lateFinalVariableWithInit = 0;
+
+    lateFinalInstanceFieldWithInit = 0;
+
+    lateFinalStaticFieldWithInit = 0;
   }
 }
 
-main() {}
\ No newline at end of file
+main() {}
+
+noErrors() {
+  lateTopLevelField = 0;
+  lateFinalTopLevelField = 0;
+  var c1 = new Class();
+  c1.method();
+  var c2 = new Class();
+  c2.lateInstanceField = 0;
+  c2.lateFinalInstanceField2 = 0;
+  Class.lateStaticField = 0;
+  Class.lateFinalStaticField2 = 0;
+}
+
+errors() {
+  lateFinalTopLevelFieldWithInit = 0;
+  var c = new Class();
+  c.lateFinalInstanceFieldWithInit = 0;
+  c.methodWithErrors();
+  Class.lateFinalStaticFieldWithInit = 0;
+}
diff --git a/pkg/front_end/testcases/nnbd/late.dart.outline.expect b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
index 4c3658f..ab02fd7 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.outline.expect
@@ -4,15 +4,28 @@
 
 class Class extends core::Object {
   late field core::int lateInstanceField;
-  late final field core::int finalLateInstanceField;
+  late final field core::int lateFinalInstanceField1;
+  late final field core::int lateFinalInstanceField2;
+  late final field core::int lateFinalInstanceFieldWithInit;
+  late field self::Class lateInstanceFieldThis;
+  late final field self::Class lateFinalInstanceFieldThis;
   late static field core::int lateStaticField;
-  late static final field core::int finalLateStaticField;
+  late static final field core::int lateFinalStaticField1;
+  late static final field core::int lateFinalStaticField2;
+  late static final field core::int lateFinalStaticFieldWithInit;
   synthetic constructor •() → self::Class*
     ;
   method method() → dynamic
     ;
+  method methodWithErrors() → dynamic
+    ;
 }
-late static field core::int lateStaticField;
-late static final field core::int finalLateStaticField;
+late static field core::int lateTopLevelField;
+late static final field core::int lateFinalTopLevelField;
+late static final field core::int lateFinalTopLevelFieldWithInit;
 static method main() → dynamic
   ;
+static method noErrors() → dynamic
+  ;
+static method errors() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
index 06376e9..190ad8e 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
@@ -1,20 +1,105 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/late.dart:40:5: Error: Setter not found: 'lateFinalVariableWithInit'.
+//     lateFinalVariableWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:44:5: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+//     lateFinalStaticFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:42:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+//     lateFinalInstanceFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
+//   lateFinalTopLevelFieldWithInit = 0;
+//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:67:9: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+//   Class.lateFinalStaticFieldWithInit = 0;
+//         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+//   c.lateFinalInstanceFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
 class Class extends core::Object {
-  late field core::int lateInstanceField = null;
-  late final field core::int finalLateInstanceField = 0;
-  late static field core::int lateStaticField = null;
-  late static final field core::int finalLateStaticField = 0;
+  late field core::int lateInstanceField;
+  late final field core::int lateFinalInstanceField1;
+  late final field core::int lateFinalInstanceField2;
+  late final field core::int lateFinalInstanceFieldWithInit = 0;
+  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 field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class*
     : super core::Object::•()
     ;
   method method() → dynamic {
     late core::int lateVariable;
-    late final core::int lateFinalVariable = 0;
+    late final core::int lateFinalVariable;
+    late final core::int lateFinalVariableWithInit = 0;
+    lateVariable = 0;
+    lateFinalVariable = 0;
+    this.{self::Class::lateInstanceField} = 0;
+    this.{self::Class::lateFinalInstanceField1} = 0;
+    self::Class::lateStaticField = 0;
+    self::Class::lateFinalStaticField1 = 0;
+  }
+  method methodWithErrors() → dynamic {
+    late final core::int lateFinalVariableWithInit = 0;
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:40:5: Error: Setter not found: 'lateFinalVariableWithInit'.
+    lateFinalVariableWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^";
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:42:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+    lateFinalInstanceFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:44:5: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+    lateFinalStaticFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
   }
 }
-late static field core::int lateStaticField;
-late static final field core::int finalLateStaticField;
+late static field core::int lateTopLevelField;
+late static final field core::int lateFinalTopLevelField;
+late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
+static method noErrors() → dynamic {
+  self::lateTopLevelField = 0;
+  self::lateFinalTopLevelField = 0;
+  self::Class* c1 = new self::Class::•();
+  c1.{self::Class::method}();
+  self::Class* c2 = new self::Class::•();
+  c2.{self::Class::lateInstanceField} = 0;
+  c2.{self::Class::lateFinalInstanceField2} = 0;
+  self::Class::lateStaticField = 0;
+  self::Class::lateFinalStaticField2 = 0;
+}
+static method errors() → dynamic {
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
+  lateFinalTopLevelFieldWithInit = 0;
+  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+  self::Class* c = new self::Class::•();
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+  c.lateFinalInstanceFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+  c.{self::Class::methodWithErrors}();
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:67:9: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+  Class.lateFinalStaticFieldWithInit = 0;
+        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+}
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 06376e9..190ad8e 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
@@ -1,20 +1,105 @@
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/late.dart:40:5: Error: Setter not found: 'lateFinalVariableWithInit'.
+//     lateFinalVariableWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:44:5: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+//     lateFinalStaticFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:42:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+//     lateFinalInstanceFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
+//   lateFinalTopLevelFieldWithInit = 0;
+//   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:67:9: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+//   Class.lateFinalStaticFieldWithInit = 0;
+//         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+// Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+//   c.lateFinalInstanceFieldWithInit = 0;
+//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
 class Class extends core::Object {
-  late field core::int lateInstanceField = null;
-  late final field core::int finalLateInstanceField = 0;
-  late static field core::int lateStaticField = null;
-  late static final field core::int finalLateStaticField = 0;
+  late field core::int lateInstanceField;
+  late final field core::int lateFinalInstanceField1;
+  late final field core::int lateFinalInstanceField2;
+  late final field core::int lateFinalInstanceFieldWithInit = 0;
+  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 field core::int lateFinalStaticFieldWithInit = 0;
   synthetic constructor •() → self::Class*
     : super core::Object::•()
     ;
   method method() → dynamic {
     late core::int lateVariable;
-    late final core::int lateFinalVariable = 0;
+    late final core::int lateFinalVariable;
+    late final core::int lateFinalVariableWithInit = 0;
+    lateVariable = 0;
+    lateFinalVariable = 0;
+    this.{self::Class::lateInstanceField} = 0;
+    this.{self::Class::lateFinalInstanceField1} = 0;
+    self::Class::lateStaticField = 0;
+    self::Class::lateFinalStaticField1 = 0;
+  }
+  method methodWithErrors() → dynamic {
+    late final core::int lateFinalVariableWithInit = 0;
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:40:5: Error: Setter not found: 'lateFinalVariableWithInit'.
+    lateFinalVariableWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^";
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:42:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+    lateFinalInstanceFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+    invalid-expression "pkg/front_end/testcases/nnbd/late.dart:44:5: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+    lateFinalStaticFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
   }
 }
-late static field core::int lateStaticField;
-late static final field core::int finalLateStaticField;
+late static field core::int lateTopLevelField;
+late static final field core::int lateFinalTopLevelField;
+late static final field core::int lateFinalTopLevelFieldWithInit = 0;
 static method main() → dynamic {}
+static method noErrors() → dynamic {
+  self::lateTopLevelField = 0;
+  self::lateFinalTopLevelField = 0;
+  self::Class* c1 = new self::Class::•();
+  c1.{self::Class::method}();
+  self::Class* c2 = new self::Class::•();
+  c2.{self::Class::lateInstanceField} = 0;
+  c2.{self::Class::lateFinalInstanceField2} = 0;
+  self::Class::lateStaticField = 0;
+  self::Class::lateFinalStaticField2 = 0;
+}
+static method errors() → dynamic {
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
+  lateFinalTopLevelFieldWithInit = 0;
+  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+  self::Class* c = new self::Class::•();
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
+ - 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
+Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
+  c.lateFinalInstanceFieldWithInit = 0;
+    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+  c.{self::Class::methodWithErrors}();
+  invalid-expression "pkg/front_end/testcases/nnbd/late.dart:67:9: Error: Setter not found: 'lateFinalStaticFieldWithInit'.
+  Class.lateFinalStaticFieldWithInit = 0;
+        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+}
diff --git a/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect
new file mode 100644
index 0000000..d8c4180
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/late.dart.type_promotion.expect
@@ -0,0 +1,6 @@
+pkg/front_end/testcases/nnbd/late.dart:29:23: Context: Write to lateFinalVariable@862
+    lateFinalVariable = 0;
+                      ^
+pkg/front_end/testcases/nnbd/late.dart:40:31: Context: Write to lateFinalVariableWithInit@1146
+    lateFinalVariableWithInit = 0;
+                              ^
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart b/pkg/front_end/testcases/nnbd/null_shorting.dart
new file mode 100644
index 0000000..3f9a93b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart
@@ -0,0 +1,130 @@
+// 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.
+
+class Class {
+  Class? field;
+  Class? method() => field;
+
+  Class? operator [](Class? key) => field;
+  void operator []=(Class? key, Class? value) {
+    field = value;
+  }
+
+  Class? operator +(int value) => field;
+}
+
+main() {
+  propertyAccess(null);
+  indexAccess(null);
+  operatorAccess(null);
+  ifNull(null);
+}
+
+void propertyAccess(Class? c) {
+  c?.field;
+  c?.field = new Class();
+  c = c?.field = new Class();
+  c?.method();
+
+  c?.field.field;
+  c?.field.field = new Class();
+  c = c?.field.field = new Class();
+  c?.field.method();
+  c?.field = new Class().field;
+  c = c?.field = new Class().field;
+  c?.field = new Class().field = new Class();
+  c = c?.field = new Class().field = new Class();
+  c?.field = new Class().method();
+  c = c?.field = new Class().method();
+  c?.method().field;
+  c?.method().field = new Class();
+  c?.method().method();
+
+  c?.field.field.field;
+  c?.field.field.field = new Class();
+  c = c?.field.field.field = new Class();
+  c?.field.field.method();
+  c?.field = new Class().field.field;
+  c = c?.field = new Class().field.field;
+  c?.field = new Class().field.field = new Class();
+  c = c?.field = new Class().field.field = new Class();
+  c?.field = new Class().field.method();
+  c = c?.field = new Class().field.method();
+  c?.method().field.field;
+  c?.method().field.field = new Class();
+  c?.method().field.method();
+
+  c?.field.field = new Class().field;
+  c = c?.field.field = new Class().field;
+  c?.field.field = new Class().field = new Class();
+  c = c?.field.field = new Class().field = new Class();
+  c?.field.field = new Class().method();
+  c = c?.field.field = new Class().method();
+  c?.field = new Class().field = new Class().field;
+  c = c?.field = new Class().field = new Class().field;
+  c?.field = new Class().field = new Class().field = new Class();
+  c = c?.field = new Class().field = new Class().field = new Class();
+  c?.field = new Class().field = new Class().method();
+  c = c?.field = new Class().field = new Class().method();
+  c?.method().field = new Class().field;
+  c = c?.method().field = new Class().field;
+  c?.method().field = new Class().field = new Class();
+  c = c?.method().field = new Class().field = new Class();
+  c?.method().field = new Class().method();
+  c = c?.method().field = new Class().method();
+
+  c?.field.method().field;
+  c?.field.method().field = new Class();
+  c = c?.field.method().field = new Class();
+  c?.field.method().method();
+  c?.field = new Class().method().field;
+  c = c?.field = new Class().method().field;
+  c?.field = new Class().method().field = new Class();
+  c = c?.field = new Class().method().field = new Class();
+  c?.field = new Class().method().method();
+  c = c?.field = new Class().method().method();
+  c?.method().method().field;
+  c?.method().method().field = new Class();
+  c?.method().method().method();
+}
+
+void indexAccess(Class? c) {
+  // TODO(johnniwinther): Handle null aware index access.
+  //c?.[c];
+  //c?.[c] = new Class();
+  //c?.[c].method();
+  c?.field[c];
+  c?.field[c] = new Class();
+  c = c?.field[c] = new Class();
+  c?.field[c].method();
+  c?.field[c] += 0;
+  c = c?.field[c] += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  //  update.
+  c?.field[c]++;
+  c = c?.field[c]++;
+  ++c?.field[c];
+  c = ++c?.field[c];
+}
+
+void operatorAccess(Class? c) {
+  // TODO(johnniwinther): + should _not_ be null-shortened.
+  c?.field + 0;
+  c?.field += 0;
+  c = c?.field += 0;
+  c?.field.field += 0;
+  c = c?.field.field += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  //  update.
+  c?.field++;
+  c = c?.field++;
+  ++c?.field;
+  c = ++c?.field;
+}
+
+void ifNull(Class? c) {
+  c?.field ??= c;
+  c = c?.field ??= c;
+  c?.field[c] ??= c;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
new file mode 100644
index 0000000..707d670
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? field;
+  synthetic constructor •() → self::Class*
+    ;
+  method method() → self::Class?
+    ;
+  operator [](self::Class? key) → self::Class?
+    ;
+  operator []=(self::Class? key, self::Class? value) → void
+    ;
+  operator +(core::int value) → self::Class?
+    ;
+}
+static method main() → dynamic
+  ;
+static method propertyAccess(self::Class? c) → void
+  ;
+static method indexAccess(self::Class? c) → void
+  ;
+static method operatorAccess(self::Class? c) → void
+  ;
+static method ifNull(self::Class? c) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
new file mode 100644
index 0000000..45eb1bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
@@ -0,0 +1,116 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method method() → self::Class?
+    return this.{self::Class::field};
+  operator [](self::Class? key) → self::Class?
+    return this.{self::Class::field};
+  operator []=(self::Class? key, self::Class? value) → void {
+    this.{self::Class::field} = value;
+  }
+  operator +(core::int value) → self::Class?
+    return this.{self::Class::field};
+}
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : #t1.{self::Class::field};
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : #t2.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : #t3.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
+  let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class*} null : #t7.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : #t8.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class?} null : #t10.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class*} null : #t11.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class*} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class?} null : #t15.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class*} null : #t16.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::field}.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : #t20.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class?} null : #t22.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class?} null : #t23.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class*} null : #t24.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  c = let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class?} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class?} null : #t28.{self::Class::method}().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class*} null : #t29.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::method}().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : #t32.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : #t33.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : #t37.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : #t39.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class*} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : #t43.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : #t45.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class*} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class?} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class?} null : #t49.{self::Class::field}.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : #t50.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class*} null : #t51.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class?} null : #t53.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : #t54.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : #t55.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class*} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : #t59.{self::Class::method}().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : #t60.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::method}().{self::Class::method}().{self::Class::method}();
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::field}.{self::Class::[]}(c);
+  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{void} null : #t63.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t65 = #t64.{self::Class::field} in let final self::Class? #t66 = c in let final self::Class* #t67 = new self::Class::•() in let final void #t68 = #t65.{self::Class::[]=}(#t66, #t67) in #t67;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : #t69.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+  let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in #t71.{self::Class::[]=}(#t72, #t71.{self::Class::[]}(#t72).{self::Class::+}(0));
+  c = let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in let final self::Class? #t76 = #t74.{self::Class::[]}(#t75).{self::Class::+}(0) in let final void #t77 = #t74.{self::Class::[]=}(#t75, #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t79 = #t78.{self::Class::field} in let final self::Class? #t80 = c in #t79.{self::Class::[]=}(#t80, #t79.{self::Class::[]}(#t80).{self::Class::+}(1));
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in let final self::Class? #t84 = #t82.{self::Class::[]}(#t83) in let final void #t85 = #t82.{self::Class::[]=}(#t83, #t84.{self::Class::+}(1)) in #t84;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t87 = #t86.{self::Class::field} in let final self::Class? #t88 = c in let final self::Class? #t89 = #t87.{self::Class::[]}(#t88).{self::Class::+}(1) in let final void #t90 = #t87.{self::Class::[]=}(#t88, #t89) in #t89;
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t92 = #t91.{self::Class::field} in let final self::Class? #t93 = c in let final self::Class? #t94 = #t92.{self::Class::[]}(#t93).{self::Class::+}(1) in let final void #t95 = #t92.{self::Class::[]=}(#t93, #t94) in #t94;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : #t96.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : #t97.{self::Class::field} = #t97.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t99 = #t98.{self::Class::field}.{self::Class::+}(0) in let final void #t100 = #t98.{self::Class::field} = #t99 in #t99;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = #t101.{self::Class::field} in #t102.{self::Class::field} = #t102.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t104 = #t103.{self::Class::field} in #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : #t105.{self::Class::field} = #t105.{self::Class::field}.{self::Class::+}(1);
+  c = let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t107 = #t106.{self::Class::field} in let final void #t108 = #t106.{self::Class::field} = #t107.{self::Class::+}(1) in #t107;
+  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t110 = #t109.{self::Class::field}.{self::Class::+}(1) in let final void #t111 = #t109.{self::Class::field} = #t110 in #t110;
+  c = let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t113 = #t112.{self::Class::field}.{self::Class::+}(1) in let final void #t114 = #t112.{self::Class::field} = #t113 in #t113;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t115 = c in #t115.{core::Object::==}(null) ?{self::Class?} null : #t115.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t115.{self::Class::field} = c : null;
+  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field} in #t117.{core::Object::==}(null) ?{self::Class?} #t116.{self::Class::field} = c : #t117;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t119 = #t118.{self::Class::field} in let final self::Class? #t120 = c in #t119.{self::Class::[]}(#t120).{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::[]=}(#t120, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
new file mode 100644
index 0000000..45eb1bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
@@ -0,0 +1,116 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  method method() → self::Class?
+    return this.{self::Class::field};
+  operator [](self::Class? key) → self::Class?
+    return this.{self::Class::field};
+  operator []=(self::Class? key, self::Class? value) → void {
+    this.{self::Class::field} = value;
+  }
+  operator +(core::int value) → self::Class?
+    return this.{self::Class::field};
+}
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : #t1.{self::Class::field};
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : #t2.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : #t3.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
+  let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class*} null : #t7.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : #t8.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class?} null : #t10.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class*} null : #t11.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class*} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class?} null : #t15.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class*} null : #t16.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::field}.{self::Class::field}.{self::Class::field};
+  let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : #t20.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class?} null : #t22.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class?} null : #t23.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class*} null : #t24.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  c = let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class?} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class?} null : #t28.{self::Class::method}().{self::Class::field}.{self::Class::field};
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class*} null : #t29.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::method}().{self::Class::field}.{self::Class::method}();
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : #t32.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : #t33.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : #t37.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : #t39.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class*} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : #t43.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
+  let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : #t45.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class*} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  c = let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class?} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
+  let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class?} null : #t49.{self::Class::field}.{self::Class::method}().{self::Class::field};
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : #t50.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class*} null : #t51.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class?} null : #t53.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : #t54.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : #t55.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class*} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
+  let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : #t59.{self::Class::method}().{self::Class::method}().{self::Class::field};
+  let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : #t60.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::method}().{self::Class::method}().{self::Class::method}();
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::field}.{self::Class::[]}(c);
+  let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{void} null : #t63.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t65 = #t64.{self::Class::field} in let final self::Class? #t66 = c in let final self::Class* #t67 = new self::Class::•() in let final void #t68 = #t65.{self::Class::[]=}(#t66, #t67) in #t67;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : #t69.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+  let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in #t71.{self::Class::[]=}(#t72, #t71.{self::Class::[]}(#t72).{self::Class::+}(0));
+  c = let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in let final self::Class? #t76 = #t74.{self::Class::[]}(#t75).{self::Class::+}(0) in let final void #t77 = #t74.{self::Class::[]=}(#t75, #t76) in #t76;
+  let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t79 = #t78.{self::Class::field} in let final self::Class? #t80 = c in #t79.{self::Class::[]=}(#t80, #t79.{self::Class::[]}(#t80).{self::Class::+}(1));
+  c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in let final self::Class? #t84 = #t82.{self::Class::[]}(#t83) in let final void #t85 = #t82.{self::Class::[]=}(#t83, #t84.{self::Class::+}(1)) in #t84;
+  let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t87 = #t86.{self::Class::field} in let final self::Class? #t88 = c in let final self::Class? #t89 = #t87.{self::Class::[]}(#t88).{self::Class::+}(1) in let final void #t90 = #t87.{self::Class::[]=}(#t88, #t89) in #t89;
+  c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t92 = #t91.{self::Class::field} in let final self::Class? #t93 = c in let final self::Class? #t94 = #t92.{self::Class::[]}(#t93).{self::Class::+}(1) in let final void #t95 = #t92.{self::Class::[]=}(#t93, #t94) in #t94;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : #t96.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : #t97.{self::Class::field} = #t97.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t99 = #t98.{self::Class::field}.{self::Class::+}(0) in let final void #t100 = #t98.{self::Class::field} = #t99 in #t99;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = #t101.{self::Class::field} in #t102.{self::Class::field} = #t102.{self::Class::field}.{self::Class::+}(0);
+  c = let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t104 = #t103.{self::Class::field} in #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : #t105.{self::Class::field} = #t105.{self::Class::field}.{self::Class::+}(1);
+  c = let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t107 = #t106.{self::Class::field} in let final void #t108 = #t106.{self::Class::field} = #t107.{self::Class::+}(1) in #t107;
+  let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t110 = #t109.{self::Class::field}.{self::Class::+}(1) in let final void #t111 = #t109.{self::Class::field} = #t110 in #t110;
+  c = let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t113 = #t112.{self::Class::field}.{self::Class::+}(1) in let final void #t114 = #t112.{self::Class::field} = #t113 in #t113;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t115 = c in #t115.{core::Object::==}(null) ?{self::Class?} null : #t115.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t115.{self::Class::field} = c : null;
+  c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field} in #t117.{core::Object::==}(null) ?{self::Class?} #t116.{self::Class::field} = c : #t117;
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t119 = #t118.{self::Class::field} in let final self::Class? #t120 = c in #t119.{self::Class::[]}(#t120).{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::[]=}(#t120, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect
new file mode 100644
index 0000000..20c93f0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.type_promotion.expect
@@ -0,0 +1,93 @@
+pkg/front_end/testcases/nnbd/null_shorting.dart:27:5: Context: Write to c@558
+  c = c?.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:32:5: Context: Write to c@558
+  c = c?.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:35:5: Context: Write to c@558
+  c = c?.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:37:5: Context: Write to c@558
+  c = c?.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:39:5: Context: Write to c@558
+  c = c?.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:46:5: Context: Write to c@558
+  c = c?.field.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:49:5: Context: Write to c@558
+  c = c?.field = new Class().field.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:51:5: Context: Write to c@558
+  c = c?.field = new Class().field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:53:5: Context: Write to c@558
+  c = c?.field = new Class().field.method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:59:5: Context: Write to c@558
+  c = c?.field.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:61:5: Context: Write to c@558
+  c = c?.field.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:63:5: Context: Write to c@558
+  c = c?.field.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:65:5: Context: Write to c@558
+  c = c?.field = new Class().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:67:5: Context: Write to c@558
+  c = c?.field = new Class().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:69:5: Context: Write to c@558
+  c = c?.field = new Class().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:71:5: Context: Write to c@558
+  c = c?.method().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:73:5: Context: Write to c@558
+  c = c?.method().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:75:5: Context: Write to c@558
+  c = c?.method().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:79:5: Context: Write to c@558
+  c = c?.field.method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:82:5: Context: Write to c@558
+  c = c?.field = new Class().method().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:84:5: Context: Write to c@558
+  c = c?.field = new Class().method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:86:5: Context: Write to c@558
+  c = c?.field = new Class().method().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:99:5: Context: Write to c@558
+  c = c?.field[c] = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:102:5: Context: Write to c@558
+  c = c?.field[c] += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:106:5: Context: Write to c@558
+  c = c?.field[c]++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:108:5: Context: Write to c@558
+  c = ++c?.field[c];
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:115:5: Context: Write to c@558
+  c = c?.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:117:5: Context: Write to c@558
+  c = c?.field.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:121:5: Context: Write to c@558
+  c = c?.field++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:123:5: Context: Write to c@558
+  c = ++c?.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting.dart:128:5: Context: Write to c@558
+  c = c?.field ??= c;
+    ^
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
new file mode 100644
index 0000000..78ec83e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
@@ -0,0 +1,138 @@
+// 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.
+
+class Class {
+  Class? _field;
+}
+
+extension Extension on Class {
+  Class? get field => _field;
+  void set field(Class? value) {
+    _field = value;
+  }
+
+  Class? method() => field;
+
+  Class? operator [](Class? key) => field;
+  void operator []=(Class? key, Class? value) {
+    field = value;
+  }
+
+  Class? operator +(int value) => field;
+}
+
+main() {
+  propertyAccess(null);
+  indexAccess(null);
+  operatorAccess(null);
+  ifNull(null);
+}
+
+void propertyAccess(Class? c) {
+  Extension(c)?.field;
+  Extension(c)?.field = new Class();
+  c = Extension(c)?.field = new Class();
+  Extension(c)?.method();
+
+  Extension(c)?.field.field;
+  Extension(c)?.field.field = new Class();
+  c = Extension(c)?.field.field = new Class();
+  Extension(c)?.field.method();
+  Extension(c)?.field = new Class().field;
+  c = Extension(c)?.field = new Class().field;
+  Extension(c)?.field = new Class().field = new Class();
+  c = Extension(c)?.field = new Class().field = new Class();
+  Extension(c)?.field = new Class().method();
+  c = Extension(c)?.field = new Class().method();
+  Extension(c)?.method().field;
+  Extension(c)?.method().field = new Class();
+  Extension(c)?.method().method();
+
+  Extension(c)?.field.field.field;
+  Extension(c)?.field.field.field = new Class();
+  c = Extension(c)?.field.field.field = new Class();
+  Extension(c)?.field.field.method();
+  Extension(c)?.field = new Class().field.field;
+  c = Extension(c)?.field = new Class().field.field;
+  Extension(c)?.field = new Class().field.field = new Class();
+  c = Extension(c)?.field = new Class().field.field = new Class();
+  Extension(c)?.field = new Class().field.method();
+  c = Extension(c)?.field = new Class().field.method();
+  Extension(c)?.method().field.field;
+  Extension(c)?.method().field.field = new Class();
+  Extension(c)?.method().field.method();
+
+  Extension(c)?.field.field = new Class().field;
+  c = Extension(c)?.field.field = new Class().field;
+  Extension(c)?.field.field = new Class().field = new Class();
+  c = Extension(c)?.field.field = new Class().field = new Class();
+  Extension(c)?.field.field = new Class().method();
+  c = Extension(c)?.field.field = new Class().method();
+  Extension(c)?.field = new Class().field = new Class().field;
+  c = Extension(c)?.field = new Class().field = new Class().field;
+  Extension(c)?.field = new Class().field = new Class().field = new Class();
+  c = Extension(c)?.field = new Class().field = new Class().field = new Class();
+  Extension(c)?.field = new Class().field = new Class().method();
+  c = Extension(c)?.field = new Class().field = new Class().method();
+  Extension(c)?.method().field = new Class().field;
+  c = Extension(c)?.method().field = new Class().field;
+  Extension(c)?.method().field = new Class().field = new Class();
+  c = Extension(c)?.method().field = new Class().field = new Class();
+  Extension(c)?.method().field = new Class().method();
+  c = Extension(c)?.method().field = new Class().method();
+
+  Extension(c)?.field.method().field;
+  Extension(c)?.field.method().field = new Class();
+  c = Extension(c)?.field.method().field = new Class();
+  Extension(c)?.field.method().method();
+  Extension(c)?.field = new Class().method().field;
+  c = Extension(c)?.field = new Class().method().field;
+  Extension(c)?.field = new Class().method().field = new Class();
+  c = Extension(c)?.field = new Class().method().field = new Class();
+  Extension(c)?.field = new Class().method().method();
+  c = Extension(c)?.field = new Class().method().method();
+  Extension(c)?.method().method().field;
+  Extension(c)?.method().method().field = new Class();
+  Extension(c)?.method().method().method();
+}
+
+void indexAccess(Class? c) {
+  // TODO(johnniwinther): Handle null aware index access.
+  //Extension(c)?.[c];
+  //Extension(c)?.[c] = new Class();
+  //Extension(c)?.[c].method();
+  Extension(c)?.field[c];
+  Extension(c)?.field[c] = new Class();
+  c = Extension(c)?.field[c] = new Class();
+  Extension(c)?.field[c].method();
+  Extension(c)?.field[c] += 0;
+  c = Extension(c)?.field[c] += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  // update.
+  Extension(c)?.field[c]++;
+  c = Extension(c)?.field[c]++;
+  ++Extension(c)?.field[c];
+  c = ++Extension(c)?.field[c];
+}
+
+void operatorAccess(Class? c) {
+  // TODO(johnniwinther): + should _not_ be null-shortened.
+  Extension(c)?.field + 0;
+  Extension(c)?.field += 0;
+  c = Extension(c)?.field += 0;
+  Extension(c)?.field.field += 0;
+  c = Extension(c)?.field.field += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  // update.
+  Extension(c)?.field++;
+  c = Extension(c)?.field++;
+  ++Extension(c)?.field;
+  c = ++Extension(c)?.field;
+}
+
+void ifNull(Class? c) {
+  Extension(c)?.field ??= c;
+  c = Extension(c)?.field ??= c;
+  Extension(c)?.field[c] ??= c;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
new file mode 100644
index 0000000..b39c0d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.outline.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field;
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  ;
+static method Extension|set#field(final self::Class #this, self::Class? value) → void
+  ;
+static method Extension|method(final self::Class #this) → self::Class?
+  ;
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  ;
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void
+  ;
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  ;
+static method main() → dynamic
+  ;
+static method propertyAccess(self::Class? c) → void
+  ;
+static method indexAccess(self::Class? c) → void
+  ;
+static method operatorAccess(self::Class? c) → void
+  ;
+static method ifNull(self::Class? c) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
new file mode 100644
index 0000000..d579764
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
@@ -0,0 +1,132 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  return #this.{self::Class::_field};
+static method Extension|set#field(final self::Class #this, self::Class? value) → void {
+  #this.{self::Class::_field} = value;
+}
+static method Extension|method(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void {
+  self::Extension|set#field(#this, value);
+}
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  return self::Extension|get#field(#this);
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
+  let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
+  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
+  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
+  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
+  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
+  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
+  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
+  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
+  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
+  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
+  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
+  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
+  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
+  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
+  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
+  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
+  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
+  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
+  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
+  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
+  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
+  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
+  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
+  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
+  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final self::Class? #t190 = let final self::Class? #t191 = self::Extension|+(#t189, 1) in let final void #t192 = self::Extension|set#field(#t188, #t191) in #t191 in #t189;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 1) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+  c = let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t197 = self::Extension|+(self::Extension|get#field(#t196), 1) in let final void #t198 = self::Extension|set#field(#t196, #t197) in #t197;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t199).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t199, c) : null;
+  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|get#field(#t200) in #t201.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t202 = c in let final void #t203 = self::Extension|set#field(#t200, #t202) in #t202 : #t201;
+  let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in let final self::Class? #t206 = c in self::Extension|[](#t205, #t206).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t205, #t206, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
new file mode 100644
index 0000000..d579764
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
@@ -0,0 +1,132 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  return #this.{self::Class::_field};
+static method Extension|set#field(final self::Class #this, self::Class? value) → void {
+  #this.{self::Class::_field} = value;
+}
+static method Extension|method(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void {
+  self::Extension|set#field(#this, value);
+}
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  return self::Extension|get#field(#this);
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
+  let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
+  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
+  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
+  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
+  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
+  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
+  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
+  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
+  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
+  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
+  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
+  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
+  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
+  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
+  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
+  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
+  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
+  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
+  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
+  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
+  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
+  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
+  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
+  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
+  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final self::Class? #t190 = let final self::Class? #t191 = self::Extension|+(#t189, 1) in let final void #t192 = self::Extension|set#field(#t188, #t191) in #t191 in #t189;
+  let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 1) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+  c = let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t197 = self::Extension|+(self::Extension|get#field(#t196), 1) in let final void #t198 = self::Extension|set#field(#t196, #t197) in #t197;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t199).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t199, c) : null;
+  c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|get#field(#t200) in #t201.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t202 = c in let final void #t203 = self::Extension|set#field(#t200, #t202) in #t202 : #t201;
+  let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in let final self::Class? #t206 = c in self::Extension|[](#t205, #t206).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t205, #t206, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect
new file mode 100644
index 0000000..c773aae
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.type_promotion.expect
@@ -0,0 +1,93 @@
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:35:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:40:5: Context: Write to c@681
+  c = Extension(c)?.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:43:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:45:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:47:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:54:5: Context: Write to c@681
+  c = Extension(c)?.field.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:57:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:59:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:61:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field.method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:67:5: Context: Write to c@681
+  c = Extension(c)?.field.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:69:5: Context: Write to c@681
+  c = Extension(c)?.field.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:71:5: Context: Write to c@681
+  c = Extension(c)?.field.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:73:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:75:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:77:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:79:5: Context: Write to c@681
+  c = Extension(c)?.method().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:81:5: Context: Write to c@681
+  c = Extension(c)?.method().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:83:5: Context: Write to c@681
+  c = Extension(c)?.method().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:87:5: Context: Write to c@681
+  c = Extension(c)?.field.method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:90:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().method().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:92:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:94:5: Context: Write to c@681
+  c = Extension(c)?.field = new Class().method().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:107:5: Context: Write to c@681
+  c = Extension(c)?.field[c] = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:110:5: Context: Write to c@681
+  c = Extension(c)?.field[c] += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:114:5: Context: Write to c@681
+  c = Extension(c)?.field[c]++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:116:5: Context: Write to c@681
+  c = ++Extension(c)?.field[c];
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:123:5: Context: Write to c@681
+  c = Extension(c)?.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:125:5: Context: Write to c@681
+  c = Extension(c)?.field.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:129:5: Context: Write to c@681
+  c = Extension(c)?.field++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:131:5: Context: Write to c@681
+  c = ++Extension(c)?.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart:136:5: Context: Write to c@681
+  c = Extension(c)?.field ??= c;
+    ^
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
new file mode 100644
index 0000000..ee725c7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
@@ -0,0 +1,138 @@
+// 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.
+
+class Class {
+  Class? _field;
+}
+
+extension Extension on Class {
+  Class? get field => _field;
+  void set field(Class? value) {
+    _field = value;
+  }
+
+  Class? method() => field;
+
+  Class? operator [](Class? key) => field;
+  void operator []=(Class? key, Class? value) {
+    field = value;
+  }
+
+  Class? operator +(int value) => field;
+}
+
+main() {
+  propertyAccess(null);
+  indexAccess(null);
+  operatorAccess(null);
+  ifNull(null);
+}
+
+void propertyAccess(Class? c) {
+  c?.field;
+  c?.field = new Class();
+  c = c?.field = new Class();
+  c?.method();
+
+  c?.field.field;
+  c?.field.field = new Class();
+  c = c?.field.field = new Class();
+  c?.field.method();
+  c?.field = new Class().field;
+  c = c?.field = new Class().field;
+  c?.field = new Class().field = new Class();
+  c = c?.field = new Class().field = new Class();
+  c?.field = new Class().method();
+  c = c?.field = new Class().method();
+  c?.method().field;
+  c?.method().field = new Class();
+  c?.method().method();
+
+  c?.field.field.field;
+  c?.field.field.field = new Class();
+  c = c?.field.field.field = new Class();
+  c?.field.field.method();
+  c?.field = new Class().field.field;
+  c = c?.field = new Class().field.field;
+  c?.field = new Class().field.field = new Class();
+  c = c?.field = new Class().field.field = new Class();
+  c?.field = new Class().field.method();
+  c = c?.field = new Class().field.method();
+  c?.method().field.field;
+  c?.method().field.field = new Class();
+  c?.method().field.method();
+
+  c?.field.field = new Class().field;
+  c = c?.field.field = new Class().field;
+  c?.field.field = new Class().field = new Class();
+  c = c?.field.field = new Class().field = new Class();
+  c?.field.field = new Class().method();
+  c = c?.field.field = new Class().method();
+  c?.field = new Class().field = new Class().field;
+  c = c?.field = new Class().field = new Class().field;
+  c?.field = new Class().field = new Class().field = new Class();
+  c = c?.field = new Class().field = new Class().field = new Class();
+  c?.field = new Class().field = new Class().method();
+  c = c?.field = new Class().field = new Class().method();
+  c?.method().field = new Class().field;
+  c = c?.method().field = new Class().field;
+  c?.method().field = new Class().field = new Class();
+  c = c?.method().field = new Class().field = new Class();
+  c?.method().field = new Class().method();
+  c = c?.method().field = new Class().method();
+
+  c?.field.method().field;
+  c?.field.method().field = new Class();
+  c = c?.field.method().field = new Class();
+  c?.field.method().method();
+  c?.field = new Class().method().field;
+  c = c?.field = new Class().method().field;
+  c?.field = new Class().method().field = new Class();
+  c = c?.field = new Class().method().field = new Class();
+  c?.field = new Class().method().method();
+  c = c?.field = new Class().method().method();
+  c?.method().method().field;
+  c?.method().method().field = new Class();
+  c?.method().method().method();
+}
+
+void indexAccess(Class? c) {
+  // TODO(johnniwinther): Handle null aware index access.
+  //c?.[c];
+  //c?.[c] = new Class();
+  //c?.[c].method();
+  c?.field[c];
+  c?.field[c] = new Class();
+  c = c?.field[c] = new Class();
+  c?.field[c].method();
+  c?.field[c] += 0;
+  c = c?.field[c] += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  // update.
+  c?.field[c]++;
+  c = c?.field[c]++;
+  ++c?.field[c];
+  c = ++c?.field[c];
+}
+
+void operatorAccess(Class? c) {
+  // TODO(johnniwinther): + should _not_ be null-shortened.
+  c?.field + 0;
+  c?.field += 0;
+  c = c?.field += 0;
+  c?.field.field += 0;
+  c = c?.field.field += 0;
+  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+  // update.
+  c?.field++;
+  c = c?.field++;
+  ++c?.field;
+  c = ++c?.field;
+}
+
+void ifNull(Class? c) {
+  c?.field ??= c;
+  c = c?.field ??= c;
+  c?.field[c] ??= c;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
new file mode 100644
index 0000000..b39c0d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.outline.expect
@@ -0,0 +1,42 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field;
+  synthetic constructor •() → self::Class*
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  ;
+static method Extension|set#field(final self::Class #this, self::Class? value) → void
+  ;
+static method Extension|method(final self::Class #this) → self::Class?
+  ;
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  ;
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void
+  ;
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  ;
+static method main() → dynamic
+  ;
+static method propertyAccess(self::Class? c) → void
+  ;
+static method indexAccess(self::Class? c) → void
+  ;
+static method operatorAccess(self::Class? c) → void
+  ;
+static method ifNull(self::Class? c) → void
+  ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
new file mode 100644
index 0000000..8bb6efe
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
@@ -0,0 +1,132 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  return #this.{self::Class::_field};
+static method Extension|set#field(final self::Class #this, self::Class? value) → void {
+  #this.{self::Class::_field} = value;
+}
+static method Extension|method(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void {
+  self::Extension|set#field(#this, value);
+}
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  return self::Extension|get#field(#this);
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
+  let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
+  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
+  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
+  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
+  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
+  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
+  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
+  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
+  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
+  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
+  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
+  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
+  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
+  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
+  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
+  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
+  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
+  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
+  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
+  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
+  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
+  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
+  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
+  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
+  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final void #t190 = self::Extension|set#field(#t188, self::Extension|+(#t189, 1)) in #t189;
+  let final self::Class? #t191 = c in #t191.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t192 = self::Extension|+(self::Extension|get#field(#t191), 1) in let final void #t193 = self::Extension|set#field(#t191, #t192) in #t192;
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|+(self::Extension|get#field(#t194), 1) in let final void #t196 = self::Extension|set#field(#t194, #t195) in #t195;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t197).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t197, c) : null;
+  c = let final self::Class? #t198 = c in #t198.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t199 = self::Extension|get#field(#t198) in #t199.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t200 = c in let final void #t201 = self::Extension|set#field(#t198, #t200) in #t200 : #t199;
+  let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|get#field(#t202) in let final self::Class? #t204 = c in self::Extension|[](#t203, #t204).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t203, #t204, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
new file mode 100644
index 0000000..8bb6efe
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
@@ -0,0 +1,132 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  field self::Class? _field = null;
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::Class {
+  get field = self::Extension|get#field;
+  method method = self::Extension|method;
+  tearoff method = self::Extension|get#method;
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+  operator + = self::Extension|+;
+  set field = self::Extension|set#field;
+}
+static method Extension|get#field(final self::Class #this) → self::Class?
+  return #this.{self::Class::_field};
+static method Extension|set#field(final self::Class #this, self::Class? value) → void {
+  #this.{self::Class::_field} = value;
+}
+static method Extension|method(final self::Class #this) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|get#method(final self::Class #this) → () →* self::Class?
+  return () → self::Class? => self::Extension|method(#this);
+static method Extension|[](final self::Class #this, self::Class? key) → self::Class?
+  return self::Extension|get#field(#this);
+static method Extension|[]=(final self::Class #this, self::Class? key, self::Class? value) → void {
+  self::Extension|set#field(#this, value);
+}
+static method Extension|+(final self::Class #this, core::int value) → self::Class?
+  return self::Extension|get#field(#this);
+static method main() → dynamic {
+  self::propertyAccess(null);
+  self::indexAccess(null);
+  self::operatorAccess(null);
+  self::ifNull(null);
+}
+static method propertyAccess(self::Class? c) → void {
+  let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
+  let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
+  c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+  let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
+  let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
+  let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+  c = let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t10 = new self::Class::•() in let final void #t11 = self::Extension|set#field(self::Extension|get#field(#t9), #t10) in #t10;
+  let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t12));
+  let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t13, self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t15 = self::Extension|get#field(new self::Class::•()) in let final void #t16 = self::Extension|set#field(#t14, #t15) in #t15;
+  let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t17, let final self::Class* #t18 = new self::Class::•() in let final void #t19 = self::Extension|set#field(new self::Class::•(), #t18) in #t18);
+  c = let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t21 = let final self::Class* #t22 = new self::Class::•() in let final void #t23 = self::Extension|set#field(new self::Class::•(), #t22) in #t22 in let final void #t24 = self::Extension|set#field(#t20, #t21) in #t21;
+  let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t25, self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t27 = self::Extension|method(new self::Class::•()) in let final void #t28 = self::Extension|set#field(#t26, #t27) in #t27;
+  let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t29));
+  let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t30), new self::Class::•());
+  let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t31));
+  let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t32)));
+  let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t33)), new self::Class::•());
+  c = let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t35 = new self::Class::•() in let final void #t36 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t34)), #t35) in #t35;
+  let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t37)));
+  let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t38, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t40 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t41 = self::Extension|set#field(#t39, #t40) in #t40;
+  let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t42, let final self::Class* #t43 = new self::Class::•() in let final void #t44 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t43) in #t43);
+  c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t46 = let final self::Class* #t47 = new self::Class::•() in let final void #t48 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t47) in #t47 in let final void #t49 = self::Extension|set#field(#t45, #t46) in #t46;
+  let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t50, self::Extension|method(self::Extension|get#field(new self::Class::•())));
+  c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t52 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t53 = self::Extension|set#field(#t51, #t52) in #t52;
+  let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t54)));
+  let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t55)), new self::Class::•());
+  let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t56)));
+  let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t57), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t59 = self::Extension|get#field(new self::Class::•()) in let final void #t60 = self::Extension|set#field(self::Extension|get#field(#t58), #t59) in #t59;
+  let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t61), let final self::Class* #t62 = new self::Class::•() in let final void #t63 = self::Extension|set#field(new self::Class::•(), #t62) in #t62);
+  c = let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t65 = let final self::Class* #t66 = new self::Class::•() in let final void #t67 = self::Extension|set#field(new self::Class::•(), #t66) in #t66 in let final void #t68 = self::Extension|set#field(self::Extension|get#field(#t64), #t65) in #t65;
+  let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t69), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t71 = self::Extension|method(new self::Class::•()) in let final void #t72 = self::Extension|set#field(self::Extension|get#field(#t70), #t71) in #t71;
+  let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t73, let final self::Class? #t74 = self::Extension|get#field(new self::Class::•()) in let final void #t75 = self::Extension|set#field(new self::Class::•(), #t74) in #t74);
+  c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = let final self::Class? #t78 = self::Extension|get#field(new self::Class::•()) in let final void #t79 = self::Extension|set#field(new self::Class::•(), #t78) in #t78 in let final void #t80 = self::Extension|set#field(#t76, #t77) in #t77;
+  let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t81, let final self::Class* #t82 = let final self::Class* #t83 = new self::Class::•() in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(new self::Class::•(), #t82) in #t82);
+  c = let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t87 = let final self::Class* #t88 = let final self::Class* #t89 = new self::Class::•() in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t89) in #t89 in let final void #t91 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t92 = self::Extension|set#field(#t86, #t87) in #t87;
+  let final self::Class? #t93 = c in #t93.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t93, let final self::Class? #t94 = self::Extension|method(new self::Class::•()) in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94);
+  c = let final self::Class? #t96 = c in #t96.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t97 = let final self::Class? #t98 = self::Extension|method(new self::Class::•()) in let final void #t99 = self::Extension|set#field(new self::Class::•(), #t98) in #t98 in let final void #t100 = self::Extension|set#field(#t96, #t97) in #t97;
+  let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t101), self::Extension|get#field(new self::Class::•()));
+  c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = self::Extension|get#field(new self::Class::•()) in let final void #t104 = self::Extension|set#field(self::Extension|method(#t102), #t103) in #t103;
+  let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t105), let final self::Class* #t106 = new self::Class::•() in let final void #t107 = self::Extension|set#field(new self::Class::•(), #t106) in #t106);
+  c = let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t109 = let final self::Class* #t110 = new self::Class::•() in let final void #t111 = self::Extension|set#field(new self::Class::•(), #t110) in #t110 in let final void #t112 = self::Extension|set#field(self::Extension|method(#t108), #t109) in #t109;
+  let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t113), self::Extension|method(new self::Class::•()));
+  c = let final self::Class? #t114 = c in #t114.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t115 = self::Extension|method(new self::Class::•()) in let final void #t116 = self::Extension|set#field(self::Extension|method(#t114), #t115) in #t115;
+  let final self::Class? #t117 = c in #t117.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t117)));
+  let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t118)), new self::Class::•());
+  c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t120 = new self::Class::•() in let final void #t121 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t119)), #t120) in #t120;
+  let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t122)));
+  let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t123, self::Extension|get#field(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t125 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t126 = self::Extension|set#field(#t124, #t125) in #t125;
+  let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t127, let final self::Class* #t128 = new self::Class::•() in let final void #t129 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t128) in #t128);
+  c = let final self::Class? #t130 = c in #t130.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t131 = let final self::Class* #t132 = new self::Class::•() in let final void #t133 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t132) in #t132 in let final void #t134 = self::Extension|set#field(#t130, #t131) in #t131;
+  let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t135, self::Extension|method(self::Extension|method(new self::Class::•())));
+  c = let final self::Class? #t136 = c in #t136.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t137 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t138 = self::Extension|set#field(#t136, #t137) in #t137;
+  let final self::Class? #t139 = c in #t139.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t139)));
+  let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t140)), new self::Class::•());
+  let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t141)));
+}
+static method indexAccess(self::Class? c) → void {
+  let final self::Class? #t142 = c in #t142.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t142), c);
+  let final self::Class? #t143 = c in #t143.{core::Object::==}(null) ?{void} null : self::Extension|[]=(self::Extension|get#field(#t143), c, new self::Class::•());
+  c = let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t145 = self::Extension|get#field(#t144) in let final self::Class? #t146 = c in let final self::Class* #t147 = new self::Class::•() in let final void #t148 = self::Extension|[]=(#t145, #t146, #t147) in #t147;
+  let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t149), c));
+  let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t151 = self::Extension|get#field(#t150) in let final self::Class? #t152 = c in self::Extension|[]=(#t151, #t152, self::Extension|+(self::Extension|[](#t151, #t152), 0));
+  c = let final self::Class? #t153 = c in #t153.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t154 = self::Extension|get#field(#t153) in let final self::Class? #t155 = c in let final self::Class? #t156 = self::Extension|+(self::Extension|[](#t154, #t155), 0) in let final void #t157 = self::Extension|[]=(#t154, #t155, #t156) in #t156;
+  let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 1));
+  c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|[](#t162, #t163) in let final void #t165 = self::Extension|[]=(#t162, #t163, self::Extension|+(#t164, 1)) in #t164;
+  let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|+(self::Extension|[](#t167, #t168), 1) in let final void #t170 = self::Extension|[]=(#t167, #t168, #t169) in #t169;
+  c = let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
+}
+static method operatorAccess(self::Class? c) → void {
+  let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : self::Extension|+(self::Extension|get#field(#t176), 0);
+  let final self::Class? #t177 = c in #t177.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t177, self::Extension|+(self::Extension|get#field(#t177), 0));
+  c = let final self::Class? #t178 = c in #t178.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t179 = self::Extension|+(self::Extension|get#field(#t178), 0) in let final void #t180 = self::Extension|set#field(#t178, #t179) in #t179;
+  let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t182 = self::Extension|get#field(#t181) in self::Extension|set#field(#t182, self::Extension|+(self::Extension|get#field(#t182), 0));
+  c = let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t184 = self::Extension|get#field(#t183) in let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
+  let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t187, self::Extension|+(self::Extension|get#field(#t187), 1));
+  c = let final self::Class? #t188 = c in #t188.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t189 = self::Extension|get#field(#t188) in let final void #t190 = self::Extension|set#field(#t188, self::Extension|+(#t189, 1)) in #t189;
+  let final self::Class? #t191 = c in #t191.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t192 = self::Extension|+(self::Extension|get#field(#t191), 1) in let final void #t193 = self::Extension|set#field(#t191, #t192) in #t192;
+  c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|+(self::Extension|get#field(#t194), 1) in let final void #t196 = self::Extension|set#field(#t194, #t195) in #t195;
+}
+static method ifNull(self::Class? c) → void {
+  let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t197).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t197, c) : null;
+  c = let final self::Class? #t198 = c in #t198.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t199 = self::Extension|get#field(#t198) in #t199.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t200 = c in let final void #t201 = self::Extension|set#field(#t198, #t200) in #t200 : #t199;
+  let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|get#field(#t202) in let final self::Class? #t204 = c in self::Extension|[](#t203, #t204).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t203, #t204, c) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect
new file mode 100644
index 0000000..e88f73d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.type_promotion.expect
@@ -0,0 +1,93 @@
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:35:5: Context: Write to c@681
+  c = c?.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:40:5: Context: Write to c@681
+  c = c?.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:43:5: Context: Write to c@681
+  c = c?.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:45:5: Context: Write to c@681
+  c = c?.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:47:5: Context: Write to c@681
+  c = c?.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:54:5: Context: Write to c@681
+  c = c?.field.field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:57:5: Context: Write to c@681
+  c = c?.field = new Class().field.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:59:5: Context: Write to c@681
+  c = c?.field = new Class().field.field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:61:5: Context: Write to c@681
+  c = c?.field = new Class().field.method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:67:5: Context: Write to c@681
+  c = c?.field.field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:69:5: Context: Write to c@681
+  c = c?.field.field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:71:5: Context: Write to c@681
+  c = c?.field.field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:73:5: Context: Write to c@681
+  c = c?.field = new Class().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:75:5: Context: Write to c@681
+  c = c?.field = new Class().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:77:5: Context: Write to c@681
+  c = c?.field = new Class().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:79:5: Context: Write to c@681
+  c = c?.method().field = new Class().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:81:5: Context: Write to c@681
+  c = c?.method().field = new Class().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:83:5: Context: Write to c@681
+  c = c?.method().field = new Class().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:87:5: Context: Write to c@681
+  c = c?.field.method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:90:5: Context: Write to c@681
+  c = c?.field = new Class().method().field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:92:5: Context: Write to c@681
+  c = c?.field = new Class().method().field = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:94:5: Context: Write to c@681
+  c = c?.field = new Class().method().method();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:107:5: Context: Write to c@681
+  c = c?.field[c] = new Class();
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:110:5: Context: Write to c@681
+  c = c?.field[c] += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:114:5: Context: Write to c@681
+  c = c?.field[c]++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:116:5: Context: Write to c@681
+  c = ++c?.field[c];
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:123:5: Context: Write to c@681
+  c = c?.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:125:5: Context: Write to c@681
+  c = c?.field.field += 0;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:129:5: Context: Write to c@681
+  c = c?.field++;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:131:5: Context: Write to c@681
+  c = ++c?.field;
+    ^
+pkg/front_end/testcases/nnbd/null_shorting_extension.dart:136:5: Context: Write to c@681
+  c = c?.field ??= c;
+    ^
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart b/pkg/front_end/testcases/nnbd/simple_never.dart
new file mode 100644
index 0000000..e0f2e76
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart
@@ -0,0 +1,13 @@
+// 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 checks how programs with Never type in their outline compile.
+
+Never foo() {
+  while (true) {}
+}
+
+Never? bar() => null;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect
new file mode 100644
index 0000000..a1a8eaa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+
+static method foo() → Never
+  ;
+static method bar() → Never?
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect
new file mode 100644
index 0000000..9a621b6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+
+static method foo() → Never{
+  while (true) {
+  }
+}
+static method bar() → Never?
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect
new file mode 100644
index 0000000..9a621b6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/simple_never.dart.strong.transformed.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+
+static method foo() → Never{
+  while (true) {
+  }
+}
+static method bar() → Never?
+  return null;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/old_dills/.gitignore b/pkg/front_end/testcases/old_dills/.gitignore
new file mode 100644
index 0000000..e449e17
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/.gitignore
@@ -0,0 +1 @@
+dills
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill
deleted file mode 100644
index deb7a1a..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.25.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill
deleted file mode 100644
index 40f0b90..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.27.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill
deleted file mode 100644
index 606bbf1..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.28.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill
deleted file mode 100644
index 060ab45..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.29.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.30.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.30.compile.1.dill
deleted file mode 100644
index aff0e19..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.30.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.31.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.31.compile.1.dill
deleted file mode 100644
index d38cb21..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.31.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.32.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.32.compile.1.dill
deleted file mode 100644
index ce5e225..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.32.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill
deleted file mode 100644
index 95c4245..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.33.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill
deleted file mode 100644
index 6af2b34..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.34.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/dart2js.version.35.compile.1.dill b/pkg/front_end/testcases/old_dills/dart2js.version.35.compile.1.dill
deleted file mode 100644
index efeba88..0000000
--- a/pkg/front_end/testcases/old_dills/dart2js.version.35.compile.1.dill
+++ /dev/null
Binary files differ
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 38b00e3..e90a514 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -2,6 +2,12 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE.md file.
 
+inference/downwards_inference_on_list_literals_infer_if_value_types_match_context: ExpectationFileMismatchSerialized
+inference/generic_methods_infer_generic_function_parameter_type2: ExpectationFileMismatchSerialized
+regress/issue_31181: ExpectationFileMismatchSerialized
+regress/issue_31213: ExpectationFileMismatchSerialized
+runtime_checks/contravariant_generic_return_tear_off: ExpectationFileMismatchSerialized
+
 general/abstract_members: TypeCheckError
 general/bug30695: TypeCheckError
 general/bug30695: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.strong.expect b/pkg/front_end/testcases/rasta/cascades.dart.strong.expect
index aac2bc0..6a7022b 100644
--- a/pkg/front_end/testcases/rasta/cascades.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/cascades.dart.strong.expect
@@ -13,5 +13,5 @@
   self::A* a = new self::A::•();
   function f(dynamic x) → dynamic
     return x;
-  let final self::A* #t1 = a in let final dynamic #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
+  let final self::A* #t1 = a in let final void #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
 }
diff --git a/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect
index aac2bc0..6a7022b 100644
--- a/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/cascades.dart.strong.transformed.expect
@@ -13,5 +13,5 @@
   self::A* a = new self::A::•();
   function f(dynamic x) → dynamic
     return x;
-  let final self::A* #t1 = a in let final dynamic #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
+  let final self::A* #t1 = a in let final void #t2 = #t1.{self::A::add}(f).call("WHAT") in #t1;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
index 6c371c1..896ebc5 100644
--- a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
@@ -13,5 +13,5 @@
 static method main() → dynamic {
   let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
   math..toString();
-  ^^^^" in let final dynamic #t2 = #t1.{dart.core::Object::toString}() in #t1;
+  ^^^^" in let final void #t2 = #t1.{dart.core::Object::toString}() in #t1;
 }
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
index 38593f7..896ebc5 100644
--- a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
@@ -7,12 +7,11 @@
 //   ^^^^
 //
 import self as self;
-import "dart:core" as core;
 
 import "dart:math" as math;
 
 static method main() → dynamic {
   let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
   math..toString();
-  ^^^^" in let final core::String* #t2 = #t1.{core::Object::toString}() in #t1;
+  ^^^^" in let final void #t2 = #t1.{dart.core::Object::toString}() in #t1;
 }
diff --git a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
index 932bc89..b4c142f 100644
--- a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
@@ -12,11 +12,11 @@
 //
 // pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]'.
 //     super[4] += 5;
-//          ^^
+//          ^
 //
 // pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
 //     super[4] += 5;
-//          ^^^
+//          ^
 //
 // pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:3: Error: 'on' isn't a type.
 //   on Exception catch (e) { }
@@ -53,7 +53,7 @@
     super.[]=(4, 42);
     let final core::int* #t1 = 4 in invalid-expression "pkg/front_end/testcases/rasta/unresolved_recovery.dart:8:10: Error: Superclass has no method named '[]='.
     super[4] += 5;
-         ^^^";
+         ^";
     return super.[](2);
   }
 }
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
index 34ce4a3b..20bc5b5 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.strong.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<unrelated T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
 static field <T extends core::Object* = dynamic>(T*) →* T* x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
index 34ce4a3b..20bc5b5 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.strong.transformed.expect
@@ -2,6 +2,6 @@
 import self as self;
 import "dart:core" as core;
 
-typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<unrelated T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
 static field <T extends core::Object* = dynamic>(T*) →* T* x;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
index c0f1dea..57ea785 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.expect
@@ -34,6 +34,6 @@
  - 'Type' is from 'dart:core'.
 Try correcting the name to the name of an existing method, or defining a method named '<'.
 type T = Map<A, B>
-            ^";
+            ^" as{TypeError} invalid-type;
 static field invalid-type B;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
index c0f1dea..57ea785 100644
--- a/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31188.dart.strong.transformed.expect
@@ -34,6 +34,6 @@
  - 'Type' is from 'dart:core'.
 Try correcting the name to the name of an existing method, or defining a method named '<'.
 type T = Map<A, B>
-            ^";
+            ^" as{TypeError} invalid-type;
 static field invalid-type B;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
index 69a285c..59e271c 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<contravariant K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
 static method producer<K extends core::Object* = dynamic>() → dynamic {
   return <A extends core::Object* = dynamic>(core::int* v1) → <B extends core::Object* = dynamic>(A*, self::producer::K*, B*) →* core::int* {
     return <B extends core::Object* = dynamic>(A* v2, self::producer::K* v3, B* v4) → core::int* => 0;
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
index 69a285c..59e271c 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<contravariant K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
 static method producer<K extends core::Object* = dynamic>() → dynamic {
   return <A extends core::Object* = dynamic>(core::int* v1) → <B extends core::Object* = dynamic>(A*, self::producer::K*, B*) →* core::int* {
     return <B extends core::Object* = dynamic>(A* v2, self::producer::K* v3, B* v4) → core::int* => 0;
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart b/pkg/front_end/testcases/regress/issue_39035.crash_dart
new file mode 100644
index 0000000..5329444
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart
@@ -0,0 +1,5 @@
+// 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.
+
+M("${)=
\ No newline at end of file
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect
new file mode 100644
index 0000000..efb076e
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect
@@ -0,0 +1,29 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Can't find '}' to match '${'.
+// M("${)=
+//    ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:6: Error: String starting with " must end with ".
+// M("${)=
+//      ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// M("${)=
+//   ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Expected ')' before this.
+// M("${)=
+//    ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:7: Error: Expected a function body or '=>'.
+// Try adding {}.
+// M("${)=
+//       ^
+//
+import self as self;
+
+static method M() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect
new file mode 100644
index 0000000..1a54007
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Can't find '}' to match '${'.
+// M("${)=
+//    ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:6: Error: String starting with " must end with ".
+// M("${)=
+//      ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// M("${)=
+//   ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Expected ')' before this.
+// M("${)=
+//    ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:7: Error: Expected a function body or '=>'.
+// Try adding {}.
+// M("${)=
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:8: Error: Expected ';' after this.
+// M("${)=
+//        ^...
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:8: Error: Unexpected token ''.
+// M("${)=
+//        ^...
+//
+import self as self;
+
+static method M() → dynamic
+  return "";
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect
new file mode 100644
index 0000000..1a54007
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect
@@ -0,0 +1,37 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Can't find '}' to match '${'.
+// M("${)=
+//    ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:6: Error: String starting with " must end with ".
+// M("${)=
+//      ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// M("${)=
+//   ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:4: Error: Expected ')' before this.
+// M("${)=
+//    ^^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:7: Error: Expected a function body or '=>'.
+// Try adding {}.
+// M("${)=
+//       ^
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:8: Error: Expected ';' after this.
+// M("${)=
+//        ^...
+//
+// pkg/front_end/testcases/regress/issue_39035.crash_dart:5:8: Error: Unexpected token ''.
+// M("${)=
+//        ^...
+//
+import self as self;
+
+static method M() → dynamic
+  return "";
diff --git a/pkg/front_end/testcases/regress/issue_39040.dart b/pkg/front_end/testcases/regress/issue_39040.dart
new file mode 100644
index 0000000..0232245
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39040.dart
@@ -0,0 +1,33 @@
+// 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.
+
+void main() {
+  List<String> whereWasI = [];
+  int outer = 1;
+  int inner = 0;
+  switch (outer) {
+    case 0:
+      whereWasI.add("outer 0");
+      break;
+    case 1:
+      () {
+        switch (inner) {
+          case 0:
+            whereWasI.add("inner 0");
+            continue fallThrough;
+          fallThrough:
+          case 1:
+            whereWasI.add("inner 1");
+        }
+      }();
+  }
+
+  if (whereWasI.length != 2 ||
+      whereWasI[0] != "inner 0" ||
+      whereWasI[1] != "inner 1") {
+    throw "Unexpected path.";
+  }
+
+  print(whereWasI);
+}
diff --git a/pkg/front_end/testcases/regress/issue_39040.dart.outline.expect b/pkg/front_end/testcases/regress/issue_39040.dart.outline.expect
new file mode 100644
index 0000000..2982c48
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39040.dart.outline.expect
@@ -0,0 +1,5 @@
+library;
+import self as self;
+
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_39040.dart.strong.expect b/pkg/front_end/testcases/regress/issue_39040.dart.strong.expect
new file mode 100644
index 0000000..828cbd5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39040.dart.strong.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+  core::List<core::String*>* whereWasI = <core::String*>[];
+  core::int* outer = 1;
+  core::int* inner = 0;
+  #L1:
+  switch(outer) {
+    #L2:
+    case #C1:
+      {
+        whereWasI.{core::List::add}("outer 0");
+        break #L1;
+      }
+    #L3:
+    case #C2:
+      {
+        (() → core::Null? {
+          switch(inner) {
+            #L4:
+            case #C1:
+              {
+                whereWasI.{core::List::add}("inner 0");
+                continue #L5;
+              }
+            #L5:
+            case #C2:
+              {
+                whereWasI.{core::List::add}("inner 1");
+              }
+          }
+        }).call();
+      }
+  }
+  if(!whereWasI.{core::List::length}.{core::num::==}(2) || !whereWasI.{core::List::[]}(0).{core::String::==}("inner 0") || !whereWasI.{core::List::[]}(1).{core::String::==}("inner 1")) {
+    throw "Unexpected path.";
+  }
+  core::print(whereWasI);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+}
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
new file mode 100644
index 0000000..828cbd5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39040.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+  core::List<core::String*>* whereWasI = <core::String*>[];
+  core::int* outer = 1;
+  core::int* inner = 0;
+  #L1:
+  switch(outer) {
+    #L2:
+    case #C1:
+      {
+        whereWasI.{core::List::add}("outer 0");
+        break #L1;
+      }
+    #L3:
+    case #C2:
+      {
+        (() → core::Null? {
+          switch(inner) {
+            #L4:
+            case #C1:
+              {
+                whereWasI.{core::List::add}("inner 0");
+                continue #L5;
+              }
+            #L5:
+            case #C2:
+              {
+                whereWasI.{core::List::add}("inner 1");
+              }
+          }
+        }).call();
+      }
+  }
+  if(!whereWasI.{core::List::length}.{core::num::==}(2) || !whereWasI.{core::List::[]}(0).{core::String::==}("inner 0") || !whereWasI.{core::List::[]}(1).{core::String::==}("inner 1")) {
+    throw "Unexpected path.";
+  }
+  core::print(whereWasI);
+}
+
+constants  {
+  #C1 = 0
+  #C2 = 1
+}
diff --git a/pkg/front_end/testcases/regress/issue_39091_1.dart b/pkg/front_end/testcases/regress/issue_39091_1.dart
new file mode 100644
index 0000000..8dc8ee1
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_1.dart
@@ -0,0 +1,5 @@
+// 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.
+
+hello
\ No newline at end of file
diff --git a/pkg/front_end/testcases/regress/issue_39091_1.dart.outline.expect b/pkg/front_end/testcases/regress/issue_39091_1.dart.outline.expect
new file mode 100644
index 0000000..c414477
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_1.dart.outline.expect
@@ -0,0 +1,16 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// hello
+// ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Expected ';' after this.
+// hello
+// ^^^^^
+//
+import self as self;
+
+static field dynamic hello;
diff --git a/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.expect b/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.expect
new file mode 100644
index 0000000..c414477
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.expect
@@ -0,0 +1,16 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// hello
+// ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Expected ';' after this.
+// hello
+// ^^^^^
+//
+import self as self;
+
+static field dynamic hello;
diff --git a/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.transformed.expect
new file mode 100644
index 0000000..c414477
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_1.dart.strong.transformed.expect
@@ -0,0 +1,16 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
+// Try adding the name of the type of the variable or the keyword 'var'.
+// hello
+// ^^^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_1.dart:5:1: Error: Expected ';' after this.
+// hello
+// ^^^^^
+//
+import self as self;
+
+static field dynamic hello;
diff --git a/pkg/front_end/testcases/regress/issue_39091_2.dart b/pkg/front_end/testcases/regress/issue_39091_2.dart
new file mode 100644
index 0000000..c401750
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_2.dart
@@ -0,0 +1,13 @@
+// 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() {
+"";  /*æøå*/ "";
+"";
+"";
+"A";
+"";
+"";/*æ*/ hello; /*æ*/
+}
+"";
diff --git a/pkg/front_end/testcases/regress/issue_39091_2.dart.outline.expect b/pkg/front_end/testcases/regress/issue_39091_2.dart.outline.expect
new file mode 100644
index 0000000..cd485bd
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_2.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:1: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:2: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:1: Error: Expected a declaration, but got '""'.
+// "";
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:4: Error: Unexpected token ';'.
+// "";
+//    ^
+//
+import self as self;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.expect b/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.expect
new file mode 100644
index 0000000..6db31c6
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.expect
@@ -0,0 +1,38 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:1: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:2: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:1: Error: Expected a declaration, but got '""'.
+// "";
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:4: Error: Unexpected token ';'.
+// "";
+//    ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:11:11: Error: Getter not found: 'hello'.
+// "";/*æ*/ hello; /*æ*/
+//           ^^^^^
+//
+import self as self;
+
+static method main() → dynamic {
+  "\u65279";
+  "\u65279";
+  "\u65279";
+  "\u65279";
+  "A";
+  "\u65279";
+  "\u65279";
+  invalid-expression "pkg/front_end/testcases/regress/issue_39091_2.dart:11:11: Error: Getter not found: 'hello'.
+\"\u65279\";/*\u0230*/ hello; /*\u0230*/
+          ^^^^^";
+}
diff --git a/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..6db31c6
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_39091_2.dart.strong.transformed.expect
@@ -0,0 +1,38 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:1: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:1:2: Error: The non-ASCII space character U+FEFF can only be used in strings and comments.
+// // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+//  ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:1: Error: Expected a declaration, but got '""'.
+// "";
+// ^^^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:13:4: Error: Unexpected token ';'.
+// "";
+//    ^
+//
+// pkg/front_end/testcases/regress/issue_39091_2.dart:11:11: Error: Getter not found: 'hello'.
+// "";/*æ*/ hello; /*æ*/
+//           ^^^^^
+//
+import self as self;
+
+static method main() → dynamic {
+  "\u65279";
+  "\u65279";
+  "\u65279";
+  "\u65279";
+  "A";
+  "\u65279";
+  "\u65279";
+  invalid-expression "pkg/front_end/testcases/regress/issue_39091_2.dart:11:11: Error: Getter not found: 'hello'.
+\"\u65279\";/*\u0230*/ hello; /*\u0230*/
+          ^^^^^";
+}
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
index b6cfaea..c0b0076 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic> = () →* (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void _x;
   constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
index b6cfaea..c0b0076 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic> = () →* (T*) →* void;
 class C<T extends core::Object* = dynamic> extends core::Object {
   field (self::C::T*) →* void _x;
   constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect
index d3b1e07..8060719 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.expect
@@ -2,12 +2,12 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
 //   c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                      ^
 //
-// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
 //   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                              ^
@@ -42,11 +42,11 @@
   set x(self::B<(self::C::T*) →* void>* value) → void {}
 }
 static method test(self::C<core::num*>* c) → void {
-  let final self::C<core::num*>* #t1 = c in #t1.{self::C::x} = (#t1.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+  let final self::C<core::num*>* #t1 = c in #t1.{self::C::x} = (#t1.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
   c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                      ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
-  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t3 = c in #t3.{self::C::x} = (#t3.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t3 = c in #t3.{self::C::x} = (#t3.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                              ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.transformed.expect
index d3b1e07..8060719 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart.strong.transformed.expect
@@ -2,12 +2,12 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
 //   c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                      ^
 //
-// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+// pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
 //  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
 //   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
 //                                                              ^
@@ -42,11 +42,11 @@
   set x(self::B<(self::C::T*) →* void>* value) → void {}
 }
 static method test(self::C<core::num*>* c) → void {
-  let final self::C<core::num*>* #t1 = c in #t1.{self::C::x} = (#t1.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+  let final self::C<core::num*>* #t1 = c in #t1.{self::C::x} = (#t1.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:20:54: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
   c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                      ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
-  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t3 = c in #t3.{self::C::x} = (#t3.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: The argument type 'B<num>' can't be assigned to the parameter type 'B<void Function(num)>'.
+  self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t3 = c in #t3.{self::C::x} = (#t3.{self::C::x} as{TypeError} self::B<(core::num*) →* void>*).{self::B::+}(let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart:21:62: Error: A value of type 'B<num>' can't be assigned to a variable of type 'B<void Function(num)>'.
  - 'B' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_getter_return_compound_assign.dart'.
   var y = c. /*@ checkReturn=B<(num*) ->* void>* */ x += new B<num>();
                                                              ^" in new self::B::•<core::num*>() as{TypeError} self::B<(core::num*) →* void>*);
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 34ef1fc..a78d1d1 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -34,13 +34,15 @@
 general/error_locations/error_location_06: RuntimeError
 general/expressions: RuntimeError
 general/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
-general/fallthrough: ExpectationFileMismatch
 general/ignore_function: TypeCheckError
 general/incomplete_field_formal_parameter: RuntimeError
 general/invalid_type: TypeCheckError
 general/invocations: RuntimeError
 general/issue34899: TypeCheckError
 general/issue37776: RuntimeError
+general/issue38938: RuntimeError # no main and compile time errors.
+general/issue38944: RuntimeError # no main and compile time errors.
+general/issue38961: RuntimeError # no main and compile time errors.
 general/micro: RuntimeError
 general/mixin_application_override: ExpectationFileMismatch # Too many errors.
 general/mixin_application_override: TypeCheckError
@@ -57,11 +59,11 @@
 general/reject_generic_function_types_in_bounds: RuntimeError # Expected
 general/spread_collection: RuntimeError
 general/statements: Crash
-general/type_variable_bound_access: TypeCheckError
 general/type_parameter_type_named_int: RuntimeError # Expected
 general/type_variable_as_super: RuntimeError
+general/type_variable_bound_access: TypeCheckError
 general/unsound_promotion: RuntimeError
-general/void_methods: ExpectationFileMismatch
+general/void_methods: RuntimeError
 general/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
 inference/conflicting_fields: TypeCheckError
@@ -173,6 +175,9 @@
 regress/issue_36647_2: RuntimeError # Expected
 regress/issue_36669: RuntimeError
 regress/issue_37285: RuntimeError
+regress/issue_39035.crash: RuntimeError
+regress/issue_39091_1: RuntimeError
+regress/issue_39091_2: 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
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index d617f89..681bed8 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -10,6 +10,7 @@
 expression/eval: TextSerializationFailure # Was: Pass
 expression/main: TextSerializationFailure # Was: Pass
 extensions/annotations: TextSerializationFailure
+extensions/builtin_identifiers: TextSerializationFailure
 extensions/check_bounds: TextSerializationFailure
 extensions/compounds: TextSerializationFailure
 extensions/conflict_with_object: TextSerializationFailure
@@ -23,6 +24,7 @@
 extensions/explicit_generic_extension_access: TextSerializationFailure
 extensions/explicit_invalid_access: TextSerializationFailure
 extensions/explicit_this: TextSerializationFailure
+extensions/export_twice: TextSerializationFailure
 extensions/extension_call: TextSerializationFailure
 extensions/extension_constructor: TextSerializationFailure
 extensions/extension_methods: TextSerializationFailure
@@ -48,6 +50,7 @@
 extensions/issue38750: TextSerializationFailure
 extensions/issue38755: TextSerializationFailure
 extensions/issue38915: TextSerializationFailure
+extensions/missing_toplevel: TextSerializationFailure
 extensions/nested_on_types: TextSerializationFailure
 extensions/null_aware: TextSerializationFailure
 extensions/on_function_type: TextSerializationFailure
@@ -77,6 +80,7 @@
 general/argument_mismatch: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 general/arithmetic: TextSerializationFailure # Was: Pass
 general/arrow_function: TextSerializationFailure # Was: Pass
+general/assign_to_initializing_formal: TextSerializationFailure
 general/async_function: TextSerializationFailure # Was: Pass
 general/async_nested: TextSerializationFailure # Was: Pass
 general/await: TextSerializationFailure # Was: Pass
@@ -159,7 +163,7 @@
 general/expressions: TextSerializationFailure # Was: RuntimeError
 general/external: TextSerializationFailure # Was: Pass
 general/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
-general/fallthrough: ExpectationFileMismatch
+general/fallthrough: TextSerializationFailure
 general/fibonacci: TextSerializationFailure # Was: Pass
 general/for_in_scope: TextSerializationFailure # Was: Pass
 general/for_in_without_declaration: TextSerializationFailure
@@ -175,6 +179,9 @@
 general/having_part_with_part_and_annotation: TextSerializationFailure
 general/having_part_with_parts_and_annotation: TextSerializationFailure
 general/hello: TextSerializationFailure # Was: Pass
+general/if_null_in_cascade: TextSerializationFailure
+general/if_null_in_list_literal: TextSerializationFailure
+general/if_null_in_set_literal: TextSerializationFailure
 general/ignore_function: TypeCheckError
 general/illegal_named_function_expression: TextSerializationFailure # Was: Pass
 general/illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
@@ -198,8 +205,13 @@
 general/issue37381: TextSerializationFailure
 general/issue37776: TextSerializationFailure
 general/issue38812: TextSerializationFailure
+general/issue38938: TextSerializationFailure
+general/issue38943: TextSerializationFailure
+general/issue38944: TextSerializationFailure
+general/issue38961: TextSerializationFailure
 general/literals: TextSerializationFailure # Was: Pass
 general/local_generic_function: TextSerializationFailure # Was: Pass
+general/long_chain_of_typedefs: TextSerializationFailure
 general/magic_const: TextSerializationFailure # Was: Pass
 general/many_errors: TextSerializationFailure
 general/map: TextSerializationFailure # Was: Pass
@@ -208,6 +220,7 @@
 general/micro: TextSerializationFailure # Was: RuntimeError
 general/minimum_int: TextSerializationFailure # Was: Pass
 general/missing_constructor: TextSerializationFailure # Was: Pass
+general/missing_toplevel: TextSerializationFailure
 general/mixin: TextSerializationFailure # Was: Pass
 general/mixin_application_override: ExpectationFileMismatch
 general/mixin_application_override: TypeCheckError
@@ -285,9 +298,11 @@
 general/super_call: TextSerializationFailure # Was: Pass
 general/super_nsm: TextSerializationFailure # Was: Pass
 general/tabs: TextSerializationFailure # Was: Pass
+general/three_typedefs_loop: TextSerializationFailure
 general/top_level_accessors: TextSerializationFailure # Was: Pass
 general/top_level_accessors_part: TextSerializationFailure # Was: Pass
 general/top_level_library_method: TextSerializationFailure # Was: Pass
+general/type_literal_as_metadata: TextSerializationFailure
 general/type_of_null: TextSerializationFailure
 general/type_parameter_type_named_int: TextSerializationFailure
 general/type_variable_as_super: TextSerializationFailure # Was: RuntimeError
@@ -301,7 +316,7 @@
 general/unsound_promotion: TextSerializationFailure
 general/unused_methods: TextSerializationFailure # Was: Pass
 general/var_as_type_name: TextSerializationFailure # Was: Pass
-general/void_methods: ExpectationFileMismatch
+general/void_methods: TextSerializationFailure
 general/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
 inference/assert: TextSerializationFailure # Was: Pass
@@ -876,9 +891,13 @@
 nnbd/intersection_types: TextSerializationFailure
 nnbd/late: TextSerializationFailure
 nnbd/null_check: TextSerializationFailure
+nnbd/null_shorting: TextSerializationFailure
+nnbd/null_shorting_explicit_extension: TextSerializationFailure
+nnbd/null_shorting_extension: TextSerializationFailure
 nnbd/nullable_null: TextSerializationFailure
 nnbd/nullable_param: TextSerializationFailure
 nnbd/required: TextSerializationFailure
+nnbd/simple_never: TextSerializationFailure
 nnbd/substitution_in_inference: TextSerializationFailure
 nnbd/type_parameter_types: TextSerializationFailure
 no_such_method_forwarders/abstract_accessors_from_field: TextSerializationFailure # Was: Pass
@@ -1066,6 +1085,10 @@
 regress/issue_36793: TextSerializationFailure
 regress/issue_37285: TextSerializationFailure
 regress/issue_37681: TextSerializationFailure
+regress/issue_39035.crash: TextSerializationFailure
+regress/issue_39040: TextSerializationFailure
+regress/issue_39091_1: RuntimeError
+regress/issue_39091_2: TextSerializationFailure
 runtime_checks/call_kinds: TextSerializationFailure # Was: Pass
 runtime_checks/call_kinds_get: TextSerializationFailure # Was: Pass
 runtime_checks/call_kinds_set: TextSerializationFailure # Was: Pass
@@ -1140,5 +1163,6 @@
 runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
 set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
 top_level_variance_test: TextSerializationFailure
+unified_collections/mixed_entries: TextSerializationFailure
 variance/class_type_parameter_modifier: TextSerializationFailure
 variance/mixin_type_parameter_modifier: TextSerializationFailure
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart b/pkg/front_end/testcases/unified_collections/mixed_entries.dart
new file mode 100644
index 0000000..55810a0
--- /dev/null
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart
@@ -0,0 +1,53 @@
+// 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.
+
+bool b = false;
+
+var list = [];
+
+var map0 = {};
+var map1 = {if (b) 0: 1 else ...map0};
+var map2 = {if (b) ...map0 else 0: 1};
+var map3 = {if (b) ...map0 else ...map0};
+var map4 = {if (b) 0: 1 else for (var a in list) a: 1};
+var map5 = {if (b) for (var a in list) a: 1 else 0: 1};
+var map6 = {
+  if (b) 0: 1 else for (var a in list) ...{a: 1}
+};
+var map7 = {
+  if (b) for (var a in list) ...{a: 1} else 0: 1
+};
+var map8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]: 1};
+var map9 = {if (b) for (var i = 0; i < list.length; i++) list[i]: 1 else 0: 1};
+var map10 = {
+  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]: 1}
+};
+var map11 = {
+  if (b) for (var i = 0; i < list.length; i++) ...{list[i]: 1} else 0: 1
+};
+var map12 = {
+  if (b) 0: 1 else if (b) ...{0: 1}
+};
+
+var error4 = {if (b) 0: 1 else for (var a in list) a};
+var error5 = {if (b) for (var a in list) a else 0: 1};
+var error6 = {
+  if (b) 0: 1 else for (var a in list) ...{a}
+};
+var error7 = {
+  if (b) for (var a in list) ...{a} else 0: 1
+};
+var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+var error10 = {
+  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]}
+};
+var error11 = {
+  if (b) for (var i = 0; i < list.length; i++) ...{list[i]} else 0: 1
+};
+var error12 = {
+  if (b) 0: 1 else if (b) ...{0}
+};
+
+main() {}
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.outline.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.outline.expect
new file mode 100644
index 0000000..3d8af13
--- /dev/null
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.outline.expect
@@ -0,0 +1,49 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error4 = {if (b) 0: 1 else for (var a in list) a};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error5 = {if (b) for (var a in list) a else 0: 1};
+//                      ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+//                      ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field core::bool* b;
+static field core::List<dynamic>* list;
+static field core::Map<dynamic, dynamic>* map0;
+static field core::Map<dynamic, dynamic>* map1;
+static field core::Map<dynamic, dynamic>* map2;
+static field core::Map<dynamic, dynamic>* map3;
+static field core::Map<dynamic, core::int*>* map4;
+static field core::Map<dynamic, core::int*>* map5;
+static field core::Map<dynamic, core::int*>* map6;
+static field core::Map<dynamic, core::int*>* map7;
+static field core::Map<dynamic, core::int*>* map8;
+static field core::Map<dynamic, core::int*>* map9;
+static field core::Map<dynamic, core::int*>* map10;
+static field core::Map<dynamic, core::int*>* map11;
+static field core::Map<core::int*, core::int*>* map12;
+static field core::Map<dynamic, core::Null?>* error4;
+static field core::Map<dynamic, core::Null?>* error5;
+static field dynamic error6;
+static field dynamic error7;
+static field core::Map<dynamic, core::Null?>* error8;
+static field core::Map<dynamic, core::Null?>* error9;
+static field dynamic error10;
+static field dynamic error11;
+static field dynamic error12;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.expect
new file mode 100644
index 0000000..6852242
--- /dev/null
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.expect
@@ -0,0 +1,176 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error4 = {if (b) 0: 1 else for (var a in list) a};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error5 = {if (b) for (var a in list) a else 0: 1};
+//                      ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+//                      ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:35:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error6 = {
+//              ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:38:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error7 = {
+//              ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:43:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error10 = {
+//               ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:46:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error11 = {
+//               ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:49:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error12 = {
+//               ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field core::bool* b = false;
+static field core::List<dynamic>* list = <dynamic>[];
+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>{};
+  if(self::b)
+    #t1.{core::Map::[]=}(0, 1);
+  else
+    for (final core::MapEntry<dynamic, dynamic>* #t2 in self::map0.{core::Map::entries})
+      #t1.{core::Map::[]=}(#t2.{core::MapEntry::key}, #t2.{core::MapEntry::value});
+} =>#t1;
+static field core::Map<dynamic, dynamic>* map2 = block {
+  final core::Map<dynamic, dynamic>* #t3 = <dynamic, dynamic>{};
+  if(self::b)
+    for (final core::MapEntry<dynamic, dynamic>* #t4 in self::map0.{core::Map::entries})
+      #t3.{core::Map::[]=}(#t4.{core::MapEntry::key}, #t4.{core::MapEntry::value});
+  else
+    #t3.{core::Map::[]=}(0, 1);
+} =>#t3;
+static field core::Map<dynamic, dynamic>* map3 = block {
+  final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
+  if(self::b)
+    for (final core::MapEntry<dynamic, dynamic>* #t6 in self::map0.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+  else
+    for (final core::MapEntry<dynamic, dynamic>* #t7 in self::map0.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t7.{core::MapEntry::key}, #t7.{core::MapEntry::value});
+} =>#t5;
+static field core::Map<dynamic, core::int*>* map4 = block {
+  final core::Map<dynamic, core::int*>* #t8 = <dynamic, core::int*>{};
+  if(self::b)
+    #t8.{core::Map::[]=}(0, 1);
+  else
+    for (dynamic a in self::list)
+      #t8.{core::Map::[]=}(a, 1);
+} =>#t8;
+static field core::Map<dynamic, core::int*>* map5 = block {
+  final core::Map<dynamic, core::int*>* #t9 = <dynamic, core::int*>{};
+  if(self::b)
+    for (dynamic a in self::list)
+      #t9.{core::Map::[]=}(a, 1);
+  else
+    #t9.{core::Map::[]=}(0, 1);
+} =>#t9;
+static field core::Map<dynamic, core::int*>* map6 = block {
+  final core::Map<dynamic, core::int*>* #t10 = <dynamic, core::int*>{};
+  if(self::b)
+    #t10.{core::Map::[]=}(0, 1);
+  else
+    for (dynamic a in self::list)
+      for (final core::MapEntry<dynamic, core::int*>* #t11 in <dynamic, core::int*>{a: 1}.{core::Map::entries})
+        #t10.{core::Map::[]=}(#t11.{core::MapEntry::key}, #t11.{core::MapEntry::value});
+} =>#t10;
+static field core::Map<dynamic, core::int*>* map7 = block {
+  final core::Map<dynamic, core::int*>* #t12 = <dynamic, core::int*>{};
+  if(self::b)
+    for (dynamic a in self::list)
+      for (final core::MapEntry<dynamic, core::int*>* #t13 in <dynamic, core::int*>{a: 1}.{core::Map::entries})
+        #t12.{core::Map::[]=}(#t13.{core::MapEntry::key}, #t13.{core::MapEntry::value});
+  else
+    #t12.{core::Map::[]=}(0, 1);
+} =>#t12;
+static field core::Map<dynamic, core::int*>* map8 = block {
+  final core::Map<dynamic, core::int*>* #t14 = <dynamic, core::int*>{};
+  if(self::b)
+    #t14.{core::Map::[]=}(0, 1);
+  else
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      #t14.{core::Map::[]=}(self::list.{core::List::[]}(i), 1);
+} =>#t14;
+static field core::Map<dynamic, core::int*>* map9 = block {
+  final core::Map<dynamic, core::int*>* #t15 = <dynamic, core::int*>{};
+  if(self::b)
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      #t15.{core::Map::[]=}(self::list.{core::List::[]}(i), 1);
+  else
+    #t15.{core::Map::[]=}(0, 1);
+} =>#t15;
+static field core::Map<dynamic, core::int*>* map10 = block {
+  final core::Map<dynamic, core::int*>* #t16 = <dynamic, core::int*>{};
+  if(self::b)
+    #t16.{core::Map::[]=}(0, 1);
+  else
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      for (final core::MapEntry<dynamic, core::int*>* #t17 in <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries})
+        #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
+} =>#t16;
+static field core::Map<dynamic, core::int*>* map11 = block {
+  final core::Map<dynamic, core::int*>* #t18 = <dynamic, core::int*>{};
+  if(self::b)
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      for (final core::MapEntry<dynamic, core::int*>* #t19 in <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries})
+        #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
+  else
+    #t18.{core::Map::[]=}(0, 1);
+} =>#t18;
+static field core::Map<core::int*, core::int*>* map12 = block {
+  final core::Map<core::int*, core::int*>* #t20 = <core::int*, core::int*>{};
+  if(self::b)
+    #t20.{core::Map::[]=}(0, 1);
+  else
+    if(self::b)
+      for (final core::MapEntry<core::int*, core::int*>* #t21 in <core::int*, core::int*>{0: 1}.{core::Map::entries})
+        #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
+} =>#t20;
+static field core::Map<dynamic, core::Null?>* error4 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error4 = {if (b) 0: 1 else for (var a in list) a};
+                               ^": null};
+static field core::Map<dynamic, core::Null?>* error5 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error5 = {if (b) for (var a in list) a else 0: 1};
+                     ^": null};
+static field dynamic error6 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:35:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error6 = {
+             ^";
+static field dynamic error7 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:38:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error7 = {
+             ^";
+static field core::Map<dynamic, core::Null?>* error8 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+                               ^": null};
+static field core::Map<dynamic, core::Null?>* error9 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+                     ^": null};
+static field dynamic error10 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:43:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error10 = {
+              ^";
+static field dynamic error11 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:46:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error11 = {
+              ^";
+static field dynamic error12 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:49:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error12 = {
+              ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect
new file mode 100644
index 0000000..6852242
--- /dev/null
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.strong.transformed.expect
@@ -0,0 +1,176 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error4 = {if (b) 0: 1 else for (var a in list) a};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error5 = {if (b) for (var a in list) a else 0: 1};
+//                      ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+//                                ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+//                      ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:35:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error6 = {
+//              ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:38:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error7 = {
+//              ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:43:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error10 = {
+//               ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:46:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error11 = {
+//               ^
+//
+// pkg/front_end/testcases/unified_collections/mixed_entries.dart:49:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// var error12 = {
+//               ^
+//
+import self as self;
+import "dart:core" as core;
+
+static field core::bool* b = false;
+static field core::List<dynamic>* list = <dynamic>[];
+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>{};
+  if(self::b)
+    #t1.{core::Map::[]=}(0, 1);
+  else
+    for (final core::MapEntry<dynamic, dynamic>* #t2 in self::map0.{core::Map::entries})
+      #t1.{core::Map::[]=}(#t2.{core::MapEntry::key}, #t2.{core::MapEntry::value});
+} =>#t1;
+static field core::Map<dynamic, dynamic>* map2 = block {
+  final core::Map<dynamic, dynamic>* #t3 = <dynamic, dynamic>{};
+  if(self::b)
+    for (final core::MapEntry<dynamic, dynamic>* #t4 in self::map0.{core::Map::entries})
+      #t3.{core::Map::[]=}(#t4.{core::MapEntry::key}, #t4.{core::MapEntry::value});
+  else
+    #t3.{core::Map::[]=}(0, 1);
+} =>#t3;
+static field core::Map<dynamic, dynamic>* map3 = block {
+  final core::Map<dynamic, dynamic>* #t5 = <dynamic, dynamic>{};
+  if(self::b)
+    for (final core::MapEntry<dynamic, dynamic>* #t6 in self::map0.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t6.{core::MapEntry::key}, #t6.{core::MapEntry::value});
+  else
+    for (final core::MapEntry<dynamic, dynamic>* #t7 in self::map0.{core::Map::entries})
+      #t5.{core::Map::[]=}(#t7.{core::MapEntry::key}, #t7.{core::MapEntry::value});
+} =>#t5;
+static field core::Map<dynamic, core::int*>* map4 = block {
+  final core::Map<dynamic, core::int*>* #t8 = <dynamic, core::int*>{};
+  if(self::b)
+    #t8.{core::Map::[]=}(0, 1);
+  else
+    for (dynamic a in self::list)
+      #t8.{core::Map::[]=}(a, 1);
+} =>#t8;
+static field core::Map<dynamic, core::int*>* map5 = block {
+  final core::Map<dynamic, core::int*>* #t9 = <dynamic, core::int*>{};
+  if(self::b)
+    for (dynamic a in self::list)
+      #t9.{core::Map::[]=}(a, 1);
+  else
+    #t9.{core::Map::[]=}(0, 1);
+} =>#t9;
+static field core::Map<dynamic, core::int*>* map6 = block {
+  final core::Map<dynamic, core::int*>* #t10 = <dynamic, core::int*>{};
+  if(self::b)
+    #t10.{core::Map::[]=}(0, 1);
+  else
+    for (dynamic a in self::list)
+      for (final core::MapEntry<dynamic, core::int*>* #t11 in <dynamic, core::int*>{a: 1}.{core::Map::entries})
+        #t10.{core::Map::[]=}(#t11.{core::MapEntry::key}, #t11.{core::MapEntry::value});
+} =>#t10;
+static field core::Map<dynamic, core::int*>* map7 = block {
+  final core::Map<dynamic, core::int*>* #t12 = <dynamic, core::int*>{};
+  if(self::b)
+    for (dynamic a in self::list)
+      for (final core::MapEntry<dynamic, core::int*>* #t13 in <dynamic, core::int*>{a: 1}.{core::Map::entries})
+        #t12.{core::Map::[]=}(#t13.{core::MapEntry::key}, #t13.{core::MapEntry::value});
+  else
+    #t12.{core::Map::[]=}(0, 1);
+} =>#t12;
+static field core::Map<dynamic, core::int*>* map8 = block {
+  final core::Map<dynamic, core::int*>* #t14 = <dynamic, core::int*>{};
+  if(self::b)
+    #t14.{core::Map::[]=}(0, 1);
+  else
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      #t14.{core::Map::[]=}(self::list.{core::List::[]}(i), 1);
+} =>#t14;
+static field core::Map<dynamic, core::int*>* map9 = block {
+  final core::Map<dynamic, core::int*>* #t15 = <dynamic, core::int*>{};
+  if(self::b)
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      #t15.{core::Map::[]=}(self::list.{core::List::[]}(i), 1);
+  else
+    #t15.{core::Map::[]=}(0, 1);
+} =>#t15;
+static field core::Map<dynamic, core::int*>* map10 = block {
+  final core::Map<dynamic, core::int*>* #t16 = <dynamic, core::int*>{};
+  if(self::b)
+    #t16.{core::Map::[]=}(0, 1);
+  else
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      for (final core::MapEntry<dynamic, core::int*>* #t17 in <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries})
+        #t16.{core::Map::[]=}(#t17.{core::MapEntry::key}, #t17.{core::MapEntry::value});
+} =>#t16;
+static field core::Map<dynamic, core::int*>* map11 = block {
+  final core::Map<dynamic, core::int*>* #t18 = <dynamic, core::int*>{};
+  if(self::b)
+    for (core::int* i = 0; i.{core::num::<}(self::list.{core::List::length}); i = i.{core::num::+}(1))
+      for (final core::MapEntry<dynamic, core::int*>* #t19 in <dynamic, core::int*>{self::list.{core::List::[]}(i): 1}.{core::Map::entries})
+        #t18.{core::Map::[]=}(#t19.{core::MapEntry::key}, #t19.{core::MapEntry::value});
+  else
+    #t18.{core::Map::[]=}(0, 1);
+} =>#t18;
+static field core::Map<core::int*, core::int*>* map12 = block {
+  final core::Map<core::int*, core::int*>* #t20 = <core::int*, core::int*>{};
+  if(self::b)
+    #t20.{core::Map::[]=}(0, 1);
+  else
+    if(self::b)
+      for (final core::MapEntry<core::int*, core::int*>* #t21 in <core::int*, core::int*>{0: 1}.{core::Map::entries})
+        #t20.{core::Map::[]=}(#t21.{core::MapEntry::key}, #t21.{core::MapEntry::value});
+} =>#t20;
+static field core::Map<dynamic, core::Null?>* error4 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error4 = {if (b) 0: 1 else for (var a in list) a};
+                               ^": null};
+static field core::Map<dynamic, core::Null?>* error5 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error5 = {if (b) for (var a in list) a else 0: 1};
+                     ^": null};
+static field dynamic error6 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:35:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error6 = {
+             ^";
+static field dynamic error7 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:38:14: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error7 = {
+             ^";
+static field core::Map<dynamic, core::Null?>* error8 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+                               ^": null};
+static field core::Map<dynamic, core::Null?>* error9 = <dynamic, core::Null?>{invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+                     ^": null};
+static field dynamic error10 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:43:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error10 = {
+              ^";
+static field dynamic error11 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:46:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error11 = {
+              ^";
+static field dynamic error12 = invalid-expression "pkg/front_end/testcases/unified_collections/mixed_entries.dart:49:15: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+var error12 = {
+              ^";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect
new file mode 100644
index 0000000..f87b142
--- /dev/null
+++ b/pkg/front_end/testcases/unified_collections/mixed_entries.dart.type_promotion.expect
@@ -0,0 +1,24 @@
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:21:64: Context: Write to i@665
+var map8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]: 1};
+                                                               ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:22:54: Context: Write to i@665
+var map9 = {if (b) for (var i = 0; i < list.length; i++) list[i]: 1 else 0: 1};
+                                                     ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:24:54: Context: Write to i@665
+  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]: 1}
+                                                     ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:27:44: Context: Write to i@665
+  if (b) for (var i = 0; i < list.length; i++) ...{list[i]: 1} else 0: 1
+                                           ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:66: Context: Write to i@665
+var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
+                                                                 ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:56: Context: Write to i@665
+var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
+                                                       ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:44:54: Context: Write to i@665
+  if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]}
+                                                     ^^
+pkg/front_end/testcases/unified_collections/mixed_entries.dart:47:44: Context: Write to i@665
+  if (b) for (var i = 0; i < list.length; i++) ...{list[i]} else 0: 1
+                                           ^^
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 5d80908..73550ac 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -7,7 +7,7 @@
     {
       "name": "messages",
       "kind": "Chain",
-      "source": "test/fasta/messages_test.dart",
+      "source": "test/fasta/messages_suite.dart",
       "path": "./",
       "status": "messages.status",
       "pattern": [],
@@ -45,11 +45,12 @@
     {
       "name": "outline",
       "kind": "Chain",
-      "source": "test/fasta/outline_test.dart",
+      "source": "test/fasta/outline_suite.dart",
       "path": "testcases/",
       "status": "testcases/outline.status",
       "pattern": [
-        "\\.dart$"
+        "\\.dart$",
+        "\\.crash_dart$"
       ],
       "exclude": [
         "/testcases/.*_part[0-9]*\\.dart$",
@@ -66,7 +67,26 @@
       "path": "testcases/",
       "status": "testcases/strong.status",
       "pattern": [
-        "\\.dart$"
+        "\\.dart$",
+        "\\.crash_dart$"
+      ],
+      "exclude": [
+        "/testcases/.*_part[0-9]*\\.dart$",
+        "/testcases/.*_lib[0-9]*\\.dart$",
+        "/testcases/dartino/",
+        "/testcases/shaker/",
+        "/testcases/expression/"
+      ]
+    },
+    {
+      "name": "fast_strong",
+      "kind": "Chain",
+      "source": "test/fasta/fast_strong_suite.dart",
+      "path": "testcases/",
+      "status": "testcases/strong.status",
+      "pattern": [
+        "\\.dart$",
+        "\\.crash_dart$"
       ],
       "exclude": [
         "/testcases/.*_part[0-9]*\\.dart$",
@@ -79,11 +99,12 @@
     {
       "name": "text_serialization",
       "kind": "Chain",
-      "source": "test/fasta/text_serialization_test.dart",
+      "source": "test/fasta/text_serialization_suite.dart",
       "path": "testcases/",
       "status": "testcases/text_serialization.status",
       "pattern": [
-        "\\.dart$"
+        "\\.dart$",
+        "\\.crash_dart$"
       ],
       "exclude": [
         "/testcases/.*_part[0-9]*\\.dart$",
@@ -96,7 +117,7 @@
     {
       "name": "incremental",
       "kind": "Chain",
-      "source": "test/fasta/incremental_test.dart",
+      "source": "test/fasta/incremental_suite.dart",
       "path": "testcases/",
       "status": "testcases/incremental.status",
       "pattern": [
@@ -107,7 +128,7 @@
     {
       "name": "expression",
       "kind": "Chain",
-      "source": "test/fasta/expression_test.dart",
+      "source": "test/fasta/expression_suite.dart",
       "path": "testcases/expression/",
       "status": "testcases/expression.status",
       "pattern": [
@@ -118,7 +139,7 @@
     {
       "name": "incremental_load_from_dill",
       "kind": "Chain",
-      "source": "test/incremental_load_from_dill_test.dart",
+      "source": "test/incremental_load_from_dill_suite.dart",
       "path": "testcases/incremental_initialize_from_dill/",
       "status": "testcases/incremental_initialize_from_dill/status.status",
       "pattern": [
@@ -129,7 +150,7 @@
     {
       "name": "incremental_bulk_compiler_smoke",
       "kind": "Chain",
-      "source": "test/incremental_bulk_compiler_smoke_test.dart",
+      "source": "test/incremental_bulk_compiler_smoke_suite.dart",
       "path": "../../tests/",
       "status": "testcases/incremental_bulk_compiler_smoke.status",
       "pattern": [
@@ -168,8 +189,8 @@
     {
       "name": "old_dill_test",
       "kind": "Chain",
-      "source": "test/old_dill_test.dart",
-      "path": "testcases/old_dills/",
+      "source": "test/old_dill_suite.dart",
+      "path": "testcases/old_dills/dills/",
       "status": "testcases/old_dills/old_dills.status",
       "pattern": [
         ".*\\.dill$"
@@ -179,18 +200,19 @@
     {
       "name": "parser_test",
       "kind": "Chain",
-      "source": "test/parser_test.dart",
+      "source": "test/parser_suite.dart",
       "path": "parser_testcases/",
       "status": "parser_testcases/parser.status",
       "pattern": [
-        "\\.dart$"
+        "\\.dart$",
+        "\\.crash_dart$"
       ],
       "exclude": []
     },
     {
       "name": "lint_test",
       "kind": "Chain",
-      "source": "test/lint_test.dart",
+      "source": "test/lint_suite.dart",
       "path": "lib/",
       "status": "test/lint_test.status",
       "pattern": [
@@ -203,7 +225,7 @@
     {
       "name": "spelling_test_src_test",
       "kind": "Chain",
-      "source": "test/spelling_test_src_test.dart",
+      "source": "test/spelling_test_src_suite.dart",
       "path": "../",
       "status": "test/spelling_test.status",
       "pattern": [
@@ -211,13 +233,14 @@
         "kernel/lib/.*\\.dart$"
       ],
       "exclude": [
-        "src/fasta/fasta_codes_generated\\.dart$"
+        "src/fasta/fasta_codes_generated\\.dart$",
+        "src/fasta/fasta_codes_cfe_generated\\.dart$"
       ]
     },
     {
       "name": "spelling_test_not_src_test",
       "kind": "Chain",
-      "source": "test/spelling_test_not_src_test.dart",
+      "source": "test/spelling_test_not_src_suite.dart",
       "path": ".",
       "status": "test/spelling_test.status",
       "pattern": [
@@ -228,14 +251,16 @@
         "test/fasta/super_mixins_test\\.dart$",
         "test/fasta/types/subtypes_benchmark\\.dart$",
         "test/fasta/unlinked_scope_test\\.dart$",
-        "test/incremental_load_from_dill_test\\.dart$",
+        "test/incremental_load_from_dill_suite\\.dart$",
         "test/incremental_load_from_invalid_dill_test\\.dart$",
         "test/memory_file_system_test\\.dart$",
         "test/scanner_fasta_test\\.dart$",
         "test/scanner_test\\.dart$",
+        "test/spell_checking_utils_test.dart",
         "test/standard_file_system_test\\.dart$",
         "test/tool/reload\\.dart$",
         "test/type_labeler_test\\.dart$",
+        "test/unit_test_suites\\.dart$",
         "testcases/expression/main\\.dart$",
         "testcases/general/DeltaBlue\\.dart$",
         "testcases/general/annotation_variable_declaration\\.dart$",
@@ -353,7 +378,7 @@
     {
       "name": "type_promotion_look_ahead",
       "kind": "Chain",
-      "source": "test/fasta/type_promotion_look_ahead_test.dart",
+      "source": "test/fasta/type_promotion_look_ahead_suite.dart",
       "path": "testcases/",
       "status": "testcases/type_promotion_look_ahead.status",
       "pattern": [
@@ -372,7 +397,6 @@
     "options": "analysis_options_no_lints.yaml",
     "uris": [
       "lib/",
-      "../analyzer/lib/src/generated/parser_fasta.dart",
       "tool/",
       "test/",
       "../kernel/lib/",
@@ -394,6 +418,7 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
+      "test/flow_analysis/assigned_variables/data/",
       "test/flow_analysis/definite_assignment/data/",
       "test/flow_analysis/nullability/data/",
       "test/flow_analysis/reachability/data/",
@@ -401,4 +426,4 @@
       "test/patching/data"
     ]
   }
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/testing_with_lints.json b/pkg/front_end/testing_with_lints.json
index ed396e1..8f65ff9 100644
--- a/pkg/front_end/testing_with_lints.json
+++ b/pkg/front_end/testing_with_lints.json
@@ -15,6 +15,7 @@
       "test/extensions/data/",
       "test/id_testing/data/",
       "test/language_versioning/data/",
+      "test/flow_analysis/assigned_variables/data/",
       "test/flow_analysis/definite_assignment/data/",
       "test/flow_analysis/nullability/data/",
       "test/flow_analysis/reachability/data/",
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index a8683a9..7c2dc8e 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -198,6 +198,23 @@
     return nodeNames[node] = name;
   }
 
+  void writeNullability(Nullability nullability, StringBuffer sb) {
+    switch (nullability) {
+      case Nullability.nullable:
+        sb.write("?");
+        break;
+      case Nullability.legacy:
+        sb.write("*");
+        break;
+      case Nullability.undetermined:
+        sb.write("%");
+        break;
+      case Nullability.nonNullable:
+      default:
+        break;
+    }
+  }
+
   @override
   void defaultDartType(DartType node, StringBuffer sb) {
     if (node is UnknownType) {
@@ -228,6 +245,12 @@
   }
 
   @override
+  void visitNeverType(NeverType node, StringBuffer sb) {
+    sb.write("Never");
+    writeNullability(node.nullability, sb);
+  }
+
+  @override
   void visitInterfaceType(InterfaceType node, StringBuffer sb) {
     sb.write(computeName(node.classNode));
     if (node.typeArguments.isNotEmpty) {
@@ -240,6 +263,7 @@
       }
       sb.write(">");
     }
+    writeNullability(node.nullability, sb);
   }
 
   @override
@@ -280,7 +304,9 @@
       sb.write("}");
       first = false;
     }
-    sb.write(") -> ");
+    sb.write(") ->");
+    writeNullability(node.nullability, sb);
+    sb.write(" ");
     node.returnType.accept1(this, sb);
   }
 
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 891b2113..05a5b83 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -8,6 +8,8 @@
 
 import 'dart:io' show exit, stderr;
 
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:build_integration/file_system/single_root.dart'
     show SingleRootFileSystem;
 
@@ -44,8 +46,6 @@
 import 'package:front_end/src/fasta/resolve_input_uri.dart'
     show resolveInputUri;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 import 'package:front_end/src/scheme_based_file_system.dart'
     show SchemeBasedFileSystem;
 
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 4fb21cc..b4c1cde 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -10,7 +10,9 @@
 
 import 'dart:io' show File, Platform, exitCode, stderr, stdin, stdout;
 
-import 'package:front_end/src/fasta/resolve_input_uri.dart';
+import 'package:_fe_analyzer_shared/src/util/relativize.dart'
+    show isWindows, relativizeUri;
+
 import 'package:kernel/kernel.dart'
     show CanonicalName, Library, Component, Source, loadComponentFromBytes;
 
@@ -48,8 +50,6 @@
 
 import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
 
-import 'package:front_end/src/fasta/util/relativize.dart' show relativizeUri;
-
 import 'package:front_end/src/kernel_generator_impl.dart'
     show generateKernelInternal;
 
diff --git a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
index 096b051..b250c51 100644
--- a/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
+++ b/pkg/front_end/tool/_fasta/generate_experimental_flags.dart
@@ -8,11 +8,12 @@
 
 import 'dart:isolate';
 
-import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
+import 'package:_fe_analyzer_shared/src/scanner/characters.dart'
+    show $A, $MINUS, $a, $z;
 
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
-import '../../lib/src/fasta/scanner/characters.dart' show $A, $MINUS, $a, $z;
+import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
 
 main(List<String> arguments) async {
   var port = new ReceivePort();
diff --git a/pkg/front_end/tool/_fasta/generate_messages.dart b/pkg/front_end/tool/_fasta/generate_messages.dart
index dba3a10..9b78a88 100644
--- a/pkg/front_end/tool/_fasta/generate_messages.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages.dart
@@ -8,31 +8,48 @@
 
 import 'dart:isolate';
 
-import 'package:yaml/yaml.dart' show loadYaml;
+import "package:_fe_analyzer_shared/src/messages/severity.dart"
+    show severityEnumNames;
 
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
-import "package:front_end/src/fasta/severity.dart" show severityEnumNames;
+import 'package:yaml/yaml.dart' show loadYaml;
 
 main(List<String> arguments) async {
   var port = new ReceivePort();
-  await new File.fromUri(await computeGeneratedFile())
-      .writeAsString(await generateMessagesFile(), flush: true);
+  Messages message = await generateMessagesFiles();
+  await new File.fromUri(await computeSharedGeneratedFile())
+      .writeAsString(message.sharedMessages, flush: true);
+  await new File.fromUri(await computeCfeGeneratedFile())
+      .writeAsString(message.cfeMessages, flush: true);
   port.close();
 }
 
-Future<Uri> computeGeneratedFile() {
-  return Isolate.resolvePackageUri(
-      Uri.parse('package:front_end/src/fasta/fasta_codes_generated.dart'));
+Future<Uri> computeSharedGeneratedFile() {
+  return Isolate.resolvePackageUri(Uri.parse(
+      'package:_fe_analyzer_shared/src/messages/codes_generated.dart'));
 }
 
-Future<String> generateMessagesFile() async {
+Future<Uri> computeCfeGeneratedFile() {
+  return Isolate.resolvePackageUri(
+      Uri.parse('package:front_end/src/fasta/fasta_codes_cfe_generated.dart'));
+}
+
+class Messages {
+  final String sharedMessages;
+  final String cfeMessages;
+
+  Messages(this.sharedMessages, this.cfeMessages);
+}
+
+Future<Messages> generateMessagesFiles() async {
   Uri messagesFile = Platform.script.resolve("../../messages.yaml");
   Map<dynamic, dynamic> yaml =
       loadYaml(await new File.fromUri(messagesFile).readAsStringSync());
-  StringBuffer sb = new StringBuffer();
+  StringBuffer sharedMessages = new StringBuffer();
+  StringBuffer cfeMessages = new StringBuffer();
 
-  sb.writeln("""
+  const String preamble = """
 // 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.
@@ -43,7 +60,15 @@
 // 'pkg/front_end/tool/fasta generate-messages' to update.
 
 // ignore_for_file: lines_longer_than_80_chars
+""";
 
+  sharedMessages.writeln(preamble);
+  sharedMessages.writeln("""
+part of _fe_analyzer_shared.messages.codes;
+""");
+
+  cfeMessages.writeln(preamble);
+  cfeMessages.writeln("""
 part of fasta.codes;
 """);
 
@@ -84,8 +109,13 @@
         }
       }
     }
-    sb.writeln(compileTemplate(name, index, map['template'], map['tip'],
-        map['analyzerCode'], map['severity']));
+    Template template = compileTemplate(name, index, map['template'],
+        map['tip'], map['analyzerCode'], map['severity']);
+    if (template.isShared) {
+      sharedMessages.writeln(template.text);
+    } else {
+      cfeMessages.writeln(template.text);
+    }
   }
   if (largestIndex > indexNameMap.length) {
     print('Error: The "index:" field values should be unique, consecutive'
@@ -105,21 +135,29 @@
       }
     }
     print('The next available index is ${nextAvailableIndex}');
-    return '';
+    return new Messages('', '');
   }
 
-  return new DartFormatter().format("$sb");
+  return new Messages(new DartFormatter().format("$sharedMessages"),
+      new DartFormatter().format("$cfeMessages"));
 }
 
 final RegExp placeholderPattern =
     new RegExp("#\([-a-zA-Z0-9_]+\)(?:%\([0-9]*\)\.\([0-9]+\))?");
 
-String compileTemplate(String name, int index, String template, String tip,
+class Template {
+  final String text;
+  final isShared;
+
+  Template(this.text, {this.isShared}) : assert(isShared != null);
+}
+
+Template compileTemplate(String name, int index, String template, String tip,
     Object analyzerCode, String severity) {
   if (template == null) {
     print('Error: missing template for message: $name');
     exitCode = 1;
-    return '';
+    return new Template('', isShared: true);
   }
   // Remove trailing whitespace. This is necessary for templates defined with
   // `|` (verbatim) as they always contain a trailing newline that we don't
@@ -130,10 +168,12 @@
   var conversions2 = new Set<String>();
   var arguments = new Set<String>();
   bool hasLabeler = false;
+  bool canBeShared = true;
   void ensureLabeler() {
     if (hasLabeler) return;
     conversions.add("TypeLabeler labeler = new TypeLabeler();");
     hasLabeler = true;
+    canBeShared = false;
   }
 
   for (Match match
@@ -355,14 +395,14 @@
       codeArguments.add('tip: r"""$tip"""');
     }
 
-    return """
+    return new Template("""
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> code$name = message$name;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode message$name =
     const MessageCode(\"$name\", ${codeArguments.join(', ')});
-""";
+""", isShared: canBeShared);
   }
 
   List<String> templateArguments = <String>[];
@@ -386,7 +426,7 @@
   }
   messageArguments.add("arguments: { ${arguments.join(', ')} }");
 
-  return """
+  return new Template("""
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(${parameters.join(', ')})> template$name =
     const Template<Message Function(${parameters.join(', ')})>(
@@ -404,5 +444,5 @@
      code$name,
      ${messageArguments.join(', ')});
 }
-""";
+""", isShared: canBeShared);
 }
diff --git a/pkg/front_end/tool/_fasta/generate_messages_test.dart b/pkg/front_end/tool/_fasta/generate_messages_test.dart
index d351316..303be61 100644
--- a/pkg/front_end/tool/_fasta/generate_messages_test.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages_test.dart
@@ -8,15 +8,22 @@
 
 import "package:expect/expect.dart" show Expect;
 
-import "generate_messages.dart" show computeGeneratedFile, generateMessagesFile;
+import "generate_messages.dart";
 
 main() {
   asyncTest(() async {
-    Uri generatedFile = await computeGeneratedFile();
-    String generated = await generateMessagesFile();
-    String actual = (await new File.fromUri(generatedFile).readAsString())
+    Messages messages = await generateMessagesFiles();
+
+    Uri generatedFile = await computeSharedGeneratedFile();
+    String sharedActual = (await new File.fromUri(generatedFile).readAsString())
         .replaceAll('\r\n', '\n');
-    Expect.stringEquals(
-        generated, actual, "${generatedFile.path} is out of date");
+    Expect.stringEquals(messages.sharedMessages, sharedActual,
+        "${generatedFile.path} is out of date");
+
+    Uri cfeGeneratedFile = await computeCfeGeneratedFile();
+    String cfeActual = (await new File.fromUri(cfeGeneratedFile).readAsString())
+        .replaceAll('\r\n', '\n');
+    Expect.stringEquals(messages.cfeMessages, cfeActual,
+        "${cfeGeneratedFile.path} is out of date");
   });
 }
diff --git a/pkg/front_end/tool/_fasta/parser.dart b/pkg/front_end/tool/_fasta/parser.dart
index b6091b4..aec74f9 100644
--- a/pkg/front_end/tool/_fasta/parser.dart
+++ b/pkg/front_end/tool/_fasta/parser.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:front_end/src/fasta/parser/parser_main.dart'
+import 'package:_fe_analyzer_shared/src/parser/parser_main.dart'
     show mainEntryPoint;
 
 main(List<String> arguments) => mainEntryPoint(arguments);
diff --git a/pkg/front_end/tool/_fasta/scanner.dart b/pkg/front_end/tool/_fasta/scanner.dart
index c0de49b..9d58567 100644
--- a/pkg/front_end/tool/_fasta/scanner.dart
+++ b/pkg/front_end/tool/_fasta/scanner.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.md file.
 
-import 'package:front_end/src/fasta/scanner/scanner_main.dart'
+import 'package:_fe_analyzer_shared/src/scanner/scanner_main.dart'
     show mainEntryPoint;
 
 main(List<String> arguments) => mainEntryPoint(arguments);
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index 3ad1726..a047f73 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -8,15 +8,17 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/parser/parser.dart';
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/io.dart'
+    show readBytesFromFileSync;
+
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/fasta/ast_builder.dart';
 import 'package:args/args.dart';
 
 import 'package:front_end/src/api_prototype/front_end.dart';
 import 'package:front_end/src/base/processed_options.dart';
-import 'package:front_end/src/fasta/parser.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/fasta/scanner/io.dart' show readBytesFromFileSync;
 import 'package:front_end/src/fasta/source/directive_listener.dart';
 import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
 
diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart
index 5e5dad1..6c82961 100644
--- a/pkg/front_end/tool/perf.dart
+++ b/pkg/front_end/tool/perf.dart
@@ -18,6 +18,8 @@
 import 'dart:async';
 import 'dart:io' show Directory, File, Platform, exit;
 
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart';
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
@@ -30,8 +32,6 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:front_end/src/fasta/scanner.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:package_config/discovery.dart';
 import 'package:path/path.dart' as path;
 
diff --git a/pkg/front_end/tool/perf_common.dart b/pkg/front_end/tool/perf_common.dart
index 5a8db5e..11afafa 100644
--- a/pkg/front_end/tool/perf_common.dart
+++ b/pkg/front_end/tool/perf_common.dart
@@ -7,22 +7,22 @@
 
 import 'dart:io' show exitCode, stderr;
 
+import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
+    show DiagnosticMessage, DiagnosticMessageHandler, getMessageCodeObject;
+
+import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
+
 import 'package:kernel/target/targets.dart' show Target, TargetFlags;
 
 import 'package:vm/target/flutter.dart' show FlutterTarget;
 
 import 'package:vm/target/vm.dart' show VmTarget;
 
-import 'package:front_end/src/api_prototype/diagnostic_message.dart'
-    show DiagnosticMessage, DiagnosticMessageHandler, getMessageCodeObject;
-
 import 'package:front_end/src/api_prototype/terminal_color_support.dart'
     show printDiagnosticMessage;
 
 import 'package:front_end/src/fasta/fasta_codes.dart' as fastaCodes;
 
-import 'package:front_end/src/fasta/severity.dart' show Severity;
-
 /// Error messages that we temporarily allow when compiling benchmarks in strong
 /// mode.
 ///
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 9b148a0..e2f411d 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.dart
@@ -16,12 +16,12 @@
   futures.add(
       run("pkg/front_end/test/explicit_creation_test.dart", [], filter: false));
   futures.add(run(
-    "pkg/front_end/test/fasta/messages_test.dart",
+    "pkg/front_end/test/fasta/messages_suite.dart",
     ["-DfastOnly=true"],
   ));
-  futures.add(run("pkg/front_end/test/spelling_test_not_src_test.dart", []));
-  futures.add(run("pkg/front_end/test/spelling_test_src_test.dart", []));
-  futures.add(run("pkg/front_end/test/lint_test.dart", []));
+  futures.add(run("pkg/front_end/test/spelling_test_not_src_suite.dart", []));
+  futures.add(run("pkg/front_end/test/spelling_test_src_suite.dart", []));
+  futures.add(run("pkg/front_end/test/lint_suite.dart", []));
   futures.add(run("pkg/front_end/test/deps_test.dart", [], filter: false));
   await Future.wait(futures);
   print("\n-----------------------\n");
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index c409d5f..852fb49 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -35,25 +35,10 @@
     show generateBytecode, createFreshComponentWithBytecode;
 import 'package:vm/bytecode/options.dart' show BytecodeOptions;
 import 'package:vm/incremental_compiler.dart' show IncrementalCompiler;
-import 'package:vm/kernel_front_end.dart'
-    show
-        KernelCompilationResults,
-        asFileUri,
-        compileToKernel,
-        convertFileOrUriArgumentToUri,
-        createFrontEndFileSystem,
-        createFrontEndTarget,
-        forEachPackage,
-        packageFor,
-        parseCommandLineDefines,
-        runWithFrontEndCompilerContext,
-        setVMEnvironmentDefines,
-        sortComponent,
-        writeDepfile;
-import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
-import 'package:vm/target/flutter.dart' show FlutterTarget;
-import 'package:vm/target/flutter_runner.dart' show FlutterRunnerTarget;
-import 'package:vm/target/vm.dart' show VmTarget;
+import 'package:vm/kernel_front_end.dart';
+
+import 'src/javascript_bundle.dart';
+import 'src/strong_components.dart';
 
 ArgParser argParser = ArgParser(allowTrailingOptions: true)
   ..addFlag('train',
@@ -148,7 +133,7 @@
   ..addFlag('track-widget-creation',
       help: 'Run a kernel transformer to track creation locations for widgets.',
       defaultsTo: false)
-  ..addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false)
+  ..addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: null)
   ..addMultiOption('bytecode-options',
       help: 'Specify options for bytecode generation:',
       valueHelp: 'opt1,opt2,...',
@@ -160,7 +145,15 @@
       help: 'Whether asserts will be enabled.', defaultsTo: false)
   ..addMultiOption('enable-experiment',
       help: 'Comma separated list of experimental features, eg set-literals.',
-      hide: true);
+      hide: true)
+  ..addFlag('split-output-by-packages',
+      help:
+          'Split resulting kernel file into multiple files (one per package).',
+      defaultsTo: false)
+  ..addOption('component-name', help: 'Name of the Fuchsia component')
+  ..addOption('data-dir',
+      help: 'Name of the subdirectory of //data for output files')
+  ..addOption('far-manifest', help: 'Path to output Fuchsia package manifest');
 
 String usage = '''
 Usage: server [options] [input.dart]
@@ -273,14 +266,7 @@
       this.unsafePackageSerialization,
       this.incrementalSerialization: true}) {
     _outputStream ??= stdout;
-    printerFactory ??= BinaryPrinterFactory();
-    // Initialize supported kernel targets.
-    targets['dart_runner'] = (TargetFlags flags) => DartRunnerTarget(flags);
-    targets['flutter'] = (TargetFlags flags) => FlutterTarget(flags);
-    targets['flutter_runner'] =
-        (TargetFlags flags) => FlutterRunnerTarget(flags);
-    targets['vm'] = (TargetFlags flags) => VmTarget(flags);
-    targets['dartdevc'] = (TargetFlags flags) => DevCompilerTarget(flags);
+    printerFactory ??= new BinaryPrinterFactory();
   }
 
   StringSink _outputStream;
@@ -374,13 +360,16 @@
       return false;
     }
 
-    compilerOptions.bytecode = options['gen-bytecode'];
+    compilerOptions.bytecode = options['gen-bytecode'] ?? options['aot'];
     final BytecodeOptions bytecodeOptions = BytecodeOptions(
-        enableAsserts: options['enable-asserts'],
-        emitSourceFiles: options['embed-source-text'],
-        environmentDefines: environmentDefines)
-      ..parseCommandLineFlags(options['bytecode-options']);
+      enableAsserts: options['enable-asserts'],
+      emitSourceFiles: options['embed-source-text'],
+      environmentDefines: environmentDefines,
+      aot: options['aot'],
+    )..parseCommandLineFlags(options['bytecode-options']);
 
+    // Initialize additional supported kernel targets.
+    targets['dartdevc'] = (TargetFlags flags) => DevCompilerTarget(flags);
     compilerOptions.target = createFrontEndTarget(
       options['target'],
       trackWidgetCreation: options['track-widget-creation'],
@@ -440,16 +429,19 @@
           aot: options['aot'],
           useGlobalTypeFlowAnalysis: options['tfa'],
           environmentDefines: environmentDefines,
+          enableAsserts: options['enable-asserts'],
           useProtobufTreeShaker: options['protobuf-tree-shaker']));
     }
     if (results.component != null) {
-      if (transformer != null) {
-        transformer.transform(results.component);
-      }
+      transformer?.transform(results.component);
 
-      await writeDillFile(results, _kernelBinaryFilename,
-          filterExternal: importDill != null,
-          incrementalSerializer: incrementalSerializer);
+      if (_compilerOptions.target.name == 'dartdevc') {
+        await writeJavascriptBundle(results, _kernelBinaryFilename);
+      } else {
+        await writeDillFile(results, _kernelBinaryFilename,
+            filterExternal: importDill != null,
+            incrementalSerializer: incrementalSerializer);
+      }
 
       _outputStream.writeln(boundaryKey);
       await _outputDependenciesDelta(results.compiledSources);
@@ -513,6 +505,35 @@
     previouslyReportedDependencies = uris;
   }
 
+  /// Write a JavaScript bundle containg the provided component.
+  Future<void> writeJavascriptBundle(
+      KernelCompilationResults results, String filename) async {
+    final Component component = results.component;
+    // Compute strongly connected components.
+    final strongComponents = StrongComponents(component, _mainSource,
+        _compilerOptions.packagesFileUri, _compilerOptions.fileSystem);
+    await strongComponents.computeModules();
+
+    // Create JavaScript bundler.
+    final File sourceFile = File('$filename.sources');
+    final File manifestFile = File('$filename.json');
+    final File sourceMapsFile = File('$filename.map');
+    if (!sourceFile.parent.existsSync()) {
+      sourceFile.parent.createSync(recursive: true);
+    }
+    final bundler = JavaScriptBundler(component, strongComponents);
+    final sourceFileSink = sourceFile.openWrite();
+    final manifestFileSink = manifestFile.openWrite();
+    final sourceMapsFileSink = sourceMapsFile.openWrite();
+    bundler.compile(results.classHierarchy, results.coreTypes, sourceFileSink,
+        manifestFileSink, sourceMapsFileSink);
+    await Future.wait([
+      sourceFileSink.close(),
+      manifestFileSink.close(),
+      sourceMapsFileSink.close()
+    ]);
+  }
+
   writeDillFile(KernelCompilationResults results, String filename,
       {bool filterExternal: false,
       IncrementalSerializer incrementalSerializer}) async {
@@ -528,10 +549,12 @@
         await runWithFrontEndCompilerContext(
             _mainSource, _compilerOptions, component, () async {
           if (_options['incremental']) {
+            // When loading a single kernel buffer with multiple sub-components,
+            // the VM expects 'main' to be the first sub-component.
             await forEachPackage(component,
                 (String package, List<Library> libraries) async {
               _writePackage(results, package, libraries, sink);
-            });
+            }, mainFirst: true);
           } else {
             _writePackage(results, 'main', component.libraries, sink);
           }
@@ -553,7 +576,9 @@
           }
         }
 
-        final IOSink sink = File(_initializeFromDill).openWrite();
+        final file = new File(_initializeFromDill);
+        await file.create(recursive: true);
+        final IOSink sink = file.openWrite();
         final BinaryPrinter printer = filterExternal
             ? LimitedBinaryPrinter(
                 sink, (lib) => !lib.isExternal, true /* excludeUriToSource */)
@@ -584,6 +609,28 @@
       printer.writeComponentFile(component);
       await sink.close();
     }
+
+    if (_options['split-output-by-packages']) {
+      await writeOutputSplitByPackages(
+          _mainSource,
+          _compilerOptions,
+          results.component,
+          results.coreTypes,
+          results.classHierarchy,
+          filename,
+          genBytecode: _compilerOptions.bytecode,
+          bytecodeOptions: _bytecodeOptions,
+          dropAST: _options['drop-ast']);
+    }
+
+    final String manifestFilename = _options['far-manifest'];
+    if (manifestFilename != null) {
+      final String output = _options['output-dill'];
+      final String dataDir = _options.options.contains('component-name')
+          ? _options['component-name']
+          : _options['data-dir'];
+      await createFarManifest(output, dataDir, manifestFilename);
+    }
   }
 
   Future<Null> invalidateIfInitializingFromDill() async {
@@ -704,8 +751,12 @@
         _generator.getCoreTypes(),
         deltaProgram.uriToSource.keys);
 
-    await writeDillFile(results, _kernelBinaryFilename,
-        incrementalSerializer: _generator.incrementalSerializer);
+    if (_compilerOptions.target.name == 'dartdevc') {
+      await writeJavascriptBundle(results, _kernelBinaryFilename);
+    } else {
+      await writeDillFile(results, _kernelBinaryFilename,
+          incrementalSerializer: _generator.incrementalSerializer);
+    }
 
     _outputStream.writeln(boundaryKey);
     await _outputDependenciesDelta(results.compiledSources);
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
new file mode 100644
index 0000000..63e5163
--- /dev/null
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -0,0 +1,100 @@
+// Copyright 2019 The Chromium Authors. 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:dev_compiler/dev_compiler.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+
+import 'strong_components.dart';
+
+/// Produce a special bundle format for compiled JavaScript.
+///
+/// The bundle format consists of two files: One containing all produced
+/// JavaScript modules concatenated together, and a second containing the byte
+/// offsets by module name for each JavaScript module in JSON format.
+///
+/// Ths format is analgous to the dill and .incremental.dill in that during
+/// an incremental build, a different file is written for each which contains
+/// only the updated libraries.
+class JavaScriptBundler {
+  JavaScriptBundler(this._originalComponent, this._strongComponents) {
+    _summaries = <Component>[];
+    _summaryUris = <Uri>[];
+    _moduleImportForSummary = <Uri, String>{};
+    _uriToComponent = <Uri, Component>{};
+    for (Uri uri in _strongComponents.modules.keys) {
+      final List<Library> libraries = _strongComponents.modules[uri].toList();
+      final Component summaryComponent = Component(
+        libraries: libraries,
+        nameRoot: _originalComponent.root,
+        uriToSource: _originalComponent.uriToSource,
+      );
+      _summaries.add(summaryComponent);
+      _summaryUris.add(uri);
+      _moduleImportForSummary[uri] = '${uri.path}.js';
+      _uriToComponent[uri] = summaryComponent;
+    }
+  }
+
+  final StrongComponents _strongComponents;
+  final Component _originalComponent;
+
+  List<Component> _summaries;
+  List<Uri> _summaryUris;
+  Map<Uri, String> _moduleImportForSummary;
+  Map<Uri, Component> _uriToComponent;
+
+  /// Compile each component into a single JavaScript module.
+  void compile(ClassHierarchy classHierarchy, CoreTypes coreTypes,
+      IOSink codeSink, IOSink manifestSink, IOSink sourceMapsSink) {
+    var codeOffset = 0;
+    var sourceMapOffset = 0;
+    final manifest = <String, Map<String, List<int>>>{};
+    final Set<Uri> visited = <Uri>{};
+    for (Library library in _originalComponent.libraries) {
+      if (library.isExternal || library.importUri.scheme == 'dart') {
+        continue;
+      }
+      final Uri moduleUri = _strongComponents.moduleAssignment[library.fileUri];
+      if (visited.contains(moduleUri)) {
+        continue;
+      }
+      visited.add(moduleUri);
+
+      final summaryComponent = _uriToComponent[moduleUri];
+      final compiler = ProgramCompiler(
+        _originalComponent,
+        classHierarchy,
+        SharedCompilerOptions(sourceMap: true, summarizeApi: false),
+        coreTypes: coreTypes,
+      );
+      final jsModule = compiler.emitModule(
+          summaryComponent, _summaries, _summaryUris, _moduleImportForSummary);
+      final moduleUrl = moduleUri.toString();
+      final code = jsProgramToCode(jsModule, ModuleFormat.amd,
+          inlineSourceMap: true,
+          buildSourceMap: true,
+          jsUrl: '$moduleUrl',
+          mapUrl: '$moduleUrl.js.map');
+      final codeBytes = utf8.encode(code.code);
+      final sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
+      codeSink.add(codeBytes);
+      sourceMapsSink.add(sourceMapBytes);
+
+      final String moduleKey = _moduleImportForSummary[moduleUri];
+      manifest[moduleKey] = {
+        'code': <int>[codeOffset, codeOffset += codeBytes.length],
+        'sourcemap': <int>[
+          sourceMapOffset,
+          sourceMapOffset += sourceMapBytes.length
+        ],
+      };
+    }
+    manifestSink.add(utf8.encode(json.encode(manifest)));
+  }
+}
diff --git a/pkg/frontend_server/lib/src/strong_components.dart b/pkg/frontend_server/lib/src/strong_components.dart
new file mode 100644
index 0000000..80cb7fa5
--- /dev/null
+++ b/pkg/frontend_server/lib/src/strong_components.dart
@@ -0,0 +1,168 @@
+// Copyright 2019 The Chromium Authors. 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:kernel/ast.dart';
+import 'package:kernel/util/graph.dart';
+
+import 'package:vm/kernel_front_end.dart';
+import 'package:front_end/src/api_unstable/vm.dart' show FileSystem;
+
+/// Compute the strongly connected components for JavaScript compilation.
+///
+/// Implements a Path-based strong component algorithm.
+/// See https://en.wikipedia.org/wiki/Path-based_strong_component_algorithm
+///
+/// The file URI for each library is used as an identifier for the module
+/// name. [moduleAssignment] will be populated with a mapping of library URI to
+/// module name, while [modules] will be populated with a mapping of module
+/// name to library set.
+///
+/// JavaScript import semantics do not permit circular imports in the same
+/// manner that Dart does. When compiling a set of libraries with circular
+/// imports, these must be combined into a single JavaScript module.
+///
+/// On incremental updates, we completely recompute the strongly connected
+/// components, but only for the partial component produced.
+class StrongComponents {
+  StrongComponents(
+    this.component,
+    this.mainUri, [
+    this.packagesUri,
+    this.fileSystem,
+  ]);
+
+  /// The Component that is being compiled.
+  ///
+  /// On incremental compiles, this will only contain the invalidated
+  /// lbraries.
+  final Component component;
+
+  /// The main URI for thiis application.
+  final Uri mainUri;
+
+  /// The URI of the .packages file.
+  final Uri packagesUri;
+
+  /// The filesystem instance for resolving files.
+  final FileSystem fileSystem;
+
+  /// The set of libraries for each module URI.
+  ///
+  /// This is populated after calling [computeModules] once.
+  final Map<Uri, List<Library>> modules = <Uri, List<Library>>{};
+
+  /// The module URI for each library file URI.
+  ///
+  /// This is populated after calling [computeModules] once.
+  final Map<Uri, Uri> moduleAssignment = <Uri, Uri>{};
+
+  /// Compute the strongly connected components for the current program.
+  ///
+  /// Throws an [Exception] if [mainUri] cannot be located in the given
+  /// component.
+  Future<void> computeModules() async {
+    assert(modules.isEmpty);
+    if (component.libraries.isEmpty) {
+      return;
+    }
+    Uri entrypointFileUri = mainUri;
+    if (!entrypointFileUri.isScheme('file')) {
+      entrypointFileUri = await asFileUri(fileSystem,
+          await _convertToFileUri(fileSystem, entrypointFileUri, packagesUri));
+    }
+    if (entrypointFileUri == null || !entrypointFileUri.isScheme('file')) {
+      throw Exception(
+          'Unable to map ${entrypointFileUri} back to file scheme.');
+    }
+
+    // If we don't have a file uri, just use the first library in the
+    // component.
+    Library entrypoint = component.libraries.firstWhere(
+        (Library library) => library.fileUri == entrypointFileUri,
+        orElse: () => null);
+
+    if (entrypoint == null) {
+      throw Exception(
+          'Could not find entrypoint ${entrypointFileUri} in Component.');
+    }
+
+    final List<List<Library>> results =
+        computeStrongComponents(_LibraryGraph(entrypoint));
+    for (List<Library> component in results) {
+      assert(component.length > 0);
+      final Uri moduleUri = component.first.fileUri;
+      modules[moduleUri] = component;
+      for (Library componentLibrary in component) {
+        moduleAssignment[componentLibrary.fileUri] = moduleUri;
+      }
+    }
+  }
+
+  // Convert package URI to file URI if it is inside one of the packages.
+  Future<Uri> _convertToFileUri(
+      FileSystem fileSystem, Uri uri, Uri packagesUri) async {
+    if (uri == null || uri.scheme != 'package') {
+      return uri;
+    }
+    // Convert virtual URI to a real file URI.
+    // String uriString = (await asFileUri(fileSystem, uri)).toString();
+    List<String> packages;
+    try {
+      packages =
+          await File((await asFileUri(fileSystem, packagesUri)).toFilePath())
+              .readAsLines();
+    } on IOException {
+      // Can't read packages file - silently give up.
+      return uri;
+    }
+    // package:x.y/main.dart -> file:///a/b/x/y/main.dart
+    for (var line in packages) {
+      if (line.isEmpty || line.startsWith("#")) {
+        continue;
+      }
+
+      final colon = line.indexOf(':');
+      if (colon == -1) {
+        continue;
+      }
+      final packageName = line.substring(0, colon);
+      if (!uri.path.startsWith('$packageName/')) {
+        continue;
+      }
+      String packagePath;
+      try {
+        packagePath = (await asFileUri(
+                fileSystem, packagesUri.resolve(line.substring(colon + 1))))
+            .toString();
+      } on FileSystemException {
+        // Can't resolve package path.
+        continue;
+      }
+      return Uri.parse(
+          '$packagePath${uri.path.substring(packageName.length + 1)}');
+    }
+    return uri;
+  }
+}
+
+class _LibraryGraph implements Graph<Library> {
+  _LibraryGraph(this.library);
+
+  final Library library;
+
+  @override
+  Iterable<Library> neighborsOf(Library vertex) {
+    return <Library>[
+      for (LibraryDependency dependency in vertex.dependencies)
+        if (!dependency.targetLibrary.isExternal &&
+            dependency.targetLibrary.importUri.scheme != 'dart')
+          dependency.targetLibrary
+    ];
+  }
+
+  @override
+  Iterable<Library> get vertices => <Library>[library];
+}
diff --git a/pkg/frontend_server/pubspec.yaml b/pkg/frontend_server/pubspec.yaml
index 17121fe..a64d956 100644
--- a/pkg/frontend_server/pubspec.yaml
+++ b/pkg/frontend_server/pubspec.yaml
@@ -13,3 +13,6 @@
   front_end: ^0.1.6
   kernel: ^0.3.6
   args: ^1.4.4
+
+dev_dependencies:
+  test: any
\ No newline at end of file
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 7da2336..b88dda9 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -102,6 +102,31 @@
       expect(await result, 0);
       inputStreamController.close();
     });
+
+    test('compile one file to JavaScript', () async {
+      final StreamController<List<int>> inputStreamController =
+          new StreamController<List<int>>();
+      final ReceivePort compileCalled = new ReceivePort();
+      when(compiler.compile(any, any, generator: anyNamed('generator')))
+          .thenAnswer((Invocation invocation) async {
+        expect(invocation.positionalArguments[0], equals('server.dart'));
+        expect(
+            invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
+        compileCalled.sendPort.send(true);
+        return true;
+      });
+
+      Future<int> result = starter(
+        ['--target=dartdevc', ...args],
+        compiler: compiler,
+        input: inputStreamController.stream,
+      );
+      inputStreamController.add('compile server.dart\n'.codeUnits);
+      await compileCalled.first;
+      inputStreamController.add('quit\n'.codeUnits);
+      expect(await result, 0);
+      inputStreamController.close();
+    });
   });
 
   group('interactive compile with mocked compiler', () {
@@ -410,6 +435,8 @@
   group('full compiler tests', () {
     final platformKernel =
         computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
+    final ddcPlatformKernel =
+        computePlatformBinariesLocation().resolve('ddc_sdk.dill');
     final sdkRoot = computePlatformBinariesLocation();
 
     Directory tempDir;
@@ -1097,6 +1124,52 @@
       expect(await starter(args), 0);
     });
 
+    test('compile to JavaScript', () async {
+      var file = new File('${tempDir.path}/foo.dart')..createSync();
+      file.writeAsStringSync("main() {}\n");
+      var packages = new File('${tempDir.path}/.packages')
+        ..createSync()
+        ..writeAsStringSync("\n");
+      var dillFile = new File('${tempDir.path}/app.dill');
+
+      expect(dillFile.existsSync(), false);
+
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${ddcPlatformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--packages=${packages.path}',
+        '--target=dartdevc',
+        file.path,
+      ];
+
+      expect(await starter(args), 0);
+    });
+
+    test('compile to JavaScript with package scheme', () async {
+      var file = new File('${tempDir.path}/foo.dart')..createSync();
+      file.writeAsStringSync("main() {}\n");
+      new File('${tempDir.path}/.packages')
+        ..createSync()
+        ..writeAsStringSync("hello:${tempDir.uri}\n");
+      var dillFile = new File('${tempDir.path}/app.dill');
+
+      expect(dillFile.existsSync(), false);
+
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${ddcPlatformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--target=dartdevc',
+        '--packages=${tempDir.path}/.packages',
+        'package:hello/foo.dart'
+      ];
+
+      expect(await starter(args), 0);
+    });
+
     test('compile with bytecode', () async {
       var file = new File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("main() {}\n");
diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart
new file mode 100644
index 0000000..b6d860d
--- /dev/null
+++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart
@@ -0,0 +1,178 @@
+// Copyright 2019 The Chromium Authors. 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:frontend_server/src/javascript_bundle.dart';
+import 'package:frontend_server/src/strong_components.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:test/test.dart';
+
+/// Additional indexed types required by the dev_compiler's NativeTypeSet.
+final Map<String, List<String>> additionalRequiredClasses = {
+  'dart:core': ['Comparable'],
+  'dart:async': [
+    'StreamIterator',
+    '_AsyncStarImpl',
+  ],
+  'dart:_interceptors': [
+    'JSBool',
+    'JSNumber',
+    'JSArray',
+    'JSString',
+  ],
+  'dart:_native_typed_data': [],
+  'dart:collection': [
+    'ListMixin',
+    'LinkedHashSet',
+    '_HashSet',
+    '_IdentityHashSet',
+  ],
+  'dart:math': ['Rectangle'],
+  'dart:html': [],
+  'dart:indexed_db': [],
+  'dart:svg': [],
+  'dart:web_audio': [],
+  'dart:web_gl': [],
+  'dart:web_sql': [],
+  'dart:_js_helper': [
+    'PrivateSymbol',
+    'LinkedMap',
+    'IdentityMap',
+    'SyncIterable',
+  ],
+};
+
+void main() {
+  final allRequiredTypes =
+      _combineMaps(CoreTypes.requiredClasses, additionalRequiredClasses);
+  final testCoreLibraries = [
+    for (String requiredLibrary in allRequiredTypes.keys)
+      Library(Uri.parse(requiredLibrary), classes: [
+        for (String requiredClass in allRequiredTypes[requiredLibrary])
+          Class(name: requiredClass),
+      ]),
+  ];
+
+  test('compiles JavaScript code', () async {
+    final library = Library(
+      Uri.file('/c.dart'),
+      fileUri: Uri.file('/c.dart'),
+      procedures: [
+        Procedure(Name('ArbitrarilyChosen'), ProcedureKind.Method,
+            FunctionNode(Block([])))
+      ],
+    );
+    final testComponent = Component(libraries: [library, ...testCoreLibraries]);
+    final strongComponents =
+        StrongComponents(testComponent, Uri.file('/c.dart'));
+    strongComponents.computeModules();
+    final javaScriptBundler =
+        JavaScriptBundler(testComponent, strongComponents);
+    final manifestSink = _MemorySink();
+    final codeSink = _MemorySink();
+    final sourcemapSink = _MemorySink();
+
+    javaScriptBundler.compile(ClassHierarchy(testComponent),
+        CoreTypes(testComponent), codeSink, manifestSink, sourcemapSink);
+
+    final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
+    final String code = utf8.decode(codeSink.buffer);
+
+    expect(manifest, {
+      '/c.dart.js': {
+        'code': [0, codeSink.buffer.length],
+        'sourcemap': [0, sourcemapSink.buffer.length],
+      },
+    });
+    expect(code, contains('ArbitrarilyChosen'));
+
+    // verify source map url is correct.
+    expect(code, contains('sourceMappingURL=c.dart.js.map'));
+  });
+
+  test('can combine strongly connected components', () {
+    // Create three libraries A, B, C where A is the entrypoint and B & C
+    // circularly import each other.
+    final libraryC = Library(Uri.file('/c.dart'), fileUri: Uri.file('/c.dart'));
+    final libraryB = Library(Uri.file('/b.dart'), fileUri: Uri.file('/b.dart'));
+    libraryC.dependencies.add(LibraryDependency.import(libraryB));
+    libraryB.dependencies.add(LibraryDependency.import(libraryC));
+    final libraryA = Library(
+      Uri.file('/a.dart'),
+      fileUri: Uri.file('/a.dart'),
+      dependencies: [
+        LibraryDependency.import(libraryB),
+      ],
+      procedures: [
+        Procedure(Name('ArbitrarilyChosen'), ProcedureKind.Method,
+            FunctionNode(Block([])))
+      ],
+    );
+    final testComponent = Component(
+        libraries: [libraryA, libraryB, libraryC, ...testCoreLibraries]);
+
+    final strongComponents =
+        StrongComponents(testComponent, Uri.file('/a.dart'));
+    strongComponents.computeModules();
+    final javaScriptBundler =
+        JavaScriptBundler(testComponent, strongComponents);
+    final manifestSink = _MemorySink();
+    final codeSink = _MemorySink();
+    final sourcemapSink = _MemorySink();
+
+    javaScriptBundler.compile(ClassHierarchy(testComponent),
+        CoreTypes(testComponent), codeSink, manifestSink, sourcemapSink);
+
+    final code = utf8.decode(codeSink.buffer);
+    final manifest = json.decode(utf8.decode(manifestSink.buffer));
+
+    // There should only be two modules since C and B should be combined.
+    const moduleHeader = r"define(['dart_sdk'], function(dart_sdk) {";
+
+    expect(moduleHeader.allMatches(code), hasLength(2));
+
+    // verify source map url is correct.
+    expect(code, contains('sourceMappingURL=a.dart.js.map'));
+
+    final offsets = manifest['/a.dart.js']['sourcemap'];
+    final sourcemapModuleA = json.decode(
+        utf8.decode(sourcemapSink.buffer.sublist(offsets.first, offsets.last)));
+
+    // verify source maps are pointing at correct source files.
+    expect(sourcemapModuleA['file'], 'a.dart');
+  });
+}
+
+class _MemorySink implements IOSink {
+  final List<int> buffer = <int>[];
+
+  @override
+  void add(List<int> data) {
+    buffer.addAll(data);
+  }
+
+  @override
+  Future<void> close() => Future.value();
+
+  @override
+  void noSuchMethod(Invocation invocation) {
+    throw UnsupportedError(invocation.memberName.toString());
+  }
+}
+
+Map<String, List<String>> _combineMaps(
+  Map<String, List<String>> left,
+  Map<String, List<String>> right,
+) {
+  final result = Map<String, List<String>>.from(left);
+  for (String key in right.keys) {
+    result[key] ??= [];
+    result[key].addAll(right[key]);
+  }
+  return result;
+}
diff --git a/pkg/frontend_server/test/src/strong_components_test.dart b/pkg/frontend_server/test/src/strong_components_test.dart
new file mode 100644
index 0000000..42dab3b
--- /dev/null
+++ b/pkg/frontend_server/test/src/strong_components_test.dart
@@ -0,0 +1,139 @@
+// Copyright 2019 The Chromium Authors. 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:frontend_server/src/strong_components.dart';
+import 'package:kernel/ast.dart';
+import 'package:test/test.dart';
+
+void main() {
+  test('empty component', () {
+    final testComponent = Component(libraries: []);
+    final StrongComponents strongComponents =
+        StrongComponents(testComponent, Uri.file('/c.dart'));
+    strongComponents.computeModules();
+
+    expect(strongComponents.modules, {});
+  });
+
+  test('no circular imports', () {
+    final libraryA = Library(
+      Uri.file('/a.dart'),
+      fileUri: Uri.file('/a.dart'),
+    );
+    final libraryB = Library(
+      Uri.file('/b.dart'),
+      fileUri: Uri.file('/b.dart'),
+      dependencies: [
+        LibraryDependency.import(libraryA),
+      ],
+    );
+    final libraryC = Library(
+      Uri.file('/c.dart'),
+      fileUri: Uri.file('/c.dart'),
+      dependencies: [
+        LibraryDependency.import(libraryB),
+      ],
+    );
+    final testComponent = Component(libraries: [
+      libraryA,
+      libraryB,
+      libraryC,
+    ]);
+    final StrongComponents strongComponents =
+        StrongComponents(testComponent, Uri.file('/c.dart'));
+    strongComponents.computeModules();
+
+    expect(strongComponents.modules, {
+      Uri.file('/a.dart'): [libraryA],
+      Uri.file('/b.dart'): [libraryB],
+      Uri.file('/c.dart'): [libraryC],
+    });
+    expect(strongComponents.moduleAssignment, {
+      Uri.file('/a.dart'): Uri.file('/a.dart'),
+      Uri.file('/b.dart'): Uri.file('/b.dart'),
+      Uri.file('/c.dart'): Uri.file('/c.dart'),
+    });
+  });
+
+  test('circular imports are combined into single module', () {
+    final libraryA = Library(
+      Uri.file('/a.dart'),
+      fileUri: Uri.file('/a.dart'),
+    );
+    final libraryB = Library(
+      Uri.file('/b.dart'),
+      fileUri: Uri.file('/b.dart'),
+    );
+    // induce circular import.
+    libraryB.dependencies.add(LibraryDependency.import(libraryA));
+    libraryA.dependencies.add(LibraryDependency.import(libraryB));
+    final libraryC = Library(
+      Uri.file('/c.dart'),
+      fileUri: Uri.file('/c.dart'),
+      dependencies: [
+        LibraryDependency.import(libraryB),
+      ],
+    );
+    final testComponent = Component(libraries: [
+      libraryA,
+      libraryB,
+      libraryC,
+    ]);
+    final StrongComponents strongComponents =
+        StrongComponents(testComponent, Uri.file('/c.dart'));
+    strongComponents.computeModules();
+
+    expect(strongComponents.modules, {
+      // The choice of module here is arbitrary, but should be consistent for
+      // a given component.
+      Uri.file('/a.dart'): [libraryA, libraryB],
+      Uri.file('/c.dart'): [libraryC],
+    });
+    expect(strongComponents.moduleAssignment, {
+      Uri.file('/a.dart'): Uri.file('/a.dart'),
+      Uri.file('/b.dart'): Uri.file('/a.dart'),
+      Uri.file('/c.dart'): Uri.file('/c.dart'),
+    });
+  });
+
+  test('does not index external, dart:, or unimported libraries', () {
+    final libraryExternal = Library(
+      Uri.file('a.dart'),
+      fileUri: Uri.file('/a.dart'),
+      isExternal: true,
+    );
+    final libraryDart = Library(
+      Uri.parse('dart:foo'),
+      fileUri: Uri.file('/b.dart'),
+    );
+    final libraryUnrelated = Library(
+      Uri.file('/z.dart'),
+      fileUri: Uri.file('/z.dart'),
+    );
+    final libraryC = Library(
+      Uri.file('/c.dart'),
+      fileUri: Uri.file('/c.dart'),
+      dependencies: [
+        LibraryDependency.import(libraryExternal),
+        LibraryDependency.import(libraryDart),
+      ],
+    );
+    final testComponent = Component(libraries: [
+      libraryExternal,
+      libraryDart,
+      libraryUnrelated,
+      libraryC,
+    ]);
+    final StrongComponents strongComponents =
+        StrongComponents(testComponent, Uri.file('/c.dart'));
+    strongComponents.computeModules();
+
+    expect(strongComponents.modules, {
+      Uri.file('/c.dart'): [libraryC],
+    });
+    expect(strongComponents.moduleAssignment, {
+      Uri.file('/c.dart'): Uri.file('/c.dart'),
+    });
+  });
+}
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 7e503a8..40f1ea1 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 35;
+  UInt32 formatVersion = 36;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
   UriSource sourceMap;
@@ -1236,7 +1236,7 @@
 
 enum Nullability { nullable = 0, nonNullable = 1, neither = 2, legacy = 3, }
 
-enum Variance { unrelated = 0, covariant = 1, contravariant = 2, invariant = 3, }
+enum Variance { unrelated = 0, covariant = 1, contravariant = 2, invariant = 3, legacyCovariant = 4, }
 
 abstract type DartType extends Node {}
 
@@ -1244,6 +1244,11 @@
   Byte tag = 89;
 }
 
+type NeverType extends DartType {
+  Byte tag = 98;
+  Byte nullability; // Index into the Nullability enum above.
+}
+
 type InvalidType extends DartType {
   Byte tag = 90;
 }
diff --git a/pkg/kernel/doc/nnbd_api.md b/pkg/kernel/doc/nnbd_api.md
index b3e4ec8..3b5757e 100644
--- a/pkg/kernel/doc/nnbd_api.md
+++ b/pkg/kernel/doc/nnbd_api.md
@@ -2,12 +2,18 @@
 
 Author: The Dart CFE team.
 
-Status: Draft
+Status: Living document.
 
 
 
 ## CHANGELOG
 
+2019.10.18:
+- Added information about `NeverType`.
+
+2019.10.17:
+- Renamed `Nullability.neither` to `Nullability.undetermined`.
+
 2019.10.15:
 - Added information about implementing the subtype relation.
 
@@ -21,7 +27,7 @@
 
 ## Summary
 
-The sections below describe the encoding of the nullability property on types in the Kernel ASTs produced by the CFE.  Details are discussed, such as the use of `Nullability.neither`, and computation of the nullability property for the results of type substitution and type intersection is described.  The encoding for late fields and variables and required named parameters is described.  Finally, the list of the updates to the public interface of the CFE is given along with some recommendations on updating the client code.
+The sections below describe the encoding of the nullability property on types in the Kernel ASTs produced by the CFE.  Details are discussed, such as the use of `Nullability.undetermined`, and computation of the nullability property for the results of type substitution and type intersection is described.  The encoding for late fields and variables and required named parameters is described.  Finally, the list of the updates to the public interface of the CFE is given along with some recommendations on updating the client code.
 
 This is a living document describing the changes in the output and in the public interface of the CFE related to the NNBD Dart language feature.  It is being updated as more changes are made.
 
@@ -73,7 +79,7 @@
 
 - **Nullable** types.  Mainly, these are the types that are marked with `?` by the programmer.  They can also be inferred from other nullable types or synthesized according to the language specification.  For example, if the programmer omits the type bound on a type variable in an opted-in library, the CFE should synthesize `Object?` for the bound.
 - **Non-nullable** types.  This is the default category of types.  If a type is declared without any modifiers in an opted-in library, in most cases it would be non-nullable.
-- Types in opted-in libraries that are potentially nullable or potentially non-nullable, but **neither** can be said about them at compile time.  An example of such type is a type-parameter type with the nullable bound.  At run time both nullable and non-nullable types can be passed for that type parameter, so it's impossible to say anything about the nullability of such type at compile time.
+- Types in opted-in libraries that are potentially nullable or potentially non-nullable, but neither can be said about them at compile time are of **undetermined** nullability.  An example of such type is a type-parameter type with the nullable bound.  At run time both nullable and non-nullable types can be passed for that type parameter, so it's impossible to say anything about the nullability of such type at compile time.
 - **Legacy** types.  These are the types originating from the opted-out libraries.
 
 Every `DartType` subclass implements the `nullability` getter.  The return value of the getter is described by the following [`enum`](https://github.com/dart-lang/sdk/blob/0a4d47de3cb8cd398c5a2c669953129cdb11ec9a/pkg/kernel/lib/ast.dart#L4803):
@@ -82,19 +88,19 @@
 enum Nullability {
   nullable,
   nonNullable,
-  neither,
+  undetermined,
   legacy
 }
 ```
 
-In the textual representation of Kernel that is commonly used in `.expect` files `Nullability.nullable` is printed out as `?`, `Nullability.nonNullable` is printed as an empty sequence of characters, `Nullability.neither` is printed as `%`, and `Nullability.legacy` is printed as `*`.
+In the textual representation of Kernel that is commonly used in `.expect` files `Nullability.nullable` is printed out as `?`, `Nullability.nonNullable` is printed as an empty sequence of characters, `Nullability.undetermined` is printed as `%`, and `Nullability.legacy` is printed as `*`.
 
 *TODO: Add an example of a .expect file.*
 
 
-####The 'neither' Nullability
+#### The 'undetermined' Nullability
 
-`Nullability.neither` marks all types that can't be put into any other three categories at compile time and that should be categorized at run time.  The primary use case for `Nullability.neither` are type-parameter types with nullable bounds.  Consider the following Dart program:
+`Nullability.undetermined` marks all types that can't be put into any other three categories at compile time and that should be categorized at run time.  The primary use case for `Nullability.undetermined` are type-parameter types with nullable bounds.  Consider the following Dart program:
 
 ```dart
 // The enclosing library is opted in.
@@ -113,7 +119,7 @@
 
 At compile time nothing can be said about the nullability of `T` because it is possible that at run time either a nullable or non-nullable type will be passed for it.  We have to be restrictive and prohibit both assignments of `null` to variables of type `T` and assignments of expression values of type `T` to variables of non-nullable types.  However, there are cases when the error can be caught only at run time when the nullability of the type passed for `T` is known.  An example of that is an invocation of a function stored in a variable of type `dynamic`.
 
-A type-parameter type also has `Nullability.neither` if its bound have `Nullability.neither`.  In the following example types `T`, `S`, and `V` are of `neither` nullability:
+A type-parameter type also has `Nullability.undetermined` if its bound have `Nullability.undetermined`.  In the following example types `T`, `S`, and `V` are of `undetermined` nullability:
 
 ```dart
 class B<T extends S, S extends V, V extends Object?> {
@@ -123,7 +129,7 @@
 }
 ```
 
-Additionally, if the nullability of a type depends on the nullability of an `InvalidType`, the former is set to `Nullability.neither` for recovery purposes.  An example of such dependency is the nullability of a type-parameter type with an `InvalidType` as the bound of its type parameter.  Note that the `.nullability` getter of `InvalidType` throws when accessed in order to make sure all such dependencies are treated explicitly.
+Additionally, if the nullability of a type depends on the nullability of an `InvalidType`, the former is set to `Nullability.undetermined` for recovery purposes.  An example of such dependency is the nullability of a type-parameter type with an `InvalidType` as the bound of its type parameter.  Note that the `.nullability` getter of `InvalidType` throws when accessed in order to make sure all such dependencies are treated explicitly.
 
 
 #### Type Substitution and Nullability
@@ -139,7 +145,7 @@
 | * | * | ? | * | * |
 | % | N/A | ? | * | % |
 
-In the table `!` denotes `Nullability.nonNullable`, `?` denotes `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes `Nullability.neither`.
+In the table `!` denotes `Nullability.nonNullable`, `?` denotes `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes `Nullability.undetermined`.
 
 Type-parameter types are assigned their nullabilities as follows:
 
@@ -165,7 +171,7 @@
 class A<X extends int, Y extends dynamic> { foo(X x, Y y) {} }
 ```
 
-- If a type parameter has a nullable bound or a bound that has `Nullability.neither`, and a type-parameter type referring that type parameter isn't marked with `?`, then that type-parameter type has `Nullability.neither`.  In the following example `X`, `Y`, and `Z` have `Nullability.neither` when used as types:
+- If a type parameter has a nullable bound or a bound that has `Nullability.undetermined`, and a type-parameter type referring that type parameter isn't marked with `?`, then that type-parameter type has `Nullability.undetermined`.  In the following example `X`, `Y`, and `Z` have `Nullability.undetermined` when used as types:
 
 ```dart
 // Note that 'Object?' is provided for the omitted bounds in opted-in libraries.
@@ -186,7 +192,7 @@
   return null;
 ```
 
-Note that `X` has `Nullability.neither` when used as a type in the right-hand side of the `typedef` declaration.  The return type of `foo` is `int? Function(String?)`, which is the result of substituting `X` with `int?` and `Y` with `String` in `X% Function(Y?)`.
+Note that `X` has `Nullability.undetermined` when used as a type in the right-hand side of the `typedef` declaration.  The return type of `foo` is `int? Function(String?)`, which is the result of substituting `X` with `int?` and `Y` with `String` in `X% Function(Y?)`.
 
 Obtaining the type for a type check, such as the is-check in the body of `foo` in the program fragment below, is an example where type substitution is needed at run time. 
 
@@ -196,7 +202,7 @@
 }
 ```
 
-The elements of the table that are marked with N/A correspond to cases that should be rejected by a type check.  The case for type argument having `Nullability.nullable` and the type parameter having `Nullability.nonNullable` should result in a type error because a nullable type can't be a subtype of a non-nullable type.  Similar is true for the argument that have `Nullability.neither` and the type parameter that have `Nullability.nonNullable` because at run time `Nullability.neither` can be replaced with `Nullability.nullable`.
+The elements of the table that are marked with N/A correspond to cases that should be rejected by a type check.  The case for type argument having `Nullability.nullable` and the type parameter having `Nullability.nonNullable` should result in a type error because a nullable type can't be a subtype of a non-nullable type.  Similar is true for the argument that have `Nullability.undetermined` and the type parameter that have `Nullability.nonNullable` because at run time `Nullability.undetermined` can be replaced with `Nullability.nullable`.
 
 The substitution routines in `pkg/kernel/lib/type_algebra.dart` follow the nullability computation rules described above.
 
@@ -214,7 +220,7 @@
 | * | N/A | N/A | * | N/A |
 | % | ! | % | N/A | % |
 
-In the table `!` denotes `Nullability.nonNullable`, `?` denotes `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes `Nullability.neither`.
+In the table `!` denotes `Nullability.nonNullable`, `?` denotes `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes `Nullability.undetermined`.
 
 The table elements marked with N/A represent combinations that can't be a part of a well-formed CFE output.  Some of them are due to the restriction on the intersection type that the RHS of the intersection should be a subtype of the bound of the type variable, and some others are due to the restriction that a nullable type is never promoted to an intersection type.
 
@@ -230,7 +236,7 @@
 }
 ```
 
-The type of the variable `t` in the example is promoted from `T` to `T & int?` because the RHS of the intersection, namely `int?`, is a subtype of the bound of `T`, which is `num?`.  In Kernel `T` has `Nullability.neither` because the bound of `T` is nullable, and the intersection type with the nullabilities of all its parts looks like `T% & int?`.  The following is the textual representation of the program from the example above compiled by the CFE.
+The type of the variable `t` in the example is promoted from `T` to `T & int?` because the RHS of the intersection, namely `int?`, is a subtype of the bound of `T`, which is `num?`.  In Kernel `T` has `Nullability.undetermined` because the bound of `T` is nullable, and the intersection type with the nullabilities of all its parts looks like `T% & int?`.  The following is the textual representation of the program from the example above compiled by the CFE.
 
 ```kernel
 library;
@@ -296,6 +302,11 @@
 - `IsSubtypeOf` class is added.  It represents a result of a nullability-aware type check.  Objects of `IsSubtypeOf` can further be queried for whether the checked types are in the subtype relation when the nullability modifiers are taken into account (using `IsSubtypeOf.isSubtypeWhenUsingNullabilities`) or when the modifiers are ignored (using `IsSubtypeOf.isSubtypeWhenIgnoringNullabilities`).
 - `SubtypeTester.performNullabilityAwareSubtypeCheck` method is added.  It takes two types as input and produces a result of type `IsSubtypeOf`.  Using `SubtypeTester.performNullabilityAwareSubtypeCheck` is recommended for performance considerations if a call site needs to differentiate between NNBD and pre-NNBD cases.
 
+#### Type Never
+
+* A new subclass of `DartType` called `NeverType` is added to represent type `Never`.  It is a subtype of all Dart types.  It's different from `BottomType` already present in Kernel; the latter is reserved for other purposes with the addition to the subtyping rules that `BottomType` is a subtype of `NeverType`.
+* `DartTypeVisitor` and `DartTypeVisitor1` visitors are updated to include `visitNeverType` methods.  All implementations of the interfaces of `DartTypeVisitor` and `DartTypeVisitor1` are updated to include implementations of `visitNeverType`.
+
 #### isRequired and isLate flags
 
 - `VariableDeclaration.isRequired` setter and getter are added.
@@ -371,6 +382,10 @@
 
 As described in section **Nullability of Intersection Types**, objects of `TypeParameterType` implement `.nullability` as a getter, not a field, and the overall nullability value for the type is not serialized in the binary format.  The back ends that implement their own deserialization may need to compute the nullability for `TypeParameterType`s.
 
+#### Implementing visitNeverType
+
+Following the introduction of `NeverType`, all implementors of `DartTypeVisitor` and `DartTypeVisitor1` should implement their new methods, `visitNeverType`.  Reasonable implementations are provided in the CL adding `NeverType`, and they might need to be revisited.
+
 #### Type equality
 
 *TODO: Update the section.*
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 399b75e..0b5196d 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -97,6 +97,12 @@
   /// (possibly synthesized) name, whereas other AST nodes return the complete
   /// textual representation of their subtree.
   String toString() => debugNodeToString(this);
+
+  /// Returns the textual representation of this node for use in debugging.
+  ///
+  /// Note that this adds some nodes to a static map to ensure consistent
+  /// naming, but that it thus also leaks memory.
+  String leakingDebugToString() => debugNodeToString(this);
 }
 
 /// A mutable AST node with a parent pointer.
@@ -190,7 +196,7 @@
   Uri get fileUri;
 }
 
-abstract class Annotatable {
+abstract class Annotatable extends TreeNode {
   List<Expression> get annotations;
   void addAnnotation(Expression node);
 }
@@ -312,7 +318,7 @@
 
   // TODO(jensj): Do we have a better option than this?
   static int defaultLanguageVersionMajor = 2;
-  static int defaultLanguageVersionMinor = 6;
+  static int defaultLanguageVersionMinor = 7;
 
   int _languageVersionMajor;
   int _languageVersionMinor;
@@ -980,7 +986,8 @@
   /// Internal. Should *ONLY* be used from within kernel.
   ///
   /// If non-null, the function that will have to be called to fill-out the
-  /// content of this class. Note that this should not be called directly though.
+  /// content of this class. Note that this should not be called directly
+  /// though.
   void Function() lazyBuilder;
 
   /// Makes sure the class is loaded, i.e. the fields, procedures etc have been
@@ -1646,7 +1653,7 @@
   bool get isMutable => flags & (FlagFinal | FlagConst) == 0;
   bool get isInstanceMember => !isStatic;
   bool get hasGetter => true;
-  bool get hasSetter => isMutable;
+  bool get hasSetter => isMutable || isLate && initializer == null;
 
   bool get isExternal => false;
   void set isExternal(bool value) {
@@ -1674,7 +1681,7 @@
   }
 
   DartType get getterType => type;
-  DartType get setterType => isMutable ? type : const BottomType();
+  DartType get setterType => hasSetter ? type : const BottomType();
 
   Location _getLocationInEnclosingFile(int offset) {
     return _getLocationInComponent(enclosingComponent, fileUri, offset);
@@ -4375,7 +4382,7 @@
   LoadLibrary(this.import);
 
   DartType getStaticType(TypeEnvironment types) {
-    return types.futureType(const DynamicType());
+    return types.futureType(const DynamicType(), Nullability.legacy);
   }
 
   R accept<R>(ExpressionVisitor<R> v) => v.visitLoadLibrary(this);
@@ -5159,6 +5166,19 @@
   /// positional parameters and local variables.
   bool get isRequired => flags & FlagRequired != 0;
 
+  /// Whether the variable is assignable.
+  ///
+  /// This is `true` if the variable is neither constant nor final, or if it
+  /// is late final without an initializer.
+  bool get isAssignable {
+    if (isConst) return false;
+    if (isFinal) {
+      if (isLate) return initializer == null;
+      return false;
+    }
+    return true;
+  }
+
   void set isFinal(bool value) {
     flags = value ? (flags | FlagFinal) : (flags & ~FlagFinal);
   }
@@ -5300,6 +5320,12 @@
   visitChildren(Visitor v) {
     // DESIGN TODO: Should we visit the library as a library reference?
   }
+
+  /// Returns the textual representation of this node for use in debugging.
+  ///
+  /// Note that this adds some nodes to a static map to ensure consistent
+  /// naming, but that it thus also leaks memory.
+  String leakingDebugToString() => debugNodeToString(this);
 }
 
 class _PrivateName extends Name {
@@ -5338,19 +5364,7 @@
 
 /// Represents nullability of a type.
 enum Nullability {
-  /// Nullable types are marked with the '?' modifier.
-  ///
-  /// Null, dynamic, and void are nullable by default.
-  nullable,
-
-  /// Non-nullable types are types that aren't marked with the '?' modifier.
-  ///
-  /// Note that Null, dynamic, and void that are nullable by default.  Note also
-  /// that some types denoted by a type parameter without the '?' modifier can
-  /// be something else rather than non-nullable.
-  nonNullable,
-
-  /// Non-legacy types that are neither nullable, nor non-nullable.
+  /// Non-legacy types not known to be nullable or non-nullable statically.
   ///
   /// An example of such type is type T in the example below.  Note that both
   /// int and int? can be passed in for T, so an attempt to assign null to x is
@@ -5362,7 +5376,19 @@
   ///       Object y = x;  // Compile-time error.
   ///     }
   ///   }
-  neither,
+  undetermined,
+
+  /// Nullable types are marked with the '?' modifier.
+  ///
+  /// Null, dynamic, and void are nullable by default.
+  nullable,
+
+  /// Non-nullable types are types that aren't marked with the '?' modifier.
+  ///
+  /// Note that Null, dynamic, and void that are nullable by default.  Note also
+  /// that some types denoted by a type parameter without the '?' modifier can
+  /// be something else rather than non-nullable.
+  nonNullable,
 
   /// Types in opt-out libraries are 'legacy' types.
   ///
@@ -5406,6 +5432,24 @@
   /// Some types have fixed nullabilities, such as `dynamic`, `invalid-type`,
   /// `void`, or `bottom`.
   DartType withNullability(Nullability nullability);
+
+  /// Checks if the type is potentially nullable.
+  ///
+  /// A type is potentially nullable if it's nullable or if it's nullability is
+  /// undetermined at compile time.
+  bool get isPotentiallyNullable {
+    return nullability == Nullability.nullable ||
+        nullability == Nullability.undetermined;
+  }
+
+  /// Checks if the type is potentially non-nullable.
+  ///
+  /// A type is potentially non-nullable if it's nullable or if it's nullability
+  /// is undetermined at compile time.
+  bool get isPotentiallyNonNullable {
+    return nullability == Nullability.nonNullable ||
+        nullability == Nullability.undetermined;
+  }
 }
 
 /// The type arising from invalid type annotations.
@@ -5463,6 +5507,29 @@
   VoidType withNullability(Nullability nullability) => this;
 }
 
+class NeverType extends DartType {
+  final Nullability nullability;
+
+  const NeverType(this.nullability);
+
+  int get hashCode {
+    return 485786 ^ ((0x33333333 >> nullability.index) ^ 0x33333333);
+  }
+
+  R accept<R>(DartTypeVisitor<R> v) => v.visitNeverType(this);
+  R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) =>
+      v.visitNeverType(this, arg);
+  visitChildren(Visitor v) {}
+
+  bool operator ==(Object other) {
+    return other is NeverType && nullability == other.nullability;
+  }
+
+  NeverType withNullability(Nullability nullability) {
+    return this.nullability == nullability ? this : new NeverType(nullability);
+  }
+}
+
 class BottomType extends DartType {
   final int hashCode = 514213;
 
@@ -5522,6 +5589,7 @@
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
     if (other is InterfaceType) {
+      if (nullability != other.nullability) return false;
       if (className != other.className) return false;
       if (typeArguments.length != other.typeArguments.length) return false;
       for (int i = 0; i < typeArguments.length; ++i) {
@@ -5538,6 +5606,8 @@
     for (int i = 0; i < typeArguments.length; ++i) {
       hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
     }
+    int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
+    hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
     return hash;
   }
 
@@ -5591,6 +5661,7 @@
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
     if (other is FunctionType) {
+      if (nullability != other.nullability) return false;
       if (typeParameters.length != other.typeParameters.length ||
           requiredParameterCount != other.requiredParameterCount ||
           positionalParameters.length != other.positionalParameters.length ||
@@ -5675,6 +5746,7 @@
       // Remove the type parameters from the scope again.
       _temporaryHashCodeTable.remove(typeParameters[i]);
     }
+    hash = 0x3fffffff & (hash * 31 + nullability.index);
     return hash;
   }
 
@@ -5720,9 +5792,10 @@
   }
 
   DartType get unaliasOnce {
-    return Substitution.fromTypedefType(this)
-        .substituteType(typedefNode.type)
-        .withNullability(nullability);
+    DartType result =
+        Substitution.fromTypedefType(this).substituteType(typedefNode.type);
+    return result.withNullability(
+        combineNullabilitiesForSubstitution(result.nullability, nullability));
   }
 
   DartType get unalias {
@@ -5732,6 +5805,7 @@
   bool operator ==(Object other) {
     if (identical(this, other)) return true;
     if (other is TypedefType) {
+      if (nullability != other.nullability) return false;
       if (typedefReference != other.typedefReference ||
           typeArguments.length != other.typeArguments.length) {
         return false;
@@ -5749,6 +5823,8 @@
     for (int i = 0; i < typeArguments.length; ++i) {
       hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
     }
+    int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
+    hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
     return hash;
   }
 
@@ -5839,10 +5915,17 @@
   visitChildren(Visitor v) {}
 
   bool operator ==(Object other) {
-    return other is TypeParameterType && parameter == other.parameter;
+    return other is TypeParameterType &&
+        parameter == other.parameter &&
+        nullability == other.nullability;
   }
 
-  int get hashCode => _temporaryHashCodeTable[parameter] ?? parameter.hashCode;
+  int get hashCode {
+    int hash = _temporaryHashCodeTable[parameter] ?? parameter.hashCode;
+    int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
+    hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
+    return hash;
+  }
 
   /// Returns the bound of the type parameter, accounting for promotions.
   DartType get bound => promotedBound ?? parameter.bound;
@@ -5853,10 +5936,10 @@
   /// nullability of [promotedBound] if it's present.
   ///
   /// For example, in the following program [typeParameterTypeNullability] of
-  /// both `x` and `y` is [Nullability.neither], because it's copied from that
-  /// of `bar` and T has a nullable type as its bound.  However, despite
-  /// [nullability] of `x` is [Nullability.neither], [nullability] of `y` is
-  /// [Nullability.nonNullable] because of its [promotedBound].
+  /// both `x` and `y` is [Nullability.undetermined], because it's copied from
+  /// that of `bar` and T has a nullable type as its bound.  However, despite
+  /// [nullability] of `x` is [Nullability.undetermined], [nullability] of `y`
+  /// is [Nullability.nonNullable] because of its [promotedBound].
   ///
   ///     class A<T extends Object?> {
   ///       foo(T bar) {
@@ -5891,19 +5974,19 @@
   /// is changing or is being set for the first time, and the update on some
   /// type-parameter types is required.
   static Nullability computeNullabilityFromBound(TypeParameter typeParameter) {
-    // If the bound is nullable or 'neither', both nullable and non-nullable
-    // types can be passed in for the type parameter, making the corresponding
-    // type parameter types 'neither.'  Otherwise, the nullability matches that
-    // of the bound.
+    // If the bound is nullable or 'undetermined', both nullable and
+    // non-nullable types can be passed in for the type parameter, making the
+    // corresponding type parameter types 'undetermined.'  Otherwise, the
+    // nullability matches that of the bound.
     DartType bound = typeParameter.bound;
     if (bound == null) {
       throw new StateError("Can't compute nullability from an absent bound.");
     }
     Nullability boundNullability =
-        bound is InvalidType ? Nullability.neither : bound.nullability;
+        bound is InvalidType ? Nullability.undetermined : bound.nullability;
     return boundNullability == Nullability.nullable ||
-            boundNullability == Nullability.neither
-        ? Nullability.neither
+            boundNullability == Nullability.undetermined
+        ? Nullability.undetermined
         : boundNullability;
   }
 
@@ -5940,7 +6023,7 @@
     //
     // In the table, LHS corresponds to lhsNullability in the code below; RHS
     // corresponds to promotedBound.nullability; !, ?, *, and % correspond to
-    // nonNullable, nullable, legacy, and neither values of the Nullability
+    // nonNullable, nullable, legacy, and undetermined values of the Nullability
     // enum.
     //
     // Whenever there's N/A in the table, it means that the corresponding
@@ -5965,8 +6048,8 @@
       return Nullability.nonNullable;
     }
 
-    // If the nullability of LHS is 'neither,' the nullability of the
-    // intersection is also 'neither' if RHS is 'neither' or nullable.
+    // If the nullability of LHS is 'undetermined', the nullability of the
+    // intersection is also 'undetermined' if RHS is 'undetermined' or nullable.
     //
     // Consider the following example:
     //
@@ -5982,9 +6065,9 @@
     //         }
     //       }
     //     }
-    if (lhsNullability == Nullability.neither ||
-        promotedBound.nullability == Nullability.neither) {
-      return Nullability.neither;
+    if (lhsNullability == Nullability.undetermined ||
+        promotedBound.nullability == Nullability.undetermined) {
+      return Nullability.undetermined;
     }
 
     return Nullability.legacy;
@@ -6082,6 +6165,19 @@
       return unrelated;
     }
   }
+
+  // Returns the keyword lexeme associated with the variance given.
+  static String keywordString(int variance) {
+    switch (variance) {
+      case Variance.contravariant:
+        return 'in';
+      case Variance.invariant:
+        return 'inout';
+      case Variance.covariant:
+      default:
+        return 'out';
+    }
+  }
 }
 
 /// Declaration of a type variable.
@@ -6118,10 +6214,20 @@
   DartType defaultType;
 
   /// Describes variance of the type parameter w.r.t. declaration on which it is
-  /// defined.  It's always [Variance.covariant] for classes, and for typedefs
-  /// it's the variance of the type parameters in the type term on the r.h.s. of
-  /// the typedef.
-  int variance = Variance.covariant;
+  /// defined. For classes, if variance is not explicitly set, the type
+  /// parameter has legacy covariance defined by [isLegacyCovariant] which
+  /// on the lattice is equivalent to [Variance.covariant]. For typedefs, it's
+  /// the variance of the type parameters in the type term on the r.h.s. of the
+  /// typedef.
+  int _variance;
+
+  int get variance => _variance ?? Variance.covariant;
+
+  void set variance(int newVariance) => _variance = newVariance;
+
+  bool get isLegacyCovariant => _variance == null;
+
+  static const int legacyCovariantSerializationMarker = 4;
 
   TypeParameter([this.name, this.bound, this.defaultType]);
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index dbfb0a4..11695a2 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -9,7 +9,6 @@
 import 'dart:typed_data';
 
 import '../ast.dart';
-import '../src/bounds_checks.dart' show computeVariance;
 import '../transformations/flags.dart';
 import 'tag.dart';
 
@@ -73,6 +72,7 @@
   final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
   final List<LabeledStatement> labelStack = <LabeledStatement>[];
   int labelStackBase = 0;
+  int switchCaseStackBase = 0;
   final List<SwitchCase> switchCaseStack = <SwitchCase>[];
   final List<TypeParameter> typeParameterStack = <TypeParameter>[];
   final String filename;
@@ -1057,10 +1057,6 @@
     node.namedParameters.addAll(readAndPushVariableDeclarationList());
     typeParameterStack.length = 0;
     variableStack.length = 0;
-    for (int i = 0; i < node.typeParameters.length; ++i) {
-      node.typeParameters[i].variance =
-          computeVariance(node.typeParameters[i], type);
-    }
     if (shouldWriteData) {
       node.fileOffset = fileOffset;
       node.name = name;
@@ -1509,6 +1505,7 @@
     var named = readAndPushVariableDeclarationList();
     var returnType = readDartType();
     int oldLabelStackBase = labelStackBase;
+    int oldSwitchCaseStackBase = switchCaseStackBase;
 
     if (lazyLoadBody && outerEndOffset > 0) {
       lazyLoadBody = outerEndOffset - _byteOffset >
@@ -1518,6 +1515,7 @@
     var body;
     if (!lazyLoadBody) {
       labelStackBase = labelStack.length;
+      switchCaseStackBase = switchCaseStack.length;
       body = readStatementOption();
     }
 
@@ -1533,18 +1531,20 @@
       ..fileEndOffset = endOffset;
 
     if (lazyLoadBody) {
-      _setLazyLoadFunction(result, oldLabelStackBase, variableStackHeight);
+      _setLazyLoadFunction(result, oldLabelStackBase, oldSwitchCaseStackBase,
+          variableStackHeight);
     }
 
     labelStackBase = oldLabelStackBase;
+    switchCaseStackBase = oldSwitchCaseStackBase;
     variableStack.length = variableStackHeight;
     typeParameterStack.length = typeParameterStackHeight;
 
     return result;
   }
 
-  void _setLazyLoadFunction(
-      FunctionNode result, int oldLabelStackBase, int variableStackHeight) {
+  void _setLazyLoadFunction(FunctionNode result, int oldLabelStackBase,
+      int oldSwitchCaseStackBase, int variableStackHeight) {
     final int savedByteOffset = _byteOffset;
     final int componentStartOffset = _componentStartOffset;
     final List<TypeParameter> typeParameters = typeParameterStack.toList();
@@ -1562,6 +1562,7 @@
       result.body = readStatementOption();
       result.body?.parent = result;
       labelStackBase = oldLabelStackBase;
+      switchCaseStackBase = oldSwitchCaseStackBase;
       variableStack.length = variableStackHeight;
       typeParameterStack.clear();
       if (result.parent is Procedure) {
@@ -2012,7 +2013,8 @@
       case Tag.ContinueSwitchStatement:
         int offset = readOffset();
         int index = readUInt();
-        return new ContinueSwitchStatement(switchCaseStack[index])
+        return new ContinueSwitchStatement(
+            switchCaseStack[switchCaseStackBase + index])
           ..fileOffset = offset;
       case Tag.IfStatement:
         int offset = readOffset();
@@ -2163,6 +2165,9 @@
         return const DynamicType();
       case Tag.VoidType:
         return const VoidType();
+      case Tag.NeverType:
+        int nullabilityIndex = readByte();
+        return new NeverType(Nullability.values[nullabilityIndex]);
       case Tag.InterfaceType:
         int nullabilityIndex = readByte();
         return new InterfaceType.byReference(readClassReference(),
@@ -2231,7 +2236,12 @@
   void readTypeParameter(TypeParameter node) {
     node.flags = readByte();
     node.annotations = readAnnotationList(node);
-    node.variance = readByte();
+    int variance = readByte();
+    if (variance == TypeParameter.legacyCovariantSerializationMarker) {
+      node.variance = null;
+    } else {
+      node.variance = variance;
+    }
     node.name = readStringOrNullIfEmpty();
     node.bound = readDartType();
     node.defaultType = readDartTypeOption();
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index babd66e..da2fd24 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -2025,6 +2025,12 @@
   }
 
   @override
+  void visitNeverType(NeverType node) {
+    writeByte(Tag.NeverType);
+    writeByte(node.nullability.index);
+  }
+
+  @override
   void visitInvalidType(InvalidType node) {
     writeByte(Tag.InvalidType);
   }
@@ -2125,7 +2131,11 @@
   void visitTypeParameter(TypeParameter node) {
     writeByte(node.flags);
     writeAnnotationList(node.annotations);
-    writeByte(node.variance);
+    if (node.isLegacyCovariant) {
+      writeByte(TypeParameter.legacyCovariantSerializationMarker);
+    } else {
+      writeByte(node.variance);
+    }
     writeStringReference(node.name ?? '');
     writeNode(node.bound);
     writeOptionalNode(node.defaultType);
@@ -2163,57 +2173,68 @@
   // during serialization is an error.
   @override
   void defaultNode(Node node) {
-    throw new UnsupportedError('serialization of generic Nodes');
+    throw new UnsupportedError(
+        'serialization of generic Node: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultConstant(Constant node) {
-    throw new UnsupportedError('serialization of generic Constants');
+    throw new UnsupportedError(
+        'serialization of generic Constant: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultBasicLiteral(BasicLiteral node) {
-    throw new UnsupportedError('serialization of generic BasicLiterals');
+    throw new UnsupportedError(
+        'serialization of generic BasicLiteral: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultConstantReference(Constant node) {
-    throw new UnsupportedError('serialization of generic Constant references');
+    throw new UnsupportedError('serialization of generic Constant reference: '
+        '${node} (${node.runtimeType})');
   }
 
   @override
   void defaultDartType(DartType node) {
-    throw new UnsupportedError('serialization of generic DartTypes');
+    throw new UnsupportedError(
+        'serialization of generic DartType: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultExpression(Expression node) {
-    throw new UnsupportedError('serialization of generic Expressions');
+    throw new UnsupportedError(
+        'serialization of generic Expression: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultInitializer(Initializer node) {
-    throw new UnsupportedError('serialization of generic Initializers');
+    throw new UnsupportedError(
+        'serialization of generic Initializer: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultMember(Member node) {
-    throw new UnsupportedError('serialization of generic Members');
+    throw new UnsupportedError(
+        'serialization of generic Member: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultMemberReference(Member node) {
-    throw new UnsupportedError('serialization of generic Member references');
+    throw new UnsupportedError('serialization of generic Member reference: '
+        '${node} (${node.runtimeType})');
   }
 
   @override
   void defaultStatement(Statement node) {
-    throw new UnsupportedError('serialization of generic Statements');
+    throw new UnsupportedError(
+        'serialization of generic Statement: ${node} (${node.runtimeType})');
   }
 
   @override
   void defaultTreeNode(TreeNode node) {
-    throw new UnsupportedError('serialization of generic TreeNodes');
+    throw new UnsupportedError(
+        'serialization of generic TreeNode: ${node} (${node.runtimeType})');
   }
 
   @override
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 230688a..00e609f 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -119,6 +119,7 @@
   static const int TypeParameterType = 95;
   static const int SimpleInterfaceType = 96;
   static const int SimpleFunctionType = 97;
+  static const int NeverType = 98;
 
   static const int ConstantExpression = 106;
 
@@ -148,7 +149,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 = 35;
+  static const int BinaryFormatVersion = 36;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 9e3dea1..d18d3aa 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -488,7 +488,7 @@
         return objectNullableRawType;
       case Nullability.nonNullable:
         return objectNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -525,7 +525,7 @@
         return boolNullableRawType;
       case Nullability.nonNullable:
         return boolNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -556,7 +556,7 @@
         return intNullableRawType;
       case Nullability.nonNullable:
         return intNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -587,7 +587,7 @@
         return numNullableRawType;
       case Nullability.nonNullable:
         return numNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -619,7 +619,7 @@
         return doubleNullableRawType;
       case Nullability.nonNullable:
         return doubleNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -651,7 +651,7 @@
         return stringNullableRawType;
       case Nullability.nonNullable:
         return stringNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -684,7 +684,7 @@
         return listNullableRawType;
       case Nullability.nonNullable:
         return listNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -717,7 +717,7 @@
         return setNullableRawType;
       case Nullability.nonNullable:
         return setNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -756,7 +756,7 @@
         return mapNullableRawType;
       case Nullability.nonNullable:
         return mapNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -789,7 +789,7 @@
         return iterableNullableRawType;
       case Nullability.nonNullable:
         return iterableNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -822,7 +822,7 @@
         return iteratorNullableRawType;
       case Nullability.nonNullable:
         return iteratorNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -854,7 +854,7 @@
         return symbolNullableRawType;
       case Nullability.nonNullable:
         return symbolNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -885,7 +885,7 @@
         return typeNullableRawType;
       case Nullability.nonNullable:
         return typeNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -918,7 +918,7 @@
         return functionNullableRawType;
       case Nullability.nonNullable:
         return functionNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -951,7 +951,7 @@
         return invocationNullableRawType;
       case Nullability.nonNullable:
         return invocationNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -984,7 +984,7 @@
         return invocationMirrorNullableRawType;
       case Nullability.nonNullable:
         return invocationMirrorNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1017,7 +1017,7 @@
         return futureNullableRawType;
       case Nullability.nonNullable:
         return futureNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1050,7 +1050,7 @@
         return stackTraceNullableRawType;
       case Nullability.nonNullable:
         return stackTraceNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1083,7 +1083,7 @@
         return streamNullableRawType;
       case Nullability.nonNullable:
         return streamNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1122,7 +1122,7 @@
         return asyncAwaitCompleterNullableRawType;
       case Nullability.nonNullable:
         return asyncAwaitCompleterNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1155,7 +1155,7 @@
         return futureOrNullableRawType;
       case Nullability.nonNullable:
         return futureOrNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1187,7 +1187,7 @@
         return pragmaNullableRawType;
       case Nullability.nonNullable:
         return pragmaNonNullableRawType;
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
@@ -1229,7 +1229,7 @@
         return nullableRawType(klass);
       case Nullability.nonNullable:
         return nonNullableRawType(klass);
-      case Nullability.neither:
+      case Nullability.undetermined:
       default:
         throw new StateError(
             "Unsupported nullability $nullability on an InterfaceType.");
diff --git a/pkg/kernel/lib/import_table.dart b/pkg/kernel/lib/import_table.dart
index f549933..06d9051 100644
--- a/pkg/kernel/lib/import_table.dart
+++ b/pkg/kernel/lib/import_table.dart
@@ -75,6 +75,7 @@
 
   void addLibraryImport(Library target) {
     if (target == referenceLibrary) return; // Self-reference is special.
+    if (target == null) return;
     var referenceUri = referenceLibrary.importUri;
     var targetUri = target.importUri;
     if (targetUri == null) {
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index d4e2d21..2710985 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -12,8 +12,10 @@
         InterfaceType,
         InvalidType,
         NamedType,
+        NeverType,
         TypeParameter,
         TypeParameterType,
+        Typedef,
         TypedefType,
         Variance,
         VoidType;
@@ -24,7 +26,7 @@
 
 import '../util/graph.dart' show Graph, computeStrongComponents;
 
-import '../visitor.dart' show DartTypeVisitor;
+import '../visitor.dart' show DartTypeVisitor, DartTypeVisitor1;
 
 class TypeVariableGraph extends Graph<int> {
   List<int> vertices;
@@ -473,57 +475,97 @@
       type.classNode == typeEnvironment.nullType.classNode;
 }
 
-int computeVariance(TypeParameter typeParameter, DartType type) {
-  return type.accept(new VarianceCalculator(typeParameter));
+int computeVariance(TypeParameter typeParameter, DartType type,
+    {Map<TypeParameter, Map<DartType, int>> computedVariances}) {
+  computedVariances ??= new Map<TypeParameter, Map<DartType, int>>.identity();
+  computedVariances[typeParameter] ??= new Map<DartType, int>.identity();
+
+  int variance = computedVariances[typeParameter][type];
+  if (variance != null) return variance;
+  computedVariances[typeParameter][type] = VarianceCalculator._visitMarker;
+
+  return computedVariances[typeParameter][type] =
+      type.accept1(new VarianceCalculator(typeParameter), computedVariances);
 }
 
-class VarianceCalculator implements DartTypeVisitor<int> {
+class VarianceCalculator
+    implements DartTypeVisitor1<int, Map<TypeParameter, Map<DartType, int>>> {
   final TypeParameter typeParameter;
 
+  static const int _visitMarker = -2;
+
   VarianceCalculator(this.typeParameter);
 
   @override
-  int defaultDartType(DartType node) => Variance.unrelated;
+  int defaultDartType(
+      DartType node, Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    throw new StateError("Unhandled ${node.runtimeType} "
+        "when computing variance of a type parameter.");
+  }
 
   @override
-  int visitTypeParameterType(TypeParameterType node) {
+  int visitTypeParameterType(TypeParameterType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
     if (node.parameter == typeParameter) return Variance.covariant;
     return Variance.unrelated;
   }
 
   @override
-  int visitInterfaceType(InterfaceType node) {
-    int result = Variance.unrelated;
-    for (DartType argument in node.typeArguments) {
-      result = Variance.meet(result, argument.accept(this));
-    }
-    return result;
-  }
-
-  @override
-  int visitTypedefType(TypedefType node) {
+  int visitInterfaceType(InterfaceType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
     int result = Variance.unrelated;
     for (int i = 0; i < node.typeArguments.length; ++i) {
       result = Variance.meet(
           result,
           Variance.combine(
-              node.typeArguments[i].accept(this),
-              node.typedefNode.type.accept(
-                  new VarianceCalculator(node.typedefNode.typeParameters[i]))));
+              node.classNode.typeParameters[i].variance,
+              computeVariance(typeParameter, node.typeArguments[i],
+                  computedVariances: computedVariances)));
     }
     return result;
   }
 
   @override
-  int visitFunctionType(FunctionType node) {
+  int visitTypedefType(TypedefType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
     int result = Variance.unrelated;
-    result = Variance.meet(result, node.returnType.accept(this));
+    for (int i = 0; i < node.typeArguments.length; ++i) {
+      Typedef typedefNode = node.typedefNode;
+      TypeParameter typedefTypeParameter = typedefNode.typeParameters[i];
+      if (computedVariances.containsKey(typedefTypeParameter) &&
+          computedVariances[typedefTypeParameter][typedefNode.type] ==
+              _visitMarker) {
+        throw new StateError("The typedef '${node.typedefNode.name}' "
+            "has a reference to itself.");
+      }
+
+      result = Variance.meet(
+          result,
+          Variance.combine(
+              computeVariance(typeParameter, node.typeArguments[i],
+                  computedVariances: computedVariances),
+              computeVariance(typedefTypeParameter, typedefNode.type,
+                  computedVariances: computedVariances)));
+    }
+    return result;
+  }
+
+  @override
+  int visitFunctionType(FunctionType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    int result = Variance.unrelated;
+    result = Variance.meet(
+        result,
+        computeVariance(typeParameter, node.returnType,
+            computedVariances: computedVariances));
     for (TypeParameter functionTypeParameter in node.typeParameters) {
       // If [typeParameter] is referenced in the bound at all, it makes the
       // variance of [typeParameter] in the entire type invariant.  The
       // invocation of the visitor below is made to simply figure out if
       // [typeParameter] occurs in the bound.
-      if (functionTypeParameter.bound.accept(this) != Variance.unrelated) {
+      if (computeVariance(typeParameter, functionTypeParameter.bound,
+              computedVariances: computedVariances) !=
+          Variance.unrelated) {
         result = Variance.invariant;
       }
     }
@@ -531,26 +573,48 @@
       result = Variance.meet(
           result,
           Variance.combine(
-              Variance.contravariant, positionalType.accept(this)));
+              Variance.contravariant,
+              computeVariance(typeParameter, positionalType,
+                  computedVariances: computedVariances)));
     }
     for (NamedType namedType in node.namedParameters) {
       result = Variance.meet(
           result,
           Variance.combine(
-              Variance.contravariant, namedType.type.accept(this)));
+              Variance.contravariant,
+              computeVariance(typeParameter, namedType.type,
+                  computedVariances: computedVariances)));
     }
     return result;
   }
 
   @override
-  int visitBottomType(BottomType node) => defaultDartType(node);
+  int visitBottomType(BottomType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    return Variance.unrelated;
+  }
 
   @override
-  int visitVoidType(VoidType node) => defaultDartType(node);
+  int visitNeverType(NeverType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    return Variance.unrelated;
+  }
 
   @override
-  int visitDynamicType(DynamicType node) => defaultDartType(node);
+  int visitVoidType(
+      VoidType node, Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    return Variance.unrelated;
+  }
 
   @override
-  int visitInvalidType(InvalidType node) => defaultDartType(node);
+  int visitDynamicType(DynamicType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    return Variance.unrelated;
+  }
+
+  @override
+  int visitInvalidType(InvalidType node,
+      Map<TypeParameter, Map<DartType, int>> computedVariances) {
+    return Variance.unrelated;
+  }
 }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 8f6d44e..750cc48 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -466,6 +466,10 @@
         Library nodeLibrary = node.enclosingLibrary;
         String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
         write(prefix + '::' + node.name);
+      } else if (node is Extension) {
+        Library nodeLibrary = node.enclosingLibrary;
+        String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
+        write(prefix + '::' + node.name);
       } else if (node is Field) {
         Library nodeLibrary = node.enclosingLibrary;
         String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
@@ -2063,7 +2067,7 @@
           state = WORD; // Disallow a word immediately after the '?'.
         }
         break;
-      case Nullability.neither:
+      case Nullability.undetermined:
         writeSymbol('%');
         if (!inComment) {
           state = WORD; // Disallow a word immediately after the '%'.
@@ -2079,7 +2083,7 @@
 
   void writeDartTypeNullability(DartType type, {bool inComment = false}) {
     if (type is InvalidType) {
-      writeNullability(Nullability.neither);
+      writeNullability(Nullability.undetermined);
     } else {
       writeNullability(type.nullability, inComment: inComment);
     }
@@ -2097,6 +2101,11 @@
     writeWord('void');
   }
 
+  visitNeverType(NeverType node) {
+    write('Never');
+    writeNullability(node.nullability);
+  }
+
   visitInterfaceType(InterfaceType node) {
     writeClassReferenceFromReference(node.className);
     if (node.typeArguments.isNotEmpty) {
diff --git a/pkg/kernel/lib/text/text_serialization_verifier.dart b/pkg/kernel/lib/text/text_serialization_verifier.dart
index f381ec2..4b7eff8 100644
--- a/pkg/kernel/lib/text/text_serialization_verifier.dart
+++ b/pkg/kernel/lib/text/text_serialization_verifier.dart
@@ -474,6 +474,12 @@
   }
 
   @override
+  void visitNeverType(NeverType node) {
+    storeLastSeenUriAndOffset(node);
+    makeDartTypeRoundTrip(node);
+  }
+
+  @override
   void visitVoidType(VoidType node) {
     storeLastSeenUriAndOffset(node);
     makeDartTypeRoundTrip(node);
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 5081b9e..2aa31c6 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -200,6 +200,7 @@
             dst.namedParameters[j].flags = src.namedParameters[j].flags;
           }
 
+          originalProcedure.canonicalName?.unbind();
           class_.procedures[i] = clone;
           continue outer;
         }
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index cb25f2c..f1d903e 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -394,6 +394,50 @@
   }
 }
 
+/// Combines nullabilities of types during type substitution.
+///
+/// In a type substitution, for example, when `int` is substituted for `T` in
+/// `List<T?>`, the nullability of the occurrence of the type parameter should
+/// be combined with the nullability of the type that is being substituted for
+/// that type parameter.  In the example above it's the nullability of `T?`
+/// and `int`.  The function computes the nullability for the replacement as
+/// per the following table:
+///
+/// | arg \ var |  !  |  ?  |  *  |  %  |
+/// |-----------|-----|-----|-----|-----|
+/// |     !     |  !  |  ?  |  *  |  !  |
+/// |     ?     | N/A |  ?  |  ?  |  ?  |
+/// |     *     |  *  |  ?  |  *  |  *  |
+/// |     %     | N/A |  ?  |  *  |  %  |
+///
+/// Here `!` denotes `Nullability.nonNullable`, `?` denotes
+/// `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes
+/// `Nullability.neither`.  The table elements marked with N/A denote the
+/// cases that should yield a type error before the substitution is performed.
+Nullability combineNullabilitiesForSubstitution(Nullability a, Nullability b) {
+  // In the table above we may extend the function given by it, replacing N/A
+  // with whatever is easier to implement.  In this implementation, we extend
+  // the table function as follows:
+  //
+  // | arg \ var |  !  |  ?  |  *  |  %  |
+  // |-----------|-----|-----|-----|-----|
+  // |     !     |  !  |  ?  |  *  |  !  |
+  // |     ?     |  ?  |  ?  |  ?  |  ?  |
+  // |     *     |  *  |  ?  |  *  |  *  |
+  // |     %     |  %  |  ?  |  *  |  %  |
+  //
+
+  if (a == Nullability.nullable || b == Nullability.nullable) {
+    return Nullability.nullable;
+  }
+
+  if (a == Nullability.legacy || b == Nullability.legacy) {
+    return Nullability.legacy;
+  }
+
+  return a;
+}
+
 abstract class _TypeSubstitutor extends DartTypeVisitor<DartType> {
   final _TypeSubstitutor outer;
   bool covariantContext = true;
@@ -441,6 +485,7 @@
   DartType visitDynamicType(DynamicType node) => node;
   DartType visitVoidType(VoidType node) => node;
   DartType visitBottomType(BottomType node) => node;
+  DartType visitNeverType(NeverType node) => node;
 
   DartType visitInterfaceType(InterfaceType node) {
     if (node.typeArguments.isEmpty) return node;
@@ -530,51 +575,6 @@
     return null;
   }
 
-  /// Combines nullabilities of types during type substitution.
-  ///
-  /// In a type substitution, for example, when `int` is substituted for `T` in
-  /// `List<T?>`, the nullability of the occurrence of the type parameter should
-  /// be combined with the nullability of the type that is being substituted for
-  /// that type parameter.  In the example above it's the nullability of `T?`
-  /// and `int`.  The function computes the nullability for the replacement as
-  /// per the following table:
-  ///
-  /// | arg \ var |  !  |  ?  |  *  |  %  |
-  /// |-----------|-----|-----|-----|-----|
-  /// |     !     |  !  |  ?  |  *  |  !  |
-  /// |     ?     | N/A |  ?  |  ?  |  ?  |
-  /// |     *     |  *  |  ?  |  *  |  *  |
-  /// |     %     | N/A |  ?  |  *  |  %  |
-  ///
-  /// Here `!` denotes `Nullability.nonNullable`, `?` denotes
-  /// `Nullability.nullable`, `*` denotes `Nullability.legacy`, and `%` denotes
-  /// `Nullability.neither`.  The table elements marked with N/A denote the
-  /// cases that should yield a type error before the substitution is performed.
-  static Nullability combineNullabilitiesForSubstitution(
-      Nullability a, Nullability b) {
-    // In the table above we may extend the function given by it, replacing N/A
-    // with whatever is easier to implement.  In this implementation, we extend
-    // the table function as follows:
-    //
-    // | arg \ var |  !  |  ?  |  *  |  %  |
-    // |-----------|-----|-----|-----|-----|
-    // |     !     |  !  |  ?  |  *  |  !  |
-    // |     ?     |  ?  |  ?  |  ?  |  ?  |
-    // |     *     |  *  |  ?  |  *  |  *  |
-    // |     %     |  %  |  ?  |  *  |  %  |
-    //
-
-    if (a == Nullability.nullable || b == Nullability.nullable) {
-      return Nullability.nullable;
-    }
-
-    if (a == Nullability.legacy || b == Nullability.legacy) {
-      return Nullability.legacy;
-    }
-
-    return a;
-  }
-
   DartType visitTypeParameterType(TypeParameterType node) {
     DartType replacement = getSubstitute(node.parameter);
     if (replacement is InvalidType) return replacement;
@@ -795,6 +795,7 @@
   }
 
   bool visitBottomType(BottomType node) => false;
+  bool visitNeverType(NeverType node) => false;
   bool visitInvalidType(InvalidType node) => false;
   bool visitDynamicType(DynamicType node) => false;
   bool visitVoidType(VoidType node) => false;
@@ -842,6 +843,7 @@
   }
 
   bool visitBottomType(BottomType node) => false;
+  bool visitNeverType(NeverType node) => false;
   bool visitInvalidType(InvalidType node) => false;
   bool visitDynamicType(DynamicType node) => false;
   bool visitVoidType(VoidType node) => false;
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index a0f364a..6024d89 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -815,7 +815,7 @@
 
   @override
   DartType visitLoadLibrary(LoadLibrary node) {
-    return environment.futureType(const DynamicType());
+    return environment.futureType(const DynamicType(), Nullability.legacy);
   }
 
   @override
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index d872d55..de454c1 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -34,9 +34,12 @@
 
   Class get intClass => coreTypes.intClass;
   Class get numClass => coreTypes.numClass;
+  Class get functionClass => coreTypes.functionClass;
   Class get futureOrClass => coreTypes.futureOrClass;
+  Class get objectClass => coreTypes.objectClass;
 
   InterfaceType get objectLegacyRawType => coreTypes.objectLegacyRawType;
+  InterfaceType get objectNullableRawType => coreTypes.objectNullableRawType;
   InterfaceType get nullType => coreTypes.nullType;
   InterfaceType get functionLegacyRawType => coreTypes.functionLegacyRawType;
 
@@ -60,8 +63,10 @@
     return new InterfaceType(coreTypes.streamClass, <DartType>[type]);
   }
 
-  InterfaceType futureType(DartType type) {
-    return new InterfaceType(coreTypes.futureClass, <DartType>[type]);
+  InterfaceType futureType(DartType type,
+      [Nullability nullability = Nullability.legacy]) {
+    return new InterfaceType(
+        coreTypes.futureClass, <DartType>[type], nullability);
   }
 
   /// Removes a level of `Future<>` types wrapping a type.
@@ -135,18 +140,19 @@
   /// Otherwise `num` is returned.
   DartType getTypeOfOverloadedArithmetic(DartType type1, DartType type2) {
     if (type1 == type2) return type1;
-    if (type1 == coreTypes.doubleLegacyRawType ||
-        type2 == coreTypes.doubleLegacyRawType)
-      return coreTypes.doubleLegacyRawType;
-    return coreTypes.numLegacyRawType;
-  }
-}
 
-/// The value enum for internal states of [IsSubtypeOf].
-enum _IsSubtypeOfValues {
-  always,
-  onlyIfIgnoringNullabilities,
-  never,
+    if (type1 is InterfaceType && type2 is InterfaceType) {
+      if (type1.classNode == type2.classNode) {
+        return type1;
+      }
+      if (type1.classNode == coreTypes.doubleClass ||
+          type2.classNode == coreTypes.doubleClass) {
+        return coreTypes.doubleRawType(type1.nullability);
+      }
+    }
+
+    return coreTypes.numRawType(type1.nullability);
+  }
 }
 
 /// Result of a nullability-aware subtype check.
@@ -158,27 +164,91 @@
 /// nullability markers are ignored, it should also fail for those types in
 /// full-NNBD mode.
 class IsSubtypeOf {
-  final _IsSubtypeOfValues _value;
+  /// Internal value constructed via [IsSubtypeOf.never].
+  ///
+  /// The integer values of [_valueNever], [_valueOnlyIfIgnoringNullabilities],
+  /// and [_valueAlways] are important for the implementations of [_joinValues],
+  /// [_all], and [join].  They should be kept in sync.
+  static const int _valueNever = 0;
+
+  /// Internal value constructed via [IsSubtypeOf.onlyIfIgnoringNullabilities].
+  static const int _valueOnlyIfIgnoringNullabilities = 1;
+
+  /// Internal value constructed via [IsSubtypeOf.always].
+  static const int _valueAlways = 3;
+
+  static const List<IsSubtypeOf> _all = const <IsSubtypeOf>[
+    const IsSubtypeOf.never(),
+    const IsSubtypeOf.onlyIfIgnoringNullabilities(),
+    null, // Deliberately left empty because there's no index value for that.
+    const IsSubtypeOf.always()
+  ];
+
+  /// Joins results of subtype checks on parts into the overall result.
+  ///
+  /// Both [value1] and [value2] should be chosen from
+  /// [_valueNever], [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
+  /// The method produces the result which is one of [_valueNever],
+  /// [_valueOnlyIfIgnoringNullabilities], and [_valueAlways].
+  static int _joinValues(int value1, int value2) => value1 & value2;
+
+  /// The only state of an [IsSubtypeOf] object.
+  final int _value;
+
+  const IsSubtypeOf._internal(int value) : _value = value;
 
   /// Subtype check succeeds in both modes.
-  const IsSubtypeOf.always() : _value = _IsSubtypeOfValues.always;
+  const IsSubtypeOf.always() : this._internal(_valueAlways);
 
   /// Subtype check succeeds only if the nullability markers are ignored.
   ///
   /// This implies that if the nullability markers aren't ignored, the subtype
   /// check fails.
   const IsSubtypeOf.onlyIfIgnoringNullabilities()
-      : _value = _IsSubtypeOfValues.onlyIfIgnoringNullabilities;
+      : this._internal(_valueOnlyIfIgnoringNullabilities);
 
   /// Subtype check fails in both modes.
-  const IsSubtypeOf.never() : _value = _IsSubtypeOfValues.never;
+  const IsSubtypeOf.never() : this._internal(_valueNever);
+
+  /// Checks if two types are in relation based solely on their nullabilities.
+  factory IsSubtypeOf.basedSolelyOnNullabilities(
+      DartType subtype, DartType supertype) {
+    if (subtype.isPotentiallyNullable && supertype.isPotentiallyNonNullable) {
+      return const IsSubtypeOf.onlyIfIgnoringNullabilities();
+    }
+    return const IsSubtypeOf.always();
+  }
+
+  /// Combines results for the type parts into the overall result for the type.
+  ///
+  /// For example, the result of `A<B1, C1>? <: A<B2, C2>*` can be computed as
+  /// `Rb.join(Rc).join(Rn)` where `Rb` is the result of `B1 <: B2`, `Rc` is the
+  /// result of `C1 <: C2`, and `Rn` is
+  /// `new IsSubtypeOf.basedSolelyOnNullabilities(A<B1, C1>?, A<B2, C2>*)`.
+  IsSubtypeOf join(IsSubtypeOf other) {
+    return _all[_joinValues(_value, other._value)];
+  }
+
+  /// Shorts the computation of [join] if `this` is [IsSubtypeOf.never].
+  ///
+  /// Use this instead of [join] for optimization in case the argument to [join]
+  /// is, for example, a potentially expensive subtype check.  Unlike [join],
+  /// [joinWithSubtypeCheckFor] will immediately return if [this] was
+  /// constructed as [IsSubtypeOf.never] because the right-hand side will not
+  /// change the result anyway.
+  IsSubtypeOf joinWithSubtypeCheckFor(
+      DartType subtype, DartType supertype, SubtypeTester tester) {
+    if (_value == _valueNever) return this;
+    return this
+        .join(tester.performNullabilityAwareSubtypeCheck(subtype, supertype));
+  }
 
   bool isSubtypeWhenIgnoringNullabilities() {
-    return _value != _IsSubtypeOfValues.never;
+    return _value != _valueNever;
   }
 
   bool isSubtypeWhenUsingNullabilities() {
-    return _value == _IsSubtypeOfValues.always;
+    return _value == _valueAlways;
   }
 }
 
@@ -192,10 +262,14 @@
 /// This lives in a separate class so it can be tested independently of the SDK.
 abstract class SubtypeTester {
   InterfaceType get objectLegacyRawType;
+  InterfaceType get objectNullableRawType;
   InterfaceType get nullType;
   InterfaceType get functionLegacyRawType;
+  Class get objectClass;
+  Class get functionClass;
   Class get futureOrClass;
-  InterfaceType futureType(DartType type);
+  InterfaceType futureType(DartType type,
+      [Nullability nullability = Nullability.legacy]);
 
   static List<Object> typeChecks;
 
@@ -206,7 +280,8 @@
   bool isTop(DartType type) {
     return type is DynamicType ||
         type is VoidType ||
-        type == objectLegacyRawType;
+        type == objectLegacyRawType ||
+        type == objectNullableRawType;
   }
 
   /// Can be use to collect type checks. To use:
@@ -214,9 +289,10 @@
   /// 2. Rename `_collect_isSubtypeOf` to `isSubtypeOf`.
   /// 3. Comment out the call to `_isSubtypeOf` below.
   // ignore:unused_element
-  bool _collect_isSubtypeOf(DartType subtype, DartType supertype) {
+  bool _collect_isSubtypeOf(
+      DartType subtype, DartType supertype, SubtypeCheckMode mode) {
     bool result = true;
-    // result = _isSubtypeOf(subtype, supertype);
+    //result = _isSubtypeOf(subtype, supertype, mode);
     typeChecks ??= <Object>[];
     typeChecks.add([subtype, supertype, result]);
     return result;
@@ -246,11 +322,26 @@
     supertype = supertype.unalias;
     if (identical(subtype, supertype)) return const IsSubtypeOf.always();
     if (subtype is BottomType) return const IsSubtypeOf.always();
-    if (subtype == nullType) {
-      // See rule 4 of the subtype rules from the Dart Language Specification.
+    if (subtype is NeverType) {
       return supertype is BottomType
           ? const IsSubtypeOf.never()
-          : const IsSubtypeOf.always();
+          : new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype);
+    }
+    if (subtype == nullType) {
+      // TODO(dmitryas): Remove InvalidType from subtype relation.
+      if (supertype is InvalidType) {
+        // The return value is supposed to keep the backward compatibility.
+        return const IsSubtypeOf.always();
+      }
+
+      if (supertype.nullability == Nullability.nullable ||
+          supertype.nullability == Nullability.legacy) {
+        return const IsSubtypeOf.always();
+      }
+      // See rule 4 of the subtype rules from the Dart Language Specification.
+      return supertype is BottomType || supertype is NeverType
+          ? const IsSubtypeOf.never()
+          : const IsSubtypeOf.onlyIfIgnoringNullabilities();
     }
     if (isTop(supertype)) return const IsSubtypeOf.always();
 
@@ -267,13 +358,15 @@
 
       // given t1 is Future<A> | A, then:
       // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
-      var subtypeFuture = futureType(subtypeArg);
-      return performNullabilityAwareSubtypeCheck(subtypeFuture, supertype)
-                  .isSubtypeWhenIgnoringNullabilities() &&
-              performNullabilityAwareSubtypeCheck(subtypeArg, supertype)
-                  .isSubtypeWhenIgnoringNullabilities()
-          ? const IsSubtypeOf.always()
-          : const IsSubtypeOf.never();
+      return performNullabilityAwareSubtypeCheck(subtypeArg, supertype)
+          .joinWithSubtypeCheckFor(
+              futureType(subtypeArg, Nullability.nonNullable), supertype, this)
+          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
+    }
+
+    if (supertype is InterfaceType && supertype.classNode == objectClass) {
+      assert(supertype.nullability == Nullability.nonNullable);
+      return new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype);
     }
 
     if (supertype is InterfaceType &&
@@ -281,7 +374,7 @@
       // given t2 is Future<A> | A, then:
       // t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
       var supertypeArg = supertype.typeArguments[0];
-      var supertypeFuture = futureType(supertypeArg);
+      var supertypeFuture = futureType(supertypeArg, Nullability.legacy);
       return performNullabilityAwareSubtypeCheck(subtype, supertypeFuture)
                   .isSubtypeWhenIgnoringNullabilities() ||
               performNullabilityAwareSubtypeCheck(subtype, supertypeArg)
@@ -293,31 +386,34 @@
     if (subtype is InterfaceType && supertype is InterfaceType) {
       var upcastType = getTypeAsInstanceOf(subtype, supertype.classNode);
       if (upcastType == null) return const IsSubtypeOf.never();
+      IsSubtypeOf result = const IsSubtypeOf.always();
       for (int i = 0; i < upcastType.typeArguments.length; ++i) {
         // Termination: the 'supertype' parameter decreases in size.
         int variance = upcastType.classNode.typeParameters[i].variance;
         DartType leftType = upcastType.typeArguments[i];
         DartType rightType = supertype.typeArguments[i];
         if (variance == Variance.contravariant) {
-          if (!performNullabilityAwareSubtypeCheck(rightType, leftType)
-              .isSubtypeWhenIgnoringNullabilities()) {
+          result = result
+              .join(performNullabilityAwareSubtypeCheck(rightType, leftType));
+          if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         } else if (variance == Variance.invariant) {
-          if (!performNullabilityAwareSubtypeCheck(rightType, leftType)
-                  .isSubtypeWhenIgnoringNullabilities() ||
-              !performNullabilityAwareSubtypeCheck(leftType, rightType)
-                  .isSubtypeWhenIgnoringNullabilities()) {
+          result = result.join(
+              performNullabilityAwareMutualSubtypesCheck(leftType, rightType));
+          if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         } else {
-          if (!performNullabilityAwareSubtypeCheck(leftType, rightType)
-              .isSubtypeWhenIgnoringNullabilities()) {
+          result = result
+              .join(performNullabilityAwareSubtypeCheck(leftType, rightType));
+          if (!result.isSubtypeWhenIgnoringNullabilities()) {
             return const IsSubtypeOf.never();
           }
         }
       }
-      return const IsSubtypeOf.always();
+      return result
+          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
     }
     if (subtype is TypeParameterType) {
       if (supertype is TypeParameterType &&
@@ -337,10 +433,13 @@
       // Termination: if there are no cyclically bound type parameters, this
       // recursive call can only occur a finite number of times, before reaching
       // a shrinking recursive call (or terminating).
-      return performNullabilityAwareSubtypeCheck(subtype.bound, supertype);
+      return performNullabilityAwareSubtypeCheck(subtype.bound, supertype)
+          .join(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
     }
     if (subtype is FunctionType) {
-      if (supertype == functionLegacyRawType) return const IsSubtypeOf.always();
+      if (supertype is InterfaceType && supertype.classNode == functionClass) {
+        return new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype);
+      }
       if (supertype is FunctionType) {
         return _performNullabilityAwareFunctionSubtypeCheck(subtype, supertype);
       }
@@ -348,6 +447,12 @@
     return const IsSubtypeOf.never();
   }
 
+  IsSubtypeOf performNullabilityAwareMutualSubtypesCheck(
+      DartType type1, DartType type2) {
+    return performNullabilityAwareSubtypeCheck(type1, type2)
+        .joinWithSubtypeCheckFor(type2, type1, this);
+  }
+
   IsSubtypeOf _performNullabilityAwareFunctionSubtypeCheck(
       FunctionType subtype, FunctionType supertype) {
     if (subtype.requiredParameterCount > supertype.requiredParameterCount) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index b6007db..f9683d9 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -279,6 +279,7 @@
   R visitFunctionType(FunctionType node) => defaultDartType(node);
   R visitTypeParameterType(TypeParameterType node) => defaultDartType(node);
   R visitTypedefType(TypedefType node) => defaultDartType(node);
+  R visitNeverType(NeverType node) => defaultDartType(node);
 }
 
 class DartTypeVisitor1<R, T> {
@@ -293,6 +294,7 @@
   R visitTypeParameterType(TypeParameterType node, T arg) =>
       defaultDartType(node, arg);
   R visitTypedefType(TypedefType node, T arg) => defaultDartType(node, arg);
+  R visitNeverType(NeverType node, T arg) => defaultDartType(node, arg);
 }
 
 /// Visitor for [Constant] nodes.
@@ -521,6 +523,7 @@
   R visitFunctionType(FunctionType node) => defaultDartType(node);
   R visitTypeParameterType(TypeParameterType node) => defaultDartType(node);
   R visitTypedefType(TypedefType node) => defaultDartType(node);
+  R visitNeverType(NeverType node) => defaultDartType(node);
 
   // Constants
   R defaultConstant(Constant node) => defaultNode(node);
diff --git a/pkg/kernel/problems.md b/pkg/kernel/problems.md
index 3c1fb5e..82731a9 100644
--- a/pkg/kernel/problems.md
+++ b/pkg/kernel/problems.md
@@ -15,7 +15,7 @@
 problem-texts as reported by the compiler.
 
 `severity`: An integer representing severity. This should match the index in
-`package:front_end/src/fasta/severity.dart`.
+`package:_fe_analyzer_shared/src/messages/severity.dart`.
 
 `uri: A uri that this problems relates to.
 
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 51765de..7c83598 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,7 +1,7 @@
 name: kernel
 # Currently, kernel API is not stable and users should
 # not depend on semver semantics when depending on this package.
-version: 0.3.27
+version: 0.3.29
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
index 2065aea..c775f36 100644
--- a/pkg/kernel/tool/smoke_test_quick.dart
+++ b/pkg/kernel/tool/smoke_test_quick.dart
@@ -11,7 +11,7 @@
 main(List<String> args) async {
   Stopwatch stopwatch = new Stopwatch()..start();
   List<Future> futures = new List<Future>();
-  futures.add(run("pkg/front_end/test/old_dill_test.dart", ["--checkDill"]));
+  futures.add(run("pkg/front_end/test/old_dill_suite.dart", ["--checkDill"]));
   await Future.wait(futures);
   print("\n-----------------------\n");
   print("Done with exitcode $exitCode in ${stopwatch.elapsedMilliseconds} ms");
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index 284d9ba..b5b8c99 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 1.1.8
+
+* Introduce `@nonVirtual` to annotate instance members that should not be
+  overridden in subclasses or when mixed in.
+
 ## 1.1.7
 
 * Introduce `@sealed` to declare that a class or mixin is not allowed as a
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 285356d..7b2cd07 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -149,6 +149,21 @@
 ///   without invoking the overridden method.
 const _MustCallSuper mustCallSuper = const _MustCallSuper();
 
+/// Used to annotate an instance member (method, getter, setter, operator, or
+/// field) `m` in a class `C` or mixin `M`. Indicates that `m` should not be
+/// overridden in any classes that extend or mixin `C` or `M`.
+///
+/// Tools, such as the analyzer, can provide feedback if
+///
+/// * the annotation is associated with anything other than an instance member,
+/// * the annotation is associated with an abstract member (because subclasses
+///   are required to override the member),
+/// * the annotation is associated with an extension method,
+/// * the annotation is associated with a member `m` in class `C`, and there is
+///   a class `D` or mixin `M`, that extends or mixes in `C`, that declares an
+///   overriding member `m`.
+const _NonVirtual nonVirtual = const _NonVirtual();
+
 /// Used to annotate a class, mixin, or extension declaration `C`. Indicates
 /// that any type arguments declared on `C` are to be treated as optional.
 /// Tools such as the analyzer and linter can use this information to suppress
@@ -296,6 +311,10 @@
   const _MustCallSuper();
 }
 
+class _NonVirtual {
+  const _NonVirtual();
+}
+
 class _OptionalTypeArgs {
   const _OptionalTypeArgs();
 }
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index 0d1b4f8..3e5ecaf 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 1.1.7
+version: 1.1.8
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/meta
 description: >
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
index e23d38e..5bfdc37 100644
--- a/pkg/modular_test/lib/src/loader.dart
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -202,13 +202,20 @@
 }
 
 Future<Module> _createSdkModule(Uri root) async {
-  List<Uri> sources = [Uri.parse('sdk/lib/libraries.json')];
+  List<Uri> sources = [
+    Uri.parse('sdk/lib/libraries.json'),
+    // TODO(#38701) Cleanup after merging the forked SDK into mainline.
+    Uri.parse('sdk_nnbd/lib/libraries.json'),
+    Uri.parse('sdk_nnbd/lib/libraries_nnbd_mix_hack.json')
+  ];
 
   // Include all dart2js, ddc, vm library sources and patch files.
   // Note: we don't extract the list of files from the libraries.json because
   // it doesn't list files that are transitively imported.
   var sdkLibrariesAndPatchesRoots = [
     'sdk/lib/',
+    // TODO(#38701) Cleanup after merging the forked SDK into mainline.
+    'sdk_nnbd/lib/',
     'runtime/lib/',
     'runtime/bin/',
   ];
diff --git a/pkg/modular_test/lib/src/runner.dart b/pkg/modular_test/lib/src/runner.dart
index 1ed2fcb..13fb65a 100644
--- a/pkg/modular_test/lib/src/runner.dart
+++ b/pkg/modular_test/lib/src/runner.dart
@@ -87,7 +87,8 @@
               ' and `shards - 1`.')
       ..addOption('output-directory',
           help: 'location where to emit the jsonl result and log files')
-      ..addOption('configuration-name',
+      ..addOption('named-configuration',
+          abbr: 'n',
           help: 'configuration name to use for emitting jsonl result files.');
     ArgResults argResults = parser.parse(args);
     int shards = int.tryParse(argResults['shards']) ?? 1;
@@ -108,7 +109,7 @@
       ..filter = argResults['filter']
       ..shards = shards
       ..shard = shard
-      ..configurationName = argResults['configuration-name']
+      ..configurationName = argResults['named-configuration']
       ..outputDirectory = toUri(argResults['output-directory']);
   }
 }
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 558c1d4..35b8c5e 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -87,6 +87,11 @@
   /// The [isHard] property is always true for union edges.
   bool get isUnion;
 
+  /// Indicates whether the downstream node of this edge is non-nullable and the
+  /// edge is hard (and thus upstream nullability propagation should try to make
+  /// the source node non-nullable, if possible).
+  bool get isUpstreamTriggered;
+
   /// Information about the graph node that this edge "points away from".
   NullabilityNodeInfo get sourceNode;
 }
diff --git a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
index 23c98c2..9890f67 100644
--- a/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
+++ b/pkg/nnbd_migration/lib/src/already_migrated_code_decorator.dart
@@ -64,8 +64,9 @@
           namedParameters: namedParameters,
           positionalParameters: positionalParameters);
     } else if (type is InterfaceType) {
-      if (type.typeParameters.isNotEmpty) {
-        assert(type.typeArguments.length == type.typeParameters.length);
+      var typeParameters = type.element.typeParameters;
+      if (typeParameters.isNotEmpty) {
+        assert(type.typeArguments.length == typeParameters.length);
         return DecoratedType(type, node,
             typeArguments: type.typeArguments.map(decorate).toList());
       }
diff --git a/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart b/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
index 3935f4d4..601fb12 100644
--- a/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_class_hierarchy.dart
@@ -85,7 +85,7 @@
         // this specific [superclass].
         Map<TypeParameterElement, DecoratedType> substitution = {};
         for (int i = 0; i < supertype.typeArguments.length; i++) {
-          substitution[supertype.typeParameters[i]] =
+          substitution[supertype.element.typeParameters[i]] =
               decoratedSupertype.typeArguments[i];
         }
         // Apply that substitution to the relation between [superclass] and
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index d599c48..3378ce5 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -245,54 +245,15 @@
         if (thisType.typeFormals.length != otherType.typeFormals.length) {
           return false;
         }
-        var thisReturnType = this.returnType;
-        var otherReturnType = other.returnType;
-        var thisPositionalParameters = this.positionalParameters;
-        var otherPositionalParameters = other.positionalParameters;
-        var thisNamedParameters = this.namedParameters;
-        var otherNamedParameters = other.namedParameters;
-        if (!_compareTypeFormalLists(
-            thisType.typeFormals, otherType.typeFormals)) {
-          // Create a fresh set of type variables and substitute so we can
-          // compare safely.
-          var thisSubstitution = <TypeParameterElement, DecoratedType>{};
-          var otherSubstitution = <TypeParameterElement, DecoratedType>{};
-          var newParameters = <TypeParameterElement>[];
-          for (int i = 0; i < thisType.typeFormals.length; i++) {
-            var newParameter = TypeParameterElementImpl.synthetic(
-                thisType.typeFormals[i].name);
-            newParameters.add(newParameter);
-            var newParameterType =
-                DecoratedType._forTypeParameterSubstitution(newParameter);
-            thisSubstitution[thisType.typeFormals[i]] = newParameterType;
-            otherSubstitution[otherType.typeFormals[i]] = newParameterType;
-          }
-          for (int i = 0; i < thisType.typeFormals.length; i++) {
-            var thisBound =
-                this.typeFormalBounds[i].substitute(thisSubstitution);
-            var otherBound =
-                other.typeFormalBounds[i].substitute(otherSubstitution);
-            if (thisBound != otherBound) return false;
-            recordTypeParameterBound(newParameters[i], thisBound);
-          }
-          // TODO(paulberry): need to substitute bounds and compare them.
-          thisReturnType = thisReturnType.substitute(thisSubstitution);
-          otherReturnType = otherReturnType.substitute(otherSubstitution);
-          thisPositionalParameters =
-              _substituteList(thisPositionalParameters, thisSubstitution);
-          otherPositionalParameters =
-              _substituteList(otherPositionalParameters, otherSubstitution);
-          thisNamedParameters =
-              _substituteMap(thisNamedParameters, thisSubstitution);
-          otherNamedParameters =
-              _substituteMap(otherNamedParameters, otherSubstitution);
-        }
-        if (thisReturnType != otherReturnType) return false;
+        var renamed = RenamedDecoratedFunctionTypes.match(
+            this, other, (bound1, bound2) => bound1 == bound2);
+        if (renamed == null) return false;
+        if (renamed.returnType1 != renamed.returnType2) return false;
         if (!_compareLists(
-            thisPositionalParameters, otherPositionalParameters)) {
+            renamed.positionalParameters1, renamed.positionalParameters2)) {
           return false;
         }
-        if (!_compareMaps(thisNamedParameters, otherNamedParameters)) {
+        if (!_compareMaps(renamed.namedParameters1, renamed.namedParameters2)) {
           return false;
         }
         return true;
@@ -566,20 +527,6 @@
         namedParameters: newNamedParameters);
   }
 
-  List<DecoratedType> _substituteList(List<DecoratedType> list,
-      Map<TypeParameterElement, DecoratedType> substitution) {
-    return list.map((t) => t.substitute(substitution)).toList();
-  }
-
-  Map<String, DecoratedType> _substituteMap(Map<String, DecoratedType> map,
-      Map<TypeParameterElement, DecoratedType> substitution) {
-    var result = <String, DecoratedType>{};
-    for (var entry in map.entries) {
-      result[entry.key] = entry.value.substitute(substitution);
-    }
-    return result;
-  }
-
   /// Retrieves the decorated bound of the given [typeParameter].
   ///
   /// [typeParameter] must have an enclosing element of `null`.  Type parameters
@@ -621,14 +568,112 @@
     }
     return true;
   }
+}
 
-  static bool _compareTypeFormalLists(List<TypeParameterElement> formals1,
-      List<TypeParameterElement> formals2) {
-    if (identical(formals1, formals2)) return true;
-    if (formals1.length != formals2.length) return false;
-    for (int i = 0; i < formals1.length; i++) {
-      if (!identical(formals1[i], formals2[i])) return false;
+/// Helper class that renames the type parameters in two decorated function
+/// types so that they match.
+class RenamedDecoratedFunctionTypes {
+  final DecoratedType returnType1;
+
+  final DecoratedType returnType2;
+
+  final List<DecoratedType> positionalParameters1;
+
+  final List<DecoratedType> positionalParameters2;
+
+  final Map<String, DecoratedType> namedParameters1;
+
+  final Map<String, DecoratedType> namedParameters2;
+
+  RenamedDecoratedFunctionTypes._(
+      this.returnType1,
+      this.returnType2,
+      this.positionalParameters1,
+      this.positionalParameters2,
+      this.namedParameters1,
+      this.namedParameters2);
+
+  /// Attempt to find a renaming of the type parameters of [type1] and [type2]
+  /// (both of which should be function types) such that the generic type
+  /// parameters match.
+  ///
+  /// The callback [boundsMatcher] is used to determine whether type parameter
+  /// bounds match.
+  ///
+  /// If such a renaming can be found, it is returned.  If not, `null` is
+  /// returned.
+  static RenamedDecoratedFunctionTypes match(
+      DecoratedType type1,
+      DecoratedType type2,
+      bool Function(DecoratedType, DecoratedType) boundsMatcher) {
+    if (!_isNeeded(type1.typeFormals, type2.typeFormals)) {
+      return RenamedDecoratedFunctionTypes._(
+          type1.returnType,
+          type2.returnType,
+          type1.positionalParameters,
+          type2.positionalParameters,
+          type1.namedParameters,
+          type2.namedParameters);
     }
-    return true;
+    // Create a fresh set of type variables and substitute so we can
+    // compare safely.
+    var substitution1 = <TypeParameterElement, DecoratedType>{};
+    var substitution2 = <TypeParameterElement, DecoratedType>{};
+    var newParameters = <TypeParameterElement>[];
+    for (int i = 0; i < type1.typeFormals.length; i++) {
+      var newParameter =
+          TypeParameterElementImpl.synthetic(type1.typeFormals[i].name);
+      newParameters.add(newParameter);
+      var newParameterType =
+          DecoratedType._forTypeParameterSubstitution(newParameter);
+      substitution1[type1.typeFormals[i]] = newParameterType;
+      substitution2[type2.typeFormals[i]] = newParameterType;
+    }
+    for (int i = 0; i < type1.typeFormals.length; i++) {
+      var bound1 = type1.typeFormalBounds[i].substitute(substitution1);
+      var bound2 = type2.typeFormalBounds[i].substitute(substitution2);
+      if (!boundsMatcher(bound1, bound2)) return null;
+      DecoratedType.recordTypeParameterBound(newParameters[i], bound1);
+    }
+    var returnType1 = type1.returnType.substitute(substitution1);
+    var returnType2 = type2.returnType.substitute(substitution2);
+    var positionalParameters1 =
+        _substituteList(type1.positionalParameters, substitution1);
+    var positionalParameters2 =
+        _substituteList(type2.positionalParameters, substitution2);
+    var namedParameters1 = _substituteMap(type1.namedParameters, substitution1);
+    var namedParameters2 = _substituteMap(type2.namedParameters, substitution2);
+    return RenamedDecoratedFunctionTypes._(
+        returnType1,
+        returnType2,
+        positionalParameters1,
+        positionalParameters2,
+        namedParameters1,
+        namedParameters2);
+  }
+
+  static bool _isNeeded(List<TypeParameterElement> formals1,
+      List<TypeParameterElement> formals2) {
+    if (identical(formals1, formals2)) return false;
+    if (formals1.length != formals2.length) return true;
+    for (int i = 0; i < formals1.length; i++) {
+      if (!identical(formals1[i], formals2[i])) return true;
+    }
+    return false;
+  }
+
+  static List<DecoratedType> _substituteList(List<DecoratedType> list,
+      Map<TypeParameterElement, DecoratedType> substitution) {
+    return list.map((t) => t.substitute(substitution)).toList();
+  }
+
+  static Map<String, DecoratedType> _substituteMap(
+      Map<String, DecoratedType> map,
+      Map<TypeParameterElement, DecoratedType> substitution) {
+    var result = <String, DecoratedType>{};
+    for (var entry in map.entries) {
+      result[entry.key] = entry.value.substitute(substitution);
+    }
+    return result;
   }
 }
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
index 3e9f14e..940d44e 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type_system.dart';
-import 'package:front_end/src/fasta/flow_analysis/flow_analysis.dart';
 import 'package:nnbd_migration/src/decorated_type.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
@@ -26,7 +26,18 @@
 
   @override
   bool isSubtypeOf(DecoratedType leftType, DecoratedType rightType) {
-    return _typeSystem.isSubtypeOf(leftType.type, rightType.type);
+    if (!_typeSystem.isSubtypeOf(leftType.type, rightType.type)) {
+      // Pre-migrated types don't meet the subtype requirement.  Not a subtype.
+      return false;
+    } else if (rightType.node == _graph.never &&
+        leftType.node != _graph.never) {
+      // The "never" node will never be nullable, so not a subtype.
+      return false;
+    } else {
+      // We don't know whether a subtype relation will hold once the graph is
+      // solved.  Assume it will.
+      return true;
+    }
   }
 
   @override
@@ -35,6 +46,16 @@
   }
 
   @override
+  DecoratedType tryPromoteToType(DecoratedType to, DecoratedType from) {
+    // TODO(paulberry): implement appropriate logic for type variable promotion.
+    if (isSubtypeOf(to, from)) {
+      return to;
+    } else {
+      return null;
+    }
+  }
+
+  @override
   DecoratedType variableType(PromotableElement variable) {
     return _variableRepository.decoratedElementType(variable);
   }
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index f2b03b4..11598f2 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -13,7 +14,6 @@
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/flow_analysis/flow_analysis.dart';
 import 'package:meta/meta.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
@@ -112,7 +112,7 @@
 
   /// If we are visiting a function body or initializer, instance of flow
   /// analysis.  Otherwise `null`.
-  FlowAnalysis<Statement, Expression, PromotableElement, DecoratedType>
+  FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DecoratedType>
       _flowAnalysis;
 
   /// If we are visiting a function body or initializer, assigned variable
@@ -190,6 +190,10 @@
   /// nullable.
   final Map<Expression, NullabilityNode> _conditionalNodes = {};
 
+  /// If we are visiting a cascade expression, the decorated type of the target
+  /// of the cascade.  Otherwise `null`.
+  DecoratedType _currentCascadeTargetType;
+
   EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
       this.source, this.listener, this._decoratedClassHierarchy,
       {this.instrumentation})
@@ -255,11 +259,13 @@
   DecoratedType visitAsExpression(AsExpression node) {
     final typeNode = _variables.decoratedTypeAnnotation(source, node.type);
     _handleAssignment(node.expression, destinationType: typeNode);
+    _flowAnalysis.asExpression_end(node.expression, typeNode);
     return typeNode;
   }
 
   @override
   DecoratedType visitAssertInitializer(AssertInitializer node) {
+    _flowAnalysis.assert_begin();
     _checkExpressionNotNull(node.condition);
     if (identical(_conditionInfo?.condition, node.condition)) {
       var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
@@ -269,12 +275,15 @@
             hard: true);
       }
     }
+    _flowAnalysis.assert_afterCondition(node.condition);
     node.message?.accept(this);
+    _flowAnalysis.assert_end();
     return null;
   }
 
   @override
   DecoratedType visitAssertStatement(AssertStatement node) {
+    _flowAnalysis.assert_begin();
     _checkExpressionNotNull(node.condition);
     if (identical(_conditionInfo?.condition, node.condition)) {
       var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
@@ -284,7 +293,9 @@
             hard: true);
       }
     }
+    _flowAnalysis.assert_afterCondition(node.condition);
     node.message?.accept(this);
+    _flowAnalysis.assert_end();
     return null;
   }
 
@@ -359,7 +370,7 @@
     } else if (operatorType == TokenType.QUESTION_QUESTION) {
       DecoratedType expressionType;
       var leftType = leftOperand.accept(this);
-      _flowAnalysis.ifNullExpression_rightBegin();
+      _flowAnalysis.ifNullExpression_rightBegin(node.leftOperand);
       try {
         _guards.add(leftType.node);
         DecoratedType rightType;
@@ -367,7 +378,9 @@
           rightType = rightOperand.accept(this);
         });
         var ifNullNode = NullabilityNode.forIfNotNull();
-        expressionType = DecoratedType(node.staticType, ifNullNode);
+        expressionType = _decorateUpperOrLowerBound(
+            node, node.staticType, leftType, rightType, true,
+            node: ifNullNode);
         _connect(
             rightType.node, expressionType.node, IfNullOrigin(source, node));
       } finally {
@@ -419,23 +432,22 @@
 
   @override
   DecoratedType visitCascadeExpression(CascadeExpression node) {
-    var type = node.target.accept(this);
-    node.cascadeSections.accept(this);
-    return type;
+    var oldCascadeTargetType = _currentCascadeTargetType;
+    try {
+      _currentCascadeTargetType = _checkExpressionNotNull(node.target);
+      node.cascadeSections.accept(this);
+      return _currentCascadeTargetType;
+    } finally {
+      _currentCascadeTargetType = oldCascadeTargetType;
+    }
   }
 
   @override
   DecoratedType visitCatchClause(CatchClause node) {
-    _flowAnalysis.tryCatchStatement_catchBegin();
+    _flowAnalysis.tryCatchStatement_catchBegin(
+        node.exceptionParameter?.staticElement as PromotableElement,
+        node.stackTraceParameter?.staticElement as PromotableElement);
     node.exceptionType?.accept(this);
-    for (var identifier in [
-      node.exceptionParameter,
-      node.stackTraceParameter
-    ]) {
-      if (identifier != null) {
-        _flowAnalysis.initialize(identifier.staticElement as PromotableElement);
-      }
-    }
     // The catch clause may not execute, so create a new scope for
     // post-dominators.
     _postDominatedLocals.doScoped(action: () => node.body.accept(this));
@@ -445,6 +457,7 @@
 
   @override
   DecoratedType visitClassDeclaration(ClassDeclaration node) {
+    node.metadata.accept(this);
     node.members.accept(this);
     return null;
   }
@@ -562,10 +575,7 @@
 
   @override
   DecoratedType visitDoStatement(DoStatement node) {
-    _flowAnalysis.doStatement_bodyBegin(
-        node,
-        _assignedVariables.writtenInNode(node),
-        _assignedVariables.capturedInNode(node));
+    _flowAnalysis.doStatement_bodyBegin(node);
     node.body.accept(this);
     _flowAnalysis.doStatement_conditionBegin();
     _checkExpressionNotNull(node.condition);
@@ -750,8 +760,10 @@
   @override
   DecoratedType visitIndexExpression(IndexExpression node) {
     DecoratedType targetType;
-    var target = node.realTarget;
-    if (target != null) {
+    var target = node.target;
+    if (node.isCascaded) {
+      targetType = _currentCascadeTargetType;
+    } else if (target != null) {
       targetType = _checkExpressionNotNull(target);
     }
     var callee = node.staticElement;
@@ -839,13 +851,8 @@
     }
     var expression = node.expression;
     expression.accept(this);
-    if (expression is SimpleIdentifier) {
-      var element = expression.staticElement;
-      if (element is PromotableElement) {
-        _flowAnalysis.isExpression_end(
-            node, element, node.notOperator != null, decoratedType);
-      }
-    }
+    _flowAnalysis.isExpression_end(
+        node, expression, node.notOperator != null, decoratedType);
     return DecoratedType(node.staticType, _graph.never);
   }
 
@@ -904,12 +911,13 @@
   @override
   DecoratedType visitMethodInvocation(MethodInvocation node) {
     DecoratedType targetType;
-    var target = node.realTarget;
-    var operator = node.operator;
-    bool isNullAware = operator != null && isNullAwareToken(operator.type);
+    var target = node.target;
+    bool isNullAware = node.isNullAware;
     var callee = node.methodName.staticElement;
     bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
-    if (target != null) {
+    if (node.isCascaded) {
+      targetType = _currentCascadeTargetType;
+    } else if (target != null) {
       if (_isPrefix(target)) {
         // Nothing to do.
       } else if (calleeIsStatic) {
@@ -981,10 +989,28 @@
 
   @override
   DecoratedType visitPostfixExpression(PostfixExpression node) {
-    var operatorType = node.operator.type;
-    if (operatorType == TokenType.PLUS_PLUS ||
-        operatorType == TokenType.MINUS_MINUS) {
-      return _checkExpressionNotNull(node.operand);
+    if (node.operator.type.isIncrementOperator) {
+      var operand = node.operand;
+      var targetType = _checkExpressionNotNull(operand);
+      var callee = node.staticElement;
+      DecoratedType writeType;
+      if (callee == null) {
+        // Dynamic dispatch.  The return type is `dynamic`.
+        // TODO(paulberry): would it be better to assume a return type of `Never`
+        // so that we don't unnecessarily propagate nullabilities everywhere?
+        writeType = _dynamicType;
+      } else {
+        var calleeType =
+            getOrComputeElementType(callee, targetType: targetType);
+        writeType = _fixNumericTypes(calleeType.returnType, node.staticType);
+      }
+      if (operand is SimpleIdentifier) {
+        var element = operand.staticElement;
+        if (element is PromotableElement) {
+          _flowAnalysis.write(element, writeType);
+        }
+      }
+      return targetType;
     }
     _unimplemented(
         node, 'Postfix expression with operator ${node.operator.lexeme}');
@@ -996,40 +1022,54 @@
       // TODO(paulberry)
       _unimplemented(node, 'PrefixedIdentifier with a prefix');
     } else {
-      return _handlePropertyAccess(node, node.prefix, node.identifier, false);
+      return _handlePropertyAccess(
+          node, node.prefix, node.identifier, false, false);
     }
   }
 
   @override
   DecoratedType visitPrefixExpression(PrefixExpression node) {
-    var targetType = _checkExpressionNotNull(node.operand);
+    var operand = node.operand;
+    var targetType = _checkExpressionNotNull(operand);
     var operatorType = node.operator.type;
     if (operatorType == TokenType.BANG) {
-      _flowAnalysis.logicalNot_end(node, node.operand);
+      _flowAnalysis.logicalNot_end(node, operand);
       return _nonNullableBoolType;
     } else {
       var callee = node.staticElement;
+      var isIncrementOrDecrement = operatorType.isIncrementOperator;
+      DecoratedType staticType;
       if (callee == null) {
         // Dynamic dispatch.  The return type is `dynamic`.
         // TODO(paulberry): would it be better to assume a return type of `Never`
         // so that we don't unnecessarily propagate nullabilities everywhere?
-        return _dynamicType;
-      }
-      var calleeType = getOrComputeElementType(callee, targetType: targetType);
-      if (operatorType == TokenType.PLUS_PLUS ||
-          operatorType == TokenType.MINUS_MINUS) {
-        return _fixNumericTypes(calleeType.returnType, node.staticType);
+        staticType = _dynamicType;
       } else {
-        return _handleInvocationArguments(
-            node, [], null, null, calleeType, null);
+        var calleeType =
+            getOrComputeElementType(callee, targetType: targetType);
+        if (isIncrementOrDecrement) {
+          staticType = _fixNumericTypes(calleeType.returnType, node.staticType);
+        } else {
+          staticType = _handleInvocationArguments(
+              node, [], null, null, calleeType, null);
+        }
       }
+      if (isIncrementOrDecrement) {
+        if (operand is SimpleIdentifier) {
+          var element = operand.staticElement;
+          if (element is PromotableElement) {
+            _flowAnalysis.write(element, staticType);
+          }
+        }
+      }
+      return staticType;
     }
   }
 
   @override
   DecoratedType visitPropertyAccess(PropertyAccess node) {
-    return _handlePropertyAccess(node, node.realTarget, node.propertyName,
-        isNullAwareToken(node.operator.type));
+    return _handlePropertyAccess(node, node.target, node.propertyName,
+        node.isNullAware, node.isCascaded);
   }
 
   @override
@@ -1207,12 +1247,10 @@
   DecoratedType visitSwitchStatement(SwitchStatement node) {
     node.expression.accept(this);
     _flowAnalysis.switchStatement_expressionEnd(node);
-    var notPromoted = _assignedVariables.writtenInNode(node);
-    var captured = _assignedVariables.capturedInNode(node);
     var hasDefault = false;
     for (var member in node.members) {
       var hasLabel = member.labels.isNotEmpty;
-      _flowAnalysis.switchStatement_beginCase(hasLabel, notPromoted, captured);
+      _flowAnalysis.switchStatement_beginCase(hasLabel, node);
       if (member is SwitchCase) {
         member.expression.accept(this);
       } else {
@@ -1254,19 +1292,16 @@
     }
     var body = node.body;
     body.accept(this);
-    var assignedInBody = _assignedVariables.writtenInNode(body);
-    var capturedInBody = _assignedVariables.capturedInNode(body);
     if (catchClauses.isNotEmpty) {
-      _flowAnalysis.tryCatchStatement_bodyEnd(assignedInBody, capturedInBody);
+      _flowAnalysis.tryCatchStatement_bodyEnd(body);
       catchClauses.accept(this);
       _flowAnalysis.tryCatchStatement_end();
     }
     if (finallyBlock != null) {
       _flowAnalysis.tryFinallyStatement_finallyBegin(
-          assignedInBody, capturedInBody);
+          catchClauses.isNotEmpty ? node : body);
       finallyBlock.accept(this);
-      _flowAnalysis.tryFinallyStatement_end(
-          _assignedVariables.writtenInNode(finallyBlock));
+      _flowAnalysis.tryFinallyStatement_end(finallyBlock);
     }
     return null;
   }
@@ -1373,9 +1408,7 @@
   DecoratedType visitWhileStatement(WhileStatement node) {
     // Note: we do not create guards. A null check here is *very* unlikely to be
     // unnecessary after analysis.
-    _flowAnalysis.whileStatement_conditionBegin(
-        _assignedVariables.writtenInNode(node),
-        _assignedVariables.capturedInNode(node));
+    _flowAnalysis.whileStatement_conditionBegin(node);
     _checkExpressionNotNull(node.condition);
     _flowAnalysis.whileStatement_bodyBegin(node, node.condition);
     _postDominatedLocals.doScoped(action: () => node.body.accept(this));
@@ -1422,11 +1455,10 @@
     assert(_assignedVariables == null);
     _assignedVariables =
         FlowAnalysisHelper.computeAssignedVariables(node, parameters);
-    _flowAnalysis =
-        FlowAnalysis<Statement, Expression, PromotableElement, DecoratedType>(
-            DecoratedTypeOperations(_typeSystem, _variables, _graph),
-            _assignedVariables.writtenAnywhere,
-            _assignedVariables.capturedAnywhere);
+    _flowAnalysis = FlowAnalysis<AstNode, Statement, Expression,
+            PromotableElement, DecoratedType>(
+        DecoratedTypeOperations(_typeSystem, _variables, _graph),
+        _assignedVariables);
   }
 
   DecoratedType _decorateUpperOrLowerBound(AstNode astNode, DartType type,
@@ -1552,7 +1584,7 @@
       {DecoratedType destinationType,
       Expression destinationExpression,
       AssignmentExpression compoundOperatorInfo,
-      Expression questionAssignNode,
+      AssignmentExpression questionAssignNode,
       bool fromDefaultValue = false,
       bool wrapFuture = false}) {
     assert(
@@ -1576,6 +1608,8 @@
 
     if (questionAssignNode != null) {
       _guards.add(destinationType.node);
+      _flowAnalysis
+          .ifNullExpression_rightBegin(questionAssignNode.leftHandSide);
     }
     DecoratedType sourceType;
     try {
@@ -1634,7 +1668,11 @@
             hard: questionAssignNode == null &&
                 _postDominatedLocals.isReferenceInScope(expression));
       }
+      if (destinationLocalVariable != null) {
+        _flowAnalysis.write(destinationLocalVariable, sourceType);
+      }
       if (questionAssignNode != null) {
+        _flowAnalysis.ifNullExpression_end();
         // a ??= b is only nullable if both a and b are nullable.
         sourceType = destinationType.withNode(_nullabilityNodeForGLB(
             questionAssignNode, sourceType.node, destinationType.node));
@@ -1649,9 +1687,6 @@
     if (destinationExpression != null) {
       _postDominatedLocals.removeReferenceFromAllScopes(destinationExpression);
     }
-    if (destinationLocalVariable != null) {
-      _flowAnalysis.write(destinationLocalVariable);
-    }
     return sourceType;
   }
 
@@ -1801,8 +1836,7 @@
       } else if (parts is ForPartsWithExpression) {
         parts.initialization?.accept(this);
       }
-      _flowAnalysis.for_conditionBegin(_assignedVariables.writtenInNode(node),
-          _assignedVariables.capturedInNode(node));
+      _flowAnalysis.for_conditionBegin(node);
       if (parts.condition != null) {
         _checkExpressionNotNull(parts.condition);
       }
@@ -1820,12 +1854,13 @@
             'Unexpected ForEachParts subtype: ${parts.runtimeType}');
       }
       var iterableType = _checkExpressionNotNull(parts.iterable);
+      DecoratedType elementType;
       if (lhsElement != null) {
         DecoratedType lhsType = _variables.decoratedElementType(lhsElement);
         var iterableTypeType = iterableType.type;
         if (_typeSystem.isSubtypeOf(
             iterableTypeType, typeProvider.iterableDynamicType)) {
-          var elementType = _decoratedClassHierarchy
+          elementType = _decoratedClassHierarchy
               .asInstanceOf(
                   iterableType, typeProvider.iterableDynamicType.element)
               .typeArguments[0];
@@ -1834,9 +1869,9 @@
         }
       }
       _flowAnalysis.forEach_bodyBegin(
-          _assignedVariables.writtenInNode(node),
-          _assignedVariables.capturedInNode(node),
-          lhsElement is PromotableElement ? lhsElement : null);
+          node,
+          lhsElement is PromotableElement ? lhsElement : null,
+          elementType ?? _dynamicType);
     }
 
     // The condition may fail/iterable may be empty, so the body gets a new
@@ -1960,11 +1995,13 @@
   }
 
   DecoratedType _handlePropertyAccess(Expression node, Expression target,
-      SimpleIdentifier propertyName, bool isNullAware) {
+      SimpleIdentifier propertyName, bool isNullAware, bool isCascaded) {
     DecoratedType targetType;
     var callee = propertyName.staticElement;
     bool calleeIsStatic = callee is ExecutableElement && callee.isStatic;
-    if (_isPrefix(target)) {
+    if (isCascaded) {
+      targetType = _currentCascadeTargetType;
+    } else if (_isPrefix(target)) {
       return propertyName.accept(this);
     } else if (calleeIsStatic) {
       target.accept(this);
@@ -2284,17 +2321,17 @@
       {@required DecoratedType source,
       @required DecoratedType destination,
       @required bool hard}) {
-    assert(_typeSystem.isSubtypeOf(destination.type, source.type));
+    var destinationType = destination.type;
+    assert(_typeSystem.isSubtypeOf(destinationType, source.type));
     // Nullability should narrow to maintain subtype relationship.
     _connect(source.node, destination.node, origin, hard: hard);
     if (source.type.isDynamic) {
       assert(destination.typeFormals?.isEmpty ?? true,
           'downcast to something with type parameters not yet supported.');
-      assert(destination is! FunctionType,
+      assert(destinationType is! FunctionType,
           'downcast to function type not yet supported.');
-      if (destination.type is ParameterizedType) {
-        for (final param
-            in (destination.type as ParameterizedType).typeParameters) {
+      if (destinationType is InterfaceType) {
+        for (final param in destinationType.element.typeParameters) {
           assert(param.bound == null,
               'downcast to type parameters with bounds not supported');
         }
@@ -2304,7 +2341,7 @@
         // We cannot assume we're downcasting to C<T!>. Downcast to C<T?>.
         _checkDowncast(origin, source: source, destination: arg, hard: false);
       }
-    } else if (destination.type is TypeParameterType &&
+    } else if (destinationType is TypeParameterType &&
         source.type is! TypeParameterType) {
       // Assume an assignment to the type parameter's bound.
       _checkAssignment(origin,
@@ -2312,15 +2349,12 @@
           destination:
               _getTypeParameterTypeBound(destination).withNode(_graph.always),
           hard: false);
-    } else if (destination.type is InterfaceTypeImpl) {
+    } else if (destinationType is InterfaceType) {
       assert(source.typeArguments.isEmpty,
           'downcast from interface type with type args not supported.');
-      if (destination.type is ParameterizedType) {
-        for (final param
-            in (destination.type as ParameterizedType).typeParameters) {
-          assert(param.bound == null,
-              'downcast to type parameters with bounds not supported');
-        }
+      for (final param in destinationType.element.typeParameters) {
+        assert(param.bound == null,
+            'downcast to type parameters with bounds not supported');
       }
       for (final arg in destination.typeArguments) {
         // We cannot assume we're downcasting to C<T!>. Downcast to C<T?>.
@@ -2333,7 +2367,7 @@
       assert(
           false,
           'downcasting from ${source.type.runtimeType} to '
-          '${destination.type.runtimeType} not supported.');
+          '${destinationType.runtimeType} not supported.');
     }
   }
 
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index c686258..eae5178 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.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:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
@@ -15,7 +16,6 @@
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/fasta/flow_analysis/flow_analysis.dart';
 import 'package:meta/meta.dart';
 import 'package:nnbd_migration/src/decorated_class_hierarchy.dart';
 import 'package:nnbd_migration/src/utilities/resolution_utils.dart';
@@ -76,14 +76,14 @@
   final TypeProvider typeProvider;
 
   /// The type system.
-  final TypeSystem _typeSystem;
+  final Dart2TypeSystem _typeSystem;
 
   /// Variables for this migration run.
   final Variables _variables;
 
   /// If we are visiting a function body or initializer, instance of flow
   /// analysis.  Otherwise `null`.
-  FlowAnalysis<Statement, Expression, PromotableElement, DartType>
+  FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>
       _flowAnalysis;
 
   /// If we are visiting a function body or initializer, assigned variable
@@ -102,13 +102,8 @@
       : typeProvider = (typeProvider as TypeProviderImpl)
             .withNullability(NullabilitySuffix.none);
 
-  /// Called whenever a type annotation is found for which a `?` needs to be
-  /// inserted.
-  void addNullable(TypeAnnotation node);
-
-  /// Called whenever an expression is found for which a `!` needs to be
-  /// inserted.
-  void addNullCheck(Expression subexpression);
+  /// Called whenever an AST node is found that needs to be changed.
+  void addChange(AstNode node, NodeChange change);
 
   /// Called whenever code is found that can't be automatically fixed.
   void addProblem(AstNode node, Problem problem);
@@ -119,11 +114,26 @@
     assert(_assignedVariables == null);
     _assignedVariables =
         FlowAnalysisHelper.computeAssignedVariables(node, parameters);
-    _flowAnalysis =
-        FlowAnalysis<Statement, Expression, PromotableElement, DartType>(
-            TypeSystemTypeOperations(_typeSystem),
-            _assignedVariables.writtenAnywhere,
-            _assignedVariables.capturedAnywhere);
+    _flowAnalysis = FlowAnalysis<
+        AstNode,
+        Statement,
+        Expression,
+        PromotableElement,
+        DartType>(TypeSystemTypeOperations(_typeSystem), _assignedVariables);
+  }
+
+  @override
+  DartType visitArgumentList(ArgumentList node) {
+    for (var argument in node.arguments) {
+      Expression expression;
+      if (argument is NamedExpression) {
+        expression = argument.expression;
+      } else {
+        expression = argument;
+      }
+      visitSubexpression(expression, UnknownInferredType.instance);
+    }
+    return null;
   }
 
   @override
@@ -137,10 +147,10 @@
       // TODO(paulberry): if targetInfo.readType is non-nullable, then the
       // assignment is dead code.
       // See https://github.com/dart-lang/sdk/issues/38678
-      // TODO(paulberry): once flow analysis supports `??=`, integrate it here.
-      // See https://github.com/dart-lang/sdk/issues/38680
+      _flowAnalysis.ifNullExpression_rightBegin(node.leftHandSide);
       var rhsType =
           visitSubexpression(node.rightHandSide, targetInfo.writeType);
+      _flowAnalysis.ifNullExpression_end();
       return _typeSystem.leastUpperBound(
           _typeSystem.promoteToNonNull(targetInfo.readType as TypeImpl),
           rhsType);
@@ -176,10 +186,17 @@
   AssignmentTargetInfo visitAssignmentTarget(Expression node, bool isCompound) {
     if (node is SimpleIdentifier) {
       var writeType = _computeMigratedType(node.staticElement);
-      var auxiliaryElements = node.auxiliaryElements;
-      var readType = auxiliaryElements == null
-          ? writeType
-          : _computeMigratedType(auxiliaryElements.staticElement);
+      DartType readType;
+      var element = node.staticElement;
+      if (element is PromotableElement) {
+        readType = _flowAnalysis.variableRead(node, element) ??
+            _computeMigratedType(element);
+      } else {
+        var auxiliaryElements = node.auxiliaryElements;
+        readType = auxiliaryElements == null
+            ? writeType
+            : _computeMigratedType(auxiliaryElements.staticElement);
+      }
       return AssignmentTargetInfo(isCompound ? readType : null, writeType);
     } else if (node is IndexExpression) {
       var targetType = visitSubexpression(node.target, typeProvider.objectType);
@@ -209,8 +226,8 @@
       visitSubexpression(node.index, indexContext);
       return AssignmentTargetInfo(readType, writeType);
     } else if (node is PropertyAccess) {
-      return _handleAssignmentTargetForPropertyAccess(node, node.target,
-          node.propertyName, isNullAwareToken(node.operator.type), isCompound);
+      return _handleAssignmentTargetForPropertyAccess(
+          node, node.target, node.propertyName, node.isNullAware, isCompound);
     } else if (node is PrefixedIdentifier) {
       if (node.prefix.staticElement is ImportElement) {
         // TODO(paulberry)
@@ -253,7 +270,7 @@
         // migrate it to `(a ?? b)!`.  We want to migrate it to `a ?? b!`.
         var leftType = visitSubexpression(node.leftOperand,
             _typeSystem.makeNullable(_contextType as TypeImpl));
-        _flowAnalysis.ifNullExpression_rightBegin();
+        _flowAnalysis.ifNullExpression_rightBegin(node.leftOperand);
         var rightType = visitSubexpression(node.rightOperand, _contextType);
         _flowAnalysis.ifNullExpression_end();
         return _typeSystem.leastUpperBound(
@@ -304,6 +321,22 @@
   }
 
   @override
+  DartType visitFunctionExpressionInvocation(
+      FunctionExpressionInvocation node) {
+    var targetType = visitSubexpression(node.function, typeProvider.objectType);
+    if (targetType is FunctionType) {
+      return _handleInvocationArguments(node, node.argumentList.arguments,
+          node.typeArguments, node.typeArgumentTypes, targetType, null,
+          invokeType: node.staticInvokeType);
+    } else {
+      // Dynamic dispatch.  The return type is `dynamic`.
+      node.typeArguments?.accept(this);
+      node.argumentList.accept(this);
+      return typeProvider.dynamicType;
+    }
+  }
+
+  @override
   DartType visitIfStatement(IfStatement node) {
     visitSubexpression(node.condition, typeProvider.boolType);
     _flowAnalysis.ifStatement_thenBegin(node.condition);
@@ -384,6 +417,44 @@
   }
 
   @override
+  DartType visitMethodInvocation(MethodInvocation node) {
+    var target = node.realTarget;
+    var callee = node.methodName.staticElement;
+    bool isNullAware = node.isNullAware;
+    DartType targetType;
+    if (target != null) {
+      if (callee is ExecutableElement && callee.isStatic) {
+        target.accept(this);
+      } else {
+        targetType = visitSubexpression(
+            target,
+            isNullAware || isDeclaredOnObject(node.methodName.name)
+                ? typeProvider.dynamicType
+                : typeProvider.objectType);
+      }
+    }
+    if (callee == null) {
+      // Dynamic dispatch.  The return type is `dynamic`.
+      node.typeArguments?.accept(this);
+      node.argumentList.accept(this);
+      return typeProvider.dynamicType;
+    }
+    var calleeType = _computeMigratedType(callee, targetType: targetType);
+    var expressionType = _handleInvocationArguments(
+        node,
+        node.argumentList.arguments,
+        node.typeArguments,
+        node.typeArgumentTypes,
+        calleeType as FunctionType,
+        null,
+        invokeType: node.staticInvokeType);
+    if (isNullAware) {
+      expressionType = _typeSystem.makeNullable(expressionType as TypeImpl);
+    }
+    return expressionType;
+  }
+
+  @override
   DartType visitNode(AstNode node) {
     // Every node type needs its own visit method.
     throw UnimplementedError('No visit method for ${node.runtimeType}');
@@ -410,7 +481,8 @@
           'supported yet');
     } else {
       var targetInfo = visitAssignmentTarget(node.operand, true);
-      _handleIncrementOrDecrement(node.staticElement, targetInfo, node);
+      _handleIncrementOrDecrement(
+          node.staticElement, targetInfo, node, node.operand);
       return targetInfo.readType;
     }
   }
@@ -449,8 +521,8 @@
         break;
       case TokenType.PLUS_PLUS:
       case TokenType.MINUS_MINUS:
-        return _handleIncrementOrDecrement(
-            node.staticElement, visitAssignmentTarget(operand, true), node);
+        return _handleIncrementOrDecrement(node.staticElement,
+            visitAssignmentTarget(operand, true), node, node.operand);
       default:
         throw StateError('Unexpected prefix operator: ${node.operator}');
     }
@@ -458,8 +530,8 @@
 
   @override
   DartType visitPropertyAccess(PropertyAccess node) {
-    return _handlePropertyAccess(node, node.target, node.propertyName,
-        isNullAwareToken(node.operator.type));
+    return _handlePropertyAccess(
+        node, node.target, node.propertyName, node.isNullAware);
   }
 
   @override
@@ -482,7 +554,7 @@
       _contextType = contextType;
       var type = subexpression.accept(this);
       if (_doesAssignmentNeedCheck(from: type, to: contextType)) {
-        addNullCheck(subexpression);
+        addChange(subexpression, NullCheck());
         _flowAnalysis.nonNullAssert_end(subexpression);
         return _typeSystem.promoteToNonNull(type as TypeImpl);
       } else {
@@ -517,7 +589,7 @@
       var element = decoratedType.type.element as ClassElement;
       bool isNullable = decoratedType.node.isNullable;
       if (isNullable) {
-        addNullable(node);
+        addChange(node, MakeNullable());
       }
       return InterfaceTypeImpl.explicit(element, arguments,
           nullabilitySuffix:
@@ -651,7 +723,7 @@
   }
 
   DartType _handleIncrementOrDecrement(MethodElement combiner,
-      AssignmentTargetInfo targetInfo, Expression node) {
+      AssignmentTargetInfo targetInfo, Expression node, Expression operand) {
     DartType combinedType;
     if (combiner == null) {
       combinedType = typeProvider.dynamicType;
@@ -667,9 +739,60 @@
       addProblem(node, const CompoundAssignmentCombinedNullable());
       combinedType = _typeSystem.promoteToNonNull(combinedType as TypeImpl);
     }
+    if (operand is SimpleIdentifier) {
+      var element = operand.staticElement;
+      if (element is PromotableElement) {
+        _flowAnalysis.write(element, combinedType);
+      }
+    }
     return combinedType;
   }
 
+  DartType _handleInvocationArguments(
+      AstNode node,
+      Iterable<AstNode> arguments,
+      TypeArgumentList typeArguments,
+      List<DartType> typeArgumentTypes,
+      FunctionType calleeType,
+      List<TypeParameterElement> constructorTypeParameters,
+      {DartType invokeType}) {
+    var typeFormals = constructorTypeParameters ?? calleeType.typeFormals;
+    if (typeFormals.isNotEmpty) {
+      throw UnimplementedError('TODO(paulberry): Invocation of generic method');
+    }
+    int i = 0;
+    var namedParameterTypes = <String, DartType>{};
+    var positionalParameterTypes = <DartType>[];
+    for (var parameter in calleeType.parameters) {
+      if (parameter.isNamed) {
+        namedParameterTypes[parameter.name] = parameter.type;
+      } else {
+        positionalParameterTypes.add(parameter.type);
+      }
+    }
+    for (var argument in arguments) {
+      String name;
+      Expression expression;
+      if (argument is NamedExpression) {
+        name = argument.name.label.name;
+        expression = argument.expression;
+      } else {
+        expression = argument as Expression;
+      }
+      DartType parameterType;
+      if (name != null) {
+        parameterType = namedParameterTypes[name];
+        assert(parameterType != null, 'Missing type for named parameter');
+      } else {
+        assert(i < positionalParameterTypes.length,
+            'Missing positional parameter at $i');
+        parameterType = positionalParameterTypes[i++];
+      }
+      visitSubexpression(expression, parameterType);
+    }
+    return calleeType.returnType;
+  }
+
   DartType _handlePropertyAccess(Expression node, Expression target,
       SimpleIdentifier propertyName, bool isNullAware) {
     var staticElement = propertyName.staticElement;
@@ -694,5 +817,25 @@
       [for (var argument in arguments.arguments) argument.accept(this)];
 }
 
+/// [NodeChange] reprensenting a type annotation that needs to have a question
+/// mark added to it, to make it nullable.
+class MakeNullable implements NodeChange {
+  factory MakeNullable() => const MakeNullable._();
+
+  const MakeNullable._();
+}
+
+/// Base class representing a change the FixBuilder wishes to make to an AST
+/// node.
+abstract class NodeChange {}
+
+/// [NodeChange] representing an expression that needs to have a null check
+/// added to it.
+class NullCheck implements NodeChange {
+  factory NullCheck() => const NullCheck._();
+
+  const NullCheck._();
+}
+
 /// Common supertype for problems reported by [FixBuilder.addProblem].
 abstract class Problem {}
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 85cdb6e..48d5425 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.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:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -10,7 +11,6 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:front_end/src/scanner/token.dart';
 import 'package:meta/meta.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
@@ -353,7 +353,7 @@
     var positionalParameters = const <DecoratedType>[];
     var namedParameters = const <String, DecoratedType>{};
     var typeFormalBounds = const <DecoratedType>[];
-    if (type is InterfaceType && type.typeParameters.isNotEmpty) {
+    if (type is InterfaceType && type.element.typeParameters.isNotEmpty) {
       if (node is TypeName) {
         if (node.typeArguments == null) {
           typeArguments = type.typeArguments
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index 0711d42..d974c23 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -50,6 +50,13 @@
   bool get isUnion => _kind == _NullabilityEdgeKind.union;
 
   @override
+  bool get isUpstreamTriggered {
+    if (!isHard) return false;
+    if (destinationNode._state != NullabilityState.nonNullable) return false;
+    return true;
+  }
+
+  @override
   NullabilityNode get sourceNode => upstreamNodes.first;
 
   @override
@@ -277,6 +284,9 @@
     _pendingEdges.addAll(never._upstreamEdges);
     while (_pendingEdges.isNotEmpty) {
       var edge = _pendingEdges.removeLast();
+      // We only propagate for nodes that are "upstream triggered".  At this
+      // point of propagation, a node is upstream triggered if it is hard.
+      assert(edge.isUpstreamTriggered == edge.isHard);
       if (!edge.isHard) continue;
       var node = edge.sourceNode;
       if (node is NullabilityNodeMutable &&
diff --git a/pkg/nnbd_migration/lib/src/utilities/annotation_tracker.dart b/pkg/nnbd_migration/lib/src/utilities/annotation_tracker.dart
index 20f7729..6ae2038 100644
--- a/pkg/nnbd_migration/lib/src/utilities/annotation_tracker.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/annotation_tracker.dart
@@ -12,7 +12,7 @@
 /// Mixing in this class should have very low overhead when assertions are
 /// disabled.
 mixin AnnotationTracker<T> on AstVisitor<T>, PermissiveModeVisitor<T> {
-  static _AnnotationTracker _annotationTracker;
+  _AnnotationTracker _annotationTracker;
 
   @override
   T visitAnnotation(Annotation node) {
@@ -27,9 +27,8 @@
   T visitCompilationUnit(CompilationUnit node) {
     T result;
     reportExceptionsIfPermissive(node, () {
-      _AnnotationTracker oldAnnotationTracker;
       assert(() {
-        oldAnnotationTracker = _annotationTracker;
+        assert(_annotationTracker == null);
         _annotationTracker = _AnnotationTracker();
         node.accept(_annotationTracker);
         return true;
@@ -39,7 +38,7 @@
         assert(_annotationTracker._nodes.isEmpty,
             'Annotation nodes not visited: ${_annotationTracker._nodes}');
       } finally {
-        _annotationTracker = oldAnnotationTracker;
+        _annotationTracker = null;
       }
     });
     return result;
diff --git a/pkg/nnbd_migration/lib/src/utilities/resolution_utils.dart b/pkg/nnbd_migration/lib/src/utilities/resolution_utils.dart
index 897d731..d6f7148 100644
--- a/pkg/nnbd_migration/lib/src/utilities/resolution_utils.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/resolution_utils.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/token.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
 /// This mixin provides utilities that are useful to visitors implementing
@@ -17,20 +16,6 @@
   bool isDeclaredOnObject(String name) =>
       (_objectGetNames ??= _computeObjectGetNames()).contains(name);
 
-  /// Determines whether the given property/method access token is null-aware.
-  bool isNullAwareToken(TokenType tokenType) {
-    switch (tokenType) {
-      case TokenType.PERIOD:
-      case TokenType.PERIOD_PERIOD:
-        return false;
-      case TokenType.QUESTION_PERIOD:
-        return true;
-      default:
-        throw new UnimplementedError(
-            'Unexpected token passed to isNullAwareToken: $tokenType');
-    }
-  }
-
   List<String> _computeObjectGetNames() {
     var result = <String>[];
     var objectClass = typeProvider.objectType.element;
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
index a91a24f..d975520 100644
--- a/pkg/nnbd_migration/pubspec.yaml
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -3,4 +3,5 @@
 environment:
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
+  _fe_analyzer_shared: 1.0.0
   analyzer: ^0.37.0
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
index a9f80a5..645ca41 100644
--- a/pkg/nnbd_migration/test/abstract_context.dart
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -105,7 +105,6 @@
 
   void tearDown() {
     AnalysisEngine.instance.clearCaches();
-    AnalysisEngine.instance.logger = null;
   }
 
   void _addTestPackageDependency(String name, String rootPath) {
diff --git a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
index 7a20cc3..fc51ced 100644
--- a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
+++ b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
@@ -113,7 +113,8 @@
     var typeFormal = TypeParameterElementImpl.synthetic('T')
       ..bound = typeProvider.numType;
     var decoratedType = decorate(FunctionTypeImpl.synthetic(
-        TypeParameterTypeImpl(typeFormal), [typeFormal], []));
+        TypeParameterTypeImpl(typeFormal), [typeFormal], [],
+        nullabilitySuffix: NullabilitySuffix.star));
     expect(decoratedType.typeFormalBounds, hasLength(1));
     checkNum(decoratedType.typeFormalBounds[0], never);
     checkTypeParameter(decoratedType.returnType, never, typeFormal);
@@ -122,34 +123,47 @@
   test_decorate_functionType_generic_no_explicit_bound() {
     var typeFormal = TypeParameterElementImpl.synthetic('T');
     var decoratedType = decorate(FunctionTypeImpl.synthetic(
-        TypeParameterTypeImpl(typeFormal), [typeFormal], []));
+        TypeParameterTypeImpl(typeFormal), [typeFormal], [],
+        nullabilitySuffix: NullabilitySuffix.star));
     expect(decoratedType.typeFormalBounds, hasLength(1));
     checkObject(decoratedType.typeFormalBounds[0], always);
     checkTypeParameter(decoratedType.returnType, never, typeFormal);
   }
 
   test_decorate_functionType_named_parameter() {
-    checkDynamic(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.voidType, [], [
-      ParameterElementImpl.synthetic(
-          'x', typeProvider.dynamicType, ParameterKind.NAMED)
-    ])).namedParameters['x']);
+    checkDynamic(decorate(FunctionTypeImpl.synthetic(
+            typeProvider.voidType,
+            [],
+            [
+              ParameterElementImpl.synthetic(
+                  'x', typeProvider.dynamicType, ParameterKind.NAMED)
+            ],
+            nullabilitySuffix: NullabilitySuffix.star))
+        .namedParameters['x']);
   }
 
   test_decorate_functionType_ordinary_parameter() {
-    checkDynamic(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.voidType, [], [
-      ParameterElementImpl.synthetic(
-          'x', typeProvider.dynamicType, ParameterKind.REQUIRED)
-    ])).positionalParameters[0]);
+    checkDynamic(decorate(FunctionTypeImpl.synthetic(
+            typeProvider.voidType,
+            [],
+            [
+              ParameterElementImpl.synthetic(
+                  'x', typeProvider.dynamicType, ParameterKind.REQUIRED)
+            ],
+            nullabilitySuffix: NullabilitySuffix.star))
+        .positionalParameters[0]);
   }
 
   test_decorate_functionType_positional_parameter() {
-    checkDynamic(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.voidType, [], [
-      ParameterElementImpl.synthetic(
-          'x', typeProvider.dynamicType, ParameterKind.POSITIONAL)
-    ])).positionalParameters[0]);
+    checkDynamic(decorate(FunctionTypeImpl.synthetic(
+            typeProvider.voidType,
+            [],
+            [
+              ParameterElementImpl.synthetic(
+                  'x', typeProvider.dynamicType, ParameterKind.POSITIONAL)
+            ],
+            nullabilitySuffix: NullabilitySuffix.star))
+        .positionalParameters[0]);
   }
 
   test_decorate_functionType_question() {
@@ -161,9 +175,10 @@
   }
 
   test_decorate_functionType_returnType() {
-    checkDynamic(
-        decorate(FunctionTypeImpl.synthetic(typeProvider.dynamicType, [], []))
-            .returnType);
+    checkDynamic(decorate(FunctionTypeImpl.synthetic(
+            typeProvider.dynamicType, [], [],
+            nullabilitySuffix: NullabilitySuffix.star))
+        .returnType);
   }
 
   test_decorate_functionType_star() {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 315052a..b441ee4 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -2352,6 +2352,28 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  test_null_check_in_cascade_target() async {
+    var content = '''
+class _C {
+  f() {}
+}
+_C g(int/*!*/ i) => _C();
+test(int/*?*/ j) {
+  g(j)..f();
+}
+''';
+    var expected = '''
+class _C {
+  f() {}
+}
+_C g(int/*!*/ i) => _C();
+test(int?/*?*/ j) {
+  g(j!)..f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38339')
   test_operator_eq_with_inferred_parameter_type() async {
     var content = '''
diff --git a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
index 50a4879..06c8b3c 100644
--- a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
@@ -14,6 +14,108 @@
 
 @reflectiveTest
 class EdgeBuilderFlowAnalysisTest extends EdgeBuilderTestBase {
+  test_as() async {
+    await analyze('''
+void f(num n) {
+  h(n);
+  n as int;
+  g(n);
+}
+void g(int i) {}
+void h(num m) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var nNode = decoratedTypeAnnotation('num n').node;
+    var mNode = decoratedTypeAnnotation('num m').node;
+    // No edge from n to i because n is known to be non-nullable at the site of
+    // the call to g
+    assertNoEdge(nNode, iNode);
+    // But there is an edge from n to m.
+    assertEdge(nNode, mNode, hard: true);
+  }
+
+  test_assert_initializer_condition_promotes_to_message() async {
+    await analyze('''
+class C {
+  C(int i)
+      : assert(i == null, g(i)) {
+    h(i);
+  }
+}
+String g(int j) => 'foo';
+void h(int k) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var kNode = decoratedTypeAnnotation('int k').node;
+    // No edge from i to j because i is known to be non-nullable at the site of
+    // the call to g
+    assertNoEdge(iNode, jNode);
+    // But there is an edge from i to k.
+    assertEdge(iNode, kNode, hard: true);
+  }
+
+  test_assert_initializer_does_not_promote_beyond_assert() async {
+    await analyze('''
+class C {
+  C(int i)
+      : assert(i != null) {
+    g(i);
+    if (i == null) return;
+    h(i);
+  }
+}
+void g(int j) {}
+void h(int k) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var kNode = decoratedTypeAnnotation('int k').node;
+    // There is an edge from i to j because i not promoted by the assert.
+    assertEdge(iNode, jNode, hard: true);
+    // But there is no edge from i to k.
+    assertNoEdge(iNode, kNode);
+  }
+
+  test_assert_statement_condition_promotes_to_message() async {
+    await analyze('''
+void f(int i) {
+  assert(i == null, g(i));
+  h(i);
+}
+String g(int j) => 'foo';
+void h(int k) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var kNode = decoratedTypeAnnotation('int k').node;
+    // No edge from i to j because i is known to be non-nullable at the site of
+    // the call to g
+    assertNoEdge(iNode, jNode);
+    // But there is an edge from i to k.
+    assertEdge(iNode, kNode, hard: true);
+  }
+
+  test_assert_statement_does_not_promote_beyond_assert() async {
+    await analyze('''
+void f(int i) {
+  assert(i != null);
+  g(i);
+  if (i == null) return;
+  h(i);
+}
+void g(int j) {}
+void h(int k) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var jNode = decoratedTypeAnnotation('int j').node;
+    var kNode = decoratedTypeAnnotation('int k').node;
+    // There is an edge from i to j because i not promoted by the assert.
+    assertEdge(iNode, jNode, hard: true);
+    // But there is no edge from i to k.
+    assertNoEdge(iNode, kNode);
+  }
+
   test_assignmentExpression() async {
     await analyze('''
 void f(int i, int j) {
@@ -62,6 +164,29 @@
     assertEdge(gReturnNode, iNode, hard: false);
   }
 
+  test_assignmentExpression_null_aware() async {
+    await analyze('''
+void f(bool b, int i, int j) {
+  if (b) {
+    j ??= i is int ? i : throw 'foo';
+    g(i);
+    j = i is int ? i : throw 'foo';
+    h(i);
+  }
+}
+void g(int k) {}
+void h(int l) {}
+''');
+    var iNode = decoratedTypeAnnotation('int i').node;
+    var kNode = decoratedTypeAnnotation('int k').node;
+    var lNode = decoratedTypeAnnotation('int l').node;
+    // No edge from i to l because i's type is promoted to non-nullable
+    assertNoEdge(iNode, lNode);
+    // But there is an edge from i to k, because the RHS of the `??=` is not
+    // guaranteed to execute
+    assertEdge(iNode, kNode, hard: false);
+  }
+
   test_assignmentExpression_write_after_rhs() async {
     await analyze('''
 void f(int i) {
@@ -1061,6 +1186,106 @@
     assertEdge(iNode, jNode, hard: false);
   }
 
+  test_postfixDecrement() async {
+    await analyze('''
+void f(C c1) {
+  if (c1 != null) {
+    g(c1);
+    c1--;
+    h(c1);
+  }
+}
+void g(C c2) {}
+void h(C c3) {}
+class C {
+  C operator-(int i) => this;
+}
+''');
+    var c1Node = decoratedTypeAnnotation('C c1').node;
+    var c2Node = decoratedTypeAnnotation('C c2').node;
+    var c3Node = decoratedTypeAnnotation('C c3').node;
+    // No edge from c1 to c2 because c1's type is promoted to non-nullable
+    assertNoEdge(c1Node, c2Node);
+    // But there is an edge from c1 to c3, because the decrement un-does the
+    // promotion.
+    assertEdge(c1Node, c3Node, hard: false);
+  }
+
+  test_postfixIncrement() async {
+    await analyze('''
+void f(C c1) {
+  if (c1 != null) {
+    g(c1);
+    c1++;
+    h(c1);
+  }
+}
+void g(C c2) {}
+void h(C c3) {}
+class C {
+  C operator+(int i) => this;
+}
+''');
+    var c1Node = decoratedTypeAnnotation('C c1').node;
+    var c2Node = decoratedTypeAnnotation('C c2').node;
+    var c3Node = decoratedTypeAnnotation('C c3').node;
+    // No edge from c1 to c2 because c1's type is promoted to non-nullable
+    assertNoEdge(c1Node, c2Node);
+    // But there is an edge from c1 to c3, because the increment un-does the
+    // promotion.
+    assertEdge(c1Node, c3Node, hard: false);
+  }
+
+  test_prefixDecrement() async {
+    await analyze('''
+void f(C c1) {
+  if (c1 != null) {
+    g(c1);
+    --c1;
+    h(c1);
+  }
+}
+void g(C c2) {}
+void h(C c3) {}
+class C {
+  C operator-(int i) => this;
+}
+''');
+    var c1Node = decoratedTypeAnnotation('C c1').node;
+    var c2Node = decoratedTypeAnnotation('C c2').node;
+    var c3Node = decoratedTypeAnnotation('C c3').node;
+    // No edge from c1 to c2 because c1's type is promoted to non-nullable
+    assertNoEdge(c1Node, c2Node);
+    // But there is an edge from c1 to c3, because the decrement un-does the
+    // promotion.
+    assertEdge(c1Node, c3Node, hard: false);
+  }
+
+  test_prefixIncrement() async {
+    await analyze('''
+void f(C c1) {
+  if (c1 != null) {
+    g(c1);
+    ++c1;
+    h(c1);
+  }
+}
+void g(C c2) {}
+void h(C c3) {}
+class C {
+  C operator+(int i) => this;
+}
+''');
+    var c1Node = decoratedTypeAnnotation('C c1').node;
+    var c2Node = decoratedTypeAnnotation('C c2').node;
+    var c3Node = decoratedTypeAnnotation('C c3').node;
+    // No edge from c1 to c2 because c1's type is promoted to non-nullable
+    assertNoEdge(c1Node, c2Node);
+    // But there is an edge from c1 to c3, because the increment un-does the
+    // promotion.
+    assertEdge(c1Node, c3Node, hard: false);
+  }
+
   test_rethrow() async {
     await analyze('''
 void f(int i, int j) {
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 05fc775..9e3cc4e 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -74,8 +74,7 @@
         ..supertype = _myListOfListSupertype.type as InterfaceType;
     }
     return DecoratedType(
-        InterfaceTypeImpl(_myListOfListClass)
-          ..typeArguments = [elementType.type],
+        InterfaceTypeImpl.explicit(_myListOfListClass, [elementType.type]),
         newNode(),
         typeArguments: [elementType]);
   }
@@ -1202,6 +1201,15 @@
     assertEdge(right, expression, guards: [left], hard: false);
   }
 
+  test_binaryExpression_questionQuestion_genericReturnType() async {
+    await analyze('''
+class C<E> {
+  C<E> operator +(C<E> c) => this;
+}
+C<int> f(C<int> i, C<int> j) => i ?? j;
+''');
+  }
+
   test_binaryExpression_right_dynamic() async {
     await analyze('''
 class C {
@@ -1378,6 +1386,15 @@
         decoratedTypeAnnotation('int/*1*/').node);
   }
 
+  test_class_metadata() async {
+    await analyze('''
+@deprecated
+class C {}
+''');
+    // No assertions needed; the AnnotationTracker mixin verifies that the
+    // metadata was visited.
+  }
+
   test_conditionalExpression_condition_check() async {
     await analyze('''
 int f(bool b, int i, int j) {
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 9019de2..6f1b668 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -93,7 +93,7 @@
 _f(dynamic x, int/*?*/ y) => x += y + 1;
 ''');
     visitSubexpression(findNode.assignment('+='), 'dynamic',
-        nullChecked: {findNode.simple('y +')});
+        changes: {findNode.simple('y +'): NullCheck()});
   }
 
   test_assignmentExpression_compound_intRules() async {
@@ -130,7 +130,7 @@
     // assignment `x = y` should be null checked because the RHS of `&&` cannot
     // be nullable.
     visitSubexpression(findNode.binary('&&'), 'bool',
-        nullChecked: {findNode.parenthesized('x = y')});
+        changes: {findNode.parenthesized('x = y'): NullCheck()});
   }
 
   test_assignmentExpression_compound_rhs_nonNullable() async {
@@ -153,7 +153,7 @@
 _f(_C/*!*/ x, int/*?*/ y) => x += y;
 ''');
     visitSubexpression(findNode.assignment('+='), '_D',
-        nullChecked: {findNode.simple('y;')});
+        changes: {findNode.simple('y;'): NullCheck()});
   }
 
   test_assignmentExpression_compound_rhs_nullable_noCheck() async {
@@ -167,6 +167,23 @@
     visitSubexpression(findNode.assignment('+='), '_D');
   }
 
+  test_assignmentExpression_null_aware_rhs_does_not_promote() async {
+    await analyze('''
+_f(bool/*?*/ b, int/*?*/ i) {
+  b ??= i.isEven; // 1
+  b = i.isEven; // 2
+  b = i.isEven; // 3
+}
+''');
+    // The null check inserted at 1 fails to promote i because it's inside the
+    // `??=`, so a null check is inserted at 2.  This does promote i, so no null
+    // check is inserted at 3.
+    visitStatement(findNode.block('{'), changes: {
+      findNode.simple('i.isEven; // 1'): NullCheck(),
+      findNode.simple('i.isEven; // 2'): NullCheck()
+    });
+  }
+
   test_assignmentExpression_null_aware_rhs_nonNullable() async {
     await analyze('''
 abstract class _B {}
@@ -216,7 +233,7 @@
 _f(int/*!*/ x, int/*?*/ y) => x = y;
 ''');
     visitSubexpression(findNode.assignment('= '), 'int',
-        contextType: objectType, nullChecked: {findNode.simple('y;')});
+        contextType: objectType, changes: {findNode.simple('y;'): NullCheck()});
   }
 
   test_assignmentExpression_simple_nullable_to_nullable() async {
@@ -263,7 +280,7 @@
 _f(_C/*?*/ c) => c['foo'] += 0;
 ''');
     visitAssignmentTarget(findNode.index('c['), 'int', 'num',
-        nullChecked: {findNode.simple('c[')});
+        changes: {findNode.simple('c['): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_compound_simple_check_rhs() async {
@@ -275,7 +292,7 @@
 _f(_C c, String/*?*/ s) => c[s] += 0;
 ''');
     visitAssignmentTarget(findNode.index('c['), 'int', 'num',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_compound_substituted() async {
@@ -298,7 +315,7 @@
 _f(_C<int, String/*!*/> c, String/*?*/ s) => c[s] += 1;
 ''');
     visitAssignmentTarget(findNode.index('c['), 'int', 'int',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_compound_substituted_no_check_rhs() async {
@@ -339,7 +356,7 @@
 _f(_C/*?*/ c) => c['foo'] = 0;
 ''');
     visitAssignmentTarget(findNode.index('c['), null, 'num',
-        nullChecked: {findNode.simple('c[')});
+        changes: {findNode.simple('c['): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_simple_check_rhs() async {
@@ -351,7 +368,7 @@
 _f(_C c, String/*?*/ s) => c[s] = 0;
 ''');
     visitAssignmentTarget(findNode.index('c['), null, 'num',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_substituted() async {
@@ -369,12 +386,12 @@
     await analyze('''
 class _C<T, U> {
   T operator[](U u) => throw 'foo';
-  void operator[]=(U/*?*/ u, T t) {}
+  void operator[]=(U/*!*/ u, T t) {}
 }
 _f(_C<int, String/*!*/> c, String/*?*/ s) => c[s] = 1;
 ''');
     visitAssignmentTarget(findNode.index('c['), null, 'int',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_assignmentTarget_indexExpression_substituted_no_check_rhs() async {
@@ -460,7 +477,7 @@
 _f(_C/*?*/ c) => (c).x += 1;
 ''');
     visitAssignmentTarget(findNode.propertyAccess('(c).x'), 'int', 'num',
-        nullChecked: {findNode.parenthesized('(c).x')});
+        changes: {findNode.parenthesized('(c).x'): NullCheck()});
   }
 
   test_assignmentTarget_propertyAccess_getter_setter_nonNullable() async {
@@ -684,7 +701,7 @@
     var xRef = findNode.simple('x &&');
     var yRef = findNode.simple('y;');
     visitSubexpression(findNode.binary('&&'), 'bool',
-        nullChecked: {xRef, yRef});
+        changes: {xRef: NullCheck(), yRef: NullCheck()});
   }
 
   test_binaryExpression_bang_eq() async {
@@ -721,7 +738,7 @@
     var xRef = findNode.simple('x ||');
     var yRef = findNode.simple('y;');
     visitSubexpression(findNode.binary('||'), 'bool',
-        nullChecked: {xRef, yRef});
+        changes: {xRef: NullCheck(), yRef: NullCheck()});
   }
 
   test_binaryExpression_eq_eq() async {
@@ -750,7 +767,7 @@
     // The null check on the RHS of the `??` doesn't promote, because it is not
     // guaranteed to execute.
     visitSubexpression(findNode.listLiteral('['), 'List<dynamic>',
-        nullChecked: {findNode.simple('y +')});
+        changes: {findNode.simple('y +'): NullCheck()});
   }
 
   test_binaryExpression_question_question_nullChecked() async {
@@ -761,7 +778,7 @@
 ''');
     var yRef = findNode.simple('y;');
     visitSubexpression(findNode.binary('??'), 'num',
-        contextType: objectType, nullChecked: {yRef});
+        contextType: objectType, changes: {yRef: NullCheck()});
   }
 
   test_binaryExpression_userDefinable_dynamic() async {
@@ -797,7 +814,7 @@
 _f(_C/*?*/ c) => c + 'foo';
 ''');
     visitSubexpression(findNode.binary('c +'), 'int',
-        nullChecked: {findNode.simple('c +')});
+        changes: {findNode.simple('c +'): NullCheck()});
   }
 
   test_binaryExpression_userDefinable_simple_check_rhs() async {
@@ -808,7 +825,7 @@
 _f(_C c, String/*?*/ s) => c + s;
 ''');
     visitSubexpression(findNode.binary('c +'), 'int',
-        nullChecked: {findNode.simple('s;')});
+        changes: {findNode.simple('s;'): NullCheck()});
   }
 
   test_binaryExpression_userDefinable_substituted() async {
@@ -824,12 +841,12 @@
   test_binaryExpression_userDefinable_substituted_check_rhs() async {
     await analyze('''
 class _C<T, U> {
-  T operator+(U u) => throw 'foo';
+  T operator+(U/*!*/ u) => throw 'foo';
 }
 _f(_C<int, String/*!*/> c, String/*?*/ s) => c + s;
 ''');
     visitSubexpression(findNode.binary('c +'), 'int',
-        nullChecked: {findNode.simple('s;')});
+        changes: {findNode.simple('s;'): NullCheck()});
   }
 
   test_binaryExpression_userDefinable_substituted_no_check_rhs() async {
@@ -851,8 +868,10 @@
   }
 }
 ''');
-    visitStatement(findNode.statement('{ // block'),
-        nullChecked: {findNode.simple('x + 1'), findNode.simple('y + 1')});
+    visitStatement(findNode.statement('{ // block'), changes: {
+      findNode.simple('x + 1'): NullCheck(),
+      findNode.simple('y + 1'): NullCheck()
+    });
   }
 
   test_booleanLiteral() async {
@@ -878,7 +897,7 @@
     // No explicit check needs to be added to either `x && true`, because there
     // is already an explicit null check inserted for the condition.
     visitSubexpression(findNode.conditionalExpression('x ?'), 'bool',
-        nullChecked: {findNode.simple('x ?')});
+        changes: {findNode.simple('x ?'): NullCheck()});
   }
 
   test_conditionalExpression_flow_then_else() async {
@@ -888,9 +907,9 @@
     // No explicit check needs to be added to the final reference to `y`,
     // because null checks are added to the "then" and "else" branches promoting
     // y.
-    visitSubexpression(findNode.binary('&& y'), 'bool', nullChecked: {
-      findNode.simple('y && true) '),
-      findNode.simple('y && true))')
+    visitSubexpression(findNode.binary('&& y'), 'bool', changes: {
+      findNode.simple('y && true) '): NullCheck(),
+      findNode.simple('y && true))'): NullCheck()
     });
   }
 
@@ -925,7 +944,65 @@
 }
 ''');
     visitStatement(findNode.statement('x = y'),
-        nullChecked: {findNode.simple('y;')});
+        changes: {findNode.simple('y;'): NullCheck()});
+  }
+
+  test_functionExpressionInvocation_dynamic() async {
+    await analyze('''
+_f(dynamic d) => d();
+''');
+    visitSubexpression(findNode.functionExpressionInvocation('d('), 'dynamic');
+  }
+
+  test_functionExpressionInvocation_function_checked() async {
+    await analyze('''
+_f(Function/*?*/ func) => func();
+''');
+    visitSubexpression(
+        findNode.functionExpressionInvocation('func('), 'dynamic',
+        changes: {findNode.simple('func()'): NullCheck()});
+  }
+
+  test_functionExpressionInvocation_getter() async {
+    await analyze('''
+abstract class _C {
+  int Function() get f;
+}
+_f(_C c) => (c.f)();
+''');
+    visitSubexpression(findNode.functionExpressionInvocation('c.f'), 'int');
+  }
+
+  test_functionExpressionInvocation_getter_looksLikeMethodCall() async {
+    await analyze('''
+abstract class _C {
+  int Function() get f;
+}
+_f(_C c) => c.f();
+''');
+    visitSubexpression(findNode.functionExpressionInvocation('c.f'), 'int');
+  }
+
+  test_functionExpressionInvocation_getter_nullChecked() async {
+    await analyze('''
+abstract class _C {
+  int Function()/*?*/ get f;
+}
+_f(_C c) => (c.f)();
+''');
+    visitSubexpression(findNode.functionExpressionInvocation('c.f'), 'int',
+        changes: {findNode.parenthesized('c.f'): NullCheck()});
+  }
+
+  test_functionExpressionInvocation_getter_nullChecked_looksLikeMethodCall() async {
+    await analyze('''
+abstract class _C {
+  int Function()/*?*/ get f;
+}
+_f(_C c) => c.f();
+''');
+    visitSubexpression(findNode.functionExpressionInvocation('c.f'), 'int',
+        changes: {findNode.propertyAccess('c.f'): NullCheck()});
   }
 
   test_ifStatement_flow_promote_in_else() async {
@@ -939,7 +1016,7 @@
 }
 ''');
     visitStatement(findNode.statement('if'),
-        nullChecked: {findNode.simple('x + 1')});
+        changes: {findNode.simple('x + 1'): NullCheck()});
   }
 
   test_ifStatement_flow_promote_in_then() async {
@@ -953,7 +1030,7 @@
 }
 ''');
     visitStatement(findNode.statement('if'),
-        nullChecked: {findNode.simple('x + 2')});
+        changes: {findNode.simple('x + 2'): NullCheck()});
   }
 
   test_ifStatement_flow_promote_in_then_no_else() async {
@@ -993,7 +1070,7 @@
 _f(_C/*?*/ c) => c['foo'];
 ''');
     visitSubexpression(findNode.index('c['), 'int',
-        nullChecked: {findNode.simple('c[')});
+        changes: {findNode.simple('c['): NullCheck()});
   }
 
   test_indexExpression_simple_check_rhs() async {
@@ -1004,7 +1081,7 @@
 _f(_C c, String/*?*/ s) => c[s];
 ''');
     visitSubexpression(findNode.index('c['), 'int',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_indexExpression_substituted() async {
@@ -1020,12 +1097,12 @@
   test_indexExpression_substituted_check_rhs() async {
     await analyze('''
 class _C<T, U> {
-  T operator[](U u) => throw 'foo';
+  T operator[](U/*!*/ u) => throw 'foo';
 }
 _f(_C<int, String/*!*/> c, String/*?*/ s) => c[s];
 ''');
     visitSubexpression(findNode.index('c['), 'int',
-        nullChecked: {findNode.simple('s]')});
+        changes: {findNode.simple('s]'): NullCheck()});
   }
 
   test_indexExpression_substituted_no_check_rhs() async {
@@ -1057,7 +1134,104 @@
 _f(int/*?*/ x) => <int/*!*/>[x];
 ''');
     visitSubexpression(findNode.listLiteral('['), 'List<int>',
-        nullChecked: {findNode.simple('x]')});
+        changes: {findNode.simple('x]'): NullCheck()});
+  }
+
+  test_methodInvocation_dynamic() async {
+    await analyze('''
+Object/*!*/ _f(dynamic d) => d.f();
+''');
+    visitSubexpression(findNode.methodInvocation('d.f'), 'dynamic',
+        contextType: objectType);
+  }
+
+  test_methodInvocation_namedParameter() async {
+    await analyze('''
+abstract class _C {
+  int f({int/*!*/ x});
+}
+_f(_C c, int/*?*/ y) => c.f(x: y);
+''');
+    visitSubexpression(findNode.methodInvocation('c.f'), 'int',
+        changes: {findNode.simple('y);'): NullCheck()});
+  }
+
+  test_methodInvocation_ordinaryParameter() async {
+    await analyze('''
+abstract class _C {
+  int f(int/*!*/ x);
+}
+_f(_C c, int/*?*/ y) => c.f(y);
+''');
+    visitSubexpression(findNode.methodInvocation('c.f'), 'int',
+        changes: {findNode.simple('y);'): NullCheck()});
+  }
+
+  test_methodInvocation_return_nonNullable() async {
+    await analyze('''
+abstract class _C {
+  int f();
+}
+_f(_C c) => c.f();
+''');
+    visitSubexpression(findNode.methodInvocation('c.f'), 'int');
+  }
+
+  test_methodInvocation_return_nonNullable_check_target() async {
+    await analyze('''
+abstract class _C {
+  int f();
+}
+_f(_C/*?*/ c) => c.f();
+''');
+    visitSubexpression(findNode.methodInvocation('c.f'), 'int',
+        changes: {findNode.simple('c.f'): NullCheck()});
+  }
+
+  test_methodInvocation_return_nonNullable_nullAware() async {
+    await analyze('''
+abstract class _C {
+  int f();
+}
+_f(_C/*?*/ c) => c?.f();
+''');
+    visitSubexpression(findNode.methodInvocation('c?.f'), 'int?');
+  }
+
+  test_methodInvocation_return_nullable() async {
+    await analyze('''
+abstract class _C {
+  int/*?*/ f();
+}
+_f(_C c) => c.f();
+''');
+    visitSubexpression(findNode.methodInvocation('c.f'), 'int?');
+  }
+
+  test_methodInvocation_static() async {
+    await analyze('''
+_f() => _C.g();
+class _C {
+  static int g() => 1;
+}
+''');
+    visitSubexpression(findNode.methodInvocation('_C.g();'), 'int');
+  }
+
+  test_methodInvocation_topLevel() async {
+    await analyze('''
+_f() => _g();
+int _g() => 1;
+''');
+    visitSubexpression(findNode.methodInvocation('_g();'), 'int');
+  }
+
+  test_methodInvocation_toString() async {
+    await analyze('''
+abstract class _C {}
+_f(_C/*?*/ c) => c.toString();
+''');
+    visitSubexpression(findNode.methodInvocation('c.toString'), 'String');
   }
 
   test_nullAssertion_promotes() async {
@@ -1067,7 +1241,7 @@
     // Only the first `x` is null-checked because thereafter, the type of `x` is
     // promoted to `bool`.
     visitSubexpression(findNode.binary('&&'), 'bool',
-        nullChecked: {findNode.simple('x &&')});
+        changes: {findNode.simple('x &&'): NullCheck()});
   }
 
   test_nullLiteral() async {
@@ -1136,6 +1310,23 @@
     });
   }
 
+  test_postfixExpression_decrement_undoes_promotion() async {
+    await analyze('''
+abstract class _C {
+  _C/*?*/ operator-(int value);
+}
+_f(_C/*?*/ c) { // method
+  if (c != null) {
+    c--;
+    _g(c);
+  }
+}
+_g(_C/*!*/ c) {}
+''');
+    visitStatement(findNode.block('{ // method'),
+        changes: {findNode.simple('c);'): NullCheck()});
+  }
+
   test_postfixExpression_dynamic() async {
     await analyze('''
 _f(dynamic x) => x++;
@@ -1143,6 +1334,23 @@
     visitSubexpression(findNode.postfix('++'), 'dynamic');
   }
 
+  test_postfixExpression_increment_undoes_promotion() async {
+    await analyze('''
+abstract class _C {
+  _C/*?*/ operator+(int value);
+}
+_f(_C/*?*/ c) { // method
+  if (c != null) {
+    c++;
+    _g(c);
+  }
+}
+_g(_C/*!*/ c) {}
+''');
+    visitStatement(findNode.block('{ // method'),
+        changes: {findNode.simple('c);'): NullCheck()});
+  }
+
   test_postfixExpression_lhs_nullable_problem() async {
     await analyze('''
 abstract class _C {
@@ -1208,7 +1416,7 @@
 _f(_C/*?*/ c) => c.x;
 ''');
     visitSubexpression(findNode.prefixed('c.x'), 'int',
-        nullChecked: {findNode.simple('c.x')});
+        changes: {findNode.simple('c.x'): NullCheck()});
   }
 
   test_prefixedIdentifier_getter_nonNullable() async {
@@ -1282,7 +1490,7 @@
 _f(bool/*?*/ x) => !x;
 ''');
     visitSubexpression(findNode.prefix('!x'), 'bool',
-        nullChecked: {findNode.simple('x;')});
+        changes: {findNode.simple('x;'): NullCheck()});
   }
 
   test_prefixExpression_combined_nullable_noProblem() async {
@@ -1330,6 +1538,40 @@
     });
   }
 
+  test_prefixExpression_decrement_undoes_promotion() async {
+    await analyze('''
+abstract class _C {
+  _C/*?*/ operator-(int value);
+}
+_f(_C/*?*/ c) { // method
+  if (c != null) {
+    --c;
+    _g(c);
+  }
+}
+_g(_C/*!*/ c) {}
+''');
+    visitStatement(findNode.block('{ // method'),
+        changes: {findNode.simple('c);'): NullCheck()});
+  }
+
+  test_prefixExpression_increment_undoes_promotion() async {
+    await analyze('''
+abstract class _C {
+  _C/*?*/ operator+(int value);
+}
+_f(_C/*?*/ c) { // method
+  if (c != null) {
+    ++c;
+    _g(c);
+  }
+}
+_g(_C/*!*/ c) {}
+''');
+    visitStatement(findNode.block('{ // method'),
+        changes: {findNode.simple('c);'): NullCheck()});
+  }
+
   test_prefixExpression_intRules() async {
     await analyze('''
 _f(int x) => ++x;
@@ -1374,7 +1616,7 @@
 _f(int/*?*/ x) => -x;
 ''');
     visitSubexpression(findNode.prefix('-x'), 'int',
-        nullChecked: {findNode.simple('x;')});
+        changes: {findNode.simple('x;'): NullCheck()});
   }
 
   test_prefixExpression_minus_substitution() async {
@@ -1417,7 +1659,7 @@
 _f(int/*?*/ x) => ~x;
 ''');
     visitSubexpression(findNode.prefix('~x'), 'int',
-        nullChecked: {findNode.simple('x;')});
+        changes: {findNode.simple('x;'): NullCheck()});
   }
 
   test_prefixExpression_tilde_substitution() async {
@@ -1466,7 +1708,7 @@
 _f(_C/*?*/ c) => (c).x;
 ''');
     visitSubexpression(findNode.propertyAccess('(c).x'), 'int',
-        nullChecked: {findNode.parenthesized('(c).x')});
+        changes: {findNode.parenthesized('(c).x'): NullCheck()});
   }
 
   test_propertyAccess_getter_nonNullable() async {
@@ -1695,7 +1937,7 @@
 _f(int/*?*/ i) => throw i;
 ''');
     visitSubexpression(findNode.throw_('throw'), 'Never',
-        nullChecked: {findNode.simple('i;')});
+        changes: {findNode.simple('i;'): NullCheck()});
   }
 
   test_throw_simple() async {
@@ -1731,7 +1973,7 @@
 ''');
     var listIntAnnotation = findNode.typeAnnotation('List<int>');
     visitTypeAnnotation(listIntAnnotation, 'List<int>?',
-        nullable: {listIntAnnotation});
+        changes: {listIntAnnotation: MakeNullable()});
   }
 
   test_typeName_generic_nullable_arg() async {
@@ -1741,7 +1983,7 @@
 }
 ''');
     visitTypeAnnotation(findNode.typeAnnotation('List<int>'), 'List<int?>',
-        nullable: {findNode.typeAnnotation('int')});
+        changes: {findNode.typeAnnotation('int'): MakeNullable()});
   }
 
   test_typeName_simple_nonNullable() async {
@@ -1760,7 +2002,8 @@
 }
 ''');
     var intAnnotation = findNode.typeAnnotation('int');
-    visitTypeAnnotation((intAnnotation), 'int?', nullable: {intAnnotation});
+    visitTypeAnnotation((intAnnotation), 'int?',
+        changes: {intAnnotation: MakeNullable()});
   }
 
   test_typeName_void() async {
@@ -1797,7 +2040,7 @@
 }
 ''');
     visitStatement(findNode.statement('int x'),
-        nullable: {findNode.typeAnnotation('int')});
+        changes: {findNode.typeAnnotation('int'): MakeNullable()});
   }
 
   test_variableDeclaration_typed_uninitialized() async {
@@ -1833,13 +2076,15 @@
   bool z = x && y;
 }
 ''');
-    visitStatement(findNode.statement('bool z'),
-        nullChecked: {findNode.simple('x &&'), findNode.simple('y;')});
+    visitStatement(findNode.statement('bool z'), changes: {
+      findNode.simple('x &&'): NullCheck(),
+      findNode.simple('y;'): NullCheck()
+    });
   }
 
   void visitAssignmentTarget(
       Expression node, String expectedReadType, String expectedWriteType,
-      {Set<Expression> nullChecked = const <Expression>{},
+      {Map<AstNode, NodeChange> changes = const <Expression, NodeChange>{},
       Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{}}) {
     _FixBuilder fixBuilder = _createFixBuilder(node);
     var targetInfo =
@@ -1852,46 +2097,40 @@
     }
     expect((targetInfo.writeType as TypeImpl).toString(withNullability: true),
         expectedWriteType);
-    expect(fixBuilder.nullCheckedExpressions, nullChecked);
+    expect(fixBuilder.changes, changes);
     expect(fixBuilder.problems, problems);
   }
 
   void visitStatement(Statement node,
-      {Set<Expression> nullChecked = const <Expression>{},
-      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{},
-      Set<TypeAnnotation> nullable = const <TypeAnnotation>{}}) {
+      {Map<AstNode, NodeChange> changes = const <Expression, NodeChange>{},
+      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{}}) {
     _FixBuilder fixBuilder = _createFixBuilder(node);
     var type = node.accept(fixBuilder);
     expect(type, null);
-    expect(fixBuilder.nullCheckedExpressions, nullChecked);
+    expect(fixBuilder.changes, changes);
     expect(fixBuilder.problems, problems);
-    expect(fixBuilder.nullable, nullable);
   }
 
   void visitSubexpression(Expression node, String expectedType,
       {DartType contextType,
-      Set<Expression> nullChecked = const <Expression>{},
-      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{},
-      Set<TypeAnnotation> nullable = const <TypeAnnotation>{}}) {
+      Map<AstNode, NodeChange> changes = const <Expression, NodeChange>{},
+      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{}}) {
     contextType ??= dynamicType;
     _FixBuilder fixBuilder = _createFixBuilder(node);
     var type = fixBuilder.visitSubexpression(node, contextType);
     expect((type as TypeImpl).toString(withNullability: true), expectedType);
-    expect(fixBuilder.nullCheckedExpressions, nullChecked);
+    expect(fixBuilder.changes, changes);
     expect(fixBuilder.problems, problems);
-    expect(fixBuilder.nullable, nullable);
   }
 
   void visitTypeAnnotation(TypeAnnotation node, String expectedType,
-      {Set<Expression> nullChecked = const <Expression>{},
-      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{},
-      Set<TypeAnnotation> nullable = const <TypeAnnotation>{}}) {
+      {Map<AstNode, NodeChange> changes = const <AstNode, NodeChange>{},
+      Map<AstNode, Set<Problem>> problems = const <AstNode, Set<Problem>>{}}) {
     _FixBuilder fixBuilder = _createFixBuilder(node);
     var type = node.accept(fixBuilder);
     expect((type as TypeImpl).toString(withNullability: true), expectedType);
-    expect(fixBuilder.nullCheckedExpressions, nullChecked);
+    expect(fixBuilder.changes, changes);
     expect(fixBuilder.problems, problems);
-    expect(fixBuilder.nullable, nullable);
   }
 
   _FixBuilder _createFixBuilder(AstNode node) {
@@ -1899,33 +2138,33 @@
         typeProvider, typeSystem, variables);
     var body = node.thisOrAncestorOfType<FunctionBody>();
     var declaration = body.thisOrAncestorOfType<Declaration>();
-    fixBuilder.createFlowAnalysis(declaration, null);
+    FormalParameterList parameters;
+    if (declaration is FunctionDeclaration) {
+      parameters = declaration.functionExpression.parameters;
+    }
+    fixBuilder.createFlowAnalysis(declaration, parameters);
     return fixBuilder;
   }
 }
 
 class _FixBuilder extends FixBuilder {
-  final Set<Expression> nullCheckedExpressions = {};
-
-  final Set<TypeAnnotation> nullable = {};
+  final Map<AstNode, NodeChange> changes = {};
 
   final Map<AstNode, Set<Problem>> problems = {};
 
-  _FixBuilder(Source source, DecoratedClassHierarchy decoratedClassHierarchy,
-      TypeProvider typeProvider, TypeSystem typeSystem, Variables variables)
+  _FixBuilder(
+      Source source,
+      DecoratedClassHierarchy decoratedClassHierarchy,
+      TypeProvider typeProvider,
+      Dart2TypeSystem typeSystem,
+      Variables variables)
       : super(source, decoratedClassHierarchy, typeProvider, typeSystem,
             variables);
 
   @override
-  void addNullable(TypeAnnotation node) {
-    var newlyAdded = nullable.add(node);
-    expect(newlyAdded, true);
-  }
-
-  @override
-  void addNullCheck(Expression subexpression) {
-    var newlyAdded = nullCheckedExpressions.add(subexpression);
-    expect(newlyAdded, true);
+  void addChange(AstNode node, NodeChange change) {
+    expect(changes, isNot(contains(node)));
+    changes[node] = change;
   }
 
   @override
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index 942bb85..638a853 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -284,6 +284,70 @@
     expect(kToL.isSatisfied, true);
   }
 
+  test_graphEdge_isUpstreamTriggered() async {
+    await analyze('''
+void f(int i, bool b) {
+  assert(i != null);
+  i.isEven; // unconditional
+  g(i);
+  h(i);
+  if (b) {
+    i.isEven; // conditional
+  }
+}
+void g(int/*?*/ j) {}
+void h(int k) {}
+''');
+    var iNode = explicitTypeNullability[findNode.typeAnnotation('int i')];
+    var jNode = explicitTypeNullability[findNode.typeAnnotation('int/*?*/ j')];
+    var kNode = explicitTypeNullability[findNode.typeAnnotation('int k')];
+    var assertNode = findNode.statement('assert');
+    var unconditionalUsageNode = findNode.simple('i.isEven; // unconditional');
+    var conditionalUsageNode = findNode.simple('i.isEven; // conditional');
+    var nonNullEdges = edgeOrigin.entries
+        .where((entry) =>
+            entry.key.sourceNode == iNode && entry.key.destinationNode == never)
+        .toList();
+    var assertEdge = nonNullEdges
+        .where((entry) => entry.value.node == assertNode)
+        .single
+        .key;
+    var unconditionalUsageEdge = edgeOrigin.entries
+        .where((entry) => entry.value.node == unconditionalUsageNode)
+        .single
+        .key;
+    var gCallEdge = edges
+        .where((e) => e.sourceNode == iNode && e.destinationNode == jNode)
+        .single;
+    var hCallEdge = edges
+        .where((e) => e.sourceNode == iNode && e.destinationNode == kNode)
+        .single;
+    var conditionalUsageEdge = edgeOrigin.entries
+        .where((entry) => entry.value.node == conditionalUsageNode)
+        .single
+        .key;
+    // Both assertEdge and unconditionalUsageEdge are upstream triggered because
+    // either of them would have been sufficient to cause i to be marked as
+    // non-nullable, even though only one of them was actually reported to have
+    // done so via propagationStep.
+    expect(propagationSteps.where((s) => s.node == iNode), hasLength(1));
+    expect(assertEdge.isUpstreamTriggered, true);
+    expect(unconditionalUsageEdge.isUpstreamTriggered, true);
+    // conditionalUsageEdge is not upstream triggered because it is a soft edge,
+    // so it would not have caused i to be marked as non-nullable.
+    expect(conditionalUsageEdge.isUpstreamTriggered, false);
+    // Even though gCallEdge is a hard edge, it is not upstream triggered
+    // because its destination node is nullable.
+    expect(gCallEdge.isHard, true);
+    expect(gCallEdge.isUpstreamTriggered, false);
+    // Even though hCallEdge is a hard edge and its destination node is
+    // non-nullable, it is not upstream triggered because k could have been made
+    // nullable without causing any problems, so the presence of this edge would
+    // not have caused i to be marked as non-nullable.
+    expect(hCallEdge.isHard, true);
+    expect(hCallEdge.isUpstreamTriggered, false);
+  }
+
   test_graphEdge_origin() async {
     await analyze('''
 int f(int x) => x;
@@ -817,7 +881,7 @@
         hasLength(1));
   }
 
-  test_propagationStep() async {
+  test_propagationStep_downstream() async {
     await analyze('''
 int x = null;
 ''');
@@ -829,6 +893,20 @@
     expect(step.edge.destinationNode, xNode);
   }
 
+  test_propagationStep_upstream() async {
+    await analyze('''
+void f(int x) {
+  assert(x != null);
+}
+''');
+    var xNode = explicitTypeNullability[findNode.typeAnnotation('int')];
+    var step = propagationSteps.where((s) => s.node == xNode).single;
+    expect(step.newState, NullabilityState.nonNullable);
+    expect(step.reason, StateChangeReason.upstream);
+    expect(step.edge.sourceNode, xNode);
+    expect(step.edge.destinationNode, never);
+  }
+
   test_substitutionNode() async {
     await analyze('''
 class C<T> {
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 91219ff..fc1b855 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -75,7 +75,8 @@
     parameters.addAll(named.entries.map((e) => ParameterElementImpl.synthetic(
         e.key, e.value.type, ParameterKind.NAMED)));
     return DecoratedType(
-        FunctionTypeImpl.synthetic(returnType.type, typeFormals, parameters),
+        FunctionTypeImpl.synthetic(returnType.type, typeFormals, parameters,
+            nullabilitySuffix: NullabilitySuffix.star),
         node ?? newNode(),
         typeFormalBounds: typeFormals
             .map((formal) => _decoratedTypeParameterBounds[formal])
@@ -318,7 +319,8 @@
 
   TypeProvider get typeProvider => testAnalysisResult.typeProvider;
 
-  TypeSystem get typeSystem => testAnalysisResult.typeSystem;
+  Dart2TypeSystem get typeSystem =>
+      testAnalysisResult.typeSystem as Dart2TypeSystem;
 
   Future<CompilationUnit> analyze(String code) async {
     await resolveTestUnit(code);
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 5b741e2..0769ac3 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -186,6 +186,10 @@
 [ $compiler == dart2js && $csp ]
 mutation_observer: Skip # This test cannot run under CSP because it is injecting a JavaScript polyfill
 
+[ $compiler == dart2js && $host_checked ]
+js_ast/test/printer_callback_test: Slow, Pass
+js_ast/test/string_escape_test: Slow, Pass
+
 [ $compiler == dart2js && ($runtime == chrome || $runtime == ff) ]
 async/test/stream_zip_test: SkipSlow # Times out. Issue 22050
 collection/test/unmodifiable_collection_test: SkipSlow # Times out. Issue 22050
@@ -210,7 +214,7 @@
 
 # Timeout. These tests do not run efficiently on our simulator or low-end
 # devices.
-[ $runtime == vm && ($arch == armv5te || $arch == armv6 || $arch == simarm || $arch == simarm64 || $arch == simarmv5te || $arch == simarmv6 || $arch == simdbc64) ]
+[ $runtime == vm && ($arch == armv6 || $arch == simarm || $arch == simarm64 || $arch == simarmv6) ]
 *: Skip
 
 [ $arch != x64 || $compiler != none || $mode != release || $runtime != vm ]
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index ac3df99..be9c74c 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -244,6 +244,7 @@
         nnbdMode: nnbdMode,
         babel: stringOption("babel"),
         builderTag: stringOption("builder-tag"),
+        genKernelOptions: stringListOption("gen-kernel-options"),
         vmOptions: stringListOption("vm-options"),
         dart2jsOptions: stringListOption("dart2js-options"),
         experiments: stringListOption("enable-experiment"),
@@ -288,6 +289,8 @@
 
   final String builderTag;
 
+  final List<String> genKernelOptions;
+
   final List<String> vmOptions;
 
   final List<String> dart2jsOptions;
@@ -335,6 +338,7 @@
       {NnbdMode nnbdMode,
       String babel,
       String builderTag,
+      List<String> genKernelOptions,
       List<String> vmOptions,
       List<String> dart2jsOptions,
       List<String> experiments,
@@ -354,6 +358,7 @@
       : nnbdMode = nnbdMode ?? NnbdMode.legacy,
         babel = babel ?? "",
         builderTag = builderTag ?? "",
+        genKernelOptions = genKernelOptions ?? <String>[],
         vmOptions = vmOptions ?? <String>[],
         dart2jsOptions = dart2jsOptions ?? <String>[],
         experiments = experiments ?? <String>[],
@@ -382,6 +387,7 @@
       nnbdMode == other.nnbdMode &&
       babel == other.babel &&
       builderTag == other.builderTag &&
+      _listsEqual(genKernelOptions, other.genKernelOptions) &&
       _listsEqual(vmOptions, other.vmOptions) &&
       _listsEqual(dart2jsOptions, other.dart2jsOptions) &&
       _listsEqual(experiments, other.experiments) &&
@@ -429,6 +435,7 @@
       nnbdMode.hashCode ^
       babel.hashCode ^
       builderTag.hashCode ^
+      genKernelOptions.join(" & ").hashCode ^
       vmOptions.join(" & ").hashCode ^
       dart2jsOptions.join(" & ").hashCode ^
       experiments.join(" & ").hashCode ^
@@ -469,6 +476,7 @@
 
     if (babel.isNotEmpty) fields.add("babel: $babel");
     if (builderTag.isNotEmpty) fields.add("builder-tag: $builderTag");
+    stringListField("gen-kernel-options", genKernelOptions);
     stringListField("vm-options", vmOptions);
     stringListField("dart2js-options", dart2jsOptions);
     stringListField("enable-experiment", experiments);
@@ -522,6 +530,8 @@
     fields.add("nnbd: $nnbdMode ${other.nnbdMode}");
     stringField("babel", babel, other.babel);
     stringField("builder-tag", builderTag, other.builderTag);
+    stringListField(
+        "gen-kernel-options", genKernelOptions, other.genKernelOptions);
     stringListField("vm-options", vmOptions, other.vmOptions);
     stringListField("dart2js-options", dart2jsOptions, other.dart2jsOptions);
     stringListField("experiments", experiments, other.experiments);
@@ -553,14 +563,10 @@
   static const arm = Architecture._('arm');
   static const arm_x64 = Architecture._('arm_x64');
   static const armv6 = Architecture._('armv6');
-  static const armv5te = Architecture._('armv5te');
   static const arm64 = Architecture._('arm64');
   static const simarm = Architecture._('simarm');
   static const simarmv6 = Architecture._('simarmv6');
-  static const simarmv5te = Architecture._('simarmv5te');
   static const simarm64 = Architecture._('simarm64');
-  static const simdbc = Architecture._('simdbc');
-  static const simdbc64 = Architecture._('simdbc64');
 
   static final List<String> names = _all.keys.toList();
 
@@ -569,15 +575,11 @@
     x64,
     arm,
     armv6,
-    armv5te,
     arm_x64,
     arm64,
     simarm,
     simarmv6,
-    simarmv5te,
     simarm64,
-    simdbc,
-    simdbc64
   ], key: (architecture) => (architecture as Architecture).name);
 
   static Architecture find(String name) {
diff --git a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
index 505b951..7799b9e 100644
--- a/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
+++ b/pkg/sourcemap_testing/lib/src/stacktrace_helper.dart
@@ -6,8 +6,8 @@
 import 'dart:io';
 import 'dart:convert' show jsonDecode;
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:expect/expect.dart';
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 import 'package:source_maps/source_maps.dart';
 import 'package:source_maps/src/utils.dart';
 import 'package:source_span/source_span.dart';
diff --git a/pkg/sourcemap_testing/lib/src/stepping_helper.dart b/pkg/sourcemap_testing/lib/src/stepping_helper.dart
index d001fd6..525b818 100644
--- a/pkg/sourcemap_testing/lib/src/stepping_helper.dart
+++ b/pkg/sourcemap_testing/lib/src/stepping_helper.dart
@@ -1,7 +1,7 @@
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:expect/minitest.dart';
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 import 'package:path/path.dart' as path;
 import 'package:source_maps/source_maps.dart';
 
diff --git a/pkg/status_file/test/data/standalone_2_vm.status b/pkg/status_file/test/data/standalone_2_vm.status
index 2b85902..d58085f 100644
--- a/pkg/status_file/test/data/standalone_2_vm.status
+++ b/pkg/status_file/test/data/standalone_2_vm.status
@@ -24,16 +24,6 @@
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 link_natives_lazily_test: SkipByDesign # Not supported.
 
-[ $arch == simdbc || $arch == simdbc64 ]
-full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
-
-link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives.
-
-no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers
-
-[ $arch == simdbc64 && $mode == debug && $checked ]
-io/web_socket_test: Pass, RuntimeError # Issue 26814.
-
 [ $system == windows ]
 verbose_gc_to_bmu_test: Skip
 io/process_sync_test: Pass, Timeout # Issue 24596
diff --git a/pkg/status_file/test/data/vm.status b/pkg/status_file/test/data/vm.status
index 5cb581d..5db98f2 100644
--- a/pkg/status_file/test/data/vm.status
+++ b/pkg/status_file/test/data/vm.status
@@ -47,11 +47,10 @@
 dart/data_uri_spawn_test: Skip # TODO(zra): package:unittest is not in the image.
 cc/Read: Fail  # TODO(zra): Investigate, ../../dart/runtime/bin/file_test.cc: 34: error: expected: !file->WriteByte(1)
 
-# Profiler is completely disabled in SIMDBC builds.
 # On the simluator stack traces produced by the Profiler do not match
 # up with the real Dart stack trace and hence we don't get correct
 # symbol names.
-[ $arch == simarm || $arch == simarmv6 || $arch == simarmv5te || $arch == simarm64 || $arch == simdbc  || $arch == simdbc64 ]
+[ $arch == simarm || $arch == simarmv6 || $arch == simarm64 ]
 cc/Service_Profile: Skip
 cc/Profiler_AllocationSampleTest: Skip
 cc/Profiler_ArrayAllocation: Skip
@@ -166,20 +165,6 @@
 [ $runtime == vm && $mode == product ]
 cc/DartAPI_IsolateSetCheckedMode: Fail,OK  # Checked mode disabled in product mode.
 
-[ $arch == simdbc  || $arch == simdbc64 ]
-cc/RegExp_ExternalOneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_ExternalTwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_OneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-
-cc/GuardFieldConstructor2Test: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldConstructorTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldFinalListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldFinalVariableLengthListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldSimpleTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-
-cc/RegenerateAllocStubs: Skip # This test is meaningless for DBC as allocation stubs are not used.
-
 [ $hot_reload || $hot_reload_rollback ]
 dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
 dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 0874125..01389c4 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -85,8 +85,7 @@
 
       case Compiler.dartk:
       case Compiler.dartkb:
-        if (configuration.architecture == Architecture.simdbc64 ||
-            configuration.architecture == Architecture.simarm ||
+        if (configuration.architecture == Architecture.simarm ||
             configuration.architecture == Architecture.simarm64 ||
             configuration.system == System.android) {
           return VMKernelCompilerConfiguration(configuration);
@@ -1101,11 +1100,7 @@
           arguments.contains('--enable-asserts') ||
           arguments.contains('--enable_asserts'))
         '--enable-asserts',
-      if (_configuration.useKernelBytecode) ...[
-        '--gen-bytecode',
-        '--drop-ast',
-        '--bytecode-options=source-positions${_isProduct ? '' : ',local-var-info,debugger-stops'}'
-      ]
+      ..._configuration.genKernelOptions,
     ];
 
     var batchArgs = [if (useAbiVersion != null) useAbiVersion];
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index d91dc66..dd62818 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -42,7 +42,6 @@
       this.reportInJson,
       this.resetBrowser,
       this.skipCompilation,
-      this.useKernelBytecode,
       this.writeDebugLog,
       this.writeResults,
       this.writeLogs,
@@ -94,7 +93,6 @@
   final bool reportInJson;
   final bool resetBrowser;
   final bool skipCompilation;
-  final bool useKernelBytecode;
   final bool writeDebugLog;
   final bool writeResults;
   final bool writeLogs;
@@ -147,6 +145,9 @@
   /// Extra dart2js options passed to the testing script.
   List<String> get dart2jsOptions => configuration.dart2jsOptions;
 
+  /// Extra gen_kernel options passed to the testing script.
+  List<String> get genKernelOptions => configuration.genKernelOptions;
+
   /// Extra VM options passed to the testing script.
   List<String> get vmOptions => configuration.vmOptions;
 
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 029dfe9..9064cb5 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -14,7 +14,6 @@
 
 const _defaultTestSelectors = [
   'samples',
-  'standalone',
   'standalone_2',
   'corelib_2',
   'language_2',
@@ -142,9 +141,8 @@
 Allowed values are:
 all
 ia32, x64
-arm, armv6, armv5te, arm64,
-simarm, simarmv6, simarmv5te, simarm64,
-simdbc, simdbc64, arm_x64''',
+arm, armv6, arm64,
+simarm, simarmv6, simarm64, arm_x64''',
         abbr: 'a',
         values: ['all']..addAll(Architecture.names),
         defaultsTo: Architecture.x64.name,
@@ -688,7 +686,7 @@
       // Expand architectures.
       var architectures = data["arch"] as String;
       if (architectures == "all") {
-        architectures = "ia32,x64,simarm,simarm64,simdbc64";
+        architectures = "ia32,x64,simarm,simarm64";
       }
 
       for (var architectureName in architectures.split(",")) {
@@ -745,8 +743,6 @@
                 reportInJson: data["report_in_json"] as bool,
                 resetBrowser: data["reset_browser_configuration"] as bool,
                 skipCompilation: data["skip_compilation"] as bool,
-                useKernelBytecode:
-                    innerConfiguration.compiler == Compiler.dartkb,
                 writeDebugLog: data["write_debug_log"] as bool,
                 writeResults: data["write_results"] as bool,
                 writeLogs: data["write_logs"] as bool,
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index 7cb3cda..5a2b45b 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -233,11 +233,7 @@
       case Architecture.arm64:
       case Architecture.simarmv6:
       case Architecture.armv6:
-      case Architecture.simarmv5te:
-      case Architecture.armv5te:
       case Architecture.simarm64:
-      case Architecture.simdbc:
-      case Architecture.simdbc64:
         multiplier *= 4;
         break;
     }
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index 674c55c..0d35524 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -38,7 +38,6 @@
   Path('tests/kernel'),
   Path('tests/language_2'),
   Path('tests/lib_2'),
-  Path('tests/standalone'),
   Path('tests/standalone_2'),
   Path('tests/ffi'),
   Path('utils/tests/peg'),
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 78a9310..0389d59 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -707,8 +707,6 @@
 
 /// Writes a results.json file with a line for each test.
 /// Each line is a json map with the test name and result and expected result.
-/// Also writes a run.json file with a json map containing the configuration
-/// and the start time and duration of the run.
 class ResultWriter extends EventListener {
   final TestConfiguration _configuration;
   final List<Map> _results = [];
@@ -767,7 +765,6 @@
   void allDone() {
     writeOutputFile(_results, TestUtils.resultsFileName);
     writeOutputFile(_logs, TestUtils.logsFileName);
-    writeRunFile();
   }
 
   void writeOutputFile(List<Map> results, String fileName) {
@@ -776,19 +773,4 @@
     File.fromUri(path)
         .writeAsStringSync(newlineTerminated(results.map(jsonEncode)));
   }
-
-  void writeRunFile() {
-    _startStopwatch.stop();
-    if (_outputDirectory == null) return;
-    var suites = _configuration.selectors.keys.toList();
-    var run = {
-      "start_time": _startTime.millisecondsSinceEpoch ~/ 1000,
-      "duration": _startStopwatch.elapsed.inSeconds,
-      "configuration": _configuration.configuration.name,
-      "suites": suites
-    };
-    final path = Uri.directory(_outputDirectory)
-        .resolve(TestUtils.resultsInstanceFileName);
-    File.fromUri(path).writeAsStringSync(jsonEncode(run) + '\n');
-  }
 }
diff --git a/pkg/test_runner/lib/src/utils.dart b/pkg/test_runner/lib/src/utils.dart
index e62242e..2c1334a 100644
--- a/pkg/test_runner/lib/src/utils.dart
+++ b/pkg/test_runner/lib/src/utils.dart
@@ -439,10 +439,6 @@
   /// test outcomes to this file in the '--output-directory'.
   static const resultsFileName = "results.json";
 
-  /// If test.py was invoked with '--write-results' it will write
-  /// data about this run of test.py to this file in the '--output-directory'.
-  static const resultsInstanceFileName = "run.json";
-
   /// If test.py was invoked with '--write-results' and '--write-logs", save
   /// the stdout and stderr to this file in the '--output-directory'.
   static const logsFileName = "logs.json";
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index 803f10f..56d0b23 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -136,6 +136,7 @@
     Map<TestDescription, Set<Expectation>> unexpectedOutcomes =
         <TestDescription, Set<Expectation>>{};
     int completed = 0;
+    logger.logSuiteStarted(suite);
     List<Future> futures = <Future>[];
     for (TestDescription description in descriptions) {
       String selector = "${suite.name}/${description.shortName}";
@@ -215,6 +216,8 @@
                 suite, description, result, expectedOutcomes);
             exitCode = 1;
           } else {
+            logger.logExpectedResult(
+                suite, description, result, expectedOutcomes);
             logger.logMessage(sb);
           }
           logger.logTestComplete(++completed, unexpectedResults.length,
@@ -234,7 +237,7 @@
       await doStep(description);
     }
     await Future.wait(futures);
-    logger.logSuiteComplete();
+    logger.logSuiteComplete(suite);
     if (unexpectedResults.isNotEmpty) {
       unexpectedResults.forEach((TestDescription description, Result result) {
         logger.logUnexpectedResult(
diff --git a/pkg/testing/lib/src/log.dart b/pkg/testing/lib/src/log.dart
index b15de14..e916ba9 100644
--- a/pkg/testing/lib/src/log.dart
+++ b/pkg/testing/lib/src/log.dart
@@ -63,7 +63,9 @@
   void logUnexpectedResult(Suite suite, TestDescription description,
       Result result, Set<Expectation> expectedOutcomes);
 
-  void logSuiteComplete();
+  void logSuiteStarted(Suite suite);
+
+  void logSuiteComplete(Suite suite);
 
   void logUncaughtError(error, StackTrace stackTrace);
 }
@@ -167,7 +169,11 @@
     }
   }
 
-  void logSuiteComplete() {
+  void logSuiteStarted(Suite suite) {
+    print("Running suite ${suite.name}...");
+  }
+
+  void logSuiteComplete(Suite suite) {
     if (!isVerbose) {
       print("");
     }
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index 12305ba..49d0b12 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -62,7 +62,6 @@
     if (cl.verbose) enableVerboseOutput();
     for (Chain suite in testRoot.toolChains) {
       if (me == suite.source) {
-        print("Running suite ${suite.name}...");
         ChainContext context = await f(suite, cl.environment);
         await context.run(suite, new Set<String>.from(cl.selectors),
             shards: shards, shard: shard, logger: logger);
diff --git a/pkg/testing/lib/src/run_tests.dart b/pkg/testing/lib/src/run_tests.dart
index ecb28d4..b4ccd3b 100644
--- a/pkg/testing/lib/src/run_tests.dart
+++ b/pkg/testing/lib/src/run_tests.dart
@@ -188,5 +188,4 @@
         const StdoutLogger()
             .logTestComplete(++completed, 0, tests.length, null, null);
       }
-      const StdoutLogger().logSuiteComplete();
     });
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index f4969eb..912eede 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -12,6 +12,8 @@
 import 'local_variable_table.dart' show LocalVariableTable;
 import 'source_positions.dart' show SourcePositions;
 
+import 'dart:typed_data' show Uint8List;
+
 class Label {
   final bool allowsBackwardJumps;
   List<int> _jumps = <int>[];
@@ -52,8 +54,11 @@
   static const int kMinInt32 = -0x80000000;
   static const int kMaxInt32 = 0x7FFFFFFF;
 
-  // TODO(alexmarkov): figure out more efficient storage for generated bytecode.
-  final List<int> bytecode = new List<int>();
+  static const int kInitialCapacity = 32;
+
+  int _length = 0;
+  Uint8List _buffer = new Uint8List(kInitialCapacity);
+
   final ExceptionsTable exceptionsTable = new ExceptionsTable();
   final LocalVariableTable localVariableTable = new LocalVariableTable();
   final SourcePositions sourcePositions = new SourcePositions();
@@ -64,7 +69,9 @@
   BytecodeAssembler(BytecodeOptions options)
       : _emitSourcePositions = options.emitSourcePositions;
 
-  int get offset => bytecode.length;
+  int get offset => _length;
+
+  Uint8List get bytecode => new Uint8List.view(_buffer.buffer, 0, _length);
 
   void bind(Label label) {
     final List<int> jumps = label.bind(offset);
@@ -76,6 +83,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void emitSourcePosition() {
     if (_emitSourcePositions &&
         !isUnreachable &&
@@ -88,6 +96,7 @@
   // calls without corresponding source position. Debugger uses the absence of
   // source position to distinguish these calls and avoid stopping at them
   // while single stepping.
+  @pragma('vm:prefer-inline')
   void emitSourcePositionForCall() {
     if (_emitSourcePositions && !isUnreachable) {
       sourcePositions.add(
@@ -104,30 +113,88 @@
     }
   }
 
+  void _grow() {
+    final newSize = _buffer.length << 1;
+    final newBuffer = new Uint8List(newSize);
+    newBuffer.setRange(0, _buffer.length, _buffer);
+    _buffer = newBuffer;
+  }
+
+  void _growAndEmitBytes(int b0, [int b1, int b2, int b3, int b4, int b5]) {
+    _grow();
+    assert(_length + 6 < _buffer.length);
+    _buffer[_length] = b0;
+    ++_length;
+    if (b1 != null) {
+      _buffer[_length] = b1;
+      ++_length;
+      if (b2 != null) {
+        _buffer[_length] = b2;
+        ++_length;
+        if (b3 != null) {
+          _buffer[_length] = b3;
+          ++_length;
+          if (b4 != null) {
+            _buffer[_length] = b4;
+            ++_length;
+            if (b5 != null) {
+              _buffer[_length] = b5;
+              ++_length;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  @pragma('vm:prefer-inline')
   void _emitByte(int abyte) {
     assert(_isUint8(abyte));
-    bytecode.add(abyte);
+    if (_length < _buffer.length) {
+      _buffer[_length] = abyte;
+      ++_length;
+    } else {
+      _growAndEmitBytes(abyte);
+    }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitBytes2(int b0, int b1) {
     assert(_isUint8(b0) && _isUint8(b1));
-    bytecode.add(b0);
-    bytecode.add(b1);
+    if (_length + 1 < _buffer.length) {
+      _buffer[_length] = b0;
+      _buffer[_length + 1] = b1;
+      _length += 2;
+    } else {
+      _growAndEmitBytes(b0, b1);
+    }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitBytes3(int b0, int b1, int b2) {
     assert(_isUint8(b0) && _isUint8(b1) && _isUint8(b2));
-    bytecode.add(b0);
-    bytecode.add(b1);
-    bytecode.add(b2);
+    if (_length + 2 < _buffer.length) {
+      _buffer[_length] = b0;
+      _buffer[_length + 1] = b1;
+      _buffer[_length + 2] = b2;
+      _length += 3;
+    } else {
+      _growAndEmitBytes(b0, b1, b2);
+    }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitBytes4(int b0, int b1, int b2, int b3) {
     assert(_isUint8(b0) && _isUint8(b1) && _isUint8(b2) && _isUint8(b3));
-    bytecode.add(b0);
-    bytecode.add(b1);
-    bytecode.add(b2);
-    bytecode.add(b3);
+    if (_length + 3 < _buffer.length) {
+      _buffer[_length] = b0;
+      _buffer[_length + 1] = b1;
+      _buffer[_length + 2] = b2;
+      _buffer[_length + 3] = b3;
+      _length += 4;
+    } else {
+      _growAndEmitBytes(b0, b1, b2, b3);
+    }
   }
 
   void _emitBytes5(int b0, int b1, int b2, int b3, int b4) {
@@ -136,11 +203,16 @@
         _isUint8(b2) &&
         _isUint8(b3) &&
         _isUint8(b4));
-    bytecode.add(b0);
-    bytecode.add(b1);
-    bytecode.add(b2);
-    bytecode.add(b3);
-    bytecode.add(b4);
+    if (_length + 4 < _buffer.length) {
+      _buffer[_length] = b0;
+      _buffer[_length + 1] = b1;
+      _buffer[_length + 2] = b2;
+      _buffer[_length + 3] = b3;
+      _buffer[_length + 4] = b4;
+      _length += 5;
+    } else {
+      _growAndEmitBytes(b0, b1, b2, b3, b4);
+    }
   }
 
   void _emitBytes6(int b0, int b1, int b2, int b3, int b4, int b5) {
@@ -150,34 +222,56 @@
         _isUint8(b3) &&
         _isUint8(b4) &&
         _isUint8(b5));
-    bytecode.add(b0);
-    bytecode.add(b1);
-    bytecode.add(b2);
-    bytecode.add(b3);
-    bytecode.add(b4);
-    bytecode.add(b5);
+    if (_length + 5 < _buffer.length) {
+      _buffer[_length] = b0;
+      _buffer[_length + 1] = b1;
+      _buffer[_length + 2] = b2;
+      _buffer[_length + 3] = b3;
+      _buffer[_length + 4] = b4;
+      _buffer[_length + 5] = b5;
+      _length += 6;
+    } else {
+      _growAndEmitBytes(b0, b1, b2, b3, b4, b5);
+    }
   }
 
   int _byteAt(int pos) {
-    return bytecode[pos];
+    return _buffer[pos];
   }
 
   void _setByteAt(int pos, int value) {
     assert(_isUint8(value));
-    bytecode[pos] = value;
+    _buffer[pos] = value;
   }
 
+  @pragma('vm:prefer-inline')
   int _byte0(int v) => v & kByteMask;
+
+  @pragma('vm:prefer-inline')
   int _byte1(int v) => (v >> 8) & kByteMask;
+
+  @pragma('vm:prefer-inline')
   int _byte2(int v) => (v >> 16) & kByteMask;
+
+  @pragma('vm:prefer-inline')
   int _byte3(int v) => (v >> 24) & kByteMask;
 
+  @pragma('vm:prefer-inline')
   bool _isInt8(int v) => (kMinInt8 <= v) && (v <= kMaxInt8);
+
+  @pragma('vm:prefer-inline')
   bool _isInt24(int v) => (kMinInt24 <= v) && (v <= kMaxInt24);
+
+  @pragma('vm:prefer-inline')
   bool _isInt32(int v) => (kMinInt32 <= v) && (v <= kMaxInt32);
+
+  @pragma('vm:prefer-inline')
   bool _isUint8(int v) => (v & kByteMask) == v;
+
+  @pragma('vm:prefer-inline')
   bool _isUint32(int v) => (v & kUint32Mask) == v;
 
+  @pragma('vm:prefer-inline')
   void _emitInstruction0(Opcode opcode) {
     if (isUnreachable) {
       return;
@@ -185,6 +279,7 @@
     _emitByte(opcode.index);
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionA(Opcode opcode, int ra) {
     if (isUnreachable) {
       return;
@@ -192,6 +287,7 @@
     _emitBytes2(opcode.index, ra);
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionD(Opcode opcode, int rd) {
     if (isUnreachable) {
       return;
@@ -205,6 +301,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionX(Opcode opcode, int rx) {
     if (isUnreachable) {
       return;
@@ -218,6 +315,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionAE(Opcode opcode, int ra, int re) {
     if (isUnreachable) {
       return;
@@ -231,6 +329,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionAY(Opcode opcode, int ra, int ry) {
     if (isUnreachable) {
       return;
@@ -244,6 +343,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionDF(Opcode opcode, int rd, int rf) {
     if (isUnreachable) {
       return;
@@ -257,6 +357,7 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void _emitInstructionABC(Opcode opcode, int ra, int rb, int rc) {
     if (isUnreachable) {
       return;
@@ -264,12 +365,14 @@
     _emitBytes4(opcode.index, ra, rb, rc);
   }
 
+  @pragma('vm:prefer-inline')
   void emitSpecializedBytecode(Opcode opcode) {
     assert(BytecodeFormats[opcode].encoding == Encoding.k0);
     emitSourcePosition();
     _emitInstruction0(opcode);
   }
 
+  @pragma('vm:prefer-inline')
   void _emitJumpInstruction(Opcode opcode, Label label) {
     assert(isJump(opcode));
     if (isUnreachable) {
@@ -302,277 +405,339 @@
     isUnreachable = true;
   }
 
+  @pragma('vm:prefer-inline')
   void emitDrop1() {
     _emitInstruction0(Opcode.kDrop1);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJump(Label label) {
     _emitJumpInstruction(Opcode.kJump, label);
     isUnreachable = true;
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfNoAsserts(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfNoAsserts, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfNotZeroTypeArgs(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfNotZeroTypeArgs, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfEqStrict(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfEqStrict, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfNeStrict(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfNeStrict, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfTrue(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfTrue, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfFalse(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfFalse, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfNull(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfNull, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfNotNull(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfNotNull, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitJumpIfUnchecked(Label label) {
     _emitJumpInstruction(Opcode.kJumpIfUnchecked, label);
   }
 
+  @pragma('vm:prefer-inline')
   void emitReturnTOS() {
     emitSourcePosition();
     _emitInstruction0(Opcode.kReturnTOS);
     isUnreachable = true;
   }
 
+  @pragma('vm:prefer-inline')
   void emitPush(int rx) {
     _emitInstructionX(Opcode.kPush, rx);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadConstant(int ra, int re) {
     _emitInstructionAE(Opcode.kLoadConstant, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPushConstant(int rd) {
     _emitInstructionD(Opcode.kPushConstant, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPushNull() {
     _emitInstruction0(Opcode.kPushNull);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPushTrue() {
     _emitInstruction0(Opcode.kPushTrue);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPushFalse() {
     _emitInstruction0(Opcode.kPushFalse);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPushInt(int rx) {
     _emitInstructionX(Opcode.kPushInt, rx);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreLocal(int rx) {
     _emitInstructionX(Opcode.kStoreLocal, rx);
   }
 
+  @pragma('vm:prefer-inline')
   void emitPopLocal(int rx) {
     _emitInstructionX(Opcode.kPopLocal, rx);
   }
 
+  @pragma('vm:prefer-inline')
   void emitDirectCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kDirectCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitUncheckedDirectCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kUncheckedDirectCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitInterfaceCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kInterfaceCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitInstantiatedInterfaceCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kInstantiatedInterfaceCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitUncheckedClosureCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kUncheckedClosureCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitUncheckedInterfaceCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kUncheckedInterfaceCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitDynamicCall(int rd, int rf) {
     emitSourcePositionForCall();
     _emitInstructionDF(Opcode.kDynamicCall, rd, rf);
   }
 
+  @pragma('vm:prefer-inline')
   void emitNativeCall(int rd) {
     _emitInstructionD(Opcode.kNativeCall, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadStatic(int rd) {
     _emitInstructionD(Opcode.kLoadStatic, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreStaticTOS(int rd) {
     emitSourcePosition();
     _emitInstructionD(Opcode.kStoreStaticTOS, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitCreateArrayTOS() {
     _emitInstruction0(Opcode.kCreateArrayTOS);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAllocate(int rd) {
     emitSourcePosition();
     _emitInstructionD(Opcode.kAllocate, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAllocateT() {
     emitSourcePosition();
     _emitInstruction0(Opcode.kAllocateT);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreIndexedTOS() {
     _emitInstruction0(Opcode.kStoreIndexedTOS);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreFieldTOS(int rd) {
     emitSourcePosition();
     _emitInstructionD(Opcode.kStoreFieldTOS, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreContextParent() {
     _emitInstruction0(Opcode.kStoreContextParent);
   }
 
+  @pragma('vm:prefer-inline')
   void emitStoreContextVar(int ra, int re) {
     _emitInstructionAE(Opcode.kStoreContextVar, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadFieldTOS(int rd) {
     _emitInstructionD(Opcode.kLoadFieldTOS, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadTypeArgumentsField(int rd) {
     _emitInstructionD(Opcode.kLoadTypeArgumentsField, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadContextParent() {
     _emitInstruction0(Opcode.kLoadContextParent);
   }
 
+  @pragma('vm:prefer-inline')
   void emitLoadContextVar(int ra, int re) {
     _emitInstructionAE(Opcode.kLoadContextVar, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitBooleanNegateTOS() {
     _emitInstruction0(Opcode.kBooleanNegateTOS);
   }
 
+  @pragma('vm:prefer-inline')
   void emitThrow(int ra) {
     emitSourcePosition();
     _emitInstructionA(Opcode.kThrow, ra);
     isUnreachable = true;
   }
 
+  @pragma('vm:prefer-inline')
   void emitEntry(int rd) {
     _emitInstructionD(Opcode.kEntry, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitFrame(int rd) {
     _emitInstructionD(Opcode.kFrame, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitSetFrame(int ra) {
     _emitInstructionA(Opcode.kSetFrame, ra);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAllocateContext(int ra, int re) {
     _emitInstructionAE(Opcode.kAllocateContext, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitCloneContext(int ra, int re) {
     _emitInstructionAE(Opcode.kCloneContext, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitMoveSpecial(SpecialIndex ra, int ry) {
     _emitInstructionAY(Opcode.kMoveSpecial, ra.index, ry);
   }
 
+  @pragma('vm:prefer-inline')
   void emitInstantiateType(int rd) {
     emitSourcePosition();
     _emitInstructionD(Opcode.kInstantiateType, rd);
   }
 
+  @pragma('vm:prefer-inline')
   void emitInstantiateTypeArgumentsTOS(int ra, int re) {
     emitSourcePosition();
     _emitInstructionAE(Opcode.kInstantiateTypeArgumentsTOS, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAssertAssignable(int ra, int re) {
     emitSourcePosition();
     _emitInstructionAE(Opcode.kAssertAssignable, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAssertSubtype() {
     emitSourcePosition();
     _emitInstruction0(Opcode.kAssertSubtype);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAssertBoolean(int ra) {
     emitSourcePosition();
     _emitInstructionA(Opcode.kAssertBoolean, ra);
   }
 
+  @pragma('vm:prefer-inline')
   void emitCheckStack(int ra) {
     emitSourcePosition();
     _emitInstructionA(Opcode.kCheckStack, ra);
   }
 
+  @pragma('vm:prefer-inline')
   void emitDebugCheck() {
     emitSourcePosition();
     _emitInstruction0(Opcode.kDebugCheck);
   }
 
+  @pragma('vm:prefer-inline')
   void emitCheckFunctionTypeArgs(int ra, int re) {
     emitSourcePosition();
     _emitInstructionAE(Opcode.kCheckFunctionTypeArgs, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitEntryFixed(int ra, int re) {
     _emitInstructionAE(Opcode.kEntryFixed, ra, re);
   }
 
+  @pragma('vm:prefer-inline')
   void emitEntryOptional(int ra, int rb, int rc) {
     _emitInstructionABC(Opcode.kEntryOptional, ra, rb, rc);
   }
 
+  @pragma('vm:prefer-inline')
   void emitAllocateClosure(int rd) {
     emitSourcePosition();
     _emitInstructionD(Opcode.kAllocateClosure, rd);
   }
 
-  void emitCheckReceiverForNull(int rd) {
+  @pragma('vm:prefer-inline')
+  void emitNullCheck(int rd) {
     emitSourcePosition();
-    _emitInstructionD(Opcode.kCheckReceiverForNull, rd);
+    _emitInstructionD(Opcode.kNullCheck, rd);
   }
 }
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index 5f2dd85..671cf16 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -4,7 +4,7 @@
 
 library vm.bytecode.bytecode_serialization;
 
-import 'dart:io' show BytesBuilder;
+import 'package:kernel/ast.dart' show BinarySink;
 import 'dart:typed_data' show ByteData, Endian, Uint8List, Uint16List;
 
 abstract class StringWriter {
@@ -26,62 +26,206 @@
 }
 
 class BufferedWriter {
+  /// Initial size of the buffer in BufferedWriter.
+  static const int initialSize = 1024;
+
+  /// Lists less than this size are copied into the buffer.
+  /// Larger lists are appended without copying.
+  static const int avoidCopyingSize = 1024;
+
+  /// Keep buffers with this remaining bytes or more, instead of
+  /// creating a new buffer.
+  static const int minRemainderToKeep = 256;
+
   final int formatVersion;
   final StringWriter stringWriter;
   final ObjectWriter objectWriter;
   final LinkWriter linkWriter;
-  final BytesBuilder bytes = new BytesBuilder();
-  final int baseOffset;
 
-  BufferedWriter(
-      this.formatVersion, this.stringWriter, this.objectWriter, this.linkWriter,
-      {this.baseOffset: 0});
+  // Prefix of the data stored in this writer.
+  // List of pairs Uint8List buffer, int length.
+  List<dynamic> _buffers;
+  // Total length of data in [_buffers].
+  int _buffersLength = 0;
+
+  Uint8List _currentBuffer = new Uint8List(initialSize);
+  int _currentLength = 0;
+  int _nextBufferSize = initialSize << 1;
+
+  BufferedWriter(this.formatVersion, this.stringWriter, this.objectWriter,
+      this.linkWriter);
 
   factory BufferedWriter.fromWriter(BufferedWriter writer) =>
       new BufferedWriter(writer.formatVersion, writer.stringWriter,
           writer.objectWriter, writer.linkWriter);
 
-  List<int> takeBytes() => bytes.takeBytes();
+  Uint8List getContents() {
+    if (_buffers == null) {
+      return new Uint8List.view(
+          _currentBuffer.buffer, _currentBuffer.offsetInBytes, _currentLength);
+    }
+    final Uint8List result = new Uint8List(_buffersLength + _currentLength);
+    int position = 0;
+    for (int i = 0; i < _buffers.length; i += 2) {
+      final Uint8List buf = _buffers[i];
+      final int len = _buffers[i + 1];
+      result.setRange(position, position + len, buf);
+      position += len;
+    }
+    assert(position == _buffersLength);
+    result.setRange(position, position + _currentLength, _currentBuffer);
+    return result;
+  }
 
-  int get offset => bytes.length;
+  void writeContentsToBinarySink(BinarySink sink) {
+    if (_buffers != null) {
+      for (int i = 0; i < _buffers.length; i += 2) {
+        Uint8List buf = _buffers[i];
+        final int len = _buffers[i + 1];
+        if (len != buf.length) {
+          buf = new Uint8List.view(buf.buffer, buf.offsetInBytes, len);
+        }
+        sink.writeBytes(buf);
+      }
+    }
+    Uint8List buf = _currentBuffer;
+    if (_currentLength != buf.length) {
+      buf = new Uint8List.view(buf.buffer, buf.offsetInBytes, _currentLength);
+    }
+    sink.writeBytes(buf);
+  }
 
-  void writeByte(int value) {
+  int get offset => _buffersLength + _currentLength;
+
+  @pragma('vm:prefer-inline')
+  void _addByte(int value) {
     assert((value >> 8) == 0);
-    bytes.addByte(value);
+    _currentBuffer[_currentLength] = value;
+    ++_currentLength;
   }
 
-  void writeBytes(List<int> values) {
-    bytes.add(values);
+  void _flushBuffer(Uint8List buf, int len) {
+    _buffers ??= <dynamic>[];
+    _buffers.add(buf);
+    _buffers.add(len);
+    _buffersLength += len;
   }
 
+  void _flushCurrentBuffer() {
+    _flushBuffer(_currentBuffer, _currentLength);
+    _currentBuffer = null;
+    _currentLength = 0;
+  }
+
+  @pragma('vm:never-inline')
+  void _grow() {
+    _flushCurrentBuffer();
+    // Callers of _grow() expect up to avoidCopyingSize bytes to be available.
+    assert(_nextBufferSize >= avoidCopyingSize);
+    _currentBuffer = new Uint8List(_nextBufferSize);
+    _nextBufferSize = _nextBufferSize << 1;
+  }
+
+  @pragma('vm:prefer-inline')
+  void writeByte(int value) {
+    if (_currentLength == _currentBuffer.length) {
+      _grow();
+    }
+    _addByte(value);
+  }
+
+  void appendUint8List(Uint8List src) {
+    if (src.length < avoidCopyingSize) {
+      if (_currentLength > _currentBuffer.length - src.length) {
+        _grow();
+      }
+      _currentBuffer.setRange(_currentLength, _currentLength + src.length, src);
+      _currentLength += src.length;
+    } else {
+      final int remainingBytes = _currentBuffer.length - _currentLength;
+      if (remainingBytes >= minRemainderToKeep) {
+        final Uint8List remainder = new Uint8List.view(_currentBuffer.buffer,
+            _currentBuffer.offsetInBytes + _currentLength, remainingBytes);
+        _flushCurrentBuffer();
+        _flushBuffer(src, src.length);
+        _currentBuffer = remainder;
+        _currentLength = 0;
+      } else {
+        _flushCurrentBuffer();
+        _currentBuffer = src;
+        _currentLength = src.length;
+      }
+    }
+  }
+
+  void appendWriter(BufferedWriter other) {
+    final int remainingBytes = _currentBuffer.length - _currentLength;
+    Uint8List remainder;
+    if (remainingBytes >= minRemainderToKeep &&
+        remainingBytes > (other._currentBuffer.length - other._currentLength)) {
+      remainder = new Uint8List.view(_currentBuffer.buffer,
+          _currentBuffer.offsetInBytes + _currentLength, remainingBytes);
+    }
+    _flushCurrentBuffer();
+    if (other._buffers != null) {
+      _buffers.addAll(other._buffers);
+      _buffersLength += other._buffersLength;
+    }
+    if (remainder != null) {
+      _flushBuffer(other._currentBuffer, other._currentLength);
+      _currentBuffer = remainder;
+      _currentLength = 0;
+    } else {
+      _currentBuffer = other._currentBuffer;
+      _currentLength = other._currentLength;
+    }
+    // Reset [other] to make sure it is no longer used.
+    other._buffers = null;
+    other._buffersLength = 0;
+    other._currentBuffer = null;
+    other._currentLength = 0;
+  }
+
+  @pragma('vm:prefer-inline')
   void writeUInt32(int value) {
     if ((value >> 32) != 0) {
       throw 'Unable to write $value as 32-bit unsigned integer';
     }
+    if (_currentLength > _currentBuffer.length - 4) {
+      _grow();
+    }
     // TODO(alexmarkov): consider using native byte order
-    bytes.addByte((value >> 24) & 0xFF);
-    bytes.addByte((value >> 16) & 0xFF);
-    bytes.addByte((value >> 8) & 0xFF);
-    bytes.addByte(value & 0xFF);
+    _addByte((value >> 24) & 0xFF);
+    _addByte((value >> 16) & 0xFF);
+    _addByte((value >> 8) & 0xFF);
+    _addByte(value & 0xFF);
   }
 
+  @pragma('vm:prefer-inline')
   void writePackedUInt30(int value) {
     if ((value >> 30) != 0) {
       throw 'Unable to write $value as 30-bit unsigned integer';
     }
     if (value < 0x80) {
-      bytes.addByte(value);
+      writeByte(value);
     } else if (value < 0x4000) {
-      bytes.addByte((value >> 8) | 0x80);
-      bytes.addByte(value & 0xFF);
+      if (_currentLength > _currentBuffer.length - 2) {
+        _grow();
+      }
+      _addByte((value >> 8) | 0x80);
+      _addByte(value & 0xFF);
     } else {
-      bytes.addByte((value >> 24) | 0xC0);
-      bytes.addByte((value >> 16) & 0xFF);
-      bytes.addByte((value >> 8) & 0xFF);
-      bytes.addByte(value & 0xFF);
+      if (_currentLength > _currentBuffer.length - 4) {
+        _grow();
+      }
+      _addByte((value >> 24) | 0xC0);
+      _addByte((value >> 16) & 0xFF);
+      _addByte((value >> 8) & 0xFF);
+      _addByte(value & 0xFF);
     }
   }
 
+  @pragma('vm:prefer-inline')
   void writeSLEB128(int value) {
     bool last = false;
     do {
@@ -93,18 +237,21 @@
       } else {
         part |= 0x80;
       }
-      bytes.addByte(part);
+      writeByte(part);
     } while (!last);
   }
 
+  @pragma('vm:prefer-inline')
   void writePackedStringReference(String value) {
     writePackedUInt30(stringWriter.put(value));
   }
 
+  @pragma('vm:prefer-inline')
   void writePackedObject(BytecodeObject object) {
     objectWriter.writeObject(object, this);
   }
 
+  @pragma('vm:prefer-inline')
   void writePackedList(List<BytecodeObject> objects) {
     writePackedUInt30(objects.length);
     for (var obj in objects) {
@@ -112,19 +259,11 @@
     }
   }
 
+  @pragma('vm:prefer-inline')
   void writeLinkOffset(Object target) {
     final offset = linkWriter.getOffset(target);
     writePackedUInt30(offset);
   }
-
-  void align(int alignment) {
-    assert(alignment & (alignment - 1) == 0);
-    int offs = baseOffset + offset;
-    int padding = ((offs + alignment - 1) & -alignment) - offs;
-    for (int i = 0; i < padding; ++i) {
-      bytes.addByte(0);
-    }
-  }
 }
 
 class BufferedReader {
@@ -229,12 +368,13 @@
     return result;
   }
 
-  T readLinkOffset<T>() {
+  T readLinkOffset<T extends BytecodeDeclaration>() {
     final offset = readPackedUInt30();
     return linkReader.get<T>(offset);
   }
 
-  ForwardReference<T> readLinkOffsetAsForwardReference<T>() {
+  ForwardReference<T>
+      readLinkOffsetAsForwardReference<T extends BytecodeDeclaration>() {
     final offset = readPackedUInt30();
     return new ForwardReference<T>(offset, linkReader);
   }
@@ -429,24 +569,26 @@
   }
 }
 
-class LinkWriter {
-  final _map = <Object, int>{};
+class BytecodeDeclaration {
+  int _offset;
+}
 
-  void put(Object target, int offset) {
-    _map[target] = offset;
+class LinkWriter {
+  void put(BytecodeDeclaration target, int offset) {
+    target._offset = offset;
   }
 
-  int getOffset(Object target) {
-    return _map[target] ??
+  int getOffset(BytecodeDeclaration target) {
+    return target._offset ??
         (throw 'Offset of ${target.runtimeType} $target is not set');
   }
 }
 
 class LinkReader {
-  final _map = <Type, Map<int, Object>>{};
+  final _map = <Type, Map<int, BytecodeDeclaration>>{};
 
-  void setOffset<T>(T target, int offset) {
-    final offsetToObject = (_map[T] ??= <int, Object>{});
+  void setOffset<T extends BytecodeDeclaration>(T target, int offset) {
+    final offsetToObject = (_map[T] ??= <int, BytecodeDeclaration>{});
     final previous = offsetToObject[offset];
     if (previous != null) {
       throw 'Unable to associate offset $T/$offset with ${target.runtimeType} $target.'
@@ -455,13 +597,13 @@
     offsetToObject[offset] = target;
   }
 
-  T get<T>(int offset) {
+  T get<T extends BytecodeDeclaration>(int offset) {
     return _map[T][offset] ?? (throw 'No object at offset $T/$offset');
   }
 }
 
 // Placeholder for an object which will be read in future.
-class ForwardReference<T> {
+class ForwardReference<T extends BytecodeDeclaration> {
   final int offset;
   final LinkReader linkReader;
 
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index 4dd58a2..ee869ec 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -829,14 +829,16 @@
           isSetter: invocationKind == InvocationKind.setter)));
 
   int _add(ConstantPoolEntry entry) {
-    return _canonicalizationCache.putIfAbsent(entry, () {
-      int index = entries.length;
+    int index = _canonicalizationCache[entry];
+    if (index == null) {
+      index = entries.length;
       if (index >= constantPoolIndexLimit) {
         throw new ConstantPoolIndexOverflowException();
       }
       _addEntry(entry);
-      return index;
-    });
+      _canonicalizationCache[entry] = index;
+    }
+    return index;
   }
 
   void _addEntry(ConstantPoolEntry entry) {
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index b17b227..ff4bc6d 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
 /// Before bumping current bytecode version format, make sure that
 /// all users have switched to a VM which is able to consume new
 /// version of bytecode.
-const int currentBytecodeFormatVersion = 23;
+const int currentBytecodeFormatVersion = 25;
 
 enum Opcode {
   kUnusedOpcode000,
@@ -258,8 +258,8 @@
 
   // Null operations.
   kEqualsNull,
-  kCheckReceiverForNull,
-  kCheckReceiverForNull_Wide,
+  kNullCheck,
+  kNullCheck_Wide,
 
   // Int operations.
   kNegateInt,
@@ -468,7 +468,7 @@
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kEqualsNull: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
-  Opcode.kCheckReceiverForNull: const Format(
+  Opcode.kNullCheck: const Format(
       Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
   Opcode.kNegateInt: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
@@ -534,7 +534,7 @@
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
 };
 
-// Should match constant in runtime/vm/stack_frame_dbc.h.
+// Should match constant in runtime/vm/stack_frame_kbc.h.
 const int kParamEndSlotFromFp = 4;
 
 enum SpecialIndex {
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index c4c34b1..6acb9ff 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -4,9 +4,14 @@
 
 library vm.bytecode.declarations;
 
-import 'package:kernel/ast.dart';
+import 'package:kernel/ast.dart' show TreeNode, listHashCode, listEquals;
 import 'bytecode_serialization.dart'
-    show BufferedWriter, BufferedReader, BytecodeSizeStatistics, StringTable;
+    show
+        BufferedWriter,
+        BufferedReader,
+        BytecodeDeclaration,
+        BytecodeSizeStatistics,
+        StringTable;
 import 'constant_pool.dart' show ConstantPool;
 import 'dbc.dart' show currentBytecodeFormatVersion;
 import 'disassembler.dart' show BytecodeDisassembler;
@@ -15,7 +20,9 @@
 import 'object_table.dart' show ObjectTable, ObjectHandle, NameAndType;
 import 'source_positions.dart' show LineStarts, SourcePositions;
 
-class LibraryDeclaration {
+import 'dart:typed_data' show Uint8List;
+
+class LibraryDeclaration extends BytecodeDeclaration {
   static const usesDartMirrorsFlag = 1 << 0;
   static const usesDartFfiFlag = 1 << 1;
   static const hasExtensionsFlag = 1 << 2;
@@ -89,7 +96,7 @@
   }
 }
 
-class ClassDeclaration {
+class ClassDeclaration extends BytecodeDeclaration {
   static const isAbstractFlag = 1 << 0;
   static const isEnumFlag = 1 << 1;
   static const hasTypeParamsFlag = 1 << 2;
@@ -220,7 +227,7 @@
   }
 }
 
-class SourceFile {
+class SourceFile extends BytecodeDeclaration {
   static const hasLineStartsFlag = 1 << 0;
   static const hasSourceFlag = 1 << 1;
 
@@ -274,7 +281,7 @@
   }
 }
 
-class Members {
+class Members extends BytecodeDeclaration {
   final List<FieldDeclaration> fields;
   final List<FunctionDeclaration> functions;
 
@@ -789,7 +796,7 @@
   String toString() => '$type $name';
 }
 
-class Code {
+class Code extends BytecodeDeclaration {
   static const hasExceptionsTableFlag = 1 << 0;
   static const hasSourcePositionsFlag = 1 << 1;
   static const hasNullableFieldsFlag = 1 << 2;
@@ -800,7 +807,7 @@
   static const hasLocalVariablesFlag = 1 << 7;
 
   final ConstantPool constantPool;
-  final List<int> bytecodes;
+  final Uint8List bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
   final LocalVariableTable localVariables;
@@ -898,7 +905,7 @@
             (_) => new ClosureDeclaration.read(reader))
         : const <ClosureDeclaration>[];
     final ConstantPool constantPool = new ConstantPool.read(reader);
-    final List<int> bytecodes = _readBytecodeInstructions(reader);
+    final Uint8List bytecodes = _readBytecodeInstructions(reader);
     final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
         ? new ExceptionsTable.read(reader)
         : new ExceptionsTable();
@@ -949,16 +956,17 @@
 }
 
 class ClosureDeclaration {
-  static const int hasOptionalPositionalParamsFlag = 1 << 0;
-  static const int hasOptionalNamedParamsFlag = 1 << 1;
-  static const int hasTypeParamsFlag = 1 << 2;
-  static const int hasSourcePositionsFlag = 1 << 3;
-  static const int isAsyncFlag = 1 << 4;
-  static const int isAsyncStarFlag = 1 << 5;
-  static const int isSyncStarFlag = 1 << 6;
-  static const int isDebuggableFlag = 1 << 7;
+  static const hasOptionalPositionalParamsFlag = 1 << 0;
+  static const hasOptionalNamedParamsFlag = 1 << 1;
+  static const hasTypeParamsFlag = 1 << 2;
+  static const hasSourcePositionsFlag = 1 << 3;
+  static const isAsyncFlag = 1 << 4;
+  static const isAsyncStarFlag = 1 << 5;
+  static const isSyncStarFlag = 1 << 6;
+  static const isDebuggableFlag = 1 << 7;
+  static const hasAttributesFlag = 1 << 8;
 
-  final int flags;
+  int flags;
   final ObjectHandle parent;
   final ObjectHandle name;
   final int position;
@@ -968,6 +976,7 @@
   final int numNamedParams;
   final List<NameAndType> parameters;
   final ObjectHandle returnType;
+  ObjectHandle attributes;
   ClosureCode code;
 
   ClosureDeclaration(
@@ -980,7 +989,8 @@
       this.numRequiredParams,
       this.numNamedParams,
       this.parameters,
-      this.returnType);
+      this.returnType,
+      [this.attributes]);
 
   void write(BufferedWriter writer) {
     writer.writePackedUInt30(flags);
@@ -1012,6 +1022,9 @@
       writer.writePackedObject(param.type);
     }
     writer.writePackedObject(returnType);
+    if ((flags & hasAttributesFlag) != 0) {
+      writer.writePackedObject(attributes);
+    }
   }
 
   factory ClosureDeclaration.read(BufferedReader reader) {
@@ -1051,8 +1064,20 @@
         (_) => new NameAndType(
             reader.readPackedObject(), reader.readPackedObject()));
     final returnType = reader.readPackedObject();
-    return new ClosureDeclaration(flags, parent, name, position, endPosition,
-        typeParams, numRequiredParams, numNamedParams, parameters, returnType);
+    final attributes =
+        ((flags & hasAttributesFlag) != 0) ? reader.readPackedObject() : null;
+    return new ClosureDeclaration(
+        flags,
+        parent,
+        name,
+        position,
+        endPosition,
+        typeParams,
+        numRequiredParams,
+        numNamedParams,
+        parameters,
+        returnType,
+        attributes);
   }
 
   @override
@@ -1088,6 +1113,9 @@
     }
     sb.write(') -> ');
     sb.writeln(returnType);
+    if ((flags & hasAttributesFlag) != 0) {
+      sb.write('    attributes $attributes\n');
+    }
     if (code != null) {
       sb.write(code.toString());
     }
@@ -1102,7 +1130,7 @@
   static const hasSourcePositionsFlag = 1 << 1;
   static const hasLocalVariablesFlag = 1 << 2;
 
-  final List<int> bytecodes;
+  final Uint8List bytecodes;
   final ExceptionsTable exceptionsTable;
   final SourcePositions sourcePositions;
   final LocalVariableTable localVariables;
@@ -1137,7 +1165,7 @@
 
   factory ClosureCode.read(BufferedReader reader) {
     final int flags = reader.readPackedUInt30();
-    final List<int> bytecodes = _readBytecodeInstructions(reader);
+    final Uint8List bytecodes = _readBytecodeInstructions(reader);
     final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
         ? new ExceptionsTable.read(reader)
         : new ExceptionsTable();
@@ -1169,7 +1197,7 @@
   }
 }
 
-class AnnotationsDeclaration {
+class AnnotationsDeclaration extends BytecodeDeclaration {
   final ObjectHandle object;
 
   AnnotationsDeclaration(this.object);
@@ -1337,7 +1365,6 @@
     int offset = headerSize;
     for (var section in sections) {
       if (section.writer != null) {
-        offset = (offset + sectionAlignment - 1) & ~(sectionAlignment - 1);
         section.offset = offset;
         offset += section.size;
       } else {
@@ -1356,9 +1383,8 @@
     assert(writer.offset - start == headerSize);
     for (var section in sections) {
       if (section.writer != null) {
-        writer.align(sectionAlignment);
         assert(writer.offset - start == section.offset);
-        writer.writeBytes(section.writer.takeBytes());
+        writer.appendWriter(section.writer);
       }
     }
 
@@ -1556,13 +1582,13 @@
   }
 }
 
-void _writeBytecodeInstructions(BufferedWriter writer, List<int> bytecodes) {
+void _writeBytecodeInstructions(BufferedWriter writer, Uint8List bytecodes) {
   writer.writePackedUInt30(bytecodes.length);
-  writer.writeBytes(bytecodes);
+  writer.appendUint8List(bytecodes);
   BytecodeSizeStatistics.instructionsSize += bytecodes.length;
 }
 
-List<int> _readBytecodeInstructions(BufferedReader reader) {
+Uint8List _readBytecodeInstructions(BufferedReader reader) {
   int len = reader.readPackedUInt30();
   return reader.readBytesAsUint8List(len);
 }
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index bb7f76d..6b1b024 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -433,7 +433,7 @@
     return new Annotations(decl, hasPragma);
   }
 
-  ObjectHandle getMemberAttributes(Member member) {
+  ObjectHandle getMemberAttributes() {
     if (procedureAttributesMetadata == null && inferredTypesAttribute == null) {
       return null;
     }
@@ -453,6 +453,17 @@
     return objectTable.getHandle(ListConstant(const DynamicType(), attrs));
   }
 
+  ObjectHandle getClosureAttributes() {
+    if (inferredTypesAttribute == null) {
+      return null;
+    }
+    final attrs = <Constant>[
+      StringConstant(InferredTypeMetadataRepository.repositoryTag),
+      ListConstant(const DynamicType(), inferredTypesAttribute),
+    ];
+    return objectTable.getHandle(ListConstant(const DynamicType(), attrs));
+  }
+
   // Insert annotations for the function and its parameters into the annotations
   // section. Return the annotations for the function only. The bytecode reader
   // will implicitly find the parameter annotations by reading N packed objects
@@ -621,7 +632,7 @@
         flags |= FieldDeclaration.hasPragmaFlag;
       }
     }
-    final ObjectHandle attributes = getMemberAttributes(field);
+    final ObjectHandle attributes = getMemberAttributes();
     if (attributes != null) {
       flags |= FieldDeclaration.hasAttributesFlag;
     }
@@ -737,7 +748,7 @@
         flags |= FunctionDeclaration.hasPragmaFlag;
       }
     }
-    final ObjectHandle attributes = getMemberAttributes(member);
+    final ObjectHandle attributes = getMemberAttributes();
     if (attributes != null) {
       flags |= FunctionDeclaration.hasAttributesFlag;
     }
@@ -1060,7 +1071,7 @@
 
   Procedure _asyncAwaitCompleterGetFuture;
   Procedure get asyncAwaitCompleterGetFuture =>
-      _asyncAwaitCompleterGetFuture ??= libraryIndex.getMember(
+      _asyncAwaitCompleterGetFuture ??= libraryIndex.tryGetMember(
           'dart:async', '_AsyncAwaitCompleter', 'get:future');
 
   Procedure _setAsyncThreadStackTrace;
@@ -1645,18 +1656,18 @@
       return;
     }
 
-    labeledStatements = <LabeledStatement, Label>{};
-    switchCases = <SwitchCase, Label>{};
-    tryCatches = <TryCatch, TryBlock>{};
-    finallyBlocks = <TryFinally, List<FinallyBlock>>{};
+    labeledStatements = null;
+    switchCases = null;
+    tryCatches = null;
+    finallyBlocks = null;
     yieldPoints = null; // Initialized when entering sync-yielding closure.
-    contextLevels = <TreeNode, int>{};
-    closures = <ClosureDeclaration>[];
+    contextLevels = null;
+    closures = null;
     initializedFields = null; // Tracked for constructors only.
     nullableFields = const <ObjectHandle>[];
     cp = new ConstantPool(stringTable, objectTable);
     asm = new BytecodeAssembler(options);
-    savedAssemblers = <BytecodeAssembler>[];
+    savedAssemblers = null;
     currentLoopDepth = 0;
     savedMaxSourcePositions = <int>[];
     maxSourcePosition = node.fileOffset;
@@ -1686,7 +1697,7 @@
 
   void _appendInferredType(TreeNode node, int pc) {
     final InferredType md = inferredTypeMetadata[node];
-    if (md == null) {
+    if (md == null || (pc >= 0 && asm.isUnreachable)) {
       return;
     }
     inferredTypesAttribute ??= <Constant>[];
@@ -1769,7 +1780,7 @@
             finalizeSourcePositions(),
             finalizeLocalVariables(),
             nullableFields,
-            closures,
+            closures ?? const <ClosureDeclaration>[],
             parameterFlags,
             forwardingStubTargetCpIndex,
             defaultFunctionTypeArgsCpIndex);
@@ -1915,9 +1926,6 @@
 
     // CheckStack must see a properly initialized context when stress-testing
     // stack trace collection.
-    // Also, simdbc doesn't support arguments descriptor SpecialDbcRegister as
-    // a source location for deopt info, so CheckStack should be generated
-    // after the code which uses arguments descriptor.
     asm.emitCheckStack(0);
 
     if (locals.hasFunctionTypeArgsVar && isClosure) {
@@ -2333,6 +2341,7 @@
   }
 
   void _pushAssemblerState() {
+    savedAssemblers ??= <BytecodeAssembler>[];
     savedAssemblers.add(asm);
     asm = new BytecodeAssembler(options);
   }
@@ -2354,6 +2363,8 @@
     enclosingFunction = function;
     final savedLoopDepth = currentLoopDepth;
     currentLoopDepth = 0;
+    final savedInferredTypesAttribute = inferredTypesAttribute;
+    inferredTypesAttribute = null;
 
     if (function.typeParameters.isNotEmpty) {
       functionTypeParameters ??= new List<TypeParameter>();
@@ -2364,6 +2375,7 @@
     List<Label> savedYieldPoints = yieldPoints;
     yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
 
+    closures ??= <ClosureDeclaration>[];
     final int closureIndex = closures.length;
     final closure = getClosureDeclaration(node, function, name, closureIndex,
         savedIsClosure ? parentFunction : enclosingMember);
@@ -2431,6 +2443,13 @@
     isClosure = savedIsClosure;
     currentLoopDepth = savedLoopDepth;
 
+    final attributes = getClosureAttributes();
+    if (attributes != null) {
+      closure.attributes = attributes;
+      closure.flags |= ClosureDeclaration.hasAttributesFlag;
+    }
+    inferredTypesAttribute = savedInferredTypesAttribute;
+
     locals.leaveScope();
 
     closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
@@ -2594,9 +2613,12 @@
     _genPushFunctionTypeArguments();
     asm.emitStoreFieldTOS(cp.addInstanceField(closureFunctionTypeArguments));
 
-    asm.emitPush(temp);
-    asm.emitPushConstant(cp.addEmptyTypeArguments());
-    asm.emitStoreFieldTOS(cp.addInstanceField(closureDelayedTypeArguments));
+    // Delayed type arguments are only used by generic closures.
+    if (function.typeParameters.isNotEmpty) {
+      asm.emitPush(temp);
+      asm.emitPushConstant(cp.addEmptyTypeArguments());
+      asm.emitStoreFieldTOS(cp.addInstanceField(closureDelayedTypeArguments));
+    }
 
     asm.emitPush(temp);
     asm.emitPushConstant(closureFunctionIndex);
@@ -3228,8 +3250,7 @@
     // correct noSuchMethod for method call.
     if (checkForNull) {
       asm.emitPush(receiverTemp);
-      asm.emitCheckReceiverForNull(
-          cp.addSelectorName(node.name, InvocationKind.method));
+      asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.method));
     }
 
     _genInstanceCall(null, InvocationKind.getter, node.interfaceTarget,
@@ -3286,8 +3307,7 @@
       final int receiverTemp = locals.tempIndexInFrame(node);
       _genArguments(node.receiver, args, storeReceiverToLocal: receiverTemp);
       asm.emitPush(receiverTemp);
-      asm.emitCheckReceiverForNull(
-          cp.addSelectorName(node.name, InvocationKind.method));
+      asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.method));
     } else {
       _genArguments(node.receiver, args);
     }
@@ -3321,8 +3341,7 @@
         final int receiverTemp = locals.tempIndexInFrame(node);
         asm.emitStoreLocal(receiverTemp);
         asm.emitPush(receiverTemp);
-        asm.emitCheckReceiverForNull(
-            cp.addSelectorName(node.name, InvocationKind.getter));
+        asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.getter));
       }
       _genDirectCall(directCall.target, argDesc, 1, isGet: true, node: node);
     } else {
@@ -3344,8 +3363,7 @@
       asm.emitStoreLocal(temp);
       _generateNode(node.value);
       asm.emitPush(temp);
-      asm.emitCheckReceiverForNull(
-          cp.addSelectorName(node.name, InvocationKind.setter));
+      asm.emitNullCheck(cp.addSelectorName(node.name, InvocationKind.setter));
     } else {
       _generateNode(node.value);
     }
@@ -3455,6 +3473,15 @@
   }
 
   @override
+  visitNullCheck(NullCheck node) {
+    _generateNode(node.operand);
+    final operandTemp = locals.tempIndexInFrame(node);
+    asm.emitStoreLocal(operandTemp);
+    asm.emitPush(operandTemp);
+    asm.emitNullCheck(cp.addObjectRef(null));
+  }
+
+  @override
   visitNullLiteral(NullLiteral node) {
     asm.emitPushNull();
   }
@@ -3986,7 +4013,9 @@
   @override
   visitLabeledStatement(LabeledStatement node) {
     final label = new Label();
+    labeledStatements ??= new Map<LabeledStatement, Label>();
     labeledStatements[node] = label;
+    contextLevels ??= new Map<TreeNode, int>();
     contextLevels[node] = locals.currentContextLevel;
     _generateNode(node.body);
     asm.bind(label);
@@ -4029,6 +4058,7 @@
 
   @override
   visitSwitchStatement(SwitchStatement node) {
+    contextLevels ??= new Map<TreeNode, int>();
     contextLevels[node] = locals.currentContextLevel;
 
     _generateNode(node.expression);
@@ -4047,6 +4077,8 @@
         node.cases.length, (_) => new Label(allowsBackwardJumps: true));
     final equalsArgDesc = objectTable.getArgDescHandle(2);
 
+    switchCases ??= new Map<SwitchCase, Label>();
+
     Label defaultLabel = done;
     for (int i = 0; i < node.cases.length; i++) {
       final SwitchCase switchCase = node.cases[i];
@@ -4216,6 +4248,7 @@
 
     final TryBlock tryBlock = _startTryBlock(node);
     tryBlock.isSynthetic = node.isSynthetic;
+    tryCatches ??= new Map<TryCatch, TryBlock>();
     tryCatches[node] = tryBlock; // Used by rethrow.
 
     _generateNode(node.body);
@@ -4287,6 +4320,7 @@
 
     final TryBlock tryBlock = _startTryBlock(node);
     tryBlock.isSynthetic = true;
+    finallyBlocks ??= new Map<TryFinally, List<FinallyBlock>>();
     finallyBlocks[node] = <FinallyBlock>[];
 
     _generateNode(node.body);
@@ -4322,21 +4356,25 @@
   visitVariableDeclaration(VariableDeclaration node) {
     if (!node.isConst) {
       final bool isCaptured = locals.isCaptured(node);
-      if (isCaptured) {
-        _genPushContextForVariable(node);
-      }
+      final initializer = node.initializer;
+      final bool emitStore =
+          !(isCaptured && (initializer == null || initializer is NullLiteral));
       int maxInitializerPosition = node.fileOffset;
-      if (node.initializer != null) {
-        _startRecordingMaxPosition(node.fileOffset);
-        _generateNode(node.initializer);
-        maxInitializerPosition = _endRecordingMaxPosition();
-      } else {
-        asm.emitPushNull();
+      if (emitStore) {
+        if (isCaptured) {
+          _genPushContextForVariable(node);
+        }
+        if (initializer != null) {
+          _startRecordingMaxPosition(node.fileOffset);
+          _generateNode(initializer);
+          maxInitializerPosition = _endRecordingMaxPosition();
+        } else {
+          asm.emitPushNull();
+        }
       }
 
       if (options.emitDebuggerStops &&
-          (node.initializer == null ||
-              _variableSetNeedsDebugCheck(node.initializer))) {
+          (initializer == null || _variableSetNeedsDebugCheck(initializer))) {
         final savedSourcePosition = asm.currentSourcePosition;
         if (node.fileEqualsOffset != TreeNode.noOffset) {
           _recordSourcePosition(node.fileEqualsOffset);
@@ -4348,7 +4386,10 @@
       if (options.emitLocalVarInfo && !asm.isUnreachable && node.name != null) {
         _declareLocalVariable(node, maxInitializerPosition + 1);
       }
-      _genStoreVar(node);
+
+      if (emitStore) {
+        _genStoreVar(node);
+      }
     }
   }
 
diff --git a/pkg/vm/lib/bytecode/local_variable_table.dart b/pkg/vm/lib/bytecode/local_variable_table.dart
index 24607fa..cdbeb45 100644
--- a/pkg/vm/lib/bytecode/local_variable_table.dart
+++ b/pkg/vm/lib/bytecode/local_variable_table.dart
@@ -128,7 +128,7 @@
 }
 
 /// Keeps information about declared local variables.
-class LocalVariableTable {
+class LocalVariableTable extends BytecodeDeclaration {
   final scopes = <Scope>[];
   final activeScopes = <Scope>[];
   ContextVariable contextVariable;
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 18074aa..6261edb 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -17,18 +17,13 @@
 import '../metadata/direct_call.dart' show DirectCallMetadata;
 
 class LocalVariables {
-  final Map<TreeNode, Scope> _scopes = <TreeNode, Scope>{};
-  final Map<VariableDeclaration, VarDesc> _vars =
-      <VariableDeclaration, VarDesc>{};
-  final Map<TreeNode, List<int>> _temps = <TreeNode, List<int>>{};
-  final Map<TreeNode, VariableDeclaration> _capturedSavedContextVars =
-      <TreeNode, VariableDeclaration>{};
-  final Map<TreeNode, VariableDeclaration> _capturedExceptionVars =
-      <TreeNode, VariableDeclaration>{};
-  final Map<TreeNode, VariableDeclaration> _capturedStackTraceVars =
-      <TreeNode, VariableDeclaration>{};
-  final Map<ForInStatement, VariableDeclaration> _capturedIteratorVars =
-      <ForInStatement, VariableDeclaration>{};
+  final _scopes = new Map<TreeNode, Scope>();
+  final _vars = new Map<VariableDeclaration, VarDesc>();
+  Map<TreeNode, List<int>> _temps;
+  Map<TreeNode, VariableDeclaration> _capturedSavedContextVars;
+  Map<TreeNode, VariableDeclaration> _capturedExceptionVars;
+  Map<TreeNode, VariableDeclaration> _capturedStackTraceVars;
+  Map<ForInStatement, VariableDeclaration> _capturedIteratorVars;
   final BytecodeOptions options;
   final TypeEnvironment typeEnvironment;
   final Map<TreeNode, DirectCallMetadata> directCallMetadata;
@@ -155,13 +150,15 @@
   }
 
   VariableDeclaration capturedSavedContextVar(TreeNode node) =>
-      _capturedSavedContextVars[node];
+      _capturedSavedContextVars != null
+          ? _capturedSavedContextVars[node]
+          : null;
   VariableDeclaration capturedExceptionVar(TreeNode node) =>
-      _capturedExceptionVars[node];
+      _capturedExceptionVars != null ? _capturedExceptionVars[node] : null;
   VariableDeclaration capturedStackTraceVar(TreeNode node) =>
-      _capturedStackTraceVars[node];
+      _capturedStackTraceVars != null ? _capturedStackTraceVars[node] : null;
   VariableDeclaration capturedIteratorVar(ForInStatement node) =>
-      _capturedIteratorVars[node];
+      _capturedIteratorVars != null ? _capturedIteratorVars[node] : null;
 
   int get asyncExceptionParamIndexInFrame {
     assert(_currentFrame.isSyncYielding);
@@ -521,12 +518,18 @@
   void _captureSyntheticVariables() {
     int depth = 0;
     for (TreeNode tryBlock in _enclosingTryBlocks) {
+      locals._capturedSavedContextVars ??=
+          new Map<TreeNode, VariableDeclaration>();
       _captureSyntheticVariable(ContinuationVariables.savedTryContextVar(depth),
           tryBlock, locals._capturedSavedContextVars);
       ++depth;
     }
     depth = 0;
     for (TreeNode tryBlock in _enclosingTryCatches) {
+      locals._capturedExceptionVars ??=
+          new Map<TreeNode, VariableDeclaration>();
+      locals._capturedStackTraceVars ??=
+          new Map<TreeNode, VariableDeclaration>();
       _captureSyntheticVariable(ContinuationVariables.exceptionVar(depth),
           tryBlock, locals._capturedExceptionVars);
       _captureSyntheticVariable(ContinuationVariables.stackTraceVar(depth),
@@ -685,6 +688,8 @@
       // Declare a variable to hold 'iterator' so it could be captured.
       iteratorVar = new VariableDeclaration(':iterator');
       _declareVariable(iteratorVar);
+      locals._capturedIteratorVars ??=
+          new Map<ForInStatement, VariableDeclaration>();
       locals._capturedIteratorVars[node] = iteratorVar;
     }
 
@@ -886,6 +891,7 @@
   }
 
   void _allocateTemp(TreeNode node, {int count: 1}) {
+    locals._temps ??= new Map<TreeNode, List<int>>();
     assert(locals._temps[node] == null);
     if (_currentScope.tempsUsed + count > _currentFrame.temporaries.length) {
       // Allocate new local slots for temporary variables.
@@ -1143,7 +1149,9 @@
   @override
   visitForInStatement(ForInStatement node) {
     _allocateTemp(node);
-    _ensureVariableAllocated(locals._capturedIteratorVars[node]);
+    if (locals._capturedIteratorVars != null) {
+      _ensureVariableAllocated(locals._capturedIteratorVars[node]);
+    }
 
     node.iterable.accept(this);
 
@@ -1289,6 +1297,11 @@
   visitInstantiation(Instantiation node) {
     _visit(node, temps: 3);
   }
+
+  @override
+  visitNullCheck(NullCheck node) {
+    _visit(node, temps: 1);
+  }
 }
 
 class LocalVariableIndexOverflowException
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index ca1e1c3..063361f 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -201,6 +201,11 @@
   typeTag (flags) = 2
 }
 
+type NeverType extends Type {
+  kind = 15
+  typeTag (flags) = 9
+}
+
 // SimpleType can be used only for types without instantiator type arguments.
 type SimpleType extends Type {
   kind = 15
@@ -321,6 +326,7 @@
   kRecursiveGenericType,
   kRecursiveTypeRef,
   kFunctionType,
+  kNever,
 }
 
 /// Name of artificial class containing top-level members of a library.
@@ -343,7 +349,10 @@
   static const int flagBit1 = 1 << 6;
   static const int flagBit2 = 1 << 7;
   static const int flagBit3 = 1 << 8;
-  static const int flagsMask = flagBit0 | flagBit1 | flagBit2 | flagBit3;
+  static const int flagBit4 = 1 << 9;
+  static const int flagBit5 = 1 << 10;
+  static const int flagsMask =
+      flagBit0 | flagBit1 | flagBit2 | flagBit3 | flagBit4 | flagBit5;
 
   static int _makeReference(int index) => (index << indexShift) | referenceBit;
 
@@ -407,25 +416,29 @@
       case ObjectKind.kScript:
         return new _ScriptHandle._empty();
       case ObjectKind.kType:
-        switch (TypeTag.values[flags ~/ flagBit0]) {
+        Nullability nullability = Nullability
+            .values[(flags & _TypeHandle.nullabilityMask) ~/ flagBit4];
+        switch (TypeTag.values[(flags & _TypeHandle.tagMask) ~/ flagBit0]) {
           case TypeTag.kInvalid:
             break;
           case TypeTag.kDynamic:
             return new _DynamicTypeHandle();
           case TypeTag.kVoid:
             return new _VoidTypeHandle();
+          case TypeTag.kNever:
+            return new _NeverTypeHandle();
           case TypeTag.kSimpleType:
-            return new _SimpleTypeHandle._empty();
+            return new _SimpleTypeHandle._empty(nullability);
           case TypeTag.kTypeParameter:
-            return new _TypeParameterHandle._empty();
+            return new _TypeParameterHandle._empty(nullability);
           case TypeTag.kGenericType:
-            return new _GenericTypeHandle._empty();
+            return new _GenericTypeHandle._empty(nullability);
           case TypeTag.kRecursiveGenericType:
-            return new _RecursiveGenericTypeHandle._empty();
+            return new _RecursiveGenericTypeHandle._empty(nullability);
           case TypeTag.kRecursiveTypeRef:
-            return new _RecursiveTypeRefHandle._empty();
+            return new _RecursiveTypeRefHandle._empty(nullability);
           case TypeTag.kFunctionType:
-            return new _FunctionTypeHandle._empty();
+            return new _FunctionTypeHandle._empty(nullability);
         }
         throw 'Unexpected type tag $flags';
       case ObjectKind.kUnused1:
@@ -666,26 +679,36 @@
 }
 
 abstract class _TypeHandle extends ObjectHandle {
-  final TypeTag tag;
+  static const int tagMask = ObjectHandle.flagBit0 |
+      ObjectHandle.flagBit1 |
+      ObjectHandle.flagBit2 |
+      ObjectHandle.flagBit3;
+  static const int nullabilityMask =
+      ObjectHandle.flagBit4 | ObjectHandle.flagBit5;
 
-  _TypeHandle(this.tag);
+  final TypeTag tag;
+  Nullability nullability;
+
+  _TypeHandle(this.tag, this.nullability);
 
   @override
   ObjectKind get kind => ObjectKind.kType;
 
   @override
-  int get flags => tag.index * ObjectHandle.flagBit0;
+  int get flags =>
+      (tag.index * ObjectHandle.flagBit0) |
+      (nullability.index * ObjectHandle.flagBit4);
 
   @override
   set flags(int value) {
     if (value != flags) {
-      throw 'Unable to set flags for _TypeHandle (they are occupied by type tag)';
+      throw 'Unable to set flags for _TypeHandle (they are occupied by type tag and nnbd)';
     }
   }
 }
 
 class _DynamicTypeHandle extends _TypeHandle {
-  _DynamicTypeHandle() : super(TypeTag.kDynamic);
+  _DynamicTypeHandle() : super(TypeTag.kDynamic, Nullability.nullable);
 
   @override
   void writeContents(BufferedWriter writer) {}
@@ -704,7 +727,7 @@
 }
 
 class _VoidTypeHandle extends _TypeHandle {
-  _VoidTypeHandle() : super(TypeTag.kVoid);
+  _VoidTypeHandle() : super(TypeTag.kVoid, Nullability.nullable);
 
   @override
   void writeContents(BufferedWriter writer) {}
@@ -722,12 +745,33 @@
   String toString() => 'void';
 }
 
+class _NeverTypeHandle extends _TypeHandle {
+  _NeverTypeHandle() : super(TypeTag.kNever, Nullability.nonNullable);
+
+  @override
+  void writeContents(BufferedWriter writer) {}
+
+  @override
+  void readContents(BufferedReader reader) {}
+
+  @override
+  int get hashCode => 2049;
+
+  @override
+  bool operator ==(other) => other is _NeverTypeHandle;
+
+  @override
+  String toString() => 'Never';
+}
+
 class _SimpleTypeHandle extends _TypeHandle {
   _ClassHandle class_;
 
-  _SimpleTypeHandle._empty() : super(TypeTag.kSimpleType);
+  _SimpleTypeHandle._empty(Nullability nullability)
+      : super(TypeTag.kSimpleType, nullability);
 
-  _SimpleTypeHandle(this.class_) : super(TypeTag.kSimpleType);
+  _SimpleTypeHandle(this.class_, Nullability nullability)
+      : super(TypeTag.kSimpleType, nullability);
 
   @override
   void writeContents(BufferedWriter writer) {
@@ -747,13 +791,16 @@
   }
 
   @override
-  int get hashCode => class_.hashCode + 11;
+  int get hashCode => _combineHashes(class_.hashCode, nullability.index);
 
   @override
   bool operator ==(other) =>
-      other is _SimpleTypeHandle && this.class_ == other.class_;
+      other is _SimpleTypeHandle &&
+      this.class_ == other.class_ &&
+      this.nullability == other.nullability;
 
   @override
+  // TODO(regis): Print nullability, only if nnbd experiment is enabled?
   String toString() => '$class_';
 }
 
@@ -761,10 +808,11 @@
   ObjectHandle parent;
   int indexInParent;
 
-  _TypeParameterHandle._empty() : super(TypeTag.kTypeParameter);
+  _TypeParameterHandle._empty(Nullability nullability)
+      : super(TypeTag.kTypeParameter, nullability);
 
-  _TypeParameterHandle(this.parent, this.indexInParent)
-      : super(TypeTag.kTypeParameter) {
+  _TypeParameterHandle(this.parent, this.indexInParent, Nullability nullability)
+      : super(TypeTag.kTypeParameter, nullability) {
     assert(parent is _ClassHandle ||
         parent is _MemberHandle ||
         parent is _ClosureHandle ||
@@ -795,15 +843,18 @@
   }
 
   @override
-  int get hashCode => _combineHashes(parent.hashCode, indexInParent);
+  int get hashCode => _combineHashes(
+      parent.hashCode, _combineHashes(indexInParent, nullability.index));
 
   @override
   bool operator ==(other) =>
       other is _TypeParameterHandle &&
       this.parent == other.parent &&
-      this.indexInParent == other.indexInParent;
+      this.indexInParent == other.indexInParent &&
+      this.nullability == other.nullability;
 
   @override
+  // TODO(regis): Print nullability, only if nnbd experiment is enabled?
   String toString() => '$parent::TypeParam/$indexInParent';
 }
 
@@ -811,9 +862,11 @@
   _ClassHandle class_;
   _TypeArgumentsHandle typeArgs;
 
-  _GenericTypeHandle._empty() : super(TypeTag.kGenericType);
+  _GenericTypeHandle._empty(Nullability nullability)
+      : super(TypeTag.kGenericType, nullability);
 
-  _GenericTypeHandle(this.class_, this.typeArgs) : super(TypeTag.kGenericType);
+  _GenericTypeHandle(this.class_, this.typeArgs, Nullability nullability)
+      : super(TypeTag.kGenericType, nullability);
 
   @override
   void writeContents(BufferedWriter writer) {
@@ -836,15 +889,18 @@
   }
 
   @override
-  int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode);
+  int get hashCode => _combineHashes(
+      class_.hashCode, _combineHashes(typeArgs.hashCode, nullability.index));
 
   @override
   bool operator ==(other) =>
       other is _GenericTypeHandle &&
       this.class_ == other.class_ &&
-      this.typeArgs == other.typeArgs;
+      this.typeArgs == other.typeArgs &&
+      this.nullability == other.nullability;
 
   @override
+  // TODO(regis): Print nullability, only if nnbd experiment is enabled?
   String toString() => '$class_ $typeArgs';
 }
 
@@ -853,10 +909,12 @@
   _ClassHandle class_;
   _TypeArgumentsHandle typeArgs;
 
-  _RecursiveGenericTypeHandle._empty() : super(TypeTag.kRecursiveGenericType);
+  _RecursiveGenericTypeHandle._empty(Nullability nullability)
+      : super(TypeTag.kRecursiveGenericType, nullability);
 
-  _RecursiveGenericTypeHandle(this.id, this.class_, this.typeArgs)
-      : super(TypeTag.kRecursiveGenericType);
+  _RecursiveGenericTypeHandle(
+      this.id, this.class_, this.typeArgs, Nullability nullability)
+      : super(TypeTag.kRecursiveGenericType, nullability);
 
   @override
   bool get isCacheable => (id == 0);
@@ -884,24 +942,29 @@
   }
 
   @override
-  int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode);
+  int get hashCode => _combineHashes(
+      class_.hashCode, _combineHashes(typeArgs.hashCode, nullability.index));
 
   @override
   bool operator ==(other) =>
       other is _RecursiveGenericTypeHandle &&
       this.class_ == other.class_ &&
-      this.typeArgs == other.typeArgs;
+      this.typeArgs == other.typeArgs &&
+      this.nullability == other.nullability;
 
   @override
+  // TODO(regis): Print nullability, only if nnbd experiment is enabled?
   String toString() => '(recursive #$id) $class_ $typeArgs';
 }
 
 class _RecursiveTypeRefHandle extends _TypeHandle {
   int id;
 
-  _RecursiveTypeRefHandle._empty() : super(TypeTag.kRecursiveTypeRef);
+  _RecursiveTypeRefHandle._empty(Nullability nullability)
+      : super(TypeTag.kRecursiveTypeRef, nullability);
 
-  _RecursiveTypeRefHandle(this.id) : super(TypeTag.kRecursiveTypeRef);
+  _RecursiveTypeRefHandle(this.id)
+      : super(TypeTag.kRecursiveTypeRef, Nullability.legacy);
 
   @override
   bool get isCacheable => false;
@@ -943,6 +1006,7 @@
       this.type == other.type;
 
   @override
+  // TODO(regis): Print nullability, always or only if nnbd experiment is enabled?
   String toString() => '$type ${name.name}';
 }
 
@@ -958,11 +1022,17 @@
   List<NameAndType> namedParams;
   _TypeHandle returnType;
 
-  _FunctionTypeHandle._empty() : super(TypeTag.kFunctionType);
+  _FunctionTypeHandle._empty(Nullability nullability)
+      : super(TypeTag.kFunctionType, nullability);
 
-  _FunctionTypeHandle(this.typeParams, this.numRequiredParams,
-      this.positionalParams, this.namedParams, this.returnType)
-      : super(TypeTag.kFunctionType) {
+  _FunctionTypeHandle(
+      this.typeParams,
+      this.numRequiredParams,
+      this.positionalParams,
+      this.namedParams,
+      this.returnType,
+      Nullability nullability)
+      : super(TypeTag.kFunctionType, nullability) {
     assert(numRequiredParams <= positionalParams.length + namedParams.length);
     if (numRequiredParams < positionalParams.length) {
       assert(namedParams.isEmpty);
@@ -1079,6 +1149,7 @@
       this.returnType == other.returnType;
 
   @override
+  // TODO(regis): Print nullability, only if nnbd experiment is enabled?
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write('FunctionType');
@@ -1673,12 +1744,14 @@
   List<ObjectHandle> _indexTable;
   _TypeHandle _dynamicType;
   _TypeHandle _voidType;
+  _TypeHandle _neverType;
   CoreTypes coreTypes;
   _NodeVisitor _nodeVisitor;
 
   ObjectTable() {
     _dynamicType = getOrAddObject(new _DynamicTypeHandle());
     _voidType = getOrAddObject(new _VoidTypeHandle());
+    _neverType = getOrAddObject(new _NeverTypeHandle());
     _nodeVisitor = new _NodeVisitor(this);
   }
 
@@ -1877,11 +1950,13 @@
 
   ObjectHandle getOrAddObject(ObjectHandle obj) {
     assert(obj._useCount == 0);
-    ObjectHandle canonical = _canonicalizationCache.putIfAbsent(obj, () {
+    ObjectHandle canonical = _canonicalizationCache[obj];
+    if (canonical == null) {
       assert(_indexTable == null);
       _objects.add(obj);
-      return obj;
-    });
+      _canonicalizationCache[obj] = obj;
+      canonical = obj;
+    }
     ++canonical._useCount;
     return canonical;
   }
@@ -1968,7 +2043,7 @@
 
     writer.writePackedUInt30(_indexTable.length);
     writer.writePackedUInt30(contentsWriter.offset);
-    writer.writeBytes(contentsWriter.takeBytes());
+    writer.appendWriter(contentsWriter);
     for (var offs in offsets) {
       writer.writePackedUInt30(offs);
     }
@@ -2053,6 +2128,9 @@
   ObjectHandle visitVoidType(VoidType node) => objectTable._voidType;
 
   @override
+  ObjectHandle visitNeverType(NeverType node) => objectTable._neverType;
+
+  @override
   ObjectHandle visitBottomType(BottomType node) =>
       objectTable.getHandle(objectTable.coreTypes.nullType);
 
@@ -2060,7 +2138,8 @@
   ObjectHandle visitInterfaceType(InterfaceType node) {
     final classHandle = objectTable.getHandle(node.classNode);
     if (!hasInstantiatorTypeArguments(node.classNode)) {
-      return objectTable.getOrAddObject(new _SimpleTypeHandle(classHandle));
+      return objectTable
+          .getOrAddObject(new _SimpleTypeHandle(classHandle, node.nullability));
     }
 
     // Non-finalized types are not recursive, but finalization of
@@ -2100,8 +2179,9 @@
 
     final result = objectTable.getOrAddObject(isRecursive
         ? new _RecursiveGenericTypeHandle(
-            recursiveId, classHandle, typeArgsHandle)
-        : new _GenericTypeHandle(classHandle, typeArgsHandle));
+            recursiveId, classHandle, typeArgsHandle, node.nullability)
+        : new _GenericTypeHandle(
+            classHandle, typeArgsHandle, node.nullability));
 
     if (isRecursive) {
       _recursiveTypeIds.remove(node);
@@ -2115,7 +2195,14 @@
     final param = node.parameter;
     final handle = _typeParameters[param];
     if (handle != null) {
-      return handle;
+      final typeParameterHandle = handle as _TypeParameterHandle;
+      if (typeParameterHandle.nullability == node.nullability) {
+        return handle;
+      }
+      return objectTable.getOrAddObject(new _TypeParameterHandle(
+          typeParameterHandle.parent,
+          typeParameterHandle.indexInParent,
+          node.nullability));
     }
 
     final parent = param.parent;
@@ -2148,8 +2235,8 @@
     } else {
       throw 'Unexpected parent of TypeParameter: ${parent.runtimeType} $parent';
     }
-    return objectTable
-        .getOrAddObject(new _TypeParameterHandle(parentHandle, indexInParent));
+    return objectTable.getOrAddObject(new _TypeParameterHandle(
+        parentHandle, indexInParent, node.nullability));
   }
 
   @override
@@ -2157,7 +2244,11 @@
     final int numEnclosingTypeParameters = _typeParameters.length;
     for (int i = 0; i < node.typeParameters.length; ++i) {
       _typeParameters[node.typeParameters[i]] = objectTable.getOrAddObject(
-          new _TypeParameterHandle(null, numEnclosingTypeParameters + i));
+          new _TypeParameterHandle(
+              null, numEnclosingTypeParameters + i, Nullability.legacy));
+      // Nullability.legacy is a dummy value, since TypeParameter does not
+      // specify nullability, only the reference to a TypeParameter does, i.e.
+      // TypeParameterType.
     }
 
     final positionalParams = new List<_TypeHandle>();
@@ -2177,7 +2268,8 @@
         node.requiredParameterCount,
         positionalParams,
         namedParams,
-        returnType));
+        returnType,
+        node.nullability));
 
     for (int i = 0; i < node.typeParameters.length; ++i) {
       _typeParameters.remove(node.typeParameters[i]);
diff --git a/pkg/vm/lib/bytecode/options.dart b/pkg/vm/lib/bytecode/options.dart
index b926cfc..1eedd8d 100644
--- a/pkg/vm/lib/bytecode/options.dart
+++ b/pkg/vm/lib/bytecode/options.dart
@@ -48,9 +48,15 @@
       this.keepUnreachableCode = false,
       this.avoidClosureCallInstructions = false,
       this.showBytecodeSizeStatistics = false,
+      bool aot = false,
       this.environmentDefines = const <String, String>{}}) {
     causalAsyncStacks ??=
         environmentDefines['dart.developer.causal_async_stacks'] == 'true';
+    if (aot) {
+      emitSourcePositions = true;
+      emitLocalVarInfo = true;
+      causalAsyncStacks = true;
+    }
   }
 
   void parseCommandLineFlags(List<String> flags) {
diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart
index 5d28c90..9cf138c 100644
--- a/pkg/vm/lib/bytecode/source_positions.dart
+++ b/pkg/vm/lib/bytecode/source_positions.dart
@@ -8,13 +8,14 @@
     show
         BufferedWriter,
         BufferedReader,
+        BytecodeDeclaration,
         PackedUInt30DeltaEncoder,
         PackedUInt30DeltaDecoder,
         SLEB128DeltaEncoder,
         SLEB128DeltaDecoder;
 
 /// Maintains mapping between bytecode instructions and source positions.
-class SourcePositions {
+class SourcePositions extends BytecodeDeclaration {
   // Special value of fileOffset which marks synthetic code without source
   // position.
   static const syntheticCodeMarker = -1;
@@ -40,7 +41,7 @@
 
   void addYieldPoint(int pc, int fileOffset) {
     assert(pc > _lastPc);
-    assert(fileOffset >= 0);
+    assert((fileOffset >= 0) || (fileOffset == syntheticCodeMarker));
     _positions.add(pc);
     _positions.add(yieldPointMarker);
     _positions.add(pc);
@@ -99,7 +100,7 @@
 
 /// Keeps file offsets of line starts. This information is used to
 /// decode source positions to line/column.
-class LineStarts {
+class LineStarts extends BytecodeDeclaration {
   final List<int> lineStarts;
 
   LineStarts(this.lineStarts);
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 2963159..448405e 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -13,6 +13,8 @@
 import 'package:build_integration/file_system/multi_root.dart'
     show MultiRootFileSystem, MultiRootFileSystemEntity;
 
+import 'package:crypto/crypto.dart';
+
 import 'package:front_end/src/api_unstable/vm.dart'
     show
         CompilerContext,
@@ -59,6 +61,8 @@
 import 'transformations/obfuscation_prohibitions_annotator.dart'
     as obfuscationProhibitions;
 import 'transformations/call_site_annotator.dart' as call_site_annotator;
+import 'transformations/unreachable_code_elimination.dart'
+    as unreachable_code_elimination;
 
 /// Declare options consumed by [runCompiler].
 void declareCompilerOptions(ArgParser args) {
@@ -102,14 +106,14 @@
       help:
           'Split resulting kernel file into multiple files (one per package).',
       defaultsTo: false);
-  args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false);
+  args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: null);
   args.addMultiOption('bytecode-options',
       help: 'Specify options for bytecode generation:',
       valueHelp: 'opt1,opt2,...',
       allowed: BytecodeOptions.commandLineFlags.keys,
       allowedHelp: BytecodeOptions.commandLineFlags);
   args.addFlag('drop-ast',
-      help: 'Include only bytecode into the output file', defaultsTo: false);
+      help: 'Include only bytecode into the output file', defaultsTo: true);
   args.addMultiOption('enable-experiment',
       help: 'Comma separated list of experimental features to enable.');
   args.addFlag('help',
@@ -153,7 +157,7 @@
   final bool tfa = options['tfa'];
   final bool linkPlatform = options['link-platform'];
   final bool embedSources = options['embed-sources'];
-  final bool genBytecode = options['gen-bytecode'];
+  final bool genBytecode = options['gen-bytecode'] ?? aot;
   final bool dropAST = options['drop-ast'];
   final bool enableAsserts = options['enable-asserts'];
   final bool useProtobufTreeShaker = options['protobuf-tree-shaker'];
@@ -166,10 +170,11 @@
   }
 
   final BytecodeOptions bytecodeOptions = new BytecodeOptions(
-      enableAsserts: enableAsserts,
-      emitSourceFiles: embedSources,
-      environmentDefines: environmentDefines)
-    ..parseCommandLineFlags(options['bytecode-options']);
+    enableAsserts: enableAsserts,
+    emitSourceFiles: embedSources,
+    environmentDefines: environmentDefines,
+    aot: aot,
+  )..parseCommandLineFlags(options['bytecode-options']);
 
   final target = createFrontEndTarget(targetName);
   if (target == null) {
@@ -216,6 +221,7 @@
       aot: aot,
       useGlobalTypeFlowAnalysis: tfa,
       environmentDefines: environmentDefines,
+      enableAsserts: enableAsserts,
       genBytecode: genBytecode,
       bytecodeOptions: bytecodeOptions,
       dropAST: dropAST && !splitOutputByPackages,
@@ -284,6 +290,7 @@
     {bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
     Map<String, String> environmentDefines,
+    bool enableAsserts: true,
     bool genBytecode: false,
     BytecodeOptions bytecodeOptions,
     bool dropAST: false,
@@ -307,6 +314,7 @@
         component,
         useGlobalTypeFlowAnalysis,
         environmentDefines,
+        enableAsserts,
         useProtobufTreeShaker,
         errorDetector);
   }
@@ -361,6 +369,7 @@
     Component component,
     bool useGlobalTypeFlowAnalysis,
     Map<String, String> environmentDefines,
+    bool enableAsserts,
     bool useProtobufTreeShaker,
     ErrorDetector errorDetector) async {
   if (errorDetector.hasCompilationErrors) return;
@@ -375,6 +384,10 @@
   // when building a platform dill file for VM/JIT case.
   mixin_deduplication.transformComponent(component);
 
+  // Unreachable code elimination transformation should be performed
+  // before type flow analysis so TFA won't take unreachable code into account.
+  unreachable_code_elimination.transformComponent(component, enableAsserts);
+
   if (useGlobalTypeFlowAnalysis) {
     globalTypeFlow.transformComponent(
         compilerOptions.target, coreTypes, component);
@@ -614,6 +627,8 @@
   final packages = new List<String>();
   await runWithFrontEndCompilerContext(source, compilerOptions, component,
       () async {
+    // When loading a kernel file list, flutter_runner and dart_runner expect
+    // 'main' to be last.
     await forEachPackage(component,
         (String package, List<Library> libraries) async {
       packages.add(package);
@@ -638,7 +653,7 @@
       printer.writeComponentFile(partComponent);
 
       await sink.close();
-    });
+    }, mainFirst: false);
   });
 
   if (bytecodeOptions.showBytecodeSizeStatistics) {
@@ -680,32 +695,35 @@
   }
 }
 
-Future<Null> forEachPackage<T>(Component component,
-    T action(String package, List<Library> libraries)) async {
+Future<Null> forEachPackage<T>(
+    Component component, T action(String package, List<Library> libraries),
+    {bool mainFirst}) async {
   sortComponent(component);
 
   final packages = new Map<String, List<Library>>();
+  packages['main'] = new List<Library>(); // Always create 'main'.
   for (Library lib in component.libraries) {
     packages.putIfAbsent(packageFor(lib), () => new List<Library>()).add(lib);
   }
-  if (packages.containsKey(null)) {
-    packages.remove(null);
+  packages.remove(null); // Ignore external libraries.
+
+  final mainLibraries = packages.remove('main');
+  if (mainFirst) {
+    await action('main', mainLibraries);
   }
-  // Make sure main package is last.
-  packages['main'] = packages.remove('main') ?? const <Library>[];
 
+  final mainMethod = component.mainMethod;
+  final problemsAsJson = component.problemsAsJson;
+  component.mainMethod = null;
+  component.problemsAsJson = null;
   for (String package in packages.keys) {
-    final main = component.mainMethod;
-    final problems = component.problemsAsJson;
-    if (package != 'main') {
-      component.mainMethod = null;
-      component.problemsAsJson = null;
-    }
-
     await action(package, packages[package]);
+  }
+  component.mainMethod = mainMethod;
+  component.problemsAsJson = problemsAsJson;
 
-    component.mainMethod = main;
-    component.problemsAsJson = problems;
+  if (!mainFirst) {
+    await action('main', mainLibraries);
   }
 }
 
@@ -731,5 +749,52 @@
   await file.close();
 }
 
+Future<void> createFarManifest(
+    String output, String dataDir, String packageManifestFilename) async {
+  List<String> packages = await File('$output-packages').readAsLines();
+
+  // Make sure the 'main' package is the last (convention with package loader).
+  packages.remove('main');
+  packages.add('main');
+
+  final IOSink packageManifest = File(packageManifestFilename).openWrite();
+
+  final String kernelListFilename = '$packageManifestFilename.dilplist';
+  final IOSink kernelList = File(kernelListFilename).openWrite();
+  for (String package in packages) {
+    final String filenameInPackage = '$package.dilp';
+    final String filenameInBuild = '$output-$package.dilp';
+    packageManifest
+        .write('data/$dataDir/$filenameInPackage=$filenameInBuild\n');
+    kernelList.write('$filenameInPackage\n');
+  }
+  await kernelList.close();
+
+  final String frameworkVersionFilename =
+      '$packageManifestFilename.frameworkversion';
+  final IOSink frameworkVersion = File(frameworkVersionFilename).openWrite();
+  for (String package in [
+    'collection',
+    'flutter',
+    'meta',
+    'typed_data',
+    'vector_math'
+  ]) {
+    Digest digest;
+    if (packages.contains(package)) {
+      final filenameInBuild = '$output-$package.dilp';
+      final bytes = await File(filenameInBuild).readAsBytes();
+      digest = sha256.convert(bytes);
+    }
+    frameworkVersion.write('$package=$digest\n');
+  }
+  await frameworkVersion.close();
+
+  packageManifest.write('data/$dataDir/app.dilplist=$kernelListFilename\n');
+  packageManifest
+      .write('data/$dataDir/app.frameworkversion=$frameworkVersionFilename\n');
+  await packageManifest.close();
+}
+
 // Used by kernel_front_end_test.dart
 main() {}
diff --git a/pkg/vm/lib/metadata/bytecode.dart b/pkg/vm/lib/metadata/bytecode.dart
index 83e4a8e..fc91879 100644
--- a/pkg/vm/lib/metadata/bytecode.dart
+++ b/pkg/vm/lib/metadata/bytecode.dart
@@ -53,10 +53,9 @@
         bytecodeComponent.version,
         bytecodeComponent.stringTable,
         bytecodeComponent.objectTable,
-        linkWriter,
-        baseOffset: sink.getBufferOffset());
+        linkWriter);
     metadata.write(writer);
-    sink.writeBytes(writer.takeBytes());
+    writer.writeContentsToBinarySink(sink);
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
index 7da3194..5c35c72 100644
--- a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -20,7 +20,6 @@
     Component component, Map<String, String> environment, Target target,
     {@required bool collectInfo}) {
   final coreTypes = new CoreTypes(component);
-  component.computeCanonicalNames();
 
   TransformationInfo info = collectInfo ? TransformationInfo() : null;
 
@@ -62,6 +61,9 @@
   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 =
@@ -71,8 +73,8 @@
 
   component.accept(collector);
 
-  _UnusedFieldMetadataPruner(
-          biClass, addMethod, collector.dynamicSelectors, coreTypes, info)
+  _UnusedFieldMetadataPruner(tagNumberClass, biClass, addMethod,
+          collector.dynamicSelectors, coreTypes, info)
       .removeMetadataForUnusedFields(
     collector.gmSubclasses,
     collector.gmSubclassesInvokedMethods,
@@ -85,6 +87,8 @@
 
 /// 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:
@@ -93,26 +97,34 @@
   // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
   static final fieldAddingMethods = Set<String>.from(const <String>[
     'a',
-    'm',
-    'pp',
-    'pc',
-    'e',
-    'pc',
+    '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.builderInfoClass, this.addMethod,
-      Set<Selector> dynamicSelectors, this.coreTypes, this.info) {
+  _UnusedFieldMetadataPruner(this.tagNumberClass, this.builderInfoClass,
+      this.addMethod, Set<Selector> dynamicSelectors, this.coreTypes, this.info)
+      : tagNumberField = tagNumberClass.fields
+            .firstWhere((f) => f.name.name == 'tagNumber')
+            .reference {
     dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.name));
   }
 
@@ -140,30 +152,58 @@
     names.clear();
     names.addAll(selectors.map((sel) => sel.target.name));
     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.name;
+            if (dynamicNames.contains(name) || names.contains(name)) {
+              usedTagNumbers.add(
+                  (constant.fieldValues[tagNumberField] as IntConstant).value);
+            }
+          }
+        }
+      }
+    }
+  }
+
   @override
   visitLet(Let 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 a let, where the
+    // initializer 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.
     final initializer = node.variable.initializer;
     if (initializer is MethodInvocation &&
         initializer.interfaceTarget?.enclosingClass == builderInfoClass &&
         fieldAddingMethods.contains(initializer.name.name)) {
-      final fieldName =
-          (initializer.arguments.positional[1] as StringLiteral).value;
-      final ucase = fieldName[0].toUpperCase() + fieldName.substring(1);
-      // The name of the related `clear` method.
-      final clearName = 'clear${ucase}';
-      // The name of the related `has` method.
-      final hasName = 'has${ucase}';
-
-      bool nameIsUsed(String name) =>
-          dynamicNames.contains(name) || names.contains(name);
-
-      if (!(nameIsUsed(fieldName) ||
-          nameIsUsed(clearName) ||
-          nameIsUsed(hasName))) {
+      final tagNumber =
+          (initializer.arguments.positional[0] as IntLiteral).value;
+      if (!usedTagNumbers.contains(tagNumber)) {
         if (info != null) {
+          final fieldName =
+              (initializer.arguments.positional[1] as StringLiteral).value;
           info.removedMessageFields.add("${visitedClass.name}.$fieldName");
         }
 
diff --git a/pkg/vm/lib/transformations/unreachable_code_elimination.dart b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
new file mode 100644
index 0000000..6770707
--- /dev/null
+++ b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
@@ -0,0 +1,171 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+
+/// Simple unreachable code elimination: removes asserts and if statements
+/// with constant conditions. Does a very limited constant folding of
+/// logical expressions.
+Component transformComponent(Component component, bool enableAsserts) {
+  new SimpleUnreachableCodeElimination(enableAsserts).visitComponent(component);
+  return component;
+}
+
+class SimpleUnreachableCodeElimination extends Transformer {
+  final bool enableAsserts;
+
+  SimpleUnreachableCodeElimination(this.enableAsserts);
+
+  bool _isBoolConstant(Expression node) =>
+      node is BoolLiteral ||
+      (node is ConstantExpression && node.constant is BoolConstant);
+
+  bool _getBoolConstantValue(Expression node) {
+    if (node is BoolLiteral) {
+      return node.value;
+    }
+    if (node is ConstantExpression) {
+      final constant = node.constant;
+      if (constant is BoolConstant) {
+        return constant.value;
+      }
+    }
+    throw 'Expected bool constant: $node';
+  }
+
+  Expression _createBoolLiteral(bool value, int fileOffset) =>
+      new BoolLiteral(value)..fileOffset = fileOffset;
+
+  Statement _makeEmptyBlockIfNull(Statement node) =>
+      node == null ? Block(<Statement>[]) : node;
+
+  @override
+  TreeNode visitIfStatement(IfStatement node) {
+    node.transformChildren(this);
+    final condition = node.condition;
+    if (_isBoolConstant(condition)) {
+      final value = _getBoolConstantValue(condition);
+      return value ? node.then : node.otherwise;
+    }
+    node.then = _makeEmptyBlockIfNull(node.then);
+    return node;
+  }
+
+  @override
+  visitConditionalExpression(ConditionalExpression node) {
+    node.transformChildren(this);
+    final condition = node.condition;
+    if (_isBoolConstant(condition)) {
+      final value = _getBoolConstantValue(condition);
+      return value ? node.then : node.otherwise;
+    }
+    return node;
+  }
+
+  @override
+  TreeNode visitNot(Not node) {
+    node.transformChildren(this);
+    final operand = node.operand;
+    if (_isBoolConstant(operand)) {
+      return _createBoolLiteral(
+          !_getBoolConstantValue(operand), node.fileOffset);
+    }
+    return node;
+  }
+
+  @override
+  TreeNode visitLogicalExpression(LogicalExpression node) {
+    node.transformChildren(this);
+    final left = node.left;
+    final right = node.right;
+    final operator = node.operator;
+    if (_isBoolConstant(left)) {
+      final leftValue = _getBoolConstantValue(left);
+      if (_isBoolConstant(right)) {
+        final rightValue = _getBoolConstantValue(right);
+        if (operator == '||') {
+          return _createBoolLiteral(leftValue || rightValue, node.fileOffset);
+        } else if (operator == '&&') {
+          return _createBoolLiteral(leftValue && rightValue, node.fileOffset);
+        } else {
+          throw 'Unexpected LogicalExpression operator ${operator}: $node';
+        }
+      } else {
+        if (leftValue && operator == '||') {
+          return _createBoolLiteral(true, node.fileOffset);
+        } else if (!leftValue && operator == '&&') {
+          return _createBoolLiteral(false, node.fileOffset);
+        }
+      }
+    }
+    return node;
+  }
+
+  @override
+  visitStaticGet(StaticGet node) {
+    node.transformChildren(this);
+    final target = node.target;
+    if (target is Field && target.isConst) {
+      throw 'StaticGet from const field $target should be evaluated by front-end: $node';
+    }
+    return node;
+  }
+
+  @override
+  TreeNode visitAssertStatement(AssertStatement node) {
+    if (!enableAsserts) {
+      return null;
+    }
+    return super.visitAssertStatement(node);
+  }
+
+  @override
+  TreeNode visitAssertBlock(AssertBlock node) {
+    if (!enableAsserts) {
+      return null;
+    }
+    return super.visitAssertBlock(node);
+  }
+
+  @override
+  TreeNode visitAssertInitializer(AssertInitializer node) {
+    if (!enableAsserts) {
+      return null;
+    }
+    return super.visitAssertInitializer(node);
+  }
+
+  // Make sure we're not generating `null` bodies.
+  // Try/catch, try/finally and switch/case statements
+  // always have a Block in a body, so there is no
+  // need to guard against null.
+
+  @override
+  TreeNode visitWhileStatement(WhileStatement node) {
+    node.transformChildren(this);
+    node.body = _makeEmptyBlockIfNull(node.body);
+    return node;
+  }
+
+  @override
+  TreeNode visitDoStatement(DoStatement node) {
+    node.transformChildren(this);
+    node.body = _makeEmptyBlockIfNull(node.body);
+    return node;
+  }
+
+  @override
+  TreeNode visitForStatement(ForStatement node) {
+    node.transformChildren(this);
+    node.body = _makeEmptyBlockIfNull(node.body);
+    return node;
+  }
+
+  @override
+  TreeNode visitForInStatement(ForInStatement node) {
+    node.transformChildren(this);
+    node.body = _makeEmptyBlockIfNull(node.body);
+    return node;
+  }
+}
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index da4e6d8..aa0001e 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -33,15 +33,18 @@
 }
 
 Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
-    {Target target, bool enableSuperMixins: false}) async {
+    {Target target,
+    bool enableSuperMixins = false,
+    Map<String, String> environmentDefines}) async {
   final platformKernel =
       computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
   target ??= new TestingVmTarget(new TargetFlags())
     ..enableSuperMixins = enableSuperMixins;
+  environmentDefines ??= <String, String>{};
   final options = new CompilerOptions()
     ..target = target
     ..linkedDependencies = <Uri>[platformKernel]
-    ..environmentDefines = <String, String>{}
+    ..environmentDefines = environmentDefines
     ..onDiagnostic = (DiagnosticMessage message) {
       fail("Compilation error: ${message.plainTextFormatted.join('\n')}");
     };
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 7734f54..2b2397a 100644
--- a/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
+++ b/pkg/vm/test/transformations/protobuf_aware_treeshaker/treeshaker_test.dart
@@ -36,7 +36,8 @@
 
   for (Class messageClass in messageClasses) {
     expect(messageClass.enclosingLibrary.classes.contains(messageClass),
-        messageClass.name.endsWith('Keep'));
+        messageClass.name.endsWith('Keep'),
+        reason: '$messageClass');
   }
 
   final systemTempDir = Directory.systemTemp;
@@ -50,8 +51,8 @@
     printer.writeComponentFile(component);
     await sink.close();
 
-    ProcessResult result =
-        Process.runSync(Platform.resolvedExecutable, [file.path]);
+    final result = Process.runSync(
+        Platform.resolvedExecutable, ['--enable-asserts', file.path]);
     expect(result.exitCode, 0, reason: '${result.stderr}\n${result.stdout}');
   } finally {
     if (file.existsSync()) {
diff --git a/pkg/vm/test/transformations/unreachable_code_elimination_test.dart b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
new file mode 100644
index 0000000..10db062
--- /dev/null
+++ b/pkg/vm/test/transformations/unreachable_code_elimination_test.dart
@@ -0,0 +1,47 @@
+// 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:io';
+
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:test/test.dart';
+import 'package:vm/transformations/unreachable_code_elimination.dart'
+    show transformComponent;
+
+import '../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../..').toFilePath();
+
+runTestCase(Uri source) async {
+  final target = new TestingVmTarget(new TargetFlags());
+  Component component = await compileTestCaseToKernelProgram(source,
+      target: target,
+      environmentDefines: {
+        'test.define.isTrue': 'true',
+        'test.define.isFalse': 'false'
+      });
+
+  component = transformComponent(component, /* enableAsserts = */ false);
+
+  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+
+  compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+  group('unreachable-code-elimination', () {
+    final testCasesDir = new Directory(
+        pkgVmDir + '/testcases/transformations/unreachable_code_elimination');
+
+    for (var entry in testCasesDir
+        .listSync(recursive: true, followLinks: false)
+        .reversed) {
+      if (entry.path.endsWith(".dart")) {
+        test(entry.path, () => runTestCase(entry.uri));
+      }
+    }
+  });
+}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index cce1c2d..b186fa7 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -23,11 +23,8 @@
   PushNull
   StoreFieldTOS        CP#22
   Push                 r2
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
-  Push                 r2
   PushConstant         CP#0
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#24
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -58,20 +55,17 @@
   [21] = Reserved
   [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [23] = Reserved
-  [24] = EmptyTypeArguments
-  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [26] = Reserved
-  [27] = InstanceField dart:core::_Closure::_function (field)
-  [28] = Reserved
-  [29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [30] = Reserved
-  [31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [32] = Reserved
-  [33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [34] = Reserved
-  [35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [36] = Reserved
-  [37] = EndClosureFunctionScope
+  [24] = InstanceField dart:core::_Closure::_function (field)
+  [25] = Reserved
+  [26] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
+  [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [29] = Reserved
+  [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [31] = Reserved
+  [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = EndClosureFunctionScope
 }
 Closure #lib::asyncInFieldInitializer (field)::'<anonymous closure>' async (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
 ClosureCode {
@@ -103,27 +97,12 @@
   DirectCall           CP#8, 1
   Drop1
   StoreContextVar      0, 1
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 2
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      0, 3
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 4
-  Push                 r0
   PushInt              0
   StoreContextVar      0, 5
   Push                 r0
-  PushNull
-  StoreContextVar      0, 6
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 7
-  Push                 r0
   AllocateClosure      CP#10
   StoreLocal           r2
   Push                 r2
@@ -133,11 +112,8 @@
   PushNull
   StoreFieldTOS        CP#22
   Push                 r2
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
-  Push                 r2
   PushConstant         CP#10
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#24
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -147,22 +123,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           CP#29, 1
+  DirectCall           CP#26, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           CP#31, 1
+  DirectCall           CP#28, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          CP#33, 2
+  DynamicCall          CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        CP#35, 1
+  InterfaceCall        CP#32, 1
   ReturnTOS
 }
 
@@ -272,9 +248,6 @@
   DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 0
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 1
   PushNull
   PopLocal             r3
   PushNull
@@ -284,9 +257,6 @@
   Push                 r0
   PushInt              0
   StoreContextVar      0, 2
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 3
   AllocateClosure      CP#4
   StoreLocal           r2
   Push                 r2
@@ -296,11 +266,8 @@
   PushNull
   StoreFieldTOS        CP#16
   Push                 r2
-  PushConstant         CP#18
-  StoreFieldTOS        CP#19
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#21
+  StoreFieldTOS        CP#18
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
@@ -308,19 +275,19 @@
   PushNull
   PopLocal             r3
   Push                 r6
-  DirectCall           CP#23, 1
+  DirectCall           CP#20, 1
   PopLocal             r4
   Push                 r6
-  DirectCall           CP#25, 1
+  DirectCall           CP#22, 1
   PopLocal             r5
   Push                 r0
   LoadContextVar       0, 0
   Push                 r6
-  DynamicCall          CP#27, 2
+  DynamicCall          CP#24, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  InterfaceCall        CP#29, 1
+  InterfaceCall        CP#26, 1
   ReturnTOS
 }
 ConstantPool {
@@ -342,19 +309,16 @@
   [15] = Reserved
   [16] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [17] = Reserved
-  [18] = EmptyTypeArguments
-  [19] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [20] = Reserved
-  [21] = InstanceField dart:core::_Closure::_function (field)
-  [22] = Reserved
-  [23] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [24] = Reserved
-  [25] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [26] = Reserved
-  [27] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [28] = Reserved
-  [29] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [30] = Reserved
+  [18] = InstanceField dart:core::_Closure::_function (field)
+  [19] = Reserved
+  [20] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [21] = Reserved
+  [22] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [23] = Reserved
+  [24] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [25] = Reserved
+  [26] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
 }
 Closure #lib::foo::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureCode {
@@ -438,30 +402,12 @@
   DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 2
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 3
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      0, 4
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 5
-  Push                 r0
   PushInt              0
   StoreContextVar      0, 6
   Push                 r0
-  PushNull
-  StoreContextVar      0, 7
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 8
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 9
-  Push                 r0
   AllocateClosure      CP#4
   StoreLocal           r2
   Push                 r2
@@ -471,11 +417,8 @@
   PushNull
   StoreFieldTOS        CP#20
   Push                 r2
-  PushConstant         CP#22
-  StoreFieldTOS        CP#23
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#25
+  StoreFieldTOS        CP#22
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
@@ -485,22 +428,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           CP#27, 1
+  DirectCall           CP#24, 1
   StoreContextVar      0, 4
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           CP#29, 1
+  DirectCall           CP#26, 1
   StoreContextVar      0, 5
   Push                 r0
   LoadContextVar       0, 2
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          CP#31, 2
+  DynamicCall          CP#28, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  InterfaceCall        CP#33, 1
+  InterfaceCall        CP#30, 1
   ReturnTOS
 }
 ConstantPool {
@@ -526,19 +469,16 @@
   [19] = Reserved
   [20] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [21] = Reserved
-  [22] = EmptyTypeArguments
-  [23] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [24] = Reserved
-  [25] = InstanceField dart:core::_Closure::_function (field)
-  [26] = Reserved
-  [27] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [28] = Reserved
-  [29] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [30] = Reserved
-  [31] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [32] = Reserved
-  [33] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [34] = Reserved
+  [22] = InstanceField dart:core::_Closure::_function (field)
+  [23] = Reserved
+  [24] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [25] = Reserved
+  [26] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
+  [28] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [29] = Reserved
+  [30] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
 }
 Closure #lib::simpleAsyncAwait::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureCode {
@@ -686,33 +626,12 @@
   DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 1
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 2
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      0, 3
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 4
-  Push                 r0
   PushInt              0
   StoreContextVar      0, 5
   Push                 r0
-  PushNull
-  StoreContextVar      0, 6
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 7
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 8
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 9
-  Push                 r0
   AllocateClosure      CP#4
   StoreLocal           r2
   Push                 r2
@@ -722,11 +641,8 @@
   PushNull
   StoreFieldTOS        CP#28
   Push                 r2
-  PushConstant         CP#30
-  StoreFieldTOS        CP#31
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#33
+  StoreFieldTOS        CP#30
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
@@ -736,22 +652,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           CP#35, 1
+  DirectCall           CP#32, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  DirectCall           CP#37, 1
+  DirectCall           CP#34, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          CP#39, 2
+  DynamicCall          CP#36, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        CP#41, 1
+  InterfaceCall        CP#38, 1
   ReturnTOS
 }
 ConstantPool {
@@ -785,19 +701,16 @@
   [27] = Reserved
   [28] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [29] = Reserved
-  [30] = EmptyTypeArguments
-  [31] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [32] = Reserved
-  [33] = InstanceField dart:core::_Closure::_function (field)
-  [34] = Reserved
-  [35] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [36] = Reserved
-  [37] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [38] = Reserved
-  [39] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [40] = Reserved
-  [41] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [42] = Reserved
+  [30] = InstanceField dart:core::_Closure::_function (field)
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [35] = Reserved
+  [36] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [37] = Reserved
+  [38] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [39] = Reserved
 }
 Closure #lib::loops::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureCode {
@@ -1067,48 +980,12 @@
   DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 3
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 4
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      0, 5
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 6
-  Push                 r0
   PushInt              0
   StoreContextVar      0, 7
   Push                 r0
-  PushNull
-  StoreContextVar      0, 8
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 9
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 10
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 11
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 12
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 13
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 14
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 15
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 16
-  Push                 r0
   AllocateClosure      CP#4
   StoreLocal           r2
   Push                 r2
@@ -1118,11 +995,8 @@
   PushNull
   StoreFieldTOS        CP#26
   Push                 r2
-  PushConstant         CP#28
-  StoreFieldTOS        CP#29
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#31
+  StoreFieldTOS        CP#28
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
@@ -1132,22 +1006,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       0, 17
-  DirectCall           CP#33, 1
+  DirectCall           CP#30, 1
   StoreContextVar      0, 5
   Push                 r0
   Push                 r0
   LoadContextVar       0, 17
-  DirectCall           CP#35, 1
+  DirectCall           CP#32, 1
   StoreContextVar      0, 6
   Push                 r0
   LoadContextVar       0, 3
   Push                 r0
   LoadContextVar       0, 17
-  DynamicCall          CP#37, 2
+  DynamicCall          CP#34, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        CP#39, 1
+  InterfaceCall        CP#36, 1
   ReturnTOS
 }
 ConstantPool {
@@ -1179,19 +1053,16 @@
   [25] = Reserved
   [26] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [27] = Reserved
-  [28] = EmptyTypeArguments
-  [29] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [30] = Reserved
-  [31] = InstanceField dart:core::_Closure::_function (field)
-  [32] = Reserved
-  [33] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [34] = Reserved
-  [35] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [36] = Reserved
-  [37] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [38] = Reserved
-  [39] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [40] = Reserved
+  [28] = InstanceField dart:core::_Closure::_function (field)
+  [29] = Reserved
+  [30] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [35] = Reserved
+  [36] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [37] = Reserved
 }
 Closure #lib::tryCatchRethrow::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureCode {
@@ -1637,11 +1508,8 @@
   PushNull
   StoreFieldTOS        CP#22
   Push                 r3
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
-  Push                 r3
   PushConstant         CP#0
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#24
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1674,20 +1542,17 @@
   [21] = Reserved
   [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [23] = Reserved
-  [24] = EmptyTypeArguments
-  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [26] = Reserved
-  [27] = InstanceField dart:core::_Closure::_function (field)
-  [28] = Reserved
-  [29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [30] = Reserved
-  [31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [32] = Reserved
-  [33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [34] = Reserved
-  [35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [36] = Reserved
-  [37] = EndClosureFunctionScope
+  [24] = InstanceField dart:core::_Closure::_function (field)
+  [25] = Reserved
+  [26] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
+  [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [29] = Reserved
+  [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [31] = Reserved
+  [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = EndClosureFunctionScope
 }
 Closure #lib::closure::'nested' async () -> dart:async::Future < dart:core::int >
 ClosureCode {
@@ -1711,30 +1576,12 @@
   DirectCall           CP#5, 1
   Drop1
   StoreContextVar      1, 0
-  Push                 r0
-  PushNull
-  StoreContextVar      1, 1
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      1, 2
-  Push                 r0
-  PushNull
-  StoreContextVar      1, 3
-  Push                 r0
   PushInt              0
   StoreContextVar      1, 4
   Push                 r0
-  PushNull
-  StoreContextVar      1, 5
-  Push                 r0
-  PushNull
-  StoreContextVar      1, 6
-  Push                 r0
-  PushNull
-  StoreContextVar      1, 7
-  Push                 r0
   AllocateClosure      CP#7
   StoreLocal           r2
   Push                 r2
@@ -1744,11 +1591,8 @@
   PushNull
   StoreFieldTOS        CP#22
   Push                 r2
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
-  Push                 r2
   PushConstant         CP#7
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#24
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1758,22 +1602,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  DirectCall           CP#29, 1
+  DirectCall           CP#26, 1
   StoreContextVar      1, 2
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  DirectCall           CP#31, 1
+  DirectCall           CP#28, 1
   StoreContextVar      1, 3
   Push                 r0
   LoadContextVar       1, 0
   Push                 r0
   LoadContextVar       1, 8
-  DynamicCall          CP#33, 2
+  DynamicCall          CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       1, 0
-  InterfaceCall        CP#35, 1
+  InterfaceCall        CP#32, 1
   ReturnTOS
 }
 
@@ -1956,27 +1800,12 @@
   DirectCall           CP#2, 1
   Drop1
   StoreContextVar      0, 1
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 2
   PushNull
   PopLocal             r3
   Push                 r0
-  PushNull
-  StoreContextVar      0, 3
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 4
-  Push                 r0
   PushInt              0
   StoreContextVar      0, 5
   Push                 r0
-  PushNull
-  StoreContextVar      0, 6
-  Push                 r0
-  PushNull
-  StoreContextVar      0, 7
-  Push                 r0
   AllocateClosure      CP#4
   StoreLocal           r2
   Push                 r2
@@ -1986,11 +1815,8 @@
   PushNull
   StoreFieldTOS        CP#22
   Push                 r2
-  PushConstant         CP#24
-  StoreFieldTOS        CP#25
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#27
+  StoreFieldTOS        CP#24
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
@@ -2000,22 +1826,22 @@
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           CP#29, 1
+  DirectCall           CP#26, 1
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  DirectCall           CP#31, 1
+  DirectCall           CP#28, 1
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          CP#33, 2
+  DynamicCall          CP#30, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        CP#35, 1
+  InterfaceCall        CP#32, 1
   ReturnTOS
 }
 ConstantPool {
@@ -2043,19 +1869,16 @@
   [21] = Reserved
   [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [23] = Reserved
-  [24] = EmptyTypeArguments
-  [25] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [26] = Reserved
-  [27] = InstanceField dart:core::_Closure::_function (field)
-  [28] = Reserved
-  [29] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [30] = Reserved
-  [31] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
-  [32] = Reserved
-  [33] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
-  [34] = Reserved
-  [35] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
-  [36] = Reserved
+  [24] = InstanceField dart:core::_Closure::_function (field)
+  [25] = Reserved
+  [26] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
+  [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [29] = Reserved
+  [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+  [31] = Reserved
+  [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
 }
 Closure #lib::testAssert::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureCode {
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 52e029f..1297978 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -31,11 +31,8 @@
   PushNull
   StoreFieldTOS        CP#9
   Push                 r3
-  PushConstant         CP#11
-  StoreFieldTOS        CP#12
-  Push                 r3
   PushConstant         CP#0
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#11
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -44,7 +41,7 @@
   StoreLocal           r3
   PushInt              3
   Push                 r3
-  UncheckedClosureCall CP#16, 2
+  UncheckedClosureCall CP#13, 2
   Drop1
   Push                 r0
   LoadContextVar       0, 0
@@ -62,12 +59,9 @@
   [8] = Reserved
   [9] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [10] = Reserved
-  [11] = EmptyTypeArguments
-  [12] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [13] = Reserved
-  [14] = InstanceField dart:core::_Closure::_function (field)
-  [15] = Reserved
-  [16] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [11] = InstanceField dart:core::_Closure::_function (field)
+  [12] = Reserved
+  [13] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
 }
 Closure #lib::simpleClosure::'<anonymous closure>' (dart:core::int y) -> dart:core::Null
 ClosureCode {
@@ -753,9 +747,6 @@
   Push                 r0
   StoreFieldTOS        CP#6
   Push                 r4
-  PushConstant         CP#5
-  StoreFieldTOS        CP#3
-  Push                 r4
   PushConstant         CP#11
   StoreFieldTOS        CP#32
   Push                 r4
@@ -908,11 +899,8 @@
   PushNull
   StoreFieldTOS        CP#12
   Push                 r4
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
-  Push                 r4
   PushConstant         CP#0
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#14
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#1
@@ -921,29 +909,29 @@
   StoreLocal           r4
   PushInt              10
   Push                 r4
-  UncheckedClosureCall CP#23, 2
+  UncheckedClosureCall CP#20, 2
   Drop1
   Push                 r3
   StoreLocal           r4
   PushInt              11
   Push                 r4
-  UncheckedClosureCall CP#23, 2
+  UncheckedClosureCall CP#20, 2
   Drop1
   Push                 r2
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   Drop1
   Push                 r0
   PushInt              42
   StoreContextVar      0, 3
-  AllocateClosure      CP#24
+  AllocateClosure      CP#21
   StoreLocal           r3
   Push                 r3
   PushNull
@@ -952,11 +940,8 @@
   PushNull
   StoreFieldTOS        CP#12
   Push                 r3
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
-  Push                 r3
-  PushConstant         CP#24
-  StoreFieldTOS        CP#17
+  PushConstant         CP#21
+  StoreFieldTOS        CP#14
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -964,7 +949,7 @@
   Push                 r2
   StoreLocal           r3
   Push                 r3
-  UncheckedClosureCall CP#19, 1
+  UncheckedClosureCall CP#16, 1
   Drop1
   PushNull
   ReturnTOS
@@ -984,20 +969,17 @@
   [11] = Reserved
   [12] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [13] = Reserved
-  [14] = EmptyTypeArguments
-  [15] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [16] = Reserved
-  [17] = InstanceField dart:core::_Closure::_function (field)
+  [14] = InstanceField dart:core::_Closure::_function (field)
+  [15] = Reserved
+  [16] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [17] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
   [18] = Reserved
-  [19] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
-  [20] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
-  [21] = Reserved
-  [22] = EndClosureFunctionScope
-  [23] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
-  [24] = ClosureFunction 2
-  [25] = InterfaceCall '#lib::B::set:foo', ArgDesc num-args 2, num-type-args 0, names []
-  [26] = Reserved
-  [27] = EndClosureFunctionScope
+  [19] = EndClosureFunctionScope
+  [20] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [21] = ClosureFunction 2
+  [22] = InterfaceCall '#lib::B::set:foo', ArgDesc num-args 2, num-type-args 0, names []
+  [23] = Reserved
+  [24] = EndClosureFunctionScope
 }
 Closure #lib::B::topLevel::'<anonymous closure>' (dart:core::int y) -> dart:core::Null
 ClosureCode {
@@ -1049,11 +1031,8 @@
   PushNull
   StoreFieldTOS        CP#12
   Push                 r2
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
-  Push                 r2
   PushConstant         CP#6
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#14
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1061,11 +1040,11 @@
   Push                 r3
   StoreLocal           r2
   Push                 r2
-  UncheckedClosureCall CP#19, 1
+  UncheckedClosureCall CP#16, 1
   Drop1
   Push                 r0
   LoadContextVar       1, 1
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   Drop1
 L2:
   PushNull
@@ -1111,7 +1090,7 @@
   LoadContextVar       0, 0
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        CP#25, 2
+  InterfaceCall        CP#22, 2
   Drop1
   PushNull
   ReturnTOS
@@ -1186,18 +1165,15 @@
   PushNull
   StoreFieldTOS        CP#10
   Push                 r3
-  PushConstant         CP#12
-  StoreFieldTOS        CP#13
-  Push                 r3
   PushConstant         CP#4
-  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#12
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InstantiatedInterfaceCall CP#17, 2
+  InstantiatedInterfaceCall CP#14, 2
   Drop1
   Push                 r4
-  AllocateClosure      CP#20
+  AllocateClosure      CP#17
   StoreLocal           r3
   Push                 r3
   PushNull
@@ -1206,15 +1182,12 @@
   PushNull
   StoreFieldTOS        CP#10
   Push                 r3
-  PushConstant         CP#12
-  StoreFieldTOS        CP#13
-  Push                 r3
-  PushConstant         CP#20
-  StoreFieldTOS        CP#15
+  PushConstant         CP#17
+  StoreFieldTOS        CP#12
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#5
-  InstantiatedInterfaceCall CP#17, 2
+  InstantiatedInterfaceCall CP#14, 2
   Drop1
   Push                 r0
   CloneContext         1, 1
@@ -1252,19 +1225,16 @@
   [9] = Reserved
   [10] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [11] = Reserved
-  [12] = EmptyTypeArguments
-  [13] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [14] = Reserved
-  [15] = InstanceField dart:core::_Closure::_function (field)
+  [12] = InstanceField dart:core::_Closure::_function (field)
+  [13] = Reserved
+  [14] = InstantiatedInterfaceCall 'dart:core::List::add', ArgDesc num-args 2, num-type-args 0, names [], receiver dart:core::List < dart:core::Function >
+  [15] = Reserved
   [16] = Reserved
-  [17] = InstantiatedInterfaceCall 'dart:core::List::add', ArgDesc num-args 2, num-type-args 0, names [], receiver dart:core::List < dart:core::Function >
-  [18] = Reserved
-  [19] = Reserved
-  [20] = ClosureFunction 1
-  [21] = Type dart:core::int
-  [22] = ObjectRef 'ii'
-  [23] = SubtypeTestCache
-  [24] = EndClosureFunctionScope
+  [17] = ClosureFunction 1
+  [18] = Type dart:core::int
+  [19] = ObjectRef 'ii'
+  [20] = SubtypeTestCache
+  [21] = EndClosureFunctionScope
 }
 Closure #lib::C::testForLoop::'<anonymous closure>' () -> dart:core::int
 ClosureCode {
@@ -1291,11 +1261,11 @@
   CheckStack           0
   JumpIfUnchecked      L1
   Push                 FP[-5]
-  PushConstant         CP#21
+  PushConstant         CP#18
   PushNull
   PushNull
-  PushConstant         CP#22
-  AssertAssignable     1, CP#23
+  PushConstant         CP#19
+  AssertAssignable     1, CP#20
   Drop1
 L1:
   Push                 r0
@@ -1340,11 +1310,8 @@
   PushNull
   StoreFieldTOS        CP#12
   Push                 r4
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
-  Push                 r4
   PushConstant         CP#6
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#14
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#7
@@ -1352,11 +1319,11 @@
   Push                 r3
   StoreLocal           r4
   Push                 r4
-  UncheckedClosureCall CP#19, 1
+  UncheckedClosureCall CP#16, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   Drop1
   Push                 r0
   LoadContextParent
@@ -1381,14 +1348,11 @@
   [11] = Reserved
   [12] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [13] = Reserved
-  [14] = EmptyTypeArguments
-  [15] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [16] = Reserved
-  [17] = InstanceField dart:core::_Closure::_function (field)
+  [14] = InstanceField dart:core::_Closure::_function (field)
+  [15] = Reserved
+  [16] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [17] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
   [18] = Reserved
-  [19] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
-  [20] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
-  [21] = Reserved
 }
 Closure #lib::C::testForInLoop::'<anonymous closure>' () -> dart:core::Null
 ClosureCode {
@@ -1463,11 +1427,8 @@
   PushNull
   StoreFieldTOS        CP#10
   Push                 r2
-  PushConstant         CP#12
-  StoreFieldTOS        CP#13
-  Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#12
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#5
@@ -1487,11 +1448,8 @@
   [9] = Reserved
   [10] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [11] = Reserved
-  [12] = EmptyTypeArguments
-  [13] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [14] = Reserved
-  [15] = InstanceField dart:core::_Closure::_function (field)
-  [16] = Reserved
+  [12] = InstanceField dart:core::_Closure::_function (field)
+  [13] = Reserved
 }
 Closure #lib::D::foo::'<anonymous closure>' () -> #lib::D::TypeParam/0
 ClosureCode {
@@ -1528,11 +1486,8 @@
   PushNull
   StoreFieldTOS        CP#8
   Push                 r2
-  PushConstant         CP#10
-  StoreFieldTOS        CP#11
-  Push                 r2
   PushConstant         CP#0
-  StoreFieldTOS        CP#13
+  StoreFieldTOS        CP#10
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1549,13 +1504,10 @@
   [7] = Reserved
   [8] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [9] = Reserved
-  [10] = EmptyTypeArguments
-  [11] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [12] = Reserved
-  [13] = InstanceField dart:core::_Closure::_function (field)
-  [14] = Reserved
-  [15] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
-  [16] = EndClosureFunctionScope
+  [10] = InstanceField dart:core::_Closure::_function (field)
+  [11] = Reserved
+  [12] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [13] = EndClosureFunctionScope
 }
 Closure #lib::D::bar::'<anonymous closure>' () -> dart:core::Null
 ClosureCode {
@@ -1575,11 +1527,8 @@
   PushNull
   StoreFieldTOS        CP#8
   Push                 r3
-  PushConstant         CP#10
-  StoreFieldTOS        CP#11
-  Push                 r3
   PushConstant         CP#3
-  StoreFieldTOS        CP#13
+  StoreFieldTOS        CP#10
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1587,7 +1536,7 @@
   Push                 r2
   StoreLocal           r3
   Push                 r3
-  UncheckedClosureCall CP#15, 1
+  UncheckedClosureCall CP#12, 1
   Drop1
   PushNull
   ReturnTOS
@@ -1662,7 +1611,7 @@
   InterfaceCall        CP#2, 1
   PopLocal             r2
   Push                 r0
-  CheckReceiverForNull CP#4
+  NullCheck            CP#4
   InterfaceCall        CP#5, 1
   Push                 r1
   Push                 r2
@@ -1699,7 +1648,7 @@
   InterfaceCall        CP#3, 1
   PopLocal             r2
   Push                 r0
-  CheckReceiverForNull CP#5
+  NullCheck            CP#5
   InterfaceCall        CP#6, 1
   Push                 r1
   Push                 r2
@@ -1738,7 +1687,7 @@
   InterfaceCall        CP#5, 1
   PopLocal             r2
   Push                 r0
-  CheckReceiverForNull CP#7
+  NullCheck            CP#7
   InterfaceCall        CP#8, 1
   Push                 r1
   Push                 r2
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index 19e856e..a64977c 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -227,11 +227,8 @@
   PushNull
   StoreFieldTOS        CP#10
   Push                 r5
-  PushConstant         CP#12
-  StoreFieldTOS        CP#13
-  Push                 r5
   PushConstant         CP#0
-  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#12
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -239,7 +236,7 @@
   Push                 r4
   StoreLocal           r5
   Push                 r5
-  UncheckedClosureCall CP#17, 1
+  UncheckedClosureCall CP#14, 1
   Drop1
   Push                 r0
   LoadContextVar       0, 1
@@ -264,7 +261,7 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#18
+  PushConstant         CP#15
   StoreIndexedTOS
   Push                 r5
   PushInt              1
@@ -272,17 +269,17 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              2
-  PushConstant         CP#19
+  PushConstant         CP#16
   StoreIndexedTOS
   Push                 r5
   PushInt              3
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   DirectCall           CP#4, 1
   Drop1
-  AllocateClosure      CP#22
+  AllocateClosure      CP#19
   StoreLocal           r5
   Push                 r5
   PushNull
@@ -291,11 +288,8 @@
   PushNull
   StoreFieldTOS        CP#10
   Push                 r5
-  PushConstant         CP#12
-  StoreFieldTOS        CP#13
-  Push                 r5
-  PushConstant         CP#22
-  StoreFieldTOS        CP#15
+  PushConstant         CP#19
+  StoreFieldTOS        CP#12
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -310,7 +304,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 20, end 84, handler 84, needs-stack-trace, types [CP#6]
+  try-index 0, outer -1, start 20, end 78, handler 78, needs-stack-trace, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
@@ -325,24 +319,21 @@
   [9] = Reserved
   [10] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [11] = Reserved
-  [12] = EmptyTypeArguments
-  [13] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [14] = Reserved
-  [15] = InstanceField dart:core::_Closure::_function (field)
-  [16] = Reserved
-  [17] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
-  [18] = ObjectRef 'caught '
-  [19] = ObjectRef ' '
-  [20] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
-  [21] = Reserved
-  [22] = ClosureFunction 1
-  [23] = ObjectRef 'danger bar'
-  [24] = Type dart:core::Error
-  [25] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
-  [26] = Reserved
-  [27] = ObjectRef 'error '
-  [28] = ObjectRef ', captured stack trace: '
-  [29] = EndClosureFunctionScope
+  [12] = InstanceField dart:core::_Closure::_function (field)
+  [13] = Reserved
+  [14] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [15] = ObjectRef 'caught '
+  [16] = ObjectRef ' '
+  [17] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [18] = Reserved
+  [19] = ClosureFunction 1
+  [20] = ObjectRef 'danger bar'
+  [21] = Type dart:core::Error
+  [22] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+  [23] = Reserved
+  [24] = ObjectRef 'error '
+  [25] = ObjectRef ', captured stack trace: '
+  [26] = EndClosureFunctionScope
 }
 Closure #lib::testTryCatch3::'foo' () -> void
 ClosureCode {
@@ -390,7 +381,7 @@
   Push                 r0
   PopLocal             r2
 Try #0 start:
-  PushConstant         CP#23
+  PushConstant         CP#20
   DirectCall           CP#4, 1
   Drop1
   Jump                 L1
@@ -402,8 +393,8 @@
   MoveSpecial          exception, r2
   MoveSpecial          stackTrace, r3
   Push                 r2
-  PushConstant         CP#24
-  InterfaceCall        CP#25, 2
+  PushConstant         CP#21
+  InterfaceCall        CP#22, 2
   JumpIfFalse          L2
   Push                 r2
   PopLocal             r4
@@ -413,7 +404,7 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#27
+  PushConstant         CP#24
   StoreIndexedTOS
   Push                 r5
   PushInt              1
@@ -421,14 +412,14 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              2
-  PushConstant         CP#28
+  PushConstant         CP#25
   StoreIndexedTOS
   Push                 r5
   PushInt              3
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  DirectCall           CP#20, 1
+  DirectCall           CP#17, 1
   DirectCall           CP#4, 1
   Drop1
   Jump                 L1
@@ -637,11 +628,8 @@
   PushNull
   StoreFieldTOS        CP#12
   Push                 r8
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
-  Push                 r8
   PushConstant         CP#6
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#14
   Push                 r8
   Push                 r0
   StoreFieldTOS        CP#7
@@ -649,7 +637,7 @@
   Push                 r7
   StoreLocal           r8
   Push                 r8
-  UncheckedClosureCall CP#19, 1
+  UncheckedClosureCall CP#16, 1
   Drop1
   Jump                 L4
 Try #1 end:
@@ -659,7 +647,7 @@
   PopLocal             r0
   MoveSpecial          exception, r5
   MoveSpecial          stackTrace, r6
-  PushConstant         CP#21
+  PushConstant         CP#18
   DirectCall           CP#3, 1
   Drop1
   Push                 r5
@@ -668,7 +656,7 @@
 L4:
   Push                 r5
   PopLocal             r0
-  PushConstant         CP#21
+  PushConstant         CP#18
   DirectCall           CP#3, 1
   Drop1
   Jump                 L5
@@ -679,7 +667,7 @@
   PopLocal             r0
   MoveSpecial          exception, r3
   MoveSpecial          stackTrace, r4
-  PushConstant         CP#23
+  PushConstant         CP#20
   DirectCall           CP#3, 1
   Drop1
   Push                 r3
@@ -688,12 +676,12 @@
 L5:
   Push                 r3
   PopLocal             r0
-  PushConstant         CP#23
+  PushConstant         CP#20
   DirectCall           CP#3, 1
   Drop1
   Jump                 L2
 L2:
-  PushConstant         CP#24
+  PushConstant         CP#21
   DirectCall           CP#3, 1
   Drop1
   Jump                 L3
@@ -702,8 +690,8 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 53, end 162, handler 162, needs-stack-trace, synthetic, types [CP#20]
-  try-index 1, outer 0, start 70, end 124, handler 124, needs-stack-trace, synthetic, types [CP#20]
+  try-index 0, outer -1, start 53, end 156, handler 156, needs-stack-trace, synthetic, types [CP#17]
+  try-index 1, outer 0, start 70, end 118, handler 118, needs-stack-trace, synthetic, types [CP#17]
 }
 ConstantPool {
   [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
@@ -720,17 +708,14 @@
   [11] = Reserved
   [12] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [13] = Reserved
-  [14] = EmptyTypeArguments
-  [15] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [16] = Reserved
-  [17] = InstanceField dart:core::_Closure::_function (field)
-  [18] = Reserved
-  [19] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
-  [20] = Type dynamic
-  [21] = ObjectRef 'finally 1'
-  [22] = ObjectRef 'after try 1'
-  [23] = ObjectRef 'finally 2'
-  [24] = ObjectRef 'case 2'
+  [14] = InstanceField dart:core::_Closure::_function (field)
+  [15] = Reserved
+  [16] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [17] = Type dynamic
+  [18] = ObjectRef 'finally 1'
+  [19] = ObjectRef 'after try 1'
+  [20] = ObjectRef 'finally 2'
+  [21] = ObjectRef 'case 2'
 }
 Closure #lib::testTryFinally2::'foo' () -> void
 ClosureCode {
@@ -778,11 +763,8 @@
   PushNull
   StoreFieldTOS        CP#11
   Push                 r5
-  PushConstant         CP#13
-  StoreFieldTOS        CP#14
-  Push                 r5
   PushConstant         CP#0
-  StoreFieldTOS        CP#16
+  StoreFieldTOS        CP#13
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -800,7 +782,7 @@
   DirectCall           CP#3, 1
   Drop1
   Push                 r2
-  DynamicCall          CP#18, 1
+  DynamicCall          CP#15, 1
   Drop1
   Push                 r3
   Push                 r4
@@ -813,7 +795,7 @@
   DirectCall           CP#3, 1
   Drop1
   Push                 r2
-  DynamicCall          CP#18, 1
+  DynamicCall          CP#15, 1
   Drop1
   Push                 r0
   LoadContextParent
@@ -822,7 +804,7 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 23, end 61, handler 61, needs-stack-trace, synthetic, types [CP#6]
+  try-index 0, outer -1, start 23, end 55, handler 55, needs-stack-trace, synthetic, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
@@ -838,13 +820,10 @@
   [10] = Reserved
   [11] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [12] = Reserved
-  [13] = EmptyTypeArguments
-  [14] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [15] = Reserved
-  [16] = InstanceField dart:core::_Closure::_function (field)
-  [17] = Reserved
-  [18] = DynamicCall 'call', ArgDesc num-args 1, num-type-args 0, names []
-  [19] = Reserved
+  [13] = InstanceField dart:core::_Closure::_function (field)
+  [14] = Reserved
+  [15] = DynamicCall 'call', ArgDesc num-args 1, num-type-args 0, names []
+  [16] = Reserved
 }
 Closure #lib::testTryFinally3::'<anonymous closure>' () -> dart:core::int
 ClosureCode {
diff --git a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
index b4793ee..8031891 100755
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/compile_protos.sh
@@ -5,11 +5,12 @@
 
 # Running this script requires having protoc_plugin installed in your path.
 
-rm -rf lib/generated
-mkdir lib/generated
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+rm -rf $DIR/lib/generated
+mkdir $DIR/lib/generated
 
 # Directory of the script
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 GENERATED_DIR=$DIR/lib/generated
 
 protoc --dart_out=$GENERATED_DIR -I$DIR/protos $DIR/protos/*.proto
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
index 4063773..cab7883 100644
--- 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
@@ -1,253 +1,345 @@
 ///
 //  Generated code. Do not modify.
 //  source: foo.proto
-///
-// ignore_for_file: non_constant_identifier_names,library_prefixes,unused_import
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
 
-// ignore: UNUSED_SHOWN_NAME
-import 'dart:core' show int, bool, double, String, List, Map, override;
+import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
 class FooKeep extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = new $pb.BuilderInfo('FooKeep')
-    ..a<BarKeep>(
-        1, 'barKeep', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
-    ..a<BarKeep>(
-        2, 'barDrop', $pb.PbFieldType.OM, BarKeep.getDefault, BarKeep.create)
-    ..m<String, BarKeep>(3, 'mapKeep', 'FooKeep.MapKeepEntry',
-        $pb.PbFieldType.OS, $pb.PbFieldType.OM, BarKeep.create, null, null)
-    ..m<String, ZopDrop>(4, 'mapDrop', 'FooKeep.MapDropEntry',
-        $pb.PbFieldType.OS, $pb.PbFieldType.OM, ZopDrop.create, null, null)
-    ..a<int>(5, 'aKeep', $pb.PbFieldType.O3)
-    ..a<HasKeep>(
-        6, 'hasKeep', $pb.PbFieldType.OM, HasKeep.getDefault, HasKeep.create)
-    ..a<ClearKeep>(7, 'clearKeep', $pb.PbFieldType.OM, ClearKeep.getDefault,
-        ClearKeep.create)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('FooKeep', createEmptyInstance: create)
+        ..aOM<BarKeep>(1, 'barKeep',
+            protoName: 'barKeep', subBuilder: BarKeep.create)
+        ..aOM<BarKeep>(2, 'barDrop',
+            protoName: 'barDrop', subBuilder: BarKeep.create)
+        ..m<$core.String, BarKeep>(3, 'mapKeep',
+            protoName: 'mapKeep',
+            entryClassName: 'FooKeep.MapKeepEntry',
+            keyFieldType: $pb.PbFieldType.OS,
+            valueFieldType: $pb.PbFieldType.OM,
+            valueCreator: BarKeep.create)
+        ..m<$core.String, ZopDrop>(4, 'mapDrop',
+            protoName: 'mapDrop',
+            entryClassName: 'FooKeep.MapDropEntry',
+            keyFieldType: $pb.PbFieldType.OS,
+            valueFieldType: $pb.PbFieldType.OM,
+            valueCreator: ZopDrop.create)
+        ..a<$core.int>(5, 'aKeep', $pb.PbFieldType.O3, protoName: 'aKeep')
+        ..aOM<HasKeep>(6, 'hasKeep',
+            protoName: 'hasKeep', subBuilder: HasKeep.create)
+        ..aOM<ClearKeep>(7, 'clearKeep',
+            protoName: 'clearKeep', subBuilder: ClearKeep.create)
+        ..hasRequiredFields = false;
 
-  FooKeep() : super();
-  FooKeep.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  FooKeep.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  FooKeep clone() => new FooKeep()..mergeFromMessage(this);
+  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);
+  FooKeep clone() => FooKeep()..mergeFromMessage(this);
   FooKeep copyWith(void Function(FooKeep) updates) =>
       super.copyWith((message) => updates(message as FooKeep));
   $pb.BuilderInfo get info_ => _i;
-  static FooKeep create() => new FooKeep();
+  @$core.pragma('dart2js:noInline')
+  static FooKeep create() => FooKeep._();
   FooKeep createEmptyInstance() => create();
-  static $pb.PbList<FooKeep> createRepeated() => new $pb.PbList<FooKeep>();
-  static FooKeep getDefault() => _defaultInstance ??= create()..freeze();
+  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);
   }
 
-  bool hasBarKeep() => $_has(0);
+  @$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);
   }
 
-  bool hasBarDrop() => $_has(1);
+  @$pb.TagNumber(2)
+  $core.bool hasBarDrop() => $_has(1);
+  @$pb.TagNumber(2)
   void clearBarDrop() => clearField(2);
+  @$pb.TagNumber(2)
+  BarKeep ensureBarDrop() => $_ensure(1);
 
-  Map<String, BarKeep> get mapKeep => $_getMap(2);
+  @$pb.TagNumber(3)
+  $core.Map<$core.String, BarKeep> get mapKeep => $_getMap(2);
 
-  Map<String, ZopDrop> get mapDrop => $_getMap(3);
+  @$pb.TagNumber(4)
+  $core.Map<$core.String, ZopDrop> get mapDrop => $_getMap(3);
 
-  int get aKeep => $_get(4, 0);
-  set aKeep(int v) {
+  @$pb.TagNumber(5)
+  $core.int get aKeep => $_getIZ(4);
+  @$pb.TagNumber(5)
+  set aKeep($core.int v) {
     $_setSignedInt32(4, v);
   }
 
-  bool hasAKeep() => $_has(4);
+  @$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);
   }
 
-  bool hasHasKeep() => $_has(5);
+  @$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);
   }
 
-  bool hasClearKeep() => $_has(6);
+  @$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 = new $pb.BuilderInfo('BarKeep')
-    ..a<int>(1, 'aKeep', $pb.PbFieldType.O3)
-    ..a<int>(2, 'bDrop', $pb.PbFieldType.O3)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('BarKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aKeep', $pb.PbFieldType.O3, protoName: 'aKeep')
+        ..a<$core.int>(2, 'bDrop', $pb.PbFieldType.O3, protoName: 'bDrop')
+        ..hasRequiredFields = false;
 
-  BarKeep() : super();
-  BarKeep.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  BarKeep.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  BarKeep clone() => new BarKeep()..mergeFromMessage(this);
+  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);
+  BarKeep clone() => BarKeep()..mergeFromMessage(this);
   BarKeep copyWith(void Function(BarKeep) updates) =>
       super.copyWith((message) => updates(message as BarKeep));
   $pb.BuilderInfo get info_ => _i;
-  static BarKeep create() => new BarKeep();
+  @$core.pragma('dart2js:noInline')
+  static BarKeep create() => BarKeep._();
   BarKeep createEmptyInstance() => create();
-  static $pb.PbList<BarKeep> createRepeated() => new $pb.PbList<BarKeep>();
-  static BarKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static $pb.PbList<BarKeep> createRepeated() => $pb.PbList<BarKeep>();
+  @$core.pragma('dart2js:noInline')
+  static BarKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BarKeep>(create);
   static BarKeep _defaultInstance;
 
-  int get aKeep => $_get(0, 0);
-  set aKeep(int v) {
+  @$pb.TagNumber(1)
+  $core.int get aKeep => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aKeep($core.int v) {
     $_setSignedInt32(0, v);
   }
 
-  bool hasAKeep() => $_has(0);
+  @$pb.TagNumber(1)
+  $core.bool hasAKeep() => $_has(0);
+  @$pb.TagNumber(1)
   void clearAKeep() => clearField(1);
 
-  int get bDrop => $_get(1, 0);
-  set bDrop(int v) {
+  @$pb.TagNumber(2)
+  $core.int get bDrop => $_getIZ(1);
+  @$pb.TagNumber(2)
+  set bDrop($core.int v) {
     $_setSignedInt32(1, v);
   }
 
-  bool hasBDrop() => $_has(1);
+  @$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 = new $pb.BuilderInfo('HasKeep')
-    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('HasKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
 
-  HasKeep() : super();
-  HasKeep.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  HasKeep.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  HasKeep clone() => new HasKeep()..mergeFromMessage(this);
+  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);
+  HasKeep clone() => HasKeep()..mergeFromMessage(this);
   HasKeep copyWith(void Function(HasKeep) updates) =>
       super.copyWith((message) => updates(message as HasKeep));
   $pb.BuilderInfo get info_ => _i;
-  static HasKeep create() => new HasKeep();
+  @$core.pragma('dart2js:noInline')
+  static HasKeep create() => HasKeep._();
   HasKeep createEmptyInstance() => create();
-  static $pb.PbList<HasKeep> createRepeated() => new $pb.PbList<HasKeep>();
-  static HasKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static $pb.PbList<HasKeep> createRepeated() => $pb.PbList<HasKeep>();
+  @$core.pragma('dart2js:noInline')
+  static HasKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HasKeep>(create);
   static HasKeep _defaultInstance;
 
-  int get aDrop => $_get(0, 0);
-  set aDrop(int v) {
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
     $_setSignedInt32(0, v);
   }
 
-  bool hasADrop() => $_has(0);
+  @$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 = new $pb.BuilderInfo('ClearKeep')
-    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('ClearKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
 
-  ClearKeep() : super();
-  ClearKeep.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  ClearKeep.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  ClearKeep clone() => new ClearKeep()..mergeFromMessage(this);
+  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);
+  ClearKeep clone() => ClearKeep()..mergeFromMessage(this);
   ClearKeep copyWith(void Function(ClearKeep) updates) =>
       super.copyWith((message) => updates(message as ClearKeep));
   $pb.BuilderInfo get info_ => _i;
-  static ClearKeep create() => new ClearKeep();
+  @$core.pragma('dart2js:noInline')
+  static ClearKeep create() => ClearKeep._();
   ClearKeep createEmptyInstance() => create();
-  static $pb.PbList<ClearKeep> createRepeated() => new $pb.PbList<ClearKeep>();
-  static ClearKeep getDefault() => _defaultInstance ??= create()..freeze();
+  static $pb.PbList<ClearKeep> createRepeated() => $pb.PbList<ClearKeep>();
+  @$core.pragma('dart2js:noInline')
+  static ClearKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ClearKeep>(create);
   static ClearKeep _defaultInstance;
 
-  int get aDrop => $_get(0, 0);
-  set aDrop(int v) {
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
     $_setSignedInt32(0, v);
   }
 
-  bool hasADrop() => $_has(0);
+  @$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 = new $pb.BuilderInfo('ZopDrop')
-    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('ZopDrop', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
 
-  ZopDrop() : super();
-  ZopDrop.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  ZopDrop.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  ZopDrop clone() => new ZopDrop()..mergeFromMessage(this);
+  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);
+  ZopDrop clone() => ZopDrop()..mergeFromMessage(this);
   ZopDrop copyWith(void Function(ZopDrop) updates) =>
       super.copyWith((message) => updates(message as ZopDrop));
   $pb.BuilderInfo get info_ => _i;
-  static ZopDrop create() => new ZopDrop();
+  @$core.pragma('dart2js:noInline')
+  static ZopDrop create() => ZopDrop._();
   ZopDrop createEmptyInstance() => create();
-  static $pb.PbList<ZopDrop> createRepeated() => new $pb.PbList<ZopDrop>();
-  static ZopDrop getDefault() => _defaultInstance ??= create()..freeze();
+  static $pb.PbList<ZopDrop> createRepeated() => $pb.PbList<ZopDrop>();
+  @$core.pragma('dart2js:noInline')
+  static ZopDrop getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ZopDrop>(create);
   static ZopDrop _defaultInstance;
 
-  int get aDrop => $_get(0, 0);
-  set aDrop(int v) {
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
     $_setSignedInt32(0, v);
   }
 
-  bool hasADrop() => $_has(0);
+  @$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 = new $pb.BuilderInfo('MobDrop')
-    ..a<int>(1, 'aDrop', $pb.PbFieldType.O3)
-    ..hasRequiredFields = false;
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('MobDrop', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
 
-  MobDrop() : super();
-  MobDrop.fromBuffer(List<int> i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromBuffer(i, r);
-  MobDrop.fromJson(String i,
-      [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY])
-      : super.fromJson(i, r);
-  MobDrop clone() => new MobDrop()..mergeFromMessage(this);
+  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);
+  MobDrop clone() => MobDrop()..mergeFromMessage(this);
   MobDrop copyWith(void Function(MobDrop) updates) =>
       super.copyWith((message) => updates(message as MobDrop));
   $pb.BuilderInfo get info_ => _i;
-  static MobDrop create() => new MobDrop();
+  @$core.pragma('dart2js:noInline')
+  static MobDrop create() => MobDrop._();
   MobDrop createEmptyInstance() => create();
-  static $pb.PbList<MobDrop> createRepeated() => new $pb.PbList<MobDrop>();
-  static MobDrop getDefault() => _defaultInstance ??= create()..freeze();
+  static $pb.PbList<MobDrop> createRepeated() => $pb.PbList<MobDrop>();
+  @$core.pragma('dart2js:noInline')
+  static MobDrop getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MobDrop>(create);
   static MobDrop _defaultInstance;
 
-  int get aDrop => $_get(0, 0);
-  set aDrop(int v) {
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
     $_setSignedInt32(0, v);
   }
 
-  bool hasADrop() => $_has(0);
+  @$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
new file mode 100644
index 0000000..bc76b27
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/generated/name_mangling.pb.dart
@@ -0,0 +1,80 @@
+///
+//  Generated code. Do not modify.
+//  source: name_mangling.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class AKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('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);
+  AKeep clone() => AKeep()..mergeFromMessage(this);
+  AKeep copyWith(void Function(AKeep) updates) =>
+      super.copyWith((message) => updates(message as AKeep));
+  $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('NameManglingKeep', createEmptyInstance: create)
+        ..aOM<AKeep>(10, '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);
+  NameManglingKeep clone() => NameManglingKeep()..mergeFromMessage(this);
+  NameManglingKeep copyWith(void Function(NameManglingKeep) updates) =>
+      super.copyWith((message) => updates(message as NameManglingKeep));
+  $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
new file mode 100644
index 0000000..b52c5dc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/lib/name_mangling_test.dart
@@ -0,0 +1,14 @@
+// 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/protos/foo.proto b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
index 0a14433..1f10872 100644
--- a/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/foo.proto
@@ -34,8 +34,3 @@
 message MobDrop {
   int32 aDrop = 1;
 }
-
-message A {
-  B unused = 1;
-  C used = 2;
-}
\ No newline at end of file
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
new file mode 100644
index 0000000..f25b2f4
--- /dev/null
+++ b/pkg/vm/testcases/transformations/protobuf_aware_treeshaker/protos/name_mangling.proto
@@ -0,0 +1,10 @@
+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/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 6dc134a..62fdd38 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 @#C5
-typedef SomeType<unrelated T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
+typedef SomeType<contravariant T extends core::Object* = dynamic> = (core::List<T*>*) →* void;
 abstract class ClassAnnotation2 extends core::Object {
 }
 abstract class MethodAnnotation extends core::Object {
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 22cbe59..7f4e53f 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
@@ -30,7 +30,7 @@
   }
 }
 static method main(core::List<core::String*>* args) → dynamic {
-  core::Stopwatch* timer = let final core::Stopwatch* #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}() in #t1;
+  core::Stopwatch* timer = let final core::Stopwatch* #t1 = new core::Stopwatch::•() in let final void #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}() in #t1;
   for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
     self::run();
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 076082e..e9ee2e6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -27,7 +27,7 @@
 [@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector* v = new self::_Vector::•(10);
 [@vm.inferred-type.metadata=dart.core::_Double?]static field core::double* x = 0.0;
 static method main(core::List<core::String*>* args) → dynamic {
-  core::Stopwatch* timer = let final core::Stopwatch* #t4 = new core::Stopwatch::•() in let final dynamic #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t4.{core::Stopwatch::start}() in #t4;
+  core::Stopwatch* timer = let final core::Stopwatch* #t4 = new core::Stopwatch::•() in let final void #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] [@vm.inferred-type.metadata=!? (skip check)] #t4.{core::Stopwatch::start}() in #t4;
   for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1)) {
     self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
   }
diff --git a/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
new file mode 100644
index 0000000..378c297
--- /dev/null
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart
@@ -0,0 +1,118 @@
+// 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.
+
+const bool constTrue = const bool.fromEnvironment('test.define.isTrue');
+const bool constFalse = const bool.fromEnvironment('test.define.isFalse');
+const bool constTrue2 = !constFalse;
+const bool constFalse2 = const bool.fromEnvironment('test.define.notDefined');
+
+bool foo() => null;
+
+void testSimpleConditions() {
+  if (constTrue) {
+    print('1_yes');
+  }
+  if (constFalse) {
+    print('2_no');
+  }
+  if (constTrue2) {
+    print('3_yes');
+    if (constFalse2) {
+      print('4_no');
+    }
+  }
+}
+
+void testAndConditions() {
+  if (constTrue && foo()) {
+    print('1_yes');
+  }
+  if (constFalse && foo()) {
+    print('2_no');
+  }
+  if (constTrue && constFalse) {
+    print('3_no');
+  }
+  if (constTrue && constTrue && constFalse) {
+    print('4_no');
+  }
+}
+
+void testOrConditions() {
+  if (constTrue || foo()) {
+    print('1_yes');
+  }
+  if (constFalse || foo()) {
+    print('2_yes');
+  }
+  if (constFalse || constFalse2) {
+    print('3_no');
+  }
+  if (constFalse || !constTrue || constTrue2) {
+    print('4_yes');
+  }
+}
+
+void testNotConditions() {
+  if (!constTrue) {
+    print('1_no');
+  }
+  if (!constFalse) {
+    print('2_yes');
+  }
+  if (!(!(!constTrue && foo()) || foo())) {
+    print('3_no');
+  }
+}
+
+testConditionalExpressions() {
+  print(!constFalse && constTrue ? '1_yes' : '2_no');
+  print(constFalse && foo() ? '3_no' : '4_yes ${foo()}');
+}
+
+void testAsserts() {
+  assert(foo());
+  assert(!foo(), "oops!");
+}
+
+class TestAssertInitializer {
+  TestAssertInitializer() : assert(foo()) {}
+}
+
+testRemovalOfStatementBodies() {
+  if (foo()) assert(foo());
+  while (foo()) assert(foo());
+  do assert(foo()); while (foo());
+  for (;;) assert(foo());
+  for (var i in [1, 2]) assert(foo());
+  try {
+    assert(foo());
+  } finally {
+    assert(foo());
+  }
+  try {
+    assert(foo());
+  } catch (e) {
+    assert(foo());
+  }
+  switch (42) {
+    case 10:
+      assert(foo());
+  }
+  switch (42) {
+    default:
+      assert(foo());
+  }
+}
+
+main(List<String> args) {
+  testSimpleConditions();
+  testAndConditions();
+  testOrConditions();
+  testNotConditions();
+  testConditionalExpressions();
+  testAsserts();
+  new TestAssertInitializer();
+  testRemovalOfStatementBodies();
+}
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
new file mode 100644
index 0000000..075f92e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/unreachable_code_elimination/uce_testcases.dart.expect
@@ -0,0 +1,89 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+class TestAssertInitializer extends core::Object {
+  constructor •() → self::TestAssertInitializer*
+    : super core::Object::•() {}
+}
+static const field core::bool* constTrue = #C1;
+static const field core::bool* constFalse = #C2;
+static const field core::bool* constTrue2 = #C1;
+static const field core::bool* constFalse2 = #C2;
+static method foo() → core::bool*
+  return null;
+static method testSimpleConditions() → void {
+  {
+    core::print("1_yes");
+  }
+  {
+    core::print("3_yes");
+  }
+}
+static method testAndConditions() → void {
+  if((#C1) && self::foo()) {
+    core::print("1_yes");
+  }
+}
+static method testOrConditions() → void {
+  {
+    core::print("1_yes");
+  }
+  if((#C2) || self::foo()) {
+    core::print("2_yes");
+  }
+  {
+    core::print("4_yes");
+  }
+}
+static method testNotConditions() → void {
+  {
+    core::print("2_yes");
+  }
+}
+static method testConditionalExpressions() → dynamic {
+  core::print("1_yes");
+  core::print("4_yes ${self::foo()}");
+}
+static method testAsserts() → void {}
+static method testRemovalOfStatementBodies() → dynamic {
+  if(self::foo()) {
+  }
+  while (self::foo()) {
+  }
+  do {
+  }
+  while (self::foo())
+  for (; ; ) {
+  }
+  for (core::int* i in <core::int*>[1, 2]) {
+  }
+  try {
+  }
+  finally {
+  }
+  try {
+  }
+  on dynamic catch(final dynamic e) {
+  }
+  switch(42) {
+    #L1:
+    case #C3:
+      {}
+  }
+  switch(42) {
+    #L2:
+    default:
+      {}
+  }
+}
+static method main(core::List<core::String*>* args) → dynamic {
+  self::testSimpleConditions();
+  self::testAndConditions();
+  self::testOrConditions();
+  self::testNotConditions();
+  self::testConditionalExpressions();
+  self::testAsserts();
+  new self::TestAssertInitializer::•();
+  self::testRemovalOfStatementBodies();
+}
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index c6f5421..0bdecc9 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -31,6 +31,8 @@
     ;;
     --tfa | \
     --no-tfa | \
+    --gen-bytecode | \
+    --no-gen-bytecode | \
     -D* )
     GEN_KERNEL_OPTIONS+=("$arg")
     ;;
@@ -90,6 +92,7 @@
 
 # Step 1: Generate Kernel binary from the input Dart source.
 "$BIN_DIR"/dart                                                                \
+     ${DART_VM_FLAGS}                                                          \
      "${SDK_DIR}/pkg/vm/bin/gen_kernel.dart"                                   \
      --platform "${BIN_DIR}/vm_platform_strong.dill"                           \
      --aot                                                                     \
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index baaad58..65e42bc 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -672,6 +672,33 @@
   return obj;
 }
 
+vms.IsolateGroupRef assertIsolateGroupRef(vms.IsolateGroupRef obj) {
+  assertNotNull(obj);
+  assertString(obj.type);
+  assertString(obj.id);
+  assertString(obj.number);
+  assertString(obj.name);
+  return obj;
+}
+
+List<vms.IsolateGroupRef> assertListOfIsolateGroupRef(
+    List<vms.IsolateGroupRef> list) {
+  for (vms.IsolateGroupRef elem in list) {
+    assertIsolateGroupRef(elem);
+  }
+  return list;
+}
+
+vms.IsolateGroup assertIsolateGroup(vms.IsolateGroup obj) {
+  assertNotNull(obj);
+  assertString(obj.type);
+  assertString(obj.id);
+  assertString(obj.number);
+  assertString(obj.name);
+  assertListOfIsolateRef(obj.isolates);
+  return obj;
+}
+
 vms.InboundReferences assertInboundReferences(vms.InboundReferences obj) {
   assertNotNull(obj);
   assertString(obj.type);
@@ -1108,5 +1135,6 @@
   assertInt(obj.pid);
   assertInt(obj.startTime);
   assertListOfIsolateRef(obj.isolates);
+  assertListOfIsolateGroupRef(obj.isolateGroups);
   return obj;
 }
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index b5f4f08..ccd4e34 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -9,6 +9,8 @@
 src/org/dartlang/vm/service/consumer/FlagListConsumer.java
 src/org/dartlang/vm/service/consumer/GetInboundReferencesConsumer.java
 src/org/dartlang/vm/service/consumer/GetIsolateConsumer.java
+src/org/dartlang/vm/service/consumer/GetIsolateGroupConsumer.java
+src/org/dartlang/vm/service/consumer/GetIsolateGroupMemoryUsageConsumer.java
 src/org/dartlang/vm/service/consumer/GetMemoryUsageConsumer.java
 src/org/dartlang/vm/service/consumer/GetObjectConsumer.java
 src/org/dartlang/vm/service/consumer/InstanceSetConsumer.java
@@ -63,6 +65,8 @@
 src/org/dartlang/vm/service/element/InstanceRef.java
 src/org/dartlang/vm/service/element/InstanceSet.java
 src/org/dartlang/vm/service/element/Isolate.java
+src/org/dartlang/vm/service/element/IsolateGroup.java
+src/org/dartlang/vm/service/element/IsolateGroupRef.java
 src/org/dartlang/vm/service/element/IsolateRef.java
 src/org/dartlang/vm/service/element/Library.java
 src/org/dartlang/vm/service/element/LibraryDependency.java
diff --git a/pkg/vm_service/lib/src/helpers.dart b/pkg/vm_service/lib/src/helpers.dart
index b69fb5e..a7344f3 100644
--- a/pkg/vm_service/lib/src/helpers.dart
+++ b/pkg/vm_service/lib/src/helpers.dart
@@ -24,9 +24,3 @@
 
   TagCounter(this.name, this.count);
 }
-
-//class GraphEventHelper {
-//  // int chunkIndex
-//  // int chunkCount
-//  // int nodeCount
-//}
diff --git a/pkg/vm_service/lib/src/snapshot_graph.dart b/pkg/vm_service/lib/src/snapshot_graph.dart
index 7265cd4..388dfe3 100644
--- a/pkg/vm_service/lib/src/snapshot_graph.dart
+++ b/pkg/vm_service/lib/src/snapshot_graph.dart
@@ -346,7 +346,6 @@
       final len = reader.readUnsigned();
       final str = reader.readUtf16();
       return (str.length < len) ? '$str...' : str;
-      return reader.readUtf16();
     case _kLengthData:
       return HeapSnapshotObjectLengthData(reader.readUnsigned());
     case _kNameData:
diff --git a/pkg/vm_service/lib/vm_service.dart b/pkg/vm_service/lib/vm_service.dart
index 0eeea9b..c77250b5 100644
--- a/pkg/vm_service/lib/vm_service.dart
+++ b/pkg/vm_service/lib/vm_service.dart
@@ -131,6 +131,8 @@
   'Instance': Instance.parse,
   '@Isolate': IsolateRef.parse,
   'Isolate': Isolate.parse,
+  '@IsolateGroup': IsolateGroupRef.parse,
+  'IsolateGroup': IsolateGroup.parse,
   'InboundReferences': InboundReferences.parse,
   'InboundReference': InboundReference.parse,
   'InstanceSet': InstanceSet.parse,
@@ -188,7 +190,9 @@
   'getInboundReferences': const ['InboundReferences', 'Sentinel'],
   'getInstances': const ['InstanceSet'],
   'getIsolate': const ['Isolate', 'Sentinel'],
+  'getIsolateGroup': const ['IsolateGroup', 'Sentinel'],
   'getMemoryUsage': const ['MemoryUsage', 'Sentinel'],
+  'getIsolateGroupMemoryUsage': const ['MemoryUsage', 'Sentinel'],
   'getScripts': const ['ScriptList'],
   'getObject': const ['Obj', 'Sentinel'],
   'getRetainingPath': const ['RetainingPath'],
@@ -506,6 +510,21 @@
   /// The return value can be one of [Isolate] or [Sentinel].
   Future<dynamic> getIsolate(String isolateId);
 
+  /// The `getIsolateGroup` RPC is used to lookup an `IsolateGroup` object by
+  /// its `id`.
+  ///
+  /// If `isolateGroupId` refers to an isolate group which has exited, then the
+  /// `Expired` [Sentinel] is returned.
+  ///
+  /// `IsolateGroup` `id` is an opaque identifier that can be fetched from an
+  /// `IsolateGroup`. List of active `IsolateGroup`'s, for example, is available
+  /// on `VM` object.
+  ///
+  /// See [IsolateGroup], [VM].
+  ///
+  /// The return value can be one of [IsolateGroup] or [Sentinel].
+  Future<dynamic> getIsolateGroup(String isolateGroupId);
+
   /// The `getMemoryUsage` RPC is used to lookup an isolate's memory usage
   /// statistics by its `id`.
   ///
@@ -517,6 +536,17 @@
   /// The return value can be one of [MemoryUsage] or [Sentinel].
   Future<dynamic> getMemoryUsage(String isolateId);
 
+  /// The `getIsolateGroupMemoryUsage` RPC is used to lookup an isolate group's
+  /// memory usage statistics by its `id`.
+  ///
+  /// If `isolateGroupId` refers to an isolate group which has exited, then the
+  /// `Expired` [Sentinel] is returned.
+  ///
+  /// See [IsolateGroup].
+  ///
+  /// The return value can be one of [MemoryUsage] or [Sentinel].
+  Future<dynamic> getIsolateGroupMemoryUsage(String isolateGroupId);
+
   /// The `getScripts` RPC is used to retrieve a `ScriptList` containing all
   /// scripts for an isolate based on the isolate's `isolateId`.
   ///
@@ -1027,11 +1057,21 @@
             params['isolateId'],
           );
           break;
+        case 'getIsolateGroup':
+          response = await _serviceImplementation.getIsolateGroup(
+            params['isolateGroupId'],
+          );
+          break;
         case 'getMemoryUsage':
           response = await _serviceImplementation.getMemoryUsage(
             params['isolateId'],
           );
           break;
+        case 'getIsolateGroupMemoryUsage':
+          response = await _serviceImplementation.getIsolateGroupMemoryUsage(
+            params['isolateGroupId'],
+          );
+          break;
         case 'getScripts':
           response = await _serviceImplementation.getScripts(
             params['isolateId'],
@@ -1217,8 +1257,8 @@
       }
       _responseSink.add({
         'jsonrpc': '2.0',
-        'result': response.toJson(),
         'id': id,
+        'result': response.toJson(),
       });
     } catch (e, st) {
       var error = e is RPCError
@@ -1226,8 +1266,8 @@
           : {'code': -32603, 'message': '$e\n$st'};
       _responseSink.add({
         'jsonrpc': '2.0',
-        'error': error,
         'id': request['id'],
+        'error': error,
       });
     }
   }
@@ -1469,11 +1509,22 @@
   }
 
   @override
+  Future<dynamic> getIsolateGroup(String isolateGroupId) {
+    return _call('getIsolateGroup', {'isolateGroupId': isolateGroupId});
+  }
+
+  @override
   Future<dynamic> getMemoryUsage(String isolateId) {
     return _call('getMemoryUsage', {'isolateId': isolateId});
   }
 
   @override
+  Future<dynamic> getIsolateGroupMemoryUsage(String isolateGroupId) {
+    return _call(
+        'getIsolateGroupMemoryUsage', {'isolateGroupId': isolateGroupId});
+  }
+
+  @override
   Future<ScriptList> getScripts(String isolateId) {
     return _call('getScripts', {'isolateId': isolateId});
   }
@@ -1699,6 +1750,7 @@
   void dispose() {
     _streamSub.cancel();
     _completers.values.forEach((c) => c.completeError('disposed'));
+    _completers.clear();
     if (_disposeHandler != null) {
       _disposeHandler();
     }
@@ -4444,6 +4496,105 @@
   String toString() => '[Isolate]';
 }
 
+/// `IsolateGroupRef` is a reference to an `IsolateGroup` object.
+class IsolateGroupRef extends Response {
+  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;
+
+  /// A numeric id for this isolate group, represented as a string. Unique.
+  String number;
+
+  /// A name identifying this isolate group. Not guaranteed to be unique.
+  String name;
+
+  IsolateGroupRef({
+    @required this.id,
+    @required this.number,
+    @required this.name,
+  });
+  IsolateGroupRef._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
+    id = json['id'];
+    number = json['number'];
+    name = json['name'];
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    var json = <String, dynamic>{};
+    json['type'] = '@IsolateGroup';
+    json.addAll({
+      'id': id,
+      'number': number,
+      'name': name,
+    });
+    return json;
+  }
+
+  int get hashCode => id.hashCode;
+
+  operator ==(other) => other is IsolateGroupRef && id == other.id;
+
+  String toString() =>
+      '[IsolateGroupRef type: ${type}, id: ${id}, number: ${number}, name: ${name}]';
+}
+
+/// An `Isolate` object provides information about one isolate in the VM.
+class IsolateGroup extends Response {
+  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;
+
+  /// A numeric id for this isolate, represented as a string. Unique.
+  String number;
+
+  /// A name identifying this isolate. Not guaranteed to be unique.
+  String name;
+
+  /// A list of all isolates in this isolate group.
+  List<IsolateRef> isolates;
+
+  IsolateGroup({
+    @required this.id,
+    @required this.number,
+    @required this.name,
+    @required this.isolates,
+  });
+  IsolateGroup._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
+    id = json['id'];
+    number = json['number'];
+    name = json['name'];
+    isolates = List<IsolateRef>.from(
+        createServiceObject(json['isolates'], const ['IsolateRef']));
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    var json = <String, dynamic>{};
+    json['type'] = 'IsolateGroup';
+    json.addAll({
+      'id': id,
+      'number': number,
+      'name': name,
+      'isolates': isolates.map((f) => f.toJson()).toList(),
+    });
+    return json;
+  }
+
+  int get hashCode => id.hashCode;
+
+  operator ==(other) => other is IsolateGroup && id == other.id;
+
+  String toString() => '[IsolateGroup ' //
+      'type: ${type}, id: ${id}, number: ${number}, name: ${name}, ' //
+      'isolates: ${isolates}]';
+}
+
 /// See [getInboundReferences].
 class InboundReferences extends Response {
   static InboundReferences parse(Map<String, dynamic> json) =>
@@ -6236,6 +6387,9 @@
   /// A list of isolates running in the VM.
   List<IsolateRef> isolates;
 
+  /// A list of isolate groups running in the VM.
+  List<IsolateGroupRef> isolateGroups;
+
   VM({
     @required this.name,
     @required this.architectureBits,
@@ -6246,6 +6400,7 @@
     @required this.pid,
     @required this.startTime,
     @required this.isolates,
+    @required this.isolateGroups,
   });
   VM._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     name = json['name'];
@@ -6258,6 +6413,8 @@
     startTime = json['startTime'];
     isolates = List<IsolateRef>.from(
         createServiceObject(json['isolates'], const ['IsolateRef']));
+    isolateGroups = List<IsolateGroupRef>.from(
+        createServiceObject(json['isolateGroups'], const ['IsolateGroupRef']));
   }
 
   @override
@@ -6274,6 +6431,7 @@
       'pid': pid,
       'startTime': startTime,
       'isolates': isolates.map((f) => f.toJson()).toList(),
+      'isolateGroups': isolateGroups.map((f) => f.toJson()).toList(),
     });
     return json;
   }
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 dcc8d9b..de49353 100644
--- a/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
+++ b/pkg/vm_service/test/get_cpu_samples_rpc_test.dart
@@ -54,7 +54,7 @@
 
 var vmArgs = [
   '--profiler=true',
-  '--profile-vm=false', // So this also works with DBC and KBC.
+  '--profile-vm=false', // So this also works with KBC.
 ];
 
 main([args = const <String>[]]) async =>
diff --git a/pkg/vm_service/test/get_isolate_group_memory_usage.dart b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
new file mode 100644
index 0000000..e6323a1
--- /dev/null
+++ b/pkg/vm_service/test/get_isolate_group_memory_usage.dart
@@ -0,0 +1,35 @@
+// 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 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+var tests = <VMTest>[
+  (VmService service) async {
+    final vm = await service.getVM();
+    final result =
+        await service.getIsolateGroupMemoryUsage(vm.isolateGroups.first.id);
+    expect(result.heapUsage, isPositive);
+    expect(result.heapCapacity, isPositive);
+    expect(result.externalUsage, isNonNegative);
+  },
+  (VmService service) async {
+    bool caughtException;
+    try {
+      await service.getMemoryUsage('badid');
+      fail('Unreachable');
+    } on RPCError catch (e) {
+      caughtException = true;
+      expect(
+          e.details,
+          contains(
+              "getMemoryUsage: invalid 'isolateGroupId' parameter: badid"));
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/pkg/vm_service/test/heap_snapshot_graph_test.dart b/pkg/vm_service/test/heap_snapshot_graph_test.dart
index c0db2ec..ae72210 100644
--- a/pkg/vm_service/test/heap_snapshot_graph_test.dart
+++ b/pkg/vm_service/test/heap_snapshot_graph_test.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-import 'dart:typed_data';
-
 import 'package:vm_service/vm_service.dart';
 import 'package:test/test.dart';
 
@@ -42,7 +39,7 @@
     expect(snapshotGraph.name, "main");
     expect(snapshotGraph.flags, isNotNull);
     expect(snapshotGraph.objects, isNotNull);
-    expect(snapshotGraph.objects.length > 0, isTrue);
+    expect(snapshotGraph.objects, isNotEmpty);
 
     int actualShallowSize = 0;
     int actualRefCount = 0;
@@ -61,7 +58,7 @@
     expect(snapshotGraph.referenceCount >= actualRefCount, isTrue);
 
     int actualExternalSize = 0;
-    expect(snapshotGraph.externalProperties.length > 0, isTrue);
+    expect(snapshotGraph.externalProperties, isNotEmpty);
     snapshotGraph.externalProperties.forEach((HeapSnapshotExternalProperty e) {
       actualExternalSize += e.externalSize;
       expect(e.object >= 0, isTrue);
@@ -69,7 +66,7 @@
     });
     expect(snapshotGraph.externalSize, actualExternalSize);
 
-    expect(snapshotGraph.classes.length > 0, isTrue);
+    expect(snapshotGraph.classes, isNotEmpty);
     snapshotGraph.classes.forEach((HeapSnapshotClass c) {
       expect(c.name, isNotNull);
       expect(c.libraryName, isNotNull);
diff --git a/pkg/vm_service/test/server_test.dart b/pkg/vm_service/test/server_test.dart
index 62a351f..d0ed5b0 100644
--- a/pkg/vm_service/test/server_test.dart
+++ b/pkg/vm_service/test/server_test.dart
@@ -193,7 +193,7 @@
       expect(
           responsesController.stream.map((response) => '$response'),
           emits(startsWith(
-              '{jsonrpc: 2.0, error: {code: -32603, message: UnimplementedError')));
+              '{jsonrpc: 2.0, id: 1, error: {code: -32603, message: UnimplementedError')));
       requestsController.add(request);
     });
   });
@@ -465,8 +465,8 @@
   }
   return {
     'jsonrpc': '2.0',
-    'error': errorJson,
     'id': id,
+    'error': errorJson,
   };
 }
 
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 7949af4..c85e941 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -187,9 +187,8 @@
       } else {
         _processNotification(json);
       }
-    } else if(json.containsKey('id') && (
-                json.containsKey('result') || json.containsKey('error')
-              )) {
+    } else if (json.containsKey('id') &&
+        (json.containsKey('result') || json.containsKey('error'))) {
       _processResponse(json);
     }
     else {
@@ -715,8 +714,8 @@
     // Generate the json success response
     gen.write("""_responseSink.add({
   'jsonrpc': '2.0',
-  'result': response.toJson(),
   'id': id,
+  'result': response.toJson(),
 });
 """);
 
@@ -728,8 +727,8 @@
             : {'code': -32603, 'message': '$e\n$st'};
         _responseSink.add({
           'jsonrpc': '2.0',
-          'error': error,
           'id': request['id'],
+          'error': error,
         });
       }
 ''');
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index 6751886..1932df8 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -100,18 +100,12 @@
   } else if (dart_target_arch == "armv6") {
     defines += [ "TARGET_ARCH_ARM" ]
     defines += [ "TARGET_ARCH_ARM_6" ]
-  } else if (dart_target_arch == "armv5te") {
-    defines += [ "TARGET_ARCH_ARM" ]
-    defines += [ "TARGET_ARCH_ARM_5TE" ]
   } else if (dart_target_arch == "arm64") {
     defines += [ "TARGET_ARCH_ARM64" ]
   } else if (dart_target_arch == "x64") {
     defines += [ "TARGET_ARCH_X64" ]
   } else if (dart_target_arch == "ia32" || dart_target_arch == "x86") {
     defines += [ "TARGET_ARCH_IA32" ]
-  } else if (dart_target_arch == "dbc") {
-    defines += [ "TARGET_ARCH_DBC" ]
-    defines += [ "USING_SIMULATOR" ]
   } else {
     print("Invalid dart_target_arch: $dart_target_arch")
     assert(false)
@@ -168,6 +162,9 @@
       "-fno-exceptions",
       "-Wimplicit-fallthrough",
     ]
+    if (!is_clang) {
+      cflags += [ "-Wno-cast-function-type" ]
+    }
 
     ldflags = []
     if (is_clang && dart_vm_code_coverage) {
@@ -223,7 +220,10 @@
   }
   if (is_fuchsia) {
     if (using_fuchsia_sdk) {
-      extra_deps += [ "$fuchsia_sdk_root/pkg:fdio" ]
+      extra_deps += [
+        "$fuchsia_sdk_root/pkg:fdio",
+        "$fuchsia_sdk_root/pkg:trace-engine",
+      ]
     } else {
       extra_deps += [
         "//zircon/public/lib/fbl",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index e22d8af..1369c7b 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("../../build/config/gclient_args.gni")
 import("../../build/dart/dart_action.gni")
+import("../../sdk_args.gni")
 import("../runtime_args.gni")
 import("../vm/compiler/compiler_sources.gni")
 import("../vm/heap/heap_sources.gni")
@@ -537,7 +538,11 @@
     isolate_snapshot_data,
     isolate_snapshot_instructions,
   ]
-  args = [
+  args = []
+  if (use_nnbd) {
+    args += [ "--enable-experiment=non-nullable" ]
+  }
+  args += [
     "--deterministic",
     "--snapshot_kind=" + dart_core_snapshot_kind,
     "--vm_snapshot_data=" + rebase_path(vm_snapshot_data, root_build_dir),
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 97fd635..d85f6f3 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -634,6 +634,15 @@
   Dart_Handle set_script_name =
       Dart_SetField(platform_type, script_name, dart_script);
   RETURN_IF_ERROR(set_script_name);
+
+  Dart_Handle network_profiling_type =
+      GetDartType(DartUtils::kIOLibURL, "_NetworkProfiling");
+  RETURN_IF_ERROR(network_profiling_type);
+  Dart_Handle result =
+      Dart_Invoke(network_profiling_type,
+                  NewString("_registerServiceExtension"), 0, nullptr);
+  RETURN_IF_ERROR(result);
+
   return Dart_Null();
 }
 
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index 82ac14a..f673f13 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -16,6 +16,9 @@
 #include <unistd.h>
 
 // Only OK to use here because this is test code.
+#include <condition_variable>  // NOLINT(build/c++11)
+#include <functional>          // NOLINT(build/c++11)
+#include <mutex>               // NOLINT(build/c++11)
 #include <thread>  // NOLINT(build/c++11)
 #endif
 
@@ -561,7 +564,7 @@
   Dart_ExecuteInternalCommand("gc-now", nullptr);
 }
 
-#if !defined(HOST_OS_WINDOWS) && !defined(TARGET_ARCH_DBC)
+#if !defined(HOST_OS_WINDOWS)
 DART_EXPORT void* UnprotectCodeOtherThread(void* isolate,
                                            std::condition_variable* var,
                                            std::mutex* mut) {
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index ea04e80..f6df0b9 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -113,10 +113,6 @@
   V(vm_snapshot_instructions, vm_snapshot_instructions_filename)               \
   V(isolate_snapshot_data, isolate_snapshot_data_filename)                     \
   V(isolate_snapshot_instructions, isolate_snapshot_instructions_filename)     \
-  V(shared_data, shared_data_filename)                                         \
-  V(shared_instructions, shared_instructions_filename)                         \
-  V(shared_blobs, shared_blobs_filename)                                       \
-  V(reused_instructions, reused_instructions_filename)                         \
   V(blobs_container_filename, blobs_container_filename)                        \
   V(assembly, assembly_filename)                                               \
   V(elf, elf_filename)                                                         \
@@ -171,17 +167,6 @@
 "--isolate_snapshot_data=<output-file>                                       \n"
 "<dart-kernel-file>                                                          \n"
 "                                                                            \n"
-"To create an AOT application snapshot as blobs suitable for loading with    \n"
-"mmap:                                                                       \n"
-"--snapshot_kind=app-aot-blobs                                               \n"
-"--vm_snapshot_data=<output-file>                                            \n"
-"--vm_snapshot_instructions=<output-file>                                    \n"
-"--isolate_snapshot_data=<output-file>                                       \n"
-"--isolate_snapshot_instructions=<output-file>                               \n"
-"[--obfuscate]                                                               \n"
-"[--save-obfuscation-map=<map-filename>]                                     \n"
-"<dart-kernel-file>                                                          \n"
-"                                                                            \n"
 "To create an AOT application snapshot as assembly suitable for compilation  \n"
 "as a static or dynamic library:                                             \n"
 "--snapshot_kind=app-aot-assembly                                            \n"
@@ -287,14 +272,12 @@
     case kAppJIT: {
       if ((load_vm_snapshot_data_filename == NULL) ||
           (isolate_snapshot_data_filename == NULL) ||
-          ((isolate_snapshot_instructions_filename == NULL) &&
-           (reused_instructions_filename == NULL))) {
+          (isolate_snapshot_instructions_filename == NULL)) {
         Syslog::PrintErr(
             "Building an app JIT snapshot requires specifying input files for "
             "--load_vm_snapshot_data and --load_vm_snapshot_instructions, an "
-            " output file for --isolate_snapshot_data, and either an output "
-            "file for --isolate_snapshot_instructions or an input file for "
-            "--reused_instructions.\n\n");
+            " output file for --isolate_snapshot_data, and an output "
+            "file for --isolate_snapshot_instructions.\n\n");
         return -1;
       }
       break;
@@ -582,15 +565,7 @@
 static void CreateAndWriteAppJITSnapshot() {
   ASSERT(snapshot_kind == kAppJIT);
   ASSERT(isolate_snapshot_data_filename != NULL);
-  ASSERT((isolate_snapshot_instructions_filename != NULL) ||
-         (reused_instructions_filename != NULL));
-
-  const uint8_t* reused_instructions = NULL;
-  std::unique_ptr<MappedMemory> mapped_reused_instructions;
-  if (reused_instructions_filename != NULL) {
-    mapped_reused_instructions = MapFile(reused_instructions_filename,
-                                         File::kReadOnly, &reused_instructions);
-  }
+  ASSERT(isolate_snapshot_instructions_filename != NULL);
 
   Dart_Handle result;
   uint8_t* isolate_snapshot_data_buffer = NULL;
@@ -601,16 +576,14 @@
   result = Dart_CreateAppJITSnapshotAsBlobs(
       &isolate_snapshot_data_buffer, &isolate_snapshot_data_size,
       &isolate_snapshot_instructions_buffer,
-      &isolate_snapshot_instructions_size, reused_instructions);
+      &isolate_snapshot_instructions_size);
   CHECK_RESULT(result);
 
   WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
             isolate_snapshot_data_size);
-  if (reused_instructions_filename == NULL) {
-    WriteFile(isolate_snapshot_instructions_filename,
-              isolate_snapshot_instructions_buffer,
-              isolate_snapshot_instructions_size);
-  }
+  WriteFile(isolate_snapshot_instructions_filename,
+            isolate_snapshot_instructions_buffer,
+            isolate_snapshot_instructions_size);
 }
 
 static void StreamingWriteCallback(void* callback_data,
@@ -651,34 +624,12 @@
         Dart_CreateAppAOTSnapshotAsElf(StreamingWriteCallback, file, strip);
     CHECK_RESULT(result);
   } else if (snapshot_kind == kAppAOTBlobs) {
-    const uint8_t* shared_data = NULL;
-    const uint8_t* shared_instructions = NULL;
-    std::unique_ptr<MappedMemory> mapped_shared_data;
-    std::unique_ptr<MappedMemory> mapped_shared_instructions;
-    if (shared_blobs_filename != NULL) {
-      AppSnapshot* shared_blobs = NULL;
-      Syslog::PrintErr("Shared blobs in gen_snapshot are for testing only.\n");
-      shared_blobs = Snapshot::TryReadAppSnapshot(shared_blobs_filename);
-      if (shared_blobs == NULL) {
-        Syslog::PrintErr("Failed to load: %s\n", shared_blobs_filename);
-        Dart_ExitScope();
-        Dart_ShutdownIsolate();
-        exit(kErrorExitCode);
-      }
-      const uint8_t* ignored;
-      shared_blobs->SetBuffers(&ignored, &ignored, &shared_data,
-                               &shared_instructions);
-    } else {
-      if (shared_data_filename != NULL) {
-        mapped_shared_data =
-            MapFile(shared_data_filename, File::kReadOnly, &shared_data);
-      }
-      if (shared_instructions_filename != NULL) {
-        mapped_shared_instructions =
-            MapFile(shared_instructions_filename, File::kReadOnly,
-                    &shared_instructions);
-      }
-    }
+    Syslog::PrintErr(
+        "WARNING: app-aot-blobs snapshots have been deprecated and support for "
+        "generating them will be removed soon. Please use the app-aot-elf or "
+        "app-aot-assembly snapshot kinds in conjunction with the portable ELF "
+        "loader from //runtime/bin:elf_loader if necessary. See "
+        "http://dartbug.com/38764 for more details.\n");
 
     uint8_t* vm_snapshot_data_buffer = NULL;
     intptr_t vm_snapshot_data_size = 0;
@@ -693,7 +644,7 @@
         &vm_snapshot_instructions_buffer, &vm_snapshot_instructions_size,
         &isolate_snapshot_data_buffer, &isolate_snapshot_data_size,
         &isolate_snapshot_instructions_buffer,
-        &isolate_snapshot_instructions_size, shared_data, shared_instructions);
+        &isolate_snapshot_instructions_size);
     CHECK_RESULT(result);
 
     if (blobs_container_filename != NULL) {
@@ -761,7 +712,7 @@
     loading_kernel_failed = (isolate == nullptr);
   } else {
     isolate = Dart_CreateIsolateGroup(NULL, NULL, isolate_snapshot_data,
-                                      isolate_snapshot_instructions, NULL, NULL,
+                                      isolate_snapshot_instructions,
                                       &isolate_flags, isolate_group_data.get(),
                                       /*isolate_data=*/nullptr, &error);
   }
diff --git a/runtime/bin/isolate_data.cc b/runtime/bin/isolate_data.cc
index d7cc5d5..3bf497c 100644
--- a/runtime/bin/isolate_data.cc
+++ b/runtime/bin/isolate_data.cc
@@ -17,7 +17,6 @@
     : script_url((url != NULL) ? strdup(url) : NULL),
       package_root(NULL),
       app_snapshot_(app_snapshot),
-      dependencies_(NULL),
       resolved_packages_config_(NULL),
       kernel_buffer_(NULL),
       kernel_buffer_size_(0),
@@ -41,7 +40,6 @@
   resolved_packages_config_ = NULL;
   kernel_buffer_ = NULL;
   kernel_buffer_size_ = 0;
-  delete dependencies_;
 }
 
 IsolateData::IsolateData(IsolateGroupData* isolate_group_data)
diff --git a/runtime/bin/isolate_data.h b/runtime/bin/isolate_data.h
index a6c13bf..c4523a1 100644
--- a/runtime/bin/isolate_data.h
+++ b/runtime/bin/isolate_data.h
@@ -88,11 +88,6 @@
     resolved_packages_config_ = strdup(packages_config);
   }
 
-  MallocGrowableArray<char*>* dependencies() const { return dependencies_; }
-  void set_dependencies(MallocGrowableArray<char*>* deps) {
-    dependencies_ = deps;
-  }
-
   bool RunFromAppSnapshot() const {
     // If the main isolate is using an app snapshot the [app_snapshot_] pointer
     // will be still nullptr (see main.cc:CreateIsolateGroupAndSetupHelper)
@@ -106,7 +101,6 @@
   friend class IsolateData;  // For packages_file_
 
   std::unique_ptr<AppSnapshot> app_snapshot_;
-  MallocGrowableArray<char*>* dependencies_;
   char* resolved_packages_config_;
   std::shared_ptr<uint8_t> kernel_buffer_;
   intptr_t kernel_buffer_size_;
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index f6a5bd6..c857127 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -26,8 +26,8 @@
 #endif
 
 // Keep in sync with loader.dart.
+static const intptr_t _Dart_kInitLoader = 4;
 static const intptr_t _Dart_kImportExtension = 9;
-static const intptr_t _Dart_kResolveAsFilePath = 10;
 
 Loader::Loader(IsolateData* isolate_data)
     : port_(ILLEGAL_PORT),
@@ -136,9 +136,6 @@
   Dart_Port loader_port = Builtin::LoadPort();
   ASSERT(loader_port != ILLEGAL_PORT);
 
-  // Keep in sync with loader.dart.
-  const intptr_t _Dart_kInitLoader = 4;
-
   Dart_Handle request = Dart_NewList(9);
   Dart_ListSetAt(request, 0, trace_loader ? Dart_True() : Dart_False());
   Dart_ListSetAt(request, 1, Dart_NewInteger(Dart_GetMainPortId()));
@@ -261,46 +258,6 @@
           (strstr(path, File::PathSeparator()) != NULL));
 }
 
-void Loader::AddDependencyLocked(Loader* loader, const char* resolved_uri) {
-  MallocGrowableArray<char*>* dependencies =
-      loader->isolate_group_data()->dependencies();
-  if (dependencies == NULL) {
-    return;
-  }
-  dependencies->Add(strdup(resolved_uri));
-}
-
-void Loader::ResolveDependenciesAsFilePaths() {
-  IsolateGroupData* isolate_group_data =
-      reinterpret_cast<IsolateGroupData*>(Dart_CurrentIsolateGroupData());
-  ASSERT(isolate_group_data != NULL);
-  MallocGrowableArray<char*>* dependencies = isolate_group_data->dependencies();
-  if (dependencies == NULL) {
-    return;
-  }
-
-  for (intptr_t i = 0; i < dependencies->length(); i++) {
-    char* resolved_uri = (*dependencies)[i];
-
-    uint8_t* file_path = NULL;
-    intptr_t file_path_length = -1;
-    Dart_Handle uri = Dart_NewStringFromCString(resolved_uri);
-    ASSERT(!Dart_IsError(uri));
-    Dart_Handle result =
-        Loader::ResolveAsFilePath(uri, &file_path, &file_path_length);
-    if (Dart_IsError(result)) {
-      Syslog::Print("Error resolving dependency: %s\n", Dart_GetError(result));
-      return;
-    }
-
-    // Convert buffer buffer to NUL-terminated string.
-    (*dependencies)[i] = Utils::StrNDup(
-        reinterpret_cast<const char*>(file_path), file_path_length);
-    free(file_path);
-    free(resolved_uri);
-  }
-}
-
 class ScopedDecompress : public ValueObject {
  public:
   ScopedDecompress(const uint8_t** payload, intptr_t* payload_length)
@@ -345,8 +302,6 @@
         Dart_NewStringFromCString(reinterpret_cast<char*>(result->library_uri));
   }
 
-  AddDependencyLocked(loader, result->resolved_uri);
-
   // A negative result tag indicates a loading error occurred in the service
   // isolate. The payload is a C string of the error message.
   if (result->tag < 0) {
@@ -354,8 +309,7 @@
     Dart_Handle error =
         Dart_NewStringFromUTF8(result->payload, result->payload_length);
     // If a library with the given uri exists, give it a chance to handle
-    // the error. If the load requests stems from a deferred library load,
-    // an IO error is not fatal.
+    // the error.
     if (LibraryHandleError(library, error)) {
       return true;
     }
@@ -423,23 +377,6 @@
   return false;
 }
 
-bool Loader::ProcessPayloadResultLocked(Loader* loader,
-                                        Loader::IOResult* result) {
-  // A negative result tag indicates a loading error occurred in the service
-  // isolate. The payload is a C string of the error message.
-  if (result->tag < 0) {
-    Dart_Handle error =
-        Dart_NewStringFromUTF8(result->payload, result->payload_length);
-    loader->error_ = Dart_NewUnhandledExceptionError(error);
-    return false;
-  }
-  loader->payload_length_ = result->payload_length;
-  loader->payload_ =
-      reinterpret_cast<uint8_t*>(::malloc(loader->payload_length_));
-  memmove(loader->payload_, result->payload, loader->payload_length_);
-  return true;
-}
-
 bool Loader::ProcessQueueLocked(ProcessResult process_result) {
   bool hit_error = false;
   for (intptr_t i = 0; i < results_length(); i++) {
@@ -512,59 +449,6 @@
   return Dart_True();
 }
 
-Dart_Handle Loader::SendAndProcessReply(intptr_t tag,
-                                        Dart_Handle url,
-                                        uint8_t** payload,
-                                        intptr_t* payload_length) {
-  auto isolate_data = reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
-  ASSERT(isolate_data != NULL);
-  ASSERT(!isolate_data->HasLoader());
-  Loader* loader = NULL;
-
-  // Setup the loader. The constructor does a bunch of leg work.
-  loader = new Loader(isolate_data);
-  loader->Init(isolate_data->isolate_group_data()->package_root,
-               isolate_data->packages_file(),
-               DartUtils::original_working_directory, NULL);
-  ASSERT(loader != NULL);
-  ASSERT(isolate_data->HasLoader());
-
-  // Now send a load request to the service isolate.
-  loader->SendRequest(tag, url, Dart_Null());
-
-  // Wait for a reply to the load request.
-  loader->BlockUntilComplete(ProcessPayloadResultLocked);
-
-  // Copy fields from the loader before deleting it.
-  // The payload array itself which was malloced above is freed by
-  // the caller of LoadUrlContents.
-  Dart_Handle error = loader->error();
-  *payload = loader->payload_;
-  *payload_length = loader->payload_length_;
-
-  // Destroy the loader. The destructor does a bunch of leg work.
-  delete loader;
-
-  // An error occurred during loading.
-  if (!Dart_IsNull(error)) {
-    return error;
-  }
-  return Dart_Null();
-}
-
-Dart_Handle Loader::LoadUrlContents(Dart_Handle url,
-                                    uint8_t** payload,
-                                    intptr_t* payload_length) {
-  return SendAndProcessReply(Dart_kScriptTag, url, payload, payload_length);
-}
-
-Dart_Handle Loader::ResolveAsFilePath(Dart_Handle url,
-                                      uint8_t** payload,
-                                      intptr_t* payload_length) {
-  return SendAndProcessReply(_Dart_kResolveAsFilePath, url, payload,
-                             payload_length);
-}
-
 IsolateGroupData* Loader::isolate_group_data() {
   return isolate_data_->isolate_group_data();
 }
@@ -575,14 +459,6 @@
                                       Dart_Handle url) {
   return Dart_Null();
 }
-
-Dart_Handle Loader::DartColonLibraryTagHandler(Dart_LibraryTag tag,
-                                               Dart_Handle library,
-                                               Dart_Handle url,
-                                               const char* library_url_string,
-                                               const char* url_string) {
-  return Dart_Null();
-}
 #else
 static void MallocFinalizer(void* isolate_callback_data,
                             Dart_WeakPersistentHandle handle,
@@ -593,18 +469,28 @@
 Dart_Handle Loader::LibraryTagHandler(Dart_LibraryTag tag,
                                       Dart_Handle library,
                                       Dart_Handle url) {
+  const char* url_string = NULL;
+  Dart_Handle result = Dart_StringToCString(url, &url_string);
+  if (Dart_IsError(result)) {
+    return result;
+  }
   if (tag == Dart_kCanonicalizeUrl) {
     Dart_Handle library_url = Dart_LibraryUrl(library);
     if (Dart_IsError(library_url)) {
       return library_url;
     }
+    const char* library_url_string = NULL;
+    result = Dart_StringToCString(library_url, &library_url_string);
+    if (Dart_IsError(result)) {
+      return result;
+    }
+    bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
+    bool is_dart_library = DartUtils::IsDartSchemeURL(library_url_string);
+    if (is_dart_scheme_url || is_dart_library) {
+      return url;
+    }
     return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
-  const char* url_string = NULL;
-  Dart_Handle result = Dart_StringToCString(url, &url_string);
-  if (Dart_IsError(result)) {
-    return result;
-  }
   if (tag == Dart_kKernelTag) {
     uint8_t* kernel_buffer = NULL;
     intptr_t kernel_buffer_size = 0;
@@ -650,27 +536,6 @@
     free(lib_path);
     return result;
   }
-  if (tag != Dart_kScriptTag) {
-    // Special case for handling dart: imports and parts.
-    // Grab the library's url.
-    Dart_Handle library_url = Dart_LibraryUrl(library);
-    if (Dart_IsError(library_url)) {
-      return library_url;
-    }
-    const char* library_url_string = NULL;
-    result = Dart_StringToCString(library_url, &library_url_string);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-
-    bool is_dart_scheme_url = DartUtils::IsDartSchemeURL(url_string);
-    bool is_dart_library = DartUtils::IsDartSchemeURL(library_url_string);
-
-    if (is_dart_scheme_url || is_dart_library) {
-      return DartColonLibraryTagHandler(tag, library, url, library_url_string,
-                                        url_string);
-    }
-  }
   if (DartUtils::IsDartExtensionSchemeURL(url_string)) {
     // Handle early error cases for dart-ext: imports.
     if (tag != Dart_kImportTag) {
@@ -685,25 +550,10 @@
 
   auto isolate_data = reinterpret_cast<IsolateData*>(Dart_CurrentIsolateData());
   ASSERT(isolate_data != NULL);
-  if ((tag == Dart_kScriptTag) && Dart_IsString(library)) {
-    // Update packages file for isolate.
-    const char* packages_file = NULL;
-    Dart_Handle result = Dart_StringToCString(library, &packages_file);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-    isolate_data->UpdatePackagesFile(packages_file);
-  }
+
   // Grab this isolate's loader.
   Loader* loader = NULL;
 
-  // The outer invocation of the tag handler for this isolate. We make the outer
-  // invocation block and allow any nested invocations to operate in parallel.
-  const bool blocking_call = !isolate_data->HasLoader();
-
-  // If we are the outer invocation of the tag handler and the tag is an import
-  // this means that we are starting a deferred library load.
-  const bool is_deferred_import = blocking_call && (tag == Dart_kImportTag);
   if (!isolate_data->HasLoader()) {
     // The isolate doesn't have a loader -- this is the outer invocation which
     // will block.
@@ -712,10 +562,8 @@
     loader = new Loader(isolate_data);
     loader->Init(isolate_data->isolate_group_data()->package_root,
                  isolate_data->packages_file(),
-                 DartUtils::original_working_directory,
-                 (tag == Dart_kScriptTag) ? url_string : NULL);
+                 DartUtils::original_working_directory, NULL);
   } else {
-    ASSERT(tag != Dart_kScriptTag);
     // The isolate has a loader -- this is an inner invocation that will queue
     // work with the service isolate.
     // Use the existing loader.
@@ -754,58 +602,26 @@
     }
   }
 
-  if (blocking_call) {
-    // The outer invocation of the tag handler will block here until all nested
-    // invocations complete.
-    loader->BlockUntilComplete(ProcessResultLocked);
+  // The outer invocation of the tag handler will block here until all nested
+  // invocations complete.
+  loader->BlockUntilComplete(ProcessResultLocked);
 
-    // Remember the error (if any).
-    Dart_Handle error = loader->error();
-    // Destroy the loader. The destructor does a bunch of leg work.
-    delete loader;
+  // Remember the error (if any).
+  Dart_Handle error = loader->error();
+  // Destroy the loader. The destructor does a bunch of leg work.
+  delete loader;
 
-    // An error occurred during loading.
-    if (!Dart_IsNull(error)) {
-      if (false && is_deferred_import) {
-        // This blocks handles transitive load errors caused by a deferred
-        // import. Non-transitive load errors are handled above (see callers of
-        // |LibraryHandleError|). To handle the transitive case, we give the
-        // originating deferred library an opportunity to handle it.
-        Dart_Handle deferred_library = Dart_LookupLibrary(url);
-        if (!LibraryHandleError(deferred_library, error)) {
-          // Library did not handle it, return to caller as an unhandled
-          // exception.
-          return Dart_NewUnhandledExceptionError(error);
-        }
-      } else {
-        // We got an error during loading but we aren't loading a deferred
-        // library, return the error to the caller.
-        return error;
-      }
-    }
-
-    // Finalize loading. This will complete any futures for completed deferred
-    // loads.
-    error = Dart_FinalizeLoading(true);
-    if (Dart_IsError(error)) {
-      return error;
-    }
+  // An error occurred during loading.
+  if (!Dart_IsNull(error)) {
+    // We got an error during loading, return the error to the caller.
+    return error;
   }
-  return Dart_Null();
-}
 
-Dart_Handle Loader::DartColonLibraryTagHandler(Dart_LibraryTag tag,
-                                               Dart_Handle library,
-                                               Dart_Handle url,
-                                               const char* library_url_string,
-                                               const char* url_string) {
-  // Handle canonicalization, 'import' and 'part' of 'dart:' libraries.
-  if (tag == Dart_kCanonicalizeUrl) {
-    // These will be handled internally.
-    return url;
+  // Finalize loading.
+  error = Dart_FinalizeLoading(true);
+  if (Dart_IsError(error)) {
+    return error;
   }
-  // All cases should have been handled above.
-  UNREACHABLE();
   return Dart_Null();
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/bin/loader.h b/runtime/bin/loader.h
index dc436c5..54af63f 100644
--- a/runtime/bin/loader.h
+++ b/runtime/bin/loader.h
@@ -25,13 +25,6 @@
 
   static Dart_Handle ReloadNativeExtensions();
 
-  // Loads contents of the specified url.
-  static Dart_Handle LoadUrlContents(Dart_Handle url,
-                                     uint8_t** payload,
-                                     intptr_t* payload_length);
-
-  static void ResolveDependenciesAsFilePaths();
-
   // A static tag handler that hides all usage of a loader for an isolate.
   static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
                                        Dart_Handle library,
@@ -95,40 +88,18 @@
   // Send a request from the tag handler to the service isolate.
   void SendRequest(intptr_t tag, Dart_Handle url, Dart_Handle library_url);
 
-  static Dart_Handle SendAndProcessReply(intptr_t tag,
-                                         Dart_Handle url,
-                                         uint8_t** payload,
-                                         intptr_t* payload_length);
-
-  static Dart_Handle ResolveAsFilePath(Dart_Handle url,
-                                       uint8_t** payload,
-                                       intptr_t* payload_length);
-
   /// Queue |message| and notify the loader that a message is available.
   void QueueMessage(Dart_CObject* message);
 
   /// Blocks the caller until the loader is finished.
   void BlockUntilComplete(ProcessResult process_result);
 
-  /// Saves a script dependency when applicable.
-  static void AddDependencyLocked(Loader* loader, const char* resolved_uri);
-
   /// Returns false if |result| is an error and the loader should quit.
   static bool ProcessResultLocked(Loader* loader, IOResult* result);
 
-  /// Returns false if |result| is an error and the loader should quit.
-  static bool ProcessPayloadResultLocked(Loader* loader, IOResult* result);
-
   /// Returns false if an error occurred and the loader should quit.
   bool ProcessQueueLocked(ProcessResult process_result);
 
-  // Special inner tag handler for dart: uris.
-  static Dart_Handle DartColonLibraryTagHandler(Dart_LibraryTag tag,
-                                                Dart_Handle library,
-                                                Dart_Handle url,
-                                                const char* library_url_string,
-                                                const char* url_string);
-
   // We use one native message handler callback for N loaders. The native
   // message handler callback provides us with the Dart_Port which we use as a
   // key into our map of active loaders from |port| to |isolate_data|.
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 8e76803..8af1215 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -75,8 +75,6 @@
 static char* app_script_uri = NULL;
 static const uint8_t* app_isolate_snapshot_data = NULL;
 static const uint8_t* app_isolate_snapshot_instructions = NULL;
-static const uint8_t* app_isolate_shared_data = NULL;
-static const uint8_t* app_isolate_shared_instructions = NULL;
 static bool kernel_isolate_is_running = false;
 
 static Dart_Isolate main_isolate = NULL;
@@ -131,12 +129,6 @@
   if (Options::depfile() == NULL) {
     return;
   }
-  Loader::ResolveDependenciesAsFilePaths();
-  auto isolate_group_data =
-      reinterpret_cast<IsolateGroupData*>(Dart_IsolateGroupData(isolate));
-  ASSERT(isolate_group_data != NULL);
-  MallocGrowableArray<char*>* dependencies = isolate_group_data->dependencies();
-  ASSERT(dependencies != NULL);
   File* file =
       File::Open(NULL, Options::depfile(), File::kWriteTruncate);
   if (file == NULL) {
@@ -149,11 +141,6 @@
   } else {
     success &= file->Print("%s: ", Options::depfile_output_filename());
   }
-  for (intptr_t i = 0; i < dependencies->length(); i++) {
-    char* dep = dependencies->At(i);
-    success &= file->Print("%s ", dep);
-    free(dep);
-  }
   if (kernel_isolate_is_running) {
     Dart_KernelCompilationResult result = Dart_KernelListDependencies();
     if (result.status != Dart_KernelCompilationStatus_Ok) {
@@ -171,7 +158,6 @@
               Options::depfile());
   }
   file->Release();
-  dependencies->Clear();
 }
 
 static void OnExitHook(int64_t exit_code) {
@@ -408,11 +394,7 @@
     Dart_Handle uri =
         DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri));
     CHECK_RESULT(uri);
-    if (kernel_buffer == NULL) {
-      result = Loader::LibraryTagHandler(Dart_kScriptTag, Dart_Null(), uri);
-      CHECK_RESULT(result);
-    } else {
-      // Various core-library parts will send requests to the Loader to resolve
+    if (kernel_buffer != NULL) {
       // relative URIs and perform other related tasks. We need Loader to be
       // initialized for this to work because loading from Kernel binary
       // bypasses normal source code loading paths that initialize it.
@@ -421,7 +403,6 @@
       CHECK_RESULT(result);
       Loader::InitForSnapshot(resolved_script_uri, isolate_data);
     }
-
     Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),
                        Dart_GetMainPortId(), Dart_Timeline_Event_Async_End, 0,
                        NULL, NULL);
@@ -504,8 +485,7 @@
     isolate_data = new IsolateData(isolate_group_data);
     isolate = Dart_CreateIsolateGroup(
         DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
-        isolate_snapshot_data, isolate_snapshot_instructions,
-        app_isolate_shared_data, app_isolate_shared_instructions, flags,
+        isolate_snapshot_data, isolate_snapshot_instructions, flags,
         isolate_group_data, isolate_data, error);
   }
   if (isolate == NULL) {
@@ -565,8 +545,7 @@
       app_isolate_snapshot_instructions;
   isolate = Dart_CreateIsolateGroup(
       script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
-      isolate_snapshot_instructions, app_isolate_shared_data,
-      app_isolate_shared_instructions, flags, isolate_group_data,
+      isolate_snapshot_instructions, flags, isolate_group_data,
       /*isolate_data=*/nullptr, error);
 #else
   // JIT: Service isolate uses the core libraries snapshot.
@@ -579,8 +558,7 @@
       core_isolate_snapshot_instructions;
   isolate = Dart_CreateIsolateGroup(
       script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data,
-      isolate_snapshot_instructions, app_isolate_shared_data,
-      app_isolate_shared_instructions, flags, isolate_group_data,
+      isolate_snapshot_instructions, flags, isolate_group_data,
       /*isolate_data=*/nullptr, error);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   if (isolate == NULL) {
@@ -687,9 +665,6 @@
                                                     kernel_buffer_size);
     }
   }
-  if (is_main_isolate && (Options::depfile() != NULL)) {
-    isolate_group_data->set_dependencies(new MallocGrowableArray<char*>());
-  }
 
   Dart_Isolate isolate = NULL;
 
@@ -720,17 +695,15 @@
         flags, isolate_group_data, isolate_data, error);
   } else {
     auto isolate_data = new IsolateData(isolate_group_data);
-    isolate = Dart_CreateIsolateGroup(
-        script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions,
-        app_isolate_shared_data, app_isolate_shared_instructions, flags,
-        isolate_group_data, isolate_data, error);
+    isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
+                                      isolate_snapshot_instructions, flags,
+                                      isolate_group_data, isolate_data, error);
   }
 #else
   auto isolate_data = new IsolateData(isolate_group_data);
-  isolate = Dart_CreateIsolateGroup(
-      script_uri, name, isolate_snapshot_data, isolate_snapshot_instructions,
-      app_isolate_shared_data, app_isolate_shared_instructions, flags,
-      isolate_group_data, isolate_data, error);
+  isolate = Dart_CreateIsolateGroup(script_uri, name, isolate_snapshot_data,
+                                    isolate_snapshot_instructions, flags,
+                                    isolate_group_data, isolate_data, error);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   Dart_Isolate created_isolate = NULL;
@@ -1143,21 +1116,6 @@
 
   Loader::InitOnce();
 
-  AppSnapshot* shared_blobs = NULL;
-  if (Options::shared_blobs_filename() != NULL) {
-    Syslog::PrintErr(
-        "Shared blobs in the standalone VM are for testing only.\n");
-    shared_blobs =
-        Snapshot::TryReadAppSnapshot(Options::shared_blobs_filename());
-    if (shared_blobs == NULL) {
-      Syslog::PrintErr("Failed to load: %s\n",
-                       Options::shared_blobs_filename());
-      Platform::Exit(kErrorExitCode);
-    }
-    const uint8_t* ignored;
-    shared_blobs->SetBuffers(&ignored, &ignored, &app_isolate_shared_data,
-                             &app_isolate_shared_instructions);
-  }
   if (app_snapshot == nullptr) {
     app_snapshot = Snapshot::TryReadAppSnapshot(script_name);
   }
@@ -1265,7 +1223,6 @@
   EventHandler::Stop();
 
   delete app_snapshot;
-  delete shared_blobs;
   free(app_script_uri);
 
   // Free copied argument strings if converted.
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 24626af..3021307 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -207,8 +207,7 @@
                                   app_snapshot, app_snapshot != nullptr);
     isolate = Dart_CreateIsolateGroup(
         DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME,
-        isolate_snapshot_data, isolate_snapshot_instructions,
-        /*shared_data=*/nullptr, /*shared_instructions=*/nullptr, flags,
+        isolate_snapshot_data, isolate_snapshot_instructions, flags,
         isolate_group_data, /*isolate_data=*/nullptr, error);
     if (*error != nullptr) {
       OS::PrintErr("Error creating isolate group: %s\n", *error);
diff --git a/runtime/bin/secure_socket_utils.h b/runtime/bin/secure_socket_utils.h
index 43ba93a..ddbd2b6 100644
--- a/runtime/bin/secure_socket_utils.h
+++ b/runtime/bin/secure_socket_utils.h
@@ -102,6 +102,9 @@
     return bio_;
   }
 
+  uint8_t* data() { return bytes_; }
+  intptr_t length() { return bytes_len_; }
+
  private:
   Dart_Handle object_;
   uint8_t* bytes_;
diff --git a/runtime/bin/security_context.cc b/runtime/bin/security_context.cc
index 983e5e2..5d649df 100644
--- a/runtime/bin/security_context.cc
+++ b/runtime/bin/security_context.cc
@@ -165,30 +165,19 @@
 }
 
 static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context,
-                                             BIO* bio,
+                                             ScopedMemBIO* bio,
                                              const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
+  CBS cbs;
+  CBS_init(&cbs, bio->data(), bio->length());
 
   EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  ScopedX509Stack cert_stack(sk_X509_new_null());
+  int status = PKCS12_get_key_and_certs(&key, cert_stack.get(), &cbs, password);
   if (status == 0) {
     return status;
   }
 
-  ScopedX509Stack cert_stack(ca_certs);
   X509_STORE* store = SSL_CTX_get_cert_store(context);
-  status = X509_STORE_add_cert(store, cert);
-  // X509_STORE_add_cert increments the reference count of cert on success.
-  X509_free(cert);
-  if (status == 0) {
-    return status;
-  }
-
   X509* ca;
   while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
     status = X509_STORE_add_cert(store, ca);
@@ -234,8 +223,7 @@
       if (SecureSocketUtils::NoPEMStartLine()) {
         ERR_clear_error();
         BIO_reset(bio.bio());
-        status =
-            SetTrustedCertificatesBytesPKCS12(context(), bio.bio(), password);
+        status = SetTrustedCertificatesBytesPKCS12(context(), &bio, password);
       }
     } else {
       // The PEM file was successfully parsed.
@@ -247,25 +235,14 @@
 }
 
 static int SetClientAuthoritiesPKCS12(SSL_CTX* context,
-                                      BIO* bio,
+                                      ScopedMemBIO* bio,
                                       const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
+  CBS cbs;
+  CBS_init(&cbs, bio->data(), bio->length());
 
   EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
-  if (status == 0) {
-    return status;
-  }
-
-  ScopedX509Stack cert_stack(ca_certs);
-  status = SSL_CTX_add_client_CA(context, cert);
-  // SSL_CTX_add_client_CA increments the reference count of cert on success.
-  X509_free(cert);
+  ScopedX509Stack cert_stack(sk_X509_new_null());
+  int status = PKCS12_get_key_and_certs(&key, cert_stack.get(), &cbs, password);
   if (status == 0) {
     return status;
   }
@@ -297,13 +274,13 @@
 }
 
 static int SetClientAuthorities(SSL_CTX* context,
-                                BIO* bio,
+                                ScopedMemBIO* bio,
                                 const char* password) {
-  int status = SetClientAuthoritiesPEM(context, bio);
+  int status = SetClientAuthoritiesPEM(context, bio->bio());
   if (status == 0) {
     if (SecureSocketUtils::NoPEMStartLine()) {
       ERR_clear_error();
-      BIO_reset(bio);
+      BIO_reset(bio->bio());
       status = SetClientAuthoritiesPKCS12(context, bio, password);
     }
   } else {
@@ -319,7 +296,7 @@
   int status;
   {
     ScopedMemBIO bio(client_authorities_bytes);
-    status = SetClientAuthorities(context(), bio.bio(), password);
+    status = SetClientAuthorities(context(), &bio, password);
   }
 
   SecureSocketUtils::CheckStatus(status, "TlsException",
@@ -543,35 +520,31 @@
 }
 
 static int UseChainBytesPKCS12(SSL_CTX* context,
-                               BIO* bio,
+                               ScopedMemBIO* bio,
                                const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
+  CBS cbs;
+  CBS_init(&cbs, bio->data(), bio->length());
 
   EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  ScopedX509Stack certs(sk_X509_new_null());
+  int status = PKCS12_get_key_and_certs(&key, certs.get(), &cbs, password);
   if (status == 0) {
     return status;
   }
 
-  ScopedX509 x509(cert);
-  ScopedX509Stack certs(ca_certs);
-  status = SSL_CTX_use_certificate(context, x509.get());
+  X509* ca = sk_X509_shift(certs.get());
+  status = SSL_CTX_use_certificate(context, ca);
   if (ERR_peek_error() != 0) {
     // Key/certificate mismatch doesn't imply status is 0.
     status = 0;
   }
+  X509_free(ca);
   if (status == 0) {
     return status;
   }
 
   SSL_CTX_clear_chain_certs(context);
 
-  X509* ca;
   while ((ca = sk_X509_shift(certs.get())) != NULL) {
     status = SSL_CTX_add0_chain_cert(context, ca);
     // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
@@ -620,12 +593,14 @@
   return SecureSocketUtils::NoPEMStartLine() ? status : 0;
 }
 
-static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) {
-  int status = UseChainBytesPEM(context, bio);
+static int UseChainBytes(SSL_CTX* context,
+                         ScopedMemBIO* bio,
+                         const char* password) {
+  int status = UseChainBytesPEM(context, bio->bio());
   if (status == 0) {
     if (SecureSocketUtils::NoPEMStartLine()) {
       ERR_clear_error();
-      BIO_reset(bio);
+      BIO_reset(bio->bio());
       status = UseChainBytesPKCS12(context, bio, password);
     }
   } else {
@@ -638,7 +613,7 @@
 int SSLCertContext::UseCertificateChainBytes(Dart_Handle cert_chain_bytes,
                                              const char* password) {
   ScopedMemBIO bio(cert_chain_bytes);
-  return UseChainBytes(context(), bio.bio(), password);
+  return UseChainBytes(context(), &bio, password);
 }
 
 static X509* GetX509Certificate(Dart_NativeArguments args) {
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index 024f1ad..e0d94db 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -9,6 +9,7 @@
 
 #include "bin/security_context.h"
 
+#include <Availability.h>
 #include <CoreFoundation/CoreFoundation.h>
 #include <Security/SecureTransport.h>
 #include <Security/Security.h>
@@ -183,9 +184,25 @@
     return ctx->verify_cb(0, ctx);
   }
 
-  // Perform the certificate verification.
   SecTrustResultType trust_result;
+
+  // Perform the certificate verification.
+#if ((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && defined(__MAC_10_14_0) &&    \
+      __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_14_0) ||                     \
+     (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_12_0) &&   \
+      _IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_12_0))
+  // SecTrustEvaluateWithError available as of OSX 10.14 and iOS 12.
+  // The result is ignored as we get more information from the following call to
+  // SecTrustGetTrustResult which also happens to match the information we get from calling
+  // SecTrustEvaluate.
+  bool res = SecTrustEvaluateWithError(trust.get(), NULL);
+  USE(res);
+  status = SecTrustGetTrustResult(trust.get(), &trust_result);
+#else
+  // SecTrustEvaluate is deprecated as of OSX 10.15 and iOS 13.
   status = SecTrustEvaluate(trust.get(), &trust_result);
+#endif
+
   if (status != noErr) {
     return ctx->verify_cb(0, ctx);
   }
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 4e554cf..3a6828a 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -476,7 +476,7 @@
   intptr_t isolate_instructions_size = 0;
   Dart_Handle result = Dart_CreateAppJITSnapshotAsBlobs(
       &isolate_data_buffer, &isolate_data_size, &isolate_instructions_buffer,
-      &isolate_instructions_size, NULL);
+      &isolate_instructions_size);
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
@@ -486,9 +486,7 @@
 #endif
 }
 
-void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename,
-                                     const uint8_t* shared_data,
-                                     const uint8_t* shared_instructions) {
+void Snapshot::GenerateAppAOTAsBlobs(const char* snapshot_filename) {
   uint8_t* vm_data_buffer = NULL;
   intptr_t vm_data_size = 0;
   uint8_t* vm_instructions_buffer = NULL;
@@ -500,8 +498,7 @@
   Dart_Handle result = Dart_CreateAppAOTSnapshotAsBlobs(
       &vm_data_buffer, &vm_data_size, &vm_instructions_buffer,
       &vm_instructions_size, &isolate_data_buffer, &isolate_data_size,
-      &isolate_instructions_buffer, &isolate_instructions_size, shared_data,
-      shared_instructions);
+      &isolate_instructions_buffer, &isolate_instructions_size);
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 4fa221c..83ed202 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -32,9 +32,7 @@
                              const char* script_name,
                              const char* package_config);
   static void GenerateAppJIT(const char* snapshot_filename);
-  static void GenerateAppAOTAsBlobs(const char* snapshot_filename,
-                                    const uint8_t* shared_data,
-                                    const uint8_t* shared_instructions);
+  static void GenerateAppAOTAsBlobs(const char* snapshot_filename);
   static void GenerateAppAOTAsAssembly(const char* snapshot_filename);
 
   static AppSnapshot* TryReadAppendedAppSnapshotElf(const char* container_path);
diff --git a/runtime/bin/socket.cc b/runtime/bin/socket.cc
index 33f6907..019b33c 100644
--- a/runtime/bin/socket.cc
+++ b/runtime/bin/socket.cc
@@ -974,7 +974,7 @@
       Dart_SetIntegerReturnValue(args, IP_MULTICAST_IF);
       break;
     case DART_IPPROTO_IPV6:
-      Dart_SetIntegerReturnValue(args, DART_IPPROTO_IPV6);
+      Dart_SetIntegerReturnValue(args, IPPROTO_IPV6);
       break;
     case DART_IPV6_MULTICAST_IF:
       Dart_SetIntegerReturnValue(args, IPV6_MULTICAST_IF);
diff --git a/runtime/bin/thread_android.cc b/runtime/bin/thread_android.cc
index 2bef99c..28b47ad 100644
--- a/runtime/bin/thread_android.cc
+++ b/runtime/bin/thread_android.cc
@@ -154,7 +154,7 @@
 }
 
 intptr_t Thread::ThreadIdToIntPtr(ThreadId id) {
-  ASSERT(sizeof(id) == sizeof(intptr_t));
+  ASSERT(sizeof(id) <= sizeof(intptr_t));
   return static_cast<intptr_t>(id);
 }
 
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index 6f03a08..a450179 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.dart
@@ -952,9 +952,6 @@
 
 // See Dart_LibraryTag in dart_api.h
 const _Dart_kCanonicalizeUrl = 0; // Canonicalize the URL.
-const _Dart_kScriptTag = 1; // Load the root script.
-const _Dart_kSourceTag = 2; // Load a part source.
-const _Dart_kImportTag = 3; // Import a library.
 
 // Extra requests. Keep these in sync between loader.dart and builtin.dart.
 const _Dart_kInitLoader = 4; // Initialize the loader.
@@ -965,7 +962,6 @@
 
 // Extra requests. Keep these in sync between loader.dart and loader.cc.
 const _Dart_kImportExtension = 9; // Import a dart-ext: file.
-const _Dart_kResolveAsFilePath = 10; // Resolve uri to file path.
 
 // External entry point for loader requests.
 _processLoadRequest(request) {
@@ -1094,38 +1090,6 @@
           break;
       }
       break;
-    case _Dart_kResolveAsFilePath:
-      loaderState._triggerPackageResolution(() {
-        String uri = request[4];
-        Uri resolvedUri = Uri.parse(_sanitizeWindowsPath(uri));
-        try {
-          if (resolvedUri.scheme == 'package') {
-            resolvedUri = loaderState._resolvePackageUri(resolvedUri);
-          }
-          if (resolvedUri.scheme == '' || resolvedUri.scheme == 'file') {
-            resolvedUri = loaderState._workingDirectory.resolveUri(resolvedUri);
-            var msg = new List(5);
-            msg[0] = tag;
-            msg[1] = uri;
-            msg[2] = resolvedUri.toString();
-            msg[3] = null;
-            msg[4] = resolvedUri.toFilePath();
-            sp.send(msg);
-          } else {
-            throw "Cannot resolve scheme (${resolvedUri.scheme}) to file path"
-                " for $resolvedUri";
-          }
-        } catch (e) {
-          var msg = new List(5);
-          msg[0] = -tag;
-          msg[1] = uri;
-          msg[2] = resolvedUri.toString();
-          msg[3] = null;
-          msg[4] = e.toString();
-          sp.send(msg);
-        }
-      });
-      break;
     default:
       _log('Unknown loader request tag=$tag from $isolateId');
   }
diff --git a/runtime/docs/aot_binary_size_analysis.md b/runtime/docs/aot_binary_size_analysis.md
index fafb16a..71e66fc 100644
--- a/runtime/docs/aot_binary_size_analysis.md
+++ b/runtime/docs/aot_binary_size_analysis.md
@@ -28,3 +28,17 @@
 % chrome hello_sizes/index.html
 ```
 
+
+## Comparing the sizes of two AOT builds
+
+To visualize the differences between two AOT builds one can use our binary size
+comparison tool:
+
+```
+% dart pkg/vm/bin/compare_sizes.dart app-sizes--before.json app-sizes--after.json
+
++---------+--------+--------------+
+| Library | Method | Diff (Bytes) |
++---------+--------+--------------+
+...
+```
diff --git a/runtime/docs/compiler/exceptions.md b/runtime/docs/compiler/exceptions.md
index 222e5f8..6dd211d 100644
--- a/runtime/docs/compiler/exceptions.md
+++ b/runtime/docs/compiler/exceptions.md
@@ -81,12 +81,4 @@
 Constructing `CatchEntryMoves` dynamically from deoptimization instructions
 allows to avoid unnecessary duplication of the metadata and save memory: as
 deoptimization environments contain all information necessary for constructing
-correct stack state.
-
-IMPORTANT: There is a subtle difference between DBC and other architectures with
-respect to catch block entry state. On normal architectures `Parameter(i)` at
-catch entry would be associated with the same stack space that would be used to
-store variable with index `i`. On DBC however at catch entry `Parameter(i)`
-would be allocated to a separate scratch space at the very top of the register
-space. See `FlowGraphAllocator::ProcessInitialDefinition` and
-`FlowGraphCompiler::CatchEntryRegForVariable`.
+correct stack state.
\ No newline at end of file
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 0306c3b..6dbd703 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -908,8 +908,6 @@
                         const char* name,
                         const uint8_t* isolate_snapshot_data,
                         const uint8_t* isolate_snapshot_instructions,
-                        const uint8_t* shared_data,
-                        const uint8_t* shared_instructions,
                         Dart_IsolateFlags* flags,
                         void* isolate_group_data,
                         void* isolate_data,
@@ -2908,8 +2906,6 @@
 
 typedef enum {
   Dart_kCanonicalizeUrl = 0,
-  Dart_kScriptTag,
-  Dart_kSourceTag,
   Dart_kImportTag,
   Dart_kKernelTag,
   Dart_kImportExtensionTag,
@@ -2930,14 +2926,6 @@
  * of this tag.  The return value should be a string holding the
  * canonicalized url.
  *
- * Dart_kScriptTag
- *
- * No longer used.
- *
- * Dart_kSourceTag
- *
- * No longer used.
- *
  * Dart_kImportTag
  *
  * This tag is used to load a library from IsolateMirror.loadUri. The embedder
@@ -3443,6 +3431,10 @@
  *  provided directly as bytes that the embedder can load with mmap. The
  *  instructions pieces must be loaded with read and execute permissions; the
  *  other pieces may be loaded as read-only.
+ *
+ *  This function has been DEPRECATED. Please use Dart_CreateAppAOTSnapshotAsELF
+ *  or Dart_CreateAppAOTSnapshotAsAssembly instead. A portable ELF loader is
+ *  available in the target //runtime/bin:elf_loader.
  */
 DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
 Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer,
@@ -3452,9 +3444,7 @@
                                  uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size,
-                                 const uint8_t* shared_data,
-                                 const uint8_t* shared_instructions);
+                                 intptr_t* isolate_snapshot_instructions_size);
 
 /**
  * Sorts the class-ids in depth first traversal order of the inheritance
@@ -3475,7 +3465,7 @@
  *  permissions; the data piece may be loaded as read-only.
  *
  *   - Requires the VM to have not been started with --precompilation.
- *   - Not supported when targeting IA32 or DBC.
+ *   - Not supported when targeting IA32.
  *   - The VM writing the snapshot and the VM reading the snapshot must be the
  *     same version, must be built in the same DEBUG/RELEASE/PRODUCT mode, must
  *     be targeting the same architecture, and must both be in checked mode or
@@ -3490,8 +3480,7 @@
 Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size,
-                                 const uint8_t* reused_instructions);
+                                 intptr_t* isolate_snapshot_instructions_size);
 
 /**
  * Like Dart_CreateAppJITSnapshotAsBlobs, but also creates a new VM snapshot.
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index eb1ee94..355d1e3 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -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.
 
-#include "lib/ffi.h"
-
 #include "include/dart_api.h"
 #include "platform/globals.h"
 #include "vm/bootstrap_natives.h"
@@ -421,10 +419,7 @@
 }
 
 DEFINE_NATIVE_ENTRY(Ffi_nativeCallbackFunction, 1, 2) {
-#if defined(TARGET_ARCH_DBC)
-  Exceptions::ThrowUnsupportedError(
-      "FFI callbacks are not yet supported on DBC.");
-#elif defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
   // Calls to this function are removed by the flow-graph builder in AOT.
   // See StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction().
   UNREACHABLE();
@@ -495,7 +490,7 @@
   thread->SetFfiCallbackCode(function.FfiCallbackId(), code);
 
   uword entry_point = code.EntryPoint();
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   if (NativeCallbackTrampolines::Enabled()) {
     entry_point = isolate->native_callback_trampolines()->TrampolineForId(
         function.FfiCallbackId());
@@ -505,121 +500,4 @@
   return Pointer::New(type_arg, entry_point);
 }
 
-#if defined(TARGET_ARCH_DBC)
-
-void FfiMarshalledArguments::SetFunctionAddress(uint64_t value) const {
-  data_[kOffsetFunctionAddress] = value;
-}
-
-static intptr_t ArgumentHostRegisterIndex(host::Register reg) {
-  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
-    if (host::CallingConventions::ArgumentRegisters[i] == reg) {
-      return i;
-    }
-  }
-  UNREACHABLE();
-}
-
-void FfiMarshalledArguments::SetRegister(host::Register reg,
-                                         uint64_t value) const {
-  const intptr_t reg_index = ArgumentHostRegisterIndex(reg);
-  ASSERT(host::CallingConventions::ArgumentRegisters[reg_index] == reg);
-  const intptr_t index = kOffsetRegisters + reg_index;
-  data_[index] = value;
-}
-
-void FfiMarshalledArguments::SetFpuRegister(host::FpuRegister reg,
-                                            uint64_t value) const {
-  const intptr_t fpu_index = static_cast<intptr_t>(reg);
-  ASSERT(host::CallingConventions::FpuArgumentRegisters[fpu_index] == reg);
-  const intptr_t index = kOffsetFpuRegisters + fpu_index;
-  data_[index] = value;
-}
-
-void FfiMarshalledArguments::SetNumStackSlots(intptr_t num_args) const {
-  data_[kOffsetNumStackSlots] = num_args;
-}
-
-void FfiMarshalledArguments::SetAlignmentMask(uint64_t alignment_mask) const {
-  data_[kOffsetAlignmentMask] = alignment_mask;
-}
-
-intptr_t FfiMarshalledArguments::GetNumStackSlots() const {
-  return data_[kOffsetNumStackSlots];
-}
-
-void FfiMarshalledArguments::SetStackSlotValue(intptr_t index,
-                                               uint64_t value) const {
-  ASSERT(0 <= index && index < GetNumStackSlots());
-  data_[kOffsetStackSlotValues + index] = value;
-}
-
-uint64_t* FfiMarshalledArguments::New(
-    const compiler::ffi::FfiSignatureDescriptor& signature,
-    const uint64_t* arg_values) {
-  const intptr_t num_stack_slots = signature.num_stack_slots();
-  const uint64_t alignment_mask = ~(OS::ActivationFrameAlignment() - 1);
-  const intptr_t size =
-      FfiMarshalledArguments::kOffsetStackSlotValues + num_stack_slots;
-  uint64_t* data = Thread::Current()->GetFfiMarshalledArguments(size);
-  const auto& descr = FfiMarshalledArguments(data);
-
-  descr.SetFunctionAddress(arg_values[compiler::ffi::kFunctionAddressRegister]);
-  const intptr_t num_args = signature.length();
-  descr.SetNumStackSlots(num_stack_slots);
-  descr.SetAlignmentMask(alignment_mask);
-  for (int i = 0; i < num_args; i++) {
-    uint64_t arg_value = arg_values[compiler::ffi::kFirstArgumentRegister + i];
-    HostLocation loc = signature.LocationAt(i);
-    // TODO(36809): For 32 bit, support pair locations.
-    if (loc.IsRegister()) {
-      descr.SetRegister(loc.reg(), arg_value);
-    } else if (loc.IsFpuRegister()) {
-      descr.SetFpuRegister(loc.fpu_reg(), arg_value);
-    } else {
-      ASSERT(loc.IsStackSlot() || loc.IsDoubleStackSlot());
-      ASSERT(loc.stack_index() < num_stack_slots);
-      descr.SetStackSlotValue(loc.stack_index(), arg_value);
-    }
-  }
-
-  return data;
-}
-
-#if defined(DEBUG)
-void FfiMarshalledArguments::Print() const {
-  OS::PrintErr("FfiMarshalledArguments data_ 0x%" Pp "\n",
-               reinterpret_cast<intptr_t>(data_));
-  OS::PrintErr("  00 0x%016" Px64 " (function address, int result)\n",
-               data_[0]);
-  for (intptr_t i = 0; i < host::CallingConventions::kNumArgRegs; i++) {
-    const intptr_t index = kOffsetRegisters + i;
-    const char* result_str = i == 0 ? ", float result" : "";
-    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s%s)\n", index, data_[index],
-                 RegisterNames::RegisterName(
-                     host::CallingConventions::ArgumentRegisters[i]),
-                 result_str);
-  }
-  for (intptr_t i = 0; i < host::CallingConventions::kNumFpuArgRegs; i++) {
-    const intptr_t index = kOffsetFpuRegisters + i;
-    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (%s)\n", index, data_[index],
-                 RegisterNames::FpuRegisterName(
-                     host::CallingConventions::FpuArgumentRegisters[i]));
-  }
-  const intptr_t alignment_mask = data_[kOffsetAlignmentMask];
-  OS::PrintErr("  %02" Pd " 0x%" Pp " (stack alignment mask)\n",
-               kOffsetAlignmentMask, alignment_mask);
-  const intptr_t num_stack_slots = data_[kOffsetNumStackSlots];
-  OS::PrintErr("  %02" Pd " 0x%" Pp " (number of stack slots)\n",
-               kOffsetNumStackSlots, num_stack_slots);
-  for (intptr_t i = 0; i < num_stack_slots; i++) {
-    const intptr_t index = kOffsetStackSlotValues + i;
-    OS::PrintErr("  %02" Pd " 0x%016" Px64 " (stack slot %" Pd ")\n", index,
-                 data_[index], i);
-  }
-}
-#endif  // defined(DEBUG)
-
-#endif  // defined(TARGET_ARCH_DBC)
-
 }  // namespace dart
diff --git a/runtime/lib/ffi.h b/runtime/lib/ffi.h
deleted file mode 100644
index 4cfa855..0000000
--- a/runtime/lib/ffi.h
+++ /dev/null
@@ -1,76 +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.
-
-#ifndef RUNTIME_LIB_FFI_H_
-#define RUNTIME_LIB_FFI_H_
-
-#if defined(TARGET_ARCH_DBC)
-
-#include <platform/globals.h>
-
-#include "vm/class_id.h"
-#include "vm/compiler/backend/locations.h"
-#include "vm/compiler/ffi.h"
-#include "vm/object.h"
-#include "vm/raw_object.h"
-
-namespace dart {
-
-// This structure contains all data required for an ffi call.
-// It consists of the function address, all calling convention argument
-// register values, argument fpu register values, number of stack arguments,
-// and stack argument values. The generic DBC trampoline reads its arguments
-// from this structure.
-//
-// Moreover, the DBC trampoline also stores the integer and floating point
-// result registers in the first two slots when returning.
-class FfiMarshalledArguments : public ValueObject {
- public:
-  explicit FfiMarshalledArguments(uint64_t* data) : data_(data) {}
-
-  // Copies ffi trampoline arguments (including target address) from stack into
-  // a signature agnostic data structure (FfiMarshalledArguments) using the
-  // signature and the stack address of the first argument. (Note that this
-  // only works on DBC as the stack grows upwards in DBC.)
-  static uint64_t* New(const compiler::ffi::FfiSignatureDescriptor& signature,
-                       const uint64_t* arg_values);
-
-  uint64_t IntResult() const { return data_[kOffsetIntResult]; }
-  uint64_t DoubleResult() const { return data_[kOffsetDoubleResult]; }
-
-#if defined(DEBUG)
-  void Print() const;
-#endif
-
- private:
-  void SetFunctionAddress(uint64_t value) const;
-  void SetRegister(::dart::host::Register reg, uint64_t value) const;
-  void SetFpuRegister(::dart::host::FpuRegister reg, uint64_t value) const;
-  void SetAlignmentMask(uint64_t kOffsetAlignmentMask) const;
-  void SetNumStackSlots(intptr_t num_args) const;
-  intptr_t GetNumStackSlots() const;
-  void SetStackSlotValue(intptr_t index, uint64_t value) const;
-
-  // TODO(36809): Replace this with uword. On 32 bit architecture,
-  // this should be 32 bits, as the DBC stack itself is 32 bits.
-  uint64_t* data_;
-
-  static const intptr_t kOffsetFunctionAddress = 0;
-  static const intptr_t kOffsetRegisters = 1;
-  static const intptr_t kOffsetFpuRegisters =
-      kOffsetRegisters + ::dart::host::CallingConventions::kNumArgRegs;
-  static const intptr_t kOffsetAlignmentMask =
-      kOffsetFpuRegisters + ::dart::host::CallingConventions::kNumFpuArgRegs;
-  static const intptr_t kOffsetNumStackSlots = kOffsetAlignmentMask + 1;
-  static const intptr_t kOffsetStackSlotValues = kOffsetNumStackSlots + 1;
-
-  static const intptr_t kOffsetIntResult = 0;
-  static const intptr_t kOffsetDoubleResult = 1;
-};
-
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_DBC)
-
-#endif  // RUNTIME_LIB_FFI_H_
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index b5a8725..9c8f617 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -625,11 +625,25 @@
       Array& args = Array::Handle(Array::New(1));
       args.SetAt(0, Symbols::Dynamic());
       return CreateMirror(Symbols::_SpecialTypeMirror(), args);
+    } else if (cls.IsNeverClass()) {
+      Array& args = Array::Handle(Array::New(1));
+      args.SetAt(0, Symbols::Never());
+      return CreateMirror(Symbols::_SpecialTypeMirror(), args);
+    }
+    // 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::Cast(type).ToNullability(kLegacy, Heap::kOld));
+      return CreateClassMirror(cls, legacy_type, Bool::False(),
+                               Object::null_instance());
     }
     return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
   } else if (type.IsTypeParameter()) {
-    return CreateTypeVariableMirror(TypeParameter::Cast(type),
-                                    Object::null_instance());
+    // TODO(regis): Until mirrors reflect nullability, force kLegacy.
+    const TypeParameter& legacy_type = TypeParameter::Handle(
+        TypeParameter::Cast(type).ToNullability(kLegacy, Heap::kOld));
+    return CreateTypeVariableMirror(legacy_type, Object::null_instance());
   }
   UNREACHABLE();
   return Instance::null();
@@ -670,7 +684,7 @@
   field = cls.LookupField(fname);                                              \
   ASSERT(!field.IsNull());                                                     \
   if (field.IsUninitialized()) {                                               \
-    error ^= field.Initialize();                                               \
+    error ^= field.InitializeStatic();                                         \
     ASSERT(error.IsNull());                                                    \
   }                                                                            \
   value ^= field.StaticValue();                                                \
@@ -1683,10 +1697,8 @@
       return Instance::null();  // No source.
     }
     const Array& scripts = Array::Handle(zone, lib.LoadedScripts());
-    for (intptr_t i = 0; i < scripts.Length(); i++) {
-      script ^= scripts.At(i);
-      if (script.kind() == RawScript::kLibraryTag) break;
-    }
+    ASSERT(scripts.Length() > 0);
+    script ^= scripts.At(scripts.Length() - 1);
     ASSERT(!script.IsNull());
     const String& uri = String::Handle(zone, script.url());
     return CreateSourceLocation(uri, 1, 1);
diff --git a/runtime/llvm_codegen/codegen/BUILD.gn b/runtime/llvm_codegen/codegen/BUILD.gn
index 3addb35..4ccb309 100644
--- a/runtime/llvm_codegen/codegen/BUILD.gn
+++ b/runtime/llvm_codegen/codegen/BUILD.gn
@@ -5,13 +5,9 @@
 import("../../vm/compiler/compiler_sources.gni")
 
 config("config") {
-  include_dirs = [
-    "../../"
-  ]
+  include_dirs = [ "../../" ]
 
-  cflags = [
-    "-Wno-unused-private-field"
-  ]
+  cflags = [ "-Wno-unused-private-field" ]
 }
 
 _lib_llvm_so = "../../../third_party/llvm/lib/libLLVM-9svn.so"
@@ -22,23 +18,27 @@
 }
 
 copy("lib_llvm") {
-  sources = [ _lib_llvm_so ]
-  outputs = [ "$root_out_dir/libLLVM-9svn.so" ]
+  sources = [
+    _lib_llvm_so,
+  ]
+  outputs = [
+    "$root_out_dir/libLLVM-9svn.so",
+  ]
   public_configs = [ ":llvm" ]
 }
 
 executable("codegen") {
   sources = [
-    "main.cc",
+    "custom_zone.cc",
+    "custom_zone.h",
     "dart.cc",
-    "dart.h"
+    "dart.h",
+    "main.cc",
   ]
 
   deps = [
     ":lib_llvm",
-    "../..:libdart_nosnapshot_with_precompiler",
-    "../../vm:libdart_vm_nosnapshot_with_precompiler",
-    "../../platform:libdart_platform_nosnapshot_with_precompiler",
+    "../../third_party/double-conversion/src:libdouble_conversion",
   ]
 
   configs += [ ":config" ]
diff --git a/runtime/llvm_codegen/codegen/custom_zone.cc b/runtime/llvm_codegen/codegen/custom_zone.cc
new file mode 100644
index 0000000..f514fe5
--- /dev/null
+++ b/runtime/llvm_codegen/codegen/custom_zone.cc
@@ -0,0 +1,54 @@
+// 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.
+
+#include "custom_zone.h"
+
+#include "platform/text_buffer.h"
+#include "platform/unicode.h"
+#include "platform/utils.h"
+#include "vm/double_conversion.h"
+#include "vm/os.h"
+
+#include "platform/assert.cc"  // NOLINT
+#include "platform/syslog_linux.cc"  // NOLINT
+#include "platform/text_buffer.cc"  // NOLINT
+#include "platform/unicode.cc"  // NOLINT
+#include "platform/utils.cc"  // NOLINT
+#include "platform/utils_linux.cc"  // NOLINT
+#include "vm/compiler/backend/sexpression.cc"  // NOLINT
+#include "vm/double_conversion.cc"  // NOLINT
+#include "vm/flags.cc"  // NOLINT
+#include "vm/os_linux.cc"  // NOLINT
+#include "vm/zone_text_buffer.cc"  // NOLINT
+
+namespace dart {
+
+void* ZoneAllocated::operator new(uintptr_t size, dart::Zone* zone) {
+  return reinterpret_cast<void*>(zone->AllocUnsafe(size));
+}
+
+Zone::~Zone() {
+  while (buffers_.size() > 0) {
+    free(buffers_.back());
+    buffers_.pop_back();
+  }
+}
+
+void* Zone::AllocUnsafe(intptr_t size) {
+  void* memory = malloc(size);
+  buffers_.push_back(memory);
+  return memory;
+}
+
+DART_EXPORT void Dart_PrepareToAbort() {
+  fprintf(stderr, "Dart_PrepareToAbort() not implemented!\n");
+  exit(1);
+}
+
+DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
+  fprintf(stderr, "Dart_DumpNativeStackTrace() not implemented!\n");
+  exit(1);
+}
+
+}  // namespace dart
diff --git a/runtime/llvm_codegen/codegen/custom_zone.h b/runtime/llvm_codegen/codegen/custom_zone.h
new file mode 100644
index 0000000..3b38104
--- /dev/null
+++ b/runtime/llvm_codegen/codegen/custom_zone.h
@@ -0,0 +1,52 @@
+// 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.
+
+#ifndef RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
+#define RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
+
+#include <vector>
+
+// We use a custom zone here which doesn't depend on VM internals (e.g. handles,
+// thread, ...)
+#if defined(RUNTIME_VM_ZONE_H_)
+#error "We want our own zone implementation"
+#endif
+#define RUNTIME_VM_ZONE_H_
+
+namespace dart {
+
+class Zone {
+ public:
+  Zone() {}
+  ~Zone();
+
+  template <class ElementType>
+  inline ElementType* Alloc(intptr_t length) {
+    return static_cast<ElementType*>(
+        AllocUnsafe(sizeof(ElementType) * length));
+  }
+
+  template <class ElementType>
+  inline ElementType* Realloc(ElementType* old_array,
+                              intptr_t old_length,
+                              intptr_t new_length) {
+    void* memory = AllocUnsafe(sizeof(ElementType) * new_length);
+    memmove(memory, old_array, sizeof(ElementType) * old_length);
+    return static_cast<ElementType*>(memory);
+  }
+
+  template <class ElementType>
+  void Free(ElementType* old_array, intptr_t len) {}
+
+  void* AllocUnsafe(intptr_t size);
+
+ private:
+  Zone(const Zone&) = delete;
+  void operator=(const Zone&) = delete;
+  std::vector<void*> buffers_;
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_LLVM_CODEGEN_CODEGEN_CUSTOM_ZONE_H_
diff --git a/runtime/llvm_codegen/codegen/dart.cc b/runtime/llvm_codegen/codegen/dart.cc
index e400b41..fe21974 100644
--- a/runtime/llvm_codegen/codegen/dart.cc
+++ b/runtime/llvm_codegen/codegen/dart.cc
@@ -2,10 +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.
 
+#include <utility>
+
 #include "dart.h"
 
 #include "llvm/ADT/StringSwitch.h"
-#include "vm/dart_api_state.h"
 
 using namespace llvm;
 
@@ -128,22 +129,22 @@
     return CreateError("PushArgument should have exactly 1 argument");
   }
   dart::SExpSymbol* arg = inst->At(1)->AsSymbol();
-  if (!arg) {
+  if (arg == nullptr) {
     return CreateError("Expected PushArgument's argument to be a symbol");
   }
   const DartValue* dvalue = bb_builder.GetDef(arg->value());
-  if (!dvalue) {
+  if (dvalue == nullptr) {
     return CreateError(Twine(arg->value()) + " is not a valid symbol");
   }
   return llvm::make_unique<InstPushArgument>(dvalue);
 }
 
 void InstStaticCall::Build(BasicBlockBuilder& bb_builder) const {
-  // inst = (StaticCall <function-symbol> <arg> ...)  
+  // inst = (StaticCall <function-symbol> <arg> ...)
 
   SmallVector<Value*, 8> args;
   size_t arg_count = args_len_;
-  while (arg_count) {
+  while (arg_count > 0) {
     arg_count--;
     args.push_back(bb_builder.PopArgument());
   }
@@ -196,15 +197,15 @@
   return llvm::make_unique<InstReturn>();
 }
 
-static Expected<StringMap<DartConstant>> MakeConstants(dart::SExpList* sexpr) {
-  dart::ApiZone zone;
+static Expected<StringMap<DartConstant>> MakeConstants(dart::Zone* zone,
+                                                       dart::SExpList* sexpr) {
   StringMap<DartConstant> out;
   for (intptr_t i = 1; i < sexpr->Length(); ++i) {
     DartConstant constant;
     dart::SExpList* def = sexpr->At(i)->AsList();
     if (!def) {
       return CreateError(Twine("Stray token in constants at location ") +
-                         Twine(i) + sexpr->At(i)->ToCString(zone.GetZone()));
+                         Twine(i) + sexpr->At(i)->ToCString(zone));
     }
     if (def->Length() != 3) {
       return CreateError("Constant definitions must have exactly 3 lines");
@@ -287,10 +288,10 @@
   return out;
 }
 
-Expected<DartFunction> MakeFunction(dart::SExpression* sexpr,
+Expected<DartFunction> MakeFunction(dart::Zone* zone,
+                                    dart::SExpression* sexpr,
                                     const StringMap<const DartValue*>& env) {
   // Basic checking that this s-expression looks like a function
-  dart::ApiZone zone;
   dart::SExpList* flist = sexpr->AsList();
   if (!flist) return CreateError("S-Expression was not a function list");
   if (flist->Length() < 2)
@@ -312,10 +313,10 @@
   for (intptr_t i = 2; i < flist->Length(); ++i) {
     dart::SExpList* chunk = flist->At(i)->AsList();
     // Everything is a list so far so error out on other options
-    if (!chunk)
+    if (!chunk) {
       return CreateError(Twine("Stray token in function at location ") +
-                         Twine(i) + ": " +
-                         flist->At(i)->ToCString(zone.GetZone()));
+                         Twine(i) + ": " + flist->At(i)->ToCString(zone));
+    }
     dart::SExpSymbol* chunk_symbol = chunk->At(0)->AsSymbol();
     if (!chunk_symbol)
       return CreateError(Twine("Expected element ") + Twine(i) +
@@ -323,7 +324,7 @@
     StringRef chunk_tag = chunk_symbol->value();
 
     if (chunk_tag == "constants") {
-      auto constants = MakeConstants(chunk);
+      auto constants = MakeConstants(zone, chunk);
       if (!constants) return constants.takeError();
       function.constants = std::move(*constants);
     }
diff --git a/runtime/llvm_codegen/codegen/dart.h b/runtime/llvm_codegen/codegen/dart.h
index 1261a7b..826397a 100644
--- a/runtime/llvm_codegen/codegen/dart.h
+++ b/runtime/llvm_codegen/codegen/dart.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <vector>
+#include <string>
 
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/IRBuilder.h"
@@ -14,6 +15,9 @@
 #include "llvm/IR/ValueSymbolTable.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/WithColor.h"
+
+// Ensure to use our own zone.
+#include "custom_zone.h"
 #include "vm/compiler/backend/sexpression.h"
 
 // This file introduces several representations that exist between
@@ -229,7 +233,7 @@
 // an instance of a CheckStackOverflow instruction.
 class InstCheckStackOverflow : public DartInstruction {
  public:
-  explicit InstCheckStackOverflow() {}
+  InstCheckStackOverflow() {}
   ~InstCheckStackOverflow() override {}
   void Build(BasicBlockBuilder& bb_builder) const override;
   static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
@@ -273,7 +277,7 @@
 // instruction.
 class InstReturn : public DartInstruction {
  public:
-  explicit InstReturn() {}
+  InstReturn() {}
   ~InstReturn() override {}
   void Build(BasicBlockBuilder& bb_builder) const override;
   static llvm::Expected<std::unique_ptr<DartInstruction>> Construct(
@@ -303,7 +307,8 @@
 // of the S-Expression is invalid then the llvm::Expected will hold an
 // error explaining the issue.
 llvm::Expected<DartFunction> MakeFunction(
+    dart::Zone* zone,
     dart::SExpression* sexpr,
     const llvm::StringMap<const DartValue*>& env);
 
-#endif  // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H
+#endif  // RUNTIME_LLVM_CODEGEN_CODEGEN_DART_H_
diff --git a/runtime/llvm_codegen/codegen/main.cc b/runtime/llvm_codegen/codegen/main.cc
index 4b469bc..40d8b3f 100644
--- a/runtime/llvm_codegen/codegen/main.cc
+++ b/runtime/llvm_codegen/codegen/main.cc
@@ -13,8 +13,6 @@
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
 
-#include "vm/dart_api_state.h"
-
 using namespace llvm;
 
 namespace {
@@ -102,24 +100,14 @@
   tool_name = argv[0];
   cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
 
-  // Init dart
-  const char* err = Dart_SetVMFlags(0, argv + 2);
-  if (err != nullptr) error(Twine("Dart_SetVMFlags failed: ") + err);
-  Dart_InitializeParams init_params;
-  memset(&init_params, 0, sizeof(init_params));
-  init_params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION;
-  err = Dart_Initialize(&init_params);
-  if (err != nullptr) error(Twine("Dart Initialization failed: ") + err);
-
   // Read in the file
   auto file_or = MemoryBuffer::getFile(argv[1]);
   if (!file_or) reportError(argv[1], file_or.getError());
   std::unique_ptr<MemoryBuffer> file = std::move(file_or.get());
 
   // Parse the file
-  dart::ApiZone zone;
-  dart::SExpParser parser(zone.GetZone(), file->getBufferStart(),
-                          file->getBufferSize());
+  dart::Zone zone;
+  dart::SExpParser parser(&zone, file->getBufferStart(), file->getBufferSize());
   dart::SExpression* root = parser.Parse();
   if (root == nullptr)
     error(Twine("SExpParser failed: ") + parser.error_message());
@@ -130,7 +118,7 @@
   prelude["dart:core::print"] = &print;
 
   // Convert the function into an error checked format
-  auto function_or = MakeFunction(root, prelude);
+  auto function_or = MakeFunction(&zone, root, prelude);
   if (!function_or) error(function_or.takeError());
   auto dart_function = std::move(*function_or);
   if (!dart_function.normal_entry)
diff --git a/runtime/observatory/analysis_options.yaml b/runtime/observatory/analysis_options.yaml
index ecd5b50..6babf28 100644
--- a/runtime/observatory/analysis_options.yaml
+++ b/runtime/observatory/analysis_options.yaml
@@ -10,3 +10,8 @@
     - tests/service/get_isolate_after_language_error_test.dart
     - tests/service/get_user_level_retaining_path_rpc_test.dart
     - tests/service/pause_on_unhandled_async_exceptions_test.dart
+
+linter:
+  rules:
+    - prefer_final_fields
+    - prefer_final_locals
diff --git a/runtime/observatory/lib/models.dart b/runtime/observatory/lib/models.dart
index 60809ef..1b13845 100644
--- a/runtime/observatory/lib/models.dart
+++ b/runtime/observatory/lib/models.dart
@@ -29,6 +29,7 @@
 part 'src/models/objects/inbound_references.dart';
 part 'src/models/objects/instance.dart';
 part 'src/models/objects/isolate.dart';
+part 'src/models/objects/isolate_group.dart';
 part 'src/models/objects/library.dart';
 part 'src/models/objects/local_var_descriptors.dart';
 part 'src/models/objects/map_association.dart';
@@ -74,6 +75,7 @@
 part 'src/models/repositories/inbound_references.dart';
 part 'src/models/repositories/instance.dart';
 part 'src/models/repositories/isolate.dart';
+part 'src/models/repositories/isolate_group.dart';
 part 'src/models/repositories/library.dart';
 part 'src/models/repositories/megamorphiccache.dart';
 part 'src/models/repositories/metric.dart';
diff --git a/runtime/observatory/lib/repositories.dart b/runtime/observatory/lib/repositories.dart
index 70cb593..4810e58 100644
--- a/runtime/observatory/lib/repositories.dart
+++ b/runtime/observatory/lib/repositories.dart
@@ -30,6 +30,7 @@
 part 'src/repositories/inbound_references.dart';
 part 'src/repositories/instance.dart';
 part 'src/repositories/isolate.dart';
+part 'src/repositories/isolate_group.dart';
 part 'src/repositories/library.dart';
 part 'src/repositories/megamorphiccache.dart';
 part 'src/repositories/metric.dart';
diff --git a/runtime/observatory/lib/src/elements/retaining_path.dart b/runtime/observatory/lib/src/elements/retaining_path.dart
index 5b7e7a4..7dca764 100644
--- a/runtime/observatory/lib/src/elements/retaining_path.dart
+++ b/runtime/observatory/lib/src/elements/retaining_path.dart
@@ -103,12 +103,8 @@
     if (first) {
       // No prefix.
     } else if (item.parentField != null) {
-      content.add(new SpanElement()
-        ..children = <Element>[
-          new SpanElement()..text = 'retained by ',
-          anyRef(_isolate, item.parentField, _objects, queue: _r.queue),
-          new SpanElement()..text = ' of ',
-        ]);
+      content
+          .add(new SpanElement()..text = 'retained by ${item.parentField} of ');
     } else if (item.parentListIndex != null) {
       content.add(new SpanElement()
         ..text = 'retained by [ ${item.parentListIndex} ] of ');
diff --git a/runtime/observatory/lib/src/models/objects/isolate_group.dart b/runtime/observatory/lib/src/models/objects/isolate_group.dart
new file mode 100644
index 0000000..b18bbf7
--- /dev/null
+++ b/runtime/observatory/lib/src/models/objects/isolate_group.dart
@@ -0,0 +1,22 @@
+// 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.
+
+part of models;
+
+abstract class IsolateGroupRef {
+  /// The id which is passed to the getIsolateGroup RPC to reload this
+  /// isolate group.
+  String get id;
+
+  /// A numeric id for this isolate group, represented as a string. Unique.
+  int get number;
+
+  /// A name identifying this isolate group. Not guaranteed to be unique.
+  String get name;
+}
+
+abstract class IsolateGroup extends IsolateGroupRef {
+  /// A list of all isolates in this isolate group.
+  Iterable<IsolateRef> get isolates;
+}
diff --git a/runtime/observatory/lib/src/models/objects/retaining_path.dart b/runtime/observatory/lib/src/models/objects/retaining_path.dart
index cde8a32..360d81d 100644
--- a/runtime/observatory/lib/src/models/objects/retaining_path.dart
+++ b/runtime/observatory/lib/src/models/objects/retaining_path.dart
@@ -14,8 +14,7 @@
   ObjectRef get source;
 
   /// [optional]
-  /// FieldRef or InstanceRef (null)
-  ObjectRef get parentField;
+  String get parentField;
 
   /// [optional]
   int get parentListIndex;
diff --git a/runtime/observatory/lib/src/models/objects/vm.dart b/runtime/observatory/lib/src/models/objects/vm.dart
index b2bfd4d..fe25c84 100644
--- a/runtime/observatory/lib/src/models/objects/vm.dart
+++ b/runtime/observatory/lib/src/models/objects/vm.dart
@@ -50,6 +50,7 @@
 
   // A list of isolates running in the VM.
   Iterable<IsolateRef> get isolates;
+  Iterable<IsolateGroupRef> get isolateGroups;
 
   /// Enable the sampling profiler.
   Future enableProfiler();
diff --git a/runtime/observatory/lib/src/models/repositories/isolate_group.dart b/runtime/observatory/lib/src/models/repositories/isolate_group.dart
new file mode 100644
index 0000000..ccf2422
--- /dev/null
+++ b/runtime/observatory/lib/src/models/repositories/isolate_group.dart
@@ -0,0 +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
+
+part of models;
+
+abstract class IsolateGroupRepository {
+  Future<IsolateGroup> get(IsolateGroupRef isolateGroup);
+}
diff --git a/runtime/observatory/lib/src/repositories/isolate_group.dart b/runtime/observatory/lib/src/repositories/isolate_group.dart
new file mode 100644
index 0000000..fabc9d7
--- /dev/null
+++ b/runtime/observatory/lib/src/repositories/isolate_group.dart
@@ -0,0 +1,22 @@
+// 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
+
+part of repositories;
+
+class IsolateGroupRepository extends M.IsolateGroupRepository {
+  final S.VM _vm;
+
+  IsolateGroupRepository(this._vm) : assert(_vm != null);
+
+  Future<M.IsolateGroup> get(M.IsolateGroupRef i) async {
+    S.IsolateGroup isolateGroup = i as S.IsolateGroup;
+    assert(isolateGroup != null);
+    try {
+      await isolateGroup.reload();
+    } on SC.NetworkRpcException catch (_) {
+      /* ignore */
+    }
+    return isolateGroup;
+  }
+}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index e173438..754075c 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -229,6 +229,9 @@
       case 'Isolate':
         obj = new Isolate._empty(owner.vm);
         break;
+      case 'IsolateGroup':
+        obj = new IsolateGroup._empty(owner.vm);
+        break;
       case 'Library':
         obj = new Library._empty(owner);
         break;
@@ -661,10 +664,13 @@
   // TODO(johnmccutchan): Ensure that isolates do not end up in _cache.
   Map<String, ServiceObject> _cache = new Map<String, ServiceObject>();
   final Map<String, Isolate> _isolateCache = <String, Isolate>{};
+  final Map<String, IsolateGroup> _isolateGroupCache = <String, IsolateGroup>{};
 
   // The list of live isolates, ordered by isolate start time.
   final List<Isolate> isolates = <Isolate>[];
 
+  final List<IsolateGroup> isolateGroups = <IsolateGroup>[];
+
   final List<Service> services = <Service>[];
 
   String version = 'unknown';
@@ -771,6 +777,7 @@
   }
 
   static final String _isolateIdPrefix = 'isolates/';
+  static final String _isolateGroupIdPrefix = 'isolateGroups/';
 
   ServiceObject getFromMap(Map map) {
     if (map == null) {
@@ -784,23 +791,44 @@
     }
 
     String id = map['id'];
-    if ((id != null) && id.startsWith(_isolateIdPrefix)) {
-      // Check cache.
-      var isolate = _isolateCache[id];
-      if (isolate == null) {
-        // Add new isolate to the cache.
-        isolate = new ServiceObject._fromMap(this, map);
-        _isolateCache[id] = isolate;
-        _buildIsolateList();
+    if ((id != null)) {
+      if (id.startsWith(_isolateIdPrefix)) {
+        // Check cache.
+        var isolate = _isolateCache[id];
+        if (isolate == null) {
+          // Add new isolate to the cache.
+          isolate = ServiceObject._fromMap(this, map);
+          _isolateCache[id] = isolate;
+          _buildIsolateList();
 
-        // Eagerly load the isolate.
-        isolate.load().catchError((e, stack) {
-          Logger.root.info('Eagerly loading an isolate failed: $e\n$stack');
-        });
-      } else {
-        isolate.updateFromServiceMap(map);
+          // Eagerly load the isolate.
+          isolate.load().catchError((e, stack) {
+            Logger.root.info('Eagerly loading an isolate failed: $e\n$stack');
+          });
+        } else {
+          isolate.updateFromServiceMap(map);
+        }
+        return isolate;
       }
-      return isolate;
+      if (id.startsWith(_isolateGroupIdPrefix)) {
+        // Check cache.
+        var isolateGroup = _isolateGroupCache[id];
+        if (isolateGroup == null) {
+          // Add new isolate to the cache.
+          isolateGroup = new ServiceObject._fromMap(this, map);
+          _isolateGroupCache[id] = isolateGroup;
+          _buildIsolateGroupList();
+
+          // Eagerly load the isolate.
+          isolateGroup.load().catchError((e, stack) {
+            Logger.root
+                .info('Eagerly loading an isolate group failed: $e\n$stack');
+          });
+        } else {
+          isolateGroup.updateFromServiceMap(map);
+        }
+        return isolateGroup;
+      }
     }
 
     // Build the object from the map directly.
@@ -817,6 +845,27 @@
     return new Future.value(_isolateCache[isolateId]);
   }
 
+  int _compareIsolateGroups(IsolateGroup a, IsolateGroup b) {
+    return a.id.compareTo(b.id);
+  }
+
+  void _buildIsolateGroupList() {
+    final isolateGroupList = _isolateGroupCache.values.toList();
+    isolateGroupList.sort(_compareIsolateGroups);
+    isolateGroups.clear();
+    isolateGroups.addAll(isolateGroupList);
+  }
+
+  void _removeDeadIsolateGroups(List newIsolateGroups) {
+    // Build a set of new isolates.
+    final Set newIsolateGroupSet =
+        newIsolateGroups.map((iso) => iso.id).toSet();
+
+    // Remove any old isolates which no longer exist.
+    _isolateGroupCache.removeWhere((id, _) => !newIsolateGroupSet.contains(id));
+    _buildIsolateGroupList();
+  }
+
   // Implemented in subclass.
   Future<Map> invokeRpcRaw(String method, Map params);
 
@@ -989,6 +1038,7 @@
     assertsEnabled = map['_assertsEnabled'];
     typeChecksEnabled = map['_typeChecksEnabled'];
     _removeDeadIsolates(map['isolates']);
+    _removeDeadIsolateGroups(map['isolateGroups']);
   }
 
   // Reload all isolates.
@@ -1122,7 +1172,7 @@
 
 class RetainingPathItem implements M.RetainingPathItem {
   final ServiceObject /*HeapObject*/ source;
-  final HeapObject parentField;
+  final String parentField;
   final int parentListIndex;
   final int parentWordOffset;
 
@@ -1220,6 +1270,77 @@
   }
 }
 
+class IsolateGroup extends ServiceObjectOwner implements M.IsolateGroup {
+  IsolateGroup._empty(ServiceObjectOwner owner)
+      : assert(owner is VM),
+        super._empty(owner);
+
+  @override
+  void _update(Map map, bool mapIsRef) {
+    name = map['name'];
+    vmName = map.containsKey('_vmName') ? map['_vmName'] : name;
+    number = int.tryParse(map['number']);
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    isolates.clear();
+    isolates.addAll(map['isolates'] as List<Isolate>);
+    isolates.sort(ServiceObject.LexicalSortName);
+    vm._buildIsolateGroupList();
+  }
+
+  @override
+  ServiceObject getFromMap(Map map) {
+    if (map == null) {
+      return null;
+    }
+    final mapType = _stripRef(map['type']);
+    if (mapType == 'IsolateGroup') {
+      // There are sometimes isolate group refs in ServiceEvents.
+      return vm.getFromMap(map);
+    }
+    String mapId = map['id'];
+    var obj = (mapId != null) ? _cache[mapId] : null;
+    if (obj != null) {
+      obj.updateFromServiceMap(map);
+      return obj;
+    }
+    // Build the object from the map directly.
+    obj = new ServiceObject._fromMap(this, map);
+    if ((obj != null) && obj.canCache) {
+      _cache[mapId] = obj;
+    }
+    return obj;
+  }
+
+  Future<Map> invokeRpcNoUpgrade(String method, Map params) {
+    params['isolateGroupId'] = id;
+    return vm.invokeRpcNoUpgrade(method, params);
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params)
+        .then((Map response) => getFromMap(response));
+  }
+
+  @override
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) {
+    Map params = {
+      'isolateGroupId': id,
+    };
+    return vm.invokeRpcNoUpgrade('getIsolateGroup', params);
+  }
+
+  @override
+  final List<Isolate> isolates = <Isolate>[];
+
+  @override
+  int number;
+
+  final Map<String, ServiceObject> _cache = Map<String, ServiceObject>();
+}
+
 /// State for a running isolate.
 class Isolate extends ServiceObjectOwner implements M.Isolate {
   static const kLoggingStream = 'Logging';
diff --git a/runtime/observatory/observatory_sources.gni b/runtime/observatory/observatory_sources.gni
index 1cd8af3..cb47f7c 100644
--- a/runtime/observatory/observatory_sources.gni
+++ b/runtime/observatory/observatory_sources.gni
@@ -164,6 +164,7 @@
   "lib/src/models/objects/inbound_references.dart",
   "lib/src/models/objects/instance.dart",
   "lib/src/models/objects/isolate.dart",
+  "lib/src/models/objects/isolate_group.dart",
   "lib/src/models/objects/library.dart",
   "lib/src/models/objects/local_var_descriptors.dart",
   "lib/src/models/objects/map_association.dart",
@@ -208,6 +209,7 @@
   "lib/src/models/repositories/inbound_references.dart",
   "lib/src/models/repositories/instance.dart",
   "lib/src/models/repositories/isolate.dart",
+  "lib/src/models/repositories/isolate_group.dart",
   "lib/src/models/repositories/library.dart",
   "lib/src/models/repositories/megamorphiccache.dart",
   "lib/src/models/repositories/metric.dart",
@@ -245,6 +247,7 @@
   "lib/src/repositories/inbound_references.dart",
   "lib/src/repositories/instance.dart",
   "lib/src/repositories/isolate.dart",
+  "lib/src/repositories/isolate_group.dart",
   "lib/src/repositories/library.dart",
   "lib/src/repositories/megamorphiccache.dart",
   "lib/src/repositories/metric.dart",
diff --git a/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart
index 6660805..8c21890 100644
--- a/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart
+++ b/runtime/observatory/tests/service/breakpoint_two_args_checked_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // VMOptions=--verbose_debug
 
-// This test is mostly interesting for DBC, which needs to patch two bytecodes
+// This test was mostly interesting for DBC, which needed to patch two bytecodes
 // to create a breakpoint for fast Smi ops.
 
 import 'package:observatory/service_io.dart';
diff --git a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
index a0d7f9e..5b7d1ec 100644
--- a/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_cpu_profile_timeline_rpc_test.dart
@@ -55,7 +55,7 @@
 
 var vmArgs = [
   '--profiler=true',
-  '--profile-vm=false', // So this also works with DBC and KBC.
+  '--profile-vm=false', // So this also works with KBC.
 ];
 
 main(args) async =>
diff --git a/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart b/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart
index aa55eb3..542b476 100644
--- a/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_cpu_samples_rpc_test.dart
@@ -55,7 +55,7 @@
 
 var vmArgs = [
   '--profiler=true',
-  '--profile-vm=false', // So this also works with DBC and KBC.
+  '--profile-vm=false', // So this also works with KBC.
 ];
 
 main(args) async =>
diff --git a/runtime/observatory/tests/service/get_flag_list_rpc_test.dart b/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
index d1ee705..35484f6 100644
--- a/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_flag_list_rpc_test.dart
@@ -96,7 +96,45 @@
     expect(result['type'], equals('Success'));
     await completer.future;
     expect(await getFlagValue(vm, kProfilePeriod), kValue.toString());
-  }
+  },
+
+  // Start and stop the profiler at runtime.
+  (VM vm) async {
+    final kProfiler = 'profiler';
+    if (await getFlagValue(vm, kProfiler) == 'false') {
+      // Either in release or product modes and the profiler is disabled.
+      return;
+    }
+    final params = {
+      'name': kProfiler,
+      'value': 'false',
+    };
+
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+    expect(await getFlagValue(vm, kProfiler), 'false');
+    try {
+      // Arbitrary RPC which checks whether or not the profiler is enabled.
+      await vm.isolates.first.invokeRpcNoUpgrade('getCpuSamples', {});
+      fail('Profiler is disabled and request should fail');
+    } on ServerRpcException catch (_) {/* Expected */}
+
+    // Clear CPU samples.
+    result = await vm.isolates.first.invokeRpcNoUpgrade('clearCpuSamples', {});
+    expect(result['type'], equals('Success'));
+
+    params['value'] = 'true';
+    result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+    expect(await getFlagValue(vm, kProfiler), 'true');
+
+    try {
+      // Arbitrary RPC which checks whether or not the profiler is enabled.
+      result = await vm.isolates.first.invokeRpcNoUpgrade('getCpuSamples', {});
+    } on ServerRpcException catch (e) {
+      fail('Profiler is enabled and request should succeed. Error:\n$e');
+    }
+  },
 ];
 
 main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/get_isolate_group_memory_usage.dart b/runtime/observatory/tests/service/get_isolate_group_memory_usage.dart
new file mode 100644
index 0000000..8a834d9
--- /dev/null
+++ b/runtime/observatory/tests/service/get_isolate_group_memory_usage.dart
@@ -0,0 +1,64 @@
+// 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:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': vm.isolateGroups.first.id,
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('MemoryUsage'));
+    expect(result['heapUsage'], isPositive);
+    expect(result['heapCapacity'], isPositive);
+    expect(result['externalUsage'], isPositive);
+  },
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "getIsolateGroupMemoryUsage: invalid 'isolateGroupId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate group id, not found.
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': 'isolateGroups/9999999999',
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Expired'));
+    expect(result['valueAsString'], equals('<expired>'));
+  },
+
+  // isolate id was passed instead of isolate group id.
+  (VM vm) async {
+    final params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Expired'));
+    expect(result['valueAsString'], equals('<expired>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index de51a71..ce8af6b 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -895,7 +895,7 @@
       }
     }
     if (!use_field_guards) {
-      return; // skip the test if guards are not enabled(like on simdbc64)
+      return; // skip the test if guards are not enabled
     }
 
     // Call eval to get a class id.
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index f062d33..a950dd0 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(27));
+    expect(result['minor'], equals(28));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory/tests/service/get_vm_rpc_test.dart b/runtime/observatory/tests/service/get_vm_rpc_test.dart
index 9f63409..0e924a3 100644
--- a/runtime/observatory/tests/service/get_vm_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_rpc_test.dart
@@ -24,6 +24,8 @@
     expect(result['startTime'], isPositive);
     expect(result['isolates'].length, isPositive);
     expect(result['isolates'][0]['type'], equals('@Isolate'));
+    expect(result['isolateGroups'].length, isPositive);
+    expect(result['isolateGroups'][0]['type'], equals('@IsolateGroup'));
   },
 ];
 
diff --git a/runtime/observatory/tests/service/http_get_isolate_group_rpc_common.dart b/runtime/observatory/tests/service/http_get_isolate_group_rpc_common.dart
new file mode 100644
index 0000000..2b28be5
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_group_rpc_common.dart
@@ -0,0 +1,83 @@
+// 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:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart' as S;
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> getIsolateGroupId(
+    io.HttpClient httpClient, Uri serverUri) async {
+  // Build the request.
+  final pathSegments = <String>[]..addAll(serverUri.pathSegments);
+  const method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = serverUri.replace(pathSegments: pathSegments);
+  final request = await httpClient.getUrl(requestUri);
+  final Map response = await (await request.close())
+      .cast<List<int>>()
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+  final result = response['result'];
+  return result['isolateGroups'][0]['id'];
+}
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  expect(info.serverUri, isNotNull);
+  final httpClient = new io.HttpClient();
+
+  // Build the request.
+  final params = <String, String>{
+    'isolateGroupId': await getIsolateGroupId(httpClient, info.serverUri),
+  };
+
+  const method = 'getIsolateGroup';
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri
+      .replace(pathSegments: pathSegments, queryParameters: params);
+
+  try {
+    final request = await httpClient.getUrl(requestUri);
+    final response = await request.close();
+    final Map jsonResponse = await response
+        .cast<List<int>>()
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    final result = jsonResponse['result'];
+    expect(result['type'], equals('IsolateGroup'));
+    expect(result['id'], startsWith('isolateGroups/'));
+    expect(result['number'], new isInstanceOf<String>());
+    expect(result['isolates'].length, isPositive);
+    expect(result['isolates'][0]['type'], equals('@Isolate'));
+  } catch (e) {
+    fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    expect(true, true);
+  }
+];
diff --git a/runtime/observatory/tests/service/http_get_isolate_group_rpc_test.dart b/runtime/observatory/tests/service/http_get_isolate_group_rpc_test.dart
new file mode 100644
index 0000000..eb382b1
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_group_rpc_test.dart
@@ -0,0 +1,14 @@
+// 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 'http_get_isolate_group_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
index 06c47dc..f49e5a4 100644
--- a/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
+++ b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
@@ -78,6 +78,7 @@
     expect(result['breakpoints'].length, isZero);
     expect(result['_heaps']['new']['type'], equals('HeapSpace'));
     expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+    expect(result['isolate_group']['type'], equals('@IsolateGroup'));
   } catch (e) {
     fail('invalid request: $e');
   }
diff --git a/runtime/observatory/tests/service/http_get_vm_rpc_common.dart b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
index 7298b3d..18a0abe 100644
--- a/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
+++ b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
@@ -46,6 +46,8 @@
     expect(result['startTime'], isPositive);
     expect(result['isolates'].length, isPositive);
     expect(result['isolates'][0]['type'], equals('@Isolate'));
+    expect(result['isolateGroups'].length, isPositive);
+    expect(result['isolateGroups'][0]['type'], equals('@IsolateGroup'));
   } catch (e) {
     fail('invalid request: $e');
   }
diff --git a/runtime/observatory/tests/service/network_profiling_test.dart b/runtime/observatory/tests/service/network_profiling_test.dart
new file mode 100644
index 0000000..1705af9
--- /dev/null
+++ b/runtime/observatory/tests/service/network_profiling_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.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'package:observatory/service_io.dart';
+import 'package:observatory/sample_profile.dart';
+import 'package:unittest/unittest.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void test() {
+  // TODO(bkonyi): do actual network operations.
+  print('hello world!');
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    await isolate.load();
+
+    // Ensure all network profiling service extensions are registered.
+    const kGetHttpProfileRPC = 'ext.dart.io.getHttpProfile';
+    const kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
+    expect(isolate.extensionRPCs.length, greaterThanOrEqualTo(2));
+    expect(isolate.extensionRPCs.contains(kGetHttpProfileRPC), isTrue);
+    expect(isolate.extensionRPCs.contains(kGetSocketProfileRPC), isTrue);
+
+    // Test invocations (will throw on failure).
+    var response = await isolate.invokeRpcNoUpgrade(kGetHttpProfileRPC, {});
+    expect(response['type'], 'HttpProfile');
+    response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: test);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index ea1e417..a8f8dd4 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -46,21 +46,6 @@
 [ $arch == simarm || $arch == simarm64 ]
 *: Pass, Slow
 
-[ $arch == simdbc || $arch == simdbc64 ]
-async_single_step_exception_test: RuntimeError # Issue 29218
-get_cpu_profile_timeline_rpc_test: SkipByDesign
-implicit_getter_setter_test: RuntimeError # Field guards unimplemented.
-next_through_catch_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975).
-next_through_simple_async_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975).
-next_through_simple_linear_2_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975).
-step_through_function_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975).
-step_through_getter_test: RuntimeError # Debugging StringConcatenation doesn't work the same on simdbc as on other platforms (bug #28975).
-
-[ $arch == simdbc || $arch == simdbc64 || $mode == debug ]
-break_on_default_constructor_test: Pass, Slow
-debugger_location_second_test: Pass, Slow
-debugger_location_test: Pass, Slow
-
 # All tests use dart:io
 [ $compiler == dart2js || $browser ]
 *: SkipByDesign
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 316e3f2..0037e6e 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -53,16 +53,9 @@
 get_vm_timeline_rpc_test: Pass, Slow
 rewind_optimized_out_test: SkipSlow # Timeout
 
-[ $arch != simarm && $arch != simarm64 && $arch != simdbc && $compiler == dartk ]
+[ $arch != simarm && $arch != simarm64 && $compiler == dartk ]
 complex_reload_test: RuntimeError
 
-[ $arch == simdbc64 && $compiler == dartk ]
-eval_test: RuntimeError, Timeout # Issue #34736
-evaluate_in_frame_rpc_test: RuntimeError, Timeout # Issue #34736
-
-[ $arch == simdbc64 && $compiler == dartk && $mode == debug ]
-eval_test: Pass, Slow
-
 [ $compiler == dartkb && ($builder_tag == bytecode_interpreter || $builder_tag == bytecode_mixed) ]
 *: Skip # There are still timeouts in the interpreter and mixed modes which cause infra timeouts.
 
@@ -122,7 +115,7 @@
 step_through_switch_test: Skip # Times out. Issue 32137.
 step_through_switch_with_continue_test: Skip # Times out. Issue 32137.
 
-[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
 add_breakpoint_rpc_kernel_test: RuntimeError # Issue #34736
 async_generator_breakpoint_test: SkipByDesign # No incremental compiler available.
 bad_reload_test: Skip # Times out on sim architectures, also RuntimeError.
diff --git a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
index 548c6b2..c36f561 100644
--- a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
+++ b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
@@ -35,19 +35,19 @@
 List<String> expected = [
   "$file:${LINE + 0}:17", // on "Foo" (in "new Foo()")
   "$file:${LINE + 1}:11", // on "="
-  "list.dart:101:24", // on parameter to "contains"
-  "list.dart:102:23", // on "length" in "this.length"
-  "list.dart:103:16", // on "=" in "i = 0"
-  "list.dart:103:23", // on "<" in "i < length"
-  "list.dart:104:15", // on "[" in "this[i]"
+  "list.dart:105:24", // on parameter to "contains"
+  "list.dart:106:23", // on "length" in "this.length"
+  "list.dart:107:16", // on "=" in "i = 0"
+  "list.dart:107:23", // on "<" in "i < length"
+  "list.dart:108:15", // on "[" in "this[i]"
   "$file:${LINE + 13}:23", // on parameter in "operator []"
   "$file:${LINE + 14}:5", // on "return"
-  "list.dart:104:19", // on "=="
-  "list.dart:105:26", // on "length" in "this.length"
-  "list.dart:105:18", // on "!="
-  "list.dart:103:34", // on "++" in "i++"
-  "list.dart:103:23", // on "<" in "i < length"
-  "list.dart:109:5", // on "return"
+  "list.dart:108:19", // on "=="
+  "list.dart:109:26", // on "length" in "this.length"
+  "list.dart:109:18", // on "!="
+  "list.dart:107:34", // on "++" in "i++"
+  "list.dart:107:23", // on "<" in "i < length"
+  "list.dart:113:5", // on "return"
   "$file:${LINE + 4}:5", // on "print"
   "$file:${LINE + 6}:1" // on ending '}'
 ];
diff --git a/runtime/platform/atomic.h b/runtime/platform/atomic.h
index 95fa2b8..5fb1d45 100644
--- a/runtime/platform/atomic.h
+++ b/runtime/platform/atomic.h
@@ -63,67 +63,6 @@
   std::atomic<T> value_;
 };
 
-class AtomicOperations : public AllStatic {
- public:
-  // Atomically fetch the value at p and increment the value at p.
-  // Returns the original value at p.
-  static uintptr_t FetchAndIncrement(uintptr_t* p);
-  static intptr_t FetchAndIncrement(intptr_t* p);
-
-  // Atomically increment the value at p by 'value'.
-  static void IncrementBy(intptr_t* p, intptr_t value);
-  static void IncrementInt64By(int64_t* p, int64_t value);
-
-  // Atomically fetch the value at p and decrement the value at p.
-  // Returns the original value at p.
-  static uintptr_t FetchAndDecrement(uintptr_t* p);
-  static intptr_t FetchAndDecrement(intptr_t* p);
-
-  // Atomically decrement the value at p by 'value'.
-  static void DecrementBy(intptr_t* p, intptr_t value);
-
-  // Atomically compare *ptr to old_value, and if equal, store new_value.
-  // Returns the original value at ptr.
-  static uword CompareAndSwapWord(uword* ptr, uword old_value, uword new_value);
-  static uint32_t CompareAndSwapUint32(uint32_t* ptr,
-                                       uint32_t old_value,
-                                       uint32_t new_value);
-
-  // Performs a load of a word from 'ptr', but without any guarantees about
-  // memory order (i.e., no load barriers/fences).
-  template <typename T>
-  static T LoadRelaxed(T* ptr) {
-    return *static_cast<volatile T*>(ptr);
-  }
-
-  template <typename T>
-  static T LoadAcquire(T* ptr);
-
-  template <typename T>
-  static void StoreRelease(T* ptr, T value);
-
-  template <typename T>
-  static T* CompareAndSwapPointer(T** slot, T* old_value, T* new_value) {
-    return reinterpret_cast<T*>(AtomicOperations::CompareAndSwapWord(
-        reinterpret_cast<uword*>(slot), reinterpret_cast<uword>(old_value),
-        reinterpret_cast<uword>(new_value)));
-  }
-};
-
 }  // namespace dart
 
-#if defined(HOST_OS_ANDROID)
-#include "platform/atomic_android.h"
-#elif defined(HOST_OS_FUCHSIA)
-#include "platform/atomic_fuchsia.h"
-#elif defined(HOST_OS_LINUX)
-#include "platform/atomic_linux.h"
-#elif defined(HOST_OS_MACOS)
-#include "platform/atomic_macos.h"
-#elif defined(HOST_OS_WINDOWS)
-#include "platform/atomic_win.h"
-#else
-#error Unknown target os.
-#endif
-
 #endif  // RUNTIME_PLATFORM_ATOMIC_H_
diff --git a/runtime/platform/atomic_android.h b/runtime/platform/atomic_android.h
deleted file mode 100644
index cce35b9..0000000
--- a/runtime/platform/atomic_android.h
+++ /dev/null
@@ -1,73 +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.
-
-#ifndef RUNTIME_PLATFORM_ATOMIC_ANDROID_H_
-#define RUNTIME_PLATFORM_ATOMIC_ANDROID_H_
-
-#if !defined RUNTIME_PLATFORM_ATOMIC_H_
-#error Do not include atomic_android.h directly. Use atomic.h instead.
-#endif
-
-#if !defined(HOST_OS_ANDROID)
-#error This file should only be included on Android builds.
-#endif
-
-namespace dart {
-
-inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndIncrement(intptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_add(p, value);
-}
-
-inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-  // Some ARM implementations require 8-byte alignment for atomic access but
-  // not non-atomic access.
-  ASSERT((reinterpret_cast<uword>(p) % 8) == 0);
-  __sync_fetch_and_add(p, value);
-}
-
-inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndDecrement(intptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_sub(p, value);
-}
-
-inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
-                                                  uword old_value,
-                                                  uword new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
-                                                       uint32_t old_value,
-                                                       uint32_t new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-template <typename T>
-inline T AtomicOperations::LoadAcquire(T* ptr) {
-  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
-}
-
-template <typename T>
-inline void AtomicOperations::StoreRelease(T* ptr, T value) {
-  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
-}
-
-}  // namespace dart
-
-#endif  // RUNTIME_PLATFORM_ATOMIC_ANDROID_H_
diff --git a/runtime/platform/atomic_fuchsia.h b/runtime/platform/atomic_fuchsia.h
deleted file mode 100644
index 6af88f6..0000000
--- a/runtime/platform/atomic_fuchsia.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_PLATFORM_ATOMIC_FUCHSIA_H_
-#define RUNTIME_PLATFORM_ATOMIC_FUCHSIA_H_
-
-#if !defined RUNTIME_PLATFORM_ATOMIC_H_
-#error Do not include atomic_fuchsia.h directly. Use atomic.h instead.
-#endif
-
-#if !defined(HOST_OS_FUCHSIA)
-#error This file should only be included on Fuchsia builds.
-#endif
-
-namespace dart {
-
-inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndIncrement(intptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_add(p, value);
-}
-
-inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-  __sync_fetch_and_add(p, value);
-}
-
-inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndDecrement(intptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_sub(p, value);
-}
-
-inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
-                                                  uword old_value,
-                                                  uword new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
-                                                       uint32_t old_value,
-                                                       uint32_t new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-template <typename T>
-inline T AtomicOperations::LoadAcquire(T* ptr) {
-  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
-}
-
-template <typename T>
-inline void AtomicOperations::StoreRelease(T* ptr, T value) {
-  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
-}
-
-}  // namespace dart
-
-#endif  // RUNTIME_PLATFORM_ATOMIC_FUCHSIA_H_
diff --git a/runtime/platform/atomic_linux.h b/runtime/platform/atomic_linux.h
deleted file mode 100644
index b4bd342..0000000
--- a/runtime/platform/atomic_linux.h
+++ /dev/null
@@ -1,73 +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.
-
-#ifndef RUNTIME_PLATFORM_ATOMIC_LINUX_H_
-#define RUNTIME_PLATFORM_ATOMIC_LINUX_H_
-
-#if !defined RUNTIME_PLATFORM_ATOMIC_H_
-#error Do not include atomic_linux.h directly. Use atomic.h instead.
-#endif
-
-#if !defined(HOST_OS_LINUX)
-#error This file should only be included on Linux builds.
-#endif
-
-namespace dart {
-
-inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndIncrement(intptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_add(p, value);
-}
-
-inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-  // Some ARM implementations require 8-byte alignment for atomic access but
-  // not non-atomic access.
-  ASSERT((reinterpret_cast<uword>(p) % 8) == 0);
-  __sync_fetch_and_add(p, value);
-}
-
-inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndDecrement(intptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_sub(p, value);
-}
-
-inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
-                                                  uword old_value,
-                                                  uword new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
-                                                       uint32_t old_value,
-                                                       uint32_t new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-template <typename T>
-inline T AtomicOperations::LoadAcquire(T* ptr) {
-  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
-}
-
-template <typename T>
-inline void AtomicOperations::StoreRelease(T* ptr, T value) {
-  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
-}
-
-}  // namespace dart
-
-#endif  // RUNTIME_PLATFORM_ATOMIC_LINUX_H_
diff --git a/runtime/platform/atomic_macos.h b/runtime/platform/atomic_macos.h
deleted file mode 100644
index ba4433c..0000000
--- a/runtime/platform/atomic_macos.h
+++ /dev/null
@@ -1,73 +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.
-
-#ifndef RUNTIME_PLATFORM_ATOMIC_MACOS_H_
-#define RUNTIME_PLATFORM_ATOMIC_MACOS_H_
-
-#if !defined RUNTIME_PLATFORM_ATOMIC_H_
-#error Do not include atomic_macos.h directly. Use atomic.h instead.
-#endif
-
-#if !defined(HOST_OS_MACOS)
-#error This file should only be included on Mac OS X builds.
-#endif
-
-namespace dart {
-
-inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndIncrement(intptr_t* p) {
-  return __sync_fetch_and_add(p, 1);
-}
-
-inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_add(p, value);
-}
-
-inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-  // Some ARM implementations require 8-byte alignment for atomic access but
-  // not non-atomic access.
-  ASSERT((reinterpret_cast<uword>(p) % 8) == 0);
-  __sync_fetch_and_add(p, value);
-}
-
-inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline intptr_t AtomicOperations::FetchAndDecrement(intptr_t* p) {
-  return __sync_fetch_and_sub(p, 1);
-}
-
-inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-  __sync_fetch_and_sub(p, value);
-}
-
-inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
-                                                  uword old_value,
-                                                  uword new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
-                                                       uint32_t old_value,
-                                                       uint32_t new_value) {
-  return __sync_val_compare_and_swap(ptr, old_value, new_value);
-}
-
-template <typename T>
-inline T AtomicOperations::LoadAcquire(T* ptr) {
-  return __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
-}
-
-template <typename T>
-inline void AtomicOperations::StoreRelease(T* ptr, T value) {
-  __atomic_store_n(ptr, value, __ATOMIC_RELEASE);
-}
-
-}  // namespace dart
-
-#endif  // RUNTIME_PLATFORM_ATOMIC_MACOS_H_
diff --git a/runtime/platform/atomic_win.h b/runtime/platform/atomic_win.h
deleted file mode 100644
index 6431f4c..0000000
--- a/runtime/platform/atomic_win.h
+++ /dev/null
@@ -1,152 +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.
-
-#ifndef RUNTIME_PLATFORM_ATOMIC_WIN_H_
-#define RUNTIME_PLATFORM_ATOMIC_WIN_H_
-
-#if !defined RUNTIME_PLATFORM_ATOMIC_H_
-#error Do not include atomic_win.h directly. Use atomic.h instead.
-#endif
-
-#if !defined(HOST_OS_WINDOWS)
-#error This file should only be included on Windows builds.
-#endif
-
-namespace dart {
-
-inline uintptr_t AtomicOperations::FetchAndIncrement(uintptr_t* p) {
-#if defined(HOST_ARCH_X64)
-  return static_cast<uintptr_t>(
-             InterlockedIncrement64(reinterpret_cast<LONGLONG*>(p))) -
-         1;
-#elif defined(HOST_ARCH_IA32)
-  return static_cast<uintptr_t>(
-             InterlockedIncrement(reinterpret_cast<LONG*>(p))) -
-         1;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline intptr_t AtomicOperations::FetchAndIncrement(intptr_t* p) {
-#if defined(HOST_ARCH_X64)
-  return static_cast<intptr_t>(
-             InterlockedIncrement64(reinterpret_cast<LONGLONG*>(p))) -
-         1;
-#elif defined(HOST_ARCH_IA32)
-  return static_cast<intptr_t>(
-             InterlockedIncrement(reinterpret_cast<LONG*>(p))) -
-         1;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline void AtomicOperations::IncrementBy(intptr_t* p, intptr_t value) {
-#if defined(HOST_ARCH_X64)
-  InterlockedExchangeAdd64(reinterpret_cast<LONGLONG*>(p),
-                           static_cast<LONGLONG>(value));
-#elif defined(HOST_ARCH_IA32)
-  InterlockedExchangeAdd(reinterpret_cast<LONG*>(p), static_cast<LONG>(value));
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline void AtomicOperations::IncrementInt64By(int64_t* p, int64_t value) {
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
-  InterlockedExchangeAdd64(reinterpret_cast<LONGLONG*>(p),
-                           static_cast<LONGLONG>(value));
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline uintptr_t AtomicOperations::FetchAndDecrement(uintptr_t* p) {
-#if defined(HOST_ARCH_X64)
-  return static_cast<uintptr_t>(
-             InterlockedDecrement64(reinterpret_cast<LONGLONG*>(p))) +
-         1;
-#elif defined(HOST_ARCH_IA32)
-  return static_cast<uintptr_t>(
-             InterlockedDecrement(reinterpret_cast<LONG*>(p))) +
-         1;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline intptr_t AtomicOperations::FetchAndDecrement(intptr_t* p) {
-#if defined(HOST_ARCH_X64)
-  return static_cast<intptr_t>(
-             InterlockedDecrement64(reinterpret_cast<LONGLONG*>(p))) +
-         1;
-#elif defined(HOST_ARCH_IA32)
-  return static_cast<intptr_t>(
-             InterlockedDecrement(reinterpret_cast<LONG*>(p))) +
-         1;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline void AtomicOperations::DecrementBy(intptr_t* p, intptr_t value) {
-#if defined(HOST_ARCH_X64)
-  InterlockedExchangeAdd64(reinterpret_cast<LONGLONG*>(p),
-                           static_cast<LONGLONG>(-value));
-#elif defined(HOST_ARCH_IA32)
-  InterlockedExchangeAdd(reinterpret_cast<LONG*>(p), static_cast<LONG>(-value));
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-inline uword AtomicOperations::CompareAndSwapWord(uword* ptr,
-                                                  uword old_value,
-                                                  uword new_value) {
-#if defined(HOST_ARCH_X64)
-  return static_cast<uword>(InterlockedCompareExchange64(
-      reinterpret_cast<LONGLONG*>(ptr), static_cast<LONGLONG>(new_value),
-      static_cast<LONGLONG>(old_value)));
-#elif defined(HOST_ARCH_IA32)
-  return static_cast<uword>(InterlockedCompareExchange(
-      reinterpret_cast<LONG*>(ptr), static_cast<LONG>(new_value),
-      static_cast<LONG>(old_value)));
-#else
-#error Unsupported host architecture.
-#endif
-}
-inline uint32_t AtomicOperations::CompareAndSwapUint32(uint32_t* ptr,
-                                                       uint32_t old_value,
-                                                       uint32_t new_value) {
-#if (defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32))
-  return static_cast<uint32_t>(InterlockedCompareExchange(
-      reinterpret_cast<LONG*>(ptr), static_cast<LONG>(new_value),
-      static_cast<LONG>(old_value)));
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-template <typename T>
-inline T AtomicOperations::LoadAcquire(T* ptr) {
-#if (defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32))
-  return *ptr;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-template <typename T>
-inline void AtomicOperations::StoreRelease(T* ptr, T value) {
-#if (defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32))
-  *ptr = value;
-#else
-#error Unsupported host architecture.
-#endif
-}
-
-}  // namespace dart
-
-#endif  // RUNTIME_PLATFORM_ATOMIC_WIN_H_
diff --git a/runtime/platform/elf.h b/runtime/platform/elf.h
index 729ac7d..939225e 100644
--- a/runtime/platform/elf.h
+++ b/runtime/platform/elf.h
@@ -135,10 +135,11 @@
 static const intptr_t PF_R = 4;
 
 static const intptr_t SHT_PROGBITS = 1;
+static const intptr_t SHT_SYMTAB = 2;
 static const intptr_t SHT_STRTAB = 3;
 static const intptr_t SHT_HASH = 5;
-static const intptr_t SHT_DYNSYM = 11;
 static const intptr_t SHT_DYNAMIC = 6;
+static const intptr_t SHT_DYNSYM = 11;
 
 static const intptr_t SHF_WRITE = 0x1;
 static const intptr_t SHF_ALLOC = 0x2;
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index d754abf..9d4981f 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -299,8 +299,7 @@
 #endif
 
 #if !defined(TARGET_ARCH_ARM) && !defined(TARGET_ARCH_X64) &&                  \
-    !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64) &&               \
-    !defined(TARGET_ARCH_DBC)
+    !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_ARM64)
 // No target architecture specified pick the one matching the host architecture.
 #if defined(HOST_ARCH_ARM)
 #define TARGET_ARCH_ARM 1
@@ -319,12 +318,6 @@
 #define TARGET_ARCH_IS_32_BIT 1
 #elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
 #define TARGET_ARCH_IS_64_BIT 1
-#elif defined(TARGET_ARCH_DBC)
-#if defined(ARCH_IS_32_BIT)
-#define TARGET_ARCH_IS_32_BIT 1
-#else
-#define TARGET_ARCH_IS_64_BIT 1
-#endif
 #else
 #error Automatic target architecture detection failed.
 #endif
@@ -363,9 +356,6 @@
 #define USING_SIMULATOR 1
 #endif
 
-#elif defined(TARGET_ARCH_DBC)
-#define USING_SIMULATOR 1
-
 #else
 #error Unknown architecture.
 #endif
@@ -419,12 +409,6 @@
 #define DUAL_MAPPING_SUPPORTED 1
 #endif
 
-// Disable background threads by default on armv5te. The relevant
-// implementations are uniprocessors.
-#if !defined(TARGET_ARCH_ARM_5TE)
-#define ARCH_IS_MULTI_CORE 1
-#endif
-
 // Short form printf format specifiers
 #define Pd PRIdPTR
 #define Pu PRIuPTR
diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni
index cc02ccb..02f23fb 100644
--- a/runtime/platform/platform_sources.gni
+++ b/runtime/platform/platform_sources.gni
@@ -10,11 +10,6 @@
   "assert.cc",
   "assert.h",
   "atomic.h",
-  "atomic_android.h",
-  "atomic_fuchsia.h",
-  "atomic_linux.h",
-  "atomic_macos.h",
-  "atomic_win.h",
   "floating_point.h",
   "floating_point_win.cc",
   "floating_point_win.h",
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 819206f..ee24ad6 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -340,11 +340,9 @@
   static uword NBitMask(uint32_t n) {
     ASSERT(n <= kBitsPerWord);
     if (n == kBitsPerWord) {
-#if defined(TARGET_ARCH_X64)
-      return 0xffffffffffffffffll;
-#else
-      return 0xffffffff;
-#endif
+      static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord,
+                            "Unexpected uword size");
+      return std::numeric_limits<uword>::max();
     }
     return (1ll << n) - 1;
   }
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index 381d94a..f266ec0 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -28,7 +28,7 @@
   dart_runtime_mode = "develop"
 
   # Explicitly set the target architecture to use a simulator.
-  # Available options are: arm, arm64, x64, ia32, and dbc.
+  # Available options are: arm, arm64, x64, ia32.
   dart_target_arch = target_cpu
 
   # The optimization level to use for debug builds. Defaults to 0 for builds with
@@ -80,7 +80,7 @@
     dart_component_kind = "static_library"
   }
 
-  # Whether the VM's platform dill file contains bytecode.
+  # Controls whether the VM uses bytecode.
   dart_platform_bytecode = false
 
   # Whether the VM includes the kernel service in all modes (debug, release,
diff --git a/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart b/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart
new file mode 100644
index 0000000..72f6b76
--- /dev/null
+++ b/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart
@@ -0,0 +1,32 @@
+// 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.
+
+// OtherResources=bytecode_and_ast_mix_test_body.dart
+
+// Tests the mix of kernel AST (test) and bytecode dill files (core libraries).
+// Verifies that kernel AST can reference a not yet loaded bytecode class
+// through a constant in metadata.
+
+import 'dart:io' show Platform;
+
+import 'package:path/path.dart' as path;
+import 'snapshot_test_helper.dart';
+
+main() async {
+  final testScriptUri =
+      Platform.script.resolve('bytecode_and_ast_mix_test_body.dart');
+  await withTempDir((String temp) async {
+    final dillPath = path.join(temp, 'ast.dill');
+    final testPath = testScriptUri.toFilePath();
+
+    final buildResult = await runGenKernel('BUILD AST DILL FILE', [
+      '--no-gen-bytecode',
+      '--output=$dillPath',
+      testPath,
+    ]);
+    print(buildResult);
+    final runResult = await runDart('RUN FROM AST DILL FILE', [dillPath]);
+    expectOutput("OK", runResult);
+  });
+}
diff --git a/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart b/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart
new file mode 100644
index 0000000..dac3c07
--- /dev/null
+++ b/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart
@@ -0,0 +1,23 @@
+// 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:mirrors';
+import 'package:expect/expect.dart';
+
+class A {
+  void foo() {}
+}
+
+class B extends A {
+  @override
+  void foo() {}
+}
+
+main() {
+  ClassMirror classB = reflectClass(B);
+  MethodMirror foo = classB.declarations[#foo];
+  final annotation = foo.metadata[0].reflectee;
+  Expect.isTrue(annotation.toString().contains('_Override'));
+  print('OK');
+}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart
new file mode 100644
index 0000000..a44f8f2
--- /dev/null
+++ b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart
@@ -0,0 +1,51 @@
+// 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.
+
+// OtherResources=bytecode_with_ast_in_aot_test_body1.dart
+// OtherResources=bytecode_with_ast_in_aot_test_body2.dart
+
+// Tests that gen_kernel is able to produce dill file with both bytecode
+// and AST in AOT mode, and gen_snapshot is able to consume them.
+// Two test cases are only different in number of entry points, so
+// obfuscation prohibitions metadata has different size, causing
+// different alignment of bytecode metadata.
+
+import 'dart:io' show Platform;
+
+import 'package:path/path.dart' as path;
+import 'snapshot_test_helper.dart';
+
+testAOTOnBytecodeWithAST(String temp, String source) async {
+  final sourcePath = Platform.script.resolve(source).toFilePath();
+  final dillPath = path.join(temp, '${source}.dill');
+  final snapshotPath = path.join(temp, '${source}.so');
+
+  final genKernelResult = await runGenKernel('BUILD DILL FILE', [
+    '--aot',
+    '--gen-bytecode',
+    '--no-drop-ast',
+    '--output=$dillPath',
+    sourcePath,
+  ]);
+  print(genKernelResult);
+  final genSnapshotResult = await runGenSnapshot('GENERATE SNAPSHOT', [
+    '--use-bytecode-compiler',
+    '--snapshot-kind=app-aot-elf',
+    '--elf=$snapshotPath',
+    dillPath,
+  ]);
+  print(genSnapshotResult);
+  final runResult =
+      await runBinary('RUN SNAPSHOT', dartPrecompiledRuntime, [snapshotPath]);
+  expectOutput("OK", runResult);
+}
+
+main() async {
+  await withTempDir((String temp) async {
+    await testAOTOnBytecodeWithAST(
+        temp, 'bytecode_with_ast_in_aot_test_body1.dart');
+    await testAOTOnBytecodeWithAST(
+        temp, 'bytecode_with_ast_in_aot_test_body2.dart');
+  });
+}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart
new file mode 100644
index 0000000..18ae42b
--- /dev/null
+++ b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart
@@ -0,0 +1,19 @@
+// 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.
+
+// Test case for bytecode_with_ast_in_aot_test.dart.
+// Contains 1 entry point.
+
+import 'package:expect/expect.dart';
+
+class A {
+  // Make sure obfuscation prohibitions metadata is generated.
+  @pragma('vm:entry-point')
+  void foofoo1() {}
+}
+
+main() {
+  new A();
+  print('OK');
+}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart
new file mode 100644
index 0000000..c3a1e7e
--- /dev/null
+++ b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart
@@ -0,0 +1,24 @@
+// 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.
+
+// Test case for bytecode_with_ast_in_aot_test.dart.
+// Contains 2 entry points.
+
+import 'package:expect/expect.dart';
+
+class A {
+  // Make sure obfuscation prohibitions metadata is generated.
+  @pragma('vm:entry-point')
+  void foofoo1() {}
+
+  // One more entry for obfuscation prohibitions metadata,
+  // raises the chances that subsequent bytecode metadata is misaligned.
+  @pragma('vm:entry-point')
+  void foofoo2() {}
+}
+
+main() {
+  new A();
+  print('OK');
+}
diff --git a/runtime/tests/vm/dart/causal_stacks/async_throws_stack_no_causal_test.dart b/runtime/tests/vm/dart/causal_stacks/async_throws_stack_no_causal_test.dart
new file mode 100644
index 0000000..62e72dc
--- /dev/null
+++ b/runtime/tests/vm/dart/causal_stacks/async_throws_stack_no_causal_test.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// VMOptions=--no-causal-async-stacks
+
+import 'dart:async';
+
+import 'utils.dart';
+
+Future<void> main(List<String> args) async => doTestsNoCausal();
diff --git a/runtime/tests/vm/dart/causal_stacks/async_throws_stack_test.dart b/runtime/tests/vm/dart/causal_stacks/async_throws_stack_test.dart
new file mode 100644
index 0000000..eb1f207
--- /dev/null
+++ b/runtime/tests/vm/dart/causal_stacks/async_throws_stack_test.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// VMOptions=--causal-async-stacks
+
+import 'dart:async';
+
+import 'utils.dart';
+
+Future<void> main(List<String> args) async => doTestsCausal();
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
new file mode 100644
index 0000000..6038e33
--- /dev/null
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -0,0 +1,265 @@
+// 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:async';
+import 'dart:io';
+import 'dart:math';
+import 'dart:typed_data';
+
+import 'package:path/path.dart' as path;
+import 'package:expect/expect.dart';
+import 'package:expect/matchers_lite.dart';
+
+Matcher startsWith(String expected) {
+  return (Object actual) {
+    if (actual is String) {
+      Expect.equals(
+          expected, actual.substring(0, min(expected.length, actual.length)));
+      return;
+    }
+    Expect.fail('Expected String.');
+  };
+}
+
+void assertStack(Map expected, StackTrace stack_trace) {
+  final List<String> frames = stack_trace.toString().split('\n');
+  for (int i in expected.keys) {
+    expect(frames[i], startsWith(expected[i]));
+  }
+}
+
+Future<void> doTest(Future f(), Map<int, String> expected_stack) async {
+  // Caller catches exception.
+  try {
+    await f();
+    Expect.fail('No exception thrown!');
+  } on String catch (e, s) {
+    assertStack(expected_stack, s);
+  }
+
+  // Caller catches but a then is set.
+  try {
+    await f().then((e) {
+      // Ignore.
+    });
+    Expect.fail('No exception thrown!');
+  } on String catch (e, s) {
+    assertStack(expected_stack, s);
+  }
+
+  // Caller doesn't catch, but we have a catchError set.
+  StackTrace stack_trace;
+  await f().catchError((e, s) {
+    stack_trace = s;
+  });
+  assertStack(expected_stack, stack_trace);
+}
+
+// Test functions:
+
+Future<void> throwSync() {
+  throw '';
+}
+
+Future<void> throwAsync() async {
+  await 0;
+  throw '';
+}
+
+// ----
+// Scenario: All async functions yielded at least once before throw:
+// ----
+Future<void> allYield() async {
+  await 0;
+  await allYield2();
+}
+
+Future<void> allYield2() async {
+  await 0;
+  await allYield3();
+}
+
+Future<void> allYield3() async {
+  await 0;
+  throwSync();
+}
+
+// For: --causal-async-stacks
+Map<int, String> allYieldMapCausal = {
+  0: '#0      throwSync ',
+  1: '#1      allYield3 ',
+  2: '<asynchronous suspension>',
+  3: '#2      allYield2 ',
+  4: '<asynchronous suspension>',
+  5: '#3      allYield ',
+  4: '<asynchronous suspension>',
+  // Callers, like doTest and main ..
+};
+
+// For: --no-causal-async-stacks
+Map<int, String> allYieldMapNoCausal = {
+  0: '#0      throwSync ',
+  1: '#1      allYield3 ',
+  2: '#2      _RootZone.runUnary ',
+  // The rest are more Dart internal async mechanisms..
+};
+
+// ----
+// Scenario: None of the async functions yieled before the throw:
+// ----
+Future<void> noYields() async {
+  await noYields2();
+}
+
+Future<void> noYields2() async {
+  await noYields3();
+}
+
+Future<void> noYields3() async {
+  throwSync();
+}
+
+// For: --causal-async-stacks
+Map<int, String> noYieldsMapCausal = {
+  0: '#0      throwSync ',
+  1: '#1      noYields3 ',
+  2: '<asynchronous suspension>',
+  3: '#2      noYields2 ',
+  4: '<asynchronous suspension>',
+  5: '#3      noYields ',
+  4: '<asynchronous suspension>',
+  // Callers, like doTest and main ..
+};
+
+// For: --no-causal-async-stacks
+Map<int, String> noYieldsMapNoCausal = {
+  0: '#0      throwSync ',
+  1: '#1      noYields3 ',
+  // Skip: _AsyncAwaitCompleter.start
+  3: '#3      noYields3 ',
+  4: '#4      noYields2 ',
+  // Skip: _AsyncAwaitCompleter.start
+  6: '#6      noYields2 ',
+  7: '#7      noYields ',
+  // Skip: _AsyncAwaitCompleter.start
+  9: '#9      noYields ',
+  // Calling functions like doTest and main ..
+};
+
+// ----
+// Scenario: Mixed yielding and non-yielding frames:
+// ----
+Future<void> mixedYields() async {
+  await mixedYields2();
+}
+
+Future<void> mixedYields2() async {
+  await 0;
+  await mixedYields3();
+}
+
+Future<void> mixedYields3() async {
+  return throwAsync();
+}
+
+// For: --causal-async-stacks
+Map<int, String> mixedYieldsMapCausal = {
+  0: '#0      throwAsync ',
+  1: '<asynchronous suspension>',
+  2: '#1      mixedYields3 ',
+  3: '<asynchronous suspension>',
+  4: '#2      mixedYields2 ',
+  5: '<asynchronous suspension>',
+  6: '#3      mixedYields ',
+  7: '<asynchronous suspension>',
+  // Callers, like doTest and main ..
+};
+
+// For: --no-causal-async-stacks
+Map<int, String> mixedYieldsMapNoCausal = {
+  0: '#0      throwAsync ',
+  1: '#1      _RootZone.runUnary ',
+  // The rest are more Dart internal async mechanisms..
+};
+
+// ----
+// Scenario: Non-async frame:
+// ----
+Future<void> syncSuffix() async {
+  await syncSuffix2();
+}
+
+Future<void> syncSuffix2() async {
+  await 0;
+  await syncSuffix3();
+}
+
+Future<void> syncSuffix3() {
+  return throwAsync();
+}
+
+// For: --causal-async-stacks
+Map<int, String> syncSuffixMapCausal = {
+  0: '#0      throwAsync ',
+  1: '<asynchronous suspension>',
+  2: '#1      syncSuffix3 ',
+  3: '#2      syncSuffix2 ',
+  4: '<asynchronous suspension>',
+  5: '#3      syncSuffix ',
+  6: '<asynchronous suspension>',
+  // Callers, like doTest and main ..
+};
+
+// For: --no-causal-async-stacks
+Map<int, String> syncSuffixMapNoCausal = {
+  0: '#0      throwAsync ',
+  1: '#1      _RootZone.runUnary ',
+  // The rest are more Dart internal async mechanisms..
+};
+
+// ----
+// Scenario: Caller is non-async, has no upwards stack:
+// ----
+
+Future nonAsyncNoStack() async => await nonAsyncNoStack1();
+
+Future nonAsyncNoStack1() async => await nonAsyncNoStack2();
+
+Future nonAsyncNoStack2() async => Future.value(0).then((_) => throwAsync());
+
+// For: --causal-async-stacks
+Map<int, String> nonAsyncNoStackMapCausal = {
+  0: '#0      throwAsync ',
+  1: '<asynchronous suspension>',
+  2: '#1      nonAsyncNoStack2.<anonymous closure> ',
+  3: '#2      _RootZone.runUnary ',
+  // The rest are more Dart internal async mechanisms..
+};
+
+// For: --no-causal-async-stacks
+Map<int, String> nonAsyncNoStackMapNoCausal = {
+  0: '#0      throwAsync ',
+  1: '#1      _RootZone.runUnary ',
+  // The rest are more Dart internal async mechanisms..
+};
+
+// ----
+// Test "Suites":
+// ----
+
+Future<void> doTestsCausal() async {
+  await doTest(allYield, allYieldMapCausal);
+  await doTest(noYields, noYieldsMapCausal);
+  await doTest(mixedYields, mixedYieldsMapCausal);
+  await doTest(syncSuffix, syncSuffixMapCausal);
+  await doTest(nonAsyncNoStack, nonAsyncNoStackMapCausal);
+}
+
+Future<void> doTestsNoCausal() async {
+  await doTest(allYield, allYieldMapNoCausal);
+  await doTest(noYields, noYieldsMapNoCausal);
+  await doTest(mixedYields, mixedYieldsMapNoCausal);
+  await doTest(syncSuffix, syncSuffixMapNoCausal);
+  await doTest(nonAsyncNoStack, nonAsyncNoStackMapNoCausal);
+}
diff --git a/runtime/tests/vm/dart/emit_aot_size_info_flag_test.dart b/runtime/tests/vm/dart/emit_aot_size_info_flag_test.dart
new file mode 100644
index 0000000..8c647eb0
--- /dev/null
+++ b/runtime/tests/vm/dart/emit_aot_size_info_flag_test.dart
@@ -0,0 +1,109 @@
+// 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:async";
+import "dart:io";
+import "dart:convert";
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+
+main(List<String> args) async {
+  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
+    return; // Running in JIT: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and gen_snapshot not available on the test device.
+  }
+
+  final buildDir = path.dirname(Platform.executable);
+  final sdkDir = path.dirname(path.dirname(buildDir));
+  final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
+  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  final aotRuntime = path.join(buildDir, 'dart_precompiled_runtime');
+
+  await withTempDir((String tempDir) async {
+    final script = path.join(sdkDir, 'pkg/kernel/bin/dump.dart');
+    final scriptDill = path.join(tempDir, 'kernel_dump.dill');
+    final appHeapsnapshot = path.join(tempDir, 'app.heapsnapshot');
+    final appSizesJson = path.join(tempDir, 'app-sizes.json');
+
+    // Compile script to Kernel IR.
+    await run('pkg/vm/tool/gen_kernel', <String>[
+      '--aot',
+      '--platform=$platformDill',
+      '-o',
+      scriptDill,
+      script,
+    ]);
+
+    // Run the AOT compiler with the size information flags set.
+    final elfFile = path.join(tempDir, 'aot.snapshot');
+    await Future.wait(<Future>[
+      run(genSnapshot, <String>[
+        '--snapshot-kind=app-aot-elf',
+        '--print-instructions-sizes-to=$appSizesJson',
+        '--write-v8-snapshot-profile-to=$appHeapsnapshot',
+        '--elf=$elfFile',
+        scriptDill,
+      ]),
+    ]);
+
+    // Ensure we can actually run the code.
+    await Future.wait(<Future>[
+      run(aotRuntime, <String>[
+        elfFile,
+        scriptDill,
+        path.join(tempDir, 'ignored.txt'),
+      ]),
+    ]);
+
+    // Ensure we can read the files and they look legitimate.
+    final appHeapsnapshotBytes = await readFile(appHeapsnapshot);
+    final snapshotMap = json.decode(appHeapsnapshotBytes);
+    Expect.isTrue(snapshotMap is Map);
+    Expect.isTrue(snapshotMap.keys.contains('snapshot'));
+
+    final appSizesJsonBytes = await readFile(appSizesJson);
+    final sizeList = json.decode(appSizesJsonBytes);
+    Expect.isTrue(sizeList is List);
+    Expect.isTrue(sizeList[0] is Map);
+    Expect.isTrue(sizeList[0].keys.toSet().containsAll(['n', 's']));
+  });
+}
+
+Future<String> readFile(String file) {
+  return new File(file).readAsString();
+}
+
+Future run(String executable, List<String> args) async {
+  print('Running $executable ${args.join(' ')}');
+
+  final result = await Process.run(executable, args);
+  final String stdout = result.stdout;
+  final String stderr = result.stderr;
+  if (stdout.isNotEmpty) {
+    print('stdout:');
+    print(stdout);
+  }
+  if (stderr.isNotEmpty) {
+    print('stderr:');
+    print(stderr);
+  }
+
+  if (result.exitCode != 0) {
+    throw 'Command failed with non-zero exit code (was ${result.exitCode})';
+  }
+}
+
+Future withTempDir(Future fun(String dir)) async {
+  final tempDir =
+      Directory.systemTemp.createTempSync('aot-size-info-flags-test');
+  try {
+    await fun(tempDir.path);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
diff --git a/runtime/tests/vm/dart/regress38965_test.dart b/runtime/tests/vm/dart/regress38965_test.dart
new file mode 100644
index 0000000..ef9f4fd
--- /dev/null
+++ b/runtime/tests/vm/dart/regress38965_test.dart
@@ -0,0 +1,11 @@
+// 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.
+
+// Regression test for dartbug.com/38965.
+
+int a = -1;
+
+main() {
+  false ? (-0.0 as int) : (++a);
+}
diff --git a/runtime/tests/vm/dart/regress38979_test.dart b/runtime/tests/vm/dart/regress38979_test.dart
new file mode 100644
index 0000000..b128249
--- /dev/null
+++ b/runtime/tests/vm/dart/regress38979_test.dart
@@ -0,0 +1,58 @@
+// 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.
+
+// Verifies that compiler doesn't crash on a particular piece of code.
+
+import "package:expect/expect.dart";
+import 'dart:typed_data';
+
+Int8List var3 = Int8List(1);
+bool var14 = true;
+Duration var15 = Duration();
+int var16 = 22;
+String var18 = '';
+Map<bool, bool> var25 = {};
+Map<bool, int> var26 = {};
+Map<int, String> var30 = {};
+Map<String, bool> var31 = {};
+
+int foo1(Int8List par1, Map<bool, int> par2) {
+  throw 'err';
+}
+
+class X0 {
+  Int32x4 foo0_0(Duration par1, Set<bool> par2) {
+    if (var14) {
+      {
+        int loc0 = 0;
+        do {
+          var31 = {
+            (String.fromCharCode(((true ? true : true)
+                    ? (var14 ? 33 : var16)
+                    : (-(foo1(var3,
+                        {(false ? false : var14): (true ? 20 : var3[27])})))))):
+                ((((var16 > (-((-(loc0))))) ? Duration() : Duration()) +
+                        (var14 ? (true ? var15 : par1) : Duration())) <
+                    Duration()),
+            (((var30[(Int32x4.yzxw as int)]).toUpperCase()) +
+                (Uri.encodeComponent(('2' ??
+                    (var25[true]
+                        ? (String.fromEnvironment(''))
+                        : var18))))): (!(var14)),
+            (var31['MgOdzM']
+                    ? var30[15]
+                    : (('D9q6Ma').substring(
+                        (~((--var16))), foo1(var3, (false ? {} : var26))))):
+                (!(false)),
+          };
+        } while (++loc0 < 39);
+      }
+    }
+  }
+}
+
+main() {
+  Expect.throws(() => X0().foo0_0(Duration(), {true, false}),
+      (e) => e is NoSuchMethodError);
+}
diff --git a/runtime/tests/vm/dart/regress_39152_test.dart b/runtime/tests/vm/dart/regress_39152_test.dart
new file mode 100644
index 0000000..343df24
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_39152_test.dart
@@ -0,0 +1,27 @@
+// 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/39152.
+// Verifies that unused object allocation doesn't cause crashes
+// during SSA construction in AOT.
+
+import 'package:expect/expect.dart';
+
+class A {
+  int foo() => 42;
+}
+
+A a = new A();
+int y;
+
+class B {
+  B(int x) {
+    y = x;
+  }
+}
+
+main() {
+  B(a.foo());
+  Expect.equals(42, y);
+}
diff --git a/runtime/tests/vm/dart/regress_39168_part1.dart b/runtime/tests/vm/dart/regress_39168_part1.dart
new file mode 100644
index 0000000..9f40bf1
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_39168_part1.dart
@@ -0,0 +1,13 @@
+// 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.
+
+part of regress_39168;
+
+// This class is not used and tree-shaken.
+// However, mixin application B with C is de-duplicated with
+// mixin application in regress_39168_part2.dart. This mixin application is
+// the only thing which is used from regress_39168_part1.dart.
+// As mixin application is a synthetic code, line numbers are not included
+// for regress_39168_part1.dart script.
+class A extends B with C {}
diff --git a/runtime/tests/vm/dart/regress_39168_part2.dart b/runtime/tests/vm/dart/regress_39168_part2.dart
new file mode 100644
index 0000000..787f700
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_39168_part2.dart
@@ -0,0 +1,17 @@
+// 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.
+
+part of regress_39168;
+
+class B {}
+
+abstract class C {}
+
+// Mixin application B with C is de-duplicated with mixin application
+// in regress_39168_part1.dart.
+class D extends B with C {}
+
+main() {
+  new D();
+}
diff --git a/runtime/tests/vm/dart/regress_39168_test.dart b/runtime/tests/vm/dart/regress_39168_test.dart
new file mode 100644
index 0000000..cf24d83
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_39168_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/39168.
+// Verifies that AOT compiler can handle synthetic code without line numbers
+// (mixin application in regress_39168_part1.dart).
+
+library regress_39168;
+
+part 'regress_39168_part1.dart';
+part 'regress_39168_part2.dart';
diff --git a/runtime/tests/vm/dart/reused_instructions_test.dart b/runtime/tests/vm/dart/reused_instructions_test.dart
deleted file mode 100644
index a2316c8..0000000
--- a/runtime/tests/vm/dart/reused_instructions_test.dart
+++ /dev/null
@@ -1,92 +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:async";
-import "dart:io";
-
-import "package:path/path.dart" as p;
-
-import "snapshot_test_helper.dart";
-
-int fib(int n) {
-  if (n <= 1) return 1;
-  return fib(n - 1) + fib(n - 2);
-}
-
-Future<void> main(List<String> args) async {
-  if (args.contains("--child")) {
-    print(fib(35));
-    return;
-  }
-
-  if (!Platform.script.toString().endsWith(".dart")) {
-    print("This test must run from source");
-    return;
-  }
-
-  await withTempDir((String tmp) async {
-    final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
-    final String coreIsoDataPath =
-        p.join(tmp, "core_isolate_snapshot_data.bin");
-    final String baselineIsoDataPath =
-        p.join(tmp, "baseline_isolate_snapshot_data.bin");
-    final String baselineIsoInstrPath =
-        p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
-    final String patchIsoDataPath =
-        p.join(tmp, "patch_isolate_snapshot_data.bin");
-    final String patchIsoInstrPath =
-        p.join(tmp, "patch_isolate_snapshot_instr.bin");
-    final String kernelPath = p.join(tmp, "app.dill");
-    final String tracePath = p.join(tmp, "compilation_trace.txt");
-
-    // We don't support snapshot with code on IA32.
-    final String appSnapshotKind =
-        Platform.version.contains("ia32") ? "app" : "app-jit";
-
-    final result1 = await runGenKernel("generate kernel", [
-      Platform.script.toFilePath(),
-      "--output",
-      kernelPath,
-    ]);
-    expectOutput("", result1);
-
-    final result2 = await runDart("generate compilation trace", [
-      "--save_compilation_trace=$tracePath",
-      kernelPath,
-      "--child",
-    ]);
-    expectOutput("14930352", result2);
-
-    final result3 = await runGenSnapshot("generate core snapshot", [
-      "--snapshot_kind=core",
-      "--vm_snapshot_data=${coreVMDataPath}",
-      "--isolate_snapshot_data=${coreIsoDataPath}",
-      platformDill,
-    ]);
-    expectOutput("", result3);
-
-    final result4 = await runGenSnapshot("generate baseline app snapshot", [
-      "--snapshot_kind=${appSnapshotKind}",
-      "--load_vm_snapshot_data=${coreVMDataPath}",
-      "--load_isolate_snapshot_data=${coreIsoDataPath}",
-      "--isolate_snapshot_data=${baselineIsoDataPath}",
-      "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
-      "--load_compilation_trace=$tracePath",
-      kernelPath,
-    ]);
-    expectOutput("", result4);
-
-    final result5 = await runGenSnapshot("generate patch app snapshot", [
-      "--snapshot_kind=${appSnapshotKind}",
-      "--load_vm_snapshot_data=${coreVMDataPath}",
-      "--load_isolate_snapshot_data=${coreIsoDataPath}",
-      "--isolate_snapshot_data=${patchIsoDataPath}",
-      "--isolate_snapshot_instructions=${patchIsoInstrPath}",
-      "--reused_instructions=${baselineIsoInstrPath}",
-      "--load_compilation_trace=$tracePath",
-      kernelPath,
-    ]);
-    expectOutput("", result5);
-  });
-}
diff --git a/runtime/tests/vm/dart/shared_snapshot_test.dart b/runtime/tests/vm/dart/shared_snapshot_test.dart
deleted file mode 100644
index eff8068..0000000
--- a/runtime/tests/vm/dart/shared_snapshot_test.dart
+++ /dev/null
@@ -1,93 +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:async";
-import "dart:io";
-
-import "package:path/path.dart" as p;
-
-import "snapshot_test_helper.dart";
-
-int fib(int n) {
-  if (n <= 1) return 1;
-  return fib(n - 1) + fib(n - 2);
-}
-
-Future<void> main(List<String> args) async {
-  if (args.contains("--child")) {
-    print(fib(35));
-    return;
-  }
-
-  if (!Platform.script.toString().endsWith(".dart")) {
-    print("This test must run from source");
-    return;
-  }
-
-  await withTempDir((String tmp) async {
-    final String coreVMDataPath = p.join(tmp, "core_vm_snapshot_data.bin");
-    final String coreIsoDataPath =
-        p.join(tmp, "core_isolate_snapshot_data.bin");
-    final String baselineIsoDataPath =
-        p.join(tmp, "baseline_isolate_snapshot_data.bin");
-    final String baselineIsoInstrPath =
-        p.join(tmp, "baseline_isolate_snapshot_instructions.bin");
-    final String patchIsoDataPath =
-        p.join(tmp, "patch_isolate_snapshot_data.bin");
-    final String patchIsoInstrPath =
-        p.join(tmp, "patch_isolate_snapshot_instr.bin");
-    final String kernelPath = p.join(tmp, "app.dill");
-    final String tracePath = p.join(tmp, "compilation_trace.txt");
-
-    // We don't support snapshot with code on IA32.
-    final String appSnapshotKind =
-        Platform.version.contains("ia32") ? "app" : "app-jit";
-
-    final result1 = await runGenKernel("generate kernel", [
-      Platform.script.toFilePath(),
-      "--output",
-      kernelPath,
-    ]);
-    expectOutput("", result1);
-
-    final result2 = await runDart("generate compilation trace", [
-      "--save_compilation_trace=$tracePath",
-      kernelPath,
-      "--child",
-    ]);
-    expectOutput("14930352", result2);
-
-    final result3 = await runGenSnapshot("generate core snapshot", [
-      "--snapshot_kind=core",
-      "--vm_snapshot_data=${coreVMDataPath}",
-      "--isolate_snapshot_data=${coreIsoDataPath}",
-      platformDill,
-    ]);
-    expectOutput("", result3);
-
-    final result4 = await runGenSnapshot("generate baseline app snapshot", [
-      "--snapshot_kind=${appSnapshotKind}",
-      "--load_vm_snapshot_data=${coreVMDataPath}",
-      "--load_isolate_snapshot_data=${coreIsoDataPath}",
-      "--isolate_snapshot_data=${baselineIsoDataPath}",
-      "--isolate_snapshot_instructions=${baselineIsoInstrPath}",
-      "--load_compilation_trace=$tracePath",
-      kernelPath,
-    ]);
-    expectOutput("", result4);
-
-    final result5 = await runGenSnapshot("generate patch app snapshot", [
-      "--snapshot_kind=${appSnapshotKind}",
-      "--load_vm_snapshot_data=${coreVMDataPath}",
-      "--load_isolate_snapshot_data=${coreIsoDataPath}",
-      "--isolate_snapshot_data=${patchIsoDataPath}",
-      "--isolate_snapshot_instructions=${patchIsoInstrPath}",
-      "--shared_data=${baselineIsoDataPath}",
-      "--shared_instructions=${baselineIsoInstrPath}",
-      "--load_compilation_trace=$tracePath",
-      kernelPath,
-    ]);
-    expectOutput("", result5);
-  });
-}
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index f6ece6d..dc259ce 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -52,8 +52,18 @@
   print(result.stdout);
 
   Expect.equals(result.exitCode, 0);
-  Expect.equals(result.stderr, "");
-  Expect.equals(result.stdout, "");
+  if (!useElf) {
+    Expect.equals(
+        "WARNING: app-aot-blobs snapshots have been deprecated and support for "
+        "generating them will be removed soon. Please use the app-aot-elf or "
+        "app-aot-assembly snapshot kinds in conjunction with the portable ELF "
+        "loader from //runtime/bin:elf_loader if necessary. See "
+        "http://dartbug.com/38764 for more details.\x0A",
+        result.stderr);
+  } else {
+    Expect.equals("", result.stderr);
+  }
+  Expect.equals("", result.stdout);
 
   final V8SnapshotProfile profile = V8SnapshotProfile.fromJson(JsonDecoder()
       .convert(File("${temp.path}/profile.heapsnapshot").readAsStringSync()));
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 4810538..9cd25d6 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -13,6 +13,7 @@
 cc/IsolateReload_PendingUnqualifiedCall_StaticToInstance: Fail # Issue 32981
 cc/Profiler_StringInterpolation: Fail # Issue 37208
 dart/data_uri_import_test/none: SkipByDesign
+dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
 dart/snapshot_version_test: Skip # This test is a Dart1 test (script snapshot)
 dart/stack_overflow_shared_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -21,6 +22,13 @@
 [ $builder_tag == asan ]
 dart/transferable_throws_oom_test: SkipByDesign # This test tries to allocate too much memory on purpose. Still dartbug.com/37188
 
+[ $builder_tag == crossword || $builder_tag == crossword_ast ]
+dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
+dart/bytecode_with_ast_in_aot_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
+
+[ $builder_tag == obfuscated ]
+dart/causal_stacks/*: SkipByDesign # Asserts exact stacktrace output.
+
 [ $builder_tag == optimization_counter_threshold ]
 cc/*: Skip # Many tests want see unoptimized code running
 dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
@@ -75,7 +83,7 @@
 [ $arch == ia32 && $mode == debug && $system == windows ]
 dart/transferable_test: Skip # This is performance test and somehow debug win ia32 bot's performance is unpredictable
 
-[ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch != simarm && $arch != simarm64 && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
 dart/data_uri_import_test/base64: Crash
 dart/data_uri_import_test/nocharset: Crash
 dart/data_uri_import_test/nomime: Crash
@@ -104,6 +112,7 @@
 
 [ $compiler != dartk && $compiler != dartkb && $compiler != none ]
 dart/appjit*: SkipByDesign # Test needs to run from source
+dart/bytecode_and_ast_mix_test: SkipByDesign # Test needs to run from source
 dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
 dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
 
@@ -114,7 +123,7 @@
 [ $mode == debug && $system == windows ]
 dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
 
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
+# Enabling of dartk for sim{arm,arm64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
 [ $mode == debug && ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
@@ -161,13 +170,8 @@
 [ $checked && ($compiler == dartk || $compiler == dartkb) ]
 dart/redirection_type_shuffling_test/00: Pass # Works in --checked mode but not in --strong mode.
 
-[ ($arch == simarm || $arch == simarm64 || $arch == simdbc || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
 dart/appjit*: SkipSlow # DFE too slow
-
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
 dart/data_uri_spawn_test: Skip # Please triage.
 dart/snapshot_version_test: RuntimeError # Please triage.
 
@@ -175,20 +179,19 @@
 dart/data_uri_spawn_test: Skip # Timeout
 dart/kernel_determinism_test: SkipSlow
 
-[ $arch == arm || $arch == arm64 || $builder_tag == crossword || $compiler != dartkp ]
+[ $arch == arm || $arch == arm64 || $builder_tag == crossword || $builder_tag == crossword_ast || $compiler != dartkp ]
 dart/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host).
 
-[ $arch == arm || $arch == ia32 || $arch == simarm || $arch == simdbc || $arch == simdbc64 ]
+[ $arch == arm || $arch == ia32 || $arch == simarm ]
 cc/GenKernelKernelCombined: SkipByDesign # No interpreter support.
 cc/GenKernelKernelLoadKernel: SkipByDesign # No interpreter support.
 cc/GenKernelKernelMaxRSS: SkipByDesign # No interpreter support.
 cc/GenKernelKernelReadAllBytecode: SkipByDesign # No interpreter support.
 
-# Profiler is completely disabled in SIMDBC builds.
 # On the simluator stack traces produced by the Profiler do not match
 # up with the real Dart stack trace and hence we don't get correct
 # symbol names.
-[ $arch == simarm || $arch == simarm64 || $arch == simarmv5te || $arch == simarmv6 || $arch == simdbc || $arch == simdbc64 ]
+[ $arch == simarm || $arch == simarm64 || $arch == simarmv6 ]
 cc/LargeMap: SkipByDesign
 cc/Profiler_AllocationSampleTest: SkipByDesign
 cc/Profiler_ArrayAllocation: SkipByDesign
@@ -216,25 +219,13 @@
 cc/Profiler_TypedArrayAllocation: SkipByDesign
 cc/Service_Profile: SkipByDesign
 
-[ $arch == simdbc || $arch == simdbc64 ]
-cc/GuardFieldConstructor2Test: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldConstructorTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldFinalListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldFinalVariableLengthListTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/GuardFieldSimpleTest: Skip # TODO(vegorov) Field guards are disabled for SIMDBC
-cc/RegExp_ExternalOneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_ExternalTwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_OneByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegExp_TwoByteString: Skip # TODO(vegorov) These tests don't seem to work if FLAG_interpret_irregexp is switched on by default because they attempt to call regexp functions directly instead of going through JSSyntaxRegExp_ExecuteMatch.
-cc/RegenerateAllocStubs: SkipByDesign # This test is meaningless for DBC as allocation stubs are not used.
-
-[ $arch == simdbc || $arch == simdbc64 || $compiler == dartkb ]
-dart/generic_field_invocation_test: SkipByDesign # DBC and KBC interpreters do not support --no_lazy_dispatchers
+[ $compiler == dartkb ]
+dart/generic_field_invocation_test: SkipByDesign # KBC interpreters do not support --no_lazy_dispatchers
 
 [ $builder_tag == bytecode_interpreter || $builder_tag == bytecode_mixed || $builder_tag == optimization_counter_threshold || $hot_reload || $hot_reload_rollback || $arch != arm && $arch != simarm && $arch != x64 || $compiler != dartk && $compiler != dartkb && $compiler != dartkp ]
 dart/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensible to when functions are optimized, so they are disabled on hotreload, optcounter and bytecode interpreter bots.
 
-[ $builder_tag == crossword || $compiler != dartkp || $system != linux && $system != macos && $system != windows ]
+[ $builder_tag == crossword || $builder_tag == crossword_ast || $compiler != dartkp || $system != linux && $system != macos && $system != windows ]
 dart/run_appended_aot_snapshot_test: SkipByDesign # Tests the precompiled runtime.
 
 [ $compiler == dart2analyzer || $compiler == dart2js ]
@@ -252,13 +243,15 @@
 dart/redirection_type_shuffling_test/none: RuntimeError
 
 [ $mode == debug || $runtime != dart_precompiled || $system == android ]
+dart/emit_aot_size_info_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart/use_bare_instructions_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
+dart/bytecode_with_ast_in_aot_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
 # These Isolate tests that use spawnURI are hence skipped on purpose.
-[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
+[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ]
 dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri
 dart/issue32950_test: SkipByDesign # uses spawnUri.
 
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index 99f26d7..e351fe2 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,7 +14,7 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.61';
+const String version = '1.64';
 
 // Restriction on statements and expressions.
 const int stmtDepth = 1;
@@ -190,13 +190,11 @@
   void emitZero() => emit('0');
 
   void emitTryCatchFinally(Function tryBody, Function catchBody,
-      {Function finallyBody, bool catchOOM = true}) {
+      {Function finallyBody}) {
     emitLn('try ', newline: false);
     emitBraceWrapped(() => tryBody());
-    if (catchOOM) {
-      emit(' on OutOfMemoryError ');
-      emitBraceWrapped(() => emitLn("exit(${oomExitCode});", newline: false));
-    }
+    emit(' on OutOfMemoryError ');
+    emitBraceWrapped(() => emitLn("exit(${oomExitCode});", newline: false));
     emit(' catch (e, st) ');
     emitBraceWrapped(catchBody);
     if (finallyBody != null) {
@@ -269,6 +267,7 @@
       {bool Function() elseBodyEmitter}) {
     emitLn('if ', newline: false);
     emitParenWrapped(ifConditionEmitter);
+    emit(' ');
     final bool b1 = emitBraceWrapped(ifBodyEmitter);
     bool b2 = false;
     if (elseBodyEmitter != null) {
@@ -592,6 +591,7 @@
       emitLn('// which, in turn, flags the problem prominently');
       emitIfStatement(() => emit('ffiTestFunctions == null'),
           () => emitPrint('Did not load ffi test functions'));
+      emitNewline();
     }
   }
 
@@ -604,7 +604,7 @@
           emitTryCatchFinally(() {
             emitCall(1, outputName, globalMethods[i], includeSemicolon: true);
           }, () {
-            emitPrint('$outputName throws');
+            emitPrint('$outputName() throws');
           });
           emitNewline();
         }
@@ -654,7 +654,7 @@
             body += '\$$varName$i\\n';
           }
           emitPrint('$body');
-        }, () => emitPrint('print throws'));
+        }, () => emitPrint('print() throws'));
       });
 
   //
@@ -1027,6 +1027,8 @@
     final emitStatementsClosure = () => emitStatements(depth + 1);
     emitLn('try ', newline: false);
     emitBraceWrapped(emitStatementsClosure);
+    emit(' on OutOfMemoryError ');
+    emitBraceWrapped(() => emitLn("exit(${oomExitCode});", newline: false));
     emit(' catch (exception, stackTrace) ', newline: false);
     emitBraceWrapped(emitStatementsClosure);
     if (coinFlip()) {
@@ -1175,17 +1177,30 @@
     emit("'");
   }
 
-  void emitElementExpr(int depth, DartType tp, {RhsFilter rhsFilter}) {
-    // This check determines whether we are emitting a global variable.
-    // I.e. whenever we are not currently emitting part of a class.
-    if (currentMethod != null) {
-      emitExpr(depth, tp, rhsFilter: rhsFilter);
-    } else {
+  void emitElementExpr(int depth, DartType tp,
+      {RhsFilter rhsFilter, bool isConst = false}) {
+    // Inside a constant collection, keep collection elements constants too.
+    if (isConst) {
+      if (DartType.isCollectionType(tp)) {
+        emitConstCollection(depth + 1, tp, rhsFilter: rhsFilter);
+        return;
+      } else if (tp == DartType.DOUBLE) {
+        // Dart does not like floating-point elements. A key would, for
+        // example, yield "The key does not have a primitive operator '=='".
+        emit('null');
+        return;
+      }
+    }
+    // Use literals outside a class or inside a constant collection.
+    if (currentMethod == null || isConst) {
       emitLiteral(depth, tp, rhsFilter: rhsFilter);
+    } else {
+      emitExpr(depth, tp, rhsFilter: rhsFilter);
     }
   }
 
-  void emitElement(int depth, DartType tp, {RhsFilter rhsFilter}) {
+  void emitElement(int depth, DartType tp,
+      {RhsFilter rhsFilter, bool isConst = false}) {
     // Get the element type contained in type tp.
     // E.g. element type of List<String> is String.
     final elementType = dartType.elementType(tp);
@@ -1194,13 +1209,15 @@
       // Emit construct for the map key type.
       final indexType = dartType.indexType(tp);
       emitIndentation();
-      emitElementExpr(depth, indexType, rhsFilter: rhsFilter);
+      emitElementExpr(depth, indexType, rhsFilter: rhsFilter, isConst: isConst);
       emit(' : ');
       // Emit construct for the map value type.
-      emitElementExpr(depth, elementType, rhsFilter: rhsFilter);
+      emitElementExpr(depth, elementType,
+          rhsFilter: rhsFilter, isConst: isConst);
     } else {
       // List and Set types.
-      emitElementExpr(depth, elementType, rhsFilter: rhsFilter);
+      emitElementExpr(depth, elementType,
+          rhsFilter: rhsFilter, isConst: isConst);
     }
   }
 
@@ -1216,13 +1233,8 @@
     switch (r) {
       // Favors elements over control-flow collections.
       case 0:
-        // TODO (ajcbik): Remove restriction once compiler is fixed.
-        if (depth < 2) {
-          emitLn('...', newline: false); // spread
-          emitCollection(depth + 1, tp, rhsFilter: rhsFilter);
-        } else {
-          emitElement(depth, tp, rhsFilter: rhsFilter);
-        }
+        emitLn('...', newline: false); // spread
+        emitCollection(depth + 1, tp, rhsFilter: rhsFilter);
         break;
       case 1:
         emitLn('if ', newline: false);
@@ -1298,6 +1310,14 @@
             newline: DartType.isMapType(tp));
       }, shouldIndent: DartType.isMapType(tp));
 
+  void emitConstCollection(int depth, DartType tp, {RhsFilter rhsFilter}) =>
+      emitWrapped(
+          DartType.isListType(tp)
+              ? const ['const [', ']']
+              : const ['const {', '}'],
+          () => emitElement(depth, tp, rhsFilter: rhsFilter, isConst: true),
+          shouldIndent: DartType.isMapType(tp));
+
   void emitLiteral(int depth, DartType tp,
       {bool smallPositiveValue = false, RhsFilter rhsFilter}) {
     // Randomly specialize interface if possible. E.g. num to int.
@@ -1448,8 +1468,12 @@
       // Emit a variable of the selected list or map type.
       ret = emitScalarVar(iterType, isLhs: isLhs, rhsFilter: rhsFilter);
       emitSquareBraceWrapped(() =>
-          // Emit an expression resolving into the index type.
-          emitExpr(depth + 1, indexType));
+          // Emit an expression resolving into the index type. For
+          // collection type, only constant collections are used
+          // to avoid rehashing the same value into many entries.
+          DartType.isCollectionType(indexType)
+              ? emitConstCollection(depth + 1, indexType)
+              : emitExpr(depth + 1, indexType));
     } else {
       ret = emitScalarVar(tp,
           isLhs: isLhs, rhsFilter: rhsFilter); // resort to scalar
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 7a0e601..67f5cb6 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -187,6 +187,7 @@
     snapshot = '$tmp/snapshot';
     env = Map<String, String>.from(e);
     env['DART_CONFIGURATION'] = tag;
+    env['DART_VM_FLAGS'] = '--enable-asserts';
     cmd = [precompiler, ...extraFlags, fileName, snapshot];
   }
 
@@ -200,8 +201,11 @@
   }
 
   void printReproductionCommand() {
-    print(
-        ["DART_CONFIGURATION=${env['DART_CONFIGURATION']}", ...cmd].join(" "));
+    print([
+      "DART_CONFIGURATION='${env['DART_CONFIGURATION']}'",
+      "DART_VM_FLAGS='${env['DART_VM_FLAGS']}'",
+      ...cmd
+    ].join(" "));
     print([dart, snapshot].join(" "));
   }
 
@@ -340,15 +344,17 @@
     rand = Random();
     tmpDir = Directory.systemTemp.createTempSync('dart_fuzz');
     fileName = '${tmpDir.path}/fuzz.dart';
+
     // Testcase generation flags.
-    // Necessary To avoid false divergences between 64 and 32 bit versions.
+
+    // Only use FP when modes have same precision (to avoid false
+    // divergences between 32-bit and 64-bit versions).
     fp = samePrecision(mode1, mode2);
-    // Occasionally test FFI.
+    // Occasionally test FFI (if capable).
     ffi = ffiCapable(mode1, mode2) && (rand.nextInt(5) == 0);
-    // TODO (https://github.com/dart-lang/sdk/issues/38710):
-    // re-enable non-flat types once hash issue is fixed.
-    // flatTp = !nestedTypesAllowed(mode1, mode2) || (rand.nextInt(5) == 0);
-    flatTp = true;
+    // Resort to flat types for the more expensive modes.
+    flatTp = !nestedTypesAllowed(mode1, mode2);
+
     runner1 =
         TestRunner.getTestRunner(mode1, top, tmpDir.path, env, fileName, rand);
     runner2 =
diff --git a/runtime/tools/run_clang_tidy.dart b/runtime/tools/run_clang_tidy.dart
index d165e77..5b18c61 100644
--- a/runtime/tools/run_clang_tidy.dart
+++ b/runtime/tools/run_clang_tidy.dart
@@ -80,23 +80,19 @@
   'runtime/platform/utils_win.h',
   'runtime/vm/compiler/assembler/assembler_arm64.h',
   'runtime/vm/compiler/assembler/assembler_arm.h',
-  'runtime/vm/compiler/assembler/assembler_dbc.h',
   'runtime/vm/compiler/assembler/assembler_ia32.h',
   'runtime/vm/compiler/assembler/assembler_x64.h',
   'runtime/vm/compiler/runtime_offsets_extracted.h',
   'runtime/vm/constants_arm64.h',
   'runtime/vm/constants_arm.h',
-  'runtime/vm/constants_dbc.h',
   'runtime/vm/constants_ia32.h',
   'runtime/vm/constants_x64.h',
   'runtime/vm/cpu_arm64.h',
   'runtime/vm/cpu_arm.h',
-  'runtime/vm/cpu_dbc.h',
   'runtime/vm/cpu_ia32.h',
   'runtime/vm/cpu_x64.h',
   'runtime/vm/instructions_arm64.h',
   'runtime/vm/instructions_arm.h',
-  'runtime/vm/instructions_dbc.h',
   'runtime/vm/instructions_ia32.h',
   'runtime/vm/instructions_x64.h',
   'runtime/vm/os_thread_android.h',
@@ -107,10 +103,8 @@
   'runtime/vm/regexp_assembler_bytecode_inl.h',
   'runtime/vm/simulator_arm64.h',
   'runtime/vm/simulator_arm.h',
-  'runtime/vm/simulator_dbc.h',
   'runtime/vm/stack_frame_arm64.h',
   'runtime/vm/stack_frame_arm.h',
-  'runtime/vm/stack_frame_dbc.h',
   'runtime/vm/stack_frame_ia32.h',
   'runtime/vm/stack_frame_x64.h',
 
diff --git a/runtime/tools/verbose_gc_to_bmu.dart b/runtime/tools/verbose_gc_to_bmu.dart
index fa4d255..9564e42 100644
--- a/runtime/tools/verbose_gc_to_bmu.dart
+++ b/runtime/tools/verbose_gc_to_bmu.dart
@@ -17,7 +17,7 @@
 const WINDOW_STEP_FACTOR = 0.9;
 const MINIMUM_WINDOW_SIZE_MS = 1;
 
-class Interval<T> {
+class Interval<T extends int> {
   T begin;
   T end;
   Interval(this.begin, this.end);
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index d5867a4..cc4a18f 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -16,6 +16,7 @@
 import("../../sdk/lib/typed_data/typed_data_sources.gni")
 import("../../sdk/lib/vmservice/vmservice_sources.gni")
 import("../../sdk/lib/wasm/wasm_sources.gni")
+import("../../sdk_args.gni")
 import("../../utils/compile_platform.gni")
 import("../bin/cli_sources.gni")
 import("../bin/io_sources.gni")
@@ -71,13 +72,14 @@
       extra_deps += [
         "$fuchsia_sdk_root/fidl:fuchsia.deprecatedtimezone",
         "$fuchsia_sdk_root/pkg:sys_cpp",
+        "$fuchsia_sdk_root/pkg:trace-engine",
       ]
     } else {
       extra_deps += [
         # TODO(US-399): Remove time_service specific code when it is no longer
         # necessary.
         "//sdk/lib/sys/cpp",
-        "//sdk/fidl/fuchsia.timezone",
+        "//sdk/fidl/fuchsia.deprecatedtimezone",
 
         "//zircon/public/lib/fbl",
         "//zircon/public/lib/trace-engine",
@@ -97,7 +99,9 @@
 library_for_all_configs("libdart_lib") {
   target_type = "source_set"
   if (is_fuchsia) {
-    if (!using_fuchsia_sdk) {
+    if (using_fuchsia_sdk) {
+      extra_deps = [ "$fuchsia_sdk_root/pkg:trace-engine" ]
+    } else {
       extra_deps = [
         "//zircon/public/lib/fbl",
         "//zircon/public/lib/trace-engine",
@@ -143,6 +147,9 @@
       "-Ddart.developer.causal_async_stacks=$allow_causal_async_stacks",
       "-Ddart.isVM=true",
     ]
+    if (use_nnbd) {
+      args += [ "--enable-experiment=non-nullable" ]
+    }
     if (defined(invoker.exclude_source) && invoker.exclude_source) {
       args += [ "--exclude-source" ]
     }
diff --git a/runtime/vm/atomic_test.cc b/runtime/vm/atomic_test.cc
index a495bb4..b8d0480 100644
--- a/runtime/vm/atomic_test.cc
+++ b/runtime/vm/atomic_test.cc
@@ -11,42 +11,38 @@
 namespace dart {
 
 VM_UNIT_TEST_CASE(FetchAndIncrement) {
-  uintptr_t v = 42;
-  EXPECT_EQ(static_cast<uintptr_t>(42),
-            AtomicOperations::FetchAndIncrement(&v));
+  RelaxedAtomic<uintptr_t> v = 42;
+  EXPECT_EQ(static_cast<uintptr_t>(42), v.fetch_add(1));
   EXPECT_EQ(static_cast<uintptr_t>(43), v);
 }
 
 VM_UNIT_TEST_CASE(FetchAndDecrement) {
-  uintptr_t v = 42;
-  EXPECT_EQ(static_cast<uintptr_t>(42),
-            AtomicOperations::FetchAndDecrement(&v));
+  RelaxedAtomic<uintptr_t> v = 42;
+  EXPECT_EQ(static_cast<uintptr_t>(42), v.fetch_sub(1));
   EXPECT_EQ(static_cast<uintptr_t>(41), v);
 }
 
 VM_UNIT_TEST_CASE(FetchAndIncrementSigned) {
-  intptr_t v = -42;
-  EXPECT_EQ(static_cast<intptr_t>(-42),
-            AtomicOperations::FetchAndIncrement(&v));
+  RelaxedAtomic<intptr_t> v = -42;
+  EXPECT_EQ(static_cast<intptr_t>(-42), v.fetch_add(1));
   EXPECT_EQ(static_cast<intptr_t>(-41), v);
 }
 
 VM_UNIT_TEST_CASE(FetchAndDecrementSigned) {
-  intptr_t v = -42;
-  EXPECT_EQ(static_cast<intptr_t>(-42),
-            AtomicOperations::FetchAndDecrement(&v));
+  RelaxedAtomic<intptr_t> v = -42;
+  EXPECT_EQ(static_cast<intptr_t>(-42), v.fetch_sub(1));
   EXPECT_EQ(static_cast<intptr_t>(-43), v);
 }
 
 VM_UNIT_TEST_CASE(IncrementBy) {
-  intptr_t v = 42;
-  AtomicOperations::IncrementBy(&v, 100);
+  RelaxedAtomic<intptr_t> v = 42;
+  v.fetch_add(100);
   EXPECT_EQ(static_cast<intptr_t>(142), v);
 }
 
 VM_UNIT_TEST_CASE(DecrementBy) {
-  intptr_t v = 42;
-  AtomicOperations::DecrementBy(&v, 41);
+  RelaxedAtomic<intptr_t> v = 42;
+  v.fetch_sub(41);
   EXPECT_EQ(static_cast<intptr_t>(1), v);
 }
 
@@ -65,24 +61,36 @@
 }
 
 VM_UNIT_TEST_CASE(LoadRelaxed) {
-  uword v = 42;
-  EXPECT_EQ(static_cast<uword>(42), AtomicOperations::LoadRelaxed(&v));
+  RelaxedAtomic<uword> v = 42;
+  EXPECT_EQ(static_cast<uword>(42), v.load());
 }
 
 TEST_CASE(CompareAndSwapWord) {
   uword old_value = 42;
+  RelaxedAtomic<uword> variable = {old_value};
   uword new_value = 100;
-  uword result =
-      AtomicOperations::CompareAndSwapWord(&old_value, old_value, new_value);
-  EXPECT_EQ(static_cast<uword>(42), result);
+  bool success = variable.compare_exchange_strong(old_value, new_value);
+  EXPECT_EQ(true, success);
+  EXPECT_EQ(static_cast<uword>(42), old_value);
+
+  old_value = 50;
+  success = variable.compare_exchange_strong(old_value, new_value);
+  EXPECT_EQ(false, success);
+  EXPECT_EQ(static_cast<uword>(100), old_value);
 }
 
 TEST_CASE(CompareAndSwapUint32) {
   uint32_t old_value = 42;
+  RelaxedAtomic<uint32_t> variable = {old_value};
   uint32_t new_value = 100;
-  uint32_t result =
-      AtomicOperations::CompareAndSwapUint32(&old_value, old_value, new_value);
-  EXPECT_EQ(static_cast<uint32_t>(42), result);
+  bool success = variable.compare_exchange_strong(old_value, new_value);
+  EXPECT_EQ(true, success);
+  EXPECT_EQ(static_cast<uword>(42), old_value);
+
+  old_value = 50;
+  success = variable.compare_exchange_strong(old_value, new_value);
+  EXPECT_EQ(false, success);
+  EXPECT_EQ(static_cast<uword>(100), old_value);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index a95642a..11527a7 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -131,12 +131,6 @@
   bool read_fully = file->ReadFully(kernel_buffer, kernel_buffer_size);
   EXPECT(read_fully);
 
-  // Enable bytecode compiler in order to read bytecode.
-  // Enabling interpreter also does the trick, but it causes flaky crashes
-  // as unoptimized background compiler (which is required for interpreter)
-  // was not initialized when isolate was created.
-  SetFlagScope<bool> sfs(&FLAG_use_bytecode_compiler, true);
-
   Timer timer(true, name);
   if (benchmark_load) {
     timer.Start();
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index aa21dc9..b730cf6 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -107,7 +107,7 @@
         cids_(cids) {}
 
   void FindAllInterfaces(const Class& klass) {
-    // The class is implementing it's own interface.
+    // The class is implementing its own interface.
     cids_->Add(klass.id());
 
     ScopedHandle<Array> array(&array_handles_);
@@ -123,8 +123,7 @@
         break;
       }
 
-      // The class is implementing it's directly declared implemented
-      // interfaces.
+      // The class is implementing its directly declared implemented interfaces.
       *array = klass.interfaces();
       if (!array->IsNull()) {
         for (intptr_t i = 0; i < array->Length(); ++i) {
@@ -134,7 +133,7 @@
         }
       }
 
-      // The class is implementing it's super type's interfaces.
+      // The class is implementing its super type's interfaces.
       *type = current_class->super_type();
       if (type->IsNull()) break;
       *current_class = class_table_->At(type->type_class_id());
@@ -1253,7 +1252,7 @@
     // performing a reload.
     if (!FLAG_precompiled_mode) {
       if (field.IsUninitialized()) {
-        error = field.Initialize();
+        error = field.InitializeStatic();
         if (!error.IsNull()) {
           ReportError(error);
         }
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 353039d..feb2d05 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -208,10 +208,11 @@
   // clang-format on
 
   // The following entries do not describe a predefined class, but instead
-  // are class indexes for pre-allocated instances (Null, dynamic and Void).
+  // are class indexes for pre-allocated instances (Null, dynamic, void, Never).
   kNullCid,
   kDynamicCid,
   kVoidCid,
+  kNeverCid,
 
   kNumPredefinedCids,
 };
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 696609f..fa8108f 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -44,6 +44,7 @@
         vm_shared_class_table->SizeAt(kForwardingCorpse);
     table_[kDynamicCid] = vm_shared_class_table->SizeAt(kDynamicCid);
     table_[kVoidCid] = vm_shared_class_table->SizeAt(kVoidCid);
+    table_[kNeverCid] = vm_shared_class_table->SizeAt(kNeverCid);
   }
 #ifndef PRODUCT
   class_heap_stats_table_ = static_cast<ClassHeapStats*>(
@@ -90,6 +91,7 @@
     table_[kForwardingCorpse] = vm_class_table->At(kForwardingCorpse);
     table_[kDynamicCid] = vm_class_table->At(kDynamicCid);
     table_[kVoidCid] = vm_class_table->At(kVoidCid);
+    table_[kNeverCid] = vm_class_table->At(kNeverCid);
   }
 }
 
@@ -252,9 +254,12 @@
   memmove(new_table, table_, top_ * sizeof(intptr_t));
   memset(new_table + top_, 0, (new_capacity - top_) * sizeof(intptr_t));
 #ifndef PRODUCT
-  auto new_stats_table = static_cast<ClassHeapStats*>(
-      realloc(class_heap_stats_table_,
-              new_capacity * sizeof(ClassHeapStats)));  // NOLINT
+  auto new_stats_table = reinterpret_cast<ClassHeapStats*>(
+      malloc(new_capacity * sizeof(ClassHeapStats)));
+  for (intptr_t i = 0; i < capacity_; i++) {
+    new_stats_table[i] = class_heap_stats_table_[i];
+  }
+  free(class_heap_stats_table_);
 #endif
   for (intptr_t i = capacity_; i < new_capacity; i++) {
     new_table[i] = 0;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 45f0509..2c75b06 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -27,8 +27,7 @@
 
 namespace dart {
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) &&                 \
-    !defined(TARGET_ARCH_DBC)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 static void RelocateCodeObjects(
     bool is_vm,
@@ -59,8 +58,7 @@
 
 typedef DirectChainedHashMap<RawCodeKeyValueTrait> RawCodeSet;
 
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) &&          \
-        // !defined(TARGET_ARCH_DBC)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) {
   ASSERT(Utils::IsAligned(size, kObjectAlignment));
@@ -607,13 +605,6 @@
         if (func.HasCode() && !code.IsDisabled()) {
           func.SetInstructions(code);  // Set entrypoint.
           func.SetWasCompiled(true);
-#if !defined(DART_PRECOMPILED_RUNTIME)
-        } else if (FLAG_enable_interpreter && func.HasBytecode()) {
-          // Set the code entry_point to InterpretCall stub.
-          func.SetInstructions(StubCode::InterpretCall());
-        } else if (FLAG_use_bytecode_compiler && func.HasBytecode()) {
-          func.SetInstructions(StubCode::LazyCompile());
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
         } else {
           func.ClearCode();  // Set code and entrypoint to lazy compile stub.
         }
@@ -1109,7 +1100,7 @@
       WriteFromTo(script);
       s->Write<int32_t>(script->ptr()->line_offset_);
       s->Write<int32_t>(script->ptr()->col_offset_);
-      s->Write<uint8_t>(script->ptr()->kind_and_tags_);
+      s->Write<uint8_t>(script->ptr()->flags_);
       s->Write<int32_t>(script->ptr()->kernel_script_index_);
     }
   }
@@ -1142,7 +1133,7 @@
       ReadFromTo(script);
       script->ptr()->line_offset_ = d->Read<int32_t>();
       script->ptr()->col_offset_ = d->Read<int32_t>();
-      script->ptr()->kind_and_tags_ = d->Read<uint8_t>();
+      script->ptr()->flags_ = d->Read<uint8_t>();
       script->ptr()->kernel_script_index_ = d->Read<int32_t>();
       script->ptr()->load_timestamp_ = 0;
     }
@@ -1723,7 +1714,6 @@
         RawObjectPool::Entry& entry = pool->ptr()->data()[j];
         switch (ObjectPool::TypeBits::decode(entry_bits[j])) {
           case ObjectPool::EntryType::kTaggedObject: {
-#if !defined(TARGET_ARCH_DBC)
             if ((entry.raw_obj_ == StubCode::CallNoScopeNative().raw()) ||
                 (entry.raw_obj_ == StubCode::CallAutoScopeNative().raw())) {
               // Natives can run while precompiling, becoming linked and
@@ -1732,7 +1722,6 @@
               s->WriteElementRef(StubCode::CallBootstrapNative().raw(), j);
               break;
             }
-#endif
             s->WriteElementRef(entry.raw_obj_, j);
             break;
           }
@@ -1815,14 +1804,6 @@
             entry.raw_value_ = static_cast<intptr_t>(new_entry);
             break;
           }
-#if defined(TARGET_ARCH_DBC)
-          case ObjectPool::EntryType::kNativeFunctionWrapper: {
-            // Read nothing. Initialize with the lazy link entry.
-            uword new_entry = NativeEntry::BootstrapNativeCallWrapperEntry();
-            entry.raw_value_ = static_cast<intptr_t>(new_entry);
-            break;
-          }
-#endif
           default:
             UNREACHABLE();
         }
@@ -1922,30 +1903,13 @@
       Object::FinalizeReadOnlyObject(object);
     }
 
-    uint32_t ignored;
-    if (s->GetSharedDataOffset(object, &ignored)) {
-      shared_objects_.Add(object);
-    } else {
-      objects_.Add(object);
-    }
+    objects_.Add(object);
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(cid_);
-    intptr_t count = shared_objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      RawObject* object = shared_objects_[i];
-      s->AssignRef(object);
-      AutoTraceObject(object);
-      uint32_t offset;
-      if (!s->GetSharedDataOffset(object, &offset)) {
-        UNREACHABLE();
-      }
-      s->WriteUnsigned(offset);
-    }
 
-    count = objects_.length();
+    intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
@@ -1975,7 +1939,6 @@
  private:
   const intptr_t cid_;
   GrowableArray<RawObject*> objects_;
-  GrowableArray<RawObject*> shared_objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
@@ -1986,12 +1949,6 @@
 
   void ReadAlloc(Deserializer* d) {
     intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      uint32_t offset = d->ReadUnsigned();
-      d->AssignRef(d->GetSharedObjectAt(offset));
-    }
-
-    count = d->ReadUnsigned();
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
       running_offset += d->ReadUnsigned() << kObjectAlignmentLog2;
@@ -2968,6 +2925,7 @@
       WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
+      s->Write<int8_t>(type->ptr()->nullability_);
     }
     count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
@@ -2976,6 +2934,7 @@
       WriteFromTo(type);
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int8_t>(type->ptr()->type_state_);
+      s->Write<int8_t>(type->ptr()->nullability_);
     }
   }
 
@@ -3017,6 +2976,7 @@
       ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
+      type->ptr()->nullability_ = d->Read<int8_t>();
     }
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -3027,6 +2987,7 @@
       ReadFromTo(type);
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->type_state_ = d->Read<int8_t>();
+      type->ptr()->nullability_ = d->Read<int8_t>();
     }
   }
 
@@ -3181,6 +3142,7 @@
       s->WriteTokenPosition(type->ptr()->token_pos_);
       s->Write<int16_t>(type->ptr()->index_);
       s->Write<uint8_t>(type->ptr()->flags_);
+      s->Write<int8_t>(type->ptr()->nullability_);
     }
   }
 
@@ -3215,6 +3177,7 @@
       type->ptr()->token_pos_ = d->ReadTokenPosition();
       type->ptr()->index_ = d->Read<int16_t>();
       type->ptr()->flags_ = d->Read<uint8_t>();
+      type->ptr()->nullability_ = d->Read<int8_t>();
     }
   }
 
@@ -4564,7 +4527,7 @@
     // Code should have been removed by DropCodeWithoutReusableInstructions.
     UnexpectedObject(code, "Expected instructions to reuse");
   }
-  Write<int32_t>(offset);
+  Write<uint32_t>(offset);
 
   // If offset < 0, it's pointing to a shared instruction. We don't profile
   // references to shared text/data (since they don't consume any space). Of
@@ -4601,11 +4564,6 @@
   }
 }
 
-bool Serializer::GetSharedDataOffset(RawObject* object,
-                                     uint32_t* offset) const {
-  return image_writer_->GetSharedDataOffsetFor(object, offset);
-}
-
 uint32_t Serializer::GetDataOffset(RawObject* object) const {
   return image_writer_->GetDataOffsetFor(object);
 }
@@ -4762,8 +4720,7 @@
   }
 
   intptr_t code_order_length = 0;
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) &&                 \
-    !defined(TARGET_ARCH_DBC)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
   if (kind_ == Snapshot::kFullAOT) {
     auto code_objects =
         static_cast<CodeSerializationCluster*>(clusters_by_cid_[kCodeCid])
@@ -4798,8 +4755,7 @@
       (*code_objects)[i] = code_order[i];
     }
   }
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32) &&          \
-        // !defined(TARGET_ARCH_DBC)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
   intptr_t num_clusters = 0;
   for (intptr_t cid = 1; cid < num_cids_; cid++) {
@@ -4939,6 +4895,7 @@
   }
   AddBaseObject(table->At(kDynamicCid), "Class");
   AddBaseObject(table->At(kVoidCid), "Class");
+  AddBaseObject(table->At(kNeverCid), "Class");
 
   if (!Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
@@ -5026,8 +4983,6 @@
                            intptr_t size,
                            const uint8_t* data_buffer,
                            const uint8_t* instructions_buffer,
-                           const uint8_t* shared_data_buffer,
-                           const uint8_t* shared_instructions_buffer,
                            intptr_t offset)
     : ThreadStackResource(thread),
       heap_(thread->isolate()->heap()),
@@ -5041,9 +4996,7 @@
   if (Snapshot::IncludesCode(kind)) {
     ASSERT(instructions_buffer != NULL);
     ASSERT(data_buffer != NULL);
-    image_reader_ =
-        new (zone_) ImageReader(data_buffer, instructions_buffer,
-                                shared_data_buffer, shared_instructions_buffer);
+    image_reader_ = new (zone_) ImageReader(data_buffer, instructions_buffer);
   }
   stream_.SetPosition(offset);
 }
@@ -5294,7 +5247,7 @@
 }
 
 RawInstructions* Deserializer::ReadInstructions() {
-  int32_t offset = Read<int32_t>();
+  uint32_t offset = Read<uint32_t>();
   return image_reader_->GetInstructionsAt(offset);
 }
 
@@ -5302,10 +5255,6 @@
   return image_reader_->GetObjectAt(offset);
 }
 
-RawObject* Deserializer::GetSharedObjectAt(uint32_t offset) const {
-  return image_reader_->GetSharedObjectAt(offset);
-}
-
 void Deserializer::Prepare() {
   num_base_objects_ = ReadUnsigned();
   num_objects_ = ReadUnsigned();
@@ -5405,6 +5354,7 @@
   }
   AddBaseObject(table->At(kDynamicCid));
   AddBaseObject(table->At(kVoidCid));
+  AddBaseObject(table->At(kNeverCid));
 
   if (!Snapshot::IncludesCode(kind_)) {
     for (intptr_t i = 0; i < StubCode::NumEntries(); i++) {
@@ -5660,8 +5610,6 @@
 
 FullSnapshotReader::FullSnapshotReader(const Snapshot* snapshot,
                                        const uint8_t* instructions_buffer,
-                                       const uint8_t* shared_data,
-                                       const uint8_t* shared_instructions,
                                        Thread* thread)
     : kind_(snapshot->kind()),
       thread_(thread),
@@ -5670,13 +5618,6 @@
       data_image_(snapshot->DataImage()),
       instructions_image_(instructions_buffer) {
   thread->isolate()->set_compilation_allowed(kind_ != Snapshot::kFullAOT);
-
-  if (shared_data == NULL) {
-    shared_data_image_ = NULL;
-  } else {
-    shared_data_image_ = Snapshot::SetupFromBuffer(shared_data)->DataImage();
-  }
-  shared_instructions_image_ = shared_instructions;
 }
 
 char* SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(
@@ -5737,7 +5678,7 @@
   }
 
   Deserializer deserializer(thread_, kind_, buffer_, size_, data_image_,
-                            instructions_image_, NULL, NULL, offset);
+                            instructions_image_, offset);
   RawApiError* api_error = deserializer.VerifyImageAlignment();
   if (api_error != ApiError::null()) {
     return api_error;
@@ -5767,8 +5708,7 @@
   }
 
   Deserializer deserializer(thread_, kind_, buffer_, size_, data_image_,
-                            instructions_image_, shared_data_image_,
-                            shared_instructions_image_, offset);
+                            instructions_image_, offset);
   RawApiError* api_error = deserializer.VerifyImageAlignment();
   if (api_error != ApiError::null()) {
     return api_error;
@@ -5781,14 +5721,6 @@
     ASSERT(instructions_image_ != NULL);
     thread_->isolate()->SetupImagePage(instructions_image_,
                                        /* is_executable */ true);
-    if (shared_data_image_ != NULL) {
-      thread_->isolate()->SetupImagePage(shared_data_image_,
-                                         /* is_executable */ false);
-    }
-    if (shared_instructions_image_ != NULL) {
-      thread_->isolate()->SetupImagePage(shared_instructions_image_,
-                                         /* is_executable */ true);
-    }
   }
 
   auto object_store = thread_->isolate()->object_store();
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index ad04810..d65569c 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -349,7 +349,6 @@
   }
 
   void WriteInstructions(RawInstructions* instr, RawCode* code);
-  bool GetSharedDataOffset(RawObject* object, uint32_t* offset) const;
   uint32_t GetDataOffset(RawObject* object) const;
   void TraceDataOffset(uint32_t offset);
   intptr_t GetDataSize() const;
@@ -467,8 +466,6 @@
                intptr_t size,
                const uint8_t* data_buffer,
                const uint8_t* instructions_buffer,
-               const uint8_t* shared_data_buffer,
-               const uint8_t* shared_instructions_buffer,
                intptr_t offset = 0);
   ~Deserializer();
 
@@ -548,7 +545,6 @@
 
   RawInstructions* ReadInstructions();
   RawObject* GetObjectAt(uint32_t offset) const;
-  RawObject* GetSharedObjectAt(uint32_t offset) const;
 
   void SkipHeader() { stream_.SetPosition(Snapshot::kHeaderSize); }
 
@@ -653,8 +649,6 @@
  public:
   FullSnapshotReader(const Snapshot* snapshot,
                      const uint8_t* instructions_buffer,
-                     const uint8_t* shared_data,
-                     const uint8_t* shared_instructions,
                      Thread* thread);
   ~FullSnapshotReader() {}
 
@@ -670,8 +664,6 @@
   intptr_t size_;
   const uint8_t* data_image_;
   const uint8_t* instructions_image_;
-  const uint8_t* shared_data_image_;
-  const uint8_t* shared_instructions_image_;
 
   DISALLOW_COPY_AND_ASSIGN(FullSnapshotReader);
 };
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 923de55..0706189 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -76,8 +76,7 @@
   // returns false.
   bool Find(uint32_t pc_offset) {
     // We should never have an entry with a PC offset of 0 inside an
-    // non-empty CSM, so fail. (On DBC, a pc_offset of 0 can be provided
-    // to Find() if there's no stack map information for a given Code object.)
+    // non-empty CSM, so fail.
     if (pc_offset == 0) return false;
     do {
       if (current_pc_offset_ >= pc_offset) break;
diff --git a/runtime/vm/code_patcher.cc b/runtime/vm/code_patcher.cc
index 7168231..d711035 100644
--- a/runtime/vm/code_patcher.cc
+++ b/runtime/vm/code_patcher.cc
@@ -18,7 +18,7 @@
 DEFINE_FLAG(bool, dual_map_code, false, "Dual map jitted code, RW and RX");
 #endif  // defined(DUAL_MAPPING_SUPPORTED)
 
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_IA32)
 WritableInstructionsScope::WritableInstructionsScope(uword address,
                                                      intptr_t size)
     : address_(address), size_(size) {
@@ -34,7 +34,7 @@
                            VirtualMemory::kReadExecute);
   }
 }
-#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+#endif  // defined(TARGET_ARCH_IA32)
 
 bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size) {
   // When breaking within generated code in GDB, it may overwrite individual
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h
index ceacea6..fa5c521 100644
--- a/runtime/vm/code_patcher.h
+++ b/runtime/vm/code_patcher.h
@@ -19,7 +19,7 @@
 class RawFunction;
 class RawObject;
 
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_IA32)
 // Stack-allocated class to create a scope where the specified region
 // [address, address + size] has write access enabled. This is used
 // when patching generated code. Access is reset to read-execute in
@@ -34,7 +34,7 @@
   const uword address_;
   const intptr_t size_;
 };
-#endif  // defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+#endif  // defined(TARGET_ARCH_IA32)
 
 class CodePatcher : public AllStatic {
  public:
@@ -83,27 +83,14 @@
   static RawCode* GetSwitchableCallTargetAt(uword return_address,
                                             const Code& caller_code);
 
-#if defined(TARGET_ARCH_DBC)
-  static NativeFunctionWrapper GetNativeCallAt(uword return_address,
-                                               const Code& caller_code,
-                                               NativeFunction* target);
-#else
   static RawCode* GetNativeCallAt(uword return_address,
                                   const Code& caller_code,
                                   NativeFunction* target);
-#endif
 
-#if defined(TARGET_ARCH_DBC)
-  static void PatchNativeCallAt(uword return_address,
-                                const Code& caller_code,
-                                NativeFunction target,
-                                NativeFunctionWrapper trampoline);
-#else
   static void PatchNativeCallAt(uword return_address,
                                 const Code& caller_code,
                                 NativeFunction target,
                                 const Code& trampoline);
-#endif
 
   static intptr_t GetSubtypeTestCachePoolIndex(uword return_address);
 };
diff --git a/runtime/vm/code_patcher_dbc.cc b/runtime/vm/code_patcher_dbc.cc
deleted file mode 100644
index 93bc87a..0000000
--- a/runtime/vm/code_patcher_dbc.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/code_patcher.h"
-
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/instructions.h"
-#include "vm/object.h"
-
-namespace dart {
-
-RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address,
-                                            const Code& code) {
-  ASSERT(code.ContainsInstructionAt(return_address));
-  CallPattern call(return_address, code);
-  return call.TargetCode();
-}
-
-void CodePatcher::PatchStaticCallAt(uword return_address,
-                                    const Code& code,
-                                    const Code& new_target) {
-  ASSERT(code.ContainsInstructionAt(return_address));
-  CallPattern call(return_address, code);
-  call.SetTargetCode(new_target);
-}
-
-void CodePatcher::InsertDeoptimizationCallAt(uword start) {
-  CallPattern::InsertDeoptCallAt(start);
-}
-
-RawCode* CodePatcher::GetInstanceCallAt(uword return_address,
-                                        const Code& caller_code,
-                                        Object* cache) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  CallPattern call(return_address, caller_code);
-  if (cache != NULL) {
-    *cache = call.Data();
-  }
-  return call.TargetCode();
-}
-
-void CodePatcher::PatchInstanceCallAt(uword return_address,
-                                      const Code& caller_code,
-                                      const Object& data,
-                                      const Code& target) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  CallPattern call(return_address, caller_code);
-  call.SetData(data);
-  call.SetTargetCode(target);
-}
-
-RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(uword return_address,
-                                                     const Code& caller_code,
-                                                     ICData* ic_data_result) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  CallPattern static_call(return_address, caller_code);
-  ICData& ic_data = ICData::Handle();
-  ic_data ^= static_call.Data();
-  if (ic_data_result != NULL) {
-    *ic_data_result = ic_data.raw();
-  }
-  return ic_data.GetTargetAt(0);
-}
-
-void CodePatcher::PatchSwitchableCallAt(uword return_address,
-                                        const Code& caller_code,
-                                        const Object& data,
-                                        const Code& target) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  SwitchableCallPattern call(return_address, caller_code);
-  call.SetData(data);
-  call.SetTarget(target);
-}
-
-RawCode* CodePatcher::GetSwitchableCallTargetAt(uword return_address,
-                                                const Code& caller_code) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  SwitchableCallPattern call(return_address, caller_code);
-  return call.target();
-}
-
-RawObject* CodePatcher::GetSwitchableCallDataAt(uword return_address,
-                                                const Code& caller_code) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  SwitchableCallPattern call(return_address, caller_code);
-  return call.data();
-}
-
-void CodePatcher::PatchNativeCallAt(uword return_address,
-                                    const Code& code,
-                                    NativeFunction target,
-                                    NativeFunctionWrapper trampoline) {
-  ASSERT(code.ContainsInstructionAt(return_address));
-  NativeCallPattern call(return_address, code);
-  call.set_target(trampoline);
-  call.set_native_function(target);
-}
-
-NativeFunctionWrapper CodePatcher::GetNativeCallAt(uword return_address,
-                                                   const Code& caller_code,
-                                                   NativeFunction* target) {
-  ASSERT(caller_code.ContainsInstructionAt(return_address));
-  NativeCallPattern call(return_address, caller_code);
-  *target = call.native_function();
-  return call.target();
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index e2f4eb8..c04569b 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -279,7 +279,7 @@
   if (!field_.IsNull() && field_.is_const() && field_.is_static() &&
       (field_.StaticValue() == Object::sentinel().raw())) {
     processed = true;
-    error_ = field_.Initialize();
+    error_ = field_.InitializeStatic();
     if (error_.IsError()) {
       if (FLAG_trace_compilation_trace) {
         THR_Print(
@@ -449,9 +449,6 @@
   ADD_FLAG(causal_async_stacks);
   ADD_FLAG(fields_may_be_reset);
 #undef ADD_FLAG
-  buffer.AddString(FLAG_use_bytecode_compiler || FLAG_enable_interpreter
-                       ? " bytecode"
-                       : " no-bytecode");
 
   return buffer.Steal();
 }
@@ -523,8 +520,8 @@
   code_ = function.CurrentCode();
   intptr_t usage = function.usage_counter();
   if (usage < 0) {
-    // Usage is set to INT_MIN while in the background compilation queue ...
-    usage = (usage - INT_MIN) + FLAG_optimization_counter_threshold;
+    // Usage is set to INT32_MIN while in the background compilation queue ...
+    usage = (usage - INT32_MIN) + FLAG_optimization_counter_threshold;
   } else if (code_.is_optimized()) {
     // ... and set to 0 when an optimizing compile completes.
     usage = usage + FLAG_optimization_counter_threshold;
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 12f61e2..65afe80 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -601,7 +601,6 @@
       return false;
     }
 
-#ifndef TARGET_ARCH_DBC
     if (FlowGraphCompiler::SupportsUnboxedInt64()) {
       if (op_kind == Token::kNEGATE || op_kind == Token::kBIT_NOT) {
         left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
@@ -609,7 +608,6 @@
             op_kind, left_value, DeoptId::kNone, Instruction::kNotSpeculative);
       }
     }
-#endif
   }
 
   if (replacement != nullptr && !replacement->ComputeCanDeoptimize()) {
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 4f32164..09bb182 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -100,8 +100,7 @@
 
 Precompiler* Precompiler::singleton_ = nullptr;
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 class PrecompileParsedFunctionHelper : public ValueObject {
  public:
@@ -1574,8 +1573,9 @@
     const AbstractType& type = types.At(i);
 
     if (type.InVMIsolateHeap()) {
-      // The only important types in the vm isolate are "dynamic"/"void", which
-      // will get their optimized top-type testing stub installed at creation.
+      // The only important types in the vm isolate are
+      // "dynamic"/"void"/"Never", which will get their optimized
+      // testing stub installed at creation.
       continue;
     }
 
@@ -2055,7 +2055,7 @@
 
 void Precompiler::DedupUnlinkedCalls() {
   ASSERT(!I->compilation_allowed());
-#if !defined(TARGET_ARCH_DBC)
+
   class UnlinkedCallDeduper {
    public:
     explicit UnlinkedCallDeduper(Zone* zone)
@@ -2139,7 +2139,6 @@
       visitor.Visit(current);
     }
   }
-#endif
 }
 
 void Precompiler::Obfuscate() {
@@ -2246,7 +2245,7 @@
   if (!function.IsOptimizable()) {
     // A function with huge unoptimized code can become non-optimizable
     // after generating unoptimized code.
-    function.set_usage_counter(INT_MIN);
+    function.set_usage_counter(INT32_MIN);
   }
 
   graph_compiler->FinalizePcDescriptors(code);
@@ -2274,13 +2273,12 @@
 // to install code.
 bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
   ASSERT(FLAG_precompiled_mode);
-  const Function& function = parsed_function()->function();
-  if (optimized() && !function.IsOptimizable()) {
+  if (optimized() && !parsed_function()->function().IsOptimizable()) {
     // All functions compiled by precompiler must be optimizable.
     UNREACHABLE();
     return false;
   }
-  bool is_compiled = false;
+  volatile bool is_compiled = false;
   Zone* const zone = thread()->zone();
   HANDLESCOPE(thread());
 
@@ -2301,6 +2299,7 @@
     if (val == 0) {
       FlowGraph* flow_graph = nullptr;
       ZoneGrowableArray<const ICData*>* ic_data_array = nullptr;
+      const Function& function = parsed_function()->function();
 
       CompilerState compiler_state(thread());
 
@@ -2314,7 +2313,7 @@
       }
 
       if (optimized()) {
-        flow_graph->PopulateWithICData(parsed_function()->function());
+        flow_graph->PopulateWithICData(function);
       }
 
       const bool print_flow_graph =
@@ -2962,8 +2961,7 @@
   return result;
 }
 
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
-        // !defined(TARGET_ARCH_IA32)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 47e4d9e..9cb24d2 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -346,8 +346,7 @@
 
 typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 // ObfuscationMap maps Strings to Strings.
 class ObfuscationMapTraits {
  public:
@@ -553,8 +552,7 @@
 
   static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces) {}
 };
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
-        // !defined(TARGET_ARCH_IA32)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/asm_intrinsifier.cc b/runtime/vm/compiler/asm_intrinsifier.cc
index 6cc847a..0886fe4 100644
--- a/runtime/vm/compiler/asm_intrinsifier.cc
+++ b/runtime/vm/compiler/asm_intrinsifier.cc
@@ -12,8 +12,6 @@
 namespace dart {
 namespace compiler {
 
-#if !defined(TARGET_ARCH_DBC)
-
 void AsmIntrinsifier::String_identityHash(Assembler* assembler,
                                           Label* normal_ir_body) {
   String_getHashCode(assembler, normal_ir_body);
@@ -36,8 +34,6 @@
                                                 /*sticky=*/true);
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/asm_intrinsifier.h b/runtime/vm/compiler/asm_intrinsifier.h
index 9f7e5d7..59b3f63 100644
--- a/runtime/vm/compiler/asm_intrinsifier.h
+++ b/runtime/vm/compiler/asm_intrinsifier.h
@@ -42,11 +42,6 @@
   static void enum_name(Assembler* assembler, Label* normal_ir_body);
   ALL_INTRINSICS_LIST(DECLARE_FUNCTION)
 
-  // On DBC all intrinsics are handled the same way.
-#if defined(TARGET_ARCH_DBC)
-  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
-#endif  // defined(TARGET_ARCH_DBC)
-
 #undef DECLARE_FUNCTION
 
   static void IntrinsifyRegExpExecuteMatch(Assembler* assembler,
diff --git a/runtime/vm/compiler/asm_intrinsifier_dbc.cc b/runtime/vm/compiler/asm_intrinsifier_dbc.cc
deleted file mode 100644
index cfb1130..0000000
--- a/runtime/vm/compiler/asm_intrinsifier_dbc.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#define SHOULD_NOT_INCLUDE_RUNTIME
-
-#include "vm/class_id.h"
-#include "vm/compiler/asm_intrinsifier.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/intrinsifier.h"
-
-namespace dart {
-namespace compiler {
-
-DECLARE_FLAG(bool, interpret_irregexp);
-
-#define DEFINE_FUNCTION(class_name, test_function_name, enum_name, fp)         \
-  void AsmIntrinsifier::enum_name(Assembler* assembler,                        \
-                                  Label* normal_ir_body) {                     \
-    if (Simulator::IsSupportedIntrinsic(Simulator::k##enum_name##Intrinsic)) { \
-      assembler->Intrinsic(Simulator::k##enum_name##Intrinsic);                \
-    }                                                                          \
-    assembler->Bind(normal_ir_body);                                           \
-  }
-
-ALL_INTRINSICS_LIST(DEFINE_FUNCTION)
-GRAPH_INTRINSICS_LIST(DEFINE_FUNCTION)
-#undef DEFINE_FUNCTION
-
-}  // namespace compiler
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index 6b5427d..6cc1a58 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -244,12 +244,10 @@
   return FLAG_code_comments || FLAG_disassemble || FLAG_disassemble_optimized;
 }
 
-#if !defined(TARGET_ARCH_DBC)
 void Assembler::Stop(const char* message) {
   Comment("Stop: %s", message);
   Breakpoint();
 }
-#endif
 
 intptr_t ObjIndexPair::Hashcode(Key key) {
   if (key.type() != ObjectPoolBuilderEntry::kTaggedObject) {
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 645728a..c5100dc 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -380,8 +380,6 @@
 #include "vm/compiler/assembler/assembler_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/compiler/assembler/assembler_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/compiler/assembler/assembler_dbc.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index e2e07a3..b573250 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -418,15 +418,8 @@
   ASSERT(rd_hi != IP);
   ASSERT(rn != IP);
   ASSERT(rm != IP);
-  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
-    // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
-    EmitMulOp(AL, B22, rd_lo, rd_hi, rn, rm);
-  } else {
-    mov(IP, Operand(0));
-    umlal(rd_lo, IP, rn, rm);
-    adds(rd_lo, rd_lo, Operand(rd_hi));
-    adc(rd_hi, IP, Operand(0));
-  }
+  // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+  EmitMulOp(AL, B22, rd_lo, rd_hi, rn, rm);
 }
 
 void Assembler::EmitDivOp(Condition cond,
@@ -493,12 +486,7 @@
                      Condition cond) {
   ASSERT((rd % 2) == 0);
   ASSERT(rd2 == rd + 1);
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    ldr(rd, Address(rn, offset), cond);
-    ldr(rd2, Address(rn, offset + target::kWordSize), cond);
-  } else {
-    EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, Address(rn, offset));
-  }
+  EmitMemOpAddressMode3(cond, B7 | B6 | B4, rd, Address(rn, offset));
 }
 
 void Assembler::strd(Register rd,
@@ -508,12 +496,7 @@
                      Condition cond) {
   ASSERT((rd % 2) == 0);
   ASSERT(rd2 == rd + 1);
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-    str(rd, Address(rn, offset), cond);
-    str(rd2, Address(rn, offset + target::kWordSize), cond);
-  } else {
-    EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, Address(rn, offset));
-  }
+  EmitMemOpAddressMode3(cond, B7 | B6 | B5 | B4, rd, Address(rn, offset));
 }
 
 void Assembler::ldm(BlockAddressMode am,
@@ -533,7 +516,6 @@
 }
 
 void Assembler::ldrex(Register rt, Register rn, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() != ARMv5TE);
   ASSERT(rn != kNoRegister);
   ASSERT(rt != kNoRegister);
   ASSERT(cond != kNoCondition);
@@ -545,7 +527,6 @@
 }
 
 void Assembler::strex(Register rd, Register rt, Register rn, Condition cond) {
-  ASSERT(TargetCPUFeatures::arm_version() != ARMv5TE);
   ASSERT(rn != kNoRegister);
   ASSERT(rd != kNoRegister);
   ASSERT(rt != kNoRegister);
@@ -562,7 +543,7 @@
   // We generate the same number of instructions whether or not the slow-path is
   // forced. This simplifies GenerateJitCallbackTrampolines.
   Label slow_path, done, retry;
-  if (FLAG_use_slow_path || TargetCPUFeatures::arm_version() == ARMv5TE) {
+  if (FLAG_use_slow_path) {
     b(&slow_path);
   }
 
@@ -578,7 +559,7 @@
   cmp(TMP, Operand(0));  // 0 means strex was successful.
   b(&done, EQ);
 
-  if (!FLAG_use_slow_path && TargetCPUFeatures::arm_version() != ARMv5TE) {
+  if (!FLAG_use_slow_path) {
     b(&retry);
   }
 
@@ -614,7 +595,7 @@
   // We generate the same number of instructions whether or not the slow-path is
   // forced, for consistency with EnterSafepoint.
   Label slow_path, done, retry;
-  if (FLAG_use_slow_path || TargetCPUFeatures::arm_version() == ARMv5TE) {
+  if (FLAG_use_slow_path) {
     b(&slow_path);
   }
 
@@ -630,7 +611,7 @@
   cmp(TMP, Operand(0));  // 0 means strex was successful.
   b(&done, EQ);
 
-  if (!FLAG_use_slow_path && TargetCPUFeatures::arm_version() != ARMv5TE) {
+  if (!FLAG_use_slow_path) {
     b(&retry);
   }
 
@@ -673,7 +654,6 @@
 }
 
 void Assembler::clrex() {
-  ASSERT(TargetCPUFeatures::arm_version() != ARMv5TE);
   int32_t encoding = (kSpecialCondition << kConditionShift) | B26 | B24 | B22 |
                      B21 | B20 | (0xff << 12) | B4 | 0xf;
   Emit(encoding);
@@ -894,13 +874,13 @@
   ASSERT(cond != kNoCondition);
   ASSERT(start != kNoDRegister);
   ASSERT(static_cast<int32_t>(start) + count <= kNumberOfDRegisters);
-  const int armv5te = TargetCPUFeatures::arm_version() == ARMv5TE ? 1 : 0;
+  const int notArmv5te = 0;
 
   int32_t encoding =
       (static_cast<int32_t>(cond) << kConditionShift) | B27 | B26 | B11 | B9 |
       B8 | am | (load ? L : 0) | ArmEncode::Rn(base) |
       ((static_cast<int32_t>(start) & 0x10) ? D : 0) |
-      ((static_cast<int32_t>(start) & 0xf) << 12) | (count << 1) | armv5te;
+      ((static_cast<int32_t>(start) & 0xf) << 12) | (count << 1) | notArmv5te;
   Emit(encoding);
 }
 
@@ -2075,7 +2055,7 @@
 
   void Process(const MemoryRegion& region, intptr_t position) {
     const ARMVersion version = TargetCPUFeatures::arm_version();
-    if ((version == ARMv5TE) || (version == ARMv6)) {
+    if (version == ARMv6) {
       ProcessARMv6(region, position);
     } else {
       ASSERT(version == ARMv7);
@@ -2329,7 +2309,7 @@
 
 void Assembler::Bind(Label* label) {
   const ARMVersion version = TargetCPUFeatures::arm_version();
-  if ((version == ARMv5TE) || (version == ARMv6)) {
+  if (version == ARMv6) {
     BindARMv6(label);
   } else {
     ASSERT(version == ARMv7);
@@ -2788,7 +2768,7 @@
                                        int32_t value,
                                        Condition cond) {
   const ARMVersion version = TargetCPUFeatures::arm_version();
-  if ((version == ARMv5TE) || (version == ARMv6)) {
+  if (version == ARMv6) {
     // This sequence is patched in a few places, and should remain fixed.
     const uint32_t byte0 = (value & 0x000000ff);
     const uint32_t byte1 = (value & 0x0000ff00) >> 8;
@@ -2811,7 +2791,7 @@
                                        int32_t value,
                                        Condition cond) {
   const ARMVersion version = TargetCPUFeatures::arm_version();
-  if ((version == ARMv5TE) || (version == ARMv6)) {
+  if (version == ARMv6) {
     if (constant_pool_allowed()) {
       const int32_t offset =
           target::ObjectPool::element_offset(FindImmediate(value));
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 1180d8b..cd26332 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -504,8 +504,7 @@
   void ldrsh(Register rd, Address ad, Condition cond = AL);
 
   // ldrd and strd actually support the full range of addressing modes, but
-  // we don't use them, and we need to split them up into two instructions for
-  // ARMv5TE, so we only support the base + offset mode.
+  // we don't use them, so we only support the base + offset mode.
   // rd must be an even register and rd2 must be rd + 1.
   void ldrd(Register rd,
             Register rd2,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index fff9a9d..e8de187 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1207,13 +1207,30 @@
 #endif
 }
 
+// The ARM64 ABI requires at all times
+//   - stack limit < CSP <= stack base
+//   - CSP mod 16 = 0
+//   - we do not access stack memory below CSP
+// Practically, this means we need to keep the C stack pointer ahead of the
+// Dart stack pointer and 16-byte aligned for signal handlers. We set
+// CSP to a value near the stack limit during SetupDartSP*, and use a different
+// register within our generated code to avoid the alignment requirement.
+// Note that Fuchsia does not have signal handlers.
+
 void Assembler::SetupDartSP() {
   mov(SP, CSP);
-#if defined(TARGET_OS_FUCHSIA)
-  // Make any future signal handlers fail fast. Verifies our assumption in
-  // EnterFrame.
-  orri(CSP, ZR, Immediate(16));
-#endif
+  // The caller doesn't have a Thread available. Just kick CSP forward a bit.
+  AddImmediate(CSP, CSP, -4096);
+}
+
+void Assembler::SetupCSPFromThread(Register thr) {
+  // Thread::saved_stack_limit_ is OSThread::overflow_stack_limit(), which is
+  // OSThread::stack_limit() with some headroom. Set CSP a bit below this value
+  // so that signal handlers won't stomp on the stack of Dart code that pushs a
+  // bit past overflow_stack_limit before its next overflow check. (We build
+  // frames before doing an overflow check.)
+  ldr(TMP, Address(thr, target::Thread::saved_stack_limit_offset()));
+  AddImmediate(CSP, TMP, -4096);
 }
 
 void Assembler::RestoreCSP() {
@@ -1221,25 +1238,6 @@
 }
 
 void Assembler::EnterFrame(intptr_t frame_size) {
-  // The ARM64 ABI requires at all times
-  //   - stack limit < CSP <= stack base
-  //   - CSP mod 16 = 0
-  //   - we do not access stack memory below CSP
-  // Pratically, this means we need to keep the C stack pointer ahead of the
-  // Dart stack pointer and 16-byte aligned for signal handlers. If we knew the
-  // real stack limit, we could just set CSP to a value near it during
-  // SetupDartSP, but we do not know the real stack limit for the initial
-  // thread or threads created by the embedder.
-  // TODO(26472): It would be safer to use CSP as the Dart stack pointer, but
-  // this requires adjustments to stack handling to maintain the 16-byte
-  // alignment.
-  // Note Fuchsia does not have signal handlers; see also SetupDartSP.
-#if !defined(TARGET_OS_FUCHSIA)
-  const intptr_t kMaxDartFrameSize = 4096;
-  sub(TMP, SP, Operand(kMaxDartFrameSize));
-  andi(CSP, TMP, Immediate(~15));
-#endif
-
   PushPair(FP, LR);  // low: FP, high: LR.
   mov(FP, SP);
 
@@ -1742,80 +1740,72 @@
                                              Register array,
                                              intptr_t index) const {
   const int64_t offset =
-      index * index_scale +
-      (is_external ? 0
-                   : (target::Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      index * index_scale + HeapDataOffset(is_external, cid);
   ASSERT(Utils::IsInt(32, offset));
   const OperandSize size = Address::OperandSizeFor(cid);
   ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
   return Address(array, static_cast<int32_t>(offset), Address::Offset, size);
 }
 
-void Assembler::LoadElementAddressForIntIndex(Register address,
-                                              bool is_external,
-                                              intptr_t cid,
-                                              intptr_t index_scale,
-                                              Register array,
-                                              intptr_t index) {
+void Assembler::ComputeElementAddressForIntIndex(Register address,
+                                                 bool is_external,
+                                                 intptr_t cid,
+                                                 intptr_t index_scale,
+                                                 Register array,
+                                                 intptr_t index) {
   const int64_t offset =
-      index * index_scale +
-      (is_external ? 0
-                   : (target::Instance::DataOffsetFor(cid) - kHeapObjectTag));
+      index * index_scale + HeapDataOffset(is_external, cid);
   AddImmediate(address, array, offset);
 }
 
-Address Assembler::ElementAddressForRegIndex(bool is_load,
-                                             bool is_external,
+Address Assembler::ElementAddressForRegIndex(bool is_external,
                                              intptr_t cid,
                                              intptr_t index_scale,
                                              Register array,
-                                             Register index) {
-  return ElementAddressForRegIndexWithSize(is_load,
-                                           is_external,
+                                             Register index,
+                                             Register temp) {
+  return ElementAddressForRegIndexWithSize(is_external,
                                            cid,
                                            Address::OperandSizeFor(cid),
                                            index_scale,
                                            array,
-                                           index);
+                                           index,
+                                           temp);
 }
 
-Address Assembler::ElementAddressForRegIndexWithSize(bool is_load,
-                                                     bool is_external,
+Address Assembler::ElementAddressForRegIndexWithSize(bool is_external,
                                                      intptr_t cid,
                                                      OperandSize size,
                                                      intptr_t index_scale,
                                                      Register array,
-                                                     Register index) {
+                                                     Register index,
+                                                     Register temp) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset =
-      is_external ? 0 : (target::Instance::DataOffsetFor(cid) - kHeapObjectTag);
-  ASSERT(array != TMP);
-  ASSERT(index != TMP);
-  const Register base = is_load ? TMP : index;
+  const int32_t offset = HeapDataOffset(is_external, cid);
+  ASSERT(array != temp);
+  ASSERT(index != temp);
   if ((offset == 0) && (shift == 0)) {
     return Address(array, index, UXTX, Address::Unscaled);
   } else if (shift < 0) {
     ASSERT(shift == -1);
-    add(base, array, Operand(index, ASR, 1));
+    add(temp, array, Operand(index, ASR, 1));
   } else {
-    add(base, array, Operand(index, LSL, shift));
+    add(temp, array, Operand(index, LSL, shift));
   }
   ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
-  return Address(base, offset, Address::Offset, size);
+  return Address(temp, offset, Address::Offset, size);
 }
 
-void Assembler::LoadElementAddressForRegIndex(Register address,
-                                              bool is_load,
-                                              bool is_external,
-                                              intptr_t cid,
-                                              intptr_t index_scale,
-                                              Register array,
-                                              Register index) {
+void Assembler::ComputeElementAddressForRegIndex(Register address,
+                                                 bool is_external,
+                                                 intptr_t cid,
+                                                 intptr_t index_scale,
+                                                 Register array,
+                                                 Register index) {
   // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays.
   const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift;
-  const int32_t offset =
-      is_external ? 0 : (target::Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  const int32_t offset = HeapDataOffset(is_external, cid);
   if (shift == 0) {
     add(address, array, Operand(index));
   } else if (shift < 0) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 1df9333..6b1805c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1327,31 +1327,25 @@
   void tst(Register rn, Operand o) { ands(ZR, rn, o); }
   void tsti(Register rn, const Immediate& imm) { andis(ZR, rn, imm); }
 
-  // We use an alias of add, where ARM recommends an alias of ubfm.
   void LslImmediate(Register rd,
                     Register rn,
                     int shift,
                     OperandSize sz = kDoubleWord) {
-    if (sz == kDoubleWord) {
-      add(rd, ZR, Operand(rn, LSL, shift));
-    } else {
-      addw(rd, ZR, Operand(rn, LSL, shift));
-    }
+    const int reg_size =
+        (sz == kDoubleWord) ? kXRegSizeInBits : kWRegSizeInBits;
+    ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1, sz);
   }
-  // We use an alias of add, where ARM recommends an alias of ubfm.
   void LsrImmediate(Register rd,
                     Register rn,
                     int shift,
                     OperandSize sz = kDoubleWord) {
-    if (sz == kDoubleWord) {
-      add(rd, ZR, Operand(rn, LSR, shift));
-    } else {
-      addw(rd, ZR, Operand(rn, LSR, shift));
-    }
+    const int reg_size =
+        (sz == kDoubleWord) ? kXRegSizeInBits : kWRegSizeInBits;
+    ubfm(rd, rn, shift, reg_size - 1, sz);
   }
-  // We use an alias of add, where ARM recommends an alias of sbfm.
   void AsrImmediate(Register rd, Register rn, int shift) {
-    add(rd, ZR, Operand(rn, ASR, shift));
+    const int reg_size = kXRegSizeInBits;
+    sbfm(rd, rn, shift, reg_size - 1);
   }
 
   void VRecps(VRegister vd, VRegister vn);
@@ -1539,6 +1533,7 @@
   void LoadTaggedClassIdMayBeSmi(Register result, Register object);
 
   void SetupDartSP();
+  void SetupCSPFromThread(Register thr);
   void RestoreCSP();
 
   void EnterFrame(intptr_t frame_size);
@@ -1629,37 +1624,44 @@
                                     intptr_t index_scale,
                                     Register array,
                                     intptr_t index) const;
-  void LoadElementAddressForIntIndex(Register address,
-                                     bool is_external,
-                                     intptr_t cid,
-                                     intptr_t index_scale,
-                                     Register array,
-                                     intptr_t index);
-  Address ElementAddressForRegIndex(bool is_load,
-                                    bool is_external,
+  void ComputeElementAddressForIntIndex(Register address,
+                                        bool is_external,
+                                        intptr_t cid,
+                                        intptr_t index_scale,
+                                        Register array,
+                                        intptr_t index);
+  Address ElementAddressForRegIndex(bool is_external,
                                     intptr_t cid,
                                     intptr_t index_scale,
                                     Register array,
-                                    Register index);
+                                    Register index,
+                                    Register temp);
 
   // Special version of ElementAddressForRegIndex for the case when cid and
   // operand size for the target load don't match (e.g. when loading a few
   // elements of the array with one load).
-  Address ElementAddressForRegIndexWithSize(bool is_load,
-                                            bool is_external,
+  Address ElementAddressForRegIndexWithSize(bool is_external,
                                             intptr_t cid,
                                             OperandSize size,
                                             intptr_t index_scale,
                                             Register array,
-                                            Register index);
+                                            Register index,
+                                            Register temp);
 
-  void LoadElementAddressForRegIndex(Register address,
-                                     bool is_load,
-                                     bool is_external,
-                                     intptr_t cid,
-                                     intptr_t index_scale,
-                                     Register array,
-                                     Register index);
+  void ComputeElementAddressForRegIndex(Register address,
+                                        bool is_external,
+                                        intptr_t cid,
+                                        intptr_t index_scale,
+                                        Register array,
+                                        Register index);
+
+  // Returns object data offset for address calculation; for heap objects also
+  // accounts for the tag.
+  static int32_t HeapDataOffset(bool is_external, intptr_t cid) {
+    return is_external ?
+          0 :
+          (target::Instance::DataOffsetFor(cid) - kHeapObjectTag);
+  }
 
   static int32_t EncodeImm26BranchOffset(int64_t imm, int32_t instr) {
     const int32_t imm32 = static_cast<int32_t>(imm);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index c993976..13a69a8 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -625,6 +625,328 @@
   EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
 }
 
+constexpr uint64_t kU64MinusOne = 0xffffffffffffffffull;
+constexpr uint64_t kU64MinInt32 = 0xffffffff80000000ull;
+constexpr uint64_t kU64MaxInt32 = 0x000000007fffffffull;
+constexpr uint64_t kU64MinInt64 = 0x8000000000000000ull;
+constexpr uint64_t kU64MaxInt64 = 0x7fffffffffffffffull;
+
+#define FOR_EACH_ASR_64_TEST_CONFIG(M)                                         \
+  M(0ull, 0, 0ull)                                                             \
+  M(1ull, 0, 1ull)                                                             \
+  M(kU64MaxInt32, 0, kU64MaxInt32)                                             \
+  M(kU64MaxInt64, 0, kU64MaxInt64)                                             \
+  M(kU64MinInt32, 0, kU64MinInt32)                                             \
+  M(kU64MinInt64, 0, kU64MinInt64)                                             \
+  M(0ull, 1, 0ull)                                                             \
+  M(1ull, 1, 0ull)                                                             \
+  M(4ull, 1, 2ull)                                                             \
+  M(0xffffull, 1, 0x7fffull)                                                   \
+  M(0xffffffffull, 1, 0x7fffffffull)                                           \
+  M(kU64MaxInt32, 1, 0x3fffffffull)                                            \
+  M(kU64MaxInt64, 1, 0x3fffffffffffffffull)                                    \
+  M(kU64MinInt32, 1, 0xffffffffc0000000ull)                                    \
+  M(kU64MinInt64, 1, 0xc000000000000000ull)                                    \
+  M(kU64MinusOne, 1, kU64MinusOne)                                             \
+  M(1ull, 2, 0ull)                                                             \
+  M(4ull, 2, 1ull)                                                             \
+  M(0xffffull, 2, 0x3fffull)                                                   \
+  M(0xffffffffull, 2, 0x3fffffffull)                                           \
+  M(kU64MaxInt32, 2, 0x1fffffffull)                                            \
+  M(kU64MaxInt64, 2, 0x1fffffffffffffffull)                                    \
+  M(kU64MinInt32, 2, 0xffffffffe0000000ull)                                    \
+  M(kU64MinInt64, 2, 0xe000000000000000ull)                                    \
+  M(kU64MinusOne, 2, kU64MinusOne)                                             \
+  M(0ull, 31, 0ull)                                                            \
+  M(1ull, 31, 0ull)                                                            \
+  M(4ull, 31, 0ull)                                                            \
+  M(0xffffull, 31, 0ull)                                                       \
+  M(0xffffffffull, 31, 1ull)                                                   \
+  M(kU64MaxInt32, 31, 0ull)                                                    \
+  M(kU64MaxInt64, 31, 0xffffffffull)                                           \
+  M(kU64MinInt32, 31, kU64MinusOne)                                            \
+  M(kU64MinInt64, 31, 0xffffffff00000000ull)                                   \
+  M(kU64MinusOne, 31, kU64MinusOne)                                            \
+  M(0ull, 32, 0ull)                                                            \
+  M(1ull, 32, 0ull)                                                            \
+  M(4ull, 32, 0ull)                                                            \
+  M(0xffffull, 32, 0ull)                                                       \
+  M(0xffffffffull, 32, 0ull)                                                   \
+  M(kU64MaxInt64, 32, 0x7fffffffull)                                           \
+  M(kU64MinInt32, 32, kU64MinusOne)                                            \
+  M(kU64MinInt64, 32, 0xffffffff80000000ull)                                   \
+  M(kU64MinusOne, 32, kU64MinusOne)                                            \
+  M(0ull, 62, 0ull)                                                            \
+  M(1ull, 62, 0ull)                                                            \
+  M(4ull, 62, 0ull)                                                            \
+  M(0xffffull, 62, 0ull)                                                       \
+  M(0xffffffffull, 62, 0ull)                                                   \
+  M(kU64MaxInt64, 62, 1ull)                                                    \
+  M(kU64MinInt32, 62, kU64MinusOne)                                            \
+  M(kU64MinInt64, 62, 0xfffffffffffffffeull)                                   \
+  M(kU64MinusOne, 62, kU64MinusOne)                                            \
+  M(0ull, 63, 0ull)                                                            \
+  M(1ull, 63, 0ull)                                                            \
+  M(4ull, 63, 0ull)                                                            \
+  M(0xffffull, 63, 0ull)                                                       \
+  M(0xffffffffull, 63, 0ull)                                                   \
+  M(kU64MaxInt64, 63, 0ull)                                                    \
+  M(kU64MinInt32, 63, kU64MinusOne)                                            \
+  M(kU64MinInt64, 63, kU64MinusOne)                                            \
+  M(kU64MinusOne, 63, kU64MinusOne)
+
+#define FOR_EACH_LSR_64_TEST_CONFIG(M)                                         \
+  M(0ull, 0, 0ull)                                                             \
+  M(1ull, 0, 1ull)                                                             \
+  M(kU64MaxInt32, 0, kU64MaxInt32)                                             \
+  M(kU64MaxInt64, 0, kU64MaxInt64)                                             \
+  M(kU64MinInt32, 0, kU64MinInt32)                                             \
+  M(kU64MinInt64, 0, kU64MinInt64)                                             \
+  M(0ull, 1, 0ull)                                                             \
+  M(1ull, 1, 0ull)                                                             \
+  M(4ull, 1, 2ull)                                                             \
+  M(0xffffull, 1, 0x7fffull)                                                   \
+  M(0xffffffffull, 1, 0x7fffffffull)                                           \
+  M(kU64MaxInt32, 1, 0x3fffffffull)                                            \
+  M(kU64MaxInt64, 1, 0x3fffffffffffffffull)                                    \
+  M(kU64MinInt32, 1, 0x7fffffffc0000000ull)                                    \
+  M(kU64MinInt64, 1, 0x4000000000000000ull)                                    \
+  M(kU64MinusOne, 1, 0x7fffffffffffffffull)                                    \
+  M(1ull, 2, 0ull)                                                             \
+  M(4ull, 2, 1ull)                                                             \
+  M(0xffffull, 2, 0x3fffull)                                                   \
+  M(0xffffffffull, 2, 0x3fffffffull)                                           \
+  M(kU64MaxInt32, 2, 0x1fffffffull)                                            \
+  M(kU64MaxInt64, 2, 0x1fffffffffffffffull)                                    \
+  M(kU64MinInt32, 2, 0x3fffffffe0000000ull)                                    \
+  M(kU64MinInt64, 2, 0x2000000000000000ull)                                    \
+  M(kU64MinusOne, 2, 0x3fffffffffffffffull)                                    \
+  M(0ull, 31, 0ull)                                                            \
+  M(1ull, 31, 0ull)                                                            \
+  M(4ull, 31, 0ull)                                                            \
+  M(0xffffull, 31, 0ull)                                                       \
+  M(0xffffffffull, 31, 1ull)                                                   \
+  M(kU64MaxInt32, 31, 0ull)                                                    \
+  M(kU64MaxInt64, 31, 0xffffffffull)                                           \
+  M(kU64MinInt32, 31, 0x1ffffffffull)                                          \
+  M(kU64MinInt64, 31, 0x100000000ull)                                          \
+  M(kU64MinusOne, 31, 0x1ffffffffull)                                          \
+  M(0ull, 32, 0ull)                                                            \
+  M(1ull, 32, 0ull)                                                            \
+  M(4ull, 32, 0ull)                                                            \
+  M(0xffffull, 32, 0ull)                                                       \
+  M(0xffffffffull, 32, 0ull)                                                   \
+  M(kU64MaxInt64, 32, 0x7fffffffull)                                           \
+  M(kU64MinInt32, 32, 0xffffffffull)                                           \
+  M(kU64MinInt64, 32, 0x80000000ull)                                           \
+  M(kU64MinusOne, 32, 0xffffffffull)                                           \
+  M(0ull, 62, 0ull)                                                            \
+  M(1ull, 62, 0ull)                                                            \
+  M(4ull, 62, 0ull)                                                            \
+  M(0xffffull, 62, 0ull)                                                       \
+  M(0xffffffffull, 62, 0ull)                                                   \
+  M(kU64MaxInt64, 62, 1ull)                                                    \
+  M(kU64MinInt32, 62, 3ull)                                                    \
+  M(kU64MinInt64, 62, 2ull)                                                    \
+  M(kU64MinusOne, 62, 3ull)                                                    \
+  M(0ull, 63, 0ull)                                                            \
+  M(1ull, 63, 0ull)                                                            \
+  M(4ull, 63, 0ull)                                                            \
+  M(0xffffull, 63, 0ull)                                                       \
+  M(0xffffffffull, 63, 0ull)                                                   \
+  M(kU64MaxInt64, 63, 0ull)                                                    \
+  M(kU64MinInt32, 63, 1ull)                                                    \
+  M(kU64MinInt64, 63, 1ull)                                                    \
+  M(kU64MinusOne, 63, 1ull)
+
+#define FOR_EACH_LSL_64_TEST_CONFIG(M)                                         \
+  M(0ull, 0, 0ull)                                                             \
+  M(1ull, 0, 1ull)                                                             \
+  M(kU64MaxInt32, 0, kU64MaxInt32)                                             \
+  M(kU64MaxInt64, 0, kU64MaxInt64)                                             \
+  M(kU64MinInt32, 0, kU64MinInt32)                                             \
+  M(kU64MinInt64, 0, kU64MinInt64)                                             \
+  M(0ull, 1, 0ull)                                                             \
+  M(1ull, 1, 2ull)                                                             \
+  M(4ull, 1, 8ull)                                                             \
+  M(0xffffull, 1, 0x1fffeull)                                                  \
+  M(0xffffffffull, 1, 0x1fffffffeull)                                          \
+  M(kU64MaxInt32, 1, 0xfffffffeull)                                            \
+  M(kU64MaxInt64, 1, 0xfffffffffffffffeull)                                    \
+  M(kU64MinInt32, 1, 0xffffffff00000000ull)                                    \
+  M(kU64MinInt64, 1, 0ull)                                                     \
+  M(kU64MinusOne, 1, 0xfffffffffffffffeull)                                    \
+  M(1ull, 2, 4ull)                                                             \
+  M(4ull, 2, 16ull)                                                            \
+  M(0xffffull, 2, 0x3fffcull)                                                  \
+  M(0xffffffffull, 2, 0x3fffffffcull)                                          \
+  M(kU64MaxInt32, 2, 0x1fffffffcull)                                           \
+  M(kU64MaxInt64, 2, 0xfffffffffffffffcull)                                    \
+  M(kU64MinInt32, 2, 0xfffffffe00000000ull)                                    \
+  M(kU64MinInt64, 2, 0ull)                                                     \
+  M(kU64MinusOne, 2, 0xfffffffffffffffcull)                                    \
+  M(0ull, 31, 0ull)                                                            \
+  M(1ull, 31, 0x0000000080000000ull)                                           \
+  M(4ull, 31, 0x0000000200000000ull)                                           \
+  M(0xffffull, 31, 0x00007fff80000000ull)                                      \
+  M(0xffffffffull, 31, 0x7fffffff80000000ull)                                  \
+  M(kU64MaxInt32, 31, 0x3fffffff80000000ull)                                   \
+  M(kU64MaxInt64, 31, 0xffffffff80000000ull)                                   \
+  M(kU64MinInt32, 31, 0xc000000000000000ull)                                   \
+  M(kU64MinInt64, 31, 0ull)                                                    \
+  M(kU64MinusOne, 31, 0xffffffff80000000ull)                                   \
+  M(0ull, 32, 0ull)                                                            \
+  M(1ull, 32, 0x0000000100000000ull)                                           \
+  M(4ull, 32, 0x0000000400000000ull)                                           \
+  M(0xffffull, 32, 0x0000ffff00000000ull)                                      \
+  M(0xffffffffull, 32, 0xffffffff00000000ull)                                  \
+  M(kU64MaxInt64, 32, 0xffffffff00000000ull)                                   \
+  M(kU64MinInt32, 32, 0x8000000000000000ull)                                   \
+  M(kU64MinInt64, 32, 0ull)                                                    \
+  M(kU64MinusOne, 32, 0xffffffff00000000ull)                                   \
+  M(0ull, 62, 0ull)                                                            \
+  M(1ull, 62, 0x4000000000000000ull)                                           \
+  M(4ull, 62, 0ull)                                                            \
+  M(0xffffull, 62, 0xc000000000000000ull)                                      \
+  M(0xffffffffull, 62, 0xc000000000000000ull)                                  \
+  M(kU64MaxInt64, 62, 0xc000000000000000ull)                                   \
+  M(kU64MinInt32, 62, 0ull)                                                    \
+  M(kU64MinInt64, 62, 0ull)                                                    \
+  M(kU64MinusOne, 62, 0xc000000000000000ull)                                   \
+  M(0ull, 63, 0ull)                                                            \
+  M(1ull, 63, 0x8000000000000000ull)                                           \
+  M(4ull, 63, 0ull)                                                            \
+  M(0xffffull, 63, 0x8000000000000000ull)                                      \
+  M(0xffffffffull, 63, 0x8000000000000000ull)                                  \
+  M(kU64MaxInt64, 63, 0x8000000000000000ull)                                   \
+  M(kU64MinInt32, 63, 0ull)                                                    \
+  M(kU64MinInt64, 63, 0ull)                                                    \
+  M(kU64MinusOne, 63, 0x8000000000000000ull)
+
+#define SHIFT_64_IMMEDIATE_TEST(macro_op, val, shift, expected)                \
+  ASSEMBLER_TEST_GENERATE(macro_op##_##val##_##shift, assembler) {             \
+    __ LoadImmediate(R1, bit_cast<int64_t>(val));                              \
+    __ macro_op(R0, R1, (shift));                                              \
+    __ ret();                                                                  \
+  }                                                                            \
+                                                                               \
+  ASSEMBLER_TEST_RUN(macro_op##_##val##_##shift, test) {                       \
+    typedef int64_t (*Int64Return)() DART_UNUSED;                              \
+    EXPECT_EQ((expected), bit_cast<uint64_t>(EXECUTE_TEST_CODE_INT64(          \
+                              Int64Return, test->entry())));                   \
+  }
+
+#define ASR_64_IMMEDIATE_TEST(val, shift, expected)                            \
+  SHIFT_64_IMMEDIATE_TEST(AsrImmediate, val, shift, expected)
+
+#define LSR_64_IMMEDIATE_TEST(val, shift, expected)                            \
+  SHIFT_64_IMMEDIATE_TEST(LsrImmediate, val, shift, expected)
+
+#define LSL_64_IMMEDIATE_TEST(val, shift, expected)                            \
+  SHIFT_64_IMMEDIATE_TEST(LslImmediate, val, shift, expected)
+
+FOR_EACH_ASR_64_TEST_CONFIG(ASR_64_IMMEDIATE_TEST)
+FOR_EACH_LSR_64_TEST_CONFIG(LSR_64_IMMEDIATE_TEST)
+FOR_EACH_LSL_64_TEST_CONFIG(LSL_64_IMMEDIATE_TEST)
+
+#undef LSL_64_IMMEDIATE_TEST
+#undef LSR_64_IMMEDIATE_TEST
+#undef ASR_64_IMMEDIATE_TEST
+#undef SHIFT_64_IMMEDIATE_TEST
+#undef FOR_EACH_LSL_64_TESTS_LIST
+#undef FOR_EACH_LSR_64_TESTS_LIST
+#undef FOR_EACH_ASR_64_TESTS_LIST
+
+constexpr uint32_t kU32MinusOne = 0xffffffffu;
+constexpr uint32_t kU32MinInt32 = 0x80000000u;
+constexpr uint32_t kU32MaxInt32 = 0x7fffffffu;
+
+#define FOR_EACH_LSR_32_TEST_CONFIG(M)                                         \
+  M(0u, 0, 0u)                                                                 \
+  M(1u, 0, 1u)                                                                 \
+  M(kU32MaxInt32, 0, kU32MaxInt32)                                             \
+  M(kU32MinInt32, 0, kU32MinInt32)                                             \
+  M(0u, 1, 0u)                                                                 \
+  M(1u, 1, 0u)                                                                 \
+  M(4u, 1, 2u)                                                                 \
+  M(0xffffu, 1, 0x7fffu)                                                       \
+  M(0xffffffffu, 1, 0x7fffffffu)                                               \
+  M(kU32MaxInt32, 1, 0x3fffffffu)                                              \
+  M(kU32MinInt32, 1, 0x40000000u)                                              \
+  M(kU32MinusOne, 1, 0x7fffffffu)                                              \
+  M(1u, 2, 0u)                                                                 \
+  M(4u, 2, 1u)                                                                 \
+  M(0xffffu, 2, 0x3fffu)                                                       \
+  M(0xffffffffu, 2, 0x3fffffffu)                                               \
+  M(kU32MaxInt32, 2, 0x1fffffffu)                                              \
+  M(kU32MinInt32, 2, 0x20000000u)                                              \
+  M(kU32MinusOne, 2, 0x3fffffffu)                                              \
+  M(0u, 31, 0u)                                                                \
+  M(1u, 31, 0u)                                                                \
+  M(4u, 31, 0u)                                                                \
+  M(0xffffu, 31, 0u)                                                           \
+  M(0xffffffffu, 31, 1u)                                                       \
+  M(kU32MaxInt32, 31, 0u)                                                      \
+  M(kU32MinInt32, 31, 1u)                                                      \
+  M(kU32MinusOne, 31, 1u)
+
+#define FOR_EACH_LSL_32_TEST_CONFIG(M)                                         \
+  M(0u, 0, 0u)                                                                 \
+  M(1u, 0, 1u)                                                                 \
+  M(kU32MaxInt32, 0, kU32MaxInt32)                                             \
+  M(kU32MinInt32, 0, kU32MinInt32)                                             \
+  M(0u, 1, 0u)                                                                 \
+  M(1u, 1, 2u)                                                                 \
+  M(4u, 1, 8u)                                                                 \
+  M(0xffffu, 1, 0x1fffeu)                                                      \
+  M(0xffffffffu, 1, 0xfffffffeu)                                               \
+  M(kU32MaxInt32, 1, 0xfffffffeu)                                              \
+  M(kU32MinInt32, 1, 0x00000000u)                                              \
+  M(kU32MinusOne, 1, 0xfffffffeu)                                              \
+  M(1u, 2, 4u)                                                                 \
+  M(4u, 2, 16u)                                                                \
+  M(0xffffu, 2, 0x3fffcu)                                                      \
+  M(0xffffffffu, 2, 0xfffffffcu)                                               \
+  M(kU32MaxInt32, 2, 0xfffffffcu)                                              \
+  M(kU32MinInt32, 2, 0x00000000u)                                              \
+  M(kU32MinusOne, 2, 0xfffffffcu)                                              \
+  M(0u, 31, 0u)                                                                \
+  M(1u, 31, 0x80000000u)                                                       \
+  M(4u, 31, 0x00000000u)                                                       \
+  M(0xffffu, 31, 0x80000000u)                                                  \
+  M(0xffffffffu, 31, 0x80000000u)                                              \
+  M(kU32MaxInt32, 31, 0x80000000u)                                             \
+  M(kU32MinInt32, 31, 0x00000000u)                                             \
+  M(kU32MinusOne, 31, 0x80000000u)
+
+#define SHIFT_32_IMMEDIATE_TEST(macro_op, val, shift, expected)                \
+  ASSEMBLER_TEST_GENERATE(macro_op##a_##val##_##shift, assembler) {            \
+    __ LoadImmediate(R1, bit_cast<int32_t>(val));                              \
+    __ macro_op(R0, R1, (shift), kWord);                                       \
+    __ ret();                                                                  \
+  }                                                                            \
+                                                                               \
+  ASSEMBLER_TEST_RUN(macro_op##a_##val##_##shift, test) {                      \
+    typedef int32_t (*Int32Return)() DART_UNUSED;                              \
+    EXPECT_EQ((expected), bit_cast<uint32_t>((int32_t)EXECUTE_TEST_CODE_INT64( \
+                              Int32Return, test->entry())));                   \
+  }
+
+#define LSR_32_IMMEDIATE_TEST(val, shift, expected)                            \
+  SHIFT_32_IMMEDIATE_TEST(LsrImmediate, val, shift, expected)
+
+#define LSL_32_IMMEDIATE_TEST(val, shift, expected)                            \
+  SHIFT_32_IMMEDIATE_TEST(LslImmediate, val, shift, expected)
+
+FOR_EACH_LSR_32_TEST_CONFIG(LSR_32_IMMEDIATE_TEST)
+FOR_EACH_LSL_32_TEST_CONFIG(LSL_32_IMMEDIATE_TEST)
+
+#undef LSL_32_IMMEDIATE_TEST
+#undef LSR_32_IMMEDIATE_TEST
+#undef SHIFT_32_IMMEDIATE_TEST
+#undef FOR_EACH_LSL_32_TESTS_LIST
+#undef FOR_EACH_LSR_32_TESTS_LIST
+
 ASSEMBLER_TEST_GENERATE(AndShiftRegs, assembler) {
   __ movz(R1, Immediate(42), 0);
   __ movz(R2, Immediate(21), 0);
diff --git a/runtime/vm/compiler/assembler/assembler_arm_test.cc b/runtime/vm/compiler/assembler/assembler_arm_test.cc
index c2c9030..b11603f 100644
--- a/runtime/vm/compiler/assembler/assembler_arm_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm_test.cc
@@ -528,10 +528,10 @@
     typedef int (*FloatToIntConversion)(float arg) DART_UNUSED;
     EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion, test->entry(),
                                             12.8f));
-    EXPECT_EQ(INT_MIN, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
-                                                 test->entry(), -FLT_MAX));
-    EXPECT_EQ(INT_MAX, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
-                                                 test->entry(), FLT_MAX));
+    EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
+                                                   test->entry(), -FLT_MAX));
+    EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_F(FloatToIntConversion,
+                                                   test->entry(), FLT_MAX));
   }
 }
 
@@ -549,10 +549,10 @@
     EXPECT(test != NULL);
     EXPECT_EQ(12, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
                                             test->entry(), 12.8));
-    EXPECT_EQ(INT_MIN, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
-                                                 test->entry(), -DBL_MAX));
-    EXPECT_EQ(INT_MAX, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
-                                                 test->entry(), DBL_MAX));
+    EXPECT_EQ(INT32_MIN, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
+                                                   test->entry(), -DBL_MAX));
+    EXPECT_EQ(INT32_MAX, EXECUTE_TEST_CODE_INT32_D(DoubleToIntConversion,
+                                                   test->entry(), DBL_MAX));
   }
 }
 
@@ -749,49 +749,41 @@
 }
 
 ASSEMBLER_TEST_GENERATE(Semaphore, assembler) {
-  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
-    __ mov(R0, Operand(40));
-    __ mov(R1, Operand(42));
-    __ Push(R0);
-    Label retry;
-    __ Bind(&retry);
-    __ ldrex(R0, SP);
-    __ strex(IP, R1, SP);  // IP == 0, success
-    __ tst(IP, Operand(0));
-    __ b(&retry, NE);  // NE if context switch occurred between ldrex and strex.
-    __ Pop(R0);        // 42
-  }
+  __ mov(R0, Operand(40));
+  __ mov(R1, Operand(42));
+  __ Push(R0);
+  Label retry;
+  __ Bind(&retry);
+  __ ldrex(R0, SP);
+  __ strex(IP, R1, SP);  // IP == 0, success
+  __ tst(IP, Operand(0));
+  __ b(&retry, NE);  // NE if context switch occurred between ldrex and strex.
+  __ Pop(R0);        // 42
   __ bx(LR);
 }
 
 ASSEMBLER_TEST_RUN(Semaphore, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
-    typedef int (*Semaphore)() DART_UNUSED;
-    EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Semaphore, test->entry()));
-  }
+  typedef int (*Semaphore)() DART_UNUSED;
+  EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Semaphore, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(FailedSemaphore, assembler) {
-  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
-    __ mov(R0, Operand(40));
-    __ mov(R1, Operand(42));
-    __ Push(R0);
-    __ ldrex(R0, SP);
-    __ clrex();            // Simulate a context switch.
-    __ strex(IP, R1, SP);  // IP == 1, failure
-    __ Pop(R0);            // 40
-    __ add(R0, R0, Operand(IP));
-  }
+  __ mov(R0, Operand(40));
+  __ mov(R1, Operand(42));
+  __ Push(R0);
+  __ ldrex(R0, SP);
+  __ clrex();            // Simulate a context switch.
+  __ strex(IP, R1, SP);  // IP == 1, failure
+  __ Pop(R0);            // 40
+  __ add(R0, R0, Operand(IP));
   __ bx(LR);
 }
 
 ASSEMBLER_TEST_RUN(FailedSemaphore, test) {
   EXPECT(test != NULL);
-  if (TargetCPUFeatures::arm_version() != ARMv5TE) {
-    typedef int (*FailedSemaphore)() DART_UNUSED;
-    EXPECT_EQ(41, EXECUTE_TEST_CODE_INT32(FailedSemaphore, test->entry()));
-  }
+  typedef int (*FailedSemaphore)() DART_UNUSED;
+  EXPECT_EQ(41, EXECUTE_TEST_CODE_INT32(FailedSemaphore, test->entry()));
 }
 
 ASSEMBLER_TEST_GENERATE(AddSub, assembler) {
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.cc b/runtime/vm/compiler/assembler/assembler_dbc.cc
deleted file mode 100644
index fe6f47f..0000000
--- a/runtime/vm/compiler/assembler/assembler_dbc.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // NOLINT
-#if defined(TARGET_ARCH_DBC)
-
-#define SHOULD_NOT_INCLUDE_RUNTIME
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/cpu.h"
-#include "vm/longjump.h"
-#include "vm/simulator.h"
-
-namespace dart {
-DECLARE_FLAG(bool, check_code_pointer);
-DECLARE_FLAG(bool, inline_alloc);
-
-namespace compiler {
-
-void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) {
-  const uword end = data + length;
-  while (data < end) {
-    *reinterpret_cast<int32_t*>(data) = SimulatorBytecode::kTrap;
-    data += sizeof(int32_t);
-  }
-}
-
-#define DEFINE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2)                         \
-  void Assembler::Name(PARAMS_##Signature) {                                   \
-    Emit(SimulatorBytecode::FENCODE_##Signature(                               \
-        SimulatorBytecode::k##Name ENCODE_##Signature));                       \
-  }
-
-#define PARAMS_0
-#define PARAMS_A_D uintptr_t ra, uintptr_t rd
-#define PARAMS_D uintptr_t rd
-#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc
-#define PARAMS_A_B_Y uintptr_t ra, uintptr_t rb, intptr_t ry
-#define PARAMS_A uintptr_t ra
-#define PARAMS_T intptr_t x
-#define PARAMS_A_X uintptr_t ra, intptr_t x
-#define PARAMS_X intptr_t x
-
-#define ENCODE_0
-#define ENCODE_A_D , ra, rd
-#define ENCODE_D , 0, rd
-#define ENCODE_A_B_C , ra, rb, rc
-#define ENCODE_A_B_Y , ra, rb, ry
-#define ENCODE_A , ra, 0
-#define ENCODE_T , x
-#define ENCODE_A_X , ra, x
-#define ENCODE_X , 0, x
-
-#define FENCODE_0 Encode
-#define FENCODE_A_D Encode
-#define FENCODE_D Encode
-#define FENCODE_A_B_C Encode
-#define FENCODE_A_B_Y Encode
-#define FENCODE_A Encode
-#define FENCODE_T EncodeSigned
-#define FENCODE_A_X EncodeSigned
-#define FENCODE_X EncodeSigned
-
-BYTECODES_LIST(DEFINE_EMIT)
-
-#undef DEFINE_EMIT
-
-void Assembler::Emit(int32_t value) {
-  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
-  buffer_.Emit<int32_t>(value);
-}
-
-static int32_t EncodeJump(int32_t relative_pc) {
-  return SimulatorBytecode::kJump | (relative_pc << 8);
-}
-
-static int32_t OffsetToPC(int32_t offset) {
-  return offset >> 2;
-}
-
-void Assembler::Jump(Label* label) {
-  if (label->IsBound()) {
-    Emit(EncodeJump(OffsetToPC(label->Position() - buffer_.Size())));
-  } else {
-    const intptr_t position = buffer_.Size();
-    Emit(label->position_);
-    label->LinkTo(position);
-  }
-}
-
-void Assembler::Bind(Label* label) {
-  ASSERT(!label->IsBound());
-  ASSERT(!label->IsBound());
-  intptr_t bound_pc = buffer_.Size();
-  while (label->IsLinked()) {
-    const int32_t position = label->Position();
-    const int32_t next_position = buffer_.Load<int32_t>(position);
-    buffer_.Store<int32_t>(position,
-                           EncodeJump(OffsetToPC(bound_pc - position)));
-    label->position_ = next_position;
-  }
-  label->BindTo(bound_pc);
-}
-
-void Assembler::Stop(const char* message) {
-  // TODO(vegorov) support passing a message to the bytecode.
-  Emit(SimulatorBytecode::kTrap);
-}
-
-void Assembler::PushConstant(const Object& obj) {
-  PushConstant(AddConstant(obj));
-}
-
-void Assembler::LoadConstant(uintptr_t ra, const Object& obj) {
-  LoadConstant(ra, AddConstant(obj));
-}
-
-intptr_t Assembler::AddConstant(const Object& obj) {
-  return object_pool_builder().FindObject(
-      NewZoneHandle(ThreadState::Current()->zone(), obj));
-}
-
-}  // namespace compiler
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h
deleted file mode 100644
index 0737026..0000000
--- a/runtime/vm/compiler/assembler/assembler_dbc.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_
-#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_
-
-#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_
-#error Do not include assembler_dbc.h directly; use assembler.h instead.
-#endif
-
-#include "platform/assert.h"
-#include "platform/utils.h"
-#include "vm/constants_dbc.h"
-#include "vm/cpu.h"
-#include "vm/hash_map.h"
-#include "vm/simulator.h"
-
-namespace dart {
-
-namespace compiler {
-
-// Dummy declaration to make things compile.
-class Address : public ValueObject {
- private:
-  Address();
-};
-
-class Assembler : public AssemblerBase {
- public:
-  explicit Assembler(ObjectPoolBuilder* object_pool_builder,
-                     bool use_far_branches = false)
-      : AssemblerBase(object_pool_builder) {}
-  ~Assembler() {}
-
-  void Bind(Label* label);
-  void Jump(Label* label);
-
-  // Misc. functionality
-  intptr_t prologue_offset() const { return 0; }
-
-  void MonomorphicCheckedEntryJIT() {}
-  void MonomorphicCheckedEntryAOT() {}
-
-  // Debugging and bringup support.
-  void Breakpoint() override { Stop("Breakpoint!"); }
-  void Stop(const char* message) override;
-
-  static void InitializeMemoryWithBreakpoints(uword data, intptr_t length);
-
-  static uword GetBreakInstructionFiller() { return SimulatorBytecode::kTrap; }
-
-  static bool IsSafe(const Object& value) { return true; }
-  static bool IsSafeSmi(const Object& value) { return false; }
-
-  enum CanBeSmi {
-    kValueIsNotSmi,
-    kValueCanBeSmi,
-  };
-
-  // Bytecodes.
-
-#define DECLARE_EMIT(Name, Signature, Fmt0, Fmt1, Fmt2)                        \
-  void Name(PARAMS_##Signature);
-
-#define PARAMS_0
-#define PARAMS_A_D uintptr_t ra, uintptr_t rd
-#define PARAMS_D uintptr_t rd
-#define PARAMS_A_B_C uintptr_t ra, uintptr_t rb, uintptr_t rc
-#define PARAMS_A_B_Y uintptr_t ra, uintptr_t rb, intptr_t ry
-#define PARAMS_A uintptr_t ra
-#define PARAMS_X intptr_t x
-#define PARAMS_T intptr_t x
-#define PARAMS_A_X uintptr_t ra, intptr_t x
-
-  BYTECODES_LIST(DECLARE_EMIT)
-
-#undef PARAMS_0
-#undef PARAMS_A_D
-#undef PARAMS_D
-#undef PARAMS_A_B_C
-#undef PARAMS_A_B_Y
-#undef PARAMS_A
-#undef PARAMS_X
-#undef PARAMS_T
-#undef PARAMS_A_X
-#undef DECLARE_EMIT
-
-  void Emit(int32_t value);
-
-  void PushConstant(const Object& obj);
-  void LoadConstant(uintptr_t ra, const Object& obj);
-
-  intptr_t AddConstant(const Object& obj);
-
-  void Nop(intptr_t d) { Nop(0, d); }
-
- private:
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(Assembler);
-};
-
-}  // namespace compiler
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_DBC_H_
diff --git a/runtime/vm/compiler/assembler/assembler_dbc_test.cc b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
deleted file mode 100644
index 562fb4c..0000000
--- a/runtime/vm/compiler/assembler/assembler_dbc_test.cc
+++ /dev/null
@@ -1,2857 +0,0 @@
-// 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.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/locations.h"
-#include "vm/compiler/compiler_state.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-namespace compiler {
-
-static RawObject* ExecuteTest(const Code& code) {
-  const intptr_t kTypeArgsLen = 0;
-  const intptr_t kNumArgs = 0;
-  const Array& args_desc =
-      Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs));
-  const Array& args = Array::Handle(Array::New(0));
-  Thread* thread = Thread::Current();
-  TransitionToGenerated transition(thread);
-  return Simulator::Current()->Call(code, args_desc, args, thread);
-}
-
-#define EXECUTE_TEST_CODE_INTPTR(code)                                         \
-  Smi::Value(Smi::RawCast(ExecuteTest(code)))
-#define EXECUTE_TEST_CODE_BOOL(code)                                           \
-  (Bool::RawCast(ExecuteTest(code)) == Bool::True().raw())
-#define EXECUTE_TEST_CODE_OBJECT(code) Object::Handle(ExecuteTest(code))
-#define EXECUTE_TEST_CODE_DOUBLE(code)                                         \
-  bit_cast<double, RawObject*>(ExecuteTest(code))
-#define EXECUTE_TEST_CODE_INTPTR_UNBOXED(code)                                 \
-  reinterpret_cast<intptr_t>(ExecuteTest(code))
-
-#define __ assembler->
-
-static RawClass* CreateDummyClass(const String& class_name,
-                                  const Script& script) {
-  const Class& cls = Class::Handle(Class::New(
-      Library::Handle(), class_name, script, TokenPosition::kNoSource));
-  cls.set_is_synthesized_class();  // Dummy class for testing.
-  return cls.raw();
-}
-
-static RawLibrary* CreateDummyLibrary(const String& library_name) {
-  return Library::New(library_name);
-}
-
-static RawFunction* CreateFunction(const char* name) {
-  Thread* thread = Thread::Current();
-  const String& class_name = String::Handle(Symbols::New(thread, "ownerClass"));
-  const String& lib_name = String::Handle(Symbols::New(thread, "ownerLibrary"));
-  const Script& script = Script::Handle();
-  const Class& owner_class =
-      Class::Handle(CreateDummyClass(class_name, script));
-  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, RawFunction::kRegularFunction, true,
-                       false, false, false, false, owner_class,
-                       TokenPosition::kMinSource);
-}
-
-static void GenerateDummyCode(Assembler* assembler, const Object& result) {
-  __ PushConstant(result);
-  __ ReturnTOS();
-}
-
-static void MakeDummyInstanceCall(Assembler* assembler, const Object& result) {
-  // Make a dummy function.
-  ObjectPoolBuilder object_pool_builder;
-  Assembler _assembler_(&object_pool_builder);
-  GenerateDummyCode(&_assembler_, result);
-  const char* dummy_function_name = "dummy_instance_function";
-  const Function& dummy_instance_function =
-      Function::Handle(CreateFunction(dummy_function_name));
-  Code& code = Code::Handle(Code::FinalizeCodeAndNotify(
-      dummy_instance_function, nullptr, &_assembler_,
-      Code::PoolAttachment::kAttachPool));
-  dummy_instance_function.AttachCode(code);
-
-  // Make a dummy ICData.
-  const intptr_t kTypeArgsLen = 0;
-  const intptr_t kNumArgs = 2;
-  const Array& dummy_arguments_descriptor =
-      Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs));
-  const ICData& ic_data = ICData::Handle(ICData::New(
-      dummy_instance_function, String::Handle(dummy_instance_function.name()),
-      dummy_arguments_descriptor, DeoptId::kNone, 2, ICData::kInstance));
-
-  // Wire up the Function in the ICData.
-  GrowableArray<intptr_t> cids(2);
-  cids.Add(kSmiCid);
-  cids.Add(kSmiCid);
-  ic_data.AddCheck(cids, dummy_instance_function);
-
-  // For the non-Smi tests.
-  cids[0] = kMintCid;
-  ic_data.AddCheck(cids, dummy_instance_function);
-  ICData* call_ic_data = &ICData::ZoneHandle(ic_data.Original());
-
-  // Generate the instance call.
-  const intptr_t call_ic_data_kidx = __ AddConstant(*call_ic_data);
-  __ InstanceCall2(2, call_ic_data_kidx);
-}
-
-ASSEMBLER_TEST_GENERATE(Simple, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(Simple, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(Nop, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ Nop(0);
-  __ Nop(0);
-  __ Nop(0);
-  __ Nop(0);
-  __ Nop(0);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(Nop, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-// Called from assembler_test.cc.
-// FP[-kParamEndSlotFromFp - 1]: growable array
-// FP[-kParamEndSlotFromFp - 2]: value
-ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
-  __ Frame(2);
-  __ Move(0, -kParamEndSlotFromFp - 1);
-  __ Move(1, -kParamEndSlotFromFp - 2);
-  __ StoreField(0, GrowableObjectArray::data_offset() / target::kWordSize, 1);
-  __ Return(0);
-}
-
-//  - OneByteStringFromCharCode rA, rX
-//
-//    Load the one-character symbol with the char code given by the Smi
-//    in FP[rX] into FP[rA].
-ASSEMBLER_TEST_GENERATE(OneByteStringFromCharCode, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::ZoneHandle(Smi::New(65)));
-  __ OneByteStringFromCharCode(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(OneByteStringFromCharCode, test) {
-  EXPECT_EQ(Symbols::New(Thread::Current(), "A"),
-            EXECUTE_TEST_CODE_OBJECT(test->code()).raw());
-}
-
-//  - StringToCharCode rA, rX
-//
-//    Load and smi-encode the single char code of the string in FP[rX] into
-//    FP[rA]. If the string's length is not 1, load smi -1 instead.
-//
-ASSEMBLER_TEST_GENERATE(StringToCharCode, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, String::ZoneHandle(String::New("A", Heap::kOld)));
-  __ StringToCharCode(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(StringToCharCode, test) {
-  EXPECT_EQ(65, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(StringToCharCodeIllegalLength, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, String::ZoneHandle(String::New("AAA", Heap::kOld)));
-  __ StringToCharCode(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(StringToCharCodeIllegalLength, test) {
-  EXPECT_EQ(-1, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS;
-//    GreaterThanTOS;
-//
-//    Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are
-//    both smis and result of SP[0] <op> SP[-1] is a smi - if this is true
-//    then pops operands and pushes result on the stack and skips the next
-//    instruction (which implements a slow path fallback).
-ASSEMBLER_TEST_GENERATE(AddTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ PushConstant(Smi::Handle(Smi::New(84)));
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AddTOS, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AddTOSOverflow, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ AddTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AddTOSOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AddTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ AddTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AddTOSNonSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(SubTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(30)));
-  __ PushConstant(Smi::Handle(Smi::New(-12)));
-  __ SubTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(SubTOS, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(SubTOSOverflow, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(Smi::kMinValue)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ SubTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(SubTOSOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(SubTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ SubTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(SubTOSNonSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(MulTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(-6)));
-  __ PushConstant(Smi::Handle(Smi::New(-7)));
-  __ MulTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(MulTOS, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(MulTOSOverflow, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(Smi::kMaxValue)));
-  __ PushConstant(Smi::Handle(Smi::New(-8)));
-  __ MulTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(MulTOSOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(MulTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ MulTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(MulTOSNonSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitOrTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(0x22)));
-  __ PushConstant(Smi::Handle(Smi::New(0x08)));
-  __ BitOrTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BitOrTOS, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitOrTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(0x08)));
-  __ BitOrTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BitOrTOSNonSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitAndTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(0x2a)));
-  __ PushConstant(Smi::Handle(Smi::New(0xaa)));
-  __ BitAndTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BitAndTOS, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitAndTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(0x08)));
-  __ BitAndTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BitAndTOSNonSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(EqualTOSTrue, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ EqualTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(EqualTOSTrue, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(EqualTOSFalse, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ EqualTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::True());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(EqualTOSFalse, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(EqualTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ EqualTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Bool::True());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(EqualTOSNonSmi, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(LessThanTOSTrue, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ LessThanTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(LessThanTOSTrue, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(LessThanTOSFalse, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ LessThanTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(LessThanTOSFalse, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(LessThanTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ LessThanTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Bool::True());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(LessThanTOSNonSmi, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(GreaterThanTOSTrue, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ GreaterThanTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(GreaterThanTOSTrue, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(GreaterThanTOSFalse, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ GreaterThanTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(GreaterThanTOSFalse, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(GreaterThanTOSNonSmi, assembler) {
-  const String& numstr =
-      String::Handle(String::New("9176543219876543210", Heap::kOld));
-  __ PushConstant(Integer::Handle(Integer::New(numstr, Heap::kOld)));
-  __ PushConstant(Smi::Handle(Smi::New(-42)));
-  __ GreaterThanTOS();
-  // Shouldn't be skipped.
-  MakeDummyInstanceCall(assembler, Bool::True());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(GreaterThanTOSNonSmi, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-//  - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
-//
-//    Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
-//    If these instructions can trigger a deoptimization, the following
-//    instruction should be Deopt. If no deoptimization should be triggered,
-//    the immediately following instruction is skipped.
-ASSEMBLER_TEST_GENERATE(AddNoOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(20)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(22)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Add(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(AddNoOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AddOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Add(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(AddOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(SubNoOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(64)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(22)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Sub(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(SubNoOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(SubOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Sub(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(SubOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(MulNoOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-6)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-7)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mul(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(MulNoOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(MulOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-8)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mul(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(MulOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DivNoDeopt, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(27)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(3)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Div(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DivNoDeopt, test) {
-  EXPECT_EQ(9, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DivZero, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(3)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Div(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DivZero, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DivCornerCase, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Div(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DivCornerCase, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ModPosPos, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(4)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mod(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ModPosPos, test) {
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ModNegPos, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(4)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mod(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ModNegPos, test) {
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ModPosNeg, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-4)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mod(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ModPosNeg, test) {
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ModZero, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(3)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Mod(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ModZero, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ShlNoDeopt, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Shl(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ShlNoDeopt, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ShlOverflow, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMaxValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Shl(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ShlOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ShlNegShift, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Shl(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ShlNegShift, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ShrNoDeopt, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(84)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Shr(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(-42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ShrNoDeopt, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(ShrNegShift, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ Shr(2, 0, 1);
-  __ LoadConstant(2, Smi::Handle(Smi::New(42)));
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(ShrNegShift, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - Neg rA , rD
-//
-//    FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
-//    immediately following instruction is skipped.
-ASSEMBLER_TEST_GENERATE(NegPos, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Neg(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(NegPos, test) {
-  EXPECT_EQ(-42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(NegNeg, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Neg(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(NegNeg, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(NegOverflow, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(Smi::kMinValue)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Neg(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(NegOverflow, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - BitOr, BitAnd, BitXor rA, rB, rC
-//
-//    FP[rA] <- FP[rB] op FP[rC]
-ASSEMBLER_TEST_GENERATE(BitOr, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(0x2)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0x28)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ BitOr(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BitOr, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitAnd, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(0x2b)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0x6a)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ BitAnd(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BitAnd, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BitXor, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(0x37)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0x1d)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-1)));
-  __ BitXor(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BitXor, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - BitNot rA, rD
-//
-//    FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
-ASSEMBLER_TEST_GENERATE(BitNot, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(~42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ BitNot(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(BitNot, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS
-//
-//    Skips the next instruction unless the given condition holds. 'Num'
-//    variants perform number check while non-Num variants just compare
-//    RawObject pointers.
-//
-//    Used to implement conditional jump:
-//
-//        IfNeStrictTOS
-//        Jump T         ;; jump if not equal
-ASSEMBLER_TEST_GENERATE(IfNeStrictTOSTaken, assembler) {
-  Label branch_taken;
-  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
-  const Array& array2 = Array::Handle(Array::New(2, Heap::kOld));
-  __ PushConstant(array1);
-  __ PushConstant(array2);
-  __ IfNeStrictTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictTOSTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeStrictTOSNotTaken, assembler) {
-  Label branch_taken;
-  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
-  __ PushConstant(array1);
-  __ PushConstant(array1);
-  __ IfNeStrictTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictTOSNotTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-// TODO(zra): Also add tests that use Mint, Bignum.
-ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTaken, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ IfNeStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTaken, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ IfNeStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSTakenDouble, assembler) {
-  Label branch_taken;
-  __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld)));
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ IfNeStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictNumTOSTakenDouble, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeStrictNumTOSNotTakenDouble, assembler) {
-  Label branch_taken;
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ IfNeStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeStrictNumTOSNotTakenDouble, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqStrictTOSTaken, assembler) {
-  Label branch_taken;
-  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
-  __ PushConstant(array1);
-  __ PushConstant(array1);
-  __ IfEqStrictTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictTOSTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqStrictTOSNotTaken, assembler) {
-  Label branch_taken;
-  const Array& array1 = Array::Handle(Array::New(1, Heap::kOld));
-  const Array& array2 = Array::Handle(Array::New(2, Heap::kOld));
-  __ PushConstant(array1);
-  __ PushConstant(array2);
-  __ IfEqStrictTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictTOSNotTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-// TODO(zra): Also add tests that use Mint, Bignum.
-ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTaken, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ IfEqStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTaken, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ IfEqStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTaken, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSTakenDouble, assembler) {
-  Label branch_taken;
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ IfEqStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictNumTOSTakenDouble, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqStrictNumTOSNotTakenDouble, assembler) {
-  Label branch_taken;
-  __ PushConstant(Double::Handle(Double::New(-1.0, Heap::kOld)));
-  __ PushConstant(Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ IfEqStrictNumTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqStrictNumTOSNotTakenDouble, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - BooleanNegateTOS
-//
-//    SP[0] = !SP[0]
-ASSEMBLER_TEST_GENERATE(BooleanNegateTOSTrue, assembler) {
-  __ PushConstant(Bool::True());
-  __ BooleanNegateTOS();
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BooleanNegateTOSTrue, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BooleanNegateTOSFalse, assembler) {
-  __ PushConstant(Bool::False());
-  __ BooleanNegateTOS();
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(BooleanNegateTOSFalse, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-//  - AssertBoolean A
-//
-//    Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0).
-ASSEMBLER_TEST_GENERATE(AssertBooleanTrue, assembler) {
-  __ PushConstant(Bool::True());
-  __ AssertBoolean(1);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AssertBooleanTrue, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AssertBooleanFalse, assembler) {
-  __ PushConstant(Bool::False());
-  __ AssertBoolean(1);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AssertBooleanFalse, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AssertBooleanNotNull, assembler) {
-  __ PushConstant(Bool::True());
-  __ AssertBoolean(0);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AssertBooleanNotNull, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(AssertBooleanFail1, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ AssertBoolean(1);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AssertBooleanFail1, test) {
-  EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError());
-}
-
-ASSEMBLER_TEST_GENERATE(AssertBooleanFail2, assembler) {
-  __ PushConstant(Object::null_object());
-  __ AssertBoolean(0);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(AssertBooleanFail2, test) {
-  EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsError());
-}
-
-//  - Drop1; DropR n; Drop n
-//
-//    Drop 1 or n values from the stack, if instruction is DropR push the first
-//    dropped value to the stack;
-ASSEMBLER_TEST_GENERATE(Drop1, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ Drop1();
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(Drop1, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(Drop, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ Drop(11);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(Drop, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DropR, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(41)));
-  __ DropR(11);
-  __ AddTOS();
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(DropR, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - Frame D
-//
-//    Reserve and initialize with null space for D local variables.
-ASSEMBLER_TEST_GENERATE(FrameInitialized1, assembler) {
-  __ Frame(1);
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(FrameInitialized1, test) {
-  EXPECT(EXECUTE_TEST_CODE_OBJECT(test->code()).IsNull());
-}
-
-ASSEMBLER_TEST_GENERATE(FrameInitialized, assembler) {
-  Label error;
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ Frame(4);
-  __ PushConstant(Object::null_object());
-  __ IfNeStrictTOS();
-  __ Jump(&error);
-  __ PushConstant(Object::null_object());
-  __ IfNeStrictTOS();
-  __ Jump(&error);
-  __ PushConstant(Object::null_object());
-  __ IfNeStrictTOS();
-  __ Jump(&error);
-  __ PushConstant(Object::null_object());
-  __ IfNeStrictTOS();
-  __ Jump(&error);
-  __ ReturnTOS();
-
-  // If a frame slot was not initialized to null.
-  __ Bind(&error);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(FrameInitialized, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - StoreLocal rX; PopLocal rX
-//
-//    Store top of the stack into FP[rX] and pop it if needed.
-//
-//  - Push rX
-//
-//    Push FP[rX] to the stack.
-ASSEMBLER_TEST_GENERATE(StoreLocalPush, assembler) {
-  __ Frame(1);
-  __ PushConstant(Smi::Handle(Smi::New(37)));
-  __ PushConstant(Smi::Handle(Smi::New(21)));
-  __ StoreLocal(0);
-  __ Push(0);
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(StoreLocalPush, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(PopLocalPush, assembler) {
-  __ Frame(1);
-  __ PushConstant(Smi::Handle(Smi::New(21)));
-  __ PopLocal(0);
-  __ Push(0);
-  __ Push(0);
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(PopLocalPush, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(LoadConstantPush, assembler) {
-  __ Frame(1);
-  __ LoadConstant(0, Smi::Handle(Smi::New(21)));
-  __ Push(0);
-  __ Push(0);
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(LoadConstantPush, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - Move rA, rX
-//
-//    FP[rA] <- FP[rX]
-//    Note: rX is signed so it can be used to address parameters which are
-//    at negative indices with respect to FP.
-ASSEMBLER_TEST_GENERATE(MoveLocalLocal, assembler) {
-  __ Frame(2);
-  __ PushConstant(Smi::Handle(Smi::New(21)));
-  __ PopLocal(0);
-  __ Move(1, 0);
-  __ Push(0);
-  __ Push(1);
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(MoveLocalLocal, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - Return R; ReturnTOS
-//
-//    Return to the caller using either a value from the given register or a
-//    value from the top-of-stack as a result.
-ASSEMBLER_TEST_GENERATE(Return1, assembler) {
-  __ Frame(1);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ StoreLocal(0);
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(Return1, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(Return2, assembler) {
-  __ Frame(2);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ StoreLocal(1);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(Return2, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(Loop, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
-
-  Label loop_entry, error;
-  __ Bind(&loop_entry);
-  // Add 1 to FP[1].
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ Push(1);
-  __ AddTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(-1)));
-  __ PopLocal(1);
-
-  // Subtract 1 from FP[0].
-  __ Push(0);
-  __ PushConstant(Smi::Handle(Smi::New(1)));
-  __ SubTOS();
-  // Should be skipped.
-  MakeDummyInstanceCall(assembler, Smi::Handle(Smi::New(-1)));
-
-  // Jump to loop_entry if FP[0] != 0.
-  __ StoreLocal(0);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ IfNeStrictNumTOS();
-  __ Jump(&loop_entry);
-
-  __ Return(1);
-
-  __ Bind(&error);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(Loop, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - LoadClassIdTOS, LoadClassId rA, D
-//
-//    LoadClassIdTOS loads the class id from the object at SP[0] and stores it
-//    to SP[0]. LoadClassId loads the class id from FP[rA] and stores it to
-//    FP[D].
-ASSEMBLER_TEST_GENERATE(LoadClassIdTOS, assembler) {
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ LoadClassIdTOS();
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(LoadClassIdTOS, test) {
-  EXPECT_EQ(kSmiCid, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(LoadClassId, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadClassId(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(LoadClassId, test) {
-  EXPECT_EQ(kSmiCid, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - CreateArrayTOS
-//
-//    Allocate array of length SP[0] with type arguments SP[-1].
-ASSEMBLER_TEST_GENERATE(CreateArrayTOS, assembler) {
-  __ PushConstant(Object::null_object());
-  __ PushConstant(Smi::Handle(Smi::New(10)));
-  __ CreateArrayTOS();
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(CreateArrayTOS, test) {
-  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
-  EXPECT(obj.IsArray());
-  Array& array = Array::Handle();
-  array ^= obj.raw();
-  EXPECT_EQ(10, array.Length());
-}
-
-//  - TestSmi rA, rD
-//
-//    If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD]
-//    must be Smis.
-ASSEMBLER_TEST_GENERATE(TestSmiTrue, assembler) {
-  Label branch_taken;
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(7)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(3)));
-  __ TestSmi(0, 1);
-  __ Jump(&branch_taken);
-  __ PushConstant(Bool::True());
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(TestSmiTrue, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(TestSmiFalse, assembler) {
-  Label branch_taken;
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(8)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(4)));
-  __ TestSmi(0, 1);
-  __ Jump(&branch_taken);
-  __ PushConstant(Bool::True());
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Bool::False());
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(TestSmiFalse, test) {
-  EXPECT(!EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-//  - TestCids rA, D
-//
-//    The next D instructions must be Nops whose D field encodes a class id. If
-//    the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's
-//    A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found,
-//    jump to PC + N.
-ASSEMBLER_TEST_GENERATE(TestCidsTrue, assembler) {
-  Label true_branch, no_match_branch;
-  __ Frame(2);
-  __ LoadConstant(0, Object::Handle(String::New("Hi", Heap::kOld)));
-  const intptr_t num_cases = 2;
-  __ TestCids(0, num_cases);
-  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
-  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
-  __ Jump(&no_match_branch);
-  __ Jump(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
-  __ Return(1);
-  __ Bind(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ Return(1);
-  __ Bind(&no_match_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(TestCidsTrue, test) {
-  EXPECT_EQ(1, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(TestCidsFalse, assembler) {
-  Label true_branch, no_match_branch;
-  __ Frame(2);
-  __ LoadConstant(0, Object::Handle(Smi::New(42)));
-  const intptr_t num_cases = 2;
-  __ TestCids(0, num_cases);
-  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
-  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
-  __ Jump(&no_match_branch);
-  __ Jump(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
-  __ Return(1);
-  __ Bind(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ Return(1);
-  __ Bind(&no_match_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(TestCidsFalse, test) {
-  EXPECT_EQ(0, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(TestCidsNoMatch, assembler) {
-  Label true_branch, no_match_branch;
-  __ Frame(2);
-  __ LoadConstant(0, Object::Handle(Array::New(1, Heap::kOld)));
-  const intptr_t num_cases = 2;
-  __ TestCids(0, num_cases);
-  __ Nop(0, static_cast<uint16_t>(kSmiCid));            // Smi    => false
-  __ Nop(1, static_cast<uint16_t>(kOneByteStringCid));  // String => true
-  __ Jump(&no_match_branch);
-  __ Jump(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));  // false branch
-  __ Return(1);
-  __ Bind(&true_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(1)));
-  __ Return(1);
-  __ Bind(&no_match_branch);
-  __ LoadConstant(1, Smi::Handle(Smi::New(2)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(TestCidsNoMatch, test) {
-  EXPECT_EQ(2, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - CheckSmi rA
-//
-//    If FP[rA] is a Smi, then skip the next instruction.
-ASSEMBLER_TEST_GENERATE(CheckSmiPass, assembler) {
-  __ Frame(1);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ LoadConstant(0, Smi::Handle(Smi::New(0)));
-  __ CheckSmi(0);
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(CheckSmiPass, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(CheckSmiFail, assembler) {
-  __ Frame(1);
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(0, Bool::True());
-  __ CheckSmi(0);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(CheckSmiFail, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - CheckClassId rA, D
-//
-//    If the object at FP[rA]'s class id matches the class id in PP[D], then
-//    skip the following instruction.
-ASSEMBLER_TEST_GENERATE(CheckClassIdSmiPass, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadClassId(1, 0);
-  __ CheckClassId(1, kSmiCid);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(CheckClassIdSmiPass, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(CheckClassIdNonSmiPass, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Bool::True());
-  __ LoadClassId(1, 0);
-  __ CheckClassId(1, kBoolCid);
-  __ LoadConstant(0, Bool::False());
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(CheckClassIdNonSmiPass, test) {
-  EXPECT(EXECUTE_TEST_CODE_BOOL(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(CheckClassIdFail, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadClassId(1, 0);
-  __ CheckClassId(1, kBoolCid);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(CheckClassIdFail, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - If<Cond>Null rA
-//
-//    Cond is Eq or Ne. Skips the next instruction unless the given condition
-//    holds.
-ASSEMBLER_TEST_GENERATE(IfEqNullNotNull, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ IfEqNull(0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(IfEqNullNotNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqNullIsNull, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Object::null_object());
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ IfEqNull(0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(IfEqNullIsNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeNullIsNull, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Object::null_object());
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ IfNeNull(0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(IfNeNullIsNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeNullNotNull, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ IfNeNull(0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(IfNeNullNotNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqNullTOSNotNull, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ IfEqNullTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqNullTOSNotNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfEqNullTOSIsNull, assembler) {
-  Label branch_taken;
-  __ PushConstant(Object::null_object());
-  __ IfEqNullTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfEqNullTOSIsNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeNullTOSNotNull, assembler) {
-  Label branch_taken;
-  __ PushConstant(Smi::Handle(Smi::New(-1)));
-  __ IfNeNullTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeNullTOSNotNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfNeNullTOSIsNull, assembler) {
-  Label branch_taken;
-  __ PushConstant(Object::null_object());
-  __ IfNeNullTOS();
-  __ Jump(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(42)));
-  __ ReturnTOS();
-  __ Bind(&branch_taken);
-  __ PushConstant(Smi::Handle(Smi::New(0)));
-  __ ReturnTOS();
-}
-
-ASSEMBLER_TEST_RUN(IfNeNullTOSIsNull, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - If<Cond> rA, rD
-//
-//    Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and
-//    unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt.
-//    Skips the next instruction unless FP[rA] <Cond> FP[rD]. Assumes that
-//    FP[rA] and FP[rD] are Smis or unboxed doubles as indicated by <Cond>.
-ASSEMBLER_TEST_GENERATE(IfLeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfLe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfLeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfLeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
-  __ IfLe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfLeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfLtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfLt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfLtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfLtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
-  __ IfLt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfLtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfGeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
-  __ IfGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfGeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfGeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfGeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfGtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
-  __ IfGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfGtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfGtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfGtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-#if defined(ARCH_IS_64_BIT)
-ASSEMBLER_TEST_GENERATE(IfDNeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDNe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDNeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDNeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDNe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDNeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDNeNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDNe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDNeNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDEqTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDEq(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDEqTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDEqFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDEq(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDEqFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDEqNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDEq(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDEqNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLeNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLeNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDLtNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDLt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDLtNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGeNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGeNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(-5.0, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfDGtNan, assembler) {
-  const double not_a_number = bit_cast<double, intptr_t>(0x7FF8000000000000LL);
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Double::Handle(Double::New(not_a_number, Heap::kOld)));
-  __ LoadConstant(2, Double::Handle(Double::New(100.0, Heap::kOld)));
-  __ UnboxDouble(1, 1);
-  __ UnboxDouble(2, 2);
-  __ IfDGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfDGtNan, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-#endif  // defined(ARCH_IS_64_BIT)
-
-ASSEMBLER_TEST_GENERATE(IfULeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfULe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfULeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfULeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
-  __ IfULe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfULeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfULeNegTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(-5)));
-  __ IfULe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfULeNegTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfULtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfULt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfULtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfULtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
-  __ IfULt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfULtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfUGeTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
-  __ IfUGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfUGeTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfUGeFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfUGe(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfUGeFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfUGtTrue, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(100)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(5)));
-  __ IfUGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfUGtTrue, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(IfUGtFalse, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ LoadConstant(2, Smi::Handle(Smi::New(100)));
-  __ IfUGt(1, 2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(-1)));
-  __ Return(0);
-}
-
-ASSEMBLER_TEST_RUN(IfUGtFalse, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - Min, Max rA, rB, rC
-//
-//    FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are
-//    Smis.
-ASSEMBLER_TEST_GENERATE(Min, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(500)));
-  __ Min(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(Min, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(Max, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(5)));
-  __ Max(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(Max, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - UnboxInt32 rA, rB, C
-//
-//    Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be
-//    truncated. If FP[rA] is successfully unboxed the following instruction is
-//    skipped.
-ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateSuccess, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(1234)));
-  __ UnboxInt32(1, 0, /*may_truncate=*/0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateSuccess, test) {
-  EXPECT_EQ(1234, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxInt32NoTrunctateFail, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Integer::Handle(Integer::New(Smi::kMaxValue + 1)));
-  __ UnboxInt32(1, 0, /*may_truncate=*/0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt32NoTrunctateFail, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxInt32TrunctateSuccess, assembler) {
-  __ Frame(2);
-  __ LoadConstant(
-      0, Integer::Handle(Integer::New(static_cast<int64_t>(kMaxInt32) + 1)));
-  __ UnboxInt32(1, 0, /*may_truncate=*/1);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt32TrunctateSuccess, test) {
-  EXPECT_EQ(static_cast<int64_t>(kMaxInt32) + 1,
-            EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-//  - BoxInt32 rA, rD
-//
-//    Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA].
-ASSEMBLER_TEST_GENERATE(BoxInt32, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ UnboxInt32(1, 0, /*may_truncate=*/0);
-  __ Nop(0);  // Unboxing succeeds.
-  __ BoxInt32(2, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BoxInt32, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - BoxUint32 rA, rD
-//
-//    Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA].
-ASSEMBLER_TEST_GENERATE(BoxUint32, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ UnboxInt32(1, 0, /*may_truncate=*/0);
-  __ Nop(0);  // Unboxing succeeds.
-  __ BoxUint32(2, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BoxUint32, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - UnboxInt64 rA, rD
-//
-//    Unboxes the integer in FP[rD] into FP[rA].
-ASSEMBLER_TEST_GENERATE(UnboxInt64MaxMint, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
-  __ UnboxInt64(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt64MaxMint, test) {
-  EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxInt64MinMint, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMinInt64)));
-  __ UnboxInt64(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt64MinMint, test) {
-  EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxInt64Smi, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ UnboxInt64(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxInt64Smi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-//  - BoxInt64 rA, rD
-//
-//    Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the
-//    value does not fit into a Smi the following instruction is skipped. (The
-//    following instruction should be a jump to a label after the slow path
-//    allocating a Mint box and writing into the Mint box.)
-ASSEMBLER_TEST_GENERATE(BoxInt64Smi, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ UnboxInt64(1, 0);
-  __ BoxInt64(2, 1);
-  __ Nop(0);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BoxInt64Smi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(BoxInt64MintFails, assembler) {
-  Label done;
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
-  __ UnboxInt64(1, 0);
-  __ BoxInt64(2, 1);  // Boxing into Smi fails.
-  __ Jump(&done);
-  // Faking a slow path, with a different Mint value.
-  __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42)));
-  __ Bind(&done);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(BoxInt64MintFails, test) {
-  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
-  EXPECT(obj.IsMint());
-  EXPECT_EQ(kMaxInt64 - 42, Mint::Cast(obj).value());
-}
-
-ASSEMBLER_TEST_GENERATE(WriteIntoMint, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt64)));
-  __ UnboxInt64(1, 0);
-  __ LoadConstant(2, Integer::Handle(Integer::New(kMaxInt64 - 42)));
-  __ WriteIntoMint(2, 1);  // Transplant unboxed value into an existing box.
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(WriteIntoMint, test) {
-  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
-  EXPECT(obj.IsMint());
-  EXPECT_EQ(kMaxInt64, Mint::Cast(obj).value());
-}
-
-//  - UnboxedWidthExtender rA rB C
-//
-//    Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
-//    integer in FP[rA]. C contains SmallRepresentation which determines how
-//    the integer is extended.
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Positive, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt8 + 0xFFFFFF00)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0x7F, overwrite the upper bits with 0.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Positive, test) {
-  EXPECT_EQ(static_cast<uint32_t>(kMaxInt8),
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt8Negative, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0xFF, overwrite the upper bits with 1.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt8);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt8Negative, test) {
-  // least significant 32 bits set to 1.
-  EXPECT_EQ(kMaxUint32,
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint8, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0xFF, overwrite the upper bits with 0.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint8);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint8, test) {
-  EXPECT_EQ(kMaxUint8,
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Positive, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt16 + 0xFFFF0000)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0x7FFF, overwrite the upper bits with 0.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Positive, test) {
-  EXPECT_EQ(static_cast<uint32_t>(kMaxInt16),
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderInt16Negative, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxInt32)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0xFFFF, overwrite the upper bits with 1.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedInt16);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderInt16Negative, test) {
-  // least significant 32 bits set to 1.
-  EXPECT_EQ(kMaxUint32,
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(UnboxedWidthExtenderUint16, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Integer::Handle(Integer::New(kMaxUint32)));
-  __ UnboxInt64(1, 0);
-  // The lower bits contain 0xFFFF, overwrite the upper bits with 0.
-  __ UnboxedWidthExtender(2, 1, kSmallUnboxedUint16);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(UnboxedWidthExtenderUint16, test) {
-  EXPECT_EQ(kMaxUint16,
-            kMaxUint32 & EXECUTE_TEST_CODE_INTPTR_UNBOXED(test->code()));
-}
-
-#if defined(ARCH_IS_64_BIT)
-//  - UnboxDouble rA, rD
-//
-//    Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double.
-//
-//  - CheckedUnboxDouble rA, rD
-//
-//    Unboxes FP[rD] into FP[rA] and skips the following instruction unless
-//    FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a
-//    double.
-ASSEMBLER_TEST_GENERATE(UnboxDouble, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ UnboxDouble(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(UnboxDouble, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(CheckedUnboxDouble, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ CheckedUnboxDouble(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(CheckedUnboxDouble, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(WriteIntoDouble, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ UnboxDouble(1, 0);
-  __ LoadConstant(2, Double::Handle(Double::New(0.0, Heap::kOld)));
-  __ WriteIntoDouble(2, 1);  // Transplant unboxed value into an existing box.
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(WriteIntoDouble, test) {
-  const Object& obj = EXECUTE_TEST_CODE_OBJECT(test->code());
-  EXPECT(obj.IsDouble());
-  EXPECT_EQ(42.0, Double::Cast(obj).value());
-}
-
-ASSEMBLER_TEST_GENERATE(CheckedUnboxSmi, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ CheckedUnboxDouble(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(0)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(CheckedUnboxSmi, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(CheckedUnboxFail, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Bool::True());
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ CheckedUnboxDouble(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(CheckedUnboxFail, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-//  - DAdd, DSub, DMul, DDiv rA, rB, rC
-//
-//    Arithmetic operations on unboxed doubles. FP[rA] <- FP[rB] op FP[rC].
-ASSEMBLER_TEST_GENERATE(DAdd, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(41.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DAdd(2, 1, 0);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DAdd, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DSub, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(1.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(43.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DSub(2, 1, 0);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DSub, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DMul, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(6.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(7.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DMul(2, 1, 0);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DMul, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DDiv, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(2.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(84.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DDiv(2, 1, 0);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DDiv, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DNeg, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(-42.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ DNeg(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DNeg, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DSqrt, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(36.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ DSqrt(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DSqrt, test) {
-  EXPECT_EQ(6.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-//  - SmiToDouble rA, rD
-//
-//    Convert the Smi in FP[rD] to an unboxed double in FP[rA].
-//
-//  - DoubleToSmi rA, rD
-//
-//    If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then
-//    this instruction does so, and skips the following instruction. Otherwise,
-//    the following instruction is not skipped.
-ASSEMBLER_TEST_GENERATE(SmiToDouble, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Smi::Handle(Smi::New(42)));
-  __ SmiToDouble(1, 0);
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(SmiToDouble, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DoubleToSmi, assembler) {
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ UnboxDouble(0, 0);
-  __ DoubleToSmi(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DoubleToSmi, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMax, assembler) {
-  const double m = static_cast<double>(Smi::kMaxValue - 1000);
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ UnboxDouble(0, 0);
-  __ DoubleToSmi(0, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DoubleToSmiNearMax, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DoubleToSmiNearMin, assembler) {
-  const double m = static_cast<double>(Smi::kMinValue);
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(m, Heap::kOld)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ UnboxDouble(0, 0);
-  __ DoubleToSmi(0, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DoubleToSmiNearMin, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DoubleToSmiFailPos, assembler) {
-  const double pos_overflow = static_cast<double>(Smi::kMaxValue + 1);
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(pos_overflow, Heap::kOld)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ UnboxDouble(0, 0);
-  __ DoubleToSmi(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DoubleToSmiFailPos, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DoubleToSmiFailNeg, assembler) {
-  const double neg_overflow = static_cast<double>(Smi::kMinValue - 1000);
-  __ Frame(2);
-  __ LoadConstant(0, Double::Handle(Double::New(neg_overflow, Heap::kOld)));
-  __ LoadConstant(1, Smi::Handle(Smi::New(-1)));
-  __ UnboxDouble(0, 0);
-  __ DoubleToSmi(1, 0);
-  __ LoadConstant(1, Smi::Handle(Smi::New(42)));
-  __ Return(1);
-}
-
-ASSEMBLER_TEST_RUN(DoubleToSmiFailNeg, test) {
-  EXPECT_EQ(42, EXECUTE_TEST_CODE_INTPTR(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DMin, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(500.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DMin(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DMin, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-ASSEMBLER_TEST_GENERATE(DMax, assembler) {
-  __ Frame(3);
-  __ LoadConstant(0, Double::Handle(Double::New(42.0, Heap::kOld)));
-  __ LoadConstant(1, Double::Handle(Double::New(5.0, Heap::kOld)));
-  __ UnboxDouble(0, 0);
-  __ UnboxDouble(1, 1);
-  __ DMax(2, 0, 1);
-  __ Return(2);
-}
-
-ASSEMBLER_TEST_RUN(DMax, test) {
-  EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(test->code()));
-}
-
-#endif  // defined(ARCH_IS_64_BIT)
-
-}  // namespace compiler
-}  // namespace dart
-
-#endif  // defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index b82632d..5079549 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -687,10 +687,6 @@
             break;
           }
           case 2: {
-            if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-              Unknown(instr);
-              return;
-            }
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs");
             break;
@@ -725,11 +721,6 @@
           }
         }
       } else {
-        if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-          // strex and ldrex are only supported after ARMv6.
-          Unknown(instr);
-          return;
-        }
         // synchronization primitives
         switch (instr->Bits(20, 4)) {
           case 8: {
@@ -1433,8 +1424,7 @@
   Instr* instr = Instr::At(pc);
 
   if (instr->ConditionField() == kSpecialCondition) {
-    if ((instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) &&
-        (TargetCPUFeatures::arm_version() != ARMv5TE)) {
+    if (instr->InstructionBits() == static_cast<int32_t>(0xf57ff01f)) {
       Format(instr, "clrex");
     } else {
       if (instr->IsSIMDDataProcessing()) {
diff --git a/runtime/vm/compiler/assembler/disassembler_dbc.cc b/runtime/vm/compiler/assembler/disassembler_dbc.cc
deleted file mode 100644
index 7a15129..0000000
--- a/runtime/vm/compiler/assembler/disassembler_dbc.cc
+++ /dev/null
@@ -1,243 +0,0 @@
-// 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.
-
-#include "vm/compiler/assembler/disassembler.h"
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#include "platform/assert.h"
-#include "vm/constants_dbc.h"
-#include "vm/cpu.h"
-#include "vm/instructions.h"
-
-namespace dart {
-
-static const char* kOpcodeNames[] = {
-#define BYTECODE_NAME(name, encoding, op1, op2, op3) #name,
-    BYTECODES_LIST(BYTECODE_NAME)
-#undef BYTECODE_NAME
-};
-
-static const size_t kOpcodeCount =
-    sizeof(kOpcodeNames) / sizeof(kOpcodeNames[0]);
-
-typedef void (*BytecodeFormatter)(char* buffer,
-                                  intptr_t size,
-                                  uword pc,
-                                  uint32_t bc);
-typedef void (*Fmt)(char** buf, intptr_t* size, uword pc, int32_t value);
-
-template <typename ValueType>
-void FormatOperand(char** buf,
-                   intptr_t* size,
-                   const char* fmt,
-                   ValueType value) {
-  intptr_t written = Utils::SNPrint(*buf, *size, fmt, value);
-  if (written < *size) {
-    *buf += written;
-    *size += written;
-  } else {
-    *size = -1;
-  }
-}
-
-static void Fmt___(char** buf, intptr_t* size, uword pc, int32_t value) {}
-
-static void Fmttgt(char** buf, intptr_t* size, uword pc, int32_t value) {
-  FormatOperand(buf, size, "-> %" Px, pc + (value << 2));
-}
-
-static void Fmtlit(char** buf, intptr_t* size, uword pc, int32_t value) {
-  FormatOperand(buf, size, "k%d", value);
-}
-
-static void Fmtreg(char** buf, intptr_t* size, uword pc, int32_t value) {
-  FormatOperand(buf, size, "r%d", value);
-}
-
-static void Fmtxeg(char** buf, intptr_t* size, uword pc, int32_t value) {
-  if (value < 0) {
-    FormatOperand(buf, size, "FP[%d]", value);
-  } else {
-    Fmtreg(buf, size, pc, value);
-  }
-}
-
-static void Fmtnum(char** buf, intptr_t* size, uword pc, int32_t value) {
-  FormatOperand(buf, size, "#%d", value);
-}
-
-static void Apply(char** buf,
-                  intptr_t* size,
-                  uword pc,
-                  Fmt fmt,
-                  int32_t value,
-                  const char* suffix) {
-  if (*size <= 0) {
-    return;
-  }
-
-  fmt(buf, size, pc, value);
-  if (*size > 0) {
-    FormatOperand(buf, size, "%s", suffix);
-  }
-}
-
-static void Format0(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {}
-
-static void FormatT(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t x = static_cast<int32_t>(op) >> 8;
-  Apply(&buf, &size, pc, op1, x, "");
-}
-
-static void FormatA(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  Apply(&buf, &size, pc, op1, a, "");
-}
-
-static void FormatA_D(char* buf,
-                      intptr_t size,
-                      uword pc,
-                      uint32_t op,
-                      Fmt op1,
-                      Fmt op2,
-                      Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  const int32_t bc = op >> 16;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, bc, "");
-}
-
-static void FormatA_X(char* buf,
-                      intptr_t size,
-                      uword pc,
-                      uint32_t op,
-                      Fmt op1,
-                      Fmt op2,
-                      Fmt op3) {
-  const int32_t a = (op & 0xFF00) >> 8;
-  const int32_t bc = static_cast<int32_t>(op) >> 16;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, bc, "");
-}
-
-static void FormatX(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t bc = static_cast<int32_t>(op) >> 16;
-  Apply(&buf, &size, pc, op1, bc, "");
-}
-
-static void FormatD(char* buf,
-                    intptr_t size,
-                    uword pc,
-                    uint32_t op,
-                    Fmt op1,
-                    Fmt op2,
-                    Fmt op3) {
-  const int32_t bc = op >> 16;
-  Apply(&buf, &size, pc, op1, bc, "");
-}
-
-static void FormatA_B_C(char* buf,
-                        intptr_t size,
-                        uword pc,
-                        uint32_t op,
-                        Fmt op1,
-                        Fmt op2,
-                        Fmt op3) {
-  const int32_t a = (op >> 8) & 0xFF;
-  const int32_t b = (op >> 16) & 0xFF;
-  const int32_t c = (op >> 24) & 0xFF;
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, b, ", ");
-  Apply(&buf, &size, pc, op3, c, "");
-}
-
-static void FormatA_B_Y(char* buf,
-                        intptr_t size,
-                        uword pc,
-                        uint32_t op,
-                        Fmt op1,
-                        Fmt op2,
-                        Fmt op3) {
-  const int32_t a = (op >> 8) & 0xFF;
-  const int32_t b = (op >> 16) & 0xFF;
-  const int32_t y = static_cast<int8_t>((op >> 24) & 0xFF);
-  Apply(&buf, &size, pc, op1, a, ", ");
-  Apply(&buf, &size, pc, op2, b, ", ");
-  Apply(&buf, &size, pc, op3, y, "");
-}
-
-#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3)                      \
-  static void Format##name(char* buf, intptr_t size, uword pc, uint32_t op) {  \
-    Format##encoding(buf, size, pc, op, Fmt##op1, Fmt##op2, Fmt##op3);         \
-  }
-BYTECODES_LIST(BYTECODE_FORMATTER)
-#undef BYTECODE_FORMATTER
-
-static const BytecodeFormatter kFormatters[] = {
-#define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) &Format##name,
-    BYTECODES_LIST(BYTECODE_FORMATTER)
-#undef BYTECODE_FORMATTER
-};
-
-void Disassembler::DecodeInstruction(char* hex_buffer,
-                                     intptr_t hex_size,
-                                     char* human_buffer,
-                                     intptr_t human_size,
-                                     int* out_instr_size,
-                                     const Code& code,
-                                     Object** object,
-                                     uword pc) {
-  const uint32_t instr = *reinterpret_cast<uint32_t*>(pc);
-  const uint8_t opcode = instr & 0xFF;
-  ASSERT(opcode < kOpcodeCount);
-  size_t name_size =
-      Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
-
-  human_buffer += name_size;
-  human_size -= name_size;
-  kFormatters[opcode](human_buffer, human_size, pc, instr);
-
-  Utils::SNPrint(hex_buffer, hex_size, "%08x", instr);
-  if (out_instr_size) {
-    *out_instr_size = sizeof(uint32_t);
-  }
-
-  *object = NULL;
-  if (!code.IsNull()) {
-    *object = &Object::Handle();
-    if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
-      *object = NULL;
-    }
-  }
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 8552753..69e2ec7 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -249,8 +249,6 @@
     case KernelBytecode::kStoreStaticTOS_Wide:
     case KernelBytecode::kLoadStatic:
     case KernelBytecode::kLoadStatic_Wide:
-    case KernelBytecode::kPushStatic:
-    case KernelBytecode::kPushStatic_Wide:
     case KernelBytecode::kAllocate:
     case KernelBytecode::kAllocate_Wide:
     case KernelBytecode::kAllocateClosure:
diff --git a/runtime/vm/compiler/assembler/disassembler_test.cc b/runtime/vm/compiler/assembler/disassembler_test.cc
index ff78bd2..6b0691f 100644
--- a/runtime/vm/compiler/assembler/disassembler_test.cc
+++ b/runtime/vm/compiler/assembler/disassembler_test.cc
@@ -9,9 +9,7 @@
 
 namespace dart {
 
-// TODO(vegorov) this test is disabled on DBC because there is no PopRegister
-// method on DBC assembler.
-#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC)
+#if !defined(PRODUCT)
 
 ISOLATE_UNIT_TEST_CASE(Disassembler) {
   compiler::ObjectPoolBuilder object_pool_builder;
diff --git a/runtime/vm/compiler/backend/code_statistics.cc b/runtime/vm/compiler/backend/code_statistics.cc
index e0c2a54..f18339c 100644
--- a/runtime/vm/compiler/backend/code_statistics.cc
+++ b/runtime/vm/compiler/backend/code_statistics.cc
@@ -167,9 +167,10 @@
   intptr_t function_size = assembler_->CodeSize();
   unaccounted_bytes_ = function_size - instruction_bytes_;
   ASSERT(unaccounted_bytes_ >= 0);
+
+  const intptr_t unaligned_bytes = Instructions::HeaderSize() + function_size;
   alignment_bytes_ =
-      Utils::RoundUp(function_size, OS::PreferredCodeAlignment()) -
-      function_size;
+      Utils::RoundUp(unaligned_bytes, kObjectAlignment) - unaligned_bytes;
   assembler_ = NULL;
 }
 
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 7447b7e..0defd40 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -7,6 +7,7 @@
 #include "vm/compiler/backend/constant_propagator.h"
 
 #include "vm/bit_vector.h"
+#include "vm/compiler/backend/evaluator.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/il.h"
 #include "vm/compiler/backend/il_printer.h"
@@ -769,6 +770,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitInitInstanceField(InitInstanceFieldInstr* instr) {
+  // Nothing to do.
+}
+
 void ConstantPropagator::VisitInitStaticField(InitStaticFieldInstr* instr) {
   // Nothing to do.
 }
@@ -1007,18 +1012,15 @@
   const Object& left = binary_op->left()->definition()->constant_value();
   const Object& right = binary_op->right()->definition()->constant_value();
   if (IsConstant(left) && IsConstant(right)) {
-    if (left.IsInteger() && right.IsInteger()) {
-      const Integer& left_int = Integer::Cast(left);
-      const Integer& right_int = Integer::Cast(right);
-      const Integer& result =
-          Integer::Handle(Z, binary_op->Evaluate(left_int, right_int));
-      if (!result.IsNull()) {
-        SetValue(binary_op, Integer::ZoneHandle(Z, result.raw()));
-        return;
-      }
+    const Integer& result = Integer::Handle(
+        Z, Evaluator::BinaryIntegerEvaluate(left, right, binary_op->op_kind(),
+                                            binary_op->is_truncating(),
+                                            binary_op->representation(), T));
+    if (!result.IsNull()) {
+      SetValue(binary_op, Integer::ZoneHandle(Z, result.raw()));
+      return;
     }
   }
-
   SetValue(binary_op, non_constant_);
 }
 
@@ -1077,9 +1079,10 @@
 
 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) {
   const Object& value = unary_op->value()->definition()->constant_value();
-  if (IsConstant(value) && value.IsInteger()) {
-    const Integer& value_int = Integer::Cast(value);
-    const Integer& result = Integer::Handle(Z, unary_op->Evaluate(value_int));
+  if (IsConstant(value)) {
+    const Integer& result = Integer::Handle(
+        Z, Evaluator::UnaryIntegerEvaluate(value, unary_op->op_kind(),
+                                           unary_op->representation(), T));
     if (!result.IsNull()) {
       SetValue(unary_op, Integer::ZoneHandle(Z, result.raw()));
       return;
@@ -1210,36 +1213,19 @@
 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
   const Object& left = instr->left()->definition()->constant_value();
   const Object& right = instr->right()->definition()->constant_value();
-  if (IsNonConstant(left) || IsNonConstant(right)) {
-    SetValue(instr, non_constant_);
-  } else if (left.IsInteger() && right.IsInteger()) {
-    SetValue(instr, non_constant_);
-  } else if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right)) {
-    const double left_val = ToDouble(left);
-    const double right_val = ToDouble(right);
-    double result_val = 0.0;
-    switch (instr->op_kind()) {
-      case Token::kADD:
-        result_val = left_val + right_val;
-        break;
-      case Token::kSUB:
-        result_val = left_val - right_val;
-        break;
-      case Token::kMUL:
-        result_val = left_val * right_val;
-        break;
-      case Token::kDIV:
-        result_val = left_val / right_val;
-        break;
-      default:
-        UNREACHABLE();
+  if (IsConstant(left) && IsConstant(right)) {
+    const bool both_are_integers = left.IsInteger() && right.IsInteger();
+    if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
+        !both_are_integers) {
+      const double result_val = Evaluator::EvaluateDoubleOp(
+          ToDouble(left), ToDouble(right), instr->op_kind());
+      const Double& result =
+          Double::ZoneHandle(Double::NewCanonical(result_val));
+      SetValue(instr, result);
+      return;
     }
-    const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
-    SetValue(instr, result);
-  } else if (IsConstant(left) && IsConstant(right)) {
-    // Both values known, but no rule to evaluate this further.
-    SetValue(instr, non_constant_);
   }
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) {
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
new file mode 100644
index 0000000..f6adab3
--- /dev/null
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -0,0 +1,241 @@
+// 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.
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/backend/evaluator.h"
+
+namespace dart {
+
+static bool IsRepresentable(const Integer& value, Representation rep) {
+  switch (rep) {
+    case kTagged:  // Smi case.
+      return value.IsSmi();
+
+    case kUnboxedInt32:
+      if (value.IsSmi() || value.IsMint()) {
+        return Utils::IsInt(32, value.AsInt64Value());
+      }
+      return false;
+
+    case kUnboxedInt64:
+      return value.IsSmi() || value.IsMint();
+
+    case kUnboxedUint32:
+      if (value.IsSmi() || value.IsMint()) {
+        return Utils::IsUint(32, value.AsInt64Value());
+      }
+      return false;
+
+    default:
+      UNREACHABLE();
+  }
+}
+
+static RawInteger* BinaryIntegerEvaluateRaw(const Integer& left,
+                                            const Integer& right,
+                                            Token::Kind token_kind) {
+  switch (token_kind) {
+    case Token::kTRUNCDIV:
+      FALL_THROUGH;
+    case Token::kMOD:
+      // Check right value for zero.
+      if (right.AsInt64Value() == 0) {
+        break;  // Will throw.
+      }
+      FALL_THROUGH;
+    case Token::kADD:
+      FALL_THROUGH;
+    case Token::kSUB:
+      FALL_THROUGH;
+    case Token::kMUL:
+      return left.ArithmeticOp(token_kind, right, Heap::kOld);
+    case Token::kSHL:
+      FALL_THROUGH;
+    case Token::kSHR:
+      if (right.AsInt64Value() >= 0) {
+        return left.ShiftOp(token_kind, right, Heap::kOld);
+      }
+      break;
+    case Token::kBIT_AND:
+      FALL_THROUGH;
+    case Token::kBIT_OR:
+      FALL_THROUGH;
+    case Token::kBIT_XOR:
+      return left.BitOp(token_kind, right, Heap::kOld);
+    case Token::kDIV:
+      break;
+    default:
+      UNREACHABLE();
+  }
+
+  return Integer::null();
+}
+
+static RawInteger* UnaryIntegerEvaluateRaw(const Integer& value,
+                                           Token::Kind token_kind,
+                                           Zone* zone) {
+  switch (token_kind) {
+    case Token::kNEGATE:
+      return value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
+                                Heap::kOld);
+    case Token::kBIT_NOT:
+      if (value.IsSmi()) {
+        return Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
+      } else if (value.IsMint()) {
+        return Integer::New(~Mint::Cast(value).value(), Heap::kOld);
+      }
+      break;
+    default:
+      UNREACHABLE();
+  }
+  return Integer::null();
+}
+
+int64_t Evaluator::TruncateTo(int64_t v, Representation r) {
+  switch (r) {
+    case kTagged: {
+      // Smi occupies word minus kSmiTagShift bits.
+      const intptr_t kTruncateBits =
+          (kBitsPerInt64 - kBitsPerWord) + kSmiTagShift;
+      return Utils::ShiftLeftWithTruncation(v, kTruncateBits) >> kTruncateBits;
+    }
+    case kUnboxedInt32:
+      return Utils::ShiftLeftWithTruncation(v, kBitsPerInt32) >> kBitsPerInt32;
+    case kUnboxedUint32:
+      return v & kMaxUint32;
+    case kUnboxedInt64:
+      return v;
+    default:
+      UNREACHABLE();
+  }
+}
+
+RawInteger* Evaluator::BinaryIntegerEvaluate(const Object& left,
+                                             const Object& right,
+                                             Token::Kind token_kind,
+                                             bool is_truncating,
+                                             Representation representation,
+                                             Thread* thread) {
+  if (!left.IsInteger() || !right.IsInteger()) {
+    return Integer::null();
+  }
+  Zone* zone = thread->zone();
+  const Integer& left_int = Integer::Cast(left);
+  const Integer& right_int = Integer::Cast(right);
+  Integer& result = Integer::Handle(
+      zone, BinaryIntegerEvaluateRaw(left_int, right_int, token_kind));
+
+  if (!result.IsNull()) {
+    if (is_truncating) {
+      const int64_t truncated =
+          TruncateTo(result.AsTruncatedInt64Value(), representation);
+      result = Integer::New(truncated, Heap::kOld);
+      ASSERT(IsRepresentable(result, representation));
+    } else if (!IsRepresentable(result, representation)) {
+      // If this operation is not truncating it would deoptimize on overflow.
+      // Check that we match this behavior and don't produce a value that is
+      // larger than something this operation can produce. We could have
+      // specialized instructions that use this value under this assumption.
+      return Integer::null();
+    }
+    const char* error_str = NULL;
+    result ^= result.CheckAndCanonicalize(thread, &error_str);
+    if (error_str != NULL) {
+      FATAL1("Failed to canonicalize: %s", error_str);
+    }
+  }
+
+  return result.raw();
+}
+
+RawInteger* Evaluator::UnaryIntegerEvaluate(const Object& value,
+                                            Token::Kind token_kind,
+                                            Representation representation,
+                                            Thread* thread) {
+  if (!value.IsInteger()) {
+    return Integer::null();
+  }
+  Zone* zone = thread->zone();
+  const Integer& value_int = Integer::Cast(value);
+  Integer& result = Integer::Handle(
+      zone, UnaryIntegerEvaluateRaw(value_int, token_kind, zone));
+
+  if (!result.IsNull()) {
+    if (!IsRepresentable(result, representation)) {
+      // If this operation is not truncating it would deoptimize on overflow.
+      // Check that we match this behavior and don't produce a value that is
+      // larger than something this operation can produce. We could have
+      // specialized instructions that use this value under this assumption.
+      return Integer::null();
+    }
+
+    const char* error_str = NULL;
+    result ^= result.CheckAndCanonicalize(thread, &error_str);
+    if (error_str != NULL) {
+      FATAL1("Failed to canonicalize: %s", error_str);
+    }
+  }
+
+  return result.raw();
+}
+
+double Evaluator::EvaluateDoubleOp(const double left,
+                                   const double right,
+                                   Token::Kind token_kind) {
+  switch (token_kind) {
+    case Token::kADD:
+      return left + right;
+    case Token::kSUB:
+      return left - right;
+    case Token::kMUL:
+      return left * right;
+    case Token::kDIV:
+      return left / right;
+    default:
+      UNREACHABLE();
+  }
+}
+
+bool Evaluator::ToIntegerConstant(Value* value, int64_t* result) {
+  if (!value->BindsToConstant()) {
+    UnboxInstr* unbox = value->definition()->AsUnbox();
+    if (unbox != nullptr) {
+      switch (unbox->representation()) {
+        case kUnboxedDouble:
+        case kUnboxedInt64:
+          return ToIntegerConstant(unbox->value(), result);
+        case kUnboxedUint32:
+          if (ToIntegerConstant(unbox->value(), result)) {
+            *result = Evaluator::TruncateTo(*result, kUnboxedUint32);
+            return true;
+          }
+          break;
+          // No need to handle Unbox<Int32>(Constant(C)) because it gets
+          // canonicalized to UnboxedConstant<Int32>(C).
+        case kUnboxedInt32:
+        default:
+          break;
+      }
+    }
+    return false;
+  }
+  const Object& constant = value->BoundConstant();
+  if (constant.IsDouble()) {
+    const Double& double_constant = Double::Cast(constant);
+    *result = Utils::SafeDoubleToInt<int64_t>(double_constant.value());
+    return (static_cast<double>(*result) == double_constant.value());
+  } else if (constant.IsSmi()) {
+    *result = Smi::Cast(constant).Value();
+    return true;
+  } else if (constant.IsMint()) {
+    *result = Mint::Cast(constant).value();
+    return true;
+  }
+  return false;
+}
+
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/evaluator.h b/runtime/vm/compiler/backend/evaluator.h
new file mode 100644
index 0000000..8c8e814
--- /dev/null
+++ b/runtime/vm/compiler/backend/evaluator.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
+#define RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
+
+#include "vm/allocation.h"
+#include "vm/compiler/backend/flow_graph.h"
+#include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/locations.h"
+
+namespace dart {
+
+// Namespace for static helper methods that evaluate constant expressions.
+class Evaluator : public AllStatic {
+ public:
+  // Truncates the given int64 value based on the representation.
+  static int64_t TruncateTo(int64_t v, Representation r);
+
+  // Evaluates a binary integer operation and returns a pointer to a
+  // canonicalized RawInteger.
+  static RawInteger* BinaryIntegerEvaluate(const Object& left,
+                                           const Object& right,
+                                           Token::Kind token_kind,
+                                           bool is_truncating,
+                                           Representation representation,
+                                           Thread* thread);
+
+  // Evaluates a unary integer operation and returns a pointer to a
+  // canonicalized RawInteger.
+  static RawInteger* UnaryIntegerEvaluate(const Object& value,
+                                          Token::Kind token_kind,
+                                          Representation representation,
+                                          Thread* thread);
+
+  // Evaluates a binary double operation and returns the result.
+  static double EvaluateDoubleOp(const double left,
+                                 const double right,
+                                 Token::Kind token_kind);
+
+  // Returns whether the value is an int64, and returns the int64 value
+  // through the result parameter.
+  static bool ToIntegerConstant(Value* value, int64_t* result);
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_BACKEND_EVALUATOR_H_
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 3cc78fa..0c83b55 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1216,28 +1216,6 @@
   // Attach environment to the block entry.
   AttachEnvironment(block_entry, env);
 
-#if defined(TARGET_ARCH_DBC)
-  // On DBC the exception/stacktrace variables are in special registers when
-  // entering the catch block.  The only usage of those special registers is
-  // within the catch block.  A possible lazy-deopt at the beginning of the
-  // catch does not need to move those around, since the registers will be
-  // up-to-date when arriving in the unoptimized code and unoptimized code will
-  // take care of moving them to appropriate slots.
-  if (CatchBlockEntryInstr* catch_entry = block_entry->AsCatchBlockEntry()) {
-    Environment* deopt_env = catch_entry->env();
-    const LocalVariable* raw_exception_var = catch_entry->raw_exception_var();
-    const LocalVariable* raw_stacktrace_var = catch_entry->raw_stacktrace_var();
-    if (raw_exception_var != nullptr) {
-      Value* value = deopt_env->ValueAt(EnvIndex(raw_exception_var));
-      value->BindToEnvironment(constant_null());
-    }
-    if (raw_stacktrace_var != nullptr) {
-      Value* value = deopt_env->ValueAt(EnvIndex(raw_stacktrace_var));
-      value->BindToEnvironment(constant_null());
-    }
-  }
-#endif  // defined(TARGET_ARCH_DBC)
-
   // 2. Process normal instructions.
   for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
     Instruction* current = it.Current();
@@ -1249,8 +1227,8 @@
 
     // 2a. Handle uses:
     // Update the expression stack renaming environment for each use by
-    // removing the renamed value.
-    // For each use of a LoadLocal, StoreLocal, MakeTemp, DropTemps or Constant:
+    // removing the renamed value. For each use of a LoadLocal, StoreLocal,
+    // MakeTemp, DropTemps or Constant (or any expression under OSR),
     // replace it with the renamed value.
     for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
       Value* v = current->InputAt(i);
@@ -1259,18 +1237,23 @@
       Definition* reaching_defn = env->RemoveLast();
       Definition* input_defn = v->definition();
       if (input_defn != reaching_defn) {
-        // Under OSR, constants can reside on the expression stack. Just
-        // generate the constant rather than going through a synthetic phi.
-        if (input_defn->IsConstant() && reaching_defn->IsPhi()) {
-          ASSERT(IsCompiledForOsr() && env->length() < osr_variable_count());
-          reaching_defn = GetConstant(input_defn->AsConstant()->value());
+        // Inspect the replacing definition before making the change.
+        if (IsCompiledForOsr()) {
+          // Under OSR, constants can reside on the expression stack. Just
+          // generate the constant rather than going through a synthetic phi.
+          if (input_defn->IsConstant() && reaching_defn->IsPhi()) {
+            ASSERT(env->length() < osr_variable_count());
+            reaching_defn = GetConstant(input_defn->AsConstant()->value());
+          }
+        } else {
+          // Note: constants can only be replaced with other constants.
+          ASSERT(input_defn->IsLoadLocal() || input_defn->IsStoreLocal() ||
+                 input_defn->IsDropTemps() || input_defn->IsMakeTemp() ||
+                 (input_defn->IsConstant() && reaching_defn->IsConstant()));
         }
-        // Note: constants can only be replaced with other constants.
-        ASSERT(input_defn->IsLoadLocal() || input_defn->IsStoreLocal() ||
-               input_defn->IsDropTemps() || input_defn->IsMakeTemp() ||
-               (input_defn->IsConstant() && reaching_defn->IsConstant()));
         // Assert we are not referencing nulls in the initial environment.
         ASSERT(reaching_defn->ssa_temp_index() != -1);
+        // Replace the definition.
         v->set_definition(reaching_defn);
         input_defn = reaching_defn;
       }
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index ecc7b50..60a737d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -520,8 +520,6 @@
                        line.ToCString());
 }
 
-#if !defined(TARGET_ARCH_DBC)
-
 static bool IsPusher(Instruction* instr) {
   if (auto def = instr->AsDefinition()) {
     return def->HasTemp();
@@ -538,14 +536,10 @@
   return false;
 }
 
-#endif
-
 bool FlowGraphCompiler::IsPeephole(Instruction* instr) const {
-#if !defined(TARGET_ARCH_DBC)
   if (FLAG_enable_peephole && !is_optimizing()) {
     return IsPusher(instr) && IsPopper(instr->next());
   }
-#endif
   return false;
 }
 
@@ -573,7 +567,7 @@
       continue;
     }
 
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#if defined(DEBUG)
     if (!is_optimizing()) {
       FrameStateClear();
     }
@@ -632,7 +626,7 @@
         EndCodeSourceRange(instr->token_pos());
       }
 
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#if defined(DEBUG)
       if (!is_optimizing()) {
         FrameStateUpdateWith(instr);
       }
@@ -640,7 +634,7 @@
       StatsEnd(instr);
     }
 
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#if defined(DEBUG)
     ASSERT(is_optimizing() || FrameStateIsSafeToCall());
 #endif
   }
@@ -860,15 +854,8 @@
 // spill_area_size but the second safepoint will truncate the bitmap and
 // append the live registers to it again. The bitmap produced by both calls
 // will be the same.
-#if !defined(TARGET_ARCH_DBC)
     ASSERT(bitmap->Length() <= (spill_area_size + saved_registers_size));
     bitmap->SetLength(spill_area_size);
-#else
-    ASSERT(slow_path_argument_count == 0);
-    if (bitmap->Length() <= (spill_area_size + saved_registers_size)) {
-      bitmap->SetLength(Utils::Maximum(bitmap->Length(), spill_area_size));
-    }
-#endif
 
     ASSERT(slow_path_argument_count == 0 || !using_shared_stub);
 
@@ -1038,23 +1025,6 @@
   return stub->entry_label();
 }
 
-#if defined(TARGET_ARCH_DBC)
-void FlowGraphCompiler::EmitDeopt(intptr_t deopt_id,
-                                  ICData::DeoptReasonId reason,
-                                  uint32_t flags) {
-  ASSERT(is_optimizing());
-  ASSERT(!intrinsic_mode());
-  // The pending deoptimization environment may be changed after this deopt is
-  // emitted, so we need to make a copy.
-  Environment* env_copy = pending_deoptimization_env_->DeepCopy(zone());
-  CompilerDeoptInfo* info =
-      new (zone()) CompilerDeoptInfo(deopt_id, reason, flags, env_copy);
-  deopt_infos_.Add(info);
-  assembler()->Deopt(0, /*is_eager =*/1);
-  info->set_pc_offset(assembler()->CodeSize());
-}
-#endif  // defined(TARGET_ARCH_DBC)
-
 void FlowGraphCompiler::FinalizeExceptionHandlers(const Code& code) {
   ASSERT(exception_handlers_list_ != NULL);
   const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
@@ -1238,7 +1208,7 @@
 
         // Only intrinsify getter if the field cannot contain a mutable double.
         // Reading from a mutable double box requires allocating a fresh double.
-        if (field.is_instance() &&
+        if (field.is_instance() && !field.needs_load_guard() &&
             (FLAG_precompiled_mode || !IsPotentialUnboxedField(field))) {
           SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
           GenerateGetterIntrinsic(compiler::target::Field::OffsetOf(field));
@@ -1268,7 +1238,7 @@
         }
         break;
       }
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
       case RawFunction::kMethodExtractor: {
         auto& extracted_method = Function::ZoneHandle(
             parsed_function().function().extracted_method_closure());
@@ -1285,7 +1255,7 @@
         SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics);
         return true;
       }
-#endif  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#endif  // !defined(TARGET_ARCH_IA32)
       default:
         break;
     }
@@ -1309,9 +1279,6 @@
   return complete;
 }
 
-// DBC is very different from other architectures in how it performs instance
-// and static calls because it does not use stubs.
-#if !defined(TARGET_ARCH_DBC)
 void FlowGraphCompiler::GenerateCallWithDeopt(TokenPosition token_pos,
                                               intptr_t deopt_id,
                                               const Code& stub,
@@ -1470,7 +1437,6 @@
   CheckClassIds(class_id_reg, args, is_instance_lbl, &unknown);
   assembler()->Bind(&unknown);
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 void FlowGraphCompiler::EmitComment(Instruction* instr) {
   if (!FLAG_support_il_printer || !FLAG_support_disassembler) {
@@ -1484,8 +1450,6 @@
 #endif
 }
 
-#if !defined(TARGET_ARCH_DBC)
-// TODO(vegorov) enable edge-counters on DBC if we consider them beneficial.
 bool FlowGraphCompiler::NeedsEdgeCounter(BlockEntryInstr* block) {
   // Only emit an edge counter if there is not goto at the end of the block,
   // except for the entry block.
@@ -1504,15 +1468,11 @@
   UNREACHABLE();
   return kNoRegister;
 }
-#endif
 
 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
   ASSERT(!is_optimizing());
   instr->InitializeLocationSummary(zone(), false);  // Not optimizing.
 
-// No need to allocate registers based on LocationSummary on DBC as in
-// unoptimized mode it's a stack based bytecode just like IR itself.
-#if !defined(TARGET_ARCH_DBC)
   LocationSummary* locs = instr->locs();
 
   bool blocked_registers[kNumberOfCpuRegisters];
@@ -1627,7 +1587,6 @@
     }
     locs->set_out(0, result_location);
   }
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 static uword RegMaskBit(Register reg) {
@@ -1744,7 +1703,6 @@
   compiler_->EndCodeSourceRange(TokenPosition::kParallelMove);
 }
 
-#if !defined(TARGET_ARCH_DBC)
 void ParallelMoveResolver::EmitMove(int index) {
   MoveOperands* const move = moves_[index];
   const Location dst = move->dest();
@@ -1766,7 +1724,6 @@
 #endif
   move->Eliminate();
 }
-#endif
 
 bool ParallelMoveResolver::IsScratchLocation(Location loc) {
   for (int i = 0; i < moves_.length(); ++i) {
@@ -2062,9 +2019,6 @@
   return true;
 }
 
-#if !defined(TARGET_ARCH_DBC)
-// DBC emits calls very differently from other architectures due to its
-// interpreted nature.
 void FlowGraphCompiler::EmitPolymorphicInstanceCall(
     const CallTargets& targets,
     const InstanceCallInstr& original_call,
@@ -2270,7 +2224,7 @@
 
   int bias = 0;
   for (intptr_t i = 0; i < cid_ranges.length(); ++i) {
-    const CidRange& range = cid_ranges[i];
+    const CidRangeValue& range = cid_ranges[i];
     RELEASE_ASSERT(!range.IsIllegalRange());
     const bool last_round = i == (cid_ranges.length() - 1);
 
@@ -2380,12 +2334,8 @@
 }
 
 #undef __
-#endif
 
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
-// TODO(vegorov) re-enable frame state tracking on DBC. It is
-// currently disabled because it relies on LocationSummaries and
-// we don't use them during unoptimized compilation on DBC.
+#if defined(DEBUG)
 void FlowGraphCompiler::FrameStateUpdateWith(Instruction* instr) {
   ASSERT(!is_optimizing());
 
@@ -2450,9 +2400,8 @@
   ASSERT(!is_optimizing());
   frame_state_.TruncateTo(0);
 }
-#endif  // defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#endif  // defined(DEBUG)
 
-#if !defined(TARGET_ARCH_DBC)
 #define __ compiler->assembler()->
 
 void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -2506,8 +2455,6 @@
 }
 
 #undef __
-#endif  //  !defined(TARGET_ARCH_DBC)
-
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 884bef3..86374da 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -167,9 +167,6 @@
         deopt_id_(deopt_id),
         reason_(reason),
         flags_(flags),
-#if defined(TARGET_ARCH_DBC)
-        lazy_deopt_with_result_(false),
-#endif
         deopt_env_(deopt_env) {
     ASSERT(deopt_env != NULL);
   }
@@ -190,18 +187,6 @@
   uint32_t flags() const { return flags_; }
   const Environment* deopt_env() const { return deopt_env_; }
 
-#if defined(TARGET_ARCH_DBC)
-  // On DBC calls return results on the stack but not all calls have a result.
-  // This needs to be taken into account when constructing lazy deoptimization
-  // environment.
-  // For calls with results we add a deopt instruction that would copy top
-  // of the stack from optimized frame to unoptimized frame effectively
-  // preserving the result of the call.
-  // For calls with no results we don't emit such instruction - because there
-  // is no result pushed by the return sequence.
-  void mark_lazy_deopt_with_result() { lazy_deopt_with_result_ = true; }
-#endif
-
  private:
   void EmitMaterializations(Environment* env, DeoptInfoBuilder* builder);
 
@@ -212,9 +197,6 @@
   const intptr_t deopt_id_;
   const ICData::DeoptReasonId reason_;
   const uint32_t flags_;
-#if defined(TARGET_ARCH_DBC)
-  bool lazy_deopt_with_result_;
-#endif
   Environment* deopt_env_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerDeoptInfo);
@@ -522,9 +504,6 @@
       const Register scratch_reg,
       compiler::Label* done);
 
-// DBC emits calls very differently from all other architectures due to its
-// interpreted nature.
-#if !defined(TARGET_ARCH_DBC)
   void GenerateRuntimeCall(TokenPosition token_pos,
                            intptr_t deopt_id,
                            const RuntimeEntry& entry,
@@ -683,7 +662,7 @@
   bool NeedsEdgeCounter(BlockEntryInstr* block);
 
   void EmitEdgeCounter(intptr_t edge_id);
-#endif  // !defined(TARGET_ARCH_DBC)
+
   void RecordCatchEntryMoves(Environment* env = NULL,
                              intptr_t try_index = kInvalidTryIndex);
 
@@ -754,15 +733,6 @@
                                 ICData::DeoptReasonId reason,
                                 uint32_t flags = 0);
 
-#if defined(TARGET_ARCH_DBC)
-  void EmitDeopt(intptr_t deopt_id,
-                 ICData::DeoptReasonId reason,
-                 uint32_t flags = 0);
-
-  // If the cid does not fit in 16 bits, then this will cause a bailout.
-  uint16_t ToEmbeddableCid(intptr_t cid, Instruction* instruction);
-#endif  // defined(TARGET_ARCH_DBC)
-
   CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id);
   CompilerDeoptInfo* AddSlowPathDeoptInfo(intptr_t deopt_id, Environment* env);
 
@@ -853,26 +823,13 @@
                               Function* fn_return,
                               bool* class_is_abstract_return = NULL);
 
-#if defined(TARGET_ARCH_DBC)
-  enum CallResult {
-    kHasResult,
-    kNoResult,
-  };
-  void RecordAfterCallHelper(TokenPosition token_pos,
-                             intptr_t deopt_id,
-                             intptr_t argument_count,
-                             CallResult result,
-                             LocationSummary* locs);
-  void RecordAfterCall(Instruction* instr, CallResult result);
-#endif
-
   // Returns new class-id bias.
   //
   // TODO(kustermann): We should move this code out of the [FlowGraphCompiler]!
   static int EmitTestAndCallCheckCid(compiler::Assembler* assembler,
                                      compiler::Label* label,
                                      Register class_id_reg,
-                                     const CidRange& range,
+                                     const CidRangeValue& range,
                                      int bias,
                                      bool jump_on_miss = true);
 
@@ -940,9 +897,6 @@
 
   void EmitTestAndCallLoadCid(Register class_id_reg);
 
-// DBC handles type tests differently from all other architectures due
-// to its interpreted nature.
-#if !defined(TARGET_ARCH_DBC)
   // Type checking helper methods.
   void CheckClassIds(Register class_id_reg,
                      const GrowableArray<intptr_t>& class_ids,
@@ -1008,8 +962,6 @@
   void GenerateMethodExtractorIntrinsic(const Function& extracted_method,
                                         intptr_t type_arguments_field_offset);
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
   void GenerateGetterIntrinsic(intptr_t offset);
   void GenerateSetterIntrinsic(intptr_t offset);
 
@@ -1041,10 +993,7 @@
     return compressed_stackmaps_builder_;
   }
 
-// TODO(vegorov) re-enable frame state tracking on DBC. It is
-// currently disabled because it relies on LocationSummaries and
-// we don't use them during unoptimized compilation on DBC.
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#if defined(DEBUG)
   void FrameStateUpdateWith(Instruction* instr);
   void FrameStatePush(Definition* defn);
   void FrameStatePop(intptr_t count);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 8192b74..7143db9 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -952,7 +952,9 @@
 
   VisitBlocks();
 
+#if defined(DEBUG)
   __ bkpt(0);
+#endif
 
   if (!skip_body_compilation()) {
     ASSERT(assembler()->constant_pool_allowed());
@@ -1330,7 +1332,7 @@
 int FlowGraphCompiler::EmitTestAndCallCheckCid(compiler::Assembler* assembler,
                                                compiler::Label* label,
                                                Register class_id_reg,
-                                               const CidRange& range,
+                                               const CidRangeValue& range,
                                                int bias,
                                                bool jump_on_miss) {
   intptr_t cid_start = range.cid_start;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 8c9f45d..980cc1e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -920,7 +920,9 @@
 
   VisitBlocks();
 
+#if defined(DEBUG)
   __ brk(0);
+#endif
 
   if (!skip_body_compilation()) {
     ASSERT(assembler()->constant_pool_allowed());
@@ -1297,7 +1299,7 @@
 int FlowGraphCompiler::EmitTestAndCallCheckCid(compiler::Assembler* assembler,
                                                compiler::Label* label,
                                                Register class_id_reg,
-                                               const CidRange& range,
+                                               const CidRangeValue& range,
                                                int bias,
                                                bool jump_on_miss) {
   const intptr_t cid_start = range.cid_start;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
deleted file mode 100644
index fe42375..0000000
--- a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
+++ /dev/null
@@ -1,483 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/backend/flow_graph_compiler.h"
-
-#include "vm/compiler/backend/il_printer.h"
-#include "vm/compiler/backend/locations.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/deopt_instructions.h"
-#include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/parser.h"
-#include "vm/simulator.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
-DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
-DEFINE_FLAG(bool, unbox_doubles, true, "Optimize double arithmetic.");
-DECLARE_FLAG(bool, enable_simd_inline);
-DECLARE_FLAG(charp, optimization_filter);
-
-void FlowGraphCompiler::ArchSpecificInitialization() {}
-
-FlowGraphCompiler::~FlowGraphCompiler() {
-  // BlockInfos are zone-allocated, so their destructors are not called.
-  // Verify the labels explicitly here.
-  for (int i = 0; i < block_info_.length(); ++i) {
-    ASSERT(!block_info_[i]->jump_label()->IsLinked());
-  }
-}
-
-bool FlowGraphCompiler::SupportsUnboxedDoubles() {
-#if defined(ARCH_IS_64_BIT)
-  return true;
-#else
-  // We use 64-bit wide stack slots to unbox doubles.
-  return false;
-#endif
-}
-
-bool FlowGraphCompiler::SupportsUnboxedInt64() {
-  return false;
-}
-
-bool FlowGraphCompiler::SupportsUnboxedSimd128() {
-  return false;
-}
-
-bool FlowGraphCompiler::SupportsHardwareDivision() {
-  return true;
-}
-
-bool FlowGraphCompiler::CanConvertInt64ToDouble() {
-  return false;
-}
-
-void FlowGraphCompiler::EnterIntrinsicMode() {
-  ASSERT(!intrinsic_mode());
-  intrinsic_mode_ = true;
-}
-
-void FlowGraphCompiler::ExitIntrinsicMode() {
-  ASSERT(intrinsic_mode());
-  intrinsic_mode_ = false;
-}
-
-RawTypedData* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
-                                                 DeoptInfoBuilder* builder,
-                                                 const Array& deopt_table) {
-  if (deopt_env_ == NULL) {
-    ++builder->current_info_number_;
-    return TypedData::null();
-  }
-
-  intptr_t stack_height = compiler->StackSize();
-  AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
-
-  intptr_t slot_ix = 0;
-  Environment* current = deopt_env_;
-
-  // Emit all kMaterializeObject instructions describing objects to be
-  // materialized on the deoptimization as a prefix to the deoptimization info.
-  EmitMaterializations(deopt_env_, builder);
-
-  // The real frame starts here.
-  builder->MarkFrameStart();
-
-  Zone* zone = compiler->zone();
-
-  builder->AddCallerFp(slot_ix++);
-  builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
-  builder->AddPcMarker(Function::ZoneHandle(zone), slot_ix++);
-  builder->AddConstant(Function::ZoneHandle(zone), slot_ix++);
-
-  // Emit all values that are needed for materialization as a part of the
-  // expression stack for the bottom-most frame. This guarantees that GC
-  // will be able to find them during materialization.
-  slot_ix = builder->EmitMaterializationArguments(slot_ix);
-
-  if (lazy_deopt_with_result_) {
-    ASSERT(reason() == ICData::kDeoptAtCall);
-    builder->AddCopy(
-        NULL,
-        Location::StackSlot(
-            compiler::target::frame_layout.FrameSlotForVariableIndex(
-                -stack_height),
-            FPREG),
-        slot_ix++);
-  }
-
-  // For the innermost environment, set outgoing arguments and the locals.
-  for (intptr_t i = current->Length() - 1;
-       i >= current->fixed_parameter_count(); i--) {
-    builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
-  }
-
-  builder->AddCallerFp(slot_ix++);
-
-  Environment* previous = current;
-  current = current->outer();
-  while (current != NULL) {
-    // For any outer environment the deopt id is that of the call instruction
-    // which is recorded in the outer environment.
-    builder->AddReturnAddress(current->function(),
-                              DeoptId::ToDeoptAfter(current->deopt_id()),
-                              slot_ix++);
-
-    builder->AddPcMarker(previous->function(), slot_ix++);
-    builder->AddConstant(previous->function(), slot_ix++);
-
-    // The values of outgoing arguments can be changed from the inlined call so
-    // we must read them from the previous environment.
-    for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-      builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i),
-                       slot_ix++);
-    }
-
-    // Set the locals, note that outgoing arguments are not in the environment.
-    for (intptr_t i = current->Length() - 1;
-         i >= current->fixed_parameter_count(); i--) {
-      builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
-    }
-
-    builder->AddCallerFp(slot_ix++);
-
-    // Iterate on the outer environment.
-    previous = current;
-    current = current->outer();
-  }
-  // The previous pointer is now the outermost environment.
-  ASSERT(previous != NULL);
-
-  // For the outermost environment, set caller PC.
-  builder->AddCallerPc(slot_ix++);
-
-  builder->AddPcMarker(previous->function(), slot_ix++);
-  builder->AddConstant(previous->function(), slot_ix++);
-
-  // For the outermost environment, set the incoming arguments.
-  for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
-    builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
-  }
-
-  return builder->CreateDeoptInfo(deopt_table);
-}
-
-void FlowGraphCompiler::RecordAfterCallHelper(TokenPosition token_pos,
-                                              intptr_t deopt_id,
-                                              intptr_t argument_count,
-                                              CallResult result,
-                                              LocationSummary* locs) {
-  RecordSafepoint(locs);
-  // Marks either the continuation point in unoptimized code or the
-  // deoptimization point in optimized code, after call.
-  const intptr_t deopt_id_after = DeoptId::ToDeoptAfter(deopt_id);
-  if (is_optimizing()) {
-    // Return/ReturnTOS instruction drops incoming arguments so
-    // we have to drop outgoing arguments from the innermost environment.
-    // On all other architectures caller drops outgoing arguments itself
-    // hence the difference.
-    pending_deoptimization_env_->DropArguments(argument_count);
-    CompilerDeoptInfo* info = AddDeoptIndexAtCall(deopt_id_after);
-    if (result == kHasResult) {
-      info->mark_lazy_deopt_with_result();
-    }
-    // This descriptor is needed for exception handling in optimized code.
-    AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id_after, token_pos);
-  } else {
-    // Add deoptimization continuation point after the call and before the
-    // arguments are removed.
-    AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos);
-  }
-}
-
-void FlowGraphCompiler::RecordAfterCall(Instruction* instr, CallResult result) {
-  RecordAfterCallHelper(instr->token_pos(), instr->deopt_id(),
-                        instr->ArgumentCount(), result, instr->locs());
-}
-
-void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
-                                             intptr_t stub_ix) {
-  UNREACHABLE();
-}
-
-#define __ assembler()->
-
-void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
-                                                 intptr_t deopt_id,
-                                                 const AbstractType& dst_type,
-                                                 const String& dst_name,
-                                                 LocationSummary* locs) {
-  SubtypeTestCache& test_cache = SubtypeTestCache::Handle();
-  if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) {
-    test_cache = SubtypeTestCache::New();
-  } else if (!dst_type.IsInstantiated() &&
-             (dst_type.IsTypeParameter() || dst_type.IsType())) {
-    test_cache = SubtypeTestCache::New();
-  }
-
-  if (is_optimizing()) {
-    __ Push(locs->in(0).reg());  // Instance.
-    __ Push(locs->in(1).reg());  // Instantiator type arguments.
-    __ Push(locs->in(2).reg());  // Function type arguments.
-  }
-  __ PushConstant(dst_type);
-  __ PushConstant(dst_name);
-
-  bool may_be_smi = false;
-  if (!dst_type.IsVoidType() && dst_type.IsInstantiated()) {
-    const Class& type_class = Class::Handle(zone(), dst_type.type_class());
-    if (type_class.NumTypeArguments() == 0) {
-      const Class& smi_class = Class::Handle(zone(), Smi::Class());
-      may_be_smi = Class::IsSubtypeOf(smi_class, TypeArguments::Handle(zone()),
-                                      type_class, TypeArguments::Handle(zone()),
-                                      Heap::kOld);
-    }
-  }
-  __ AssertAssignable(may_be_smi ? 1 : 0, __ AddConstant(test_cache));
-
-  if (is_optimizing()) {
-    // Register allocator does not think that our first input (also used as
-    // output) needs to be kept alive across the call because that is how code
-    // is written on other platforms (where registers are always spilled across
-    // the call): inputs are consumed by operation and output is produced so
-    // neither are alive at the safepoint.
-    // We have to mark the slot alive manually to ensure that GC
-    // visits it.
-    locs->SetStackBit(locs->out(0).reg());
-  }
-  AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos);
-  const intptr_t kArgCount = 0;
-  RecordAfterCallHelper(token_pos, deopt_id, kArgCount,
-                        FlowGraphCompiler::kHasResult, locs);
-  if (is_optimizing()) {
-    // Assert assignable keeps the instance on the stack as the result,
-    // all other arguments are popped.
-    ASSERT(locs->out(0).reg() == locs->in(0).reg());
-    __ Drop1();
-  }
-}
-
-void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
-  if (!is_optimizing()) {
-    Definition* defn = instr->AsDefinition();
-    if ((defn != NULL) && (defn->tag() != Instruction::kPushArgument) &&
-        (defn->tag() != Instruction::kStoreIndexed) &&
-        (defn->tag() != Instruction::kStoreStaticField) &&
-        (defn->tag() != Instruction::kStoreLocal) &&
-        (defn->tag() != Instruction::kStoreInstanceField) &&
-        (defn->tag() != Instruction::kDropTemps) && !defn->HasTemp()) {
-      __ Drop1();
-    }
-  }
-}
-
-void FlowGraphCompiler::GenerateGetterIntrinsic(intptr_t offset) {
-  __ Move(0, -(1 + compiler::target::frame_layout.param_end_from_fp));
-  ASSERT(offset % kWordSize == 0);
-  if (Utils::IsInt(8, offset / kWordSize)) {
-    __ LoadField(0, 0, offset / kWordSize);
-  } else {
-    __ LoadFieldExt(0, 0);
-    __ Nop(offset / kWordSize);
-  }
-  __ Return(0);
-}
-
-void FlowGraphCompiler::GenerateSetterIntrinsic(intptr_t offset) {
-  __ Move(0, -(2 + compiler::target::frame_layout.param_end_from_fp));
-  __ Move(1, -(1 + compiler::target::frame_layout.param_end_from_fp));
-  ASSERT(offset % kWordSize == 0);
-  if (Utils::IsInt(8, offset / kWordSize)) {
-    __ StoreField(0, offset / kWordSize, 1);
-  } else {
-    __ StoreFieldExt(0, 1);
-    __ Nop(offset / kWordSize);
-  }
-  __ LoadConstant(0, Object::Handle());
-  __ Return(0);
-}
-
-void FlowGraphCompiler::EmitFrameEntry() {
-  const Function& function = parsed_function().function();
-  const intptr_t num_fixed_params = function.num_fixed_parameters();
-  const int num_locals = parsed_function().num_stack_locals();
-
-  if (CanOptimizeFunction() && function.IsOptimizable() &&
-      (!is_optimizing() || may_reoptimize())) {
-    __ HotCheck(!is_optimizing(), GetOptimizationThreshold());
-  }
-
-  if (is_optimizing()) {
-    __ EntryOptimized(num_fixed_params,
-                      flow_graph_.graph_entry()->spill_slot_count());
-  } else {
-    __ Entry(num_locals);
-  }
-
-  if (!is_optimizing()) {
-    if (parsed_function().has_arg_desc_var()) {
-      // TODO(kustermann): If dbc simulator put the args_desc_ into the
-      // _special_regs, we could replace these 3 with the MoveSpecial bytecode.
-      const intptr_t slot_index =
-          compiler::target::frame_layout.FrameSlotForVariable(
-              parsed_function().arg_desc_var());
-      __ LoadArgDescriptor();
-      __ StoreLocal(LocalVarIndex(0, slot_index));
-      __ Drop(1);
-    }
-  }
-}
-
-void FlowGraphCompiler::EmitPrologue() {
-  EmitFrameEntry();
-}
-
-void FlowGraphCompiler::CompileGraph() {
-  InitCompiler();
-  VisitBlocks();
-}
-
-uint16_t FlowGraphCompiler::ToEmbeddableCid(intptr_t cid,
-                                            Instruction* instruction) {
-  if (!Utils::IsUint(16, cid)) {
-    instruction->Unsupported(this);
-    UNREACHABLE();
-  }
-  return static_cast<uint16_t>(cid);
-}
-
-#undef __
-#define __ compiler_->assembler()->
-
-void ParallelMoveResolver::EmitMove(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
-  if (source.IsStackSlot() && destination.IsRegister()) {
-    // Only allow access to the arguments (which have in the non-inverted stack
-    // positive indices).
-    ASSERT(source.base_reg() == FPREG);
-    ASSERT(source.stack_index() >
-           compiler::target::frame_layout.param_end_from_fp);
-    __ Move(destination.reg(), -source.stack_index());
-  } else if (source.IsRegister() && destination.IsRegister()) {
-    __ Move(destination.reg(), source.reg());
-  } else if (source.IsArgsDescRegister()) {
-    ASSERT(destination.IsRegister());
-    __ LoadArgDescriptorOpt(destination.reg());
-  } else if (source.IsExceptionRegister()) {
-    ASSERT(destination.IsRegister());
-    __ MoveSpecial(destination.reg(), Simulator::kExceptionSpecialIndex);
-  } else if (source.IsStackTraceRegister()) {
-    ASSERT(destination.IsRegister());
-    __ MoveSpecial(destination.reg(), Simulator::kStackTraceSpecialIndex);
-  } else if (source.IsConstant() && destination.IsRegister()) {
-    if (source.constant_instruction()->representation() == kUnboxedDouble) {
-      const Register result = destination.reg();
-      const Object& constant = source.constant();
-      if (Utils::DoublesBitEqual(Double::Cast(constant).value(), 0.0)) {
-        __ BitXor(result, result, result);
-      } else {
-        __ LoadConstant(result, constant);
-        __ UnboxDouble(result, result);
-      }
-    } else {
-      __ LoadConstant(destination.reg(), source.constant());
-    }
-  } else {
-    compiler_->Bailout("Unsupported move");
-    UNREACHABLE();
-  }
-
-  move->Eliminate();
-}
-
-void ParallelMoveResolver::EmitSwap(int index) {
-  MoveOperands* move = moves_[index];
-  const Location source = move->src();
-  const Location destination = move->dest();
-  ASSERT(source.IsRegister() && destination.IsRegister());
-  __ Swap(destination.reg(), source.reg());
-
-  // The swap of source and destination has executed a move from source to
-  // destination.
-  move->Eliminate();
-
-  // Any unperformed (including pending) move with a source of either
-  // this move's source or destination needs to have their source
-  // changed to reflect the state of affairs after the swap.
-  for (int i = 0; i < moves_.length(); ++i) {
-    const MoveOperands& other_move = *moves_[i];
-    if (other_move.Blocks(source)) {
-      moves_[i]->set_src(destination);
-    } else if (other_move.Blocks(destination)) {
-      moves_[i]->set_src(source);
-    }
-  }
-}
-
-void ParallelMoveResolver::MoveMemoryToMemory(const compiler::Address& dst,
-                                              const compiler::Address& src) {
-  UNREACHABLE();
-}
-
-// Do not call or implement this function. Instead, use the form below that
-// uses an offset from the frame pointer instead of an Address.
-void ParallelMoveResolver::Exchange(Register reg,
-                                    const compiler::Address& mem) {
-  UNREACHABLE();
-}
-
-// Do not call or implement this function. Instead, use the form below that
-// uses offsets from the frame pointer instead of Addresses.
-void ParallelMoveResolver::Exchange(const compiler::Address& mem1,
-                                    const compiler::Address& mem2) {
-  UNREACHABLE();
-}
-
-void ParallelMoveResolver::Exchange(Register reg,
-                                    Register base_reg,
-                                    intptr_t stack_offset) {
-  UNIMPLEMENTED();
-}
-
-void ParallelMoveResolver::Exchange(Register base_reg1,
-                                    intptr_t stack_offset1,
-                                    Register base_reg2,
-                                    intptr_t stack_offset2) {
-  UNIMPLEMENTED();
-}
-
-void ParallelMoveResolver::SpillScratch(Register reg) {
-  UNIMPLEMENTED();
-}
-
-void ParallelMoveResolver::RestoreScratch(Register reg) {
-  UNIMPLEMENTED();
-}
-
-void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
-  UNIMPLEMENTED();
-}
-
-void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
-  UNIMPLEMENTED();
-}
-
-#undef __
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 5b1a9c3..b73de08 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -839,7 +839,9 @@
   VisitBlocks();
 
   if (!skip_body_compilation()) {
+#if defined(DEBUG)
     __ int3();
+#endif
     GenerateDeferredCode();
   }
 }
@@ -1185,7 +1187,7 @@
 int FlowGraphCompiler::EmitTestAndCallCheckCid(compiler::Assembler* assembler,
                                                compiler::Label* label,
                                                Register class_id_reg,
-                                               const CidRange& range,
+                                               const CidRangeValue& range,
                                                int bias,
                                                bool jump_on_miss) {
   intptr_t cid_start = range.cid_start;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index bd3e251..59af52e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -935,7 +935,9 @@
   ASSERT(!block_order().is_empty());
   VisitBlocks();
 
+#if defined(DEBUG)
   __ int3();
+#endif
 
   if (!skip_body_compilation()) {
     ASSERT(assembler()->constant_pool_allowed());
@@ -1302,7 +1304,7 @@
 int FlowGraphCompiler::EmitTestAndCallCheckCid(compiler::Assembler* assembler,
                                                compiler::Label* label,
                                                Register class_id_reg,
-                                               const CidRange& range,
+                                               const CidRangeValue& range,
                                                int bias,
                                                bool jump_on_miss) {
   // Note of WARNING: Due to smaller instruction encoding we use the 32-bit
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 6990780..2f00b22 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -10,6 +10,7 @@
 #include "vm/bootstrap.h"
 #include "vm/compiler/backend/code_statistics.h"
 #include "vm/compiler/backend/constant_propagator.h"
+#include "vm/compiler/backend/evaluator.h"
 #include "vm/compiler/backend/flow_graph_compiler.h"
 #include "vm/compiler/backend/linearscan.h"
 #include "vm/compiler/backend/locations.h"
@@ -46,7 +47,7 @@
             "Generate special IC stubs for two args Smi operations");
 DEFINE_FLAG(bool,
             unbox_numeric_fields,
-            !USING_DBC,
+            true,
             "Support unboxed double and float32x4 fields.");
 
 class SubclassFinder {
@@ -203,6 +204,7 @@
     if (cid == kTypeArgumentsCid) continue;
     if (cid == kVoidCid) continue;
     if (cid == kDynamicCid) continue;
+    if (cid == kNeverCid) continue;
     if (cid == kNullCid && !exclude_null) continue;
     cls = table->At(cid);
     if (!include_abstract && cls.is_abstract()) continue;
@@ -466,7 +468,7 @@
                               /*include_abstract=*/false,
                               /*exclude_null=*/true);
     if (ranges.length() == 1) {
-      const CidRange& range = ranges[0];
+      const CidRangeValue& range = ranges[0];
       if (!range.IsIllegalRange()) {
         *lower_limit = range.cid_start;
         *upper_limit = range.cid_end;
@@ -903,6 +905,16 @@
   return kTagged;
 }
 
+AllocateUninitializedContextInstr::AllocateUninitializedContextInstr(
+    TokenPosition token_pos,
+    intptr_t num_context_variables)
+    : token_pos_(token_pos),
+      num_context_variables_(num_context_variables),
+      identity_(AliasIdentity::Unknown()) {
+  // This instruction is not used in AOT for code size reasons.
+  ASSERT(!FLAG_precompiled_mode);
+}
+
 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
   return FLAG_unbox_numeric_fields && slot().IsDartField() &&
          FlowGraphCompiler::IsUnboxedField(slot().field());
@@ -935,11 +947,12 @@
 Instruction* StoreInstanceFieldInstr::Canonicalize(FlowGraph* flow_graph) {
   // Dart objects are allocated null-initialized, which means we can eliminate
   // all initializing stores which store null value.
-  // TODO(dartbug.com/38454) Context objects can be allocated uninitialized
-  // as a performance optimization (all initializing stores are inlined into
-  // the caller, which allocates the context). Investigate if this can be
-  // changed to align with normal Dart objects for code size reasons.
-  if (is_initialization_ && slot().IsDartField() &&
+  // Context objects can be allocated uninitialized as a performance
+  // optimization in JIT mode - however in AOT mode we always allocate them
+  // null initialized.
+  if (is_initialization_ &&
+      (!slot().IsContextSlot() ||
+       !instance()->definition()->IsAllocateUninitializedContext()) &&
       value()->BindsToConstantNull()) {
     return nullptr;
   }
@@ -1035,6 +1048,10 @@
   return &this->slot_ == &other_load->slot_;
 }
 
+Instruction* InitInstanceFieldInstr::Canonicalize(FlowGraph* flow_graph) {
+  return this;
+}
+
 Instruction* InitStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
   const bool is_initialized =
       (field_.StaticValue() != Object::sentinel().raw()) &&
@@ -2021,12 +2038,8 @@
       return RangeUtils::CanBeZero(right_range());
 
     case Token::kTRUNCDIV:
-#if defined(TARGET_ARCH_DBC)
-      return true;
-#else
       return RangeUtils::CanBeZero(right_range()) ||
              RangeUtils::Overlaps(right_range(), -1, -1);
-#endif
 
     default:
       return can_overflow();
@@ -2066,73 +2079,11 @@
                               (64 - RepresentationBits(r)));
 }
 
-static int64_t TruncateTo(int64_t v, Representation r) {
-  switch (r) {
-    case kTagged: {
-      // Smi occupies word minus kSmiTagShift bits.
-      const intptr_t kTruncateBits =
-          (kBitsPerInt64 - kBitsPerWord) + kSmiTagShift;
-      return Utils::ShiftLeftWithTruncation(v, kTruncateBits) >> kTruncateBits;
-    }
-    case kUnboxedInt32:
-      return Utils::ShiftLeftWithTruncation(v, kBitsPerInt32) >> kBitsPerInt32;
-    case kUnboxedUint32:
-      return v & kMaxUint32;
-    case kUnboxedInt64:
-      return v;
-    default:
-      UNREACHABLE();
-      return 0;
-  }
-}
-
-static bool ToIntegerConstant(Value* value, int64_t* result) {
-  if (!value->BindsToConstant()) {
-    UnboxInstr* unbox = value->definition()->AsUnbox();
-    if (unbox != NULL) {
-      switch (unbox->representation()) {
-        case kUnboxedDouble:
-        case kUnboxedInt64:
-          return ToIntegerConstant(unbox->value(), result);
-
-        case kUnboxedUint32:
-          if (ToIntegerConstant(unbox->value(), result)) {
-            *result = TruncateTo(*result, kUnboxedUint32);
-            return true;
-          }
-          break;
-
-        // No need to handle Unbox<Int32>(Constant(C)) because it gets
-        // canonicalized to UnboxedConstant<Int32>(C).
-        case kUnboxedInt32:
-        default:
-          break;
-      }
-    }
-    return false;
-  }
-
-  const Object& constant = value->BoundConstant();
-  if (constant.IsDouble()) {
-    const Double& double_constant = Double::Cast(constant);
-    *result = Utils::SafeDoubleToInt<int64_t>(double_constant.value());
-    return (static_cast<double>(*result) == double_constant.value());
-  } else if (constant.IsSmi()) {
-    *result = Smi::Cast(constant).Value();
-    return true;
-  } else if (constant.IsMint()) {
-    *result = Mint::Cast(constant).value();
-    return true;
-  }
-
-  return false;
-}
-
 static Definition* CanonicalizeCommutativeDoubleArithmetic(Token::Kind op,
                                                            Value* left,
                                                            Value* right) {
   int64_t left_value;
-  if (!ToIntegerConstant(left, &left_value)) {
+  if (!Evaluator::ToIntegerConstant(left, &left_value)) {
     return NULL;
   }
 
@@ -2330,142 +2281,6 @@
   return op;
 }
 
-static bool IsRepresentable(const Integer& value, Representation rep) {
-  switch (rep) {
-    case kTagged:  // Smi case.
-      return value.IsSmi();
-
-    case kUnboxedInt32:
-      if (value.IsSmi() || value.IsMint()) {
-        return Utils::IsInt(32, value.AsInt64Value());
-      }
-      return false;
-
-    case kUnboxedInt64:
-      return value.IsSmi() || value.IsMint();
-
-    case kUnboxedUint32:
-      if (value.IsSmi() || value.IsMint()) {
-        return Utils::IsUint(32, value.AsInt64Value());
-      }
-      return false;
-
-    default:
-      UNREACHABLE();
-  }
-
-  return false;
-}
-
-RawInteger* UnaryIntegerOpInstr::Evaluate(const Integer& value) const {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Integer& result = Integer::Handle(zone);
-
-  switch (op_kind()) {
-    case Token::kNEGATE:
-      result = value.ArithmeticOp(Token::kMUL, Smi::Handle(zone, Smi::New(-1)),
-                                  Heap::kOld);
-      break;
-
-    case Token::kBIT_NOT:
-      if (value.IsSmi()) {
-        result = Integer::New(~Smi::Cast(value).Value(), Heap::kOld);
-      } else if (value.IsMint()) {
-        result = Integer::New(~Mint::Cast(value).value(), Heap::kOld);
-      }
-      break;
-
-    default:
-      UNREACHABLE();
-  }
-
-  if (!result.IsNull()) {
-    if (!IsRepresentable(result, representation())) {
-      // If this operation is not truncating it would deoptimize on overflow.
-      // Check that we match this behavior and don't produce a value that is
-      // larger than something this operation can produce. We could have
-      // specialized instructions that use this value under this assumption.
-      return Integer::null();
-    }
-
-    const char* error_str = NULL;
-    result ^= result.CheckAndCanonicalize(thread, &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
-  }
-
-  return result.raw();
-}
-
-RawInteger* BinaryIntegerOpInstr::Evaluate(const Integer& left,
-                                           const Integer& right) const {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Integer& result = Integer::Handle(zone);
-
-  switch (op_kind()) {
-    case Token::kTRUNCDIV:
-      FALL_THROUGH;
-    case Token::kMOD:
-      // Check right value for zero.
-      if (right.AsInt64Value() == 0) {
-        break;  // Will throw.
-      }
-      FALL_THROUGH;
-    case Token::kADD:
-      FALL_THROUGH;
-    case Token::kSUB:
-      FALL_THROUGH;
-    case Token::kMUL: {
-      result = left.ArithmeticOp(op_kind(), right, Heap::kOld);
-      break;
-    }
-    case Token::kSHL:
-      FALL_THROUGH;
-    case Token::kSHR:
-      if (right.AsInt64Value() >= 0) {
-        result = left.ShiftOp(op_kind(), right, Heap::kOld);
-      }
-      break;
-    case Token::kBIT_AND:
-      FALL_THROUGH;
-    case Token::kBIT_OR:
-      FALL_THROUGH;
-    case Token::kBIT_XOR: {
-      result = left.BitOp(op_kind(), right, Heap::kOld);
-      break;
-    }
-    case Token::kDIV:
-      break;
-    default:
-      UNREACHABLE();
-  }
-
-  if (!result.IsNull()) {
-    if (is_truncating()) {
-      const int64_t truncated =
-          TruncateTo(result.AsTruncatedInt64Value(), representation());
-      result = Integer::New(truncated, Heap::kOld);
-      ASSERT(IsRepresentable(result, representation()));
-    } else if (!IsRepresentable(result, representation())) {
-      // If this operation is not truncating it would deoptimize on overflow.
-      // Check that we match this behavior and don't produce a value that is
-      // larger than something this operation can produce. We could have
-      // specialized instructions that use this value under this assumption.
-      return Integer::null();
-    }
-    const char* error_str = NULL;
-    result ^= result.CheckAndCanonicalize(thread, &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
-  }
-
-  return result.raw();
-}
-
 Definition* BinaryIntegerOpInstr::CreateConstantResult(FlowGraph* flow_graph,
                                                        const Integer& result) {
   Definition* result_defn = flow_graph->GetConstant(result);
@@ -2556,11 +2371,12 @@
   // If both operands are constants evaluate this expression. Might
   // occur due to load forwarding after constant propagation pass
   // have already been run.
-  if (left()->BindsToConstant() && left()->BoundConstant().IsInteger() &&
-      right()->BindsToConstant() && right()->BoundConstant().IsInteger()) {
-    const Integer& result =
-        Integer::Handle(Evaluate(Integer::Cast(left()->BoundConstant()),
-                                 Integer::Cast(right()->BoundConstant())));
+
+  if (left()->BindsToConstant() && right()->BindsToConstant()) {
+    const Integer& result = Integer::Handle(Evaluator::BinaryIntegerEvaluate(
+        left()->BoundConstant(), right()->BoundConstant(), op_kind(),
+        is_truncating(), representation(), Thread::Current()));
+
     if (!result.IsNull()) {
       return CreateConstantResult(flow_graph, result);
     }
@@ -2575,7 +2391,7 @@
   }
 
   int64_t rhs;
-  if (!ToIntegerConstant(right(), &rhs)) {
+  if (!Evaluator::ToIntegerConstant(right(), &rhs)) {
     return this;
   }
 
@@ -2587,7 +2403,7 @@
       case Token::kBIT_AND:
       case Token::kBIT_OR:
       case Token::kBIT_XOR:
-        rhs = TruncateTo(rhs, representation());
+        rhs = Evaluator::TruncateTo(rhs, representation());
         break;
       default:
         break;
@@ -3325,10 +3141,7 @@
     return replacement;
   }
 
-// Currently we perform this only on 64-bit architectures and not on simdbc64
-// (on simdbc64 the [UnboxedConstantInstr] handling is only implemented for
-//  doubles and causes a bailout for everthing else)
-#if !defined(TARGET_ARCH_DBC)
+  // Currently we perform this only on 64-bit architectures.
   if (compiler::target::kBitsPerWord == 64) {
     ConstantInstr* c = value()->definition()->AsConstant();
     if (c != NULL && (c->value().IsSmi() || c->value().IsMint())) {
@@ -3341,7 +3154,6 @@
       return uc;
     }
   }
-#endif  // !defined(TARGET_ARCH_DBC)
 
   return this;
 }
@@ -4062,13 +3874,9 @@
   // TODO(kusterman): Remove duplicate between
   // {TargetEntryInstr,FunctionEntryInstr}::EmitNativeCode.
   if (!compiler->is_optimizing()) {
-#if !defined(TARGET_ARCH_DBC)
-    // TODO(vegorov) re-enable edge counters on DBC if we consider them
-    // beneficial for the quality of the optimized bytecode.
     if (compiler->NeedsEdgeCounter(this)) {
       compiler->EmitEdgeCounter(preorder_number());
     }
-#endif
 
     // The deoptimization descriptor points after the edge counter code for
     // uniformity with ARM, where we can reuse pattern matching code that
@@ -4144,13 +3952,9 @@
 #endif
 
   if (!compiler->is_optimizing()) {
-#if !defined(TARGET_ARCH_DBC)
-    // TODO(vegorov) re-enable edge counters on DBC if we consider them
-    // beneficial for the quality of the optimized bytecode.
     if (compiler->NeedsEdgeCounter(this)) {
       compiler->EmitEdgeCounter(preorder_number());
     }
-#endif
 
     // The deoptimization descriptor points after the edge counter code for
     // uniformity with ARM, where we can reuse pattern matching code that
@@ -4277,7 +4081,6 @@
 }
 
 void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if !defined(TARGET_ARCH_DBC)
   // The native entry frame has size -kExitLinkSlotFromFp. In order to access
   // the top of stack from above the entry frame, we add a constant to account
   // for the the two frame pointers and two return addresses of the entry frame.
@@ -4288,14 +4091,10 @@
   const Location src = rebase.Rebase(loc_);
   NoTemporaryAllocator no_temp;
   compiler->EmitMove(dst, src, &no_temp);
-#else
-  UNREACHABLE();
-#endif
 }
 
 LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(opt);
   Location input = Location::Any();
   if (representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) {
@@ -4308,9 +4107,6 @@
   }
   return LocationSummary::Make(zone, /*num_inputs=*/0, input,
                                LocationSummary::kNoCall);
-#else
-  UNREACHABLE();
-#endif
 }
 
 bool ParallelMoveInstr::IsRedundant() const {
@@ -4426,23 +4222,10 @@
 }
 
 void DropTempsInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if defined(TARGET_ARCH_DBC)
-  // On DBC the action of poping the TOS value and then pushing it
-  // after all intermediates are poped is folded into a special
-  // bytecode (DropR). On other architectures this is handled by
-  // instruction prologue/epilogues.
-  ASSERT(!compiler->is_optimizing());
-  if ((InputCount() != 0) && HasTemp()) {
-    __ DropR(num_temps());
-  } else {
-    __ Drop(num_temps() + ((InputCount() != 0) ? 1 : 0));
-  }
-#else
   ASSERT(!compiler->is_optimizing());
   // Assert that register assignment is correct.
   ASSERT((InputCount() == 0) || (locs()->out(0).reg() == locs()->in(0).reg()));
   __ Drop(num_temps());
-#endif  // defined(TARGET_ARCH_DBC)
 }
 
 StrictCompareInstr::StrictCompareInstr(TokenPosition token_pos,
@@ -4463,8 +4246,6 @@
   return MakeCallSummary(zone);
 }
 
-// DBC does not use specialized inline cache stubs for smi operations.
-#if !defined(TARGET_ARCH_DBC)
 static RawCode* TwoArgsSmiOpInlineCacheEntry(Token::Kind kind) {
   if (!FLAG_two_args_smi_icd) {
     return Code::null();
@@ -4480,59 +4261,6 @@
       return Code::null();
   }
 }
-#else
-static void TryFastPathSmiOp(FlowGraphCompiler* compiler,
-                             ICData* call_ic_data,
-                             Token::Kind op_kind) {
-  if (!FLAG_two_args_smi_icd) {
-    return;
-  }
-  switch (op_kind) {
-    case Token::kADD:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ AddTOS();
-      }
-      break;
-    case Token::kSUB:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ SubTOS();
-      }
-      break;
-    case Token::kEQ:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ EqualTOS();
-      }
-      break;
-    case Token::kLT:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ LessThanTOS();
-      }
-      break;
-    case Token::kGT:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ GreaterThanTOS();
-      }
-      break;
-    case Token::kBIT_AND:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ BitAndTOS();
-      }
-      break;
-    case Token::kBIT_OR:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ BitOrTOS();
-      }
-      break;
-    case Token::kMUL:
-      if (call_ic_data->AddSmiSmiCheckForFastSmiStubs()) {
-        __ MulTOS();
-      }
-      break;
-    default:
-      break;
-  }
-}
-#endif
 
 void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   Zone* zone = compiler->zone();
@@ -4554,7 +4282,6 @@
     call_ic_data = &ICData::ZoneHandle(zone, ic_data()->raw());
   }
 
-#if !defined(TARGET_ARCH_DBC)
   if ((compiler->is_optimizing() || compiler->function().HasBytecode()) &&
       HasICData()) {
     ASSERT(HasICData());
@@ -4589,46 +4316,6 @@
                                      *call_ic_data);
     }
   }
-#else
-  ICData* original_ic_data = &ICData::ZoneHandle(call_ic_data->Original());
-
-  // Emit smi fast path instruction. If fast-path succeeds it skips the next
-  // instruction otherwise it falls through. Only attempt in unoptimized code
-  // because TryFastPathSmiOp will update original_ic_data.
-  if (!compiler->is_optimizing()) {
-    TryFastPathSmiOp(compiler, original_ic_data, token_kind());
-  }
-
-  const intptr_t call_ic_data_kidx = __ AddConstant(*original_ic_data);
-  switch (original_ic_data->NumArgsTested()) {
-    case 1:
-      if (compiler->is_optimizing()) {
-        __ InstanceCall1Opt(ArgumentCount(), call_ic_data_kidx);
-      } else {
-        __ InstanceCall1(ArgumentCount(), call_ic_data_kidx);
-      }
-      break;
-    case 2:
-      if (compiler->is_optimizing()) {
-        __ InstanceCall2Opt(ArgumentCount(), call_ic_data_kidx);
-      } else {
-        __ InstanceCall2(ArgumentCount(), call_ic_data_kidx);
-      }
-      break;
-    default:
-      UNIMPLEMENTED();
-      break;
-  }
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
-                                 token_pos());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kIcCall, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 bool InstanceCallInstr::MatchesCoreName(const String& name) {
@@ -4748,9 +4435,6 @@
   return targets().AggregateCallCount();
 }
 
-// DBC does not support optimizing compiler and thus doesn't emit
-// PolymorphicInstanceCallInstr.
-#if !defined(TARGET_ARCH_DBC)
 void PolymorphicInstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ArgumentsInfo args_info(instance_call()->type_args_len(),
                           instance_call()->ArgumentCount(),
@@ -4759,7 +4443,6 @@
       targets_, *instance_call(), args_info, deopt_id(),
       instance_call()->token_pos(), locs(), complete(), total_call_count());
 }
-#endif
 
 RawType* PolymorphicInstanceCallInstr::ComputeRuntimeType(
     const CallTargets& targets) {
@@ -4903,7 +4586,6 @@
     call_ic_data = &ICData::ZoneHandle(ic_data()->raw());
   }
 
-#if !defined(TARGET_ARCH_DBC)
   ArgumentsInfo args_info(type_args_len(), ArgumentCount(), argument_names());
   compiler->GenerateStaticCall(deopt_id(), token_pos(), function(), args_info,
                                locs(), *call_ic_data, rebind_rule_,
@@ -4916,30 +4598,6 @@
                                ArgumentAt(0));
     }
   }
-#else
-  const Array& arguments_descriptor = Array::Handle(
-      zone, (ic_data() == NULL) ? GetArgumentsDescriptor()
-                                : ic_data()->arguments_descriptor());
-  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
-
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(),
-                                 token_pos());
-  if (compiler->is_optimizing()) {
-    __ PushConstant(function());
-    __ StaticCall(ArgumentCount(), argdesc_kidx);
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                   token_pos());
-    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-    __ PopLocal(locs()->out(0).reg());
-  } else {
-    const intptr_t ic_data_kidx = __ AddConstant(*call_ic_data);
-    __ PushConstant(ic_data_kidx);
-    __ IndirectStaticCall(ArgumentCount(), argdesc_kidx);
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kUnoptStaticCall,
-                                   deopt_id(), token_pos());
-    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  }
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 intptr_t AssertAssignableInstr::statistics_tag() const {
@@ -4960,15 +4618,10 @@
 void AssertAssignableInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   compiler->GenerateAssertAssignable(token_pos(), deopt_id(), dst_type(),
                                      dst_name(), locs());
-
-// DBC does not use LocationSummaries in the same way as other architectures.
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(locs()->in(0).reg() == locs()->out(0).reg());
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(sub_type().IsFinalized());
   ASSERT(super_type().IsFinalized());
 
@@ -4982,19 +4635,6 @@
                                 kSubtypeCheckRuntimeEntry, 5, locs());
 
   __ Drop(5);
-#else
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());  // Instantiator type arguments.
-    __ Push(locs()->in(1).reg());  // Function type arguments.
-  } else {
-    // The 2 inputs are already on the expression stack.
-  }
-  __ PushConstant(sub_type());
-  __ PushConstant(super_type());
-  __ PushConstant(dst_name());
-  __ AssertSubtype();
-
-#endif
 }
 
 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
@@ -5003,15 +4643,9 @@
 }
 
 void DeoptimizeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if !defined(TARGET_ARCH_DBC)
   __ Jump(compiler->AddDeoptStub(deopt_id(), deopt_reason_));
-#else
-  compiler->EmitDeopt(deopt_id(), deopt_reason_);
-#endif
 }
 
-#if !defined(TARGET_ARCH_DBC)
-
 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   compiler::Label* deopt =
       compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass,
@@ -5109,8 +4743,6 @@
   return locs;
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 void CheckNullInstr::AddMetadataForRuntimeCall(CheckNullInstr* check_null,
                                                FlowGraphCompiler* compiler) {
   const String& function_name = check_null->function_name();
@@ -5120,8 +4752,6 @@
                          check_null->token_pos(), name_index);
 }
 
-#if !defined(TARGET_ARCH_DBC)
-
 void UnboxInstr::EmitLoadFromBoxWithDeopt(FlowGraphCompiler* compiler) {
   const intptr_t box_cid = BoxCid();
   const Register box = locs()->in(0).reg();
@@ -5198,8 +4828,6 @@
   }
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 Environment* Environment::From(Zone* zone,
                                const GrowableArray<Definition*>& definitions,
                                intptr_t fixed_parameter_count,
@@ -5227,7 +4855,7 @@
     copy->set_locations(new_locations);
   }
   for (intptr_t i = 0; i < length; ++i) {
-    copy->values_.Add(values_[i]->Copy(zone));
+    copy->values_.Add(values_[i]->CopyWithType(zone));
     if (locations_ != NULL) {
       copy->locations_[i] = locations_[i].Copy();
     }
@@ -5343,16 +4971,13 @@
   return true;
 }
 
-#if !defined(TARGET_ARCH_DBC)
 static bool BindsToSmiConstant(Value* value) {
   return value->BindsToConstant() && value->BoundConstant().IsSmi();
 }
-#endif
 
 bool IfThenElseInstr::Supports(ComparisonInstr* comparison,
                                Value* v1,
                                Value* v2) {
-#if !defined(TARGET_ARCH_DBC)
   bool is_smi_result = BindsToSmiConstant(v1) && BindsToSmiConstant(v2);
   if (comparison->IsStrictCompare()) {
     // Strict comparison with number checks calls a stub and is not supported
@@ -5365,9 +4990,6 @@
     return false;
   }
   return is_smi_result;
-#else
-  return false;
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 bool PhiInstr::IsRedundant() const {
@@ -5731,8 +5353,6 @@
   }
 }
 
-#if !defined(TARGET_ARCH_DBC)
-
 #define Z zone_
 
 LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
@@ -5816,34 +5436,8 @@
 
 #undef Z
 
-#else
-
-LocationSummary* FfiCallInstr::MakeLocationSummary(Zone* zone,
-                                                   bool is_optimizing) const {
-  LocationSummary* summary =
-      new (zone) LocationSummary(zone, /*num_inputs=*/InputCount(),
-                                 /*num_temps=*/0, LocationSummary::kCall);
-
-  summary->set_in(
-      TargetAddressIndex(),
-      Location::RegisterLocation(compiler::ffi::kFunctionAddressRegister));
-  for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
-    summary->set_in(i, arg_locations_[i]);
-  }
-  summary->set_out(0, compiler::ffi::ResultLocation(
-                          compiler::ffi::ResultHostRepresentation(signature_)));
-
-  return summary;
-}
-
-#endif  // !defined(TARGET_ARCH_DBC)
-
 Representation FfiCallInstr::representation() const {
-#if !defined(TARGET_ARCH_DBC)
   return compiler::ffi::ResultRepresentation(signature_);
-#else
-  return compiler::ffi::ResultHostRepresentation(signature_);
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 // SIMD
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index e2e8ac3..fc95490 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -154,7 +154,8 @@
   const Object& BoundConstant() const;
 
   // Return true if storing the value into a heap object requires applying the
-  // write barrier.
+  // write barrier. Can change the reaching type of the Value or other Values
+  // in the same chain of redefinitions.
   bool NeedsWriteBarrier();
 
   bool Equals(Value* other) const;
@@ -177,18 +178,33 @@
 // Represents a range of class-ids for use in class checks and polymorphic
 // dispatches.  The range includes both ends, i.e. it is [cid_start, cid_end].
 struct CidRange : public ZoneAllocated {
-  CidRange(const CidRange& o)
-      : ZoneAllocated(), cid_start(o.cid_start), cid_end(o.cid_end) {}
   CidRange(intptr_t cid_start_arg, intptr_t cid_end_arg)
       : cid_start(cid_start_arg), cid_end(cid_end_arg) {}
   CidRange() : cid_start(kIllegalCid), cid_end(kIllegalCid) {}
 
-  const CidRange& operator=(const CidRange& other) {
-    cid_start = other.cid_start;
-    cid_end = other.cid_end;
-    return *this;
+  bool IsSingleCid() const { return cid_start == cid_end; }
+  bool Contains(intptr_t cid) { return cid_start <= cid && cid <= cid_end; }
+  int32_t Extent() const { return cid_end - cid_start; }
+
+  // The number of class ids this range covers.
+  intptr_t size() const { return cid_end - cid_start + 1; }
+
+  bool IsIllegalRange() const {
+    return cid_start == kIllegalCid && cid_end == kIllegalCid;
   }
 
+  intptr_t cid_start;
+  intptr_t cid_end;
+
+  DISALLOW_COPY_AND_ASSIGN(CidRange);
+};
+
+struct CidRangeValue {
+  CidRangeValue(intptr_t cid_start_arg, intptr_t cid_end_arg)
+      : cid_start(cid_start_arg), cid_end(cid_end_arg) {}
+  CidRangeValue(const CidRange& other)  // NOLINT
+      : cid_start(other.cid_start), cid_end(other.cid_end) {}
+
   bool IsSingleCid() const { return cid_start == cid_end; }
   bool Contains(intptr_t cid) { return cid_start <= cid && cid <= cid_end; }
   int32_t Extent() const { return cid_end - cid_start; }
@@ -204,7 +220,7 @@
   intptr_t cid_end;
 };
 
-typedef MallocGrowableArray<CidRange> CidRangeVector;
+typedef MallocGrowableArray<CidRangeValue> CidRangeVector;
 
 class HierarchyInfo : public ThreadStackResource {
  public:
@@ -395,6 +411,7 @@
   M(LoadCodeUnits, kNoGC)                                                      \
   M(StoreIndexed, kNoGC)                                                       \
   M(StoreInstanceField, _)                                                     \
+  M(InitInstanceField, _)                                                      \
   M(InitStaticField, _)                                                        \
   M(LoadStaticField, kNoGC)                                                    \
   M(StoreStaticField, kNoGC)                                                   \
@@ -494,7 +511,7 @@
 #undef FORWARD_DECLARATION
 
 #define DEFINE_INSTRUCTION_TYPE_CHECK(type)                                    \
-  virtual type##Instr* As##type() { return this; }                             \
+  virtual const type##Instr* As##type() const { return this; }                 \
   virtual const char* DebugName() const { return #type; }
 
 // Functions required in all concrete instruction classes.
@@ -513,21 +530,11 @@
   DECLARE_INSTRUCTION_NO_BACKEND(type)                                         \
   DECLARE_INSTRUCTION_BACKEND()
 
-#if defined(TARGET_ARCH_DBC)
-#define DECLARE_COMPARISON_METHODS                                             \
-  virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing)    \
-      const;                                                                   \
-  virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,            \
-                                       BranchLabels labels);                   \
-  virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,   \
-                                                BranchLabels labels);
-#else
 #define DECLARE_COMPARISON_METHODS                                             \
   virtual LocationSummary* MakeLocationSummary(Zone* zone, bool optimizing)    \
       const;                                                                   \
   virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,            \
                                        BranchLabels labels);
-#endif
 
 #define DECLARE_COMPARISON_INSTRUCTION(type)                                   \
   DECLARE_INSTRUCTION_NO_BACKEND(type)                                         \
@@ -576,6 +583,8 @@
   const Function* target;
   intptr_t count;
   StaticTypeExactnessState exactness;
+
+  DISALLOW_COPY_AND_ASSIGN(TargetInfo);
 };
 
 // A set of class-ids, arranged in ranges. Used for the CheckClass
@@ -885,8 +894,12 @@
                                          FlowGraphSerializer* s) const;
 
 #define DECLARE_INSTRUCTION_TYPE_CHECK(Name, Type)                             \
-  bool Is##Name() { return (As##Name() != NULL); }                             \
-  virtual Type* As##Name() { return NULL; }
+  bool Is##Name() const { return (As##Name() != nullptr); }                    \
+  Type* As##Name() {                                                           \
+    auto const_this = static_cast<const Instruction*>(this);                   \
+    return const_cast<Type*>(const_this->As##Name());                          \
+  }                                                                            \
+  virtual const Type* As##Name() const { return nullptr; }
 #define INSTRUCTION_TYPE_CHECK(Name, Attrs)                                    \
   DECLARE_INSTRUCTION_TYPE_CHECK(Name, Name##Instr)
 
@@ -1055,18 +1068,11 @@
   // instead.
   Location::Kind RegisterKindForResult() const {
     const Representation rep = representation();
-#if !defined(TARGET_ARCH_DBC)
     if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
         (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
         (rep == kUnboxedFloat64x2)) {
       return Location::kFpuRegister;
     }
-#else
-    // DBC supports only unboxed doubles and does not have distinguished FPU
-    // registers.
-    ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
-           (rep != kUnboxedFloat64x2));
-#endif
     return Location::kRegister;
   }
 
@@ -1532,11 +1538,16 @@
   GrowableArray<Definition*>* initial_definitions() {
     return &initial_definitions_;
   }
+  const GrowableArray<Definition*>* initial_definitions() const {
+    return &initial_definitions_;
+  }
 
-  virtual bool IsBlockEntryWithInitialDefs() { return true; }
   virtual BlockEntryWithInitialDefs* AsBlockEntryWithInitialDefs() {
     return this;
   }
+  virtual const BlockEntryWithInitialDefs* AsBlockEntryWithInitialDefs() const {
+    return this;
+  }
 
  protected:
   void PrintInitialDefinitionsTo(BufferFormatter* f) const;
@@ -1989,6 +2000,36 @@
     return AliasIdentity(kAllocationSinkingCandidate);
   }
 
+#define FOR_EACH_ALIAS_IDENTITY_VALUE(V)                                       \
+  V(Unknown, 0)                                                                \
+  V(NotAliased, 1)                                                             \
+  V(Aliased, 2)                                                                \
+  V(AllocationSinkingCandidate, 3)
+
+  const char* ToCString() {
+    switch (value_) {
+#define VALUE_CASE(name, val)                                                  \
+  case k##name:                                                                \
+    return #name;
+      FOR_EACH_ALIAS_IDENTITY_VALUE(VALUE_CASE)
+#undef VALUE_CASE
+      default:
+        UNREACHABLE();
+        return nullptr;
+    }
+  }
+
+  static bool Parse(const char* str, AliasIdentity* out) {
+#define VALUE_CASE(name, val)                                                  \
+  if (strcmp(str, #name) == 0) {                                               \
+    out->value_ = k##name;                                                     \
+    return true;                                                               \
+  }
+    FOR_EACH_ALIAS_IDENTITY_VALUE(VALUE_CASE)
+#undef VALUE_CASE
+    return false;
+  }
+
   bool IsUnknown() const { return value_ == kUnknown; }
   bool IsAliased() const { return value_ == kAliased; }
   bool IsNotAliased() const { return (value_ & kNotAliased) != 0; }
@@ -2007,12 +2048,12 @@
  private:
   explicit AliasIdentity(intptr_t value) : value_(value) {}
 
-  enum {
-    kUnknown = 0,
-    kNotAliased = 1,
-    kAliased = 2,
-    kAllocationSinkingCandidate = 3,
-  };
+#define VALUE_DEFN(name, val) k##name = val,
+  enum { FOR_EACH_ALIAS_IDENTITY_VALUE(VALUE_DEFN) };
+#undef VALUE_DEFN
+
+// Undef the FOR_EACH helper macro, since the enum is private.
+#undef FOR_EACH_ALIAS_IDENTITY_VALUE
 
   COMPILE_ASSERT((kUnknown & kNotAliased) == 0);
   COMPILE_ASSERT((kAliased & kNotAliased) == 0);
@@ -2185,10 +2226,12 @@
   Definition* OriginalDefinitionIgnoreBoxingAndConstraints();
 
   virtual Definition* AsDefinition() { return this; }
+  virtual const Definition* AsDefinition() const { return this; }
 
  protected:
   friend class RangeAnalysis;
   friend class Value;
+  friend class FlowGraphSerializer;  // To access type_ directly.
 
   Range* range_ = nullptr;
 
@@ -2909,15 +2952,6 @@
   virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
                                        BranchLabels labels) = 0;
 
-#if defined(TARGET_ARCH_DBC)
-  // On the DBC platform EmitNativeCode needs to know ahead of time what
-  // 'Condition' will be returned by EmitComparisonCode. This call must return
-  // the same result as EmitComparisonCode, but should not emit any
-  // instructions.
-  virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
-                                                BranchLabels labels) = 0;
-#endif
-
   // Emits code that generates 'true' or 'false', depending on the comparison.
   // This implementation will call EmitComparisonCode.  If EmitComparisonCode
   // does not use the labels (merely returning a condition) then EmitNativeCode
@@ -3716,7 +3750,7 @@
   const CallTargets& Targets();
   void SetTargets(const CallTargets* targets) { targets_ = targets; }
 
-  const BinaryFeedback& BinaryFeedback();
+  const class BinaryFeedback& BinaryFeedback();
   void SetBinaryFeedback(const class BinaryFeedback* binary) {
     binary_ = binary;
   }
@@ -4248,7 +4282,7 @@
   virtual void SetIdentity(AliasIdentity identity) { identity_ = identity; }
 
   const CallTargets& Targets();
-  const BinaryFeedback& BinaryFeedback();
+  const class BinaryFeedback& BinaryFeedback();
 
   PRINT_OPERANDS_TO_SUPPORT
   ADD_OPERANDS_TO_S_EXPRESSION_SUPPORT
@@ -5332,10 +5366,7 @@
     : public TemplateAllocation<0, NoThrow> {
  public:
   AllocateUninitializedContextInstr(TokenPosition token_pos,
-                                    intptr_t num_context_variables)
-      : token_pos_(token_pos),
-        num_context_variables_(num_context_variables),
-        identity_(AliasIdentity::Unknown()) {}
+                                    intptr_t num_context_variables);
 
   DECLARE_INSTRUCTION(AllocateUninitializedContext)
   virtual CompileType ComputeType() const;
@@ -5820,6 +5851,29 @@
   DISALLOW_COPY_AND_ASSIGN(AllocateContextInstr);
 };
 
+class InitInstanceFieldInstr : public TemplateInstruction<1, Throws> {
+ public:
+  InitInstanceFieldInstr(Value* input, const Field& field, intptr_t deopt_id)
+      : TemplateInstruction(deopt_id), field_(field) {
+    SetInputAt(0, input);
+    CheckField(field);
+  }
+
+  virtual TokenPosition token_pos() const { return field_.token_pos(); }
+  const Field& field() const { return field_; }
+
+  DECLARE_INSTRUCTION(InitInstanceField)
+
+  virtual bool ComputeCanDeoptimize() const { return true; }
+  virtual bool HasUnknownSideEffects() const { return true; }
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
+ private:
+  const Field& field_;
+
+  DISALLOW_COPY_AND_ASSIGN(InitInstanceFieldInstr);
+};
+
 class InitStaticFieldInstr : public TemplateInstruction<1, Throws> {
  public:
   InitStaticFieldInstr(Value* input, const Field& field, intptr_t deopt_id)
@@ -5998,10 +6052,6 @@
     SetInputAt(0, value);
   }
 
-#if defined(TARGET_ARCH_DBC)
-  void EmitAllocateBox(FlowGraphCompiler* compiler);
-#endif
-
  private:
   intptr_t ValueOffset() const {
     return Boxing::ValueOffset(from_representation());
@@ -6577,8 +6627,6 @@
 
   PRINT_OPERANDS_TO_SUPPORT
 
-  RawInteger* Evaluate(const Integer& value) const;
-
   DEFINE_INSTRUCTION_TYPE_CHECK(UnaryIntegerOp)
 
  private:
@@ -6744,14 +6792,6 @@
   virtual Condition EmitComparisonCode(FlowGraphCompiler* compiler,
                                        BranchLabels labels);
 
-#if defined(TARGET_ARCH_DBC)
-  virtual Condition GetNextInstructionCondition(FlowGraphCompiler* compiler,
-                                                BranchLabels labels) {
-    UNREACHABLE();
-    return INVALID_CONDITION;
-  }
-#endif
-
   virtual ComparisonInstr* CopyWithNewOperands(Value* left, Value* right);
 
  private:
@@ -6805,8 +6845,6 @@
   // a power of two.
   bool RightIsPowerOfTwoConstant() const;
 
-  RawInteger* Evaluate(const Integer& left, const Integer& right) const;
-
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
   virtual bool AttributesEqual(Instruction* other) const;
@@ -7813,13 +7851,13 @@
 
 class CheckClassIdInstr : public TemplateInstruction<1, NoThrow> {
  public:
-  CheckClassIdInstr(Value* value, CidRange cids, intptr_t deopt_id)
+  CheckClassIdInstr(Value* value, CidRangeValue cids, intptr_t deopt_id)
       : TemplateInstruction(deopt_id), cids_(cids) {
     SetInputAt(0, value);
   }
 
   Value* value() const { return inputs_[0]; }
-  const CidRange& cids() const { return cids_; }
+  const CidRangeValue& cids() const { return cids_; }
 
   DECLARE_INSTRUCTION(CheckClassId)
 
@@ -7837,7 +7875,7 @@
  private:
   bool Contains(intptr_t cid) const;
 
-  CidRange cids_;
+  CidRangeValue cids_;
 
   DISALLOW_COPY_AND_ASSIGN(CheckClassIdInstr);
 };
@@ -7855,8 +7893,8 @@
   Value* length() const { return inputs_[kLengthPos]; }
   Value* index() const { return inputs_[kIndexPos]; }
 
-  virtual bool IsCheckBoundBase() { return true; }
   virtual CheckBoundBase* AsCheckBoundBase() { return this; }
+  virtual const CheckBoundBase* AsCheckBoundBase() const { return this; }
   virtual Value* RedefinedValue() const;
 
   // Returns true if the bounds check can be eliminated without
@@ -8593,17 +8631,6 @@
   // from the copy.
   Environment* DeepCopy(Zone* zone, intptr_t length) const;
 
-#if defined(TARGET_ARCH_DBC)
-  // Return/ReturnTOS instruction drops incoming arguments so
-  // we have to drop outgoing arguments from the innermost environment.
-  // On all other architectures caller drops outgoing arguments itself
-  // hence the difference.
-  // Note: this method can only be used at the code generation stage because
-  // it mutates environment in unsafe way (e.g. does not update def-use
-  // chains).
-  void DropArguments(intptr_t argc);
-#endif
-
  private:
   friend class ShallowIterator;
   friend class compiler::BlockBuilder;  // For Environment constructor.
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 1d09580..9515797 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -510,7 +510,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ bkpt(0);
+#endif
   __ Bind(&done);
 }
 
@@ -3187,6 +3189,35 @@
                          RawPcDescriptors::kOther, locs());
 }
 
+LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(R0));
+  locs->set_temp(0, Location::RegisterLocation(R1));
+  return locs;
+}
+
+void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register instance = locs()->in(0).reg();
+  Register temp = locs()->temp(0).reg();
+  compiler::Label no_call;
+
+  __ ldr(temp, compiler::FieldAddress(instance, field().Offset()));
+  __ CompareObject(temp, Object::sentinel());
+  __ b(&no_call, NE);
+
+  __ PushObject(Object::null_object());  // Make room for (unused) result.
+  __ Push(instance);
+  __ PushObject(Field::ZoneHandle(field().Original()));
+  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+                                kInitInstanceFieldRuntimeEntry, 2, locs());
+  __ Drop(3);  // Remove arguments and result placeholder.
+  __ Bind(&no_call);
+}
+
 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 1;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 220940e..b83bf31 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -499,7 +499,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ brk(0);
+#endif
   __ Bind(&done);
 }
 
@@ -919,12 +921,14 @@
 
     // We are entering runtime code, so the C stack pointer must be restored
     // from the stack limit to the top of the stack.
+    __ mov(R25, CSP);
     __ mov(CSP, SP);
 
     __ blr(branch);
 
     // Restore the Dart stack pointer.
     __ mov(SP, CSP);
+    __ mov(CSP, R25);
 
     // Update information in the thread object and leave the safepoint.
     __ TransitionNativeToGenerated(temp, /*leave_safepoint=*/true);
@@ -1032,7 +1036,9 @@
   __ Bind(compiler->GetJumpLabel(this));
 
   // We don't use the regular stack pointer in ARM64, so we have to copy the
-  // native stack pointer into the Dart stack pointer.
+  // native stack pointer into the Dart stack pointer. This will also kick CSP
+  // forward a bit, enough for the spills and leaf call below, until we can set
+  // it properly after setting up THR.
   __ SetupDartSP();
 
   // Create a dummy frame holding the pushed arguments. This simplifies
@@ -1100,6 +1106,9 @@
     __ LeaveFrame();
   }
 
+  // Now that we have THR, we can set CSP.
+  __ SetupCSPFromThread(THR);
+
   // Refresh write barrier mask.
   __ ldr(BARRIER_MASK,
          compiler::Address(
@@ -1363,9 +1372,8 @@
   compiler::Address element_address(TMP);  // Bad address.
   element_address =
       index.IsRegister()
-          ? __ ElementAddressForRegIndex(true,  // Load.
-                                         IsExternal(), class_id(),
-                                         index_scale(), array, index.reg())
+          ? __ ElementAddressForRegIndex(IsExternal(), class_id(),
+                                         index_scale(), array, index.reg(), TMP)
           : __ ElementAddressForIntIndex(IsExternal(), class_id(),
                                          index_scale(), array,
                                          Smi::Cast(index.constant()).Value());
@@ -1497,7 +1505,7 @@
   }
   // Warning: element_address may use register TMP as base.
   compiler::Address element_address = __ ElementAddressForRegIndexWithSize(
-      true, IsExternal(), class_id(), sz, index_scale(), str, index.reg());
+      IsExternal(), class_id(), sz, index_scale(), str, index.reg(), TMP);
   __ ldr(result, element_address, sz);
 
   __ SmiTag(result);
@@ -1553,7 +1561,7 @@
   if (CanBeImmediateIndex(index(), class_id(), IsExternal())) {
     locs->set_in(1, Location::Constant(index()->definition()->AsConstant()));
   } else {
-    locs->set_in(1, Location::WritableRegister());
+    locs->set_in(1, Location::RequiresRegister());
   }
   locs->set_temp(0, Location::RequiresRegister());
 
@@ -1601,32 +1609,43 @@
   // The array register points to the backing store for external arrays.
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
-  const Register address = locs()->temp(0).reg();
+  const Register temp = locs()->temp(0).reg();
+  compiler::Address element_address(TMP);  // Bad address.
 
-  if (index.IsRegister()) {
-    __ LoadElementAddressForRegIndex(address,
-                                     false,  // Store.
-                                     IsExternal(), class_id(), index_scale(),
-                                     array, index.reg());
-  } else {
-    __ LoadElementAddressForIntIndex(address, IsExternal(), class_id(),
-                                     index_scale(), array,
-                                     Smi::Cast(index.constant()).Value());
+  // Deal with a special case separately.
+  if (class_id() == kArrayCid && ShouldEmitStoreBarrier()) {
+    if (index.IsRegister()) {
+      __ ComputeElementAddressForRegIndex(temp, IsExternal(), class_id(),
+                                          index_scale(), array, index.reg());
+    } else {
+      __ ComputeElementAddressForIntIndex(temp, IsExternal(), class_id(),
+                                          index_scale(), array,
+                                          Smi::Cast(index.constant()).Value());
+    }
+    const Register value = locs()->in(2).reg();
+    __ StoreIntoArray(array, temp, value, CanValueBeSmi(),
+                      /*lr_reserved=*/!compiler->intrinsic_mode());
+    return;
   }
 
+  element_address =
+      index.IsRegister()
+          ? __ ElementAddressForRegIndex(IsExternal(), class_id(),
+                                         index_scale(), array,
+                                         index.reg(), temp)
+          : __ ElementAddressForIntIndex(IsExternal(), class_id(),
+                                         index_scale(), array,
+                                         Smi::Cast(index.constant()).Value());
+
   switch (class_id()) {
     case kArrayCid:
-      if (ShouldEmitStoreBarrier()) {
-        const Register value = locs()->in(2).reg();
-        __ StoreIntoArray(array, address, value, CanValueBeSmi(),
-                          /*lr_reserved=*/!compiler->intrinsic_mode());
-      } else if (locs()->in(2).IsConstant()) {
+      ASSERT(!ShouldEmitStoreBarrier());   // Specially treated above.
+      if (locs()->in(2).IsConstant()) {
         const Object& constant = locs()->in(2).constant();
-        __ StoreIntoObjectNoBarrier(array, compiler::Address(address),
-                                    constant);
+        __ StoreIntoObjectNoBarrier(array, element_address, constant);
       } else {
         const Register value = locs()->in(2).reg();
-        __ StoreIntoObjectNoBarrier(array, compiler::Address(address), value);
+        __ StoreIntoObjectNoBarrier(array, element_address, value);
       }
       break;
     case kTypedDataInt8ArrayCid:
@@ -1637,10 +1656,10 @@
       if (locs()->in(2).IsConstant()) {
         const Smi& constant = Smi::Cast(locs()->in(2).constant());
         __ LoadImmediate(TMP, static_cast<int8_t>(constant.Value()));
-        __ str(TMP, compiler::Address(address), kUnsignedByte);
+        __ str(TMP, element_address, kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
-        __ str(value, compiler::Address(address), kUnsignedByte);
+        __ str(value, element_address, kUnsignedByte);
       }
       break;
     }
@@ -1657,14 +1676,14 @@
           value = 0;
         }
         __ LoadImmediate(TMP, static_cast<int8_t>(value));
-        __ str(TMP, compiler::Address(address), kUnsignedByte);
+        __ str(TMP, element_address, kUnsignedByte);
       } else {
         const Register value = locs()->in(2).reg();
         // Clamp to 0x00 or 0xFF respectively.
         __ CompareImmediate(value, 0xFF);
         __ csetm(TMP, GT);             // TMP = value > 0xFF ? -1 : 0.
         __ csel(TMP, value, TMP, LS);  // TMP = value in range ? value : TMP.
-        __ str(TMP, compiler::Address(address), kUnsignedByte);
+        __ str(TMP, element_address, kUnsignedByte);
       }
       break;
     }
@@ -1672,36 +1691,36 @@
     case kTypedDataUint16ArrayCid: {
       ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       const Register value = locs()->in(2).reg();
-      __ str(value, compiler::Address(address), kUnsignedHalfword);
+      __ str(value, element_address, kUnsignedHalfword);
       break;
     }
     case kTypedDataInt32ArrayCid:
     case kTypedDataUint32ArrayCid: {
       const Register value = locs()->in(2).reg();
-      __ str(value, compiler::Address(address), kUnsignedWord);
+      __ str(value, element_address, kUnsignedWord);
       break;
     }
     case kTypedDataInt64ArrayCid:
     case kTypedDataUint64ArrayCid: {
       const Register value = locs()->in(2).reg();
-      __ str(value, compiler::Address(address), kDoubleWord);
+      __ str(value, element_address, kDoubleWord);
       break;
     }
     case kTypedDataFloat32ArrayCid: {
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrs(value_reg, compiler::Address(address));
+      __ fstrs(value_reg, element_address);
       break;
     }
     case kTypedDataFloat64ArrayCid: {
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrd(value_reg, compiler::Address(address));
+      __ fstrd(value_reg, element_address);
       break;
     }
     case kTypedDataFloat64x2ArrayCid:
     case kTypedDataInt32x4ArrayCid:
     case kTypedDataFloat32x4ArrayCid: {
       const VRegister value_reg = locs()->in(2).fpu_reg();
-      __ fstrq(value_reg, compiler::Address(address));
+      __ fstrq(value_reg, element_address);
       break;
     }
     default:
@@ -2731,6 +2750,35 @@
                          RawPcDescriptors::kOther, locs());
 }
 
+LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(R0));
+  locs->set_temp(0, Location::RegisterLocation(R1));
+  return locs;
+}
+
+void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register instance = locs()->in(0).reg();
+  Register temp = locs()->temp(0).reg();
+  compiler::Label no_call;
+
+  __ ldr(temp, compiler::FieldAddress(instance, field().Offset()));
+  __ CompareObject(temp, Object::sentinel());
+  __ b(&no_call, NE);
+
+  __ Push(ZR);  // Make room for (unused) result.
+  __ Push(instance);
+  __ PushObject(Field::ZoneHandle(field().Original()));
+  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+                                kInitInstanceFieldRuntimeEntry, 2, locs());
+  __ Drop(3);  // Remove arguments and result placeholder.
+  __ Bind(&no_call);
+}
+
 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 1;
@@ -2938,7 +2986,8 @@
   CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
   compiler->AddSlowPathCode(slow_path);
 
-  __ ldr(TMP, compiler::Address(THR, Thread::stack_limit_offset()));
+  __ ldr(TMP, compiler::Address(
+                  THR, compiler::target::Thread::stack_limit_offset()));
   __ CompareRegisters(SP, TMP);
   __ b(slow_path->entry_label(), LS);
   if (compiler->CanOSRFunction() && in_loop()) {
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
deleted file mode 100644
index bd859e9..0000000
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ /dev/null
@@ -1,2122 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/backend/il.h"
-
-#include "vm/compiler/backend/flow_graph.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/backend/locations.h"
-#include "vm/compiler/backend/range_analysis.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/object_store.h"
-#include "vm/parser.h"
-#include "vm/simulator.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
-#include "vm/symbols.h"
-
-#define __ compiler->assembler()->
-
-namespace dart {
-
-DECLARE_FLAG(bool, emit_edge_counters);
-DECLARE_FLAG(int, optimization_counter_threshold);
-
-// List of instructions that are still unimplemented by DBC backend.
-#define FOR_EACH_UNIMPLEMENTED_INSTRUCTION(M)                                  \
-  M(BinaryInt32Op)                                                             \
-  M(BinaryUint32Op)                                                            \
-  M(CheckCondition)                                                            \
-  M(DoubleToInteger)                                                           \
-  M(ExtractNthOutput)                                                          \
-  M(GuardFieldClass)                                                           \
-  M(GuardFieldLength)                                                          \
-  M(GuardFieldType)                                                            \
-  M(IfThenElse)                                                                \
-  M(Int32ToDouble)                                                             \
-  M(LoadCodeUnits)                                                             \
-  M(ShiftUint32Op)                                                             \
-  M(SpeculativeShiftUint32Op)                                                  \
-  M(TruncDivMod)                                                               \
-  M(UnaryUint32Op)                                                             \
-  M(IntConverter)
-
-// List of instructions that are not used by DBC.
-// Things we aren't planning to implement for DBC:
-// - Unboxed SIMD,
-// - Unboxed Mint,
-// - Optimized RegExps,
-// - Precompilation.
-#define FOR_EACH_UNREACHABLE_INSTRUCTION(M)                                    \
-  M(CaseInsensitiveCompare)                                                    \
-  M(GenericCheckBound)                                                         \
-  M(IndirectGoto)                                                              \
-  M(Int64ToDouble)                                                             \
-  M(BinaryInt64Op)                                                             \
-  M(ShiftInt64Op)                                                              \
-  M(SpeculativeShiftInt64Op)                                                   \
-  M(UnaryInt64Op)                                                              \
-  M(CheckedSmiOp)                                                              \
-  M(CheckedSmiComparison)                                                      \
-  M(SimdOp)                                                                    \
-  M(NativeReturn)
-
-// Location summaries actually are not used by the unoptimizing DBC compiler
-// because we don't allocate any registers.
-static LocationSummary* CreateLocationSummary(
-    Zone* zone,
-    intptr_t num_inputs,
-    Location output = Location::NoLocation(),
-    LocationSummary::ContainsCall contains_call = LocationSummary::kNoCall,
-    intptr_t num_temps = 0) {
-  LocationSummary* locs =
-      new (zone) LocationSummary(zone, num_inputs, num_temps, contains_call);
-  ASSERT(contains_call == LocationSummary::kNoCall ||
-         num_inputs <= kMaxNumberOfFixedInputRegistersUsedByIL);
-  for (intptr_t i = 0; i < num_inputs; i++) {
-    locs->set_in(i, (contains_call == LocationSummary::kNoCall)
-                        ? Location::RequiresRegister()
-                        : Location::RegisterLocation(i));
-  }
-  for (intptr_t i = 0; i < num_temps; i++) {
-    locs->set_temp(i, Location::RequiresRegister());
-  }
-  if (!output.IsInvalid()) {
-    // For instructions that call we default to returning result in R0.
-    locs->set_out(0, output);
-  }
-  return locs;
-}
-
-#define DEFINE_MAKE_LOCATION_SUMMARY(Name, ...)                                \
-  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
-      const {                                                                  \
-    return CreateLocationSummary(zone, __VA_ARGS__);                           \
-  }
-
-#define EMIT_NATIVE_CODE(Name, ...)                                            \
-  DEFINE_MAKE_LOCATION_SUMMARY(Name, __VA_ARGS__);                             \
-  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler)
-
-#define DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                       \
-  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
-      const {                                                                  \
-    if (!opt) UNIMPLEMENTED();                                                 \
-    return NULL;                                                               \
-  }
-
-#define DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                         \
-  LocationSummary* Name##Instr::MakeLocationSummary(Zone* zone, bool opt)      \
-      const {                                                                  \
-    UNREACHABLE();                                                             \
-    return NULL;                                                               \
-  }
-
-#define DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)                            \
-  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
-    UNIMPLEMENTED();                                                           \
-  }
-
-#define DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)                              \
-  void Name##Instr::EmitNativeCode(FlowGraphCompiler* compiler) {              \
-    UNREACHABLE();                                                             \
-  }
-
-#define DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(Name)                            \
-  void Name##Instr::EmitBranchCode(FlowGraphCompiler*, BranchInstr*) {         \
-    UNIMPLEMENTED();                                                           \
-  }                                                                            \
-  Condition Name##Instr::EmitComparisonCode(FlowGraphCompiler*,                \
-                                            BranchLabels) {                    \
-    UNIMPLEMENTED();                                                           \
-    return NEXT_IS_TRUE;                                                       \
-  }
-
-#define DEFINE_UNIMPLEMENTED(Name)                                             \
-  DEFINE_UNIMPLEMENTED_MAKE_LOCATION_SUMMARY(Name)                             \
-  DEFINE_UNIMPLEMENTED_EMIT_NATIVE_CODE(Name)
-
-FOR_EACH_UNIMPLEMENTED_INSTRUCTION(DEFINE_UNIMPLEMENTED)
-
-#undef DEFINE_UNIMPLEMENTED
-
-#define DEFINE_UNREACHABLE(Name)                                               \
-  DEFINE_UNREACHABLE_MAKE_LOCATION_SUMMARY(Name)                               \
-  DEFINE_UNREACHABLE_EMIT_NATIVE_CODE(Name)
-
-FOR_EACH_UNREACHABLE_INSTRUCTION(DEFINE_UNREACHABLE)
-
-#undef DEFINE_UNREACHABLE
-
-// Only used in AOT compilation.
-DEFINE_UNIMPLEMENTED_EMIT_BRANCH_CODE(CheckedSmiComparison)
-
-EMIT_NATIVE_CODE(InstanceOf,
-                 3,
-                 Location::SameAsFirstInput(),
-                 LocationSummary::kCall) {
-  SubtypeTestCache& test_cache = SubtypeTestCache::Handle();
-  if (!type().IsVoidType() && type().IsInstantiated()) {
-    test_cache = SubtypeTestCache::New();
-  }
-
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());  // Value.
-    __ Push(locs()->in(1).reg());  // Instantiator type arguments.
-    __ Push(locs()->in(2).reg());  // Function type arguments.
-  }
-
-  __ PushConstant(type());
-  __ PushConstant(test_cache);
-  __ InstanceOf();
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(AssertAssignable,
-                             3,
-                             Location::SameAsFirstInput(),
-                             LocationSummary::kCall);
-
-DEFINE_MAKE_LOCATION_SUMMARY(AssertSubtype,
-                             2,
-                             Location::NoLocation(),
-                             LocationSummary::kCall);
-
-EMIT_NATIVE_CODE(AssertBoolean,
-                 1,
-                 Location::SameAsFirstInput(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-  }
-  __ AssertBoolean(0);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  if (compiler->is_optimizing()) {
-    __ Drop1();
-  }
-}
-
-EMIT_NATIVE_CODE(PolymorphicInstanceCall,
-                 0,
-                 Location::RegisterLocation(0),
-                 LocationSummary::kCall) {
-  const Array& arguments_descriptor =
-      Array::Handle(instance_call()->GetArgumentsDescriptor());
-  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
-
-  // Push the target onto the stack.
-  const intptr_t length = targets_.length();
-  if (!Utils::IsUint(8, length)) {
-    Unsupported(compiler);
-    UNREACHABLE();
-  }
-  bool using_ranges = false;
-  for (intptr_t i = 0; i < length; i++) {
-    if (!targets_[i].IsSingleCid()) {
-      using_ranges = true;
-      break;
-    }
-  }
-
-  if (using_ranges) {
-    __ PushPolymorphicInstanceCallByRange(
-        instance_call()->ArgumentCountWithoutTypeArgs(), length);
-  } else {
-    __ PushPolymorphicInstanceCall(
-        instance_call()->ArgumentCountWithoutTypeArgs(), length);
-  }
-  for (intptr_t i = 0; i < length; i++) {
-    const Function& target = *targets_.TargetAt(i)->target;
-
-    __ Nop(compiler->ToEmbeddableCid(targets_[i].cid_start, this));
-    if (using_ranges) {
-      __ Nop(compiler->ToEmbeddableCid(1 + targets_[i].Extent(), this));
-    }
-    __ Nop(__ AddConstant(target));
-  }
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail,
-                      0);
-
-  // Call the function.
-  __ StaticCall(instance_call()->ArgumentCount(), argdesc_kidx);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 instance_call()->token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  __ PopLocal(locs()->out(0).reg());
-}
-
-EMIT_NATIVE_CODE(LoadIndexedUnsafe, 1, Location::RegisterLocation(0)) {
-  ASSERT(base_reg() == FPREG);
-
-  ASSERT(offset_ % kWordSize == 0);
-  const intptr_t slot_offset = offset_ / kWordSize;
-  ASSERT(Utils::IsInt(8, slot_offset));
-
-  if (compiler->is_optimizing()) {
-    const Register index = locs()->in(0).reg();
-    const Register result = locs()->out(0).reg();
-    __ LoadFpRelativeSlotOpt(result, index, slot_offset);
-  } else {
-    __ LoadFpRelativeSlot(slot_offset);
-  }
-}
-
-EMIT_NATIVE_CODE(StoreIndexedUnsafe, 2, Location::RegisterLocation(0)) {
-  ASSERT(base_reg() == FPREG);
-
-  ASSERT(offset_ % kWordSize == 0);
-  const intptr_t slot_offset = offset_ / kWordSize;
-  ASSERT(Utils::IsInt(8, slot_offset));
-
-  if (compiler->is_optimizing()) {
-    const Register index = locs()->in(kIndexPos).reg();
-    const Register value = locs()->in(kValuePos).reg();
-    __ StoreFpRelativeSlotOpt(value, index, slot_offset);
-  } else {
-    __ StoreFpRelativeSlot(slot_offset);
-  }
-}
-
-EMIT_NATIVE_CODE(TailCall,
-                 1,
-                 Location::NoLocation(),
-                 LocationSummary::kNoCall,
-                 1) {
-  if (compiler->is_optimizing()) {
-    const Register arg_desc = locs()->in(0).reg();
-    const Register temp = locs()->temp(0).reg();
-    __ LoadConstant(temp, code());
-    __ TailCallOpt(arg_desc, temp);
-  } else {
-    __ PushConstant(code());
-    __ TailCall();
-  }
-}
-
-EMIT_NATIVE_CODE(Stop, 0) {
-  __ Stop(message());
-}
-
-EMIT_NATIVE_CODE(CheckStackOverflow,
-                 0,
-                 Location::NoLocation(),
-                 LocationSummary::kCall) {
-  if (compiler->ForceSlowPathForStackOverflow()) {
-    __ CheckStackAlwaysExit();
-  } else {
-    __ CheckStack();
-  }
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
-}
-
-EMIT_NATIVE_CODE(PushArgument, 1) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-  }
-}
-
-EMIT_NATIVE_CODE(LoadLocal, 0) {
-  ASSERT(!compiler->is_optimizing());
-  const intptr_t slot_index =
-      compiler::target::frame_layout.FrameSlotForVariable(&local());
-  __ Push(LocalVarIndex(0, slot_index));
-}
-
-EMIT_NATIVE_CODE(StoreLocal, 0) {
-  ASSERT(!compiler->is_optimizing());
-  const intptr_t slot_index =
-      compiler::target::frame_layout.FrameSlotForVariable(&local());
-  if (HasTemp()) {
-    __ StoreLocal(LocalVarIndex(0, slot_index));
-  } else {
-    __ PopLocal(LocalVarIndex(0, slot_index));
-  }
-}
-
-EMIT_NATIVE_CODE(LoadClassId, 1, Location::RequiresRegister()) {
-  if (compiler->is_optimizing()) {
-    __ LoadClassId(locs()->out(0).reg(), locs()->in(0).reg());
-  } else {
-    __ LoadClassIdTOS();
-  }
-}
-
-EMIT_NATIVE_CODE(Constant, 0, Location::RequiresRegister()) {
-  if (compiler->is_optimizing()) {
-    if (locs()->out(0).IsRegister()) {
-      __ LoadConstant(locs()->out(0).reg(), value());
-    }
-  } else {
-    __ PushConstant(value());
-  }
-}
-
-EMIT_NATIVE_CODE(UnboxedConstant, 0, Location::RequiresRegister()) {
-  // The register allocator drops constant definitions that have no uses.
-  if (locs()->out(0).IsInvalid()) {
-    return;
-  }
-  if (representation_ != kUnboxedDouble) {
-    Unsupported(compiler);
-    UNREACHABLE();
-  }
-  const Register result = locs()->out(0).reg();
-  if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) {
-    __ BitXor(result, result, result);
-  } else {
-    __ LoadConstant(result, value());
-    __ UnboxDouble(result, result);
-  }
-}
-
-EMIT_NATIVE_CODE(Return, 1) {
-  if (compiler->is_optimizing()) {
-    __ Return(locs()->in(0).reg());
-  } else {
-    __ ReturnTOS();
-  }
-}
-
-LocationSummary* StoreStaticFieldInstr::MakeLocationSummary(
-
-    Zone* zone,
-    bool opt) const {
-  const intptr_t kNumInputs = 1;
-  const intptr_t kNumTemps = 1;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
-  for (intptr_t i = 0; i < kNumInputs; i++) {
-    locs->set_in(i, Location::RequiresRegister());
-  }
-  for (intptr_t i = 0; i < kNumTemps; i++) {
-    locs->set_temp(i, Location::RequiresRegister());
-  }
-  return locs;
-}
-
-void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  if (compiler->is_optimizing()) {
-    __ LoadConstant(locs()->temp(0).reg(),
-                    Field::ZoneHandle(field().Original()));
-    __ StoreField(locs()->temp(0).reg(),
-                  Field::static_value_offset() / kWordSize,
-                  locs()->in(0).reg());
-  } else {
-    const intptr_t kidx = __ AddConstant(field());
-    __ StoreStaticTOS(kidx);
-  }
-}
-
-EMIT_NATIVE_CODE(LoadStaticField, 1, Location::RequiresRegister()) {
-  if (compiler->is_optimizing()) {
-    __ LoadField(locs()->out(0).reg(), locs()->in(0).reg(),
-                 Field::static_value_offset() / kWordSize);
-  } else {
-    const intptr_t kidx = __ AddConstant(StaticField());
-    __ PushStatic(kidx);
-  }
-}
-
-EMIT_NATIVE_CODE(InitStaticField,
-                 1,
-                 Location::NoLocation(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-    __ InitStaticTOS();
-  } else {
-    __ InitStaticTOS();
-  }
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
-}
-
-EMIT_NATIVE_CODE(ClosureCall,
-                 1,
-                 Location::RegisterLocation(0),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-  }
-
-  const Array& arguments_descriptor =
-      Array::ZoneHandle(GetArgumentsDescriptor());
-  const intptr_t argdesc_kidx =
-      compiler->assembler()->AddConstant(arguments_descriptor);
-  __ StaticCall(ArgumentCount(), argdesc_kidx);
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-static void EmitBranchOnCondition(FlowGraphCompiler* compiler,
-                                  Condition true_condition,
-                                  BranchLabels labels) {
-  if (true_condition == NEXT_IS_TRUE) {
-    // NEXT_IS_TRUE indicates that the preceeding test expects the true case
-    // to be in the subsequent instruction, which it skips if the test fails.
-    __ Jump(labels.true_label);
-    if (labels.fall_through != labels.false_label) {
-      // The preceeding Jump instruction will be skipped if the test fails.
-      // If we aren't falling through to the false case, then we have to do
-      // a Jump to it here.
-      __ Jump(labels.false_label);
-    }
-  } else {
-    ASSERT(true_condition == NEXT_IS_FALSE);
-    // NEXT_IS_FALSE indicates that the preceeding test has been flipped and
-    // expects the false case to be in the subsequent instruction, which it
-    // skips if the test succeeds.
-    __ Jump(labels.false_label);
-    if (labels.fall_through != labels.true_label) {
-      // The preceeding Jump instruction will be skipped if the test succeeds.
-      // If we aren't falling through to the true case, then we have to do
-      // a Jump to it here.
-      __ Jump(labels.true_label);
-    }
-  }
-}
-
-Condition StrictCompareInstr::GetNextInstructionCondition(
-    FlowGraphCompiler* compiler,
-    BranchLabels labels) {
-  return (labels.fall_through == labels.false_label) ? NEXT_IS_TRUE
-                                                     : NEXT_IS_FALSE;
-}
-
-Condition StrictCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                 BranchLabels labels) {
-  ASSERT((kind() == Token::kNE_STRICT) || (kind() == Token::kEQ_STRICT));
-
-  Token::Kind comparison;
-  Condition condition;
-  if (labels.fall_through == labels.false_label) {
-    condition = NEXT_IS_TRUE;
-    comparison = kind();
-  } else {
-    // Flip comparison to save a jump.
-    condition = NEXT_IS_FALSE;
-    comparison =
-        (kind() == Token::kEQ_STRICT) ? Token::kNE_STRICT : Token::kEQ_STRICT;
-  }
-
-  if (!compiler->is_optimizing()) {
-    const SimulatorBytecode::Opcode eq_op =
-        needs_number_check() ? SimulatorBytecode::kIfEqStrictNumTOS
-                             : SimulatorBytecode::kIfEqStrictTOS;
-    const SimulatorBytecode::Opcode ne_op =
-        needs_number_check() ? SimulatorBytecode::kIfNeStrictNumTOS
-                             : SimulatorBytecode::kIfNeStrictTOS;
-    __ Emit(comparison == Token::kEQ_STRICT ? eq_op : ne_op);
-  } else {
-    const SimulatorBytecode::Opcode eq_op =
-        needs_number_check() ? SimulatorBytecode::kIfEqStrictNum
-                             : SimulatorBytecode::kIfEqStrict;
-    const SimulatorBytecode::Opcode ne_op =
-        needs_number_check() ? SimulatorBytecode::kIfNeStrictNum
-                             : SimulatorBytecode::kIfNeStrict;
-    __ Emit(SimulatorBytecode::Encode(
-        (comparison == Token::kEQ_STRICT) ? eq_op : ne_op, locs()->in(0).reg(),
-        locs()->in(1).reg()));
-  }
-
-  if (needs_number_check() && token_pos().IsReal()) {
-    compiler->RecordSafepoint(locs());
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, deopt_id_,
-                                   token_pos());
-  }
-
-  return condition;
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(StrictCompare,
-                             2,
-                             Location::RequiresRegister(),
-                             needs_number_check() ? LocationSummary::kCall
-                                                  : LocationSummary::kNoCall)
-
-void ComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
-                                     BranchInstr* branch) {
-  BranchLabels labels = compiler->CreateBranchLabels(branch);
-  Condition true_condition = EmitComparisonCode(compiler, labels);
-  if (true_condition != INVALID_CONDITION) {
-    EmitBranchOnCondition(compiler, true_condition, labels);
-  }
-}
-
-void ComparisonInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  compiler::Label is_true, is_false;
-  BranchLabels labels = {&is_true, &is_false, &is_false};
-  Condition true_condition =
-      this->GetNextInstructionCondition(compiler, labels);
-  if (true_condition == INVALID_CONDITION || !compiler->is_optimizing() ||
-      is_true.IsLinked() || is_false.IsLinked()) {
-    Condition actual_condition = EmitComparisonCode(compiler, labels);
-    ASSERT(actual_condition == true_condition);
-    if (true_condition != INVALID_CONDITION) {
-      EmitBranchOnCondition(compiler, true_condition, labels);
-    }
-    compiler::Label done;
-    __ Bind(&is_false);
-    __ PushConstant(Bool::False());
-    __ Jump(&done);
-    __ Bind(&is_true);
-    __ PushConstant(Bool::True());
-    __ Bind(&done);
-  } else {
-    const Register result = this->locs()->out(0).reg();
-    bool next_is_true = true_condition == NEXT_IS_TRUE;
-    __ LoadConstant(result, Bool::Get(!next_is_true));
-    Condition actual_condition = EmitComparisonCode(compiler, labels);
-    ASSERT(actual_condition == true_condition);
-    // Although we have a condition to branch on, the comparison code may also
-    // have contained a direct branch to one of the labels, so they may need to
-    // be bound.
-    if (next_is_true && is_true.IsLinked()) {
-      __ Bind(&is_true);
-    } else if (!next_is_true && is_false.IsLinked()) {
-      __ Bind(&is_false);
-    }
-    // This instruction is conditionally skipped by EmitComparisonCode.
-    __ LoadConstant(result, Bool::Get(next_is_true));
-    // If the other label is linked we need to bind it and emit code that loads
-    // the correct boolean.
-    if ((next_is_true && is_false.IsLinked()) ||
-        (!next_is_true && is_true.IsLinked())) {
-      compiler::Label done;
-      __ Jump(&done);
-      __ Bind(next_is_true ? &is_false : &is_true);
-      __ LoadConstant(result, Bool::Get(!next_is_true));
-      __ Bind(&done);
-    }
-  }
-}
-
-LocationSummary* BranchInstr::MakeLocationSummary(
-
-    Zone* zone,
-    bool opt) const {
-  comparison()->InitializeLocationSummary(zone, opt);
-  if (!comparison()->HasLocs()) {
-    return NULL;
-  }
-  // Branches don't produce a result.
-  comparison()->locs()->set_out(0, Location::NoLocation());
-  return comparison()->locs();
-}
-
-void BranchInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  comparison()->EmitBranchCode(compiler, this);
-}
-
-EMIT_NATIVE_CODE(Goto, 0) {
-  if (!compiler->is_optimizing()) {
-    // Add a deoptimization descriptor for deoptimizing instructions that
-    // may be inserted before this instruction.
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, GetDeoptId(),
-                                   TokenPosition::kNoSource);
-  }
-  if (HasParallelMove()) {
-    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
-  }
-  // We can fall through if the successor is the next block in the list.
-  // Otherwise, we need a jump.
-  if (!compiler->CanFallThroughTo(successor())) {
-    __ Jump(compiler->GetJumpLabel(successor()));
-  }
-}
-
-Condition TestSmiInstr::GetNextInstructionCondition(FlowGraphCompiler* compiler,
-                                                    BranchLabels labels) {
-  ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
-  return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
-}
-
-Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                           BranchLabels labels) {
-  ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE));
-  Register left = locs()->in(0).reg();
-  Register right = locs()->in(1).reg();
-  __ TestSmi(left, right);
-  return (kind() == Token::kEQ) ? NEXT_IS_TRUE : NEXT_IS_FALSE;
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(TestSmi,
-                             2,
-                             Location::RequiresRegister(),
-                             LocationSummary::kNoCall)
-
-Condition TestCidsInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                            BranchLabels labels) {
-  ASSERT((kind() == Token::kIS) || (kind() == Token::kISNOT));
-  const Register value = locs()->in(0).reg();
-  const intptr_t true_result = (kind() == Token::kIS) ? 1 : 0;
-
-  const ZoneGrowableArray<intptr_t>& data = cid_results();
-  const intptr_t num_cases = data.length() / 2;
-  ASSERT(num_cases <= 255);
-  __ TestCids(value, num_cases);
-
-  bool result = false;
-  for (intptr_t i = 0; i < data.length(); i += 2) {
-    const intptr_t test_cid = data[i];
-    result = data[i + 1] == true_result;
-    __ Nop(result ? 1 : 0, compiler->ToEmbeddableCid(test_cid, this));
-  }
-
-  // No match found, deoptimize or default action.
-  if (CanDeoptimize()) {
-    compiler->EmitDeopt(deopt_id(), ICData::kDeoptTestCids,
-                        licm_hoisted_ ? ICData::kHoisted : 0);
-  } else {
-    // If the cid is not in the list, jump to the opposite label from the cids
-    // that are in the list.  These must be all the same (see asserts in the
-    // constructor).
-    compiler::Label* target = result ? labels.false_label : labels.true_label;
-    __ Jump(target);
-  }
-
-  return NEXT_IS_TRUE;
-}
-
-Condition TestCidsInstr::GetNextInstructionCondition(
-    FlowGraphCompiler* compiler,
-    BranchLabels labels) {
-  return NEXT_IS_TRUE;
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(TestCids,
-                             1,
-                             Location::RequiresRegister(),
-                             LocationSummary::kNoCall)
-
-EMIT_NATIVE_CODE(CreateArray,
-                 2,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    const Register length = locs()->in(kLengthPos).reg();
-    const Register type_arguments = locs()->in(kElementTypePos).reg();
-    const Register out = locs()->out(0).reg();
-    __ CreateArrayOpt(out, length, type_arguments);
-    __ Push(type_arguments);
-    __ Push(length);
-    __ CreateArrayTOS();
-    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-    __ PopLocal(out);
-  } else {
-    __ CreateArrayTOS();
-    compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
-  }
-}
-
-EMIT_NATIVE_CODE(StoreIndexed,
-                 3,
-                 Location::NoLocation(),
-                 LocationSummary::kNoCall,
-                 1) {
-  if (!compiler->is_optimizing()) {
-    ASSERT(class_id() == kArrayCid);
-    __ StoreIndexedTOS();
-    return;
-  }
-  const Register array = locs()->in(kArrayPos).reg();
-  const Register index = locs()->in(kIndexPos).reg();
-  const Register value = locs()->in(kValuePos).reg();
-  const Register temp = locs()->temp(0).reg();
-  switch (class_id()) {
-    case kArrayCid:
-      __ StoreIndexed(array, index, value);
-      break;
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-      ASSERT(index_scale() == 1);
-      if (IsExternal()) {
-        __ StoreIndexedUntaggedUint8(array, index, value);
-      } else {
-        __ StoreIndexedUint8(array, index, value);
-      }
-      break;
-    case kOneByteStringCid:
-      ASSERT(index_scale() == 1);
-      __ StoreIndexedOneByteString(array, index, value);
-      break;
-    case kTypedDataInt32ArrayCid:
-    case kTypedDataUint32ArrayCid: {
-      if (IsExternal()) {
-        if (index_scale() == 1) {
-          __ StoreIndexedUntaggedUint32(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedUntaggedUint32(array, temp, value);
-        }
-      } else {
-        if (index_scale() == 1) {
-          __ StoreIndexedUint32(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedUint32(array, temp, value);
-        }
-      }
-      break;
-    }
-    case kTypedDataFloat32ArrayCid:
-      if (IsExternal()) {
-        if (index_scale() == 1) {
-          __ StoreIndexedUntaggedFloat32(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedUntaggedFloat32(array, temp, value);
-        }
-      } else {
-        if (index_scale() == 1) {
-          __ StoreIndexedFloat32(array, index, value);
-        } else if (index_scale() == 4) {
-          __ StoreIndexed4Float32(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedFloat32(array, temp, value);
-        }
-      }
-      break;
-    case kTypedDataFloat64ArrayCid:
-      if (IsExternal()) {
-        if (index_scale() == 1) {
-          __ StoreIndexedUntaggedFloat64(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedUntaggedFloat64(array, temp, value);
-        }
-      } else {
-        if (index_scale() == 1) {
-          __ StoreIndexedFloat64(array, index, value);
-        } else if (index_scale() == 8) {
-          __ StoreIndexed8Float64(array, index, value);
-        } else {
-          __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-          __ StoreIndexedFloat64(array, temp, value);
-        }
-      }
-      break;
-    default:
-      Unsupported(compiler);
-      UNREACHABLE();
-      break;
-  }
-}
-
-EMIT_NATIVE_CODE(LoadIndexed,
-                 2,
-                 Location::RequiresRegister(),
-                 LocationSummary::kNoCall,
-                 1) {
-  if (compiler->is_optimizing()) {
-    ASSERT(compiler->is_optimizing());
-    const Register array = locs()->in(0).reg();
-    const Register index = locs()->in(1).reg();
-    const Register temp = locs()->temp(0).reg();
-    const Register result = locs()->out(0).reg();
-    switch (class_id()) {
-      case kArrayCid:
-      case kImmutableArrayCid:
-        __ LoadIndexed(result, array, index);
-        break;
-      case kTypedDataUint8ArrayCid:
-      case kTypedDataUint8ClampedArrayCid:
-      case kExternalOneByteStringCid:
-      case kExternalTypedDataUint8ArrayCid:
-      case kExternalTypedDataUint8ClampedArrayCid:
-        ASSERT(index_scale() == 1);
-        if (IsExternal()) {
-          __ LoadIndexedUntaggedUint8(result, array, index);
-        } else {
-          __ LoadIndexedUint8(result, array, index);
-        }
-        break;
-      case kTypedDataInt8ArrayCid:
-        ASSERT(index_scale() == 1);
-        if (IsExternal()) {
-          __ LoadIndexedUntaggedInt8(result, array, index);
-        } else {
-          __ LoadIndexedInt8(result, array, index);
-        }
-        break;
-      case kOneByteStringCid:
-        ASSERT(index_scale() == 1);
-        __ LoadIndexedOneByteString(result, array, index);
-        break;
-      case kTwoByteStringCid:
-        if (index_scale() != 2) {
-          // TODO(zra): Fix-up index.
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        if (IsExternal()) {
-          Unsupported(compiler);
-          UNREACHABLE();
-        }
-        __ LoadIndexedTwoByteString(result, array, index);
-        break;
-      case kTypedDataInt32ArrayCid:
-        ASSERT(representation() == kUnboxedInt32);
-        if (IsExternal()) {
-          if (index_scale() == 1) {
-            __ LoadIndexedUntaggedInt32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedUntaggedInt32(result, array, temp);
-          }
-        } else {
-          if (index_scale() == 1) {
-            __ LoadIndexedInt32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedInt32(result, array, temp);
-          }
-        }
-        break;
-      case kTypedDataUint32ArrayCid:
-        ASSERT(representation() == kUnboxedUint32);
-        if (IsExternal()) {
-          if (index_scale() == 1) {
-            __ LoadIndexedUntaggedUint32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedUntaggedUint32(result, array, temp);
-          }
-        } else {
-          if (index_scale() == 1) {
-            __ LoadIndexedUint32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedUint32(result, array, temp);
-          }
-        }
-        break;
-      case kTypedDataFloat32ArrayCid:
-        if (IsExternal()) {
-          if (index_scale() == 1) {
-            __ LoadIndexedUntaggedFloat32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedUntaggedFloat32(result, array, temp);
-          }
-        } else {
-          if (index_scale() == 1) {
-            __ LoadIndexedFloat32(result, array, index);
-          } else if (index_scale() == 4) {
-            __ LoadIndexed4Float32(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedFloat32(result, array, temp);
-          }
-        }
-        break;
-      case kTypedDataFloat64ArrayCid:
-        if (IsExternal()) {
-          if (index_scale() == 1) {
-            __ LoadIndexedUntaggedFloat64(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedUntaggedFloat64(result, array, temp);
-          }
-        } else {
-          if (index_scale() == 1) {
-            __ LoadIndexedFloat64(result, array, index);
-          } else if (index_scale() == 8) {
-            __ LoadIndexed8Float64(result, array, index);
-          } else {
-            __ ShlImm(temp, index, Utils::ShiftForPowerOfTwo(index_scale()));
-            __ LoadIndexedFloat64(result, array, temp);
-          }
-        }
-        break;
-      default:
-        Unsupported(compiler);
-        UNREACHABLE();
-        break;
-    }
-  } else {
-    switch (class_id()) {
-      case kArrayCid:
-      case kImmutableArrayCid:
-        __ LoadIndexedTOS();
-        break;
-      default:
-        Unsupported(compiler);
-        UNREACHABLE();
-        break;
-    }
-  }
-}
-
-EMIT_NATIVE_CODE(StringInterpolate,
-                 1,
-                 Location::RegisterLocation(0),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-  }
-  const intptr_t kTypeArgsLen = 0;
-  const intptr_t kArgumentCount = 1;
-  const Array& arguments_descriptor = Array::Handle(ArgumentsDescriptor::New(
-      kTypeArgsLen, kArgumentCount, Object::null_array()));
-  __ PushConstant(CallFunction());
-  const intptr_t argdesc_kidx = __ AddConstant(arguments_descriptor);
-  __ StaticCall(kArgumentCount, argdesc_kidx);
-  // Note: can't use RecordAfterCall here because
-  // StringInterpolateInstr::ArgumentCount() is 0. However
-  // internally it does a call with 1 argument which needs to
-  // be reflected in the lazy deoptimization environment.
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), kArgumentCount,
-                                  FlowGraphCompiler::kHasResult, locs());
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-void FfiCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Representation result_rep =
-      compiler::ffi::ResultHostRepresentation(signature_);
-  // TODO(36809): In 32 bit we'll need a result location as well.
-  const TypedData& signature_descriptor =
-      TypedData::Handle(compiler::ffi::FfiSignatureDescriptor::New(
-          *arg_host_locations_, result_rep));
-
-  const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor);
-
-  __ FfiCall(sigdesc_kidx);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCallHelper(token_pos(), deopt_id(), 0,
-                                  FlowGraphCompiler::kHasResult, locs());
-}
-
-EMIT_NATIVE_CODE(NativeCall,
-                 0,
-                 Location::NoLocation(),
-                 LocationSummary::kCall) {
-  SetupNative();
-
-  const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function());
-
-  NativeFunctionWrapper trampoline;
-  NativeFunction function;
-  if (link_lazily()) {
-    trampoline = &NativeEntry::BootstrapNativeCallWrapper;
-    function = reinterpret_cast<NativeFunction>(&NativeEntry::LinkNativeCall);
-  } else {
-    if (is_bootstrap_native()) {
-      trampoline = &NativeEntry::BootstrapNativeCallWrapper;
-    } else if (is_auto_scope()) {
-      trampoline = &NativeEntry::AutoScopeNativeCallWrapper;
-    } else {
-      trampoline = &NativeEntry::NoScopeNativeCallWrapper;
-    }
-    function = native_c_function();
-  }
-
-  const compiler::ExternalLabel trampoline_label(
-      reinterpret_cast<uword>(trampoline));
-  const intptr_t trampoline_kidx =
-      __ object_pool_builder().FindNativeFunctionWrapper(
-          &trampoline_label, ObjectPool::Patchability::kPatchable);
-  const compiler::ExternalLabel label(reinterpret_cast<uword>(function));
-  const intptr_t target_kidx = __ object_pool_builder().FindNativeFunction(
-      &label, ObjectPool::Patchability::kPatchable);
-  const intptr_t argc_tag_kidx =
-      __ object_pool_builder().FindImmediate(static_cast<uword>(argc_tag));
-  __ NativeCall(trampoline_kidx, target_kidx, argc_tag_kidx);
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                 token_pos());
-}
-
-EMIT_NATIVE_CODE(OneByteStringFromCharCode,
-                 1,
-                 Location::RequiresRegister(),
-                 LocationSummary::kNoCall) {
-  ASSERT(compiler->is_optimizing());
-  const Register char_code = locs()->in(0).reg();  // Char code is a smi.
-  const Register result = locs()->out(0).reg();
-  __ OneByteStringFromCharCode(result, char_code);
-}
-
-EMIT_NATIVE_CODE(StringToCharCode,
-                 1,
-                 Location::RequiresRegister(),
-                 LocationSummary::kNoCall) {
-  ASSERT(cid_ == kOneByteStringCid);
-  const Register str = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();  // Result char code is a smi.
-  __ StringToCharCode(result, str);
-}
-
-EMIT_NATIVE_CODE(AllocateObject,
-                 0,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  if (ArgumentCount() == 1) {
-    // Allocate with type arguments.
-    if (compiler->is_optimizing()) {
-      // If we're optimizing, try a streamlined fastpath.
-      const intptr_t instance_size = cls().instance_size();
-      Isolate* isolate = Isolate::Current();
-      if (Heap::IsAllocatableInNewSpace(instance_size) &&
-          !cls().TraceAllocation(isolate)) {
-        uint32_t tags = 0;
-        tags = RawObject::SizeTag::update(instance_size, tags);
-        ASSERT(cls().id() != kIllegalCid);
-        tags = RawObject::ClassIdTag::update(cls().id(), tags);
-        if (Smi::IsValid(tags)) {
-          const intptr_t tags_kidx =
-              __ AddConstant(Smi::Handle(Smi::New(tags)));
-          __ AllocateTOpt(locs()->out(0).reg(), tags_kidx);
-          __ Nop(cls().type_arguments_field_offset());
-        }
-      }
-      __ PushConstant(cls());
-      __ AllocateT();
-      compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                     token_pos());
-      compiler->RecordSafepoint(locs());
-      __ PopLocal(locs()->out(0).reg());
-    } else {
-      __ PushConstant(cls());
-      __ AllocateT();
-      compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                     token_pos());
-      compiler->RecordSafepoint(locs());
-    }
-  } else if (compiler->is_optimizing()) {
-    // If we're optimizing, try a streamlined fastpath.
-    const intptr_t instance_size = cls().instance_size();
-    Isolate* isolate = Isolate::Current();
-    if (Heap::IsAllocatableInNewSpace(instance_size) &&
-        !cls().TraceAllocation(isolate)) {
-      uword tags = 0;
-      tags = RawObject::SizeTag::update(instance_size, tags);
-      ASSERT(cls().id() != kIllegalCid);
-      tags = RawObject::ClassIdTag::update(cls().id(), tags);
-      // tags also has the initial zero hash code on 64 bit.
-      if (Smi::IsValid(tags)) {
-        const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
-        __ AllocateOpt(locs()->out(0).reg(), tags_kidx);
-      }
-    }
-    const intptr_t kidx = __ AddConstant(cls());
-    __ Allocate(kidx);
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                   token_pos());
-    compiler->RecordSafepoint(locs());
-    __ PopLocal(locs()->out(0).reg());
-  } else {
-    const intptr_t kidx = __ AddConstant(cls());
-    __ Allocate(kidx);
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                   token_pos());
-    compiler->RecordSafepoint(locs());
-  }
-}
-
-EMIT_NATIVE_CODE(StoreInstanceField, 2) {
-  ASSERT(OffsetInBytes() > 0);  // Field is finalized and points after header.
-  ASSERT(OffsetInBytes() % kWordSize == 0);
-  if (compiler->is_optimizing()) {
-    const Register value = locs()->in(1).reg();
-    const Register instance = locs()->in(0).reg();
-    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
-      __ StoreField(instance, OffsetInBytes() / kWordSize, value);
-    } else {
-      __ StoreFieldExt(instance, value);
-      __ Nop(OffsetInBytes() / kWordSize);
-    }
-  } else {
-    __ StoreFieldTOS(OffsetInBytes() / kWordSize);
-  }
-}
-
-EMIT_NATIVE_CODE(LoadField, 1, Location::RequiresRegister()) {
-  ASSERT(OffsetInBytes() % kWordSize == 0);
-  if (compiler->is_optimizing()) {
-    const Register result = locs()->out(0).reg();
-    const Register instance = locs()->in(0).reg();
-    if (Utils::IsInt(8, OffsetInBytes() / kWordSize)) {
-      __ LoadField(result, instance, OffsetInBytes() / kWordSize);
-    } else {
-      __ LoadFieldExt(result, instance);
-      __ Nop(OffsetInBytes() / kWordSize);
-    }
-  } else {
-    __ LoadFieldTOS(OffsetInBytes() / kWordSize);
-  }
-}
-
-EMIT_NATIVE_CODE(LoadUntagged, 1, Location::RequiresRegister()) {
-  const Register obj = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  if (object()->definition()->representation() == kUntagged) {
-    __ LoadUntagged(result, obj, offset() / kWordSize);
-  } else {
-    ASSERT(object()->definition()->representation() == kTagged);
-    __ LoadField(result, obj, offset() / kWordSize);
-  }
-}
-
-EMIT_NATIVE_CODE(StoreUntagged, 1, Location::RequiresRegister()) {
-  const Register obj = locs()->in(0).reg();
-  const Register value = locs()->out(0).reg();
-  const auto offset_in_words = offset() / kWordSize;
-  if (object()->definition()->representation() == kUntagged) {
-    __ StoreUntagged(obj, offset_in_words, value);
-  } else {
-    ASSERT(object()->definition()->representation() == kTagged);
-    __ StoreField(obj, offset_in_words, value);
-  }
-}
-
-EMIT_NATIVE_CODE(BooleanNegate, 1, Location::RequiresRegister()) {
-  if (compiler->is_optimizing()) {
-    __ BooleanNegate(locs()->out(0).reg(), locs()->in(0).reg());
-  } else {
-    __ BooleanNegateTOS();
-  }
-}
-
-EMIT_NATIVE_CODE(AllocateContext,
-                 0,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  ASSERT(!compiler->is_optimizing());
-  __ AllocateContext(num_context_variables());
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                 token_pos());
-}
-
-EMIT_NATIVE_CODE(AllocateUninitializedContext,
-                 0,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  ASSERT(compiler->is_optimizing());
-  __ AllocateUninitializedContext(locs()->out(0).reg(),
-                                  num_context_variables());
-  __ AllocateContext(num_context_variables());
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                 token_pos());
-  __ PopLocal(locs()->out(0).reg());
-}
-
-EMIT_NATIVE_CODE(CloneContext,
-                 1,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());
-  }
-  __ CloneContext();
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                 token_pos());
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-EMIT_NATIVE_CODE(CatchBlockEntry, 0) {
-  __ Bind(compiler->GetJumpLabel(this));
-  compiler->AddExceptionHandler(
-      catch_try_index(), try_index(), compiler->assembler()->CodeSize(),
-      is_generated(), catch_handler_types_, needs_stacktrace());
-  // On lazy deoptimization we patch the optimized code here to enter the
-  // deoptimization stub.
-  const intptr_t deopt_id = DeoptId::ToDeoptAfter(GetDeoptId());
-  if (compiler->is_optimizing()) {
-    compiler->AddDeoptIndexAtCall(deopt_id);
-  } else {
-    compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id,
-                                   TokenPosition::kNoSource);
-  }
-  if (HasParallelMove()) {
-    compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
-  }
-  __ SetFrame(compiler->StackSize());
-
-  if (!compiler->is_optimizing()) {
-    if (raw_exception_var_ != nullptr) {
-      __ MoveSpecial(
-          LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable(
-                               raw_exception_var_)),
-          Simulator::kExceptionSpecialIndex);
-    }
-    if (raw_stacktrace_var_ != nullptr) {
-      __ MoveSpecial(
-          LocalVarIndex(0, compiler::target::frame_layout.FrameSlotForVariable(
-                               raw_stacktrace_var_)),
-          Simulator::kStackTraceSpecialIndex);
-    }
-  }
-}
-
-EMIT_NATIVE_CODE(Throw, 0, Location::NoLocation(), LocationSummary::kCall) {
-  __ Throw(0);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
-  __ Trap();
-}
-
-EMIT_NATIVE_CODE(ReThrow, 0, Location::NoLocation(), LocationSummary::kCall) {
-  compiler->SetNeedsStackTrace(catch_try_index());
-  __ Throw(1);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  compiler->RecordAfterCall(this, FlowGraphCompiler::kNoResult);
-  __ Trap();
-}
-
-EMIT_NATIVE_CODE(InstantiateType,
-                 2,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());  // Instantiator type arguments.
-    __ Push(locs()->in(1).reg());  // Function type arguments.
-  }
-  __ InstantiateType(__ AddConstant(type()));
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-EMIT_NATIVE_CODE(InstantiateTypeArguments,
-                 2,
-                 Location::RequiresRegister(),
-                 LocationSummary::kCall) {
-  if (compiler->is_optimizing()) {
-    __ Push(locs()->in(0).reg());  // Instantiator type arguments.
-    __ Push(locs()->in(1).reg());  // Function type arguments.
-  }
-  __ InstantiateTypeArgumentsTOS(
-      type_arguments().IsRawWhenInstantiatedFromRaw(type_arguments().Length()),
-      __ AddConstant(type_arguments()));
-  compiler->RecordSafepoint(locs());
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
-                                 token_pos());
-  if (compiler->is_optimizing()) {
-    __ PopLocal(locs()->out(0).reg());
-  }
-}
-
-void DebugStepCheckInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#ifdef PRODUCT
-  UNREACHABLE();
-#else
-  __ DebugStep();
-  compiler->AddCurrentDescriptor(stub_kind_, deopt_id_, token_pos());
-#endif
-}
-
-void GraphEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  BlockEntryInstr* entry = normal_entry();
-  if (entry != nullptr) {
-    if (!compiler->CanFallThroughTo(entry)) {
-      FATAL("Checked function entry must have no offset");
-    }
-  } else {
-    entry = osr_entry();
-    if (!compiler->CanFallThroughTo(entry)) {
-      __ Jump(compiler->GetJumpLabel(entry));
-    }
-  }
-}
-
-LocationSummary* Instruction::MakeCallSummary(Zone* zone) {
-  LocationSummary* result =
-      new (zone) LocationSummary(zone, 0, 0, LocationSummary::kCall);
-  // TODO(vegorov) support allocating out registers for calls.
-  // Currently we require them to be fixed.
-  ASSERT(0 < kMaxNumberOfFixedInputRegistersUsedByIL);
-  result->set_out(0, Location::RegisterLocation(0));
-  return result;
-}
-
-Representation LoadIndexedInstr::representation() const {
-  switch (class_id_) {
-    case kArrayCid:
-    case kImmutableArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTwoByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-
-    // These are unsupported on DBC and will cause a bailout during
-    // EmitNativeCode.
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-    case kExternalTwoByteStringCid:
-      return kUnboxedIntPtr;
-
-    default:
-      UNREACHABLE();
-      return kTagged;
-  }
-}
-
-Representation StoreIndexedInstr::RequiredInputRepresentation(
-    intptr_t idx) const {
-  // Array can be a Dart object or a pointer to external data.
-  if (idx == 0) {
-    return kNoRepresentation;  // Flexible input representation.
-  }
-  if (idx == 1) {
-    return kTagged;  // Index is a smi.
-  }
-  ASSERT(idx == 2);
-  switch (class_id_) {
-    case kArrayCid:
-      return kTagged;
-    case kOneByteStringCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalOneByteStringCid:
-    case kExternalTypedDataUint8ArrayCid:
-      return kUnboxedIntPtr;
-    case kTypedDataInt32ArrayCid:
-      return kUnboxedInt32;
-    case kTypedDataUint32ArrayCid:
-      return kUnboxedUint32;
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-      return kUnboxedDouble;
-    case kTypedDataFloat32x4ArrayCid:
-      return kUnboxedFloat32x4;
-    case kTypedDataInt32x4ArrayCid:
-      return kUnboxedInt32x4;
-    case kTypedDataFloat64x2ArrayCid:
-      return kUnboxedFloat64x2;
-
-    // These are unsupported on DBC and will cause a bailout during
-    // EmitNativeCode.
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-      return kUnboxedIntPtr;
-    default:
-      UNREACHABLE();
-      return kTagged;
-  }
-}
-
-void Environment::DropArguments(intptr_t argc) {
-#if defined(DEBUG)
-  // Check that we are in the backend - register allocation has been run.
-  ASSERT((Length() == 0) || (locations_ != nullptr));
-
-  // Check that we are only dropping a valid number of instructions from the
-  // environment.
-  ASSERT(argc <= values_.length());
-#endif
-  values_.TruncateTo(values_.length() - argc);
-}
-
-EMIT_NATIVE_CODE(CheckSmi, 1) {
-  __ CheckSmi(locs()->in(0).reg());
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckSmi,
-                      licm_hoisted_ ? ICData::kHoisted : 0);
-}
-
-EMIT_NATIVE_CODE(CheckEitherNonSmi, 2) {
-  const Register left = locs()->in(0).reg();
-  const Register right = locs()->in(1).reg();
-  __ CheckEitherNonSmi(left, right);
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinaryDoubleOp,
-                      licm_hoisted_ ? ICData::kHoisted : 0);
-}
-
-EMIT_NATIVE_CODE(CheckClassId, 1) {
-  if (cids_.IsSingleCid()) {
-    __ CheckClassId(locs()->in(0).reg(),
-                    compiler->ToEmbeddableCid(cids_.cid_start, this));
-  } else {
-    __ CheckClassIdRange(locs()->in(0).reg(),
-                         compiler->ToEmbeddableCid(cids_.cid_start, this));
-    __ Nop(compiler->ToEmbeddableCid(cids_.Extent(), this));
-  }
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass);
-}
-
-EMIT_NATIVE_CODE(CheckClass, 1) {
-  const Register value = locs()->in(0).reg();
-  if (IsNullCheck()) {
-    ASSERT(IsDeoptIfNull() || IsDeoptIfNotNull());
-    if (IsDeoptIfNull()) {
-      __ IfEqNull(value);
-    } else {
-      __ IfNeNull(value);
-    }
-  } else {
-    ASSERT(!cids_.IsMonomorphic() || !cids_.HasClassId(kSmiCid));
-    const intptr_t may_be_smi = cids_.HasClassId(kSmiCid) ? 1 : 0;
-    bool is_bit_test = false;
-    intptr_t cid_mask = 0;
-    if (IsBitTest()) {
-      cid_mask = ComputeCidMask();
-      is_bit_test = Smi::IsValid(cid_mask);
-    }
-    if (is_bit_test) {
-      intptr_t min = cids_.ComputeLowestCid();
-      __ CheckBitTest(value, may_be_smi);
-      __ Nop(compiler->ToEmbeddableCid(min, this));
-      __ Nop(__ AddConstant(Smi::Handle(Smi::New(cid_mask))));
-    } else {
-      bool using_ranges = false;
-      int smi_adjustment = 0;
-      int length = cids_.length();
-      for (intptr_t i = 0; i < length; i++) {
-        if (!cids_[i].IsSingleCid()) {
-          using_ranges = true;
-        } else if (cids_[i].cid_start == kSmiCid) {
-          ASSERT(cids_[i].cid_end == kSmiCid);  // We are in the else clause.
-          ASSERT(smi_adjustment == 0);
-          smi_adjustment = 1;
-        }
-      }
-
-      if (!Utils::IsUint(8, length)) {
-        Unsupported(compiler);
-        UNREACHABLE();
-      }
-      if (using_ranges) {
-        __ CheckCidsByRange(value, may_be_smi, (length - smi_adjustment) * 2);
-      } else {
-        __ CheckCids(value, may_be_smi, length - smi_adjustment);
-      }
-      for (intptr_t i = 0; i < length; i++) {
-        intptr_t cid_start = cids_[i].cid_start;
-        intptr_t cid_end = cids_[i].cid_end;
-        if (cid_start == kSmiCid && cid_end == kSmiCid) {
-          ASSERT(smi_adjustment == 1);
-          continue;
-        }
-        __ Nop(compiler->ToEmbeddableCid(cid_start, this));
-        if (using_ranges) {
-          __ Nop(compiler->ToEmbeddableCid(1 + cids_[i].Extent(), this));
-        }
-      }
-    }
-  }
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckClass,
-                      licm_hoisted_ ? ICData::kHoisted : 0);
-}
-
-EMIT_NATIVE_CODE(CheckNull, 1) {
-  if (compiler->is_optimizing()) {
-    const Register value = locs()->in(0).reg();
-    __ IfEqNull(value);
-  } else {
-    __ IfEqNullTOS();
-  }
-  __ NullError();
-  CheckNullInstr::AddMetadataForRuntimeCall(this, compiler);
-}
-
-EMIT_NATIVE_CODE(BinarySmiOp, 2, Location::RequiresRegister()) {
-  if (compiler->is_optimizing()) {
-    const Register left = locs()->in(0).reg();
-    const Register right = locs()->in(1).reg();
-    const Register out = locs()->out(0).reg();
-    const bool can_deopt = CanDeoptimize();
-    bool needs_nop = false;
-    switch (op_kind()) {
-      case Token::kADD:
-        __ Add(out, left, right);
-        needs_nop = true;
-        break;
-      case Token::kSUB:
-        __ Sub(out, left, right);
-        needs_nop = true;
-        break;
-      case Token::kMUL:
-        __ Mul(out, left, right);
-        needs_nop = true;
-        break;
-      case Token::kTRUNCDIV:
-        ASSERT(can_deopt);
-        __ Div(out, left, right);
-        break;
-      case Token::kBIT_AND:
-        ASSERT(!can_deopt);
-        __ BitAnd(out, left, right);
-        break;
-      case Token::kBIT_OR:
-        ASSERT(!can_deopt);
-        __ BitOr(out, left, right);
-        break;
-      case Token::kBIT_XOR:
-        ASSERT(!can_deopt);
-        __ BitXor(out, left, right);
-        break;
-      case Token::kMOD:
-        __ Mod(out, left, right);
-        needs_nop = true;
-        break;
-      case Token::kSHR:
-        __ Shr(out, left, right);
-        needs_nop = true;
-        break;
-      case Token::kSHL:
-        __ Shl(out, left, right);
-        needs_nop = true;
-        break;
-      default:
-        UNREACHABLE();
-    }
-    if (can_deopt) {
-      compiler->EmitDeopt(deopt_id(), ICData::kDeoptBinarySmiOp);
-    } else if (needs_nop) {
-      __ Nop(0);
-    }
-  } else {
-    switch (op_kind()) {
-      case Token::kADD:
-        __ SmiAddTOS();
-        break;
-      case Token::kSUB:
-        __ SmiSubTOS();
-        break;
-      case Token::kMUL:
-        __ SmiMulTOS();
-        break;
-      case Token::kBIT_AND:
-        __ SmiBitAndTOS();
-        break;
-      default:
-        UNIMPLEMENTED();
-    }
-  }
-}
-
-EMIT_NATIVE_CODE(UnarySmiOp, 1, Location::RequiresRegister()) {
-  switch (op_kind()) {
-    case Token::kNEGATE: {
-      __ Neg(locs()->out(0).reg(), locs()->in(0).reg());
-      compiler->EmitDeopt(deopt_id(), ICData::kDeoptUnaryOp);
-      break;
-    }
-    case Token::kBIT_NOT:
-      __ BitNot(locs()->out(0).reg(), locs()->in(0).reg());
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
-}
-
-void BoxInstr::EmitAllocateBox(FlowGraphCompiler* compiler) {
-  const Register out = locs()->out(0).reg();
-  const Class& box_class = compiler->BoxClassFor(from_representation());
-  const intptr_t instance_size = box_class.instance_size();
-  Isolate* isolate = Isolate::Current();
-  ASSERT(Heap::IsAllocatableInNewSpace(instance_size));
-  if (!box_class.TraceAllocation(isolate)) {
-    uword tags = 0;
-    tags = RawObject::SizeTag::update(instance_size, tags);
-    tags = RawObject::ClassIdTag::update(box_class.id(), tags);
-    // tags also has the initial zero hash code on 64 bit.
-    if (Smi::IsValid(tags)) {
-      const intptr_t tags_kidx = __ AddConstant(Smi::Handle(Smi::New(tags)));
-      __ AllocateOpt(out, tags_kidx);
-    }
-  }
-  const intptr_t kidx = __ AddConstant(box_class);
-  __ Allocate(kidx);
-  compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, DeoptId::kNone,
-                                 token_pos());
-  compiler->RecordSafepoint(locs());
-  __ PopLocal(out);
-}
-
-EMIT_NATIVE_CODE(Box, 1, Location::RequiresRegister(), LocationSummary::kCall) {
-  ASSERT(from_representation() == kUnboxedDouble ||
-         from_representation() == kUnboxedFloat);
-  const Register value = locs()->in(0).reg();
-  const Register out = locs()->out(0).reg();
-  if (from_representation() == kUnboxedFloat) {
-    __ FloatToDouble(value, value);
-  }
-  EmitAllocateBox(compiler);
-  __ WriteIntoDouble(out, value);
-}
-
-EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
-  if (representation() == kUnboxedInt64) {
-    EmitLoadInt64FromBoxOrSmi(compiler);
-    return;
-  }
-  ASSERT(representation() == kUnboxedDouble ||
-         representation() == kUnboxedFloat);
-  const intptr_t value_cid = value()->Type()->ToCid();
-  const intptr_t box_cid = BoxCid();
-  const Register box = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  if (value_cid == box_cid ||
-      (speculative_mode() == kNotSpeculative && value_cid != kSmiCid)) {
-    __ UnboxDouble(result, box);
-  } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
-    __ SmiToDouble(result, box);
-  } else if ((value()->Type()->ToNullableCid() == box_cid) &&
-             value()->Type()->is_nullable()) {
-    __ IfEqNull(box);
-    ASSERT(CanDeoptimize());
-    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
-    __ UnboxDouble(result, box);
-  } else {
-    __ CheckedUnboxDouble(result, box);
-    ASSERT(CanDeoptimize());
-    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptCheckClass);
-  }
-  if (representation() == kUnboxedFloat) {
-    __ DoubleToFloat(result, result);
-  }
-}
-
-EMIT_NATIVE_CODE(UnboxInteger32, 1, Location::RequiresRegister()) {
-#if defined(ARCH_IS_64_BIT)
-  const Register out = locs()->out(0).reg();
-  const Register value = locs()->in(0).reg();
-  const bool may_truncate = is_truncating() || !CanDeoptimize();
-  __ UnboxInt32(out, value, may_truncate);
-  if (CanDeoptimize()) {
-    compiler->EmitDeopt(GetDeoptId(), ICData::kDeoptUnboxInteger);
-  } else {
-    __ Nop(0);
-  }
-#else
-  Unsupported(compiler);
-  UNREACHABLE();
-#endif  // defined(ARCH_IS_64_BIT)
-}
-
-EMIT_NATIVE_CODE(BoxInteger32, 1, Location::RequiresRegister()) {
-#if defined(ARCH_IS_64_BIT)
-  const Register out = locs()->out(0).reg();
-  const Register value = locs()->in(0).reg();
-  if (from_representation() == kUnboxedInt32) {
-    __ BoxInt32(out, value);
-  } else {
-    ASSERT(from_representation() == kUnboxedUint32);
-    __ BoxUint32(out, value);
-  }
-#else
-  Unsupported(compiler);
-  UNREACHABLE();
-#endif  // defined(ARCH_IS_64_BIT)
-}
-
-EMIT_NATIVE_CODE(BoxInt64, 1, Location::RequiresRegister()) {
-#if defined(ARCH_IS_64_BIT)
-  compiler::Label done;
-  const Register value = locs()->in(0).reg();
-  const Register out = locs()->out(0).reg();
-  __ BoxInt64(out, value);
-  __ Jump(&done);
-  EmitAllocateBox(compiler);
-  __ WriteIntoMint(out, value);
-  __ Bind(&done);
-#else
-  Unsupported(compiler);
-  UNREACHABLE();
-#endif  // defined(ARCH_IS_64_BIT)
-}
-
-void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
-#if defined(ARCH_IS_64_BIT)
-  const Register out = locs()->out(0).reg();
-  const Register value = locs()->in(0).reg();
-  __ UnboxInt64(out, value);
-#else
-  Unsupported(compiler);
-  UNREACHABLE();
-#endif  // defined(ARCH_IS_64_BIT)
-}
-
-EMIT_NATIVE_CODE(UnboxedWidthExtender, 1, Location::RequiresRegister()) {
-  const Register out = locs()->out(0).reg();
-  const Register value = locs()->in(0).reg();
-  __ UnboxedWidthExtender(out, value, from_representation());
-}
-
-EMIT_NATIVE_CODE(DoubleToSmi, 1, Location::RequiresRegister()) {
-  const Register value = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ DoubleToSmi(result, value);
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptDoubleToSmi);
-}
-
-EMIT_NATIVE_CODE(SmiToDouble, 1, Location::RequiresRegister()) {
-  const Register value = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ SmiToDouble(result, value);
-}
-
-EMIT_NATIVE_CODE(BinaryDoubleOp, 2, Location::RequiresRegister()) {
-  const Register left = locs()->in(0).reg();
-  const Register right = locs()->in(1).reg();
-  const Register result = locs()->out(0).reg();
-  switch (op_kind()) {
-    case Token::kADD:
-      __ DAdd(result, left, right);
-      break;
-    case Token::kSUB:
-      __ DSub(result, left, right);
-      break;
-    case Token::kMUL:
-      __ DMul(result, left, right);
-      break;
-    case Token::kDIV:
-      __ DDiv(result, left, right);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-Condition DoubleTestOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                BranchLabels labels) {
-  ASSERT(compiler->is_optimizing());
-  const Register value = locs()->in(0).reg();
-  switch (op_kind()) {
-    case MethodRecognizer::kDouble_getIsNaN:
-      __ DoubleIsNaN(value);
-      break;
-    case MethodRecognizer::kDouble_getIsInfinite:
-      __ DoubleIsInfinite(value);
-      break;
-    default:
-      UNREACHABLE();
-  }
-  const bool is_negated = kind() != Token::kEQ;
-  return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
-}
-
-Condition DoubleTestOpInstr::GetNextInstructionCondition(
-    FlowGraphCompiler* compiler,
-    BranchLabels labels) {
-  const bool is_negated = kind() != Token::kEQ;
-  return is_negated ? NEXT_IS_FALSE : NEXT_IS_TRUE;
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(DoubleTestOp, 1, Location::RequiresRegister())
-
-EMIT_NATIVE_CODE(UnaryDoubleOp, 1, Location::RequiresRegister()) {
-  const Register value = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ DNeg(result, value);
-}
-
-EMIT_NATIVE_CODE(MathUnary, 1, Location::RequiresRegister()) {
-  const Register value = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  if (kind() == MathUnaryInstr::kSqrt) {
-    __ DSqrt(result, value);
-  } else if (kind() == MathUnaryInstr::kDoubleSquare) {
-    __ DMul(result, value, value);
-  } else {
-    Unsupported(compiler);
-    UNREACHABLE();
-  }
-}
-
-EMIT_NATIVE_CODE(DoubleToDouble, 1, Location::RequiresRegister()) {
-  const Register in = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  switch (recognized_kind()) {
-    case MethodRecognizer::kDoubleTruncate:
-      __ DTruncate(result, in);
-      break;
-    case MethodRecognizer::kDoubleFloor:
-      __ DFloor(result, in);
-      break;
-    case MethodRecognizer::kDoubleCeil:
-      __ DCeil(result, in);
-      break;
-    default:
-      UNREACHABLE();
-  }
-}
-
-EMIT_NATIVE_CODE(DoubleToFloat, 1, Location::RequiresRegister()) {
-  const Register in = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ DoubleToFloat(result, in);
-}
-
-EMIT_NATIVE_CODE(FloatToDouble, 1, Location::RequiresRegister()) {
-  const Register in = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  __ FloatToDouble(result, in);
-}
-
-EMIT_NATIVE_CODE(InvokeMathCFunction,
-                 InputCount(),
-                 Location::RequiresRegister()) {
-  const Register left = locs()->in(0).reg();
-  const Register result = locs()->out(0).reg();
-  if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
-    const Register right = locs()->in(1).reg();
-    __ DPow(result, left, right);
-  } else if (recognized_kind() == MethodRecognizer::kDoubleMod) {
-    const Register right = locs()->in(1).reg();
-    __ DMod(result, left, right);
-  } else if (recognized_kind() == MethodRecognizer::kMathSin) {
-    __ DSin(result, left);
-  } else if (recognized_kind() == MethodRecognizer::kMathCos) {
-    __ DCos(result, left);
-  } else {
-    Unsupported(compiler);
-    UNREACHABLE();
-  }
-}
-
-EMIT_NATIVE_CODE(MathMinMax, 2, Location::RequiresRegister()) {
-  ASSERT((op_kind() == MethodRecognizer::kMathMin) ||
-         (op_kind() == MethodRecognizer::kMathMax));
-  const Register left = locs()->in(0).reg();
-  const Register right = locs()->in(1).reg();
-  const Register result = locs()->out(0).reg();
-  if (result_cid() == kDoubleCid) {
-    if (op_kind() == MethodRecognizer::kMathMin) {
-      __ DMin(result, left, right);
-    } else {
-      __ DMax(result, left, right);
-    }
-  } else {
-    ASSERT(result_cid() == kSmiCid);
-    if (op_kind() == MethodRecognizer::kMathMin) {
-      __ Min(result, left, right);
-    } else {
-      __ Max(result, left, right);
-    }
-  }
-}
-
-static SimulatorBytecode::Opcode OpcodeForSmiCondition(Token::Kind kind) {
-  switch (kind) {
-    case Token::kEQ:
-      return SimulatorBytecode::kIfEqStrict;
-    case Token::kNE:
-      return SimulatorBytecode::kIfNeStrict;
-    case Token::kLT:
-      return SimulatorBytecode::kIfLt;
-    case Token::kGT:
-      return SimulatorBytecode::kIfGt;
-    case Token::kLTE:
-      return SimulatorBytecode::kIfLe;
-    case Token::kGTE:
-      return SimulatorBytecode::kIfGe;
-    default:
-      UNREACHABLE();
-      return SimulatorBytecode::kTrap;
-  }
-}
-
-static SimulatorBytecode::Opcode OpcodeForDoubleCondition(Token::Kind kind) {
-  switch (kind) {
-    case Token::kEQ:
-      return SimulatorBytecode::kIfDEq;
-    case Token::kNE:
-      return SimulatorBytecode::kIfDNe;
-    case Token::kLT:
-      return SimulatorBytecode::kIfDLt;
-    case Token::kGT:
-      return SimulatorBytecode::kIfDGt;
-    case Token::kLTE:
-      return SimulatorBytecode::kIfDLe;
-    case Token::kGTE:
-      return SimulatorBytecode::kIfDGe;
-    default:
-      UNREACHABLE();
-      return SimulatorBytecode::kTrap;
-  }
-}
-
-static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
-                                     LocationSummary* locs,
-                                     Token::Kind kind,
-                                     BranchLabels labels) {
-  Token::Kind comparison = kind;
-  Condition condition = NEXT_IS_TRUE;
-  if (labels.fall_through != labels.false_label) {
-    // If we aren't falling through to the false label, we can save a Jump
-    // instruction in the case that the true case is the fall through by
-    // negating the sense of the test such that the instruction following the
-    // test is the Jump to the false label.  In the case where both labels are
-    // null we don't negate the sense of the test.
-    condition = NEXT_IS_FALSE;
-    comparison = Token::NegateComparison(kind);
-  }
-  if (compiler->is_optimizing()) {
-    const Register left = locs->in(0).reg();
-    const Register right = locs->in(1).reg();
-    __ Emit(SimulatorBytecode::Encode(OpcodeForSmiCondition(comparison), left,
-                                      right));
-    return condition;
-  } else {
-    switch (kind) {
-      case Token::kEQ:
-        __ IfEqStrictTOS();
-        break;
-      case Token::kNE:
-        __ IfNeStrictTOS();
-        break;
-      case Token::kLT:
-        __ IfSmiLtTOS();
-        break;
-      case Token::kLTE:
-        __ IfSmiLeTOS();
-        break;
-      case Token::kGT:
-        __ IfSmiGtTOS();
-        break;
-      case Token::kGTE:
-        __ IfSmiGeTOS();
-        break;
-      default:
-        UNIMPLEMENTED();
-    }
-    return condition;
-  }
-}
-
-static Condition EmitDoubleComparisonOp(FlowGraphCompiler* compiler,
-                                        LocationSummary* locs,
-                                        Token::Kind kind) {
-  const Register left = locs->in(0).reg();
-  const Register right = locs->in(1).reg();
-  Token::Kind comparison = kind;
-  // For double comparisons we can't flip the condition like with smi
-  // comparisons because of NaN which will compare false for all except !=
-  // operations.
-  // TODO(fschneider): Change the block order instead in DBC so that the
-  // false block in always the fall-through block.
-  Condition condition = NEXT_IS_TRUE;
-  __ Emit(SimulatorBytecode::Encode(OpcodeForDoubleCondition(comparison), left,
-                                    right));
-  return condition;
-}
-
-Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                   BranchLabels labels) {
-  if (operation_cid() == kSmiCid) {
-    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
-  } else {
-    ASSERT(operation_cid() == kDoubleCid);
-    return EmitDoubleComparisonOp(compiler, locs(), kind());
-  }
-}
-
-Condition EqualityCompareInstr::GetNextInstructionCondition(
-    FlowGraphCompiler* compiler,
-    BranchLabels labels) {
-  if (operation_cid() == kSmiCid) {
-    return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
-                                                       : NEXT_IS_TRUE;
-  } else {
-    ASSERT(operation_cid() == kDoubleCid);
-    return NEXT_IS_TRUE;
-  }
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(EqualityCompare, 2, Location::RequiresRegister());
-
-Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
-                                                BranchLabels labels) {
-  if (operation_cid() == kSmiCid) {
-    return EmitSmiComparisonOp(compiler, locs(), kind(), labels);
-  } else {
-    ASSERT(operation_cid() == kDoubleCid);
-    return EmitDoubleComparisonOp(compiler, locs(), kind());
-  }
-}
-
-Condition RelationalOpInstr::GetNextInstructionCondition(
-    FlowGraphCompiler* compiler,
-    BranchLabels labels) {
-  if (operation_cid() == kSmiCid) {
-    return (labels.fall_through != labels.false_label) ? NEXT_IS_FALSE
-                                                       : NEXT_IS_TRUE;
-  } else {
-    ASSERT(operation_cid() == kDoubleCid);
-    return NEXT_IS_TRUE;
-  }
-}
-
-DEFINE_MAKE_LOCATION_SUMMARY(RelationalOp, 2, Location::RequiresRegister())
-
-EMIT_NATIVE_CODE(CheckArrayBound, 2) {
-  const Register length = locs()->in(kLengthPos).reg();
-  const Register index = locs()->in(kIndexPos).reg();
-  const intptr_t index_cid = this->index()->Type()->ToCid();
-  if (index_cid != kSmiCid) {
-    __ CheckSmi(index);
-    compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound,
-                        (generalized_ ? ICData::kGeneralized : 0) |
-                            (licm_hoisted_ ? ICData::kHoisted : 0));
-  }
-  __ IfULe(length, index);
-  compiler->EmitDeopt(deopt_id(), ICData::kDeoptCheckArrayBound,
-                      (generalized_ ? ICData::kGeneralized : 0) |
-                          (licm_hoisted_ ? ICData::kHoisted : 0));
-}
-
-void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  UNREACHABLE();
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index d66ce30..47d515a 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -7,8 +7,10 @@
 #include "vm/compiler/backend/il_deserializer.h"
 
 #include "vm/compiler/backend/il_serializer.h"
+#include "vm/compiler/backend/range_analysis.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/flags.h"
+#include "vm/json_writer.h"
 #include "vm/os.h"
 
 namespace dart {
@@ -40,11 +42,34 @@
   SExpression* error_sexp = nullptr;
 };
 
-static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
-  THR_Print("Results of round trip serialization: {\"function\":\"%s\"",
-            results.function.ToFullyQualifiedCString());
-  THR_Print(",\"success\":%s", results.success ? "true" : "false");
+// Return a textual description of how to find the sub-expression [to_find]
+// inside a [root] S-Expression.
+static const char* GetSExpressionPosition(Zone* zone,
+                                          SExpression* root,
+                                          SExpression* to_find) {
+  // The S-expression to find _is_ the root, so no description is needed.
+  if (root == to_find) return "";
+  // The S-expression to find cannot be a sub-expression of the given root,
+  // so return nullptr to signal this.
+  if (!root->IsList()) return nullptr;
+  auto const list = root->AsList();
+  for (intptr_t i = 0, n = list->Length(); i < n; i++) {
+    if (auto const str = GetSExpressionPosition(zone, list->At(i), to_find)) {
+      return OS::SCreate(zone, "element %" Pd "%s%s", i,
+                         *str == '\0' ? "" : " -> ", str);
+    }
+  }
+  auto it = list->ExtraIterator();
+  while (auto kv = it.Next()) {
+    if (auto const str = GetSExpressionPosition(zone, kv->value, to_find)) {
+      return OS::SCreate(zone, "label %s%s%s", kv->key,
+                         *str == '\0' ? "" : " -> ", str);
+    }
+  }
+  return nullptr;
+}
 
+static void PrintRoundTripResults(Zone* zone, const RoundTripResults& results) {
   // A few checks to make sure we'll print out enough info. First, if there are
   // no unhandled instructions, then we should have serialized the flow graph.
   ASSERT(!results.unhandled.is_empty() || results.serialized != nullptr);
@@ -53,6 +78,12 @@
   ASSERT(results.success || !results.unhandled.is_empty() ||
          (results.error_message != nullptr && results.error_sexp != nullptr));
 
+  JSONWriter js;
+
+  js.OpenObject();
+  js.PrintProperty("function", results.function.ToFullyQualifiedCString());
+  js.PrintPropertyBool("success", results.success);
+
   if (!results.unhandled.is_empty()) {
     CStringMap<intptr_t> count_map(zone);
     for (auto inst : results.unhandled) {
@@ -60,44 +91,38 @@
       auto const old_count = count_map.LookupValue(name);
       count_map.Update({name, old_count + 1});
     }
-    THR_Print(",\"unhandled\":{");
+
     auto count_it = count_map.GetIterator();
-    auto first_kv = count_it.Next();
-    THR_Print("\"%s\":%" Pd "", first_kv->key, first_kv->value);
+    js.OpenObject("unhandled");
     while (auto kv = count_it.Next()) {
-      THR_Print(",\"%s\":%" Pd "", kv->key, kv->value);
+      js.PrintProperty64(kv->key, kv->value);
     }
-    THR_Print("}");
+    js.CloseObject();
   }
+
   if (results.serialized != nullptr) {
     TextBuffer buf(1000);
     results.serialized->SerializeTo(zone, &buf, "");
-    // Now that the S-expression has been serialized to the TextBuffer, we now
-    // want to take that version and escape it since we will use it as the
-    // contents of a JSON string. Thankfully, escaping can be done via
-    // TextBuffer::AddEscapedString, so we steal the current buffer and then
-    // re-print it in escaped form into the now-cleared buffer.
-    char* const unescaped_sexp = buf.Steal();
-    buf.AddEscapedString(unescaped_sexp);
-    free(unescaped_sexp);
-    THR_Print(",\"serialized\":\"%s\"", buf.buf());
+    js.PrintProperty("serialized", buf.buf());
   }
+
   if (results.error_message != nullptr) {
-    TextBuffer buf(1000);
+    js.OpenObject("error");
+    js.PrintProperty("message", results.error_message);
+
     ASSERT(results.error_sexp != nullptr);
-    // Same serialized S-expression juggling as in the results.serialized case.
-    // We also escape the error message, in case it included quotes.
-    buf.AddEscapedString(results.error_message);
-    char* const escaped_message = buf.Steal();
+    TextBuffer buf(1000);
     results.error_sexp->SerializeTo(zone, &buf, "");
-    char* const unescaped_sexp = buf.Steal();
-    buf.AddEscapedString(unescaped_sexp);
-    free(unescaped_sexp);
-    THR_Print(",\"error\":{\"message\":\"%s\",\"expression\":\"%s\"}",
-              escaped_message, buf.buf());
-    free(escaped_message);
+    js.PrintProperty("expression", buf.buf());
+
+    auto const sexp_position =
+        GetSExpressionPosition(zone, results.serialized, results.error_sexp);
+    js.PrintProperty("path", sexp_position);
+    js.CloseObject();
   }
-  THR_Print("}\n");
+
+  js.CloseObject();
+  THR_Print("Results of round trip serialization: %s\n", js.buffer()->buf());
 }
 
 void FlowGraphDeserializer::RoundTripSerialization(CompilerPassState* state) {
@@ -149,6 +174,10 @@
       if (FLAG_trace_round_trip_serialization) {
         THR_Print("Failure during deserialization: %s\n", d.error_message());
         THR_Print("At S-expression %s\n", d.error_sexp()->ToCString(zone));
+        if (auto const pos = GetSExpressionPosition(zone, results.serialized,
+                                                    d.error_sexp())) {
+          THR_Print("Path from root: %s\n", pos);
+        }
       }
       results.error_message = d.error_message();
       results.error_sexp = d.error_sexp();
@@ -661,14 +690,7 @@
   if (pos < 2) return false;
   Instruction* last_inst = current_block_;
   for (intptr_t i = pos, n = list->Length(); i < n; i++) {
-    auto const entry = CheckTaggedList(Retrieve(list, i));
-    if (entry == nullptr) return false;
-    Instruction* inst = nullptr;
-    if (entry->Tag()->Equals("def")) {
-      inst = ParseDefinition(entry);
-    } else {
-      inst = ParseInstruction(entry);
-    }
+    auto const inst = ParseInstruction(CheckTaggedList(Retrieve(list, i)));
     if (inst == nullptr) return false;
     last_inst = last_inst->AppendInstruction(inst);
   }
@@ -690,10 +712,29 @@
 
 bool FlowGraphDeserializer::ParseDefinitionWithParsedBody(SExpList* list,
                                                           Definition* def) {
-  intptr_t index;
+  if (auto const type_sexp =
+          CheckTaggedList(list->ExtraLookupValue("type"), "CompileType")) {
+    CompileType* typ = ParseCompileType(type_sexp);
+    if (typ == nullptr) return false;
+    def->UpdateType(*typ);
+  }
+
+  if (auto const range_sexp =
+          CheckTaggedList(list->ExtraLookupValue("range"), "Range")) {
+    Range range;
+    if (!ParseRange(range_sexp, &range)) return false;
+    def->set_range(range);
+  }
+
   auto const name_sexp = CheckSymbol(Retrieve(list, 1));
   if (name_sexp == nullptr) return false;
 
+  // If the name is "_", this is a subclass of Definition where there's no real
+  // "result" that's being bound. We were just here to add Definition-specific
+  // extra info.
+  if (name_sexp->Equals("_")) return true;
+
+  intptr_t index;
   if (ParseSSATemp(name_sexp, &index)) {
     if (definition_map_.HasKey(index)) {
       StoreError(list, "multiple definitions for the same SSA index");
@@ -707,21 +748,16 @@
     return false;
   }
 
-  if (auto const type_sexp =
-          CheckTaggedList(list->ExtraLookupValue("type"), "CompileType")) {
-    CompileType* typ = ParseCompileType(type_sexp);
-    if (typ == nullptr) return false;
-    def->UpdateType(*typ);
-  }
-
   definition_map_.Insert(index, def);
   if (!FixPendingValues(index, def)) return false;
   return true;
 }
 
 Definition* FlowGraphDeserializer::ParseDefinition(SExpList* list) {
+  if (list == nullptr) return nullptr;
+  ASSERT(list->Tag() != nullptr && list->Tag()->Equals("def"));
   auto const inst_sexp = CheckTaggedList(Retrieve(list, 2));
-  Instruction* const inst = ParseInstruction(inst_sexp);
+  auto const inst = ParseInstruction(inst_sexp);
   if (inst == nullptr) return nullptr;
   if (auto const def = inst->AsDefinition()) {
     if (!ParseDefinitionWithParsedBody(list, def)) return nullptr;
@@ -735,6 +771,7 @@
 Instruction* FlowGraphDeserializer::ParseInstruction(SExpList* list) {
   if (list == nullptr) return nullptr;
   auto const tag = list->Tag();
+  if (tag->Equals("def")) return ParseDefinition(list);
 
   intptr_t deopt_id = DeoptId::kNone;
   if (auto const deopt_int = CheckInteger(list->ExtraLookupValue("deopt_id"))) {
@@ -772,6 +809,10 @@
 
   if (inst == nullptr) return nullptr;
   if (env != nullptr) env->DeepCopyTo(zone(), inst);
+  if (auto const lifetime_sexp =
+          CheckInteger(list->ExtraLookupValue("lifetime_position"))) {
+    inst->set_lifetime_position(lifetime_sexp->value());
+  }
   return inst;
 }
 
@@ -843,6 +884,14 @@
     inst->set_closure_function(closure_function);
   }
 
+  if (auto const ident_sexp = CheckSymbol(sexp->ExtraLookupValue("identity"))) {
+    auto id = AliasIdentity::Unknown();
+    if (!AliasIdentity::Parse(ident_sexp->value(), &id)) {
+      return nullptr;
+    }
+    inst->SetIdentity(id);
+  }
+
   return inst;
 }
 
@@ -1768,7 +1817,7 @@
   // This isn't necessary the hash value we will have in the new FlowGraph, but
   // it will be how this type is referred to by TypeRefs in the serialized one.
   auto const old_hash = is_recursive ? hash_sexp->value() : 0;
-  ZoneGrowableArray<TypeRef*>* pending_typerefs;
+  ZoneGrowableArray<TypeRef*>* pending_typerefs = nullptr;
   if (is_recursive) {
     if (pending_typeref_map_.LookupValue(old_hash) != nullptr) {
       StoreError(sexp, "already parsing a type with hash %" Pd64 "",
@@ -1785,17 +1834,21 @@
     StoreError(list, "non-class types not currently handled");
     return false;
   }
-  auto& cls = Class::ZoneHandle(zone());
-  if (!ParseClass(cls_sexp, &cls)) return false;
-  auto& type_args = TypeArguments::ZoneHandle(zone());
-  if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
-    if (!ParseTypeArguments(ta_sexp, &type_args)) return false;
-  }
   TokenPosition token_pos = TokenPosition::kNoSource;
   if (const auto pos_sexp = CheckInteger(list->ExtraLookupValue("token_pos"))) {
     token_pos = TokenPosition(pos_sexp->value());
   }
-  *out = Type::New(cls, type_args, token_pos, Heap::kOld);
+  auto type_args_ptr = &Object::null_type_arguments();
+  if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
+    // ParseTypeArguments may re-enter ParseType after setting the contents of
+    // the passed in handle, so we need to allocate a new handle here.
+    auto& type_args = TypeArguments::Handle(zone());
+    if (!ParseTypeArguments(ta_sexp, &type_args)) return false;
+    type_args_ptr = &type_args;
+  }
+  // Guaranteed not to re-enter ParseType.
+  if (!ParseClass(cls_sexp, &type_class_)) return false;
+  *out = Type::New(type_class_, *type_args_ptr, token_pos, Heap::kOld);
   auto& type = Type::Cast(*out);
   if (auto const sig_sexp = list->ExtraLookupValue("signature")) {
     auto& function = Function::Handle(zone());
@@ -1892,22 +1945,20 @@
     type_param_class_ = table->At(cid);
     cls = &type_param_class_;
   } else {
+    // If we weren't given an explicit source, check in the function for this
+    // flow graph.
     ASSERT(parsed_function_ != nullptr);
-    // If we weren't given an explicit source, check in the flow graph's
-    // function and in its owning class.
     function = &parsed_function_->function();
-    type_param_class_ = function->Owner();
-    cls = &type_param_class_;
   }
 
   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);
-  }
-  if (cls != nullptr && out->IsNull()) {
+  } else if (cls != nullptr) {
     *out = cls->LookupTypeParameter(tmp_string_);
   }
   if (out->IsNull()) {
@@ -2150,6 +2201,54 @@
   return true;
 }
 
+bool FlowGraphDeserializer::ParseRange(SExpList* list, Range* out) {
+  if (list == nullptr) return false;
+  RangeBoundary min, max;
+  if (!ParseRangeBoundary(Retrieve(list, 1), &min)) return false;
+  if (list->Length() == 2) {
+    max = min;
+  } else {
+    if (!ParseRangeBoundary(Retrieve(list, 2), &max)) return false;
+  }
+  out->min_ = min;
+  out->max_ = max;
+  return true;
+}
+
+bool FlowGraphDeserializer::ParseRangeBoundary(SExpression* sexp,
+                                               RangeBoundary* out) {
+  if (sexp == nullptr) return false;
+  if (auto const int_sexp = sexp->AsInteger()) {
+    out->kind_ = RangeBoundary::Kind::kConstant;
+    out->value_ = int_sexp->value();
+  } else if (auto const sym_sexp = sexp->AsSymbol()) {
+    if (!RangeBoundary::ParseKind(sym_sexp->value(), &out->kind_)) return false;
+  } else if (auto const list_sexp = sexp->AsList()) {
+    intptr_t index;
+    if (!ParseUse(CheckSymbol(Retrieve(list_sexp, 1)), &index)) return false;
+    auto const def = definition_map_.LookupValue(index);
+    if (def == nullptr) {
+      StoreError(list_sexp, "no definition for symbolic range boundary");
+      return false;
+    }
+    out->kind_ = RangeBoundary::Kind::kSymbol;
+    out->value_ = reinterpret_cast<intptr_t>(def);
+    if (auto const offset_sexp =
+            CheckInteger(list_sexp->ExtraLookupValue("offset"))) {
+      auto const offset = offset_sexp->value();
+      if (!RangeBoundary::IsValidOffsetForSymbolicRangeBoundary(offset)) {
+        StoreError(sexp, "invalid offset for symbolic range boundary");
+        return false;
+      }
+      out->offset_ = offset;
+    }
+  } else {
+    StoreError(sexp, "unexpected value for range boundary");
+    return false;
+  }
+  return true;
+}
+
 bool FlowGraphDeserializer::ParseBlockId(SExpSymbol* sym, intptr_t* out) {
   return ParseSymbolAsPrefixedInt(sym, 'B', out);
 }
diff --git a/runtime/vm/compiler/backend/il_deserializer.h b/runtime/vm/compiler/backend/il_deserializer.h
index 2b0040a..08e6103 100644
--- a/runtime/vm/compiler/backend/il_deserializer.h
+++ b/runtime/vm/compiler/backend/il_deserializer.h
@@ -62,6 +62,7 @@
         name_field_(Field::Handle(zone)),
         name_function_(Function::Handle(zone)),
         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)) {
@@ -289,6 +290,8 @@
 
   const Field& MayCloneField(const Field& field) const;
   bool ParseSlot(SExpList* list, const Slot** out);
+  bool ParseRange(SExpList* list, Range* out);
+  bool ParseRangeBoundary(SExpression* sexp, RangeBoundary* out);
 
   bool ParseBlockId(SExpSymbol* sym, intptr_t* out);
   bool ParseSSATemp(SExpSymbol* sym, intptr_t* out);
@@ -414,6 +417,7 @@
   Field& name_field_;                  // ParseCanonicalName
   Function& name_function_;            // ParseCanonicalName
   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.
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 3e7d0eb..7af91ad 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -398,7 +398,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ int3();
+#endif
   __ Bind(&done);
 }
 
@@ -2709,6 +2711,36 @@
                          RawPcDescriptors::kOther, locs());
 }
 
+LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(EAX));
+  locs->set_temp(0, Location::RegisterLocation(ECX));
+  return locs;
+}
+
+void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register instance = locs()->in(0).reg();
+  Register temp = locs()->temp(0).reg();
+
+  compiler::Label no_call;
+
+  __ movl(temp, compiler::FieldAddress(instance, field().Offset()));
+  __ CompareObject(temp, Object::sentinel());
+  __ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
+
+  __ pushl(compiler::Immediate(0));  // Make room for (unused) result.
+  __ pushl(instance);
+  __ PushObject(Field::ZoneHandle(field().Original()));
+  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+                                kInitInstanceFieldRuntimeEntry, 2, locs());
+  __ Drop(3);  // Remove arguments and unused result.
+  __ Bind(&no_call);
+}
+
 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 1;
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index c8166bc..527cc9e 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -614,7 +614,13 @@
   instance()->PrintTo(f);
   f->Print(" . %s = ", slot().Name());
   value()->PrintTo(f);
-  if (!ShouldEmitStoreBarrier()) f->Print(", barrier removed");
+
+  // Here, we just print the value of the enum field. We would prefer to get
+  // the final decision on whether a store barrier will be emitted by calling
+  // ShouldEmitStoreBarrier(), but that can change parts of the flow graph.
+  if (emit_store_barrier_ == kNoStoreBarrier) {
+    f->Print(", NoStoreBarrier");
+  }
 }
 
 void IfThenElseInstr::PrintOperandsTo(BufferFormatter* f) const {
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index 2be7442..01ab465 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -8,6 +8,7 @@
 
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/range_analysis.h"
 #include "vm/compiler/method_recognizer.h"
 #include "vm/object_store.h"
 #include "vm/os.h"
@@ -237,20 +238,19 @@
 #define KIND_TAG(name) block_entry_kind_tags[k##name]
 SExpSymbol* FlowGraphSerializer::BlockEntryTag(const BlockEntryInstr* entry) {
   if (entry == nullptr) return nullptr;
-  BlockEntryInstr* const to_test = const_cast<BlockEntryInstr*>(entry);
-  if (to_test->IsGraphEntry()) {
+  if (entry->IsGraphEntry()) {
     return BlockEntryKindToTag(kGraph);
   }
-  if (to_test->IsOsrEntry()) {
+  if (entry->IsOsrEntry()) {
     return BlockEntryKindToTag(kOSR);
   }
-  if (to_test->IsCatchBlockEntry()) {
+  if (entry->IsCatchBlockEntry()) {
     return BlockEntryKindToTag(kCatch);
   }
-  if (to_test->IsIndirectEntry()) {
+  if (entry->IsIndirectEntry()) {
     return BlockEntryKindToTag(kIndirect);
   }
-  if (to_test->IsFunctionEntry()) {
+  if (entry->IsFunctionEntry()) {
     if (entry == flow_graph()->graph_entry()->normal_entry()) {
       return BlockEntryKindToTag(kNormal);
     }
@@ -258,20 +258,21 @@
       return BlockEntryKindToTag(kUnchecked);
     }
   }
-  if (to_test->IsJoinEntry()) {
+  if (entry->IsJoinEntry()) {
     return BlockEntryKindToTag(kJoin);
   }
   return nullptr;
 }
 #undef KIND_TAG
 
-SExpression* FlowGraphSerializer::FunctionEntryToSExp(BlockEntryInstr* entry) {
+SExpression* FlowGraphSerializer::FunctionEntryToSExp(
+    const BlockEntryInstr* entry) {
   if (entry == nullptr) return nullptr;
   auto sexp = new (zone()) SExpList(zone());
   sexp->Add(BlockEntryTag(entry));
   sexp->Add(BlockIdToSExp(entry->block_id()));
-  if (auto with_defs = entry->AsBlockEntryWithInitialDefs()) {
-    auto initial_defs = with_defs->initial_definitions();
+  if (auto const with_defs = entry->AsBlockEntryWithInitialDefs()) {
+    auto const initial_defs = with_defs->initial_definitions();
     for (intptr_t i = 0; i < initial_defs->length(); i++) {
       sexp->Add(initial_defs->At(i)->ToSExpression(this));
     }
@@ -284,7 +285,7 @@
   return sexp;
 }
 
-SExpression* FlowGraphSerializer::EntriesToSExp(GraphEntryInstr* start) {
+SExpression* FlowGraphSerializer::EntriesToSExp(const GraphEntryInstr* start) {
   auto sexp = new (zone()) SExpList(zone());
   AddSymbol(sexp, "Entries");
   if (auto const normal = FunctionEntryToSExp(start->normal_entry())) {
@@ -409,13 +410,8 @@
                        CanonicalNameToSExp(flow_graph_->function()));
       }
     } else if (param.IsClassTypeParameter()) {
-      if (param.parameterized_class() != flow_graph_->function().Owner()) {
-        type_class_ = param.parameterized_class();
-        AddExtraInteger(sexp, "class", type_class_.id());
-      } else if (FLAG_verbose_flow_graph_serialization) {
-        type_class_ = flow_graph_->function().Owner();
-        AddExtraInteger(sexp, "class", type_class_.id());
-      }
+      type_class_ = param.parameterized_class();
+      AddExtraInteger(sexp, "class", type_class_.id());
     }
     return sexp;
   }
@@ -731,7 +727,8 @@
   return DartValueToSExp(ta);
 }
 
-SExpression* FlowGraphSerializer::ConstantPoolToSExp(GraphEntryInstr* start) {
+SExpression* FlowGraphSerializer::ConstantPoolToSExp(
+    const GraphEntryInstr* start) {
   auto const initial_defs = start->initial_definitions();
   if (initial_defs == nullptr || initial_defs->is_empty()) return nullptr;
   auto constant_list = new (zone()) SExpList(zone());
@@ -745,14 +742,7 @@
     // Use ObjectToSExp here, not DartValueToSExp!
     const auto& value = definition->AsConstant()->value();
     elem->Add(ObjectToSExp(value));
-    // Check this first, otherwise Type() can have the side effect of setting
-    // a new CompileType!
-    if (definition->HasType()) {
-      auto const type = definition->Type();
-      if (ShouldSerializeType(type)) {
-        elem->AddExtra("type", type->ToSExpression(this));
-      }
-    }
+    AddDefinitionExtraInfoToSExp(definition, elem);
     // Only add constants to the LLVM constant pool that are actually used in
     // the flow graph.
     if (FLAG_populate_llvm_constant_pool && definition->HasUses()) {
@@ -808,10 +798,8 @@
 
 void BlockEntryInstr::AddOperandsToSExpression(SExpList* sexp,
                                                FlowGraphSerializer* s) const {
-  // We don't use RemoveCurrentFromGraph(), so this cast is safe.
-  auto block = const_cast<BlockEntryInstr*>(this);
-  for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-    sexp->Add(it.Current()->ToSExpression(s));
+  for (const auto* inst = next_; inst != nullptr; inst = inst->next_) {
+    sexp->Add(inst->ToSExpression(s));
   }
 }
 
@@ -844,18 +832,75 @@
   if (!token_pos().IsNoSource()) {
     s->AddExtraInteger(sexp, "token_pos", token_pos().value());
   }
+  if (lifetime_position() != kNoPlaceId) {
+    s->AddExtraInteger(sexp, "lifetime_position", lifetime_position());
+  }
+}
+
+SExpression* Range::ToSExpression(FlowGraphSerializer* s) {
+  auto const sexp = new (s->zone()) SExpList(s->zone());
+  s->AddSymbol(sexp, "Range");
+  sexp->Add(min_.ToSExpression(s));
+  if (!max_.Equals(min_)) sexp->Add(max_.ToSExpression(s));
+  return sexp;
+}
+
+SExpression* RangeBoundary::ToSExpression(FlowGraphSerializer* s) {
+  switch (kind_) {
+    case kSymbol: {
+      auto const sexp = new (s->zone()) SExpList(s->zone());
+      sexp->Add(s->UseToSExp(symbol()));
+      if (offset() != 0) {
+        s->AddExtraInteger(sexp, "offset", offset());
+      }
+      return sexp;
+    }
+    case kConstant:
+      return new (s->zone()) SExpInteger(value_);
+    default:
+      return new (s->zone()) SExpSymbol(RangeBoundary::KindToCString(kind_));
+  }
+}
+
+bool FlowGraphSerializer::HasDefinitionExtraInfo(const Definition* def) {
+  return ShouldSerializeType(def->type_) || def->range() != nullptr;
+}
+
+void FlowGraphSerializer::AddDefinitionExtraInfoToSExp(const Definition* def,
+                                                       SExpList* sexp) {
+  // Type() isn't a const method as it can cause changes to the type_
+  // field, so access type_ directly instead.
+  if (ShouldSerializeType(def->type_)) {
+    sexp->AddExtra("type", def->type_->ToSExpression(this));
+  }
+  if (def->range() != nullptr) {
+    sexp->AddExtra("range", def->range()->ToSExpression(this));
+  }
 }
 
 SExpression* Definition::ToSExpression(FlowGraphSerializer* s) const {
-  if (!HasSSATemp() && !HasTemp()) {
+  // If we don't have a temp index, then this is a Definition that has no
+  // usable result, like PushArgumentInstr.
+  const bool binds_name = HasSSATemp() || HasTemp();
+  // Don't serialize non-binding definitions as definitions unless we either
+  // have Definition-specific extra info or we're in verbose mode.
+  if (!binds_name && !FLAG_verbose_flow_graph_serialization &&
+      !s->HasDefinitionExtraInfo(this)) {
     return Instruction::ToSExpression(s);
   }
   auto sexp = new (s->zone()) SExpList(s->zone());
   s->AddSymbol(sexp, "def");
-  sexp->Add(s->UseToSExp(this));
-  if (ShouldSerializeType(type_)) {
-    sexp->AddExtra("type", type_->ToSExpression(s));
+  if (binds_name) {
+    sexp->Add(s->UseToSExp(this));
+  } else {
+    // Since there is Definition-specific extra info to serialize, we use "_"
+    // as the bound name, which lets the deserializer know the result is unused.
+    s->AddSymbol(sexp, "_");
   }
+  // Add only Definition-specific extra info to this form. Any extra info
+  // that is Instruction-specific or specific to the actual instruction type is
+  // added to the nested instruction form.
+  s->AddDefinitionExtraInfoToSExp(this, sexp);
   sexp->Add(Instruction::ToSExpression(s));
   return sexp;
 }
@@ -1257,6 +1302,9 @@
   if (auto const closure = s->DartValueToSExp(closure_function())) {
     sexp->AddExtra("closure_function", closure);
   }
+  if (!Identity().IsUnknown() || FLAG_verbose_flow_graph_serialization) {
+    s->AddExtraSymbol(sexp, "identity", Identity().ToCString());
+  }
 }
 
 void BinaryIntegerOpInstr::AddOperandsToSExpression(
diff --git a/runtime/vm/compiler/backend/il_serializer.h b/runtime/vm/compiler/backend/il_serializer.h
index 3e6e6af..0e02cd2 100644
--- a/runtime/vm/compiler/backend/il_serializer.h
+++ b/runtime/vm/compiler/backend/il_serializer.h
@@ -98,6 +98,10 @@
   SExpression* SlotToSExp(const Slot& s);
   SExpression* ICDataToSExp(const ICData* ic_data);
 
+  // Helper methods for adding Definition-specific extra info.
+  bool HasDefinitionExtraInfo(const Definition* def);
+  void AddDefinitionExtraInfoToSExp(const Definition* def, SExpList* sexp);
+
   // Helper methods for adding atoms to S-expression lists
   void AddBool(SExpList* sexp, bool b);
   void AddInteger(SExpList* sexp, intptr_t i);
@@ -118,9 +122,9 @@
 
   // Helper methods for the function level that are not used by any
   // instruction serialization methods.
-  SExpression* FunctionEntryToSExp(BlockEntryInstr* entry);
-  SExpression* EntriesToSExp(GraphEntryInstr* start);
-  SExpression* ConstantPoolToSExp(GraphEntryInstr* start);
+  SExpression* FunctionEntryToSExp(const BlockEntryInstr* entry);
+  SExpression* EntriesToSExp(const GraphEntryInstr* start);
+  SExpression* ConstantPoolToSExp(const GraphEntryInstr* start);
 
   const FlowGraph* const flow_graph_;
   Zone* const zone_;
diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc
index ff6ccd5..e764780 100644
--- a/runtime/vm/compiler/backend/il_test.cc
+++ b/runtime/vm/compiler/backend/il_test.cc
@@ -3,6 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/compiler/backend/il.h"
+
+#include <vector>
+
 #include "vm/compiler/backend/il_test_helper.h"
 #include "vm/unit_test.h"
 
@@ -85,4 +88,113 @@
   EXPECT(!store_indexed->value()->NeedsWriteBarrier());
 }
 
+static void ExpectStores(FlowGraph* flow_graph,
+                         const std::vector<const char*>& expected_stores) {
+  size_t next_expected_store = 0;
+  for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
+       !block_it.Done(); block_it.Advance()) {
+    for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
+         it.Advance()) {
+      if (auto store = it.Current()->AsStoreInstanceField()) {
+        EXPECT_LT(next_expected_store, expected_stores.size());
+        EXPECT_STREQ(expected_stores[next_expected_store],
+                     store->slot().Name());
+        next_expected_store++;
+      }
+    }
+  }
+}
+
+static void RunInitializingStoresTest(
+    const Library& root_library,
+    const char* function_name,
+    CompilerPass::PipelineMode mode,
+    const std::vector<const char*>& expected_stores) {
+  const auto& function =
+      Function::Handle(GetFunction(root_library, function_name));
+  TestPipeline pipeline(function, mode);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyICData,
+      CompilerPass::kInlining,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kSelectRepresentations,
+      CompilerPass::kCanonicalize,
+      CompilerPass::kConstantPropagation,
+  });
+  ASSERT(flow_graph != nullptr);
+  ExpectStores(flow_graph, expected_stores);
+}
+
+ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
+  const char* kScript = R"(
+    class Bar {
+      var f;
+      var g;
+
+      Bar({this.f, this.g});
+    }
+    Bar f1() => Bar(f: 10);
+    Bar f2() => Bar(g: 10);
+    f3() {
+      return () { };
+    }
+    f4<T>({T value}) {
+      return () { return value; };
+    }
+    main() {
+      f1();
+      f2();
+      f3();
+      f4();
+    }
+  )";
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  Invoke(root_library, "main");
+
+  RunInitializingStoresTest(root_library, "f1", CompilerPass::kJIT,
+                            /*expected_stores=*/{"f"});
+  RunInitializingStoresTest(root_library, "f2", CompilerPass::kJIT,
+                            /*expected_stores=*/{"g"});
+  RunInitializingStoresTest(root_library, "f3", CompilerPass::kJIT,
+                            /*expected_stores=*/
+                            {"Closure.function"});
+
+  // Note that in JIT mode we lower context allocation in a way that hinders
+  // removal of initializing moves so there would be some redundant stores of
+  // null left in the graph. In AOT mode we don't apply this optimization
+  // which enables us to remove more stores.
+  std::vector<const char*> expected_stores_jit;
+  std::vector<const char*> expected_stores_aot;
+  if (root_library.is_declared_in_bytecode()) {
+    // Bytecode flow graph builder doesn't provide readable
+    // variable names for captured variables. Also, bytecode may omit
+    // stores of context parent in certain cases.
+    expected_stores_jit.insert(
+        expected_stores_jit.end(),
+        {":context_var0", "Context.parent", ":context_var0",
+         "Closure.function_type_arguments", "Closure.function",
+         "Closure.context"});
+    expected_stores_aot.insert(
+        expected_stores_aot.end(),
+        {":context_var0", "Closure.function_type_arguments", "Closure.function",
+         "Closure.context"});
+  } else {
+    // These expectations are for AST-based flow graph builder.
+    expected_stores_jit.insert(expected_stores_jit.end(),
+                               {"value", "Context.parent", "Context.parent",
+                                "value", "Closure.function_type_arguments",
+                                "Closure.function", "Closure.context"});
+    expected_stores_aot.insert(expected_stores_aot.end(),
+                               {"value", "Closure.function_type_arguments",
+                                "Closure.function", "Closure.context"});
+  }
+
+  RunInitializingStoresTest(root_library, "f4", CompilerPass::kJIT,
+                            expected_stores_jit);
+  RunInitializingStoresTest(root_library, "f4", CompilerPass::kAOT,
+                            expected_stores_aot);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 9570fc9..82094ea 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -131,8 +131,7 @@
 
   SpeculativeInliningPolicy speculative_policy(/*enable_blacklist=*/false);
 
-#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32) ||                   \
-    defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
   const bool use_far_branches = false;
 #else
   const bool use_far_branches = true;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index e1beb73..b736c05 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -527,7 +527,9 @@
   compiler->GenerateRuntimeCall(token_pos, deopt_id,
                                 kNonBoolTypeErrorRuntimeEntry, 1, locs);
   // We should never return here.
+#if defined(DEBUG)
   __ int3();
+#endif
   __ Bind(&done);
 }
 
@@ -2842,6 +2844,36 @@
                          RawPcDescriptors::kOther, locs());
 }
 
+LocationSummary* InitInstanceFieldInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 1;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(RAX));
+  locs->set_temp(0, Location::RegisterLocation(RCX));
+  return locs;
+}
+
+void InitInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  Register instance = locs()->in(0).reg();
+  Register temp = locs()->temp(0).reg();
+
+  compiler::Label no_call;
+
+  __ movq(temp, compiler::FieldAddress(instance, field().Offset()));
+  __ CompareObject(temp, Object::sentinel());
+  __ j(NOT_EQUAL, &no_call, compiler::Assembler::kNearJump);
+
+  __ pushq(compiler::Immediate(0));  // Make room for (unused) result.
+  __ pushq(instance);
+  __ PushObject(Field::ZoneHandle(field().Original()));
+  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
+                                kInitInstanceFieldRuntimeEntry, 2, locs());
+  __ Drop(3);  // Remove arguments and unused result.
+  __ Bind(&no_call);
+}
+
 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone,
                                                            bool opt) const {
   const intptr_t kNumInputs = 1;
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index d171a71..52e3cac 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1032,8 +1032,7 @@
 #endif
           CalleeGraphValidator::Validate(callee_graph);
         }
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
         if (FLAG_precompiled_mode) {
           callee_graph->PopulateWithICData(parsed_function->function());
         }
@@ -1128,8 +1127,7 @@
           // TODO(fschneider): Improve suppression of speculative inlining.
           // Deopt-ids overlap between caller and callee.
           if (FLAG_precompiled_mode) {
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
             AotCallSpecializer call_specializer(inliner_->precompiler_,
                                                 callee_graph,
                                                 inliner_->speculative_policy_);
@@ -1140,8 +1138,7 @@
             CompilerPass::RunInliningPipeline(CompilerPass::kAOT, &state);
 #else
             UNREACHABLE();
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
-        // !defined(TARGET_ARCH_IA32)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
           } else {
             JitCallSpecializer call_specializer(callee_graph,
                                                 inliner_->speculative_policy_);
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index efce8fa..7635384 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -140,9 +140,7 @@
   // TODO(fschneider): Handle saving and restoring these registers when
   // generating intrinsic code.
   if (intrinsic_mode) {
-#if !defined(TARGET_ARCH_DBC)
     blocked_cpu_registers_[ARGS_DESC_REG] = true;
-#endif
 
 #if !defined(TARGET_ARCH_IA32)
     // Need to preserve CODE_REG to be able to store the PC marker
@@ -186,15 +184,6 @@
 
       // Initialize location summary for instruction.
       current->InitializeLocationSummary(zone(), true);  // opt
-#if defined(TARGET_ARCH_DBC)
-      // TODO(vegorov) remove this once we have ported all necessary
-      // instructions to DBC.
-      if (!current->HasLocs()) {
-        const char* msg = "SSALivenessAnalysis::ComputeInitialSets";
-        NOT_IN_PRODUCT(msg = current->ToCString());
-        graph_entry_->parsed_function().Bailout("SSALivenessAnalysis", msg);
-      }
-#endif
 
       LocationSummary* locs = current->locs();
 #if defined(DEBUG)
@@ -453,10 +442,6 @@
                                        intptr_t to) {
   if (loc.IsRegister()) {
     BlockRegisterLocation(loc, from, to, blocked_cpu_registers_, cpu_regs_);
-#if defined(TARGET_ARCH_DBC)
-    last_used_register_ =
-        Utils::Maximum(last_used_register_, loc.register_code());
-#endif
   } else if (loc.IsFpuRegister()) {
     BlockRegisterLocation(loc, from, to, blocked_fpu_registers_, fpu_regs_);
   } else {
@@ -690,7 +675,7 @@
       SplitInitialDefinitionAt(range, block->lifetime_position() + 1);
       ConvertAllUses(range);
 
-      // On non-DBC we'll have exception/stacktrace in a register and need to
+      // We have exception/stacktrace in a register and need to
       // ensure this register is not available for register allocation during
       // the [CatchBlockEntry] to ensure it's not overwritten.
       if (loc.IsRegister()) {
@@ -698,40 +683,6 @@
                       block->lifetime_position() + 1);
       }
       return;
-#if defined(TARGET_ARCH_DBC)
-    } else if (ParameterInstr* param = defn->AsParameter()) {
-      intptr_t slot_index = param->index();
-      AssignSafepoints(defn, range);
-      range->finger()->Initialize(range);
-      slot_index = kNumberOfCpuRegisters - 1 - slot_index;
-      if (slot_index < kMaxNumberOfFixedInputRegistersUsedByIL) {
-        // We ran out of registers for the catch block parameters.
-        // Bail out to unoptimized code
-        flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "CATCH");
-        UNREACHABLE();
-      }
-      range->set_assigned_location(Location::RegisterLocation(slot_index));
-      SplitInitialDefinitionAt(range, block->lifetime_position() + 2);
-      ConvertAllUses(range);
-      BlockLocation(Location::RegisterLocation(slot_index), 0, kMaxPosition);
-      return;
-    } else if (ConstantInstr* constant = defn->AsConstant()) {
-      ASSERT(constant != NULL);
-      range->set_assigned_location(Location::Constant(constant));
-      range->set_spill_slot(Location::Constant(constant));
-      AssignSafepoints(defn, range);
-      range->finger()->Initialize(range);
-      UsePosition* use =
-          range->finger()->FirstRegisterBeneficialUse(block->start_pos());
-      if (use != NULL) {
-        LiveRange* tail = SplitBetween(range, block->start_pos(), use->pos());
-        // Parameters and constants are tagged, so allocated to CPU registers.
-        ASSERT(constant->representation() == kTagged);
-        CompleteRange(tail, Location::kRegister);
-      }
-      ConvertAllUses(range);
-      return;
-#endif  // defined(TARGET_ARCH_DBC)
     }
   }
 
@@ -749,17 +700,6 @@
       slot_index = flow_graph_.num_direct_parameters() - 1 - slot_index;
     }
 
-#if defined(TARGET_ARCH_DBC)
-    ASSERT(param->base_reg() == FPREG);
-    if (slot_index >= 0) {
-      AssignSafepoints(defn, range);
-      range->finger()->Initialize(range);
-      range->set_assigned_location(Location::RegisterLocation(slot_index));
-      SplitInitialDefinitionAt(range, kNormalEntryPos);
-      ConvertAllUses(range);
-      return;
-    }
-#endif  // defined(TARGET_ARCH_DBC)
     if (param->base_reg() == FPREG) {
       slot_index =
           compiler::target::frame_layout.FrameSlotForVariableIndex(-slot_index);
@@ -774,11 +714,7 @@
     SpecialParameterInstr* param = defn->AsSpecialParameter();
     ASSERT(param->kind() == SpecialParameterInstr::kArgDescriptor);
     Location loc;
-#if defined(TARGET_ARCH_DBC)
-    loc = LocationArgumentsDescriptorLocation();
-#else
     loc = Location::RegisterLocation(ARGS_DESC_REG);
-#endif  // defined(TARGET_ARCH_DBC)
     range->set_assigned_location(loc);
     if (loc.IsRegister()) {
       AssignSafepoints(defn, range);
@@ -1438,9 +1374,6 @@
   }
 
 // Block all allocatable registers for calls.
-// Note that on DBC registers are always essentially spilled so
-// we don't need to block anything.
-#if !defined(TARGET_ARCH_DBC)
   if (locs->always_calls() && !locs->callee_safe_call()) {
     // Expected shape of live range:
     //
@@ -1490,7 +1423,6 @@
     }
 #endif
   }
-#endif
 
   if (locs->can_call()) {
     safepoints_.Add(current);
@@ -1971,14 +1903,6 @@
 }
 
 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) {
-#if defined(TARGET_ARCH_DBC)
-  // There is no need to support spilling on DBC because we have a lot of
-  // registers and registers and spill-slots have the same performance
-  // characteristics.
-  flow_graph_.parsed_function().Bailout("FlowGraphAllocator", "SPILL");
-  UNREACHABLE();
-#endif
-
   ASSERT(range->spill_slot().IsInvalid());
 
   // Compute range start and end.
@@ -2319,10 +2243,6 @@
 
   registers_[candidate]->Add(unallocated);
   unallocated->set_assigned_location(MakeRegisterLocation(candidate));
-#if defined(TARGET_ARCH_DBC)
-  last_used_register_ = Utils::Maximum(last_used_register_, candidate);
-#endif
-
   return true;
 }
 
@@ -2510,9 +2430,6 @@
 
   registers_[reg]->Add(unallocated);
   unallocated->set_assigned_location(MakeRegisterLocation(reg));
-#if defined(TARGET_ARCH_DBC)
-  last_used_register_ = Utils::Maximum(last_used_register_, reg);
-#endif
 }
 
 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
@@ -2595,16 +2512,10 @@
   if (loc.IsMachineRegister()) {
     for (SafepointPosition* safepoint = range->first_safepoint();
          safepoint != NULL; safepoint = safepoint->next()) {
-#if !defined(TARGET_ARCH_DBC)
       if (!safepoint->locs()->always_calls()) {
         ASSERT(safepoint->locs()->can_call());
         safepoint->locs()->live_registers()->Add(loc, range->representation());
       }
-#else
-      if (range->representation() == kTagged) {
-        safepoint->locs()->SetStackBit(loc.reg());
-      }
-#endif  // !defined(TARGET_ARCH_DBC)
     }
   }
 }
@@ -2984,10 +2895,6 @@
 
   NumberInstructions();
 
-#if defined(TARGET_ARCH_DBC)
-  last_used_register_ = -1;
-#endif
-
   BuildLiveRanges();
 
   if (FLAG_print_ssa_liveranges) {
@@ -3011,16 +2918,6 @@
   PrepareForAllocation(Location::kRegister, kNumberOfCpuRegisters,
                        unallocated_cpu_, cpu_regs_, blocked_cpu_registers_);
   AllocateUnallocatedRanges();
-#if defined(TARGET_ARCH_DBC)
-  const intptr_t last_used_cpu_register = last_used_register_;
-  last_used_register_ = -1;
-#endif
-
-#if defined(TARGET_ARCH_DBC)
-  // Spilling is unsupported on DBC.
-  ASSERT(spill_slots_.length() == 0);
-  cpu_spill_slot_count_ = 0;
-#else
   // GraphEntryInstr::fixed_slot_count() stack slots are reserved for catch
   // entries. When allocating a spill slot, AllocateSpillSlotFor() accounts for
   // these reserved slots and allocates spill slots on top of them.
@@ -3028,24 +2925,13 @@
   // slots for catch entries in the spill area.
   cpu_spill_slot_count_ = Utils::Maximum(
       spill_slots_.length(), flow_graph_.graph_entry()->fixed_slot_count());
-#endif
   spill_slots_.Clear();
   quad_spill_slots_.Clear();
   untagged_spill_slots_.Clear();
 
   PrepareForAllocation(Location::kFpuRegister, kNumberOfFpuRegisters,
                        unallocated_xmm_, fpu_regs_, blocked_fpu_registers_);
-#if defined(TARGET_ARCH_DBC)
-  // For DBC all registers should have been allocated in the first pass.
-  ASSERT(unallocated_.is_empty());
-#endif
-
   AllocateUnallocatedRanges();
-#if defined(TARGET_ARCH_DBC)
-  const intptr_t last_used_fpu_register = last_used_register_;
-  ASSERT(last_used_fpu_register == -1);  // Not supported right now.
-#endif
-
   ResolveControlFlow();
 
   GraphEntryInstr* entry = block_order_[0]->AsGraphEntry();
@@ -3053,20 +2939,6 @@
   intptr_t double_spill_slot_count = spill_slots_.length() * kDoubleSpillFactor;
   entry->set_spill_slot_count(cpu_spill_slot_count_ + double_spill_slot_count);
 
-#if defined(TARGET_ARCH_DBC)
-  // Spilling is unsupported on DBC.
-  if (entry->spill_slot_count() != 0) {
-    UNREACHABLE();
-  }
-
-  // We store number of used DBC registers in the spill slot count to avoid
-  // introducing a separate field. It has roughly the same meaning:
-  // number of used registers determines how big of a frame to reserve for
-  // this function on DBC stack.
-  entry->set_spill_slot_count((last_used_cpu_register + 1) +
-                              (last_used_fpu_register + 1));
-#endif
-
   if (FLAG_print_ssa_liveranges) {
     const Function& function = flow_graph_.function();
 
diff --git a/runtime/vm/compiler/backend/linearscan.h b/runtime/vm/compiler/backend/linearscan.h
index 9655f32..8b774cc 100644
--- a/runtime/vm/compiler/backend/linearscan.h
+++ b/runtime/vm/compiler/backend/linearscan.h
@@ -295,10 +295,6 @@
 
   intptr_t number_of_registers_;
 
-#if defined(TARGET_ARCH_DBC)
-  intptr_t last_used_register_;
-#endif
-
   // Per register lists of allocated live ranges.  Contain only those
   // ranges that can be affected by future allocation decisions.
   // Those live ranges that end before the start of the current live range are
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index 210cd37..1db7fd7 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -141,12 +141,9 @@
              : Location::Any();
 }
 
-// DBC does not have an notion of 'address' in its instruction set.
-#if !defined(TARGET_ARCH_DBC)
 compiler::Address LocationToStackSlotAddress(Location loc) {
   return compiler::Address(loc.base_reg(), loc.ToStackSlotOffset());
 }
-#endif
 
 template <class Register, class FpuRegister>
 intptr_t TemplateLocation<Register, FpuRegister>::ToStackSlotOffset() const {
@@ -189,19 +186,6 @@
           return "0";
       }
       UNREACHABLE();
-#if TARGET_ARCH_DBC
-    case kSpecialDbcRegister:
-      switch (payload()) {
-        case kArgsDescriptorReg:
-          return "ArgDescReg";
-        case kExceptionReg:
-          return "ExceptionReg";
-        case kStackTraceReg:
-          return "StackTraceReg";
-        default:
-          UNREACHABLE();
-      }
-#endif
     default:
       if (IsConstant()) {
         return "C";
@@ -269,27 +253,15 @@
 }
 
 Location LocationArgumentsDescriptorLocation() {
-#ifdef TARGET_ARCH_DBC
-  return Location(Location::kSpecialDbcRegister, Location::kArgsDescriptorReg);
-#else
   return Location::RegisterLocation(ARGS_DESC_REG);
-#endif
 }
 
 Location LocationExceptionLocation() {
-#ifdef TARGET_ARCH_DBC
-  return Location(Location::kSpecialDbcRegister, Location::kExceptionReg);
-#else
   return Location::RegisterLocation(kExceptionObjectReg);
-#endif
 }
 
 Location LocationStackTraceLocation() {
-#ifdef TARGET_ARCH_DBC
-  return Location(Location::kSpecialDbcRegister, Location::kStackTraceReg);
-#else
   return Location::RegisterLocation(kStackTraceObjectReg);
-#endif
 }
 
 Location LocationRemapForSlowPath(Location loc,
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index b6e7777..e0731f4 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -94,14 +94,6 @@
   static const uword kLocationTagMask = 0x3;
 
  public:
-#if defined(TARGET_ARCH_DBC)
-  enum SpecialDbcRegister{
-      kArgsDescriptorReg,
-      kExceptionReg,
-      kStackTraceReg,
-  };
-#endif
-
   // Constant payload can overlap with kind field so Kind values
   // have to be chosen in a way that their last 2 bits are never
   // the same as kConstantTag or kPairLocationTag.
@@ -137,12 +129,6 @@
     // FpuRegister location represents a fixed fpu register.  Payload contains
     // its code.
     kFpuRegister = 12,
-
-#ifdef TARGET_ARCH_DBC
-    // We use this to signify a special `Location` where the different
-    // [SpecialDbcRegister]s can be found on DBC.
-    kSpecialDbcRegister = 15,
-#endif
   };
 
   TemplateLocation() : value_(kInvalidLocation) {
@@ -169,12 +155,6 @@
     COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kConstantTag);
     COMPILE_ASSERT((kFpuRegister & kLocationTagMask) != kPairLocationTag);
 
-#ifdef TARGET_ARCH_DBC
-    COMPILE_ASSERT((kSpecialDbcRegister & kLocationTagMask) != kConstantTag);
-    COMPILE_ASSERT((kSpecialDbcRegister & kLocationTagMask) !=
-                   kPairLocationTag);
-#endif
-
     // Verify tags and tagmask.
     COMPILE_ASSERT((kConstantTag & kLocationTagMask) == kConstantTag);
 
@@ -295,22 +275,6 @@
 
   bool IsFpuRegister() const { return kind() == kFpuRegister; }
 
-#ifdef TARGET_ARCH_DBC
-  bool IsArgsDescRegister() const {
-    return IsSpecialDbcRegister(kArgsDescriptorReg);
-  }
-  bool IsExceptionRegister() const {
-    return IsSpecialDbcRegister(kExceptionReg);
-  }
-  bool IsStackTraceRegister() const {
-    return IsSpecialDbcRegister(kStackTraceReg);
-  }
-
-  bool IsSpecialDbcRegister(SpecialDbcRegister reg) const {
-    return kind() == kSpecialDbcRegister && payload() == reg;
-  }
-#endif
-
   FpuRegister fpu_reg() const {
     ASSERT(IsFpuRegister());
     return static_cast<FpuRegister>(payload());
@@ -493,11 +457,8 @@
                                   intptr_t* cpu_reg_slots,
                                   intptr_t* fpu_reg_slots);
 
-// DBC does not have an notion of 'address' in its instruction set.
-#if !defined(TARGET_ARCH_DBC)
 // Return a memory operand for stack slot locations.
 compiler::Address LocationToStackSlotAddress(Location loc);
-#endif
 
 template <class Location>
 class TemplatePairLocation : public ZoneAllocated {
@@ -608,7 +569,6 @@
 #endif
   }
 
-#if !defined(TARGET_ARCH_DBC)
   void AddAllArgumentRegisters() {
     // All (native) arguments are passed on the stack in IA32.
 #if !defined(TARGET_ARCH_IA32)
@@ -626,7 +586,6 @@
     }
 #endif
   }
-#endif
 
   void Add(Location loc, Representation rep = kTagged) {
     if (loc.IsRegister()) {
@@ -785,12 +744,8 @@
 
   void set_out(intptr_t index, Location loc) {
     ASSERT(index == 0);
-// DBC calls are different from call on other architectures so this
-// assert doesn't make sense.
-#if !defined(TARGET_ARCH_DBC)
     ASSERT(!always_calls() || (loc.IsMachineRegister() || loc.IsInvalid() ||
                                loc.IsPairLocation()));
-#endif
     output_location_ = loc;
   }
 
diff --git a/runtime/vm/compiler/backend/locations_helpers.h b/runtime/vm/compiler/backend/locations_helpers.h
index 481fbdb..5e7969a 100644
--- a/runtime/vm/compiler/backend/locations_helpers.h
+++ b/runtime/vm/compiler/backend/locations_helpers.h
@@ -430,8 +430,6 @@
 #include "vm/compiler/backend/locations_helpers_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 
-#elif defined(TARGET_ARCH_DBC)
-
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/compiler/backend/locations_helpers_test.cc b/runtime/vm/compiler/backend/locations_helpers_test.cc
index ed79506..aaf3805 100644
--- a/runtime/vm/compiler/backend/locations_helpers_test.cc
+++ b/runtime/vm/compiler/backend/locations_helpers_test.cc
@@ -9,8 +9,6 @@
 
 namespace dart {
 
-#if !defined(TARGET_ARCH_DBC)
-
 #define Reg(index) (static_cast<Register>(index))
 #define Fpu(index) (static_cast<FpuRegister>(index))
 
@@ -233,6 +231,4 @@
   EXPECT_EQ(Fpu(3), Fpu(temp));
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/loops_test.cc b/runtime/vm/compiler/backend/loops_test.cc
index b2b2e23..3898334 100644
--- a/runtime/vm/compiler/backend/loops_test.cc
+++ b/runtime/vm/compiler/backend/loops_test.cc
@@ -368,7 +368,6 @@
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
 
-#ifndef TARGET_ARCH_DBC
 ISOLATE_UNIT_TEST_CASE(NonStrictConditionUpWrap) {
   const char* script_chars =
       R"(
@@ -392,7 +391,6 @@
       "  ]\n";
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
-#endif
 
 ISOLATE_UNIT_TEST_CASE(NonStrictConditionDown) {
   const char* script_chars =
@@ -413,7 +411,6 @@
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
 
-#ifndef TARGET_ARCH_DBC
 ISOLATE_UNIT_TEST_CASE(NonStrictConditionDownWrap) {
   const char* script_chars =
       R"(
@@ -438,8 +435,6 @@
   EXPECT_STREQ(expected, ComputeInduction(thread, script_chars));
 }
 
-#endif
-
 ISOLATE_UNIT_TEST_CASE(NotEqualConditionUp) {
   const char* script_chars =
       R"(
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 52aee67..09d8b41 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -291,6 +291,30 @@
   return range;
 }
 
+const char* RangeBoundary::KindToCString(Kind kind) {
+  switch (kind) {
+#define KIND_CASE(name)                                                        \
+  case Kind::k##name:                                                          \
+    return #name;
+    FOR_EACH_RANGE_BOUNDARY_KIND(KIND_CASE)
+#undef KIND_CASE
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+bool RangeBoundary::ParseKind(const char* str, Kind* out) {
+#define KIND_CASE(name)                                                        \
+  if (strcmp(str, #name) == 0) {                                               \
+    *out = Kind::k##name;                                                      \
+    return true;                                                               \
+  }
+  FOR_EACH_RANGE_BOUNDARY_KIND(KIND_CASE)
+#undef KIND_CASE
+  return false;
+}
+
 static bool AreEqualDefinitions(Definition* a, Definition* b) {
   a = UnwrapConstraint(a);
   b = UnwrapConstraint(b);
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index 2b8bea7..720103b 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -10,15 +10,24 @@
 
 namespace dart {
 
+class SExpression;
+class FlowGraphSerializer;
+
 class RangeBoundary : public ValueObject {
  public:
-  enum Kind {
-    kUnknown,
-    kNegativeInfinity,
-    kPositiveInfinity,
-    kSymbol,
-    kConstant,
-  };
+#define FOR_EACH_RANGE_BOUNDARY_KIND(V)                                        \
+  V(Unknown)                                                                   \
+  V(NegativeInfinity)                                                          \
+  V(PositiveInfinity)                                                          \
+  V(Symbol)                                                                    \
+  V(Constant)
+
+#define KIND_DEFN(name) k##name,
+  enum Kind { FOR_EACH_RANGE_BOUNDARY_KIND(KIND_DEFN) };
+#undef KIND_DEFN
+
+  static const char* KindToCString(Kind kind);
+  static bool ParseKind(const char* str, Kind* out);
 
   enum RangeSize {
     kRangeBoundarySmi,
@@ -233,6 +242,7 @@
 
   void PrintTo(BufferFormatter* f) const;
   const char* ToCString() const;
+  SExpression* ToSExpression(FlowGraphSerializer* s);
 
   static RangeBoundary Add(const RangeBoundary& a,
                            const RangeBoundary& b,
@@ -287,6 +297,8 @@
   int64_t SmiLowerBound() const { return LowerBound(kRangeBoundarySmi); }
 
  private:
+  friend class FlowGraphDeserializer;  // For setting fields directly.
+
   RangeBoundary(Kind kind, int64_t value, int64_t offset)
       : kind_(kind), value_(value), offset_(offset) {}
 
@@ -331,6 +343,7 @@
 
   void PrintTo(BufferFormatter* f) const;
   static const char* ToCString(const Range* range);
+  SExpression* ToSExpression(FlowGraphSerializer* s);
 
   bool Equals(const Range* other) {
     ASSERT(min_.IsUnknown() == max_.IsUnknown());
@@ -493,6 +506,8 @@
                        Range* result);
 
  private:
+  friend class FlowGraphDeserializer;  // For setting min_/max_ directly.
+
   RangeBoundary min_;
   RangeBoundary max_;
 
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 0155377..7856acf 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1598,6 +1598,17 @@
     return forwarded_;
   }
 
+  // Only forward stores to normal arrays, float64, and simd arrays
+  // to loads because other array stores (intXX/uintXX/float32)
+  // may implicitly convert the value stored.
+  bool CanForwardStore(StoreIndexedInstr* array_store) {
+    return ((array_store == nullptr) ||
+            (array_store->class_id() == kArrayCid) ||
+            (array_store->class_id() == kTypedDataFloat64ArrayCid) ||
+            (array_store->class_id() == kTypedDataFloat32ArrayCid) ||
+            (array_store->class_id() == kTypedDataFloat32x4ArrayCid));
+  }
+
   // Compute sets of loads generated and killed by each block.
   // Additionally compute upwards exposed and generated loads for each block.
   // Exposed loads are those that can be replaced if a corresponding
@@ -1652,30 +1663,44 @@
             killed = aliased_set_->GetKilledSet(old_alias_id);
           }
 
-          if (killed != NULL) {
+          // Find canonical place of store.
+          Place* canonical_place = nullptr;
+          if (CanForwardStore(instr->AsStoreIndexed())) {
+            canonical_place = aliased_set_->LookupCanonical(&place);
+            if (canonical_place != nullptr) {
+              // Is this a redundant store (stored value already resides
+              // in this field)?
+              const intptr_t place_id = canonical_place->id();
+              if (gen->Contains(place_id)) {
+                ASSERT((out_values != nullptr) &&
+                       ((*out_values)[place_id] != nullptr));
+                if ((*out_values)[place_id] == GetStoredValue(instr)) {
+                  if (FLAG_trace_optimization) {
+                    THR_Print("Removing redundant store to place %" Pd
+                              " in block B%" Pd "\n",
+                              instr->place_id(), block->block_id());
+                  }
+                  instr_it.RemoveCurrentFromGraph();
+                  continue;
+                }
+              }
+            }
+          }
+
+          // Update kill/gen/out_values (after inspection of incoming values).
+          if (killed != nullptr) {
             kill->AddAll(killed);
             // There is no need to clear out_values when clearing GEN set
             // because only those values that are in the GEN set
             // will ever be used.
             gen->RemoveAll(killed);
           }
-
-          // Only forward stores to normal arrays, float64, and simd arrays
-          // to loads because other array stores (intXX/uintXX/float32)
-          // may implicitly convert the value stored.
-          StoreIndexedInstr* array_store = instr->AsStoreIndexed();
-          if ((array_store == NULL) || (array_store->class_id() == kArrayCid) ||
-              (array_store->class_id() == kTypedDataFloat64ArrayCid) ||
-              (array_store->class_id() == kTypedDataFloat32ArrayCid) ||
-              (array_store->class_id() == kTypedDataFloat32x4ArrayCid)) {
-            Place* canonical_place = aliased_set_->LookupCanonical(&place);
-            if (canonical_place != NULL) {
-              // Store has a corresponding numbered place that might have a
-              // load. Try forwarding stored value to it.
-              gen->Add(canonical_place->id());
-              if (out_values == NULL) out_values = CreateBlockOutValues();
-              (*out_values)[canonical_place->id()] = GetStoredValue(instr);
-            }
+          if (canonical_place != nullptr) {
+            // Store has a corresponding numbered place that might have a
+            // load. Try forwarding stored value to it.
+            gen->Add(canonical_place->id());
+            if (out_values == nullptr) out_values = CreateBlockOutValues();
+            (*out_values)[canonical_place->id()] = GetStoredValue(instr);
           }
 
           ASSERT(!instr->IsDefinition() ||
@@ -1707,31 +1732,40 @@
         }
 
         // For object allocation forward initial values of the fields to
-        // subsequent loads except for final fields of escaping objects.
-        // Final fields are initialized in constructor which potentially was
-        // not inlined into the function that we are currently optimizing.
-        // However at the same time we assume that values of the final fields
-        // can be forwarded across side-effects. If we add 'null' as known
-        // values for these fields here we will incorrectly propagate this
-        // null across constructor invocation.
-        AllocateObjectInstr* alloc = instr->AsAllocateObject();
-        if ((alloc != NULL)) {
+        // subsequent loads (and potential dead stores) except for final
+        // fields of escaping objects. Final fields are initialized in
+        // constructor which potentially was not inlined into the function
+        // that we are currently optimizing. However at the same time we
+        // assume that values of the final fields can be forwarded across
+        // side-effects. If we add 'null' as known values for these fields
+        // here we will incorrectly propagate this null across constructor
+        // invocation.
+        if (auto alloc = instr->AsAllocateObject()) {
           for (Value* use = alloc->input_use_list(); use != NULL;
                use = use->next_use()) {
-            // Look for all immediate loads from this object.
+            // Look for all immediate loads/stores from this object.
             if (use->use_index() != 0) {
               continue;
             }
+            const Slot* slot = nullptr;
+            intptr_t place_id = 0;
+            if (auto load = use->instruction()->AsLoadField()) {
+              slot = &load->slot();
+              place_id = load->place_id();
+            } else if (auto store =
+                           use->instruction()->AsStoreInstanceField()) {
+              slot = &store->slot();
+              place_id = store->place_id();
+            }
 
-            LoadFieldInstr* load = use->instruction()->AsLoadField();
-            if (load != NULL) {
-              // Found a load. Initialize current value of the field to null for
-              // normal fields, or with type arguments.
+            if (slot != nullptr) {
+              // Found a load/store. Initialize current value of the field
+              // to null for normal fields, or with type arguments.
 
               // If the object escapes then don't forward final fields - see
               // the comment above for explanation.
-              if (aliased_set_->CanBeAliased(alloc) &&
-                  load->slot().IsDartField() && load->slot().is_immutable()) {
+              if (aliased_set_->CanBeAliased(alloc) && slot->IsDartField() &&
+                  slot->is_immutable()) {
                 continue;
               }
 
@@ -1740,13 +1774,13 @@
                 ASSERT(alloc->ArgumentCount() == 1);
                 const Slot& type_args_slot = Slot::GetTypeArgumentsSlotFor(
                     graph_->thread(), alloc->cls());
-                if (load->slot().IsIdentical(type_args_slot)) {
+                if (slot->IsIdentical(type_args_slot)) {
                   forward_def = alloc->PushArgumentAt(0)->value()->definition();
                 }
               }
-              gen->Add(load->place_id());
-              if (out_values == NULL) out_values = CreateBlockOutValues();
-              (*out_values)[load->place_id()] = forward_def;
+              gen->Add(place_id);
+              if (out_values == nullptr) out_values = CreateBlockOutValues();
+              (*out_values)[place_id] = forward_def;
             }
           }
           continue;
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 14d97be..a43bb72 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -781,4 +781,74 @@
   EXPECT(boxed_result->value()->definition() == final_load);
 }
 
+static void CountLoadsStores(FlowGraph* flow_graph,
+                             intptr_t* loads,
+                             intptr_t* stores) {
+  for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
+       !block_it.Done(); block_it.Advance()) {
+    for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
+         it.Advance()) {
+      if (it.Current()->IsLoadField()) {
+        (*loads)++;
+      } else if (it.Current()->IsStoreInstanceField()) {
+        (*stores)++;
+      }
+    }
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(LoadOptimizer_RedundantStoresAndLoads) {
+  const char* kScript = R"(
+    class Bar {
+      Bar() { a = null; }
+      Object a;
+    }
+
+    Bar foo() {
+      Bar bar = new Bar();
+      bar.a = null;
+      bar.a = bar;
+      bar.a = bar.a;
+      return bar.a;
+    }
+
+    main() {
+      foo();
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  Invoke(root_library, "main");
+  const auto& function = Function::Handle(GetFunction(root_library, "foo"));
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kApplyICData,
+      CompilerPass::kInlining,
+      CompilerPass::kTypePropagation,
+      CompilerPass::kSelectRepresentations,
+      CompilerPass::kCanonicalize,
+      CompilerPass::kConstantPropagation,
+  });
+
+  ASSERT(flow_graph != nullptr);
+
+  // Before CSE, we have 2 loads and 4 stores.
+  intptr_t bef_loads = 0;
+  intptr_t bef_stores = 0;
+  CountLoadsStores(flow_graph, &bef_loads, &bef_stores);
+  EXPECT_EQ(2, bef_loads);
+  EXPECT_EQ(4, bef_stores);
+
+  DominatorBasedCSE::Optimize(flow_graph);
+
+  // After CSE, no load and only one store remains.
+  intptr_t aft_loads = 0;
+  intptr_t aft_stores = 0;
+  CountLoadsStores(flow_graph, &aft_loads, &aft_stores);
+  EXPECT_EQ(0, aft_loads);
+  EXPECT_EQ(1, aft_stores);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/sexpression.h b/runtime/vm/compiler/backend/sexpression.h
index d1dfe7e..8ed38b2 100644
--- a/runtime/vm/compiler/backend/sexpression.h
+++ b/runtime/vm/compiler/backend/sexpression.h
@@ -64,8 +64,12 @@
   intptr_t start() const { return start_; }
 
 #define S_EXPRESSION_TYPE_CHECK(name, value_type)                              \
-  bool Is##name() { return (As##name() != nullptr); }                          \
-  virtual SExp##name* As##name() { return nullptr; }
+  bool Is##name() const { return (As##name() != nullptr); }                    \
+  SExp##name* As##name() {                                                     \
+    auto const const_this = const_cast<const SExpression*>(this);              \
+    return const_cast<SExp##name*>(const_this->As##name());                    \
+  }                                                                            \
+  virtual const SExp##name* As##name() const { return nullptr; }
 
   FOR_EACH_S_EXPRESSION(S_EXPRESSION_TYPE_CHECK)
   FOR_EACH_ABSTRACT_S_EXPRESSION(S_EXPRESSION_TYPE_CHECK)
@@ -89,7 +93,7 @@
  public:
   explicit SExpAtom(intptr_t start = kInvalidPos) : SExpression(start) {}
 
-  virtual SExpAtom* AsAtom() { return this; }
+  virtual const SExpAtom* AsAtom() const { return this; }
   // No atoms have sub-elements, so they always print to a single line.
   virtual void SerializeTo(Zone* zone,
                            TextBuffer* buffer,
@@ -103,7 +107,7 @@
 };
 
 #define DEFINE_S_EXPRESSION_TYPE_CHECK(name)                                   \
-  virtual SExp##name* As##name() { return this; }                              \
+  virtual const SExp##name* As##name() const { return this; }                  \
   virtual const char* DebugName() const { return #name; }
 
 // The various concrete S-expression atom classes are thin wrappers around
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 824b73a..f310041 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -181,6 +181,10 @@
 
   bool IsIdentical(const Slot& other) const { return this == &other; }
 
+  bool IsContextSlot() const {
+    return kind() == Kind::kCapturedVariable || kind() == Kind::kContext_parent;
+  }
+
  private:
   friend class FlowGraphDeserializer;  // For GetNativeSlot.
 
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index 65156bf..3d1a906 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -13,7 +13,7 @@
 
 namespace dart {
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
+#if defined(DART_PRECOMPILER)
 
 // This test asserts that we are inlining accesses to typed data interfaces
 // (e.g. Uint8List) if there are no instantiated 3rd party classes.
@@ -445,6 +445,6 @@
   }
 }
 
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
+#endif  // defined(DART_PRECOMPILER)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 2d10861..9fd7c9d 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -741,6 +741,9 @@
   // Inline implicit instance getter.
   Field& field = Field::ZoneHandle(Z, targets.FirstTarget().accessor_field());
   ASSERT(!field.IsNull());
+  if (field.needs_load_guard()) {
+    return false;
+  }
   if (should_clone_fields_) {
     field = field.CloneFromOriginal();
   }
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index a722851..7188785 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -13,7 +13,6 @@
   "asm_intrinsifier.h",
   "asm_intrinsifier_arm.cc",
   "asm_intrinsifier_arm64.cc",
-  "asm_intrinsifier_dbc.cc",
   "asm_intrinsifier_ia32.cc",
   "asm_intrinsifier_x64.cc",
   "assembler/assembler.cc",
@@ -22,8 +21,6 @@
   "assembler/assembler_arm.h",
   "assembler/assembler_arm64.cc",
   "assembler/assembler_arm64.h",
-  "assembler/assembler_dbc.cc",
-  "assembler/assembler_dbc.h",
   "assembler/assembler_ia32.cc",
   "assembler/assembler_ia32.h",
   "assembler/assembler_x64.cc",
@@ -32,7 +29,6 @@
   "assembler/disassembler.h",
   "assembler/disassembler_arm.cc",
   "assembler/disassembler_arm64.cc",
-  "assembler/disassembler_dbc.cc",
   "assembler/disassembler_kbc.cc",
   "assembler/disassembler_kbc.h",
   "assembler/disassembler_x86.cc",
@@ -47,6 +43,8 @@
   "backend/compile_type.h",
   "backend/constant_propagator.cc",
   "backend/constant_propagator.h",
+  "backend/evaluator.cc",
+  "backend/evaluator.h",
   "backend/flow_graph.cc",
   "backend/flow_graph.h",
   "backend/flow_graph_checker.cc",
@@ -55,14 +53,12 @@
   "backend/flow_graph_compiler.h",
   "backend/flow_graph_compiler_arm.cc",
   "backend/flow_graph_compiler_arm64.cc",
-  "backend/flow_graph_compiler_dbc.cc",
   "backend/flow_graph_compiler_ia32.cc",
   "backend/flow_graph_compiler_x64.cc",
   "backend/il.cc",
   "backend/il.h",
   "backend/il_arm.cc",
   "backend/il_arm64.cc",
-  "backend/il_dbc.cc",
   "backend/il_deserializer.cc",
   "backend/il_deserializer.h",
   "backend/il_ia32.cc",
@@ -149,26 +145,13 @@
   "stub_code_compiler.h",
   "stub_code_compiler_arm.cc",
   "stub_code_compiler_arm64.cc",
-  "stub_code_compiler_dbc.cc",
   "stub_code_compiler_ia32.cc",
   "stub_code_compiler_x64.cc",
 ]
 
-# The most common way to include assembly files in C projects is to have
-# separate assembly files per architecture and operating system (for example
-# boringssl).
-#
-# Not that this diverges from our convention to build every file on every OS
-# but have ifdef guards which make the files empty on some configurations.
-if (is_linux || is_mac) {
-  # MASM on Windows does not support c preproccesor style flags.
-  compiler_sources += [ "ffi_dbc_trampoline_x64_linux_mac.S" ]
-}
-
 compiler_sources_tests = [
   "assembler/assembler_arm64_test.cc",
   "assembler/assembler_arm_test.cc",
-  "assembler/assembler_dbc_test.cc",
   "assembler/assembler_ia32_test.cc",
   "assembler/assembler_test.cc",
   "assembler/assembler_x64_test.cc",
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index 596d43c..90af59d 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -137,28 +137,8 @@
 #error "Unknown platform. Please add alignment requirements for ABI."
 #endif
 
-#if defined(TARGET_ARCH_DBC)
-static Abi HostAbi() {
-#if defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM64)
-  return Abi::kWordSize64;
-#elif (defined(HOST_ARCH_IA32) && /* NOLINT(whitespace/parens) */              \
-       (defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) ||                    \
-        defined(HOST_OS_ANDROID))) ||                                          \
-    (defined(HOST_ARCH_ARM) && defined(HOST_OS_IOS))
-  return Abi::kWordSize32Align32;
-#elif defined(HOST_ARCH_IA32) && defined(HOST_OS_WINDOWS) ||                   \
-    defined(HOST_ARCH_ARM)
-  return Abi::kWordSize32Align64;
-#else
-#error "Unknown platform. Please add alignment requirements for ABI."
-#endif
-}
-#endif  // defined(TARGET_ARCH_DBC)
-
 Abi TargetAbi() {
-#if defined(TARGET_ARCH_DBC)
-  return HostAbi();
-#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
   return Abi::kWordSize64;
 #elif (defined(TARGET_ARCH_IA32) && /* NOLINT(whitespace/parens) */            \
        (defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS) ||                \
@@ -260,8 +240,6 @@
   return rep;
 }
 
-#if !defined(TARGET_ARCH_DBC)
-
 RawFunction* NativeCallbackFunction(const Function& c_signature,
                                     const Function& dart_target,
                                     const Instance& exceptional_return) {
@@ -323,8 +301,6 @@
   return ResultRepresentationBase<CallingConventions>(signature);
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 #if defined(USING_SIMULATOR)
 
 ZoneGrowableArray<Representation>* ArgumentHostRepresentations(
@@ -459,7 +435,6 @@
   intptr_t stack_height_in_slots = 0;
 };
 
-#if !defined(TARGET_ARCH_DBC)
 ZoneGrowableArray<Location>*
 CallbackArgumentTranslator::TranslateArgumentLocations(
     const ZoneGrowableArray<Location>& arg_locs) {
@@ -528,7 +503,6 @@
   argument_slots_used_ += 8 / target::kWordSize;
   return result;
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 // Takes a list of argument representations, and converts it to a list of
 // argument locations based on calling convention.
@@ -553,33 +527,11 @@
 
 ZoneGrowableArray<Location>* ArgumentLocations(
     const ZoneGrowableArray<Representation>& arg_reps) {
-#if !defined(TARGET_ARCH_DBC)
   return ArgumentLocationsBase<dart::CallingConventions, Location,
                                dart::Register, dart::FpuRegister>(arg_reps);
-#else
-  intptr_t next_free_register = ffi::kFirstArgumentRegister;
-  intptr_t num_arguments = arg_reps.length();
-  auto result = new ZoneGrowableArray<Location>(num_arguments);
-  for (intptr_t i = 0; i < num_arguments; i++) {
-    // TODO(dacoharkes): In 32 bits, use pair locations.
-    result->Add(Location::RegisterLocation(next_free_register));
-    next_free_register++;
-  }
-  return result;
-#endif
 }
 
-#if defined(TARGET_ARCH_DBC)
-ZoneGrowableArray<HostLocation>* HostArgumentLocations(
-    const ZoneGrowableArray<Representation>& arg_reps) {
-  return ArgumentLocationsBase<dart::host::CallingConventions, HostLocation,
-                               dart::host::Register, dart::host::FpuRegister>(
-      arg_reps);
-}
-#endif
-
 Location ResultLocation(Representation result_rep) {
-#ifndef TARGET_ARCH_DBC
   switch (result_rep) {
     case kUnboxedFloat:
     case kUnboxedDouble:
@@ -604,10 +556,6 @@
     default:
       UNREACHABLE();
   }
-#else
-  // TODO(dacoharkes): Support 64 bit result values on 32 bit DBC.
-  return Location::RegisterLocation(0);
-#endif
 }
 
 // TODO(36607): Cache the trampolines.
@@ -675,85 +623,6 @@
   return TemplateNumStackSlots(locations);
 }
 
-#if defined(TARGET_ARCH_DBC)
-
-static RawTypedData* typed_data_new_uintptr(intptr_t length) {
-#if defined(ARCH_IS_32_BIT)
-  return TypedData::New(kTypedDataUint32ArrayCid, length);
-#else
-  return TypedData::New(kTypedDataUint64ArrayCid, length);
-#endif
-}
-
-static void typed_data_set_uintptr(const TypedData& typed_data,
-                                   intptr_t index,
-                                   uintptr_t value) {
-#if defined(ARCH_IS_32_BIT)
-  typed_data.SetUint32(target::kWordSize * index, value);
-#else
-  typed_data.SetUint64(target::kWordSize * index, value);
-#endif
-}
-
-static uintptr_t typed_data_get_uintptr(const TypedData& typed_data,
-                                        intptr_t index) {
-#if defined(ARCH_IS_32_BIT)
-  return typed_data.GetUint32(target::kWordSize * index);
-#else
-  return typed_data.GetUint64(target::kWordSize * index);
-#endif
-}
-
-// Number of host stack slots used in 'locations'.
-static intptr_t HostNumStackSlots(
-    const ZoneGrowableArray<HostLocation>& locations) {
-  return TemplateNumStackSlots(locations);
-}
-
-RawTypedData* FfiSignatureDescriptor::New(
-    const ZoneGrowableArray<HostLocation>& arg_host_locations,
-    const Representation result_representation) {
-  const uintptr_t num_arguments = arg_host_locations.length();
-  const uintptr_t num_stack_slots = HostNumStackSlots(arg_host_locations);
-
-  const TypedData& result = TypedData::Handle(
-      typed_data_new_uintptr(kOffsetArgumentLocations + num_arguments));
-
-  typed_data_set_uintptr(result, kOffsetNumArguments, num_arguments);
-  typed_data_set_uintptr(result, kOffsetNumStackSlots, num_stack_slots);
-  typed_data_set_uintptr(result, kOffsetResultRepresentation,
-                         result_representation);
-
-  for (uintptr_t i = 0; i < num_arguments; i++) {
-    typed_data_set_uintptr(result, kOffsetArgumentLocations + i,
-                           arg_host_locations.At(i).write());
-  }
-
-  return result.raw();
-}
-
-intptr_t FfiSignatureDescriptor::length() const {
-  return typed_data_get_uintptr(typed_data_, kOffsetNumArguments);
-}
-
-intptr_t FfiSignatureDescriptor::num_stack_slots() const {
-  return typed_data_get_uintptr(typed_data_, kOffsetNumStackSlots);
-}
-
-HostLocation FfiSignatureDescriptor::LocationAt(intptr_t index) const {
-  return HostLocation::read(
-      typed_data_get_uintptr(typed_data_, kOffsetArgumentLocations + index));
-}
-
-Representation FfiSignatureDescriptor::ResultRepresentation() const {
-  uintptr_t result_int =
-      typed_data_get_uintptr(typed_data_, kOffsetResultRepresentation);
-  ASSERT(result_int < kNumRepresentations);
-  return static_cast<Representation>(result_int);
-}
-
-#endif  // defined(TARGET_ARCH_DBC)
-
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace ffi
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index ea35203..a1b50b1 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -60,8 +60,6 @@
 RawFunction* TrampolineFunction(const Function& dart_signature,
                                 const Function& c_signature);
 
-#if !defined(TARGET_ARCH_DBC)
-
 RawFunction* NativeCallbackFunction(const Function& c_signature,
                                     const Function& dart_target,
                                     const Instance& exceptional_return);
@@ -73,19 +71,6 @@
 // Unboxed representation of the result of a C signature function.
 Representation ResultRepresentation(const Function& signature);
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
-#if defined(USING_SIMULATOR)
-
-// Unboxed host representations of the arguments to a C signature function.
-ZoneGrowableArray<Representation>* ArgumentHostRepresentations(
-    const Function& signature);
-
-// Unboxed host representation of the result of a C signature function.
-Representation ResultHostRepresentation(const Function& signature);
-
-#endif  // defined(USING_SIMULATOR)
-
 // Location for the arguments of a C signature function.
 ZoneGrowableArray<Location>* ArgumentLocations(
     const ZoneGrowableArray<Representation>& arg_reps);
@@ -93,44 +78,6 @@
 // Number of stack slots used in 'locations'.
 intptr_t NumStackSlots(const ZoneGrowableArray<Location>& locations);
 
-#if defined(TARGET_ARCH_DBC)
-
-// The first argument to a ffi trampoline is the function address, the arguments
-// to the call follow the function address.
-const intptr_t kFunctionAddressRegister = 0;
-const intptr_t kFirstArgumentRegister = 1;
-
-// Location in host for the arguments of a C signature function.
-ZoneGrowableArray<HostLocation>* HostArgumentLocations(
-    const ZoneGrowableArray<Representation>& arg_reps);
-
-// A signature descriptor consists of the signature length, argument locations,
-// and result representation.
-class FfiSignatureDescriptor : public ValueObject {
- public:
-  explicit FfiSignatureDescriptor(const TypedData& typed_data)
-      : typed_data_(typed_data) {}
-
-  static RawTypedData* New(
-      const ZoneGrowableArray<HostLocation>& arg_host_locations,
-      const Representation result_representation);
-
-  intptr_t length() const;
-  intptr_t num_stack_slots() const;
-  HostLocation LocationAt(intptr_t index) const;
-  Representation ResultRepresentation() const;
-
- private:
-  const TypedData& typed_data_;
-
-  static const intptr_t kOffsetNumArguments = 0;
-  static const intptr_t kOffsetNumStackSlots = 1;
-  static const intptr_t kOffsetResultRepresentation = 2;
-  static const intptr_t kOffsetArgumentLocations = 3;
-};
-
-#else  // defined(TARGET_ARCH_DBC)
-
 // 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.
 //
@@ -155,7 +102,6 @@
   intptr_t argument_slots_used_ = 0;
   intptr_t argument_slots_required_ = 0;
 };
-#endif  // defined(TARGET_ARCH_DBC)
 
 }  // namespace ffi
 
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline.h b/runtime/vm/compiler/ffi_dbc_trampoline.h
deleted file mode 100644
index 656d1e1..0000000
--- a/runtime/vm/compiler/ffi_dbc_trampoline.h
+++ /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.
-
-#ifndef RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
-#define RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
-
-#include "vm/globals.h"
-
-namespace dart {
-
-#if defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS)
-
-// Generic Trampoline for DBC dart:ffi calls. Argument needs to be layed out as
-// a FfiMarshalledArguments.
-extern "C" void FfiTrampolineCall(uint64_t* ffi_marshalled_args);
-
-#else
-
-void FfiTrampolineCall(uint64_t* ffi_marshalled_args) {
-  UNREACHABLE();
-}
-
-#endif  //  defined(HOST_ARCH_X64) && !defined(HOST_OS_WINDOWS)
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_COMPILER_FFI_DBC_TRAMPOLINE_H_
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
deleted file mode 100644
index 4f42279..0000000
--- a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
+++ /dev/null
@@ -1,77 +0,0 @@
-#if defined(_M_X64) || defined(__x86_64__) /* HOST_ARCH_X64 */
-
-.intel_syntax noprefix
-.text
-
-#if defined(__linux__) || defined(__FreeBSD__) /* HOST_OS_LINUX */
-.globl FfiTrampolineCall
-.type FfiTrampolineCall, @function
-FfiTrampolineCall:
-#else /* HOST_OS_MACOS */
-.globl _FfiTrampolineCall
-_FfiTrampolineCall:
-#endif
-
-/* Save argument in scratch register. */
-push  rbx              /* Backup caller saved register. */
-mov   rbx,  rdi        /* Save argument in scratch register. */
-
-/* Enter frame. */
-push  rbp
-mov   rbp,  rsp
-
-/* Reserve framespace for arguments. */
-mov   rax,  [rbx+0x80] /* Load number of stack arguments. */
-shl   rax,  3          /* Multiply by size (8 bytes). */
-sub   rsp,  rax        /* Reserve num_stack_args stack slots. */
-
-/* Stack alignment. */
-and   rsp,  [rbx+0x78] /* Align stack with stack alignment mask. */
-
-/* Copy stack arguments. */
-cmp   rax,  0x0        /* Check if number of stack arguments is 0. */
-jz    .done            /* Skip loop if no stack arguments. */
-add   rsp,  rax        /* Unreserve stack slots so we can push arguments. */
-add   rbx,  0x80       /* Offset RBX to point to stack arguments */
-.loop:                 /* Copy stack arguments loop. */
-push  [rbx+rax]        /* Push stack argument. */
-sub   rax,  0x8        /* Decrement stack argument iterator. */
-cmp   rax,  0x0        /* Compare iterator with 0 */
-jnz   .loop            /* Loop while iterator is not 0 */
-sub   rbx,  0x80       /* Restore RBX to original value. */
-.done:                 /* End stack arguments loop. */
-
-/* Copy registers and fpu registers. */
-mov   rdi,  [rbx+0x8]  /* kArg1Reg */
-mov   rsi,  [rbx+0x10] /* kArg2Reg */
-mov   rdx,  [rbx+0x18] /* kArg3Reg */
-mov   rcx,  [rbx+0x20] /* kArg4Reg */
-mov   r8,   [rbx+0x28] /* kArg5Reg */
-mov   r9,   [rbx+0x30] /* kArg6Reg */
-movsd xmm0, [rbx+0x38]
-movsd xmm1, [rbx+0x40]
-movsd xmm2, [rbx+0x48]
-movsd xmm3, [rbx+0x50]
-movsd xmm4, [rbx+0x58]
-movsd xmm5, [rbx+0x60]
-movsd xmm6, [rbx+0x68]
-movsd xmm7, [rbx+0x70]
-
-/* Do call. */
-mov   rax,  [rbx] /* function address */
-call  rax         /* Call the function. */
-
-/* Copy results back. */
-mov   [rbx],   rax  /* Move integer result in kOffsetIntResult */
-movsd [rbx+8], xmm0 /* Move double result in kOffsetDoubleResult */
-
-/* leave frame */
-mov   rsp,  rbp
-pop   rbp
-
-/* Restore caller saved register. */
-pop   rbx
-
-ret
-
-#endif /* HOST_ARCH_X64 */
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index bb70abe..9b216a9 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -478,19 +478,22 @@
 Fragment BaseFlowGraphBuilder::StoreInstanceField(
     TokenPosition position,
     const Slot& field,
-    StoreBarrierType emit_store_barrier) {
+    StoreInstanceFieldInstr::Kind
+        kind /* = StoreInstanceFieldInstr::Kind::kOther */,
+    StoreBarrierType emit_store_barrier /* = kEmitStoreBarrier */) {
   Value* value = Pop();
   if (value->BindsToConstant()) {
     emit_store_barrier = kNoStoreBarrier;
   }
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
-      field, Pop(), value, emit_store_barrier, position);
+      field, Pop(), value, emit_store_barrier, position, kind);
   return Fragment(store);
 }
 
 Fragment BaseFlowGraphBuilder::StoreInstanceField(
     const Field& field,
-    bool is_initialization_store,
+    StoreInstanceFieldInstr::Kind
+        kind /* = StoreInstanceFieldInstr::Kind::kOther */,
     StoreBarrierType emit_store_barrier) {
   Value* value = Pop();
   if (value->BindsToConstant()) {
@@ -499,16 +502,15 @@
 
   StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
       MayCloneField(field), Pop(), value, emit_store_barrier,
-      TokenPosition::kNoSource, parsed_function_,
-      is_initialization_store ? StoreInstanceFieldInstr::Kind::kInitializing
-                              : StoreInstanceFieldInstr::Kind::kOther);
+      TokenPosition::kNoSource, parsed_function_, kind);
 
   return Fragment(store);
 }
 
 Fragment BaseFlowGraphBuilder::StoreInstanceFieldGuarded(
     const Field& field,
-    bool is_initialization_store) {
+    StoreInstanceFieldInstr::Kind
+        kind /* = StoreInstanceFieldInstr::Kind::kOther */) {
   Fragment instructions;
   const Field& field_clone = MayCloneField(field);
   if (I->use_field_guards()) {
@@ -537,7 +539,7 @@
           new (Z) GuardFieldTypeInstr(Pop(), field_clone, GetNextDeoptId());
     }
   }
-  instructions += StoreInstanceField(field_clone, is_initialization_store);
+  instructions += StoreInstanceField(field_clone, kind);
   return instructions;
 }
 
@@ -628,10 +630,15 @@
   variable->set_index(
       VariableIndex(-parsed_function_->num_stack_locals() - index));
 
-  // The value has uses as if it were a local variable.  Mark the definition
-  // as used so that its temp index will not be cleared (causing it to never
-  // be materialized in the expression stack).
-  stack_->definition()->set_ssa_temp_index(0);
+  // The value on top of the stack has uses as if it were a local variable.
+  // Mark all definitions on the stack as used so that their temp indices
+  // will not be cleared (causing them to never be materialized in the
+  // expression stack and skew stack depth).
+  for (Value* item = stack_; item != nullptr; item = item->next_use()) {
+    if (!item->definition()->IsPushArgument()) {
+      item->definition()->set_ssa_temp_index(0);
+    }
+  }
 
   return variable;
 }
@@ -933,12 +940,13 @@
 
   code += LoadLocal(closure);
   code += LoadLocal(context);
-  code += StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context());
+  code += StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context(),
+                             StoreInstanceFieldInstr::Kind::kInitializing);
 
   code += LoadLocal(closure);
   code += Constant(target);
-  code +=
-      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_function());
+  code += StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_function(),
+                             StoreInstanceFieldInstr::Kind::kInitializing);
 
   // Drop address and context.
   code += DropTempsPreserveTop(2);
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 8caed54..dc8043b 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -186,13 +186,17 @@
   Fragment StoreInstanceField(
       TokenPosition position,
       const Slot& field,
+      StoreInstanceFieldInstr::Kind kind =
+          StoreInstanceFieldInstr::Kind::kOther,
       StoreBarrierType emit_store_barrier = kEmitStoreBarrier);
   Fragment StoreInstanceField(
       const Field& field,
-      bool is_initialization_store,
+      StoreInstanceFieldInstr::Kind kind =
+          StoreInstanceFieldInstr::Kind::kOther,
       StoreBarrierType emit_store_barrier = kEmitStoreBarrier);
   Fragment StoreInstanceFieldGuarded(const Field& field,
-                                     bool is_initialization_store);
+                                     StoreInstanceFieldInstr::Kind kind =
+                                         StoreInstanceFieldInstr::Kind::kOther);
   Fragment LoadStaticField();
   Fragment RedefinitionWithType(const AbstractType& type);
   Fragment StoreStaticField(TokenPosition position, const Field& field);
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 39adce9..dd1ae70 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -441,7 +441,6 @@
   for (intptr_t i = count - 1; i >= 0; --i) {
     ASSERT(!IsStackEmpty());
     Definition* arg_def = B->stack_->definition();
-    ASSERT(!arg_def->HasSSATemp());
     ASSERT(arg_def->temp_index() >= i);
 
     PushArgumentInstr* argument = new (Z) PushArgumentInstr(Pop());
@@ -1066,13 +1065,9 @@
 
   // A DebugStepCheck is performed as part of the calling stub.
 
-  const UnlinkedCall& selector =
-      UnlinkedCall::Cast(ConstantAt(DecodeOperandD()).value());
-
+  const String& name = String::Cast(ConstantAt(DecodeOperandD()).value());
   const ArgumentsDescriptor arg_desc(
-      Array::Handle(Z, selector.args_descriptor()));
-
-  const String& name = String::ZoneHandle(Z, selector.target_name());
+      Array::Cast(ConstantAt(DecodeOperandD(), 1).value()));
 
   Token::Kind token_kind;
   intptr_t checked_argument_count;
@@ -1218,13 +1213,15 @@
 
   if (field.Owner() == isolate()->object_store()->closure_class()) {
     // Stores to _Closure fields are lower-level.
-    code_ += B->StoreInstanceField(position_, ClosureSlotByField(field));
+    code_ +=
+        B->StoreInstanceField(position_, ClosureSlotByField(field),
+                              StoreInstanceFieldInstr::Kind::kInitializing);
   } else {
     // The rest of the StoreFieldTOS are for field initializers.
     // TODO(alexmarkov): Consider adding a flag to StoreFieldTOS or even
     // adding a separate bytecode instruction.
-    code_ += B->StoreInstanceFieldGuarded(field,
-                                          /* is_initialization_store = */ true);
+    code_ += B->StoreInstanceFieldGuarded(
+        field, StoreInstanceFieldInstr::Kind::kInitializing);
   }
 }
 
@@ -1251,7 +1248,8 @@
 void BytecodeFlowGraphBuilder::BuildStoreContextParent() {
   LoadStackSlots(2);
 
-  code_ += B->StoreInstanceField(position_, Slot::Context_parent());
+  code_ += B->StoreInstanceField(position_, Slot::Context_parent(),
+                                 StoreInstanceFieldInstr::Kind::kInitializing);
 }
 
 void BytecodeFlowGraphBuilder::BuildLoadContextParent() {
@@ -1332,18 +1330,6 @@
   code_ += B->LoadStaticField();
 }
 
-static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 19,
-              "Cleanup PushStatic bytecode instruction");
-void BytecodeFlowGraphBuilder::BuildPushStatic() {
-  // Note: Field object is both pushed into the stack and
-  // available in constant pool entry D.
-  // TODO(alexmarkov): clean this up. If we stop pushing field object
-  // explicitly, we might need the following code to get it from constant
-  // pool: PushConstant(ConstantAt(DecodeOperandD()));
-
-  code_ += B->LoadStaticField();
-}
-
 void BytecodeFlowGraphBuilder::BuildStoreIndexedTOS() {
   LoadStackSlots(3);
   code_ += B->StoreIndexed(kArrayCid);
@@ -1424,7 +1410,7 @@
   code_ <<= instr;
 }
 
-void BytecodeFlowGraphBuilder::BuildCheckReceiverForNull() {
+void BytecodeFlowGraphBuilder::BuildNullCheck() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
   }
@@ -1932,9 +1918,6 @@
 //             static tearoff
 // <type args> => [NativeSignatureType]
 void BytecodeFlowGraphBuilder::BuildFfiNativeCallbackFunction() {
-#if defined(TARGET_ARCH_DBC)
-  UNREACHABLE();
-#else
   const TypeArguments& type_args =
       TypeArguments::Cast(B->Peek(/*depth=*/2)->AsConstant()->value());
   ASSERT(type_args.IsInstantiated() && type_args.Length() == 1);
@@ -1956,7 +1939,6 @@
                                   native_sig, target, exceptional_return));
   code_ += B->Constant(result);
   code_ += B->DropTempsPreserveTop(3);
-#endif
 }
 
 void BytecodeFlowGraphBuilder::BuildDebugStepCheck() {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 5399205..c32f8d2 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -457,6 +457,7 @@
   const int kIsAsyncStarFlag = 1 << 5;
   const int kIsSyncStarFlag = 1 << 6;
   const int kIsDebuggableFlag = 1 << 7;
+  const int kHasAttributesFlag = 1 << 8;
 
   const intptr_t flags = reader_.ReadUInt();
 
@@ -501,14 +502,18 @@
   closures_->SetAt(closureIndex, closure);
 
   Type& signature_type = Type::Handle(
-      Z, ReadFunctionSignature(closure,
-                               (flags & kHasOptionalPositionalParamsFlag) != 0,
-                               (flags & kHasOptionalNamedParamsFlag) != 0,
-                               (flags & kHasTypeParamsFlag) != 0,
-                               /* has_positional_param_names = */ true));
+      Z, ReadFunctionSignature(
+             closure, (flags & kHasOptionalPositionalParamsFlag) != 0,
+             (flags & kHasOptionalNamedParamsFlag) != 0,
+             (flags & kHasTypeParamsFlag) != 0,
+             /* has_positional_param_names = */ true, kNonNullable));
 
   closure.SetSignatureType(signature_type);
 
+  if ((flags & kHasAttributesFlag) != 0) {
+    ReadAttributes(closure);
+  }
+
   I->AddClosureFunction(closure);
 }
 
@@ -546,7 +551,8 @@
     bool has_optional_positional_params,
     bool has_optional_named_params,
     bool has_type_params,
-    bool has_positional_param_names) {
+    bool has_positional_param_names,
+    Nullability nullability) {
   FunctionTypeScope function_type_scope(this);
 
   if (has_type_params) {
@@ -594,7 +600,7 @@
   func.set_result_type(type);
 
   // Finalize function type.
-  type = func.SignatureType();
+  type = func.SignatureType(nullability);
   ClassFinalizer::FinalizationKind finalization = ClassFinalizer::kCanonicalize;
   if (pending_recursive_types_ != nullptr && HasNonCanonicalTypes(Z, func)) {
     // This function type is a part of recursive type. Avoid canonicalization
@@ -691,7 +697,7 @@
     kUnused4,
     kUnused5,
     kUnused6,
-    kICData,  // Obsolete in bytecode v20.
+    kUnused6a,
     kUnused7,
     kStaticField,
     kInstanceField,
@@ -719,18 +725,8 @@
     kDirectCallViaDynamicForwarder,
   };
 
-  enum InvocationKind {
-    method,  // x.foo(...) or foo(...)
-    getter,  // x.foo
-    setter   // x.foo = ...
-  };
-
-  const int kInvocationKindMask = 0x3;
-  const int kFlagDynamic = 1 << 2;
-
   Object& obj = Object::Handle(Z);
   Object& elem = Object::Handle(Z);
-  Array& array = Array::Handle(Z);
   Field& field = Field::Handle(Z);
   Class& cls = Class::Handle(Z);
   String& name = String::Handle(Z);
@@ -740,33 +736,6 @@
     switch (tag) {
       case ConstantPoolTag::kInvalid:
         UNREACHABLE();
-      case ConstantPoolTag::kICData: {
-        static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 20,
-                      "Cleanup ICData constant pool entry");
-        intptr_t flags = reader_.ReadByte();
-        InvocationKind kind =
-            static_cast<InvocationKind>(flags & kInvocationKindMask);
-        bool isDynamic = (flags & kFlagDynamic) != 0;
-        name ^= ReadObject();
-        ASSERT(name.IsSymbol());
-        intptr_t arg_desc_index = reader_.ReadUInt();
-        ASSERT(arg_desc_index < i);
-        array ^= pool.ObjectAt(arg_desc_index);
-        // Do not mangle == or call:
-        //   * operator == takes an Object so its either not checked or checked
-        //     at the entry because the parameter is marked covariant, neither
-        //     of those cases require a dynamic invocation forwarder;
-        //   * we assume that all closures are entered in a checked way.
-        if (isDynamic && (kind != InvocationKind::getter) &&
-            I->should_emit_strong_mode_checks() &&
-            (name.raw() != Symbols::EqualOperator().raw()) &&
-            (name.raw() != Symbols::Call().raw())) {
-          name = Function::CreateDynamicInvocationForwarderName(name);
-        }
-        obj = UnlinkedCall::New();
-        UnlinkedCall::Cast(obj).set_target_name(name);
-        UnlinkedCall::Cast(obj).set_args_descriptor(array);
-      } break;
       case ConstantPoolTag::kStaticField:
         obj = ReadObject();
         ASSERT(obj.IsField());
@@ -890,7 +859,6 @@
       case ConstantPoolTag::kDynamicCall: {
         name ^= ReadObject();
         ASSERT(name.IsSymbol());
-        array ^= ReadObject();
         // Do not mangle == or call:
         //   * operator == takes an Object so it is either not checked or
         //     checked at the entry because the parameter is marked covariant,
@@ -901,21 +869,15 @@
             (name.raw() != Symbols::Call().raw())) {
           name = Function::CreateDynamicInvocationForwarderName(name);
         }
-        static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 20,
-                      "Can use 2 slots in object pool");
         // DynamicCall constant occupies 2 entries: selector and arguments
-        // descriptor. For backwards compatibility with ICData constants
-        // selector and arguments descriptor are packaged into UnlinkedCall
-        // object. The 2nd slot is filled with null.
-        obj = UnlinkedCall::New();
-        UnlinkedCall::Cast(obj).set_target_name(name);
-        UnlinkedCall::Cast(obj).set_args_descriptor(array);
+        // descriptor.
         pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
                        ObjectPool::Patchability::kNotPatchable);
-        pool.SetObjectAt(i, obj);
+        pool.SetObjectAt(i, name);
         ++i;
         ASSERT(i < obj_count);
-        obj = Object::null();
+        // The second entry is used for arguments descriptor.
+        obj = ReadObject();
       } break;
       case ConstantPoolTag::kDirectCallViaDynamicForwarder: {
         // DirectCallViaDynamicForwarder constant occupies 2 entries.
@@ -1534,14 +1496,20 @@
             ReadSourceFile(uri, bytecode_component_->GetSourceFilesOffset() +
                                     reader_.ReadUInt());
       } else {
-        script = Script::New(uri, Object::null_string(), RawScript::kKernelTag);
+        script = Script::New(uri, Object::null_string());
       }
       script.set_kernel_program_info(H.GetKernelProgramInfo());
       return script.raw();
     }
     case kType: {
-      const intptr_t tag = flags / kFlagBit0;
-      return ReadType(tag);
+      const intptr_t tag = (flags & kTagMask) / kFlagBit0;
+      static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 24,
+                    "Cleanup condition");
+      const Nullability nullability =
+          bytecode_component_->GetVersion() >= 24
+              ? static_cast<Nullability>((flags & kNullabilityMask) / kFlagBit4)
+              : kLegacy;
+      return ReadType(tag, nullability);
     }
     default:
       UNREACHABLE();
@@ -1663,7 +1631,8 @@
   return Object::null();
 }
 
-RawObject* BytecodeReaderHelper::ReadType(intptr_t tag) {
+RawObject* BytecodeReaderHelper::ReadType(intptr_t tag,
+                                          Nullability nullability) {
   // Must be in sync with enum TypeTag in
   // pkg/vm/lib/bytecode/object_table.dart.
   enum TypeTag {
@@ -1676,6 +1645,7 @@
     kRecursiveGenericType,
     kRecursiveTypeRef,
     kFunctionType,
+    kNever,
   };
 
   // FunctionType flags, must be in sync with _FunctionTypeHandle constants in
@@ -1692,12 +1662,21 @@
       return AbstractType::dynamic_type().raw();
     case kVoid:
       return AbstractType::void_type().raw();
+    case kNever:
+      return AbstractType::never_type().raw();
     case kSimpleType: {
       const Class& cls = Class::CheckedHandle(Z, ReadObject());
       if (!cls.is_declaration_loaded()) {
         LoadReferencedClass(cls);
       }
-      return cls.DeclarationType();
+      Type& type = Type::Handle(Z, cls.DeclarationType());
+      // TODO(regis): Remove this workaround once nullability of Null provided
+      // by CFE is always kNullable.
+      if (type.IsNullType()) {
+        ASSERT(type.IsNullable());
+        return type.raw();
+      }
+      return type.ToNullability(nullability, Heap::kOld);
     }
     case kTypeParameter: {
       Object& parent = Object::Handle(Z, ReadObject());
@@ -1720,7 +1699,9 @@
       } else {
         UNREACHABLE();
       }
-      return type_parameters.TypeAt(index_in_parent);
+      TypeParameter& type_parameter = TypeParameter::Handle(Z);
+      type_parameter ^= type_parameters.TypeAt(index_in_parent);
+      return type_parameter.ToNullability(nullability, Heap::kOld);
     }
     case kGenericType: {
       const Class& cls = Class::CheckedHandle(Z, ReadObject());
@@ -1731,6 +1712,7 @@
           TypeArguments::CheckedHandle(Z, ReadObject());
       const Type& type = Type::Handle(
           Z, Type::New(cls, type_arguments, TokenPosition::kNoSource));
+      type.set_nullability(nullability);
       type.SetIsFinalized();
       return type.Canonicalize();
     }
@@ -1762,6 +1744,7 @@
 
       Type& type = Type::Handle(
           Z, Type::New(cls, type_arguments, TokenPosition::kNoSource));
+      type.set_nullability(nullability);
       type_ref.set_type(type);
       type.SetIsFinalized();
       if (id != 0) {
@@ -1796,7 +1779,7 @@
           signature_function, (flags & kFlagHasOptionalPositionalParams) != 0,
           (flags & kFlagHasOptionalNamedParams) != 0,
           (flags & kFlagHasTypeParams) != 0,
-          /* has_positional_param_names = */ false);
+          /* has_positional_param_names = */ false, nullability);
     }
     default:
       UNREACHABLE();
@@ -1883,8 +1866,8 @@
     source = ReadString(/* is_canonical = */ false);
   }
 
-  const Script& script = Script::Handle(
-      Z, Script::New(import_uri, uri, source, RawScript::kKernelTag));
+  const Script& script =
+      Script::Handle(Z, Script::New(import_uri, uri, source));
   script.set_line_starts(line_starts);
 
   if (source.IsNull() && line_starts.IsNull()) {
@@ -2064,13 +2047,7 @@
       }
     }
 
-    static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 14,
-                  "Cleanup support for old bytecode format versions");
-    const bool has_initializer_code =
-        bytecode_component_->GetVersion() >= 14
-            ? (flags & kHasInitializerCodeFlag) != 0
-            : has_initializer && is_static;
-    if (has_initializer_code) {
+    if ((flags & kHasInitializerCodeFlag) != 0) {
       const intptr_t code_offset = reader_.ReadUInt();
       field.set_bytecode_offset(code_offset +
                                 bytecode_component_->GetCodesOffset());
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index f3d2b12..2afd9dd 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -112,7 +112,11 @@
   static const int kFlagBit1 = 1 << 6;
   static const int kFlagBit2 = 1 << 7;
   static const int kFlagBit3 = 1 << 8;
-  static const int kFlagsMask = (kFlagBit0 | kFlagBit1 | kFlagBit2 | kFlagBit3);
+  static const int kFlagBit4 = 1 << 9;
+  static const int kFlagBit5 = 1 << 10;
+  static const int kTagMask = (kFlagBit0 | kFlagBit1 | kFlagBit2 | kFlagBit3);
+  static const int kNullabilityMask = (kFlagBit4 | kFlagBit5);
+  static const int kFlagsMask = (kTagMask | kNullabilityMask);
 
   // Code flags, must be in sync with Code constants in
   // pkg/vm/lib/bytecode/declarations.dart.
@@ -190,7 +194,8 @@
                                  bool has_optional_positional_params,
                                  bool has_optional_named_params,
                                  bool has_type_params,
-                                 bool has_positional_param_names);
+                                 bool has_positional_param_names,
+                                 Nullability nullability);
   void ReadTypeParametersDeclaration(const Class& parameterized_class,
                                      const Function& parameterized_function);
 
@@ -211,7 +216,7 @@
 
   RawObject* ReadObjectContents(uint32_t header);
   RawObject* ReadConstObject(intptr_t tag);
-  RawObject* ReadType(intptr_t tag);
+  RawObject* ReadType(intptr_t tag, Nullability nullability);
   RawString* ReadString(bool is_canonical = true);
   RawScript* ReadSourceFile(const String& uri, intptr_t offset);
   RawTypeArguments* ReadTypeArguments();
diff --git a/runtime/vm/compiler/frontend/constant_evaluator.cc b/runtime/vm/compiler/frontend/constant_evaluator.cc
index b8409a8..643e0b4 100644
--- a/runtime/vm/compiler/frontend/constant_evaluator.cc
+++ b/runtime/vm/compiler/frontend/constant_evaluator.cc
@@ -457,7 +457,7 @@
     case kInstanceConstant: {
       const NameIndex index = reader.ReadCanonicalNameReference();
       const auto& klass = Class::Handle(Z, H.LookupClassByKernelClass(index));
-      if (!klass.is_declaration_loaded()) {
+      if (!klass.is_declaration_loaded() && !klass.is_declared_in_bytecode()) {
         FATAL1(
             "Trying to evaluate an instance constant whose references class "
             "%s is not loaded yet.",
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 579d7bf..b093215 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -187,7 +187,8 @@
   if (only_for_side_effects) {
     instructions += Drop();
   } else {
-    instructions += flow_graph_builder_->StoreInstanceFieldGuarded(field, true);
+    instructions += flow_graph_builder_->StoreInstanceFieldGuarded(
+        field, StoreInstanceFieldInstr::Kind::kInitializing);
   }
   return instructions;
 }
@@ -674,7 +675,8 @@
         body += LoadLocal(&raw_parameter);
         body += flow_graph_builder_->StoreInstanceField(
             TokenPosition::kNoSource,
-            Slot::GetContextVariableSlotFor(thread(), *variable));
+            Slot::GetContextVariableSlotFor(thread(), *variable),
+            StoreInstanceFieldInstr::Kind::kInitializing);
         body += NullConstant();
         body += StoreLocal(TokenPosition::kNoSource, &raw_parameter);
         body += Drop();
@@ -991,13 +993,6 @@
   ActiveTypeParametersScope active_type_params(active_class(), function, Z);
 
   if (function.is_declared_in_bytecode()) {
-    if (!(FLAG_use_bytecode_compiler || FLAG_enable_interpreter)) {
-      FATAL1(
-          "Cannot run bytecode function %s: specify --enable-interpreter or "
-          "--use-bytecode-compiler",
-          function.ToFullyQualifiedCString());
-    }
-
     bytecode_metadata_helper_.ParseBytecodeFunction(parsed_function());
 
     switch (function.kind()) {
@@ -2211,14 +2206,12 @@
 
   // True if callee can skip argument type checks.
   bool is_unchecked_call = inferred_type.IsSkipCheck();
-#ifndef TARGET_ARCH_DBC
   if (call_site_attributes.receiver_type != nullptr &&
       call_site_attributes.receiver_type->HasTypeClass() &&
       !Class::Handle(call_site_attributes.receiver_type->type_class())
            .IsGeneric()) {
     is_unchecked_call = true;
   }
-#endif
 
   Fragment instructions(MakeTemp());
   LocalVariable* variable = MakeTemporary();
@@ -3323,9 +3316,11 @@
   if (p != nullptr) *p = position;
 
   TokenPosition operand_position = TokenPosition::kNoSource;
-  Fragment instructions =
-      BuildExpression(&operand_position);  // read expression.
-  // TODO(37479): Implement null-check semantics.
+  Fragment instructions = BuildExpression(&operand_position);
+  LocalVariable* expr_temp = MakeTemporary();
+  instructions += CheckNull(position, expr_temp, String::null_string(),
+                            /* clear_the_temp = */ false);
+
   return instructions;
 }
 
@@ -3933,7 +3928,8 @@
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(type_args_vec);
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments());
+      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
   instructions += Drop();  // Drop type args.
 
   // Copy over the target function.
@@ -3942,7 +3938,8 @@
   instructions +=
       flow_graph_builder_->LoadNativeField(Slot::Closure_function());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_function());
+      TokenPosition::kNoSource, Slot::Closure_function(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   // Copy over the instantiator type arguments.
   instructions += LoadLocal(new_closure);
@@ -3950,7 +3947,8 @@
   instructions += flow_graph_builder_->LoadNativeField(
       Slot::Closure_instantiator_type_arguments());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments());
+      TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   // Copy over the function type arguments.
   instructions += LoadLocal(new_closure);
@@ -3958,14 +3956,16 @@
   instructions += flow_graph_builder_->LoadNativeField(
       Slot::Closure_function_type_arguments());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_function_type_arguments());
+      TokenPosition::kNoSource, Slot::Closure_function_type_arguments(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   // Copy over the context.
   instructions += LoadLocal(new_closure);
   instructions += LoadLocal(original_closure);
   instructions += flow_graph_builder_->LoadNativeField(Slot::Closure_context());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_context());
+      TokenPosition::kNoSource, Slot::Closure_context(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   instructions += DropTempsPreserveTop(1);  // Drop old closure.
 
@@ -5087,7 +5087,8 @@
     instructions += LoadLocal(closure);
     instructions += LoadInstantiatorTypeArguments();
     instructions += flow_graph_builder_->StoreInstanceField(
-        TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments());
+        TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments(),
+        StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
   // TODO(30455): We only need to save these if the closure uses any captured
@@ -5095,23 +5096,31 @@
   instructions += LoadLocal(closure);
   instructions += LoadFunctionTypeArguments();
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_function_type_arguments());
+      TokenPosition::kNoSource, Slot::Closure_function_type_arguments(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
-  instructions += LoadLocal(closure);
-  instructions += Constant(Object::empty_type_arguments());
-  instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments());
+  if (function.IsGeneric()) {
+    // Only generic functions need to have properly initialized
+    // delayed_type_arguments.
+    instructions += LoadLocal(closure);
+    instructions += Constant(Object::empty_type_arguments());
+    instructions += flow_graph_builder_->StoreInstanceField(
+        TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
+        StoreInstanceFieldInstr::Kind::kInitializing);
+  }
 
   // Store the function and the context in the closure.
   instructions += LoadLocal(closure);
   instructions += Constant(function);
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_function());
+      TokenPosition::kNoSource, Slot::Closure_function(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   instructions += LoadLocal(closure);
   instructions += LoadLocal(parsed_function()->current_context_var());
   instructions += flow_graph_builder_->StoreInstanceField(
-      TokenPosition::kNoSource, Slot::Closure_context());
+      TokenPosition::kNoSource, Slot::Closure_context(),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   return instructions;
 }
@@ -5136,9 +5145,6 @@
 }
 
 Fragment StreamingFlowGraphBuilder::BuildFfiNativeCallbackFunction() {
-#if defined(TARGET_ARCH_DBC)
-  UNREACHABLE();
-#else
   // The call-site must look like this (guaranteed by the FE which inserts it):
   //
   //   _nativeCallbackFunction<NativeSignatureType>(target, exceptionalReturn)
@@ -5191,7 +5197,6 @@
                                   native_sig, target, exceptional_return));
   code += Constant(result);
   return code;
-#endif
 }
 
 }  // namespace kernel
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index d089309..871f1f8 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -229,9 +229,9 @@
     case kDynamicType:
     case kVoidType:
     case kBottomType:
+    case kNeverType:
       // those contain nothing.
       break;
-      UNIMPLEMENTED();
     case kInterfaceType:
       CalculateInterfaceTypeFingerprint(false);
       break;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 8bf4ef6..973f4e9 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -120,7 +120,8 @@
   instructions += LoadLocal(context);
   instructions += LoadLocal(parsed_function_->current_context_var());
   instructions +=
-      StoreInstanceField(TokenPosition::kNoSource, Slot::Context_parent());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Context_parent(),
+                         StoreInstanceFieldInstr::Kind::kInitializing);
   instructions += StoreLocal(TokenPosition::kNoSource,
                              parsed_function_->current_context_var());
   ++context_depth_;
@@ -410,6 +411,14 @@
   }
 }
 
+Fragment FlowGraphBuilder::InitInstanceField(const Field& field) {
+  ASSERT(field.is_instance());
+  ASSERT(field.needs_load_guard());
+  InitInstanceFieldInstr* init = new (Z)
+      InitInstanceFieldInstr(Pop(), MayCloneField(field), GetNextDeoptId());
+  return Fragment(init);
+}
+
 Fragment FlowGraphBuilder::InitStaticField(const Field& field) {
   InitStaticFieldInstr* init = new (Z)
       InitStaticFieldInstr(Pop(), MayCloneField(field), GetNextDeoptId());
@@ -675,8 +684,6 @@
   const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
 
   switch (kind) {
-// On simdbc and the bytecode interpreter we fall back to natives.
-#if !defined(TARGET_ARCH_DBC)
     case MethodRecognizer::kTypedData_ByteDataView_factory:
     case MethodRecognizer::kTypedData_Int8ArrayView_factory:
     case MethodRecognizer::kTypedData_Uint8ArrayView_factory:
@@ -718,7 +725,6 @@
     case MethodRecognizer::kFfiStorePointer:
     case MethodRecognizer::kFfiFromAddress:
     case MethodRecognizer::kFfiGetAddress:
-#endif  // !defined(TARGET_ARCH_DBC)
     // This list must be kept in sync with BytecodeReaderHelper::NativeEntry in
     // runtime/vm/compiler/frontend/bytecode_reader.cc and implemented in the
     // bytecode interpreter in runtime/vm/interpreter.cc. Alternatively, these
@@ -779,8 +785,6 @@
 
   const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
   switch (kind) {
-// On simdbc we fall back to natives.
-#if !defined(TARGET_ARCH_DBC)
     case MethodRecognizer::kTypedData_ByteDataView_factory:
       body += BuildTypedDataViewFactoryConstructor(function, kByteDataViewCid);
       break;
@@ -840,7 +844,6 @@
       body += BuildTypedDataViewFactoryConstructor(
           function, kTypedDataFloat64x2ArrayViewCid);
       break;
-#endif  // !defined(TARGET_ARCH_DBC)
     case MethodRecognizer::kObjectEquals:
       ASSERT(function.NumParameters() == 2);
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
@@ -1005,9 +1008,9 @@
       ASSERT(function.NumParameters() == 2);
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
       body += LoadLocal(parsed_function_->RawParameterVariable(1));
-      body +=
-          StoreInstanceField(TokenPosition::kNoSource,
-                             Slot::LinkedHashMap_hash_mask(), kNoStoreBarrier);
+      body += StoreInstanceField(
+          TokenPosition::kNoSource, Slot::LinkedHashMap_hash_mask(),
+          StoreInstanceFieldInstr::Kind::kOther, kNoStoreBarrier);
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getUsedData:
@@ -1019,9 +1022,9 @@
       ASSERT(function.NumParameters() == 2);
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
       body += LoadLocal(parsed_function_->RawParameterVariable(1));
-      body +=
-          StoreInstanceField(TokenPosition::kNoSource,
-                             Slot::LinkedHashMap_used_data(), kNoStoreBarrier);
+      body += StoreInstanceField(
+          TokenPosition::kNoSource, Slot::LinkedHashMap_used_data(),
+          StoreInstanceFieldInstr::Kind::kOther, kNoStoreBarrier);
       body += NullConstant();
       break;
     case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
@@ -1033,9 +1036,9 @@
       ASSERT(function.NumParameters() == 2);
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
       body += LoadLocal(parsed_function_->RawParameterVariable(1));
-      body += StoreInstanceField(TokenPosition::kNoSource,
-                                 Slot::LinkedHashMap_deleted_keys(),
-                                 kNoStoreBarrier);
+      body += StoreInstanceField(
+          TokenPosition::kNoSource, Slot::LinkedHashMap_deleted_keys(),
+          StoreInstanceFieldInstr::Kind::kOther, kNoStoreBarrier);
       body += NullConstant();
       break;
     case MethodRecognizer::kAsyncStackTraceHelper:
@@ -1264,7 +1267,8 @@
       body += Box(kUnboxedFfiIntPtr);
 #endif  // defined(TARGET_ARCH_IS_32_BIT)
       body += StoreInstanceField(TokenPosition::kNoSource,
-                                 Slot::Pointer_c_memory_address());
+                                 Slot::Pointer_c_memory_address(),
+                                 StoreInstanceFieldInstr::Kind::kInitializing);
     } break;
     case MethodRecognizer::kFfiGetAddress: {
       ASSERT(function.NumParameters() == 1);
@@ -1306,15 +1310,20 @@
 
   body += LoadLocal(view_object);
   body += LoadLocal(typed_data);
-  body += StoreInstanceField(token_pos, Slot::TypedDataView_data());
+  body += StoreInstanceField(token_pos, Slot::TypedDataView_data(),
+                             StoreInstanceFieldInstr::Kind::kInitializing);
 
   body += LoadLocal(view_object);
   body += LoadLocal(offset_in_bytes);
-  body += StoreInstanceField(token_pos, Slot::TypedDataView_offset_in_bytes());
+  body += StoreInstanceField(token_pos, Slot::TypedDataView_offset_in_bytes(),
+                             StoreInstanceFieldInstr::Kind::kInitializing,
+                             kNoStoreBarrier);
 
   body += LoadLocal(view_object);
   body += LoadLocal(length);
-  body += StoreInstanceField(token_pos, Slot::TypedDataBase_length());
+  body += StoreInstanceField(token_pos, Slot::TypedDataBase_length(),
+                             StoreInstanceFieldInstr::Kind::kInitializing,
+                             kNoStoreBarrier);
 
   // Update the inner pointer.
   //
@@ -1362,8 +1371,9 @@
   if (!target.HasInstantiatedSignature(kCurrentClass)) {
     fragment += LoadLocal(closure);
     fragment += LoadInstantiatorTypeArguments();
-    fragment += StoreInstanceField(TokenPosition::kNoSource,
-                                   Slot::Closure_instantiator_type_arguments());
+    fragment += StoreInstanceField(
+        TokenPosition::kNoSource, Slot::Closure_instantiator_type_arguments(),
+        StoreInstanceFieldInstr::Kind::kInitializing);
   }
 
   // The function signature cannot have uninstantiated function type parameters,
@@ -1381,17 +1391,24 @@
   fragment += LoadLocal(closure);
   fragment += Constant(target);
   fragment +=
-      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_function());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_function(),
+                         StoreInstanceFieldInstr::Kind::kInitializing);
 
   fragment += LoadLocal(closure);
   fragment += LoadLocal(context);
   fragment +=
-      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context());
+      StoreInstanceField(TokenPosition::kNoSource, Slot::Closure_context(),
+                         StoreInstanceFieldInstr::Kind::kInitializing);
 
-  fragment += LoadLocal(closure);
-  fragment += Constant(Object::empty_type_arguments());
-  fragment += StoreInstanceField(TokenPosition::kNoSource,
-                                 Slot::Closure_delayed_type_arguments());
+  if (target.IsGeneric()) {
+    // Only generic functions need to have properly initialized
+    // delayed_type_arguments.
+    fragment += LoadLocal(closure);
+    fragment += Constant(Object::empty_type_arguments());
+    fragment += StoreInstanceField(
+        TokenPosition::kNoSource, Slot::Closure_delayed_type_arguments(),
+        StoreInstanceFieldInstr::Kind::kInitializing);
+  }
 
   // The context is on top of the operand stack.  Store `this`.  The context
   // doesn't need a parent pointer because it doesn't close over anything
@@ -1400,7 +1417,8 @@
   fragment += StoreInstanceField(
       TokenPosition::kNoSource,
       Slot::GetContextVariableSlotFor(
-          thread_, *implicit_closure_scope->context_variables()[0]));
+          thread_, *implicit_closure_scope->context_variables()[0]),
+      StoreInstanceFieldInstr::Kind::kInitializing);
 
   return fragment;
 }
@@ -2472,12 +2490,21 @@
                               AssertAssignableInstr::kParameterCheck);
     }
     if (is_method) {
-      body += StoreInstanceFieldGuarded(field, false);
+      body += StoreInstanceFieldGuarded(field,
+                                        StoreInstanceFieldInstr::Kind::kOther);
     } else {
       body += StoreStaticField(TokenPosition::kNoSource, field);
     }
     body += NullConstant();
   } else if (is_method) {
+#if !defined(PRODUCT)
+    if (field.needs_load_guard()) {
+      ASSERT(Isolate::Current()->HasAttemptedReload());
+      body += LoadLocal(parsed_function_->ParameterVariable(0));
+      body += InitInstanceField(field);
+      // TODO(rmacnak): Type check.
+    }
+#endif
     body += LoadLocal(parsed_function_->ParameterVariable(0));
     body += LoadField(field);
   } else if (field.is_const()) {
@@ -2621,14 +2648,12 @@
   return Fragment(extend);
 }
 
-#if !defined(TARGET_ARCH_DBC)
 Fragment FlowGraphBuilder::NativeReturn(Representation result) {
   auto* instr = new (Z)
       NativeReturnInstr(TokenPosition::kNoSource, Pop(), result,
                         compiler::ffi::ResultLocation(result), DeoptId::kNone);
   return Fragment(instr);
 }
-#endif
 
 Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
   LocalVariable* address = MakeTemporary();
@@ -2654,7 +2679,8 @@
   code += LoadLocal(pointer);
   code += LoadLocal(address);
   code += StoreInstanceField(TokenPosition::kNoSource,
-                             Slot::Pointer_c_memory_address());
+                             Slot::Pointer_c_memory_address(),
+                             StoreInstanceFieldInstr::Kind::kInitializing);
   code += StoreLocal(TokenPosition::kNoSource, result);
   code += Drop();  // StoreLocal^
   code += Drop();  // address
@@ -2746,13 +2772,8 @@
   body += CheckStackOverflowInPrologue(function.token_pos());
 
   const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
-#if !defined(TARGET_ARCH_DBC)
   const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
   const ZoneGrowableArray<HostLocation>* arg_host_locs = nullptr;
-#else
-  const auto& arg_reps = *compiler::ffi::ArgumentHostRepresentations(signature);
-  const auto* arg_host_locs = compiler::ffi::HostArgumentLocations(arg_reps);
-#endif
   const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
 
   BuildArgumentTypeChecks(TypeChecksToBuild::kCheckAllTypeParameterBounds,
@@ -2778,13 +2799,8 @@
   body += FfiCall(signature, arg_reps, arg_locs, arg_host_locs);
 
   ffi_type = signature.result_type();
-#if !defined(TARGET_ARCH_DBC)
   const Representation from_rep =
       compiler::ffi::ResultRepresentation(signature);
-#else
-  const Representation from_rep =
-      compiler::ffi::ResultHostRepresentation(signature);
-#endif  // !defined(TARGET_ARCH_DBC)
   body += FfiConvertArgumentToDart(ffi_type, from_rep);
   body += Return(TokenPosition::kNoSource);
 
@@ -2793,7 +2809,6 @@
 }
 
 FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) {
-#if !defined(TARGET_ARCH_DBC)
   const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
   const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
   const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
@@ -2875,9 +2890,6 @@
   PrologueInfo prologue_info(-1, -1);
   return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
                            prologue_info);
-#else
-  UNREACHABLE();
-#endif
 }
 
 void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) {
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index ca4e786..fc461c0 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -132,6 +132,7 @@
 
   Fragment RethrowException(TokenPosition position, int catch_try_index);
   Fragment LoadLocal(LocalVariable* variable);
+  Fragment InitInstanceField(const Field& field);
   Fragment InitStaticField(const Field& field);
   Fragment NativeCall(const String* name, const Function* function);
   Fragment Return(TokenPosition position, bool omit_result_type_check = false);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 95c92b2..bad19e4 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -733,6 +733,7 @@
 
   intptr_t pos = 0;
   if (is_method) {
+    // TODO(regis): Set nullability to kNonNullable instead of kLegacy.
     function.SetParameterTypeAt(pos, GetDeclarationType(klass));
     function.SetParameterNameAt(pos, Symbols::This());
     pos++;
@@ -847,8 +848,8 @@
       Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kFunctionNode);
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kPosition:
       position_ = helper_->ReadPosition();  // read position.
       if (++next_read_ == field) return;
@@ -987,8 +988,8 @@
       Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kField);
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kCanonicalName:
       canonical_name_ =
           helper_->ReadCanonicalNameReference();  // read canonical_name.
@@ -1025,8 +1026,8 @@
         helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kType:
       helper_->SkipDartType();  // read type.
       if (++next_read_ == field) return;
@@ -1051,8 +1052,8 @@
       Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kProcedure);
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kCanonicalName:
       canonical_name_ =
           helper_->ReadCanonicalNameReference();  // read canonical_name.
@@ -1097,8 +1098,8 @@
         helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kForwardingStubSuperTarget:
       forwarding_stub_super_target_ = helper_->ReadCanonicalNameReference();
       if (++next_read_ == field) return;
@@ -1127,8 +1128,8 @@
       Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kConstructor);
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kCanonicalName:
       canonical_name_ =
           helper_->ReadCanonicalNameReference();  // read canonical_name.
@@ -1165,8 +1166,8 @@
         helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kFunction:
       helper_->SkipFunctionNode();  // read function.
       if (++next_read_ == field) return;
@@ -1194,8 +1195,8 @@
       Tag tag = helper_->ReadTag();  // read tag.
       ASSERT(tag == kClass);
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kCanonicalName:
       canonical_name_ =
           helper_->ReadCanonicalNameReference();  // read canonical_name.
@@ -1232,8 +1233,8 @@
         helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kTypeParameters:
       helper_->SkipTypeParametersList();  // read type parameters.
       if (++next_read_ == field) return;
@@ -1244,16 +1245,16 @@
         helper_->SkipDartType();  // read super class type (part 2).
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kMixinType: {
       Tag type_tag = helper_->ReadTag();  // read mixin type (part 1).
       if (type_tag == kSomething) {
         helper_->SkipDartType();  // read mixin type (part 2).
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kImplementedClasses:
       helper_->SkipListOfDartTypes();  // read implemented_classes.
       if (++next_read_ == field) return;
@@ -1266,8 +1267,8 @@
         field_helper.ReadUntilExcluding(FieldHelper::kEnd);  // read field.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kConstructors: {
       intptr_t list_length =
           helper_->ReadListLength();  // read constructors list length.
@@ -1277,8 +1278,8 @@
             ConstructorHelper::kEnd);  // read constructor.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kProcedures: {
       procedure_count_ = helper_->ReadListLength();  // read procedures #.
       for (intptr_t i = 0; i < procedure_count_; i++) {
@@ -1287,8 +1288,8 @@
             ProcedureHelper::kEnd);  // read procedure.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kClassIndex:
       // Read class index.
       for (intptr_t i = 0; i < procedure_count_; ++i) {
@@ -1343,8 +1344,8 @@
         helper_->SkipBytes(helper_->ReadUInt());  // read strings.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kAnnotations:
       helper_->SkipListOfExpressions();  // read annotations.
       if (++next_read_ == field) return;
@@ -1381,18 +1382,18 @@
         helper_->SkipExpression();  // read ith expression.
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kTargetLibrary: {
       target_library_canonical_name_ = helper_->ReadCanonicalNameReference();
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kName: {
       name_index_ = helper_->ReadStringReference();
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kCombinators: {
       intptr_t count = helper_->ReadListLength();
       for (intptr_t i = 0; i < count; ++i) {
@@ -1402,8 +1403,8 @@
         helper_->SkipListOfStrings();
       }
       if (++next_read_ == field) return;
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case kEnd:
       return;
   }
@@ -1975,6 +1976,7 @@
     case kDynamicType:
     case kVoidType:
     case kBottomType:
+    case kNeverType:
       // those contain nothing.
       return;
     case kInterfaceType:
@@ -2783,6 +2785,11 @@
     case kBottomType:
       result_ =
           Class::Handle(Z, I->object_store()->null_class()).DeclarationType();
+      // We set the nullability of Null to kNullable, even in legacy mode.
+      ASSERT(result_.IsNullable());
+      break;
+    case kNeverType:
+      result_ = Object::never_type().raw();
       break;
     case kInterfaceType:
       BuildInterfaceType(false);
@@ -2810,7 +2817,7 @@
   // malformed iff `T` is malformed.
   //   => We therefore ignore errors in `A` or `B`.
 
-  helper_->ReadNullability();  // read nullability.
+  const Nullability nullability = helper_->ReadNullability();
 
   NameIndex klass_name =
       helper_->ReadCanonicalNameReference();  // read klass_name.
@@ -2825,10 +2832,16 @@
       // Fast path for non-generic types: retrieve or populate the class's only
       // canonical type, which is its declaration type.
       result_ = klass.DeclarationType();
+      // TODO(regis): Remove this workaround once nullability of Null provided
+      // by CFE is always kNullable.
+      if (!result_.IsNullType()) {
+        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());
+      Type::Cast(result_).set_nullability(nullability);
     }
     return;
   }
@@ -2838,6 +2851,7 @@
   const TypeArguments& type_arguments =
       BuildTypeArguments(length);  // read type arguments.
   result_ = Type::New(klass, type_arguments, TokenPosition::kNoSource);
+  Type::Cast(result_).set_nullability(nullability);
   if (finalize_) {
     ASSERT(active_class_->klass != NULL);
     result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
@@ -2852,7 +2866,7 @@
                                             : Function::Handle(Z),
                                         TokenPosition::kNoSource));
 
-  helper_->ReadNullability();  // read nullability.
+  const Nullability nullability = helper_->ReadNullability();
 
   // Suspend finalization of types inside this one. They will be finalized after
   // the whole function type is constructed.
@@ -2935,6 +2949,7 @@
 
   Type& signature_type =
       Type::ZoneHandle(Z, signature_function.SignatureType());
+  signature_type.set_nullability(nullability);
 
   if (finalize_) {
     signature_type ^=
@@ -2948,7 +2963,7 @@
 }
 
 void TypeTranslator::BuildTypeParameterType() {
-  helper_->ReadNullability();                      // read nullability.
+  const Nullability nullability = helper_->ReadNullability();
   intptr_t parameter_index = helper_->ReadUInt();  // read parameter index.
   helper_->SkipOptionalDartType();                 // read bound.
 
@@ -2958,6 +2973,8 @@
     // The index of the type parameter in [parameters] is
     // the same index into the `klass->type_parameters()` array.
     result_ = class_types.TypeAt(parameter_index);
+    result_ =
+        TypeParameter::Cast(result_).ToNullability(nullability, Heap::kOld);
     return;
   }
   parameter_index -= class_types.Length();
@@ -2983,6 +3000,8 @@
       //
       if (class_types.Length() > parameter_index) {
         result_ = class_types.TypeAt(parameter_index);
+        result_ =
+            TypeParameter::Cast(result_).ToNullability(nullability, Heap::kOld);
         return;
       }
       parameter_index -= class_types.Length();
@@ -2998,6 +3017,8 @@
         result_ =
             TypeArguments::Handle(Z, active_class_->member->type_parameters())
                 .TypeAt(parameter_index);
+        result_ =
+            TypeParameter::Cast(result_).ToNullability(nullability, Heap::kOld);
         if (finalize_) {
           result_ =
               ClassFinalizer::FinalizeType(*active_class_->klass, result_);
@@ -3011,6 +3032,8 @@
   if (active_class_->local_type_parameters != NULL) {
     if (parameter_index < active_class_->local_type_parameters->Length()) {
       result_ = active_class_->local_type_parameters->TypeAt(parameter_index);
+      result_ =
+          TypeParameter::Cast(result_).ToNullability(nullability, Heap::kOld);
       if (finalize_) {
         result_ = ClassFinalizer::FinalizeType(*active_class_->klass, result_);
       }
@@ -3166,6 +3189,7 @@
     type = Type::New(klass, TypeArguments::Handle(Z, klass.type_parameters()),
                      klass.token_pos());
   }
+  // TODO(regis): Set nullability to kNonNullable instead of kLegacy.
   return type;
 }
 
@@ -3216,6 +3240,7 @@
   intptr_t pos = 0;
   if (is_method) {
     ASSERT(!klass.IsNull());
+    // TODO(regis): Set nullability to kNonNullable instead of kLegacy.
     function.SetParameterTypeAt(pos, H.GetDeclarationType(klass));
     function.SetParameterNameAt(pos, Symbols::This());
     pos++;
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index d4e6473..319b362 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -1300,6 +1300,7 @@
     case kDynamicType:
     case kVoidType:
     case kBottomType:
+    case kNeverType:
       // those contain nothing.
       return;
     case kInterfaceType:
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 728aee5..9485474 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -3,8 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 // Class for intrinsifying functions.
 
-// DBC does not use graph intrinsics.
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 
 #include "vm/compiler/graph_intrinsifier.h"
 #include "vm/compiler/backend/block_builder.h"
@@ -989,4 +988,4 @@
 }  // namespace compiler
 }  // namespace dart
 
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/graph_intrinsifier.h b/runtime/vm/compiler/graph_intrinsifier.h
index 6282b58..3e398f1 100644
--- a/runtime/vm/compiler/graph_intrinsifier.h
+++ b/runtime/vm/compiler/graph_intrinsifier.h
@@ -20,8 +20,6 @@
 class Assembler;
 class Label;
 
-#if !defined(TARGET_ARCH_DBC)
-
 class GraphIntrinsifier : public AllStatic {
  public:
   static intptr_t ParameterSlotFromSp();
@@ -36,7 +34,6 @@
 #define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
   static void enum_name(Assembler* assembler, Label* normal_ir_body);
 
-  // On DBC graph intrinsics are handled in the same way as non-graph ones.
   GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
 
 #undef DECLARE_FUNCTION
@@ -49,18 +46,6 @@
 #undef DECLARE_FUNCTION
 };
 
-#else  // !defined(TARGET_ARCH_DBC)
-
-class GraphIntrinsifier : public AllStatic {
- public:
-  static bool GraphIntrinsify(const ParsedFunction& parsed_function,
-                              FlowGraphCompiler* compiler) {
-    return false;
-  }
-};
-
-#endif  // !defined(TARGET_ARCH_DBC)
-
 }  // namespace compiler
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 68217ef..73daa5b 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -198,7 +198,7 @@
   }
 #endif
 
-#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC)
+#if !defined(PRODUCT)
 #define EMIT_BREAKPOINT() compiler->assembler()->Breakpoint()
 #else
 #define EMIT_BREAKPOINT()
@@ -230,16 +230,6 @@
       break;
   }
 
-// On DBC all graph intrinsics are handled in the same way as non-graph
-// intrinsics.
-#if defined(TARGET_ARCH_DBC)
-  switch (function.recognized_kind()) {
-    GRAPH_INTRINSICS_LIST(EMIT_CASE)
-    default:
-      break;
-  }
-#endif
-
 #undef EMIT_BREAKPOINT
 
 #undef EMIT_INTRINSIC
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index dd25e7a..e52a66f 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -283,7 +283,7 @@
     // The function will not be optimized any longer. This situation can occur
     // mostly with small optimization counter thresholds.
     function.SetIsOptimizable(false);
-    function.SetUsageCounter(INT_MIN);
+    function.SetUsageCounter(INT32_MIN);
     return false;
   }
   if (FLAG_optimization_filter != NULL) {
@@ -305,7 +305,7 @@
     }
     delete[] filter;
     if (!found) {
-      function.SetUsageCounter(INT_MIN);
+      function.SetUsageCounter(INT32_MIN);
       return false;
     }
   }
@@ -315,7 +315,7 @@
     if (FLAG_trace_failed_optimization_attempts) {
       THR_Print("Not optimizable: %s\n", function.ToFullyQualifiedCString());
     }
-    function.SetUsageCounter(INT_MIN);
+    function.SetUsageCounter(INT32_MIN);
     return false;
   }
   return true;
@@ -381,7 +381,7 @@
   if (!function.IsOptimizable()) {
     // A function with huge unoptimized code can become non-optimizable
     // after generating unoptimized code.
-    function.SetUsageCounter(INT_MIN);
+    function.SetUsageCounter(INT32_MIN);
   }
 
   graph_compiler->FinalizePcDescriptors(code);
@@ -486,7 +486,7 @@
     function.SetWasCompiled(true);
     if (function.IsOptimizable() && (function.usage_counter() < 0)) {
       // While doing compilation in background, usage counter is set
-      // to INT_MIN. Reset counter so that function can be optimized further.
+      // to INT32_MIN. Reset counter so that function can be optimized further.
       function.SetUsageCounter(0);
     }
   }
@@ -877,8 +877,7 @@
 }
 
 RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
   if (FLAG_precompiled_mode) {
     return Precompiler::CompileFunction(
         /* precompiler = */ NULL, thread, thread->zone(), function);
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
index a91342f..293ff55 100644
--- a/runtime/vm/compiler/offsets_extractor.cc
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -24,10 +24,6 @@
 #define ARCH_DEF "defined(TARGET_ARCH_IA32)"
 #elif defined(TARGET_ARCH_ARM64)
 #define ARCH_DEF "defined(TARGET_ARCH_ARM64)"
-#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
-#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)"
-#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
-#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)"
 #else
 #error Unknown architecture
 #endif
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 9071252..afec50c 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -15,8 +15,8 @@
   V(::, identical, ObjectIdentical, 0xc6e9467a)                                \
   V(ClassID, getID, ClassIDgetID, 0xf0376ced)                                  \
   V(Object, Object., ObjectConstructor, 0x8f3ae7ea)                            \
-  V(List, ., ListFactory, 0xda0d774c)                                          \
-  V(_List, ., ObjectArrayAllocate, 0x704c8d5d)                                 \
+  V(List, ., ListFactory, 0xdf9970a9)                                          \
+  V(_List, ., ObjectArrayAllocate, 0x03ddbd3a)                                 \
   V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0xa24c2704)                    \
   V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0xa491df3e)                  \
   V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0xb65ae1fc)                  \
@@ -69,8 +69,8 @@
   V(_Double, _sub, DoubleSub, 0x6d3cec71)                                      \
   V(_Double, _mul, DoubleMul, 0x648e67af)                                      \
   V(_Double, _div, DoubleDiv, 0x6d72d7d4)                                      \
-  V(::, min, MathMin, 0x3ccbc098)                                              \
-  V(::, max, MathMax, 0x4e398e7f)                                              \
+  V(::, min, MathMin, 0xddeb5e75)                                              \
+  V(::, max, MathMax, 0xe152dd1c)                                              \
   V(::, _doublePow, MathDoublePow, 0x5ae04e61)                                 \
   V(::, _intPow, MathIntPow, 0x569ffd3f)                                       \
   V(Float32x4, Float32x4., Float32x4Constructor, 0xdf9f0693)                   \
@@ -143,8 +143,8 @@
   V(::, _classRangeCheck, ClassRangeCheck, 0xca52e30a)                         \
   V(::, _asyncStackTraceHelper, AsyncStackTraceHelper, 0xaeaed5cb)             \
   V(::, _abi, FfiAbi, 0xf2e89620)                                              \
-  V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x92a67518)                \
-  V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x59cc5edb)        \
+  V(::, _asFunctionInternal, FfiAsFunctionInternal, 0x77414ede)                \
+  V(::, _nativeCallbackFunction, FfiNativeCallbackFunction, 0x5bd261b8)        \
   V(::, _loadInt8, FfiLoadInt8, 0x9b1e4a8d)                                    \
   V(::, _loadInt16, FfiLoadInt16, 0x2824dc24)                                  \
   V(::, _loadInt32, FfiLoadInt32, 0x3f9bf49d)                                  \
@@ -156,7 +156,7 @@
   V(::, _loadIntPtr, FfiLoadIntPtr, 0x1ad8e69f)                                \
   V(::, _loadFloat, FfiLoadFloat, 0x234b92dc)                                  \
   V(::, _loadDouble, FfiLoadDouble, 0x97c755b3)                                \
-  V(::, _loadPointer, FfiLoadPointer, 0xd478c108)                              \
+  V(::, _loadPointer, FfiLoadPointer, 0xd9d293a5)                              \
   V(::, _storeInt8, FfiStoreInt8, 0x9a637adf)                                  \
   V(::, _storeInt16, FfiStoreInt16, 0x7c5ad40b)                                \
   V(::, _storeInt32, FfiStoreInt32, 0xc729a9da)                                \
@@ -168,8 +168,8 @@
   V(::, _storeIntPtr, FfiStoreIntPtr, 0xc75ef10f)                              \
   V(::, _storeFloat, FfiStoreFloat, 0x34a22e07)                                \
   V(::, _storeDouble, FfiStoreDouble, 0x09226ca7)                              \
-  V(::, _storePointer, FfiStorePointer, 0x2641a44b)                            \
-  V(::, _fromAddress, FfiFromAddress, 0x8eb74eb8)                              \
+  V(::, _storePointer, FfiStorePointer, 0x3c7143a8)                            \
+  V(::, _fromAddress, FfiFromAddress, 0x612a64d5)                              \
   V(Pointer, get:address, FfiGetAddress, 0x29a505a1)                           \
 
 // List of intrinsics:
@@ -203,7 +203,7 @@
   V(_Double, get:isNegative, Double_getIsNegative, 0xb15ff274)                 \
   V(_Double, _mulFromInteger, Double_mulFromInteger, 0xe2853768)               \
   V(_Double, .fromInteger, DoubleFromInteger, 0x89504536)                      \
-  V(_GrowableList, ._withData, GrowableArray_Allocate, 0x57717122)             \
+  V(_GrowableList, ._withData, GrowableArray_Allocate, 0x5cfd6a7f)             \
   V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0xb961fc8d)                   \
   V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0xb22daf53)       \
   V(Object, ==, ObjectEquals, 0x91ead0d6)                                      \
@@ -430,9 +430,9 @@
 // (factory-name-symbol, class-name-string, constructor-name-string,
 //  result-cid, fingerprint).
 #define RECOGNIZED_LIST_FACTORY_LIST(V)                                        \
-  V(_ListFactory, _List, ., kArrayCid, 0x704c8d5d)                             \
+  V(_ListFactory, _List, ., kArrayCid, 0x03ddbd3a)                             \
   V(_GrowableListWithData, _GrowableList, ._withData, kGrowableObjectArrayCid, \
-    0x57717122)                                                                \
+    0x5cfd6a7f)                                                                \
   V(_GrowableListFactory, _GrowableList, ., kGrowableObjectArrayCid,           \
     0x3eed680b)                                                                \
   V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x6ce2f102)        \
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index af363e6..e9f3bf7 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -12,8 +12,7 @@
 
 namespace dart {
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 // Only for testing.
 DEFINE_FLAG(bool,
@@ -21,9 +20,12 @@
             false,
             "Generate always trampolines (for testing purposes).");
 
-// The trampolines will have a 1-word object header in front of them.
+// The trampolines will be disguised as FreeListElement objects, with a 1-word
+// object header in front of the jump code.
 const intptr_t kOffsetInTrampoline = kWordSize;
-const intptr_t kTrampolineSize = OS::kMaxPreferredCodeAlignment;
+const intptr_t kTrampolineSize = Utils::RoundUp(
+    kOffsetInTrampoline + PcRelativeTrampolineJumpPattern::kLengthInBytes,
+    kObjectAlignment);
 
 CodeRelocator::CodeRelocator(Thread* thread,
                              GrowableArray<RawCode*>* code_objects,
@@ -408,7 +410,12 @@
 static void MarkAsFreeListElement(uint8_t* trampoline_bytes,
                                   intptr_t trampoline_length) {
   uint32_t tags = 0;
+#if defined(IS_SIMARM_X64)
+  // Account for difference in kObjectAlignment between host and target.
+  tags = RawObject::SizeTag::update(trampoline_length * 2, tags);
+#else
   tags = RawObject::SizeTag::update(trampoline_length, tags);
+#endif
   tags = RawObject::ClassIdTag::update(kFreeListElement, tags);
   tags = RawObject::OldBit::update(true, tags);
   tags = RawObject::OldAndNotMarkedBit::update(true, tags);
@@ -464,9 +471,6 @@
       // buffer.
       auto trampoline_bytes = new uint8_t[kTrampolineSize];
       memset(trampoline_bytes, 0x00, kTrampolineSize);
-      ASSERT((kOffsetInTrampoline +
-              PcRelativeTrampolineJumpPattern::kLengthInBytes) <
-             kTrampolineSize);
       auto unresolved_trampoline = new UnresolvedTrampoline{
           unresolved_call->callee,
           unresolved_call->offset_into_target,
@@ -507,7 +511,6 @@
          offset_into_target;
 }
 
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
-        // !defined(TARGET_ARCH_IA32)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/relocation.h b/runtime/vm/compiler/relocation.h
index 91ed48c..50db3e1 100644
--- a/runtime/vm/compiler/relocation.h
+++ b/runtime/vm/compiler/relocation.h
@@ -14,8 +14,7 @@
 
 namespace dart {
 
-#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
-    !defined(TARGET_ARCH_IA32)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 // Represents a pc-relative call which has not been patched up with the final
 // destination.
@@ -208,8 +207,7 @@
   Code& destination_;
 };
 
-#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
-        // !defined(TARGET_ARCH_IA32)
+#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
 
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index e7f6f80..05bb858 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -208,7 +208,6 @@
 }
 #endif
 
-#if !defined(TARGET_ARCH_DBC)
 const Code& StubCodeAllocateArray() {
   return dart::StubCode::AllocateArray();
 }
@@ -220,7 +219,6 @@
 const Code& StubCodeSubtype6TestCache() {
   return dart::StubCode::Subtype6TestCache();
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 #define DEFINE_ALIAS(name)                                                     \
   const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry);
@@ -505,19 +503,13 @@
 const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
 
 word Instructions::HeaderSize() {
-  intptr_t alignment = OS::PreferredCodeAlignment();
-  intptr_t aligned_size =
-      Utils::RoundUp(Instructions::UnalignedHeaderSize(), alignment);
-  ASSERT(aligned_size == alignment);
-  return aligned_size;
+  return Utils::RoundUp(Instructions::UnalignedHeaderSize(), target::kWordSize);
 }
 
-#if !defined(TARGET_ARCH_DBC)
 word Thread::stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
   return fpu_regs ? stack_overflow_shared_with_fpu_regs_entry_point_offset()
                   : stack_overflow_shared_without_fpu_regs_entry_point_offset();
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 uword Thread::safepoint_state_unacquired() {
   return dart::Thread::safepoint_state_unacquired();
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 8c36561..f6f7eaa 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -189,11 +189,9 @@
                                          Assembler*,
                                          intptr_t);
 
-#if !defined(TARGET_ARCH_DBC)
 const Code& StubCodeAllocateArray();
 const Code& StubCodeSubtype2TestCache();
 const Code& StubCodeSubtype6TestCache();
-#endif  // !defined(TARGET_ARCH_DBC)
 
 class RuntimeEntry : public ValueObject {
  public:
@@ -668,12 +666,12 @@
   static word stack_overflow_flags_offset();
   static word stack_overflow_shared_stub_entry_point_offset(bool fpu_regs);
   static word stack_limit_offset();
+  static word saved_stack_limit_offset();
   static word unboxed_int64_runtime_arg_offset();
 
   static word callback_code_offset();
 
   static word AllocateArray_entry_point_offset();
-#if !defined(TARGET_ARCH_DBC)
   static word write_barrier_code_offset();
   static word array_write_barrier_code_offset();
   static word fix_callers_target_code_offset();
@@ -700,7 +698,6 @@
   static word exit_safepoint_stub_offset();
   static word call_native_through_safepoint_stub_offset();
   static word call_native_through_safepoint_entry_point_offset();
-#endif  // !defined(TARGET_ARCH_DBC)
 
   static word no_scope_native_wrapper_entry_point_offset();
   static word auto_scope_native_wrapper_entry_point_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 0965a3c..4c3564a 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -193,130 +193,132 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 284;
+    Thread_AllocateArray_entry_point_offset = 292;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    616;
+    628;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    620;
+    632;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_code_offset = 112;
+    Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 196;
+    Thread_array_write_barrier_entry_point_offset = 204;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    84;
+    88;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 252;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 108;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 200;
+    Thread_call_to_runtime_entry_point_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_stub_offset = 132;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 652;
+    Thread_call_to_runtime_stub_offset = 140;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 664;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    228;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
+    236;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 164;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    160;
+    168;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    264;
+    272;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 260;
-static constexpr dart::compiler::target::word Thread_end_offset = 60;
+    Thread_double_negate_address_offset = 268;
+static constexpr dart::compiler::target::word Thread_end_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 180;
+    Thread_enter_safepoint_stub_offset = 188;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    648;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 244;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 124;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 280;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    276;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 288;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
     636;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 184;
+    Thread_interpret_call_entry_point_offset = 256;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 188;
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 136;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 236;
+    Thread_invoke_dart_code_stub_offset = 132;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 52;
 static constexpr dart::compiler::target::word
-    Thread_fix_allocation_stub_code_offset = 120;
+    Thread_lazy_deopt_from_return_stub_offset = 172;
 static constexpr dart::compiler::target::word
-    Thread_fix_callers_target_code_offset = 116;
+    Thread_lazy_deopt_from_throw_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 276;
+    Thread_lazy_specialize_type_test_stub_offset = 184;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 272;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    268;
+    Thread_marking_stack_block_offset = 76;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 280;
-static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    624;
+    Thread_megamorphic_call_checked_entry_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 248;
+    Thread_monomorphic_miss_entry_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
+    Thread_monomorphic_miss_stub_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_stub_offset = 124;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
+    Thread_no_scope_native_wrapper_entry_point_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 164;
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 168;
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 148;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 176;
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 72;
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 220;
+    Thread_predefined_symbols_address_offset = 260;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 640;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 224;
-static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 152;
-static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 240;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
-static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 252;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 628;
-static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 632;
+    Thread_saved_shadow_call_stack_offset = 644;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    640;
+    652;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 172;
+    Thread_slow_type_test_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    40;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 40;
+    Thread_stack_overflow_flags_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 224;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 220;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    68;
+    72;
 static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 64;
-static constexpr dart::compiler::target::word Thread_top_offset = 56;
+    Thread_top_exit_frame_info_offset = 68;
+static constexpr dart::compiler::target::word Thread_top_offset = 60;
 static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
 static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 88;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
+    Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 84;
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
-    108;
+    116;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 192;
+    Thread_write_barrier_entry_point_offset = 200;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    44;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 644;
+    48;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 656;
 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;
@@ -349,15 +351,15 @@
     Code_function_entry_point_offset[] = {4, 8};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        580, 584, 588, 592, 596, -1, 600, 604,
-        608, 612, -1,  -1,  -1,  -1, -1,  -1};
+        592, 596, 600, 604, 608, -1, 612, 616,
+        620, 624, -1,  -1,  -1,  -1, -1,  -1};
 static constexpr dart::compiler::target::word Array_header_size = 12;
 static constexpr dart::compiler::target::word Context_header_size = 12;
 static constexpr dart::compiler::target::word Double_InstanceSize = 16;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    16;
+    12;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
@@ -552,131 +554,133 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 560;
+    Thread_AllocateArray_entry_point_offset = 568;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1240;
+    1256;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1248;
+    1264;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_code_offset = 216;
+    Thread_array_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 384;
+    Thread_array_write_barrier_entry_point_offset = 392;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    168;
+    176;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 488;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 392;
+    Thread_call_to_runtime_entry_point_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1312;
+    Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1328;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    448;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
-static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
     456;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 312;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    464;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    312;
+    320;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    520;
-static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 512;
-static constexpr dart::compiler::target::word Thread_end_offset = 120;
-static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 352;
-static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1280;
-static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 360;
-static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 368;
-static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 464;
-static constexpr dart::compiler::target::word
-    Thread_fix_allocation_stub_code_offset = 232;
-static constexpr dart::compiler::target::word
-    Thread_fix_callers_target_code_offset = 224;
-static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 544;
-static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 536;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
     528;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 552;
+    Thread_double_negate_address_offset = 520;
+static constexpr dart::compiler::target::word Thread_end_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1296;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 544;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    536;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 560;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1256;
+    1272;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 488;
+    Thread_interpret_call_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_stub_offset = 240;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
+    Thread_invoke_dart_code_stub_offset = 248;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 104;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 320;
+    Thread_lazy_deopt_from_return_stub_offset = 328;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 328;
+    Thread_lazy_deopt_from_throw_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 344;
+    Thread_lazy_specialize_type_test_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 144;
+    Thread_marking_stack_block_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 432;
+    Thread_megamorphic_call_checked_entry_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 440;
+    Thread_monomorphic_miss_entry_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 296;
+    Thread_monomorphic_miss_stub_offset = 304;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 472;
+    Thread_no_scope_native_wrapper_entry_point_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 416;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 496;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1264;
+    Thread_predefined_symbols_address_offset = 504;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1280;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1272;
+    Thread_saved_shadow_call_stack_offset = 1288;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1288;
+    1304;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 336;
+    Thread_slow_type_test_stub_offset = 344;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    80;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 80;
+    Thread_stack_overflow_flags_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 432;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 424;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    136;
+    144;
 static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 128;
-static constexpr dart::compiler::target::word Thread_top_offset = 112;
+    Thread_top_exit_frame_info_offset = 136;
+static constexpr dart::compiler::target::word Thread_top_offset = 120;
 static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
 static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 176;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
+    Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 168;
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 376;
+    Thread_write_barrier_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    88;
+    96;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1296;
+    1312;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -710,15 +714,15 @@
     Code_function_entry_point_offset[] = {8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1152, 1160, 1168, 1176, -1,   -1,   1184, 1192,
-        1200, 1208, 1216, -1,   1224, 1232, -1,   -1};
+        1168, 1176, 1184, 1192, -1,   -1,   1200, 1208,
+        1216, 1224, 1232, -1,   1240, 1248, -1,   -1};
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Context_header_size = 24;
 static constexpr dart::compiler::target::word Double_InstanceSize = 16;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    24;
+    16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
@@ -911,130 +915,132 @@
 static constexpr dart::compiler::target::word String_length_offset = 4;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 284;
+    Thread_AllocateArray_entry_point_offset = 292;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    580;
+    592;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    584;
+    596;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_code_offset = 112;
+    Thread_array_write_barrier_code_offset = 120;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 196;
+    Thread_array_write_barrier_entry_point_offset = 204;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    84;
+    88;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 244;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 252;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 108;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 200;
+    Thread_call_to_runtime_entry_point_offset = 208;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_stub_offset = 132;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 616;
+    Thread_call_to_runtime_stub_offset = 140;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 628;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    228;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 156;
+    236;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 164;
 static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    160;
+    168;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    264;
+    272;
 static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 260;
-static constexpr dart::compiler::target::word Thread_end_offset = 60;
+    Thread_double_negate_address_offset = 268;
+static constexpr dart::compiler::target::word Thread_end_offset = 64;
 static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 180;
+    Thread_enter_safepoint_stub_offset = 188;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    612;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 192;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 196;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 244;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 124;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 284;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 280;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    276;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 288;
+static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
     600;
 static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 184;
+    Thread_interpret_call_entry_point_offset = 256;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 188;
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 136;
 static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 236;
+    Thread_invoke_dart_code_stub_offset = 132;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 52;
 static constexpr dart::compiler::target::word
-    Thread_fix_allocation_stub_code_offset = 120;
+    Thread_lazy_deopt_from_return_stub_offset = 172;
 static constexpr dart::compiler::target::word
-    Thread_fix_callers_target_code_offset = 116;
+    Thread_lazy_deopt_from_throw_stub_offset = 176;
 static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 276;
+    Thread_lazy_specialize_type_test_stub_offset = 184;
 static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 272;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    268;
+    Thread_marking_stack_block_offset = 76;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 280;
-static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    588;
+    Thread_megamorphic_call_checked_entry_offset = 228;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 248;
+    Thread_monomorphic_miss_entry_offset = 232;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_from_bytecode_stub_offset = 128;
+    Thread_monomorphic_miss_stub_offset = 160;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_stub_offset = 124;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
+    Thread_no_scope_native_wrapper_entry_point_offset = 248;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 164;
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 216;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 168;
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 148;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 176;
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 212;
 static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 72;
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 220;
+    Thread_predefined_symbols_address_offset = 260;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 604;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 224;
-static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 152;
-static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 240;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_stub_offset = 140;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
-static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
-static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 252;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 592;
-static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 596;
+    Thread_saved_shadow_call_stack_offset = 608;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    604;
+    616;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 172;
+    Thread_slow_type_test_stub_offset = 180;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    40;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 40;
+    Thread_stack_overflow_flags_offset = 44;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 224;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 156;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 220;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 152;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    68;
+    72;
 static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 64;
-static constexpr dart::compiler::target::word Thread_top_offset = 56;
+    Thread_top_exit_frame_info_offset = 68;
+static constexpr dart::compiler::target::word Thread_top_offset = 60;
 static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
 static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 88;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
+    Thread_unboxed_int64_runtime_arg_offset = 96;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 84;
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
-    108;
+    116;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 192;
+    Thread_write_barrier_entry_point_offset = 200;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    44;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 608;
+    48;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 620;
 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;
@@ -1071,7 +1077,7 @@
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    16;
+    12;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
@@ -1266,131 +1272,133 @@
 static constexpr dart::compiler::target::word String_length_offset = 8;
 static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
 static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 560;
+    Thread_AllocateArray_entry_point_offset = 568;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1328;
+    1344;
 static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    1336;
+    1352;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_code_offset = 216;
+    Thread_array_write_barrier_code_offset = 224;
 static constexpr dart::compiler::target::word
-    Thread_array_write_barrier_entry_point_offset = 384;
+    Thread_array_write_barrier_entry_point_offset = 392;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    168;
+    176;
 static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 480;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
+    Thread_auto_scope_native_wrapper_entry_point_offset = 488;
+static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
+static constexpr dart::compiler::target::word Thread_bool_true_offset = 200;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_entry_point_offset = 392;
+    Thread_call_to_runtime_entry_point_offset = 400;
 static constexpr dart::compiler::target::word
-    Thread_call_to_runtime_stub_offset = 256;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1400;
+    Thread_call_to_runtime_stub_offset = 264;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1416;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
-    448;
-static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 304;
-static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
     456;
+static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 312;
+static constexpr dart::compiler::target::word Thread_deoptimize_entry_offset =
+    464;
 static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
-    312;
+    320;
 static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    520;
-static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 512;
-static constexpr dart::compiler::target::word Thread_end_offset = 120;
-static constexpr dart::compiler::target::word
-    Thread_enter_safepoint_stub_offset = 352;
-static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1368;
-static constexpr dart::compiler::target::word
-    Thread_exit_safepoint_stub_offset = 360;
-static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_stub_offset = 368;
-static constexpr dart::compiler::target::word
-    Thread_call_native_through_safepoint_entry_point_offset = 464;
-static constexpr dart::compiler::target::word
-    Thread_fix_allocation_stub_code_offset = 232;
-static constexpr dart::compiler::target::word
-    Thread_fix_callers_target_code_offset = 224;
-static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 544;
-static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 536;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
     528;
 static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 552;
+    Thread_double_negate_address_offset = 520;
+static constexpr dart::compiler::target::word Thread_end_offset = 128;
+static constexpr dart::compiler::target::word
+    Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::compiler::target::word Thread_execution_state_offset =
+    1384;
+static constexpr dart::compiler::target::word
+    Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_stub_offset = 376;
+static constexpr dart::compiler::target::word
+    Thread_call_native_through_safepoint_entry_point_offset = 472;
+static constexpr dart::compiler::target::word
+    Thread_fix_allocation_stub_code_offset = 240;
+static constexpr dart::compiler::target::word
+    Thread_fix_callers_target_code_offset = 232;
+static constexpr dart::compiler::target::word
+    Thread_float_absolute_address_offset = 552;
+static constexpr dart::compiler::target::word
+    Thread_float_negate_address_offset = 544;
+static constexpr dart::compiler::target::word Thread_float_not_address_offset =
+    536;
+static constexpr dart::compiler::target::word
+    Thread_float_zerow_address_offset = 560;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1344;
+    1360;
 static constexpr dart::compiler::target::word
-    Thread_interpret_call_entry_point_offset = 488;
+    Thread_interpret_call_entry_point_offset = 496;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_from_bytecode_stub_offset = 248;
+    Thread_invoke_dart_code_from_bytecode_stub_offset = 256;
 static constexpr dart::compiler::target::word
-    Thread_invoke_dart_code_stub_offset = 240;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
+    Thread_invoke_dart_code_stub_offset = 248;
+static constexpr dart::compiler::target::word Thread_isolate_offset = 104;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_return_stub_offset = 320;
+    Thread_lazy_deopt_from_return_stub_offset = 328;
 static constexpr dart::compiler::target::word
-    Thread_lazy_deopt_from_throw_stub_offset = 328;
+    Thread_lazy_deopt_from_throw_stub_offset = 336;
 static constexpr dart::compiler::target::word
-    Thread_lazy_specialize_type_test_stub_offset = 344;
+    Thread_lazy_specialize_type_test_stub_offset = 352;
 static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 144;
+    Thread_marking_stack_block_offset = 152;
 static constexpr dart::compiler::target::word
-    Thread_megamorphic_call_checked_entry_offset = 432;
+    Thread_megamorphic_call_checked_entry_offset = 440;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_entry_offset = 440;
+    Thread_monomorphic_miss_entry_offset = 448;
 static constexpr dart::compiler::target::word
-    Thread_monomorphic_miss_stub_offset = 296;
+    Thread_monomorphic_miss_stub_offset = 304;
 static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 472;
+    Thread_no_scope_native_wrapper_entry_point_offset = 480;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+    Thread_null_error_shared_with_fpu_regs_entry_point_offset = 416;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_with_fpu_regs_stub_offset = 272;
+    Thread_null_error_shared_with_fpu_regs_stub_offset = 280;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+    Thread_null_error_shared_without_fpu_regs_entry_point_offset = 408;
 static constexpr dart::compiler::target::word
-    Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
+    Thread_null_error_shared_without_fpu_regs_stub_offset = 272;
+static constexpr dart::compiler::target::word Thread_object_null_offset = 192;
 static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 496;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1352;
+    Thread_predefined_symbols_address_offset = 504;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1360;
+    Thread_saved_shadow_call_stack_offset = 1376;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1376;
+    1392;
 static constexpr dart::compiler::target::word
-    Thread_slow_type_test_stub_offset = 336;
+    Thread_slow_type_test_stub_offset = 344;
 static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
+static constexpr dart::compiler::target::word Thread_saved_stack_limit_offset =
+    80;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 80;
+    Thread_stack_overflow_flags_offset = 88;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+    Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 432;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+    Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 296;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+    Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 424;
 static constexpr dart::compiler::target::word
-    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+    Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 288;
 static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    136;
+    144;
 static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 128;
-static constexpr dart::compiler::target::word Thread_top_offset = 112;
+    Thread_top_exit_frame_info_offset = 136;
+static constexpr dart::compiler::target::word Thread_top_offset = 120;
 static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
 static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 176;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
+    Thread_unboxed_int64_runtime_arg_offset = 184;
+static constexpr dart::compiler::target::word Thread_vm_tag_offset = 168;
 static constexpr dart::compiler::target::word Thread_write_barrier_code_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word
-    Thread_write_barrier_entry_point_offset = 376;
+    Thread_write_barrier_entry_point_offset = 384;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    88;
+    96;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1384;
+    1400;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1424,16 +1432,16 @@
     Code_function_entry_point_offset[] = {8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232,
-        1240, 1248, 1256, 1264, -1,   -1,   -1,   -1,   1272, 1280, 1288,
-        1296, 1304, 1312, 1320, -1,   -1,   -1,   -1,   -1,   -1};
+        1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1240, 1248,
+        1256, 1264, 1272, 1280, -1,   -1,   -1,   -1,   1288, 1296, 1304,
+        1312, 1320, 1328, 1336, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word Array_header_size = 24;
 static constexpr dart::compiler::target::word Context_header_size = 24;
 static constexpr dart::compiler::target::word Double_InstanceSize = 16;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    24;
+    16;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
 static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
@@ -1448,579 +1456,4 @@
 static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
 #endif  // defined(TARGET_ARCH_ARM64)
 
-#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
-static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
-    16;
-static constexpr dart::compiler::target::word ObjectPool_element_size = 8;
-static constexpr dart::compiler::target::word Array_kMaxElements =
-    576460752303423487;
-static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
-    32765;
-static constexpr dart::compiler::target::word
-    Instructions_kMonomorphicEntryOffsetJIT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kPolymorphicEntryOffsetJIT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kMonomorphicEntryOffsetAOT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kPolymorphicEntryOffsetAOT = 0;
-static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 10;
-static constexpr dart::compiler::target::word
-    NativeEntry_kNumCallWrapperArguments = 2;
-static constexpr dart::compiler::target::word String_kMaxElements =
-    2305843009213693951;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kFunctionTypeArguments = 4;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceTypeArguments = 2;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstantiatorTypeArguments = 3;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kTestEntryLength = 7;
-static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
-static constexpr dart::compiler::target::word
-    AbstractType_type_test_stub_entry_point_offset = 8;
-static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
-    32;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_first_named_entry_offset = 48;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_named_entry_size = 16;
-static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
-    0;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_position_offset = 8;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_positional_count_offset = 40;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_type_args_len_offset = 24;
-static constexpr dart::compiler::target::word Array_data_offset = 24;
-static constexpr dart::compiler::target::word Array_length_offset = 16;
-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;
-static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    190;
-static constexpr dart::compiler::target::word Class_super_type_offset = 88;
-static constexpr dart::compiler::target::word
-    Class_type_arguments_field_offset_in_words_offset = 180;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_allocated_since_gc_new_space_offset = 96;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
-static constexpr dart::compiler::target::word
-    ClassTable_shared_class_table_offset = 40;
-static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
-static constexpr dart::compiler::target::word
-    SharedClassTable_class_heap_stats_table_offset = 0;
-static constexpr dart::compiler::target::word Closure_context_offset = 40;
-static constexpr dart::compiler::target::word
-    Closure_delayed_type_arguments_offset = 24;
-static constexpr dart::compiler::target::word Closure_function_offset = 32;
-static constexpr dart::compiler::target::word
-    Closure_function_type_arguments_offset = 16;
-static constexpr dart::compiler::target::word Closure_hash_offset = 48;
-static constexpr dart::compiler::target::word
-    Closure_instantiator_type_arguments_offset = 8;
-static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
-static constexpr dart::compiler::target::word Code_saved_instructions_offset =
-    48;
-static constexpr dart::compiler::target::word Code_owner_offset = 56;
-static constexpr dart::compiler::target::word Context_num_variables_offset = 8;
-static constexpr dart::compiler::target::word Context_parent_offset = 16;
-static constexpr dart::compiler::target::word Double_value_offset = 8;
-static constexpr dart::compiler::target::word
-    ExternalOneByteString_external_data_offset = 16;
-static constexpr dart::compiler::target::word
-    ExternalTwoByteString_external_data_offset = 16;
-static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
-static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
-static constexpr dart::compiler::target::word Field_guarded_cid_offset = 88;
-static constexpr dart::compiler::target::word
-    Field_guarded_list_length_in_object_offset_offset = 96;
-static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
-    56;
-static constexpr dart::compiler::target::word Field_is_nullable_offset = 90;
-static constexpr dart::compiler::target::word Field_static_value_offset = 32;
-static constexpr dart::compiler::target::word Field_kind_bits_offset = 98;
-static constexpr dart::compiler::target::word Function_code_offset = 88;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 8;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 16;
-static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    132;
-static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
-    24;
-static constexpr dart::compiler::target::word
-    GrowableObjectArray_length_offset = 16;
-static constexpr dart::compiler::target::word
-    GrowableObjectArray_type_arguments_offset = 8;
-static constexpr dart::compiler::target::word HeapPage_card_table_offset = 40;
-static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
-static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 24;
-static constexpr dart::compiler::target::word ICData_entries_offset = 8;
-static constexpr dart::compiler::target::word ICData_owner_offset = 40;
-static constexpr dart::compiler::target::word ICData_state_bits_offset = 52;
-static constexpr dart::compiler::target::word
-    ICData_receivers_static_type_offset = 32;
-static constexpr dart::compiler::target::word Isolate_class_table_offset = 80;
-static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
-static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
-static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
-static constexpr dart::compiler::target::word Isolate_object_store_offset = 72;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 128;
-static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
-static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
-static constexpr dart::compiler::target::word
-    LinkedHashMap_deleted_keys_offset = 48;
-static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
-    24;
-static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
-    40;
-static constexpr dart::compiler::target::word
-    MarkingStackBlock_pointers_offset = 16;
-static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 8;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 32;
-static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    8;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 16;
-static constexpr dart::compiler::target::word Mint_value_offset = 8;
-static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
-    8;
-static constexpr dart::compiler::target::word NativeArguments_argv_offset = 16;
-static constexpr dart::compiler::target::word NativeArguments_retval_offset =
-    24;
-static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
-static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    128;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 64;
-static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    160;
-static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
-    16;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_entry_point_offset = 16;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_lower_limit_offset = 24;
-static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
-    8;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_upper_limit_offset = 26;
-static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
-    16;
-static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 8;
-static constexpr dart::compiler::target::word String_hash_offset = 4;
-static constexpr dart::compiler::target::word String_length_offset = 8;
-static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
-static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 296;
-static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    888;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    896;
-static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    168;
-static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 216;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 200;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 192;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 960;
-static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    256;
-static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 248;
-static constexpr dart::compiler::target::word Thread_end_offset = 120;
-static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    928;
-static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 280;
-static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 272;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    264;
-static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 288;
-static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    904;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 96;
-static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 144;
-static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 208;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 184;
-static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 232;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 912;
-static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 920;
-static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    936;
-static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
-static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 80;
-static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    136;
-static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 128;
-static constexpr dart::compiler::target::word Thread_top_offset = 112;
-static constexpr dart::compiler::target::word Thread_top_resource_offset = 48;
-static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 176;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 160;
-static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    88;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 944;
-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
-    TypeArguments_instantiations_offset = 8;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
-static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
-    8;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
-static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
-static constexpr dart::compiler::target::word UserTag_tag_offset = 16;
-static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
-static constexpr dart::compiler::target::word Array_element_size = 8;
-static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 32;
-static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
-static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
-    0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 288;
-static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
-    8, 24, 16, 32};
-static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {8, 16};
-static constexpr dart::compiler::target::word Array_header_size = 24;
-static constexpr dart::compiler::target::word Context_header_size = 24;
-static constexpr dart::compiler::target::word Double_InstanceSize = 16;
-static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
-static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    24;
-static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
-static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
-static constexpr dart::compiler::target::word NativeArguments_StructSize = 32;
-static constexpr dart::compiler::target::word String_InstanceSize = 16;
-static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
-static constexpr dart::compiler::target::word Object_InstanceSize = 8;
-static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 24;
-static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
-static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
-    32;
-static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 56;
-#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
-
-#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
-static constexpr dart::compiler::target::word ObjectPool_elements_start_offset =
-    8;
-static constexpr dart::compiler::target::word ObjectPool_element_size = 4;
-static constexpr dart::compiler::target::word Array_kMaxElements = 268435455;
-static constexpr dart::compiler::target::word Array_kMaxNewSpaceElements =
-    65533;
-static constexpr dart::compiler::target::word
-    Instructions_kMonomorphicEntryOffsetJIT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kPolymorphicEntryOffsetJIT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kMonomorphicEntryOffsetAOT = 0;
-static constexpr dart::compiler::target::word
-    Instructions_kPolymorphicEntryOffsetAOT = 0;
-static constexpr dart::compiler::target::word HeapPage_kBytesPerCardLog2 = 9;
-static constexpr dart::compiler::target::word
-    NativeEntry_kNumCallWrapperArguments = 2;
-static constexpr dart::compiler::target::word String_kMaxElements = 536870911;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kFunctionTypeArguments = 4;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceClassIdOrFunction = 1;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstanceTypeArguments = 2;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kInstantiatorTypeArguments = 3;
-static constexpr dart::compiler::target::word
-    SubtypeTestCache_kTestEntryLength = 7;
-static constexpr dart::compiler::target::word SubtypeTestCache_kTestResult = 0;
-static constexpr dart::compiler::target::word
-    AbstractType_type_test_stub_entry_point_offset = 4;
-static constexpr dart::compiler::target::word ArgumentsDescriptor_count_offset =
-    16;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_first_named_entry_offset = 24;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_named_entry_size = 8;
-static constexpr dart::compiler::target::word ArgumentsDescriptor_name_offset =
-    0;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_position_offset = 4;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_positional_count_offset = 20;
-static constexpr dart::compiler::target::word
-    ArgumentsDescriptor_type_args_len_offset = 12;
-static constexpr dart::compiler::target::word Array_data_offset = 12;
-static constexpr dart::compiler::target::word Array_length_offset = 8;
-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;
-static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
-    106;
-static constexpr dart::compiler::target::word Class_super_type_offset = 44;
-static constexpr dart::compiler::target::word
-    Class_type_arguments_field_offset_in_words_offset = 96;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_allocated_since_gc_new_space_offset = 48;
-static constexpr dart::compiler::target::word
-    ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
-static constexpr dart::compiler::target::word
-    ClassTable_shared_class_table_offset = 20;
-static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
-static constexpr dart::compiler::target::word
-    SharedClassTable_class_heap_stats_table_offset = 0;
-static constexpr dart::compiler::target::word Closure_context_offset = 20;
-static constexpr dart::compiler::target::word
-    Closure_delayed_type_arguments_offset = 12;
-static constexpr dart::compiler::target::word Closure_function_offset = 16;
-static constexpr dart::compiler::target::word
-    Closure_function_type_arguments_offset = 8;
-static constexpr dart::compiler::target::word Closure_hash_offset = 24;
-static constexpr dart::compiler::target::word
-    Closure_instantiator_type_arguments_offset = 4;
-static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
-static constexpr dart::compiler::target::word Code_saved_instructions_offset =
-    24;
-static constexpr dart::compiler::target::word Code_owner_offset = 28;
-static constexpr dart::compiler::target::word Context_num_variables_offset = 4;
-static constexpr dart::compiler::target::word Context_parent_offset = 8;
-static constexpr dart::compiler::target::word Double_value_offset = 8;
-static constexpr dart::compiler::target::word
-    ExternalOneByteString_external_data_offset = 12;
-static constexpr dart::compiler::target::word
-    ExternalTwoByteString_external_data_offset = 12;
-static constexpr dart::compiler::target::word Float32x4_value_offset = 8;
-static constexpr dart::compiler::target::word Float64x2_value_offset = 8;
-static constexpr dart::compiler::target::word Field_guarded_cid_offset = 48;
-static constexpr dart::compiler::target::word
-    Field_guarded_list_length_in_object_offset_offset = 56;
-static constexpr dart::compiler::target::word Field_guarded_list_length_offset =
-    28;
-static constexpr dart::compiler::target::word Field_is_nullable_offset = 50;
-static constexpr dart::compiler::target::word Field_static_value_offset = 16;
-static constexpr dart::compiler::target::word Field_kind_bits_offset = 58;
-static constexpr dart::compiler::target::word Function_code_offset = 44;
-static constexpr dart::compiler::target::word Function_entry_point_offset = 4;
-static constexpr dart::compiler::target::word
-    Function_unchecked_entry_point_offset = 8;
-static constexpr dart::compiler::target::word Function_usage_counter_offset =
-    76;
-static constexpr dart::compiler::target::word GrowableObjectArray_data_offset =
-    12;
-static constexpr dart::compiler::target::word
-    GrowableObjectArray_length_offset = 8;
-static constexpr dart::compiler::target::word
-    GrowableObjectArray_type_arguments_offset = 4;
-static constexpr dart::compiler::target::word HeapPage_card_table_offset = 20;
-static constexpr dart::compiler::target::word ICData_NumArgsTestedMask = 3;
-static constexpr dart::compiler::target::word ICData_NumArgsTestedShift = 0;
-static constexpr dart::compiler::target::word
-    ICData_arguments_descriptor_offset = 12;
-static constexpr dart::compiler::target::word ICData_entries_offset = 4;
-static constexpr dart::compiler::target::word ICData_owner_offset = 20;
-static constexpr dart::compiler::target::word ICData_state_bits_offset = 28;
-static constexpr dart::compiler::target::word
-    ICData_receivers_static_type_offset = 16;
-static constexpr dart::compiler::target::word Isolate_class_table_offset = 40;
-static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
-static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
-static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
-static constexpr dart::compiler::target::word Isolate_object_store_offset = 36;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 64;
-static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
-static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
-static constexpr dart::compiler::target::word
-    LinkedHashMap_deleted_keys_offset = 24;
-static constexpr dart::compiler::target::word LinkedHashMap_hash_mask_offset =
-    12;
-static constexpr dart::compiler::target::word LinkedHashMap_index_offset = 8;
-static constexpr dart::compiler::target::word LinkedHashMap_used_data_offset =
-    20;
-static constexpr dart::compiler::target::word
-    MarkingStackBlock_pointers_offset = 8;
-static constexpr dart::compiler::target::word MarkingStackBlock_top_offset = 4;
-static constexpr dart::compiler::target::word
-    MegamorphicCache_arguments_descriptor_offset = 16;
-static constexpr dart::compiler::target::word MegamorphicCache_buckets_offset =
-    4;
-static constexpr dart::compiler::target::word MegamorphicCache_mask_offset = 8;
-static constexpr dart::compiler::target::word Mint_value_offset = 8;
-static constexpr dart::compiler::target::word NativeArguments_argc_tag_offset =
-    4;
-static constexpr dart::compiler::target::word NativeArguments_argv_offset = 8;
-static constexpr dart::compiler::target::word NativeArguments_retval_offset =
-    12;
-static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
-static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    64;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 32;
-static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    80;
-static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word Pointer_c_memory_address_offset =
-    8;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_entry_point_offset = 8;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_lower_limit_offset = 12;
-static constexpr dart::compiler::target::word SingleTargetCache_target_offset =
-    4;
-static constexpr dart::compiler::target::word
-    SingleTargetCache_upper_limit_offset = 14;
-static constexpr dart::compiler::target::word StoreBufferBlock_pointers_offset =
-    8;
-static constexpr dart::compiler::target::word StoreBufferBlock_top_offset = 4;
-static constexpr dart::compiler::target::word String_hash_offset = 8;
-static constexpr dart::compiler::target::word String_length_offset = 4;
-static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
-static constexpr dart::compiler::target::word
-    Thread_AllocateArray_entry_point_offset = 152;
-static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    448;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
-    452;
-static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
-    84;
-static constexpr dart::compiler::target::word
-    Thread_auto_scope_native_wrapper_entry_point_offset = 112;
-static constexpr dart::compiler::target::word Thread_bool_false_offset = 104;
-static constexpr dart::compiler::target::word Thread_bool_true_offset = 100;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 484;
-static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
-    132;
-static constexpr dart::compiler::target::word
-    Thread_double_negate_address_offset = 128;
-static constexpr dart::compiler::target::word Thread_end_offset = 60;
-static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    468;
-static constexpr dart::compiler::target::word
-    Thread_float_absolute_address_offset = 144;
-static constexpr dart::compiler::target::word
-    Thread_float_negate_address_offset = 140;
-static constexpr dart::compiler::target::word Thread_float_not_address_offset =
-    136;
-static constexpr dart::compiler::target::word
-    Thread_float_zerow_address_offset = 148;
-static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    456;
-static constexpr dart::compiler::target::word Thread_isolate_offset = 48;
-static constexpr dart::compiler::target::word
-    Thread_marking_stack_block_offset = 72;
-static constexpr dart::compiler::target::word
-    Thread_no_scope_native_wrapper_entry_point_offset = 108;
-static constexpr dart::compiler::target::word Thread_object_null_offset = 96;
-static constexpr dart::compiler::target::word
-    Thread_predefined_symbols_address_offset = 120;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 460;
-static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 464;
-static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    472;
-static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
-static constexpr dart::compiler::target::word
-    Thread_stack_overflow_flags_offset = 40;
-static constexpr dart::compiler::target::word Thread_store_buffer_block_offset =
-    68;
-static constexpr dart::compiler::target::word
-    Thread_top_exit_frame_info_offset = 64;
-static constexpr dart::compiler::target::word Thread_top_offset = 56;
-static constexpr dart::compiler::target::word Thread_top_resource_offset = 24;
-static constexpr dart::compiler::target::word
-    Thread_unboxed_int64_runtime_arg_offset = 88;
-static constexpr dart::compiler::target::word Thread_vm_tag_offset = 80;
-static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
-    44;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 476;
-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
-    TypeArguments_instantiations_offset = 4;
-static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
-static constexpr dart::compiler::target::word TypedDataBase_data_field_offset =
-    4;
-static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
-static constexpr dart::compiler::target::word
-    TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
-static constexpr dart::compiler::target::word UserTag_tag_offset = 8;
-static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
-static constexpr dart::compiler::target::word Array_element_size = 4;
-static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 16;
-static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
-static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
-    0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 168;
-static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
-    4, 12, 8, 16};
-static constexpr dart::compiler::target::word
-    Code_function_entry_point_offset[] = {4, 8};
-static constexpr dart::compiler::target::word Array_header_size = 12;
-static constexpr dart::compiler::target::word Context_header_size = 12;
-static constexpr dart::compiler::target::word Double_InstanceSize = 16;
-static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
-static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
-static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
-    16;
-static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
-static constexpr dart::compiler::target::word Mint_InstanceSize = 16;
-static constexpr dart::compiler::target::word NativeArguments_StructSize = 16;
-static constexpr dart::compiler::target::word String_InstanceSize = 12;
-static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
-static constexpr dart::compiler::target::word Object_InstanceSize = 4;
-static constexpr dart::compiler::target::word TypedDataBase_InstanceSize = 12;
-static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
-static constexpr dart::compiler::target::word GrowableObjectArray_InstanceSize =
-    16;
-static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word LinkedHashMap_InstanceSize = 28;
-#endif  // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
-
 #endif  // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index de860a7..dc49487 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -149,75 +149,73 @@
   FIELD(Thread, AllocateArray_entry_point_offset)                              \
   FIELD(Thread, active_exception_offset)                                       \
   FIELD(Thread, active_stacktrace_offset)                                      \
-  NOT_IN_DBC(FIELD(Thread, array_write_barrier_code_offset))                   \
-  NOT_IN_DBC(FIELD(Thread, array_write_barrier_entry_point_offset))            \
+  FIELD(Thread, array_write_barrier_code_offset)                               \
+  FIELD(Thread, array_write_barrier_entry_point_offset)                        \
   FIELD(Thread, async_stack_trace_offset)                                      \
   FIELD(Thread, auto_scope_native_wrapper_entry_point_offset)                  \
   FIELD(Thread, bool_false_offset)                                             \
   FIELD(Thread, bool_true_offset)                                              \
-  NOT_IN_DBC(FIELD(Thread, call_to_runtime_entry_point_offset))                \
-  NOT_IN_DBC(FIELD(Thread, call_to_runtime_stub_offset))                       \
+  FIELD(Thread, call_to_runtime_entry_point_offset)                            \
+  FIELD(Thread, call_to_runtime_stub_offset)                                   \
   FIELD(Thread, dart_stream_offset)                                            \
-  NOT_IN_DBC(FIELD(Thread, optimize_entry_offset))                             \
-  NOT_IN_DBC(FIELD(Thread, optimize_stub_offset))                              \
-  NOT_IN_DBC(FIELD(Thread, deoptimize_entry_offset))                           \
-  NOT_IN_DBC(FIELD(Thread, deoptimize_stub_offset))                            \
+  FIELD(Thread, optimize_entry_offset)                                         \
+  FIELD(Thread, optimize_stub_offset)                                          \
+  FIELD(Thread, deoptimize_entry_offset)                                       \
+  FIELD(Thread, deoptimize_stub_offset)                                        \
   FIELD(Thread, double_abs_address_offset)                                     \
   FIELD(Thread, double_negate_address_offset)                                  \
   FIELD(Thread, end_offset)                                                    \
-  NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset))                       \
+  FIELD(Thread, enter_safepoint_stub_offset)                                   \
   FIELD(Thread, execution_state_offset)                                        \
-  NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset))                        \
-  NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_stub_offset))         \
-  NOT_IN_DBC(FIELD(Thread, call_native_through_safepoint_entry_point_offset))  \
-  NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset))                   \
-  NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset))                    \
+  FIELD(Thread, exit_safepoint_stub_offset)                                    \
+  FIELD(Thread, call_native_through_safepoint_stub_offset)                     \
+  FIELD(Thread, call_native_through_safepoint_entry_point_offset)              \
+  FIELD(Thread, fix_allocation_stub_code_offset)                               \
+  FIELD(Thread, fix_callers_target_code_offset)                                \
   FIELD(Thread, float_absolute_address_offset)                                 \
   FIELD(Thread, float_negate_address_offset)                                   \
   FIELD(Thread, float_not_address_offset)                                      \
   FIELD(Thread, float_zerow_address_offset)                                    \
   FIELD(Thread, global_object_pool_offset)                                     \
-  NOT_IN_DBC(FIELD(Thread, interpret_call_entry_point_offset))                 \
-  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset))        \
-  NOT_IN_DBC(FIELD(Thread, invoke_dart_code_stub_offset))                      \
+  FIELD(Thread, interpret_call_entry_point_offset)                             \
+  FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset)                    \
+  FIELD(Thread, invoke_dart_code_stub_offset)                                  \
   FIELD(Thread, isolate_offset)                                                \
-  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_return_stub_offset))                \
-  NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_throw_stub_offset))                 \
-  NOT_IN_DBC(FIELD(Thread, lazy_specialize_type_test_stub_offset))             \
+  FIELD(Thread, lazy_deopt_from_return_stub_offset)                            \
+  FIELD(Thread, lazy_deopt_from_throw_stub_offset)                             \
+  FIELD(Thread, lazy_specialize_type_test_stub_offset)                         \
   FIELD(Thread, marking_stack_block_offset)                                    \
-  NOT_IN_DBC(FIELD(Thread, megamorphic_call_checked_entry_offset))             \
-  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_entry_offset))                     \
-  NOT_IN_DBC(FIELD(Thread, monomorphic_miss_stub_offset))                      \
+  FIELD(Thread, megamorphic_call_checked_entry_offset)                         \
+  FIELD(Thread, monomorphic_miss_entry_offset)                                 \
+  FIELD(Thread, monomorphic_miss_stub_offset)                                  \
   FIELD(Thread, no_scope_native_wrapper_entry_point_offset)                    \
-  NOT_IN_DBC(                                                                  \
-      FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset))       \
-  NOT_IN_DBC(FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset))       \
-  NOT_IN_DBC(                                                                  \
-      FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset))    \
-  NOT_IN_DBC(FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset))    \
+  FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset)            \
+  FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset)                   \
+                                                                               \
+  FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset)         \
+  FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset)                \
   FIELD(Thread, object_null_offset)                                            \
   FIELD(Thread, predefined_symbols_address_offset)                             \
   FIELD(Thread, resume_pc_offset)                                              \
   FIELD(Thread, saved_shadow_call_stack_offset)                                \
   FIELD(Thread, safepoint_state_offset)                                        \
-  NOT_IN_DBC(FIELD(Thread, slow_type_test_stub_offset))                        \
+  FIELD(Thread, slow_type_test_stub_offset)                                    \
   FIELD(Thread, stack_limit_offset)                                            \
+  FIELD(Thread, saved_stack_limit_offset)                                      \
   FIELD(Thread, stack_overflow_flags_offset)                                   \
-  NOT_IN_DBC(                                                                  \
-      FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset))   \
-  NOT_IN_DBC(FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset))   \
-  NOT_IN_DBC(FIELD(Thread,                                                     \
-                   stack_overflow_shared_without_fpu_regs_entry_point_offset)) \
-  NOT_IN_DBC(                                                                  \
-      FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset))       \
+  FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset)        \
+  FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset)               \
+  FIELD(Thread, stack_overflow_shared_without_fpu_regs_entry_point_offset)     \
+                                                                               \
+  FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset)            \
   FIELD(Thread, store_buffer_block_offset)                                     \
   FIELD(Thread, top_exit_frame_info_offset)                                    \
   FIELD(Thread, top_offset)                                                    \
   FIELD(Thread, top_resource_offset)                                           \
   FIELD(Thread, unboxed_int64_runtime_arg_offset)                              \
   FIELD(Thread, vm_tag_offset)                                                 \
-  NOT_IN_DBC(FIELD(Thread, write_barrier_code_offset))                         \
-  NOT_IN_DBC(FIELD(Thread, write_barrier_entry_point_offset))                  \
+  FIELD(Thread, write_barrier_code_offset)                                     \
+  FIELD(Thread, write_barrier_entry_point_offset)                              \
   FIELD(Thread, write_barrier_mask_offset)                                     \
   FIELD(Thread, callback_code_offset)                                          \
   FIELD(TimelineStream, enabled_offset)                                        \
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index c7ce24a..abb5b97 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -19,7 +19,7 @@
 
 class StubCodeCompiler : public AllStatic {
  public:
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
   static void GenerateBuildMethodExtractorStub(
       Assembler* assembler,
       const Object& closure_allocation_stub,
@@ -80,14 +80,12 @@
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 4;
 #elif defined(TARGET_ARCH_ARM64)
   static constexpr intptr_t kNativeCallbackTrampolineSize = 12;
-  static constexpr intptr_t kNativeCallbackSharedStubSize = 284;
+  static constexpr intptr_t kNativeCallbackSharedStubSize = 268;
   static constexpr intptr_t kNativeCallbackTrampolineStackDelta = 2;
 #endif
 
-#if !defined(TARGET_ARCH_DBC)
   static void GenerateJITCallbackTrampolines(Assembler* assembler,
                                              intptr_t next_callback_id);
-#endif
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index b8d0cb9..f506902 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -1559,6 +1559,7 @@
     // R3: next object start.
     // R4: allocation stats address.
     __ LoadObject(R8, NullObject());
+    __ MoveRegister(R9, R8);  // Needed for InitializeFieldsNoBarrier.
     __ StoreIntoObjectNoBarrier(
         R0, FieldAddress(R0, target::Context::parent_offset()), R8);
 
@@ -1658,27 +1659,17 @@
   // Save values being destroyed.
   __ PushList((1 << R2) | (1 << R3) | (1 << R4));
 
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-// TODO(21263): Implement 'swp' and use it below.
-#if !defined(USING_SIMULATOR)
-    ASSERT(OS::NumberOfAvailableProcessors() <= 1);
-#endif
-    __ ldr(R2, FieldAddress(R1, target::Object::tags_offset()));
-    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotRememberedBit));
-    __ str(R2, FieldAddress(R1, target::Object::tags_offset()));
-  } else {
-    // Atomically set the remembered bit of the object header.
-    ASSERT(target::Object::tags_offset() == 0);
-    __ sub(R3, R1, Operand(kHeapObjectTag));
-    // R3: Untagged address of header word (ldrex/strex do not support offsets).
-    Label retry;
-    __ Bind(&retry);
-    __ ldrex(R2, R3);
-    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotRememberedBit));
-    __ strex(R4, R2, R3);
-    __ cmp(R4, Operand(1));
-    __ b(&retry, EQ);
-  }
+  // Atomically set the remembered bit of the object header.
+  ASSERT(target::Object::tags_offset() == 0);
+  __ sub(R3, R1, Operand(kHeapObjectTag));
+  // R3: Untagged address of header word (ldrex/strex do not support offsets).
+  Label retry;
+  __ Bind(&retry);
+  __ ldrex(R2, R3);
+  __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotRememberedBit));
+  __ strex(R4, R2, R3);
+  __ cmp(R4, Operand(1));
+  __ b(&retry, EQ);
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
@@ -1717,28 +1708,18 @@
   __ PushList((1 << R2) | (1 << R3) | (1 << R4));  // Spill.
 
   Label marking_retry, lost_race, marking_overflow;
-  if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-// TODO(21263): Implement 'swp' and use it below.
-#if !defined(USING_SIMULATOR)
-    ASSERT(OS::NumberOfAvailableProcessors() <= 1);
-#endif
-    __ ldr(R2, FieldAddress(R0, target::Object::tags_offset()));
-    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
-    __ str(R2, FieldAddress(R0, target::Object::tags_offset()));
-  } else {
-    // Atomically clear kOldAndNotMarkedBit.
-    ASSERT(target::Object::tags_offset() == 0);
-    __ sub(R3, R0, Operand(kHeapObjectTag));
-    // R3: Untagged address of header word (ldrex/strex do not support offsets).
-    __ Bind(&marking_retry);
-    __ ldrex(R2, R3);
-    __ tst(R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
-    __ b(&lost_race, ZERO);
-    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
-    __ strex(R4, R2, R3);
-    __ cmp(R4, Operand(1));
-    __ b(&marking_retry, EQ);
-  }
+  // Atomically clear kOldAndNotMarkedBit.
+  ASSERT(target::Object::tags_offset() == 0);
+  __ sub(R3, R0, Operand(kHeapObjectTag));
+  // R3: Untagged address of header word (ldrex/strex do not support offsets).
+  __ Bind(&marking_retry);
+  __ ldrex(R2, R3);
+  __ tst(R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
+  __ b(&lost_race, ZERO);
+  __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
+  __ strex(R4, R2, R3);
+  __ cmp(R4, Operand(1));
+  __ b(&marking_retry, EQ);
 
   __ ldr(R4, Address(THR, target::Thread::marking_stack_block_offset()));
   __ ldr(R2, Address(R4, target::MarkingStackBlock::top_offset()));
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 326edcd..688e60b 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -212,18 +212,20 @@
   __ EnterFrame(0);
   __ PushRegisters(all_registers);
 
-  __ mov(CALLEE_SAVED_TEMP, SP);
+  __ mov(CALLEE_SAVED_TEMP, CSP);
+  __ mov(CALLEE_SAVED_TEMP2, SP);
   __ ReserveAlignedFrameSpace(0);
-
   __ mov(CSP, SP);
+
   __ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CALLEE_SAVED_TEMP);
+
+  __ mov(SP, CALLEE_SAVED_TEMP2);
+  __ mov(CSP, CALLEE_SAVED_TEMP);
 
   __ PopRegisters(all_registers);
   __ LeaveFrame();
 
-  __ mov(CSP, SP);
   __ Ret();
 }
 
@@ -234,9 +236,9 @@
   __ EnterFrame(0);
   __ PushRegisters(all_registers);
 
-  __ mov(CALLEE_SAVED_TEMP, SP);
+  __ mov(CALLEE_SAVED_TEMP, CSP);
+  __ mov(CALLEE_SAVED_TEMP2, SP);
   __ ReserveAlignedFrameSpace(0);
-
   __ mov(CSP, SP);
 
   // Set the execution state to VM while waiting for the safepoint to end.
@@ -247,12 +249,13 @@
 
   __ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
   __ blr(R0);
-  __ mov(SP, CALLEE_SAVED_TEMP);
+
+  __ mov(SP, CALLEE_SAVED_TEMP2);
+  __ mov(CSP, CALLEE_SAVED_TEMP);
 
   __ PopRegisters(all_registers);
   __ LeaveFrame();
 
-  __ mov(CSP, SP);
   __ Ret();
 }
 
@@ -272,6 +275,7 @@
   __ mov(R19, LR);
   __ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/,
                                  /*enter_safepoint=*/true);
+  __ mov(R25, CSP);
   __ mov(CSP, SP);
 
 #if defined(DEBUG)
@@ -286,7 +290,10 @@
 #endif
 
   __ blr(R8);
+
   __ mov(SP, CSP);
+  __ mov(CSP, R25);
+
   __ TransitionNativeToGenerated(R9, /*leave_safepoint=*/true);
   __ ret(R19);
 }
@@ -385,12 +392,12 @@
   __ LoadFieldFromOffset(R9, R9,
                          compiler::target::GrowableObjectArray::data_offset());
   __ ldr(R9, __ ElementAddressForRegIndex(
-                 /*is_load=*/true,
                  /*external=*/false,
                  /*array_cid=*/kArrayCid,
                  /*index, smi-tagged=*/compiler::target::kWordSize * 2,
                  /*array=*/R9,
-                 /*index=*/R8));
+                 /*index=*/R8,
+                 /*temp=*/TMP));
   __ LoadFieldFromOffset(R9, R9, compiler::target::Code::entry_point_offset());
 
   // Clobbers all volatile registers, including the callback ID in R8.
@@ -1313,9 +1320,12 @@
 void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ Comment("InvokeDartCodeStub");
 
-  // Copy the C stack pointer (R31) into the stack pointer we'll actually use
-  // to access the stack.
-  __ SetupDartSP();
+  // Copy the C stack pointer (CSP/R31) into the stack pointer we'll actually
+  // use to access the stack (SP/R15) and set the C stack pointer to near the
+  // stack limit, loaded from the Thread held in R3, to prevent signal handlers
+  // from over-writing Dart frames.
+  __ mov(SP, CSP);
+  __ SetupCSPFromThread(R3);
   __ Push(LR);  // Marker for the profiler.
   __ EnterFrame(0);
 
@@ -1430,7 +1440,7 @@
 
 
 #if defined(TARGET_OS_FUCHSIA)
-  __ mov (R3, THR);
+  __ mov(R3, THR);
 #endif
 
   __ PopNativeCalleeSavedRegisters();  // Clobbers THR
@@ -1460,9 +1470,12 @@
 #if defined(DART_PRECOMPILED_RUNTIME)
   __ Stop("Not using interpreter");
 #else
-  // Copy the C stack pointer (R31) into the stack pointer we'll actually use
-  // to access the stack.
-  __ SetupDartSP();
+  // Copy the C stack pointer (CSP/R31) into the stack pointer we'll actually
+  // use to access the stack (SP/R15) and set the C stack pointer to near the
+  // stack limit, loaded from the Thread held in R3, to prevent signal handlers
+  // from over-writing Dart frames.
+  __ mov(SP, CSP);
+  __ SetupCSPFromThread(R3);
   __ Push(LR);  // Marker for the profiler.
   __ EnterFrame(0);
 
@@ -1569,7 +1582,7 @@
   __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
 #if defined(TARGET_OS_FUCHSIA)
-  __ mov (R3, THR);
+  __ mov(R3, THR);
 #endif
 
   __ PopNativeCalleeSavedRegisters();  // Clobbers THR
@@ -3143,6 +3156,7 @@
   __ mov(SP, R1);  // Stack pointer.
   __ mov(FP, R2);  // Frame_pointer.
   __ mov(THR, R3);
+  __ SetupCSPFromThread(THR);
 #if defined(TARGET_OS_FUCHSIA)
   __ ldr(R18, Address(THR, target::Thread::saved_shadow_call_stack_offset()));
 #elif defined(USING_SHADOW_CALL_STACK)
diff --git a/runtime/vm/compiler/stub_code_compiler_dbc.cc b/runtime/vm/compiler/stub_code_compiler_dbc.cc
deleted file mode 100644
index f303ad4..0000000
--- a/runtime/vm/compiler/stub_code_compiler_dbc.cc
+++ /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.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
-#include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/runtime_entry.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
-#include "vm/tags.h"
-
-#define __ assembler->
-
-namespace dart {
-
-DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
-DEFINE_FLAG(bool,
-            use_slow_path,
-            false,
-            "Set to true for debugging & verifying the slow paths.");
-
-namespace compiler {
-
-void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
-  __ Compile();
-}
-
-void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
-    Assembler* assembler) {
-  __ NoSuchMethod();
-}
-
-// Not executed, but used as a stack marker when calling
-// DRT_OptimizeInvokedFunction.
-void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// Not executed, but used as a sentinel in Simulator::JumpToFrame.
-void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
-  __ DeoptRewind();
-}
-
-// TODO(vegorov) Don't generate this stub.
-void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(vegorov) Don't generate these stubs.
-void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
-                                                      const Class& cls) {
-  __ Trap();
-}
-
-// TODO(vegorov) Don't generate this stub.
-void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// These deoptimization stubs are only used to populate stack frames
-// with something meaningful to make sure GC can scan the stack during
-// the last phase of deoptimization which materializes objects.
-void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
-    Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
-    Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
-    Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
-    Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
-    Assembler* assembler) {
-  __ Trap();
-}
-
-}  // namespace compiler
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 5e58117..f0b4045 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -13,8 +13,6 @@
 #include "vm/constants_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/constants_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/constants_dbc.h"
 #else
 #error Unknown architecture.
 #endif
@@ -41,8 +39,6 @@
 using namespace arch_arm;  // NOLINT
 #elif defined(TARGET_ARCH_ARM64)
 using namespace arch_arm64;  // NOLINT
-#elif defined(TARGET_ARCH_DBC)
-// DBC is defined in namespace dart already.
 #else
 #error Unknown architecture.
 #endif
@@ -85,8 +81,6 @@
 #endif  // !defined(HOST_ARCH_EQUALS_TARGET_ARCH)
 };
 
-#if !defined(TARGET_ARCH_DBC)
-
 static constexpr bool IsArgumentRegister(Register reg) {
   return ((1 << reg) & CallingConventions::kArgumentRegisters) != 0;
 }
@@ -99,8 +93,6 @@
   return ((1 << reg) & CallingConventions::kCalleeSaveCpuRegisters) != 0;
 }
 
-#endif  // !defined(TARGET_ARCH_DBC)
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_CONSTANTS_H_
diff --git a/runtime/vm/constants_dbc.cc b/runtime/vm/constants_dbc.cc
deleted file mode 100644
index abad6e5..0000000
--- a/runtime/vm/constants_dbc.cc
+++ /dev/null
@@ -1,25 +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.
-
-#define RUNTIME_VM_CONSTANTS_H_  // To work around include guard.
-#include "vm/constants_dbc.h"
-
-namespace dart {
-
-const char* cpu_reg_names[kNumberOfCpuRegisters] = {
-    "R0",  "R1",  "R2",  "R3",  "R4",  "R5",  "R6",  "R7",  "R8",  "R9",  "R10",
-    "R11", "R12", "R13", "R14", "R15", "R16", "R17", "R18", "R19", "R20", "R21",
-    "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R29", "R30", "R31",
-#if defined(ARCH_IS_64_BIT)
-    "R32", "R33", "R34", "R35", "R36", "R37", "R38", "R39", "R40", "R41", "R42",
-    "R43", "R44", "R45", "R46", "R47", "R48", "R49", "R50", "R51", "R52", "R53",
-    "R54", "R55", "R56", "R57", "R58", "R59", "R60", "R61", "R62", "R63",
-#endif
-};
-
-const char* fpu_reg_names[kNumberOfFpuRegisters] = {
-    "F0",
-};
-
-}  // namespace dart
diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h
deleted file mode 100644
index d05a74e..0000000
--- a/runtime/vm/constants_dbc.h
+++ /dev/null
@@ -1,1161 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_CONSTANTS_DBC_H_
-#define RUNTIME_VM_CONSTANTS_DBC_H_
-
-#include "platform/assert.h"
-#include "platform/globals.h"
-#include "platform/utils.h"
-
-namespace dart {
-
-// clang-format off
-// List of Simulator Bytecode instructions.
-//
-// INTERPRETER STATE
-//
-//      current frame info (see stack_frame_dbc.h for layout)
-//        v-----^-----v
-//   ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~
-//   ~    |    ~ ~    | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] |
-//   ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~
-//                    ^                             ^
-//                    FP                            SP
-//
-//
-// The state of execution is captured in few interpreter registers:
-//
-//   FP - base of the current frame
-//   SP - top of the stack (TOS) for the current frame
-//   PP - object pool for the currently execution function
-//
-// Frame info stored below FP additionally contains pointers to the currently
-// executing function and code (see stack_frame_dbc.h for more information).
-//
-// In the unoptimized code most of bytecodes take operands implicitly from
-// stack and store results again on the stack. Constant operands are usually
-// taken from the object pool by index.
-//
-// ENCODING
-//
-// Each instruction is a 32-bit integer with opcode stored in the least
-// significant byte. The following operand encodings are used:
-//
-//   0........8.......16.......24.......32
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~~~~~~~~~~~~~~~~~~~|   0: no operands
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |~~~~~~~~~~~~~~~~~|   A: single unsigned 8-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |        D        | A_D: unsigned 8-bit operand and
-//   +--------+--------+--------+--------+      unsigned 16-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |        X        | A_X: unsigned 8-bit operand and
-//   +--------+--------+--------+--------+      signed 16-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~|        D        |   D: unsigned 16-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |~~~~~~~~|        X        |   X: signed 16-bit operand
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |    B   |    C   | A_B_C: 3 unsigned 8-bit operands
-//   +--------+--------+--------+--------+
-//
-//   +--------+--------+--------+--------+
-//   | opcode |    A   |    B   |    Y   | A_B_Y: 2 unsigned 8-bit operands
-//   +--------+--------+--------+--------+        1 signed 8-bit operand
-//
-//   +--------+--------+--------+--------+
-//   | opcode |             T            |   T: signed 24-bit operand
-//   +--------+--------+--------+--------+
-//
-//
-// INSTRUCTIONS
-//
-//  - Trap
-//
-//    Unreachable instruction.
-//
-//  - Nop D
-//
-//    This instruction does nothing. It may refer to an object in the constant
-//    pool that may be decoded by other instructions.
-//
-//  - Compile
-//
-//    Compile current function and start executing newly produced code
-//    (used to implement LazyCompileStub);
-//
-//  - Intrinsic id
-//
-//    Execute intrinsic with the given id. If intrinsic returns true then
-//    return from the current function to the caller passing value produced
-//    by the intrinsic as a result;
-//
-//  - Drop1; DropR n; Drop n
-//
-//    Drop 1 or n values from the stack, if instruction is DropR push the first
-//    dropped value to the stack;
-//
-//  - Jump target
-//
-//    Jump to the given target. Target is specified as offset from the PC of the
-//    jump instruction.
-//
-//  - Return R; ReturnTOS
-//
-//    Return to the caller using either a value from the given register or a
-//    value from the top-of-stack as a result.
-//
-//    Note: return instruction knows how many arguments to remove from the
-//    stack because it can look at the call instruction at caller's PC and
-//    take argument count from it.
-//
-//  - Move rA, rX
-//
-//    FP[rA] <- FP[rX]
-//    Note: rX is signed so it can be used to address parameters which are
-//    at negative indices with respect to FP.
-//
-//  - Swap rA, rX
-//
-//    FP[rA], FP[rX] <- FP[rX], FP[rA]
-//    Note: rX is signed so it can be used to address parameters which are
-//    at negative indices with respect to FP.
-//
-//  - Push rX
-//
-//    Push FP[rX] to the stack.
-//
-//  - LoadConstant rA, D; PushConstant D
-//
-//    Load value at index D from constant pool into FP[rA] or push it onto the
-//    stack.
-//
-//  - StoreLocal rX; PopLocal rX
-//
-//    Store top of the stack into FP[rX] and pop it if needed.
-//
-//  - StaticCall ArgC, D
-//
-//    Invoke function in SP[0] with arguments SP[-(1+ArgC)], ..., SP[-1] and
-//    argument descriptor PP[D], which indicates whether the first argument
-//    is a type argument vector.
-//
-//  - IndirectStaticCall ArgC, D
-//
-//    Invoke the function given by the ICData in SP[0] with arguments
-//    SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which
-//    indicates whether the first argument is a type argument vector.
-//
-//  - InstanceCall<N> ArgC, D; InstanceCall<N>Opt ArgC, D
-//
-//    Lookup and invoke method with N checked arguments using ICData in PP[D]
-//    with arguments SP[-(1+ArgC)], ..., SP[-1].
-//    The ICData indicates whether the first argument is a type argument vector.
-//
-//  - NativeCall ArgA, ArgB, ArgC
-//
-//    Invoke native function at pool[ArgB] with argc_tag at pool[ArgC] using
-//    wrapper at pool[ArgA].
-//
-//  - FfiCall ArgD
-//
-//    Invoke foreign function with unboxed arguments using the signature
-//    descriptor PP[D].
-//
-//  - PushPolymorphicInstanceCall ArgC, D
-//
-//    Skips 2*D + 1 instructions and pushes a function object onto the stack
-//    if one can be found as follows. Otherwise skips only 2*D instructions.
-//    The function is looked up in the IC data encoded in the following 2*D
-//    Nop instructions. The Nop instructions should be arranged in pairs with
-//    the first being the cid, and the second being the function to push if
-//    the cid matches the cid in the pair.
-//
-//  - PushPolymorphicInstanceCallByRange ArgC, D
-//
-//    Skips 3*D + 1 instructions and pushes a function object onto the stack
-//    if one can be found as follows. Otherwise skips only 3*D instructions.
-//    The function is looked up in the IC data encoded in the following 3*D
-//    Nop instructions. The Nop instructions should be arranged in triples with
-//    the first being the start cid, the second being the number of cids, and
-//    the third being the function to push if the cid is in the range given
-//    by the first two Nop instructions.
-//
-//  - OneByteStringFromCharCode rA, rX
-//
-//    Load the one-character symbol with the char code given by the Smi
-//    in FP[rX] into FP[rA].
-//
-//  - StringToCharCode rA, rX
-//
-//    Load and smi-encode the single char code of the string in FP[rX] into
-//    FP[rA]. If the string's length is not 1, load smi -1 instead.
-//
-//  - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS;
-//    GreaterThanTOS;
-//
-//    Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are
-//    both smis and result of SP[0] <op> SP[-1] is a smi - if this is true
-//    then pops operands and pushes result on the stack and skips the next
-//    instruction (which implements a slow path fallback).
-//
-//  - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC
-//
-//    Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC].
-//    If these instructions can trigger a deoptimization, the following
-//    instruction should be Deopt. If no deoptimization should be triggered,
-//    the immediately following instruction is skipped. These instructions
-//    expect their operands to be Smis, but don't check that they are.
-//
-//  - Smi<op>TOS
-//
-//    Performs SP[0] <op> SP[-1], pops operands and pushes result on the stack.
-//    Assumes SP[0] and SP[-1] are both smis and the result is a Smi.
-//
-//  - ShlImm rA, rB, rC
-//
-//    FP[rA] <- FP[rB] << rC. Shifts the Smi in FP[rB] left by rC. rC is
-//    assumed to be a legal positive number by which left-shifting is possible.
-//
-//  - Min, Max rA, rB, rC
-//
-//    FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are
-//    Smis.
-//
-//  - Neg rA , rD
-//
-//    FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the
-//    immediately following instruction is skipped.
-//
-//  - DMin, DMax, DAdd, DSub, DMul, DDiv, DPow, DMod rA, rB, rC
-//
-//    Arithmetic operations on unboxed doubles. FP[rA] <- FP[rB] op FP[rC].
-//
-//  - DNeg, DCos, DSin, DSqrt rA, rD
-//
-//    FP[rA] <- op(FP[rD]). Assumes FP[rD] is an unboxed double.
-//
-//  - DTruncate, DFloor, DCeil rA, rD
-//
-//    Applies trunc(), floor(), or ceil() to the unboxed double in FP[rD], and
-//    stores the result in FP[rA].
-//
-//  - DoubleToFloat, FloatToDouble rA, rD
-//
-//    Convert the unboxed float or double in FP[rD] as indicated, and store the
-//    result in FP[rA].
-//
-//  - DoubleIsNaN rA, rD
-//
-//    If the unboxed double in FP[rD] is a NaN, then writes Bool::True().raw()
-//    into FP[rA], and Bool::False().raw() otherwise.
-//
-//  - DoubleIsInfinite rA, rD
-//
-//    If the unboxed double in FP[rD] is + or - infinity, then
-//    writes Bool::True().raw() into FP[rA], and Bool::False().raw() otherwise.
-//
-//  - BitOr, BitAnd, BitXor rA, rB, rC
-//
-//    FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be
-//    Smis, but don't check that they are.
-//
-//  - BitNot rA, rD
-//
-//    FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi.
-//
-//  - WriteIntoDouble rA, rD
-//
-//    Box the double in FP[rD] using the box in FP[rA].
-//
-//  - UnboxDouble rA, rD
-//
-//    Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double.
-//
-//  - CheckedUnboxDouble rA, rD
-//
-//    Unboxes FP[rD] into FP[rA] and skips the following instruction unless
-//    FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a
-//    double.
-//
-//  - UnboxInt32 rA, rB, C
-//
-//    Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be
-//    truncated. If FP[rA] is successfully unboxed the following instruction is
-//    skipped.
-//
-//  - BoxInt32 rA, rD
-//
-//    Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA].
-//
-//  - BoxUint32 rA, rD
-//
-//    Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA].
-//
-//  - UnboxInt64 rA, rD
-//
-//    Unboxes the integer in FP[rD] into FP[rA].
-//
-//  - BoxInt64 rA, rD
-//
-//    Boxes the unboxed signed 64-bit integer in FP[rD] into FP[rA]. If the
-//    value does not fit into a Smi the following instruction is skipped. (The
-//    following instruction should be a jump to a label after the slow path
-//    allocating a Mint box and writing into the Mint box.)
-//
-//  - UnboxedWidthExtender rA rB C
-//
-//    Sign- or zero-extends an unboxed integer in FP[rB] into an unboxed
-//    integer in FP[rA]. C contains SmallRepresentation which determines how
-//    the integer is extended.
-//
-//  - WriteIntoMint rA, rD
-//
-//    Box the integer in FP[rD] using the Mint box in FP[rA].
-//
-//  - SmiToDouble rA, rD
-//
-//    Convert the Smi in FP[rD] to an unboxed double in FP[rA].
-//
-//  - DoubleToSmi rA, rD
-//
-//    If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then
-//    this instruction does so, and skips the following instruction. Otherwise,
-//    the following instruction is not skipped.
-//
-//  - StoreStaticTOS D
-//
-//    Stores TOS into the static field PP[D].
-//
-//  - PushStatic
-//
-//    Pushes value of the static field PP[D] on to the stack.
-//
-//  - InitStaticTOS
-//
-//    Takes static field from TOS and ensures that it is initialized.
-//
-//  - If<Cond>(Num)TOS
-//    If<Cond>(Num) rA, rD
-//
-//    Cond is either NeStrict or EqStrict
-//
-//    Skips the next instruction unless the given condition holds. 'Num'
-//    variants perform number check while non-Num variants just compare
-//    RawObject pointers.
-//
-//    Used to implement conditional jump:
-//
-//        IfNeStrictTOS
-//        Jump T         ;; jump if not equal
-//
-//  - If<Cond>Null rA
-//    If<Cond>NullTOS
-//
-//    Cond is Eq or Ne. Skips the next instruction unless the given condition
-//    holds.
-//
-//  - If<Cond> rA, rD
-//
-//    Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and
-//    unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt.
-//    Skips the next instruction unless FP[rA] <Cond> FP[rD]. Assumes that
-//    FP[rA] and FP[rD] are Smis or unboxed doubles as indicated by <Cond>.
-//
-//  - IfSmi<Cond>TOS
-//
-//    Cond is Lt, Le, Ge, Gt.
-//    Skips the next instruction unless SP[-1] <Cond> SP[-0].
-//    It is expected both SP[-1] and SP[-0] are Smis.
-//
-//  - CreateArrayTOS
-//
-//    Allocate array of length SP[0] with type arguments SP[-1].
-//
-//  - CreateArrayOpt rA, rB, rC
-//
-//    Try to allocate a new array where FP[rB] is the length, and FP[rC] is the
-//    type. If allocation is successful, the result is stored in FP[rA], and
-//    the next four instructions, which should be the
-//    (Push type; Push length; AllocateTOS; PopLocal) slow path are skipped.
-//
-//  - Allocate D
-//
-//    Allocate object of class PP[D] with no type arguments.
-//
-//  - AllocateOpt rA, D
-//
-//    Try allocating an object with tags in PP[D] with no type arguments.
-//    If allocation is successful, the result is stored in FP[rA], and
-//    the next two instructions, which should be the (Allocate class; PopLocal)
-//    slow path are skipped
-//
-//  - AllocateT
-//
-//    Allocate object of class SP[0] with type arguments SP[-1].
-//
-//  - AllocateTOpt rA, D
-//
-//    Similar to AllocateOpt with the difference that the offset of the
-//    type arguments in the resulting object is taken from the D field of the
-//    following Nop instruction, and on success 4 instructions are skipped and
-//    the object at the top of the stack is popped.
-//
-//  - StoreIndexedTOS
-//
-//    Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done.
-//    SP[-2] is assumed to be a RawArray, SP[-1] to be a smi.
-//
-//  - StoreIndexed rA, rB, rC
-//
-//    Store FP[rC] into array FP[rA] at index FP[rB]. No typechecking is done.
-//    FP[rA] is assumed to be a RawArray, FP[rB] to be a smi.
-//
-//  - StoreIndexed{N}{Type} rA, rB, rC
-//
-//    Where Type is Float32, Float64, Uint8, or OneByteString
-//    Where N is '', '4', or '8'. N may only be '4' for Float32 and '8' for
-//    Float64.
-//
-//    Store the unboxed double or tagged Smi in FP[rC] into the typed data array
-//    at FP[rA] at index FP[rB]. If N is not '', the index is assumed to be
-//    already scaled by N.
-//
-//  - StoreIndexedExternalUint8 rA, rB, rC
-//
-//    Similar to StoreIndexedUint8 but FP[rA] is an external typed data aray.
-//
-//  - NoSuchMethod
-//
-//    Performs noSuchmethod handling code.
-//
-//  - TailCall
-//
-//    Unwinds the current frame, populates the arguments descriptor register
-//    with SP[-1] and tail calls the code in SP[-0].
-//
-//  - TailCallOpt  rA, rD
-//
-//    Unwinds the current frame, populates the arguments descriptor register
-//    with rA and tail calls the code in rD.
-//
-//  - LoadArgDescriptor
-//
-//    Load the caller-provoided argument descriptor and pushes it onto the
-//    stack.
-//
-//  - LoadArgDescriptorOpt rA
-//
-//    Load the caller-provoided argument descriptor into [rA].
-//
-//  - LoadFpRelativeSlot rD
-//
-//    Loads from FP using the negative index of SP[-0]+rD.
-//    It is assumed that SP[-0] is a Smi.
-//
-//  - LoadFpRelativeSlotOpt  rA, rB, rY
-//
-//    Loads from FP using the negative index of FP[rB]+rY and stores the result
-//    into rA.
-//    It is assumed that rY is a Smi.
-//
-//  - StoreFpRelativeSlot rD
-//
-//    Stores SP[-0] by indexing into FP using the negative index of SP[-1]+rD.
-//    It is assumed that SP[-1] is a Smi.
-//
-//  - StoreFpRelativeSlotOpt  rA, rB, rY
-//
-//    Stores rA by indexing into FP using the the negative index of FP[rB]+rY.
-//    It is assumed that rY is a Smi.
-//
-//  - LoadIndexedTOS
-//
-//    Loads from array SP[-1] at index SP[-0].
-//    It is assumed that SP[-0] is a Smi.
-//
-//  - LoadIndexed rA, rB, rC
-//
-//    Loads from array FP[rB] at index FP[rC] into FP[rA]. No typechecking is
-//    done. FP[rB] is assumed to be a RawArray, and to contain a Smi at FP[rC].
-//
-//  - LoadIndexed{N}{Type} rA, rB, rC
-//
-//    Where Type is Float32, Float64, OneByteString, TwoByteString, Uint8,
-//    Int8, and N is '', '4', or '8'. N may only be '4' for Float32, and may
-//    only be '8' for Float64.
-//
-//    Loads from typed data array FP[rB] at index FP[rC] into an unboxed double,
-//    or tagged Smi in FP[rA] as indicated by the type in the name. If N is not
-//    '', the index is assumed to be already scaled by N.
-//
-//  - LoadIndexedExternal{Int8, Uint8} rA, rB, rC
-//
-//    Loads from the external typed data array FP[rB] at index FP[rC] into
-//    FP[rA]. No typechecking is done.
-//
-//  - StoreField rA, B, rC
-//
-//    Store value FP[rC] into object FP[rA] at offset (in words) B.
-//
-//  - StoreFieldExt rA, rD
-//
-//    Store value FP[rD] into object FP[rA] at offset (in words)
-//    stored in the following Nop instruction. Used to access fields with
-//    large offsets.
-//
-//  - StoreUntagged rA, B, rC
-//
-//    Like StoreField, but assumes that FP[rC] is untagged.
-//
-//  - StoreFieldTOS D
-//
-//    Store value SP[0] into object SP[-1] at offset (in words) D.
-//
-//  - LoadField rA, rB, C
-//
-//    Load value at offset (in words) C from object FP[rB] into FP[rA].
-//
-//  - LoadFieldExt rA, rD
-//
-//    Load value from object FP[rD] at offset (in words) stored in the
-//    following Nop instruction into FP[rA]. Used to access fields with
-//    large offsets.
-//
-//  - LoadUntagged rA, rB, C
-//
-//    Like LoadField, but assumes that FP[rB] is untagged.
-//
-//  - LoadFieldTOS D
-//
-//    Push value at offset (in words) D from object SP[0].
-//
-//  - BooleanNegateTOS
-//
-//    SP[0] = !SP[0]
-//
-//  - BooleanNegate rA, rD
-//
-//    FP[rA] = !FP[rD]
-//
-//  - Throw A
-//
-//    Throw (Rethrow if A != 0) exception. Exception object and stack object
-//    are taken from TOS.
-//
-//  - Entry rD
-//
-//    Function prologue for the function
-//        rD - number of local slots to reserve;
-//
-//  - EntryOptimized rD
-//
-//    Function prologue for optimized functions.
-//        rD - number of local slots to reserve for registers;
-//
-//    Note: reserved slots are not initialized because optimized code
-//    has stack maps attached to call sites.
-//
-//  - HotCheck A, D
-//
-//    Increment current function's usage counter by A and check if it
-//    exceeds D. If it does trigger (re)optimization of the current
-//    function.
-//
-//  - Frame D
-//
-//    Reserve and initialize with null space for D local variables.
-//
-//  - SetFrame A
-//
-//    Reinitialize SP assuming that current frame has size A.
-//    Used to drop temporaries from the stack in the exception handler.
-//
-//  - AllocateContext D
-//
-//    Allocate Context object assuming for D context variables.
-//
-//  - AllocateUninitializedContext rA, D
-//
-//    Allocates an uninitialized context for D variables, and places the result
-//    in FP[rA]. On success, skips the next 2 instructions, which should be the
-//    slow path (AllocateContext D; PopLocal rA).
-//
-//  - CloneContext
-//
-//    Clone context stored in TOS.
-//
-//  - MoveSpecial rA, D
-//
-//    Copy special values from inside interpreter to FP[rA]. Currently only
-//    used to pass exception object (D = 0) and stack trace object (D = 1) to
-//    catch handler.
-//
-//  - InstantiateType D
-//
-//    Instantiate type PP[D] with instantiator type arguments SP[-1] and
-//    function type arguments SP[0].
-//
-//  - InstantiateTypeArgumentsTOS D
-//
-//    Instantiate type arguments PP[D] with instantiator type arguments SP[-1]
-//    and function type arguments SP[0].
-//
-//  - InstanceOf
-//
-//    Test if instance SP[-4] with instantiator type arguments SP[-3] and
-//    function type arguments SP[-2] is a subtype of type SP[-1] using
-//    SubtypeTestCache SP[0], with result placed at top of stack.
-//
-//  - AssertAssignable A, D
-//
-//    Assert that instance SP[-4] is assignable to variable named SP[0] of
-//    type SP[-1] with instantiator type arguments SP[-3] and function type
-//    arguments SP[-2] using SubtypeTestCache PP[D].
-//    If A is 1, then the instance may be a Smi.
-//
-//    Instance remains on stack. Other arguments are consumed.
-//
-//  - AssertSubtype
-//
-//    Assert that one type is a subtype of another.  Throws a TypeError
-//    otherwise.  The stack has the following arguments on it:
-//
-//        SP[-4]  instantiator type args
-//        SP[-3]  function type args
-//        SP[-2]  sub_type
-//        SP[-1]  super_type
-//        SP[-0]  dst_name
-//
-//    All 5 arguments are consumed from the stack and no results is pushed.
-//
-//  - BadTypeError
-//
-//    If SP[-4] is non-null, throws a BadType error by calling into the runtime.
-//    Assumes that the stack is arranged the same as for AssertAssignable.
-//
-//  - AssertBoolean A
-//
-//    Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0).
-//
-//  - TestSmi rA, rD
-//
-//    If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD]
-//    must be Smis.
-//
-//  - TestCids rA, D
-//
-//    The next D instructions must be Nops whose D field encodes a class id. If
-//    the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's
-//    A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found,
-//    jump to PC + N.
-//
-//  - CheckSmi rA
-//
-//    If FP[rA] is a Smi, then skip the next instruction.
-//
-//  - CheckEitherNonSmi rA, rD
-//
-//    If either FP[rA] or FP[rD] is not a Smi, then skip the next instruction.
-//
-//  - CheckClassId rA, D
-//
-//    If the class id in FP[rA] matches the class id D, then skip the
-//    following instruction.
-//
-//  - CheckClassIdRange rA, D
-//
-//    Next instruction is a Nop with S, the size of the class-id range.
-//    If the class id in FP[rA] is between the D D + S, then skip the
-//    following instruction.
-//
-//  - CheckBitTest rA, D
-//
-//    Skips the next 3 instructions if the object at FP[rA] is a valid class for
-//    a dense switch with low cid encoded in the following Nop instruction, and
-//    the cid mask encoded in the Nop instruction after that, or if D == 1 and
-//    FP[rA] is a Smi. Skips 2 instructions otherwise.
-//
-//  - CheckCids rA, rB, rC
-//
-//    Skips rC + 1 instructions if the object at FP[rA] is a Smi and
-//    rB == 1, or if FP[rA]'s cid is found in the array of cids encoded by the
-//    following rC Nop instructions. Otherwise skips only rC instructions.
-//
-//  - CheckCidsByRange rA, rB, rC
-//
-//    Skips rC + 1 instructions if the object at FP[rA] is a Smi and rB ==
-//    1, or if FP[rA]'s cid is found in the array of cid ranges encoded by the
-//    following rC Nop instructions. The cid ranges from a inclusive to b
-//    exclusive are coded in pairs of (a, b - a). Otherwise skips only 2
-//    instructions.
-//
-//  - CheckStack
-//
-//    Compare SP against isolate stack limit and call StackOverflow handler if
-//    necessary.
-//
-//  - CheckStackAlwaysExit
-//
-//    Unconditionally call StackOverflow handler.
-//
-//  - CheckFunctionTypeArgs A, D
-//
-//    Check for a passed-in type argument vector of length A and
-//    store it at FP[D].
-//
-//  - DebugStep, DebugBreak A
-//
-//    Debugger support. DebugBreak is bytecode that can be patched into the
-//    instruction stream to trigger in place breakpoint.
-//
-//    When patching instance or static call with DebugBreak we set A to
-//    match patched call's argument count so that Return instructions continue
-//    to work.
-//
-// TODO(vegorov) the way we replace calls with DebugBreak does not work
-//               with our smi fast paths because DebugBreak is simply skipped.
-//
-//  - LoadClassIdTOS, LoadClassId rA, D
-//
-//    LoadClassIdTOS loads the class id from the object at SP[0] and stores it
-//    to SP[0]. LoadClassId loads the class id from FP[rA] and stores it to
-//    FP[D].
-//
-//  - Deopt ArgC, D
-//
-//    If D != 0 then trigger eager deoptimization with deopt id (D - 1).
-//    If D == 0 then trigger lazy deoptimization.
-//
-//    The meaning of operand ArgC (encoded as A operand) matches that of an
-//    ArgC operand in call instructions. This is needed because we could
-//    potentially patch calls instructions with a lazy deopt and we need to
-//    ensure that any Return/ReturnTOS instructions
-//    returning from the patched calls will continue to function,
-//    e.g. in bytecode sequences like
-//
-//    InstanceCall ... <- lazy deopt inside first call
-//    InstanceCall ... <- patches second call with Deopt
-//
-//  - NullError
-//
-//    Throws a NullError.
-//
-// BYTECODE LIST FORMAT
-//
-// Bytecode list below is specified using the following format:
-//
-//     V(BytecodeName, OperandForm, Op1, Op2, Op3)
-//
-// - OperandForm specifies operand encoding and should be one of 0, A, T, A_D,
-//   A_X, X, D (see ENCODING section above).
-//
-// - Op1, Op2, Op2 specify operand meaning. Possible values:
-//
-//     ___ ignored / non-existent operand
-//     num immediate operand
-//     lit constant literal from object pool
-//     reg register (unsigned FP relative local)
-//     xeg x-register (signed FP relative local)
-//     tgt jump target relative to the PC of the current instruction
-//
-// TODO(vegorov) jump targets should be encoded relative to PC of the next
-//               instruction because PC is incremented immediately after fetch
-//               and before decoding.
-//
-#define BYTECODES_LIST(V)                                    \
-  V(Trap,                                  0, ___, ___, ___) \
-  V(Nop,                                 A_D, num, lit, ___) \
-  V(Compile,                               0, ___, ___, ___) \
-  V(HotCheck,                            A_D, num, num, ___) \
-  V(Intrinsic,                             A, num, ___, ___) \
-  V(Drop1,                                 0, ___, ___, ___) \
-  V(DropR,                                 A, num, ___, ___) \
-  V(Drop,                                  A, num, ___, ___) \
-  V(Jump,                                  T, tgt, ___, ___) \
-  V(Return,                                A, reg, ___, ___) \
-  V(ReturnTOS,                             0, ___, ___, ___) \
-  V(Move,                                A_X, reg, xeg, ___) \
-  V(Swap,                                A_X, reg, xeg, ___) \
-  V(Push,                                  X, xeg, ___, ___) \
-  V(LoadConstant,                        A_D, reg, lit, ___) \
-  V(LoadClassId,                         A_D, reg, reg, ___) \
-  V(LoadClassIdTOS,                        0, ___, ___, ___) \
-  V(PushConstant,                          D, lit, ___, ___) \
-  V(StoreLocal,                            X, xeg, ___, ___) \
-  V(PopLocal,                              X, xeg, ___, ___) \
-  V(IndirectStaticCall,                  A_D, num, num, ___) \
-  V(StaticCall,                          A_D, num, num, ___) \
-  V(InstanceCall1,                       A_D, num, num, ___) \
-  V(InstanceCall2,                       A_D, num, num, ___) \
-  V(InstanceCall1Opt,                    A_D, num, num, ___) \
-  V(InstanceCall2Opt,                    A_D, num, num, ___) \
-  V(PushPolymorphicInstanceCall,         A_D, num, num, ___) \
-  V(PushPolymorphicInstanceCallByRange,  A_D, num, num, ___) \
-  V(NativeCall,                        A_B_C, num, num, num) \
-  V(FfiCall,                               D, lit, ___, ___) \
-  V(OneByteStringFromCharCode,           A_X, reg, xeg, ___) \
-  V(StringToCharCode,                    A_X, reg, xeg, ___) \
-  V(AddTOS,                                0, ___, ___, ___) \
-  V(SubTOS,                                0, ___, ___, ___) \
-  V(MulTOS,                                0, ___, ___, ___) \
-  V(BitOrTOS,                              0, ___, ___, ___) \
-  V(BitAndTOS,                             0, ___, ___, ___) \
-  V(EqualTOS,                              0, ___, ___, ___) \
-  V(LessThanTOS,                           0, ___, ___, ___) \
-  V(GreaterThanTOS,                        0, ___, ___, ___) \
-  V(SmiAddTOS,                             0, ___, ___, ___) \
-  V(SmiSubTOS,                             0, ___, ___, ___) \
-  V(SmiMulTOS,                             0, ___, ___, ___) \
-  V(SmiBitAndTOS,                          0, ___, ___, ___) \
-  V(Add,                               A_B_C, reg, reg, reg) \
-  V(Sub,                               A_B_C, reg, reg, reg) \
-  V(Mul,                               A_B_C, reg, reg, reg) \
-  V(Div,                               A_B_C, reg, reg, reg) \
-  V(Mod,                               A_B_C, reg, reg, reg) \
-  V(Shl,                               A_B_C, reg, reg, reg) \
-  V(Shr,                               A_B_C, reg, reg, reg) \
-  V(ShlImm,                            A_B_C, reg, reg, num) \
-  V(Neg,                                 A_D, reg, reg, ___) \
-  V(BitOr,                             A_B_C, reg, reg, reg) \
-  V(BitAnd,                            A_B_C, reg, reg, reg) \
-  V(BitXor,                            A_B_C, reg, reg, reg) \
-  V(BitNot,                              A_D, reg, reg, ___) \
-  V(Min,                               A_B_C, reg, reg, reg) \
-  V(Max,                               A_B_C, reg, reg, reg) \
-  V(WriteIntoDouble,                     A_D, reg, reg, ___) \
-  V(WriteIntoMint,                       A_D, reg, reg, ___) \
-  V(UnboxDouble,                         A_D, reg, reg, ___) \
-  V(CheckedUnboxDouble,                  A_D, reg, reg, ___) \
-  V(UnboxInt32,                        A_B_C, reg, reg, num) \
-  V(BoxInt32,                            A_D, reg, reg, ___) \
-  V(BoxUint32,                           A_D, reg, reg, ___) \
-  V(UnboxInt64,                          A_D, reg, reg, ___) \
-  V(BoxInt64,                            A_D, reg, reg, ___) \
-  V(UnboxedWidthExtender,              A_B_C, reg, reg, num) \
-  V(SmiToDouble,                         A_D, reg, reg, ___) \
-  V(DoubleToSmi,                         A_D, reg, reg, ___) \
-  V(DAdd,                              A_B_C, reg, reg, reg) \
-  V(DSub,                              A_B_C, reg, reg, reg) \
-  V(DMul,                              A_B_C, reg, reg, reg) \
-  V(DDiv,                              A_B_C, reg, reg, reg) \
-  V(DNeg,                                A_D, reg, reg, ___) \
-  V(DSqrt,                               A_D, reg, reg, ___) \
-  V(DMin,                              A_B_C, reg, reg, reg) \
-  V(DMax,                              A_B_C, reg, reg, reg) \
-  V(DCos,                                A_D, reg, reg, ___) \
-  V(DSin,                                A_D, reg, reg, ___) \
-  V(DPow,                              A_B_C, reg, reg, reg) \
-  V(DMod,                              A_B_C, reg, reg, reg) \
-  V(DTruncate,                           A_D, reg, reg, ___) \
-  V(DFloor,                              A_D, reg, reg, ___) \
-  V(DCeil,                               A_D, reg, reg, ___) \
-  V(DoubleToFloat,                       A_D, reg, reg, ___) \
-  V(FloatToDouble,                       A_D, reg, reg, ___) \
-  V(DoubleIsNaN,                           A, reg, ___, ___) \
-  V(DoubleIsInfinite,                      A, reg, ___, ___) \
-  V(StoreStaticTOS,                        D, lit, ___, ___) \
-  V(PushStatic,                            D, lit, ___, ___) \
-  V(InitStaticTOS,                         0, ___, ___, ___) \
-  V(IfNeStrictTOS,                         0, ___, ___, ___) \
-  V(IfEqStrictTOS,                         0, ___, ___, ___) \
-  V(IfNeStrictNumTOS,                      0, ___, ___, ___) \
-  V(IfEqStrictNumTOS,                      0, ___, ___, ___) \
-  V(IfSmiLtTOS,                            0, ___, ___, ___) \
-  V(IfSmiLeTOS,                            0, ___, ___, ___) \
-  V(IfSmiGeTOS,                            0, ___, ___, ___) \
-  V(IfSmiGtTOS,                            0, ___, ___, ___) \
-  V(IfNeStrict,                          A_D, reg, reg, ___) \
-  V(IfEqStrict,                          A_D, reg, reg, ___) \
-  V(IfLe,                                A_D, reg, reg, ___) \
-  V(IfLt,                                A_D, reg, reg, ___) \
-  V(IfGe,                                A_D, reg, reg, ___) \
-  V(IfGt,                                A_D, reg, reg, ___) \
-  V(IfULe,                               A_D, reg, reg, ___) \
-  V(IfULt,                               A_D, reg, reg, ___) \
-  V(IfUGe,                               A_D, reg, reg, ___) \
-  V(IfUGt,                               A_D, reg, reg, ___) \
-  V(IfDNe,                               A_D, reg, reg, ___) \
-  V(IfDEq,                               A_D, reg, reg, ___) \
-  V(IfDLe,                               A_D, reg, reg, ___) \
-  V(IfDLt,                               A_D, reg, reg, ___) \
-  V(IfDGe,                               A_D, reg, reg, ___) \
-  V(IfDGt,                               A_D, reg, reg, ___) \
-  V(IfNeStrictNum,                       A_D, reg, reg, ___) \
-  V(IfEqStrictNum,                       A_D, reg, reg, ___) \
-  V(IfEqNull,                              A, reg, ___, ___) \
-  V(IfNeNull,                              A, reg, ___, ___) \
-  V(IfEqNullTOS,                           0, ___, ___, ___) \
-  V(IfNeNullTOS,                           0, ___, ___, ___) \
-  V(CreateArrayTOS,                        0, ___, ___, ___) \
-  V(CreateArrayOpt,                    A_B_C, reg, reg, reg) \
-  V(Allocate,                              D, lit, ___, ___) \
-  V(AllocateT,                             0, ___, ___, ___) \
-  V(AllocateOpt,                         A_D, reg, lit, ___) \
-  V(AllocateTOpt,                        A_D, reg, lit, ___) \
-  V(StoreIndexedTOS,                       0, ___, ___, ___) \
-  V(StoreIndexed,                      A_B_C, reg, reg, reg) \
-  V(StoreIndexedOneByteString,         A_B_C, reg, reg, reg) \
-  V(StoreIndexedUint8,                 A_B_C, reg, reg, reg) \
-  V(StoreIndexedUint32,                A_B_C, reg, reg, reg) \
-  V(StoreIndexedFloat32,               A_B_C, reg, reg, reg) \
-  V(StoreIndexed4Float32,              A_B_C, reg, reg, reg) \
-  V(StoreIndexedFloat64,               A_B_C, reg, reg, reg) \
-  V(StoreIndexed8Float64,              A_B_C, reg, reg, reg) \
-  V(StoreIndexedUntaggedUint8,         A_B_C, reg, reg, reg) \
-  V(StoreIndexedUntaggedUint32,        A_B_C, reg, reg, reg) \
-  V(StoreIndexedUntaggedFloat32,       A_B_C, reg, reg, reg) \
-  V(StoreIndexedUntaggedFloat64,       A_B_C, reg, reg, reg) \
-  V(NoSuchMethod,                          0, ___, ___, ___) \
-  V(TailCall,                              0, ___, ___, ___) \
-  V(TailCallOpt,                         A_D, reg, reg, ___) \
-  V(LoadArgDescriptor,                     0, ___, ___, ___) \
-  V(LoadArgDescriptorOpt,                  A, reg, ___, ___) \
-  V(LoadFpRelativeSlot,                    X, reg, ___, ___) \
-  V(LoadFpRelativeSlotOpt,             A_B_Y, reg, reg, reg) \
-  V(StoreFpRelativeSlot,                   X, reg, ___, ___) \
-  V(StoreFpRelativeSlotOpt,            A_B_Y, reg, reg, reg) \
-  V(LoadIndexedTOS,                        0, ___, ___, ___) \
-  V(LoadIndexed,                       A_B_C, reg, reg, reg) \
-  V(LoadIndexedOneByteString,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedTwoByteString,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedUint8,                  A_B_C, reg, reg, reg) \
-  V(LoadIndexedInt8,                   A_B_C, reg, reg, reg) \
-  V(LoadIndexedInt32,                  A_B_C, reg, reg, reg) \
-  V(LoadIndexedUint32,                 A_B_C, reg, reg, reg) \
-  V(LoadIndexedFloat32,                A_B_C, reg, reg, reg) \
-  V(LoadIndexed4Float32,               A_B_C, reg, reg, reg) \
-  V(LoadIndexedFloat64,                A_B_C, reg, reg, reg) \
-  V(LoadIndexed8Float64,               A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedInt8,           A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedUint8,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedInt32,          A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedUint32,         A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedFloat32,        A_B_C, reg, reg, reg) \
-  V(LoadIndexedUntaggedFloat64,        A_B_C, reg, reg, reg) \
-  V(StoreField,                        A_B_C, reg, num, reg) \
-  V(StoreFieldExt,                       A_D, reg, reg, ___) \
-  V(StoreUntagged,                     A_B_C, reg, num, reg) \
-  V(StoreFieldTOS,                         D, num, ___, ___) \
-  V(LoadField,                         A_B_C, reg, reg, num) \
-  V(LoadFieldExt,                        A_D, reg, reg, ___) \
-  V(LoadUntagged,                      A_B_C, reg, reg, num) \
-  V(LoadFieldTOS,                          D, num, ___, ___) \
-  V(BooleanNegateTOS,                      0, ___, ___, ___) \
-  V(BooleanNegate,                       A_D, reg, reg, ___) \
-  V(Throw,                                 A, num, ___, ___) \
-  V(Entry,                                 D, num, ___, ___) \
-  V(EntryOptimized,                      A_D, num, num, ___) \
-  V(Frame,                                 D, num, ___, ___) \
-  V(SetFrame,                              A, num, ___, ___) \
-  V(AllocateContext,                       D, num, ___, ___) \
-  V(AllocateUninitializedContext,        A_D, reg, num, ___) \
-  V(CloneContext,                          0, ___, ___, ___) \
-  V(MoveSpecial,                         A_D, reg, num, ___) \
-  V(InstantiateType,                       D, lit, ___, ___) \
-  V(InstantiateTypeArgumentsTOS,         A_D, num, lit, ___) \
-  V(InstanceOf,                            0, ___, ___, ___) \
-  V(BadTypeError,                          0, ___, ___, ___) \
-  V(AssertAssignable,                    A_D, num, lit, ___) \
-  V(AssertSubtype,                         0, ___, ___, ___) \
-  V(AssertBoolean,                         A, num, ___, ___) \
-  V(TestSmi,                             A_D, reg, reg, ___) \
-  V(TestCids,                            A_D, reg, num, ___) \
-  V(CheckSmi,                              A, reg, ___, ___) \
-  V(CheckEitherNonSmi,                   A_D, reg, reg, ___) \
-  V(CheckClassId,                        A_D, reg, num, ___) \
-  V(CheckClassIdRange,                   A_D, reg, num, ___) \
-  V(CheckBitTest,                        A_D, reg, num, ___) \
-  V(CheckCids,                         A_B_C, reg, num, num) \
-  V(CheckCidsByRange,                  A_B_C, reg, num, num) \
-  V(CheckStack,                            0, ___, ___, ___) \
-  V(CheckStackAlwaysExit,                  0, ___, ___, ___) \
-  V(CheckFunctionTypeArgs,               A_D, num, num, ___) \
-  V(DebugStep,                             0, ___, ___, ___) \
-  V(DebugBreak,                            A, num, ___, ___) \
-  V(Deopt,                               A_D, num, num, ___) \
-  V(DeoptRewind,                           0, ___, ___, ___) \
-  V(NullError,                             0, ___, ___, ___)
-
-// clang-format on
-
-typedef uint32_t Instr;
-
-class SimulatorBytecode {
- public:
-  enum Opcode {
-#define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name,
-    BYTECODES_LIST(DECLARE_BYTECODE)
-#undef DECLARE_BYTECODE
-  };
-
-  static const char* NameOf(Instr instr) {
-    const char* names[] = {
-#define NAME(name, encoding, op1, op2, op3) #name,
-        BYTECODES_LIST(NAME)
-#undef NAME
-    };
-    return names[DecodeOpcode(instr)];
-  }
-
-  static const intptr_t kOpShift = 0;
-  static const intptr_t kAShift = 8;
-  static const intptr_t kAMask = 0xFF;
-  static const intptr_t kBShift = 16;
-  static const intptr_t kBMask = 0xFF;
-  static const intptr_t kCShift = 24;
-  static const intptr_t kCMask = 0xFF;
-  static const intptr_t kDShift = 16;
-  static const intptr_t kDMask = 0xFFFF;
-  static const intptr_t kYShift = 24;
-  static const intptr_t kYMask = 0xFF;
-
-  static Instr Encode(Opcode op, uintptr_t a, uintptr_t b, uintptr_t c) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((b & kBMask) == b);
-    ASSERT((c & kCMask) == c);
-    return op | (a << kAShift) | (b << kBShift) | (c << kCShift);
-  }
-
-  static Instr Encode(Opcode op, uintptr_t a, uintptr_t d) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((d & kDMask) == d);
-    return op | (a << kAShift) | (d << kDShift);
-  }
-
-  static Instr EncodeSigned(Opcode op, uintptr_t a, intptr_t x) {
-    ASSERT((a & kAMask) == a);
-    ASSERT((x << kDShift) >> kDShift == x);
-    return op | (a << kAShift) | (x << kDShift);
-  }
-
-  static Instr EncodeSigned(Opcode op, intptr_t x) {
-    ASSERT((x << kAShift) >> kAShift == x);
-    return op | (x << kAShift);
-  }
-
-  static Instr Encode(Opcode op) { return op; }
-
-  DART_FORCE_INLINE static uint8_t DecodeA(Instr bc) {
-    return (bc >> kAShift) & kAMask;
-  }
-
-  DART_FORCE_INLINE static uint8_t DecodeB(Instr bc) {
-    return (bc >> kBShift) & kBMask;
-  }
-
-  DART_FORCE_INLINE static uint16_t DecodeD(Instr bc) {
-    return (bc >> kDShift) & kDMask;
-  }
-
-  DART_FORCE_INLINE static Opcode DecodeOpcode(Instr bc) {
-    return static_cast<Opcode>(bc & 0xFF);
-  }
-
-  DART_FORCE_INLINE static bool IsTrap(Instr instr) {
-    return DecodeOpcode(instr) == SimulatorBytecode::kTrap;
-  }
-
-  DART_FORCE_INLINE static bool IsCallOpcode(Instr instr) {
-    switch (DecodeOpcode(instr)) {
-      case SimulatorBytecode::kStaticCall:
-      case SimulatorBytecode::kIndirectStaticCall:
-      case SimulatorBytecode::kInstanceCall1:
-      case SimulatorBytecode::kInstanceCall2:
-      case SimulatorBytecode::kInstanceCall1Opt:
-      case SimulatorBytecode::kInstanceCall2Opt:
-      case SimulatorBytecode::kDebugBreak:
-        return true;
-
-      default:
-        return false;
-    }
-  }
-
-  DART_FORCE_INLINE static bool IsFastSmiOpcode(Instr instr) {
-    switch (DecodeOpcode(instr)) {
-      case SimulatorBytecode::kAddTOS:
-      case SimulatorBytecode::kSubTOS:
-      case SimulatorBytecode::kMulTOS:
-      case SimulatorBytecode::kBitOrTOS:
-      case SimulatorBytecode::kBitAndTOS:
-      case SimulatorBytecode::kEqualTOS:
-      case SimulatorBytecode::kLessThanTOS:
-      case SimulatorBytecode::kGreaterThanTOS:
-        return true;
-
-      default:
-        return false;
-    }
-  }
-
-  DART_FORCE_INLINE static uint8_t DecodeArgc(Instr call) {
-    ASSERT(IsCallOpcode(call));
-    return (call >> 8) & 0xFF;
-  }
-
-  static Instr At(uword pc) { return *reinterpret_cast<Instr*>(pc); }
-
- private:
-  DISALLOW_ALLOCATION();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(SimulatorBytecode);
-};
-
-// Various dummy declarations to make shared code compile.
-// TODO(vegorov) we need to prune away as much dead code as possible instead
-// of just making it compile.
-typedef int16_t Register;
-
-const int16_t FPREG = 0;
-const int16_t SPREG = 1;
-#if defined(ARCH_IS_64_BIT)
-const intptr_t kNumberOfCpuRegisters = 64;
-#else
-const intptr_t kNumberOfCpuRegisters = 32;
-#endif
-const intptr_t kDartAvailableCpuRegs = -1;
-const intptr_t kNoRegister = -1;
-const intptr_t kReservedCpuRegisters = 0;
-const intptr_t ARGS_DESC_REG = 0;
-const intptr_t CODE_REG = 0;
-const intptr_t kExceptionObjectReg = 0;
-const intptr_t kStackTraceObjectReg = 0;
-
-// The maximum number of fixed registers that are used by some
-// DBC instructions. The register allocator must avoid clashing
-// with these when assigning registers to catch parameters.
-const intptr_t kMaxNumberOfFixedInputRegistersUsedByIL = 3;
-
-enum FpuRegister {
-  kNoFpuRegister = -1,
-  kFakeFpuRegister,
-  kNumberOfDummyFpuRegisters,
-};
-const FpuRegister FpuTMP = kFakeFpuRegister;
-const intptr_t kNumberOfFpuRegisters = 1;
-
-extern const char* cpu_reg_names[kNumberOfCpuRegisters];
-extern const char* fpu_reg_names[kNumberOfFpuRegisters];
-
-// After a comparison, the condition NEXT_IS_TRUE means the following
-// instruction is executed if the comparison is true and skipped over overwise.
-// Condition NEXT_IS_FALSE means the following instruction is executed if the
-// comparison is false and skipped over otherwise.
-enum Condition { NEXT_IS_TRUE, NEXT_IS_FALSE, INVALID_CONDITION };
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_CONSTANTS_DBC_H_
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index ff0d8b4..a6f9de5 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -32,7 +32,7 @@
 //   PP - object pool for the currently execution function
 //
 // Frame info stored below FP additionally contains pointers to the currently
-// executing function and code (see stack_frame_dbc.h for more information).
+// executing function and code.
 //
 // In the unoptimized code most of bytecodes take operands implicitly from
 // stack and store results again on the stack. Constant operands are usually
@@ -625,8 +625,8 @@
   V(StoreFieldTOS_Wide,                    D, WIDE, lit, ___, ___)             \
   V(StoreIndexedTOS,                       0, ORDN, ___, ___, ___)             \
   V(Unused20,                              0, RESV, ___, ___, ___)             \
-  V(PushStatic,                            D, ORDN, lit, ___, ___)             \
-  V(PushStatic_Wide,                       D, WIDE, lit, ___, ___)             \
+  V(Unused40,                              0, RESV, ___, ___, ___)             \
+  V(Unused41,                              0, RESV, ___, ___, ___)             \
   V(StoreStaticTOS,                        D, ORDN, lit, ___, ___)             \
   V(StoreStaticTOS_Wide,                   D, WIDE, lit, ___, ___)             \
   V(Jump,                                  T, ORDN, tgt, ___, ___)             \
@@ -689,8 +689,8 @@
   V(MoveSpecial_Wide,                    A_Y, WIDE, num, xeg, ___)             \
   V(BooleanNegateTOS,                      0, ORDN, ___, ___, ___)             \
   V(EqualsNull,                            0, ORDN, ___, ___, ___)             \
-  V(CheckReceiverForNull,                  D, ORDN, lit, ___, ___)             \
-  V(CheckReceiverForNull_Wide,             D, WIDE, lit, ___, ___)             \
+  V(NullCheck,                             D, ORDN, lit, ___, ___)             \
+  V(NullCheck_Wide,                        D, WIDE, lit, ___, ___)             \
   V(NegateInt,                             0, ORDN, ___, ___, ___)             \
   V(AddInt,                                0, ORDN, ___, ___, ___)             \
   V(SubInt,                                0, ORDN, ___, ___, ___)             \
@@ -745,11 +745,11 @@
   // Magic value of bytecode files.
   static const intptr_t kMagicValue = 0x44424332;  // 'DBC2'
   // Minimum bytecode format version supported by VM.
-  static const intptr_t kMinSupportedBytecodeFormatVersion = 10;
+  static const intptr_t kMinSupportedBytecodeFormatVersion = 20;
   // Maximum bytecode format version supported by VM.
   // The range of supported versions should include version produced by bytecode
   // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
-  static const intptr_t kMaxSupportedBytecodeFormatVersion = 23;
+  static const intptr_t kMaxSupportedBytecodeFormatVersion = 25;
 
   enum Opcode {
 #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
diff --git a/runtime/vm/cpu.h b/runtime/vm/cpu.h
index e75e1a1..2713cab 100644
--- a/runtime/vm/cpu.h
+++ b/runtime/vm/cpu.h
@@ -30,8 +30,6 @@
 #include "vm/cpu_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/cpu_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/cpu_dbc.h"
 #else
 #error Unknown architecture.
 #endif
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index b07435e..c3d91d4 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -25,7 +25,7 @@
 #endif
 
 // ARM version differences.
-// We support three major 32-bit ARM ISA versions: ARMv5TE, ARMv6 and variants,
+// We support two major 32-bit ARM ISA versions: ARMv6 and variants,
 // and ARMv7 and variants. For each of these we detect the presence of vfp,
 // neon, and integer division instructions. Considering ARMv5TE as the baseline,
 // later versions add the following features/instructions that we use:
@@ -42,7 +42,7 @@
 //
 // If an aarch64 CPU is detected, we generate ARMv7 code.
 //
-// If an instruction is missing on ARMv5TE or ARMv6, we emulate it, if possible.
+// If an instruction is missing on ARMv6, we emulate it, if possible.
 // Where we are missing vfp, we do not unbox doubles, or generate intrinsics for
 // floating point operations. Where we are missing neon, we do not unbox SIMD
 // values, or inline operations on SIMD values. Where we are missing integer
@@ -52,24 +52,13 @@
 //
 // Alignment:
 //
-// Before ARMv6, that is only for ARMv5TE, unaligned accesses will cause a
-// crash. This includes the ldrd and strd instructions, which must use addresses
-// that are 8-byte aligned. Since we don't always guarantee that for our uses
-// of ldrd and strd, these instructions are emulated with two load or store
-// instructions on ARMv5TE. On ARMv6 and on, we assume that the kernel is
-// set up to fixup unaligned accesses. This can be verified by checking
-// /proc/cpu/alignment on modern Linux systems.
+// On ARMv6 and on, we assume that the kernel is set up to fixup unaligned
+// accesses. This can be verified by checking /proc/cpu/alignment on modern
+// Linux systems.
 
 namespace dart {
 
-#if defined(TARGET_ARCH_ARM_5TE)
-DEFINE_FLAG(bool, use_vfp, false, "Use vfp instructions if supported");
-DEFINE_FLAG(bool, use_neon, false, "Use neon instructions if supported");
-DEFINE_FLAG(bool,
-            use_integer_division,
-            false,
-            "Use integer division instruction if supported");
-#elif defined(TARGET_ARCH_ARM_6)
+#if defined(TARGET_ARCH_ARM_6)
 DEFINE_FLAG(bool, use_vfp, true, "Use vfp instructions if supported");
 DEFINE_FLAG(bool, use_neon, false, "Use neon instructions if supported");
 DEFINE_FLAG(bool,
@@ -86,8 +75,7 @@
 #endif
 
 #if defined(TARGET_HOST_MISMATCH)
-#if defined(TARGET_ARCH_ARM_5TE) || defined(TARGET_OS_ANDROID) \
-    || defined(TARGET_OS_IOS)
+#if defined(TARGET_OS_ANDROID) || defined(TARGET_OS_IOS)
 DEFINE_FLAG(bool, sim_use_hardfp, false, "Use the hardfp ABI.");
 #else
 DEFINE_FLAG(bool, sim_use_hardfp, true, "Use the hardfp ABI.");
@@ -170,7 +158,7 @@
   CpuInfo::Init();
   hardware_ = CpuInfo::GetCpuModel();
 
-  // Check for ARMv5TE, ARMv6, ARMv7, or aarch64.
+  // Check for ARMv6, ARMv7, or aarch64.
   // It can be in either the Processor or Model information fields.
   if (CpuInfo::FieldContains(kCpuInfoProcessor, "aarch64") ||
       CpuInfo::FieldContains(kCpuInfoModel, "aarch64") ||
@@ -179,28 +167,15 @@
     // pretend that this arm64 cpu is really an ARMv7
     arm_version_ = ARMv7;
     is_arm64 = true;
-  } else if (CpuInfo::FieldContains(kCpuInfoProcessor, "ARM926EJ-S") ||
-             CpuInfo::FieldContains(kCpuInfoModel, "ARM926EJ-S")) {
-    // Lego Mindstorm EV3.
-    arm_version_ = ARMv5TE;
-    // On ARMv5, the PC read offset in an STR or STM instruction is either 8 or
-    // 12 bytes depending on the implementation. On the Mindstorm EV3 it is 12
-    // bytes.
-    store_pc_read_offset_ = 12;
-  } else if (CpuInfo::FieldContains(kCpuInfoProcessor, "Feroceon 88FR131") ||
-             CpuInfo::FieldContains(kCpuInfoModel, "Feroceon 88FR131")) {
-    // This is for the DGBox. For the time-being, assume it is similar to the
-    // Lego Mindstorm.
-    arm_version_ = ARMv5TE;
-    store_pc_read_offset_ = 12;
   } else if (CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv6") ||
              CpuInfo::FieldContains(kCpuInfoModel, "ARMv6")) {
     // Raspberry Pi, etc.
     arm_version_ = ARMv6;
-  } else {
-    ASSERT(CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv7") ||
-           CpuInfo::FieldContains(kCpuInfoModel, "ARMv7"));
+  } else if (CpuInfo::FieldContains(kCpuInfoProcessor, "ARMv7") ||
+             CpuInfo::FieldContains(kCpuInfoModel, "ARMv7")) {
     arm_version_ = ARMv7;
+  } else {
+    FATAL("Unsupported ARM CPU architecture.");
   }
 
   // Has floating point unit.
@@ -273,9 +248,7 @@
   CpuInfo::Init();
   hardware_ = CpuInfo::GetCpuModel();
 
-#if defined(TARGET_ARCH_ARM_5TE)
-  arm_version_ = ARMv5TE;
-#elif defined(TARGET_ARCH_ARM_6)
+#if defined(TARGET_ARCH_ARM_6)
   arm_version_ = ARMv6;
 #else
   arm_version_ = ARMv7;
diff --git a/runtime/vm/cpu_arm.h b/runtime/vm/cpu_arm.h
index 6f5b774..18d55fc 100644
--- a/runtime/vm/cpu_arm.h
+++ b/runtime/vm/cpu_arm.h
@@ -23,7 +23,6 @@
 // they may be altered for testing.
 
 enum ARMVersion {
-  ARMv5TE,
   ARMv6,
   ARMv7,
   ARMvUnknown,
diff --git a/runtime/vm/cpu_dbc.cc b/runtime/vm/cpu_dbc.cc
deleted file mode 100644
index c6e9c6a..0000000
--- a/runtime/vm/cpu_dbc.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/cpu.h"
-#include "vm/cpu_dbc.h"
-
-#include "vm/cpuinfo.h"
-
-namespace dart {
-
-void CPU::FlushICache(uword start, uword size) {
-  // Nothing to do.
-}
-
-const char* CPU::Id() {
-  return "dbc";
-}
-
-const char* HostCPUFeatures::hardware_ = NULL;
-#if defined(DEBUG)
-bool HostCPUFeatures::initialized_ = false;
-#endif
-
-void HostCPUFeatures::Init() {
-  CpuInfo::Init();
-  hardware_ = CpuInfo::GetCpuModel();
-#if defined(DEBUG)
-  initialized_ = true;
-#endif
-}
-
-void HostCPUFeatures::Cleanup() {
-  DEBUG_ASSERT(initialized_);
-#if defined(DEBUG)
-  initialized_ = false;
-#endif
-  ASSERT(hardware_ != NULL);
-  free(const_cast<char*>(hardware_));
-  hardware_ = NULL;
-  CpuInfo::Cleanup();
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/cpu_dbc.h b/runtime/vm/cpu_dbc.h
deleted file mode 100644
index 5e0064b..0000000
--- a/runtime/vm/cpu_dbc.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_CPU_DBC_H_
-#define RUNTIME_VM_CPU_DBC_H_
-
-#if !defined(RUNTIME_VM_CPU_H_)
-#error Do not include cpu_dbc.h directly; use cpu.h instead.
-#endif
-
-#include "vm/allocation.h"
-#include "vm/simulator.h"
-
-namespace dart {
-
-class HostCPUFeatures : public AllStatic {
- public:
-  static void Init();
-  static void Cleanup();
-
-  static const char* hardware() {
-    DEBUG_ASSERT(initialized_);
-    return hardware_;
-  }
-
- private:
-  static const char* hardware_;
-#if defined(DEBUG)
-  static bool initialized_;
-#endif
-};
-
-class TargetCPUFeatures : public AllStatic {
- public:
-  static void Init() { HostCPUFeatures::Init(); }
-  static void Cleanup() { HostCPUFeatures::Cleanup(); }
-
-  static const char* hardware() { return CPU::Id(); }
-
-  static bool double_truncate_round_supported() { return true; }
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_CPU_DBC_H_
diff --git a/runtime/vm/cpu_test.cc b/runtime/vm/cpu_test.cc
index 35c44f4..d902713 100644
--- a/runtime/vm/cpu_test.cc
+++ b/runtime/vm/cpu_test.cc
@@ -26,8 +26,6 @@
 #else   // defined(HOST_ARCH_ARM64)
   EXPECT_STREQ("simarm64", CPU::Id());
 #endif  // defined(HOST_ARCH_ARM64)
-#elif defined(TARGET_ARCH_DBC)
-  EXPECT_STREQ("dbc", CPU::Id());
 #else
 #error Architecture was not detected as supported by Dart.
 #endif
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 35e6f8d..05fb029 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -177,26 +177,6 @@
     }
   }
 
-#if defined(DEBUG)
-  // Turn on verify_gc_contains if any of the other GC verification flag
-  // is turned on.
-  if (FLAG_verify_before_gc || FLAG_verify_after_gc ||
-      FLAG_verify_on_transition) {
-    FLAG_verify_gc_contains = true;
-  }
-#endif
-
-#if defined(TARGET_ARCH_DBC)
-  // DBC instructions are never executable.
-  FLAG_write_protect_code = false;
-#endif
-
-  if (FLAG_enable_interpreter) {
-#if defined(TARGET_ARCH_DBC)
-    return strdup("--enable-interpreter is not supported with DBC");
-#endif  // defined(TARGET_ARCH_DBC)
-  }
-
   FrameLayout::Init();
 
   set_thread_exit_callback(thread_exit);
@@ -216,6 +196,7 @@
   TimelineDurationScope tds(Timeline::GetVMStream(), "Dart::Init");
 #endif
   Isolate::InitVM();
+  IsolateGroup::Init();
   PortMap::Init();
   FreeListElement::Init();
   ForwardingCorpse::Init();
@@ -248,10 +229,10 @@
     // We make a fake [IsolateGroupSource] here, since the "vm-isolate" is not
     // really an isolate itself - it acts more as a container for VM-global
     // objects.
-    std::unique_ptr<IsolateGroupSource> source(
-        new IsolateGroupSource(nullptr, "vm-isolate", nullptr, nullptr, nullptr,
-                               nullptr, nullptr, -1, api_flags));
+    std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
+        nullptr, "vm-isolate", nullptr, nullptr, nullptr, -1, api_flags));
     auto group = new IsolateGroup(std::move(source), /*embedder_data=*/nullptr);
+    IsolateGroup::RegisterIsolateGroup(group);
     vm_isolate_ =
         Isolate::InitIsolate("vm-isolate", group, api_flags, is_vm_isolate);
     group->set_initial_spawn_successful();
@@ -306,7 +287,7 @@
       } else {
         return strdup("Invalid vm isolate snapshot seen");
       }
-      FullSnapshotReader reader(snapshot, instructions_snapshot, NULL, NULL, T);
+      FullSnapshotReader reader(snapshot, instructions_snapshot, T);
       const Error& error = Error::Handle(reader.ReadVMSnapshot());
       if (!error.IsNull()) {
         // Must copy before leaving the zone.
@@ -399,7 +380,7 @@
 
 #ifndef DART_PRECOMPILED_RUNTIME
   if (start_kernel_isolate) {
-    KernelIsolate::Run();
+    KernelIsolate::InitializeState();
   }
 #endif  // DART_PRECOMPILED_RUNTIME
 
@@ -581,6 +562,7 @@
   vm_isolate_ = NULL;
   ASSERT(Isolate::IsolateListLength() == 0);
   PortMap::Cleanup();
+  IsolateGroup::Cleanup();
   ICData::Cleanup();
   SubtypeTestCache::Cleanup();
   ArgumentsDescriptor::Cleanup();
@@ -646,8 +628,6 @@
 
 RawError* Dart::InitializeIsolate(const uint8_t* snapshot_data,
                                   const uint8_t* snapshot_instructions,
-                                  const uint8_t* shared_data,
-                                  const uint8_t* shared_instructions,
                                   const uint8_t* kernel_buffer,
                                   intptr_t kernel_buffer_size,
                                   void* isolate_data) {
@@ -692,8 +672,7 @@
     if (FLAG_trace_isolates) {
       OS::PrintErr("Size of isolate snapshot = %" Pd "\n", snapshot->length());
     }
-    FullSnapshotReader reader(snapshot, snapshot_instructions, shared_data,
-                              shared_instructions, T);
+    FullSnapshotReader reader(snapshot, snapshot_instructions, T);
     const Error& error = Error::Handle(reader.ReadIsolateSnapshot());
     if (!error.IsNull()) {
       return error.raw();
@@ -777,7 +756,7 @@
   if (I->object_store()->megamorphic_miss_code() == Code::null()) {
     MegamorphicCacheTable::InitMissHandler(I);
   }
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
   if (I != Dart::vm_isolate()) {
     I->object_store()->set_build_method_extractor_code(
         Code::Handle(StubCode::GetBuildMethodExtractorStub(nullptr)));
@@ -868,9 +847,6 @@
     buffer.AddString(FLAG_causal_async_stacks ? " causal_async_stacks"
                                               : " no-causal_async_stacks");
 
-    buffer.AddString((FLAG_enable_interpreter || FLAG_use_bytecode_compiler)
-                         ? " bytecode"
-                         : " no-bytecode");
 
 // Generated code must match the host architecture and ABI.
 #if defined(TARGET_ARCH_ARM)
@@ -897,14 +873,6 @@
     buffer.AddString(" x64-sysv");
 #endif
 
-#elif defined(TARGET_ARCH_DBC)
-#if defined(ARCH_IS_32_BIT)
-    buffer.AddString(" dbc32");
-#elif defined(ARCH_IS_64_BIT)
-    buffer.AddString(" dbc64");
-#else
-#error What word size?
-#endif
 #else
 #error What architecture?
 #endif
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 8c11967..3fd9376 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -57,8 +57,6 @@
   // from_kernel.  Otherwise, initialize from sources.
   static RawError* InitializeIsolate(const uint8_t* snapshot_data,
                                      const uint8_t* snapshot_instructions,
-                                     const uint8_t* shared_data,
-                                     const uint8_t* shared_instructions,
                                      const uint8_t* kernel_buffer,
                                      intptr_t kernel_buffer_size,
                                      void* data);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7636aa3..d66238a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1060,7 +1060,7 @@
 #if !defined(PRODUCT)
 #define VM_METRIC_API(type, variable, name, unit)                              \
   DART_EXPORT int64_t Dart_VM##variable##Metric() {                            \
-    return vm_metric_##variable.value();                                       \
+    return vm_metric_##variable.Value();                                       \
   }
 VM_METRIC_LIST(VM_METRIC_API);
 #undef VM_METRIC_API
@@ -1071,7 +1071,7 @@
       FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);   \
     }                                                                          \
     Isolate* iso = reinterpret_cast<Isolate*>(isolate);                        \
-    return iso->Get##variable##Metric()->value();                              \
+    return iso->Get##variable##Metric()->Value();                              \
   }
 ISOLATE_METRIC_LIST(ISOLATE_METRIC_API);
 #undef ISOLATE_METRIC_API
@@ -1114,12 +1114,11 @@
     // bootstrap library files which call out to a tag handler that may create
     // Api Handles when an error is encountered.
     T->EnterApiScope();
-    const Error& error_obj =
-        Error::Handle(Z, Dart::InitializeIsolate(
-                             source->snapshot_data,
-                             source->snapshot_instructions, source->shared_data,
-                             source->shared_instructions, source->kernel_buffer,
-                             source->kernel_buffer_size, isolate_data));
+    const Error& error_obj = Error::Handle(
+        Z, Dart::InitializeIsolate(source->snapshot_data,
+                                   source->snapshot_instructions,
+                                   source->kernel_buffer,
+                                   source->kernel_buffer_size, isolate_data));
     if (error_obj.IsNull()) {
 #if defined(DART_NO_SNAPSHOT) && !defined(PRODUCT)
       if (FLAG_check_function_fingerprints && source->kernel_buffer == NULL) {
@@ -1217,8 +1216,6 @@
                         const char* name,
                         const uint8_t* snapshot_data,
                         const uint8_t* snapshot_instructions,
-                        const uint8_t* shared_data,
-                        const uint8_t* shared_instructions,
                         Dart_IsolateFlags* flags,
                         void* isolate_group_data,
                         void* isolate_data,
@@ -1232,10 +1229,11 @@
   }
 
   const char* non_null_name = name == nullptr ? "isolate" : name;
-  std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
-      script_uri, non_null_name, snapshot_data, snapshot_instructions,
-      shared_data, shared_instructions, nullptr, -1, *flags));
+  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);
+  IsolateGroup::RegisterIsolateGroup(group);
   Dart_Isolate isolate =
       CreateIsolate(group, non_null_name, isolate_data, error);
   if (isolate != nullptr) {
@@ -1262,10 +1260,11 @@
   }
 
   const char* non_null_name = name == nullptr ? "isolate" : name;
-  std::unique_ptr<IsolateGroupSource> source(new IsolateGroupSource(
-      script_uri, non_null_name, nullptr, nullptr, nullptr, nullptr,
-      kernel_buffer, kernel_buffer_size, *flags));
+  std::unique_ptr<IsolateGroupSource> source(
+      new IsolateGroupSource(script_uri, non_null_name, nullptr, nullptr,
+                             kernel_buffer, kernel_buffer_size, *flags));
   auto group = new IsolateGroup(std::move(source), isolate_group_data);
+  IsolateGroup::RegisterIsolateGroup(group);
   Dart_Isolate isolate =
       CreateIsolate(group, non_null_name, isolate_data, error);
   if (isolate != nullptr) {
@@ -4737,7 +4736,7 @@
               " type Integer.",
               CURRENT_FUNC, i);
         }
-        if (value < INT_MIN || value > INT_MAX) {
+        if (value < INT32_MIN || value > INT32_MAX) {
           return Api::NewArgumentError(
               "%s: argument value at index %d is out of range", CURRENT_FUNC,
               i);
@@ -4754,7 +4753,7 @@
               " type Integer.",
               CURRENT_FUNC, i);
         }
-        if (value < 0 || value > UINT_MAX) {
+        if (value < 0 || value > UINT32_MAX) {
           return Api::NewArgumentError(
               "%s: argument value at index %d is out of range", CURRENT_FUNC,
               i);
@@ -6091,8 +6090,6 @@
 DART_EXPORT Dart_Handle Dart_Precompile() {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
-#elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("AOT compilation is not supported on DBC.");
 #elif !defined(DART_PRECOMPILER)
   return Api::NewError(
       "This VM was built without support for AOT compilation.");
@@ -6117,8 +6114,6 @@
                                     void* callback_data) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
-#elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("AOT compilation is not supported on DBC.");
 #elif defined(TARGET_OS_WINDOWS)
   return Api::NewError("Assembly generation is not implemented for Windows.");
 #elif !defined(DART_PRECOMPILER)
@@ -6136,7 +6131,7 @@
   CHECK_NULL(callback);
 
   TIMELINE_DURATION(T, Isolate, "WriteAppAOTSnapshot");
-  AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
+  AssemblyImageWriter image_writer(T, callback, callback_data);
   uint8_t* vm_snapshot_data_buffer = NULL;
   uint8_t* isolate_snapshot_data_buffer = NULL;
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
@@ -6155,8 +6150,6 @@
                                    void* callback_data) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
-#elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("AOT compilation is not supported on DBC.");
 #elif defined(TARGET_OS_WINDOWS)
   return Api::NewError("Assembly generation is not implemented for Windows.");
 #elif !defined(DART_PRECOMPILER)
@@ -6168,8 +6161,7 @@
   CHECK_NULL(callback);
 
   TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
-  AssemblyImageWriter image_writer(T, callback, callback_data, nullptr,
-                                   nullptr);
+  AssemblyImageWriter image_writer(T, callback, callback_data);
   uint8_t* vm_snapshot_data_buffer = nullptr;
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                             nullptr, ApiReallocate, &image_writer, nullptr);
@@ -6186,8 +6178,6 @@
                                bool strip) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
-#elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("AOT compilation is not supported on DBC.");
 #elif !defined(DART_PRECOMPILER)
   return Api::NewError(
       "This VM was built without support for AOT compilation.");
@@ -6212,11 +6202,10 @@
 
   BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
                                   ApiReallocate, /* initial_size= */ 2 * MB,
-                                  nullptr, nullptr, nullptr, elf, dwarf);
-  BlobImageWriter isolate_image_writer(
-      T, &isolate_snapshot_instructions_buffer, ApiReallocate,
-      /* initial_size= */ 2 * MB, /* shared_data_image= */ nullptr,
-      /* shared_instructions_image= */ nullptr, nullptr, elf, dwarf);
+                                  elf, dwarf);
+  BlobImageWriter isolate_image_writer(T, &isolate_snapshot_instructions_buffer,
+                                       ApiReallocate,
+                                       /* initial_size= */ 2 * MB, elf, dwarf);
   FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
                             &isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6245,13 +6234,9 @@
                                  uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size,
-                                 const uint8_t* shared_data,
-                                 const uint8_t* shared_instructions) {
+                                 intptr_t* isolate_snapshot_instructions_size) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("AOT compilation is not supported on IA32.");
-#elif defined(TARGET_ARCH_DBC)
-  return Api::NewError("AOT compilation is not supported on DBC.");
 #elif !defined(DART_PRECOMPILER)
   return Api::NewError(
       "This VM was built without support for AOT compilation.");
@@ -6273,22 +6258,12 @@
   CHECK_NULL(isolate_snapshot_instructions_buffer);
   CHECK_NULL(isolate_snapshot_instructions_size);
 
-  const void* shared_data_image = NULL;
-  if (shared_data != NULL) {
-    shared_data_image = Snapshot::SetupFromBuffer(shared_data)->DataImage();
-  }
-  const void* shared_instructions_image = shared_instructions;
-
   TIMELINE_DURATION(T, Isolate, "WriteAppAOTSnapshot");
   BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
-                                  ApiReallocate, 2 * MB /* initial_size */,
-                                  /*shared_objects=*/nullptr,
-                                  /*shared_instructions=*/nullptr,
-                                  /*reused_objects=*/nullptr);
-  BlobImageWriter isolate_image_writer(
-      T, isolate_snapshot_instructions_buffer, ApiReallocate,
-      2 * MB /* initial_size */, shared_data_image, shared_instructions_image,
-      /* reuse_instructions= */ nullptr);
+                                  ApiReallocate, 2 * MB /* initial_size */);
+  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
+                                       ApiReallocate,
+                                       2 * MB /* initial_size */);
   FullSnapshotWriter writer(Snapshot::kFullAOT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6388,15 +6363,10 @@
 
   TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
   BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
-                                  ApiReallocate, 2 * MB /* initial_size */,
-                                  /*shared_objects=*/nullptr,
-                                  /*shared_instructions=*/nullptr,
-                                  /*reused_objects=*/nullptr);
+                                  ApiReallocate, 2 * MB /* initial_size */);
   BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
-                                       ApiReallocate, 2 * MB /* initial_size */,
-                                       /*shared_objects=*/nullptr,
-                                       /*shared_instructions=*/nullptr,
-                                       /*reused_objects=*/nullptr);
+                                       ApiReallocate,
+                                       2 * MB /* initial_size */);
   FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
                             &vm_image_writer, &isolate_image_writer);
@@ -6416,8 +6386,7 @@
 Dart_CreateAppJITSnapshotAsBlobs(uint8_t** isolate_snapshot_data_buffer,
                                  intptr_t* isolate_snapshot_data_size,
                                  uint8_t** isolate_snapshot_instructions_buffer,
-                                 intptr_t* isolate_snapshot_instructions_size,
-                                 const uint8_t* reused_instructions) {
+                                 intptr_t* isolate_snapshot_instructions_size) {
 #if defined(TARGET_ARCH_IA32)
   return Api::NewError("Snapshots with code are not supported on IA32.");
 #elif defined(DART_PRECOMPILED_RUNTIME)
@@ -6438,9 +6407,6 @@
   BackgroundCompiler::Stop(I);
   DropRegExpMatchCode(Z);
 
-  if (reused_instructions != nullptr) {
-    DropCodeWithoutReusableInstructions(reused_instructions);
-  }
   ProgramVisitor::Dedup();
   Symbols::Compact();
 
@@ -6452,10 +6418,8 @@
 
   TIMELINE_DURATION(T, Isolate, "WriteAppJITSnapshot");
   BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
-                                       ApiReallocate, 2 * MB /* initial_size */,
-                                       /*shared_objects=*/nullptr,
-                                       /*shared_instructions=*/nullptr,
-                                       reused_instructions);
+                                       ApiReallocate,
+                                       2 * MB /* initial_size */);
   FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
                             isolate_snapshot_data_buffer, ApiReallocate, NULL,
                             &isolate_image_writer);
@@ -6465,10 +6429,6 @@
   *isolate_snapshot_instructions_size =
       isolate_image_writer.InstructionsBlobSize();
 
-  if (reused_instructions != nullptr) {
-    *isolate_snapshot_instructions_buffer = NULL;
-  }
-
   return Api::Success();
 #endif
 }
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 0b6e42b..496531e 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -301,10 +301,7 @@
 
   static bool IsFfiEnabled() {
     // dart:ffi is not implemented for the following configurations
-#if defined(TARGET_ARCH_DBC) && !defined(ARCH_IS_64_BIT)
-    // TODO(36809): Support SimDBC32.
-    return false;
-#elif defined(TARGET_ARCH_ARM) &&                                              \
+#if defined(TARGET_ARCH_ARM) &&                                                \
     !(defined(TARGET_OS_ANDROID) || defined(TARGET_OS_MACOS_IOS))
     // TODO(36309): Support hardfp calling convention.
     return false;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 437ce00..937f7cf 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2953,7 +2953,6 @@
     for (int i = 1000; i < 1500; i++) {
       handles[i] = Dart_NewPersistentHandle(ref1);
     }
-    VERIFY_ON_TRANSITION;
     Dart_ExitScope();
   }
   Dart_ExitScope();
@@ -3674,7 +3673,6 @@
           }
           EXPECT_EQ(300, thread->CountLocalHandles());
         }
-        VERIFY_ON_TRANSITION;
         Dart_ExitScope();
       }
       EXPECT_EQ(200, thread->CountLocalHandles());
diff --git a/runtime/vm/dart_api_state.cc b/runtime/vm/dart_api_state.cc
index 5a8a024..888bab9 100644
--- a/runtime/vm/dart_api_state.cc
+++ b/runtime/vm/dart_api_state.cc
@@ -14,6 +14,6 @@
 
 namespace dart {
 
-intptr_t ApiNativeScope::current_memory_usage_ = 0;
+RelaxedAtomic<intptr_t> ApiNativeScope::current_memory_usage_ = 0;
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index ecb922a..0fba463 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -636,11 +636,11 @@
   static uintptr_t current_memory_usage() { return current_memory_usage_; }
 
   static void IncrementNativeScopeMemoryCapacity(intptr_t size) {
-    AtomicOperations::IncrementBy(&current_memory_usage_, size);
+    current_memory_usage_.fetch_add(size);
   }
 
   static void DecrementNativeScopeMemoryCapacity(intptr_t size) {
-    AtomicOperations::DecrementBy(&current_memory_usage_, size);
+    current_memory_usage_.fetch_sub(size);
   }
 
   Zone* zone() {
@@ -652,7 +652,7 @@
 
  private:
   // The current total memory usage within ApiNativeScopes.
-  static intptr_t current_memory_usage_;
+  static RelaxedAtomic<intptr_t> current_memory_usage_;
 
   ApiZone zone_;
 };
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 2f26ce6..49e4b47 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -41,14 +41,6 @@
   explicit ScopedIsolateStackLimits(Thread* thread, uword current_sp)
       : thread_(thread) {
     ASSERT(thread != NULL);
-    // Set the thread's stack_base based on the current
-    // stack pointer, we keep refining this value as we
-    // see higher stack pointers (Note: we assume the stack
-    // grows from high to low addresses).
-    OSThread* os_thread = thread->os_thread();
-    ASSERT(os_thread != NULL);
-    os_thread->RefineStackBoundsFromSP(current_sp);
-
     // Save the Thread's current stack limit and adjust the stack limit.
     ASSERT(thread->isolate() == Isolate::Current());
     saved_stack_limit_ = thread->saved_stack_limit();
@@ -167,20 +159,15 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-// Now Call the invoke stub which will invoke the dart function.
-#if !defined(TARGET_ARCH_DBC)
+  // Now Call the invoke stub which will invoke the dart function.
   invokestub entrypoint =
       reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
-#endif
   const Code& code = Code::Handle(zone, function.CurrentCode());
   ASSERT(!code.IsNull());
   ASSERT(thread->no_callback_scope_depth() == 0);
   SuspendLongJumpScope suspend_long_jump_scope(thread);
   TransitionToGenerated transition(thread);
-#if defined(TARGET_ARCH_DBC)
-  return Simulator::Current()->Call(code, arguments_descriptor, arguments,
-                                    thread);
-#elif defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR)
   return bit_copy<RawObject*, int64_t>(Simulator::Current()->Call(
       reinterpret_cast<intptr_t>(entrypoint), reinterpret_cast<intptr_t>(&code),
       reinterpret_cast<intptr_t>(&arguments_descriptor),
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 3f5212c..e49bd50 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -180,9 +180,7 @@
 void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&bytecode_));
-#if !defined(TARGET_ARCH_DBC)
   visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
-#endif
 }
 
 ActivationFrame::ActivationFrame(uword pc,
@@ -1055,7 +1053,6 @@
   }
 
   ASSERT(!IsInterpreted());
-  ASSERT(script.kind() == RawScript::kKernelTag);
   const intptr_t await_jump_var = GetAwaitJumpVariable();
   if (await_jump_var < 0) {
     return;
@@ -1750,13 +1747,7 @@
       bpt_location_(NULL),
       next_(NULL),
       breakpoint_kind_(kind),
-#if !defined(TARGET_ARCH_DBC)
-      saved_value_(Code::null())
-#else
-      saved_value_(SimulatorBytecode::kTrap),
-      saved_value_fastsmi_(SimulatorBytecode::kTrap)
-#endif
-{
+      saved_value_(Code::null()) {
   ASSERT(!code.IsNull());
   ASSERT(token_pos_.IsReal());
   ASSERT(pc_ != 0);
@@ -1775,13 +1766,7 @@
       bpt_location_(NULL),
       next_(NULL),
       breakpoint_kind_(RawPcDescriptors::kAnyKind),
-#if !defined(TARGET_ARCH_DBC)
-      saved_value_(Code::null())
-#else
-      saved_value_(SimulatorBytecode::kTrap),
-      saved_value_fastsmi_(SimulatorBytecode::kTrap)
-#endif
-{
+      saved_value_(Code::null()) {
   ASSERT(!bytecode.IsNull());
   ASSERT(FLAG_enable_interpreter);
   ASSERT(token_pos_.IsReal());
@@ -3077,7 +3062,6 @@
     const TokenPosition begin_pos = best_fit_pos;
 
     TokenPosition end_of_line_pos;
-    ASSERT(script.kind() == RawScript::kKernelTag);
     if (best_line == -1) {
       script.GetTokenLocation(begin_pos, &best_line, NULL);
     }
@@ -4393,7 +4377,6 @@
     }
     ASSERT(!top_frame->IsInterpreted());
     const Script& script = Script::Handle(zone, top_frame->SourceScript());
-    ASSERT(script.kind() == RawScript::kKernelTag);
     const auto& yield_positions = GrowableObjectArray::Handle(
         zone, script.GetYieldPositions(top_frame->function()));
     // No yield statements
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index cff3791..3300813 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -244,15 +244,7 @@
   CodeBreakpoint* next_;
 
   RawPcDescriptors::Kind breakpoint_kind_;
-#if !defined(TARGET_ARCH_DBC)
   RawCode* saved_value_;
-#else
-  // When running on the DBC interpreter we patch bytecode in place with
-  // DebugBreak. This is an instruction that was replaced. DebugBreak
-  // will execute it after the breakpoint.
-  Instr saved_value_;
-  Instr saved_value_fastsmi_;
-#endif
 
   friend class Debugger;
   DISALLOW_COPY_AND_ASSIGN(CodeBreakpoint);
diff --git a/runtime/vm/debugger_dbc.cc b/runtime/vm/debugger_dbc.cc
deleted file mode 100644
index 56234ce..0000000
--- a/runtime/vm/debugger_dbc.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// 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.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/code_patcher.h"
-#include "vm/cpu.h"
-#include "vm/debugger.h"
-#include "vm/instructions.h"
-#include "vm/stub_code.h"
-
-namespace dart {
-
-#ifndef PRODUCT
-
-RawCode* CodeBreakpoint::OrigStubAddress() const {
-  return reinterpret_cast<RawCode*>(static_cast<uintptr_t>(saved_value_));
-}
-
-static Instr* CallInstructionFromReturnAddress(uword pc) {
-  return reinterpret_cast<Instr*>(pc) - 1;
-}
-
-static Instr* FastSmiInstructionFromReturnAddress(uword pc) {
-  return reinterpret_cast<Instr*>(pc) - 2;
-}
-
-void CodeBreakpoint::PatchCode() {
-  ASSERT(!is_enabled_);
-  auto thread = Thread::Current();
-  auto zone = thread->zone();
-  const Code& code = Code::Handle(zone, code_);
-  const Instructions& instrs = Instructions::Handle(zone, code.instructions());
-  thread->isolate_group()->RunWithStoppedMutators([&]() {
-    WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
-    saved_value_ = *CallInstructionFromReturnAddress(pc_);
-    switch (breakpoint_kind_) {
-      case RawPcDescriptors::kIcCall:
-      case RawPcDescriptors::kUnoptStaticCall: {
-        // DebugBreak has an A operand matching the call it replaces.
-        // This ensures that Return instructions continue to work - as they
-        // look at calls to figure out how many arguments to drop.
-        *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::Encode(
-            SimulatorBytecode::kDebugBreak,
-            SimulatorBytecode::DecodeArgc(saved_value_), 0, 0);
-        break;
-      }
-
-      case RawPcDescriptors::kRuntimeCall: {
-        *CallInstructionFromReturnAddress(pc_) = SimulatorBytecode::kDebugBreak;
-        break;
-      }
-
-      default:
-        UNREACHABLE();
-    }
-
-    // If this call is the fall-through for a fast Smi op, also disable the fast
-    // Smi op.
-    if ((SimulatorBytecode::DecodeOpcode(saved_value_) ==
-         SimulatorBytecode::kInstanceCall2) &&
-        SimulatorBytecode::IsFastSmiOpcode(
-            *FastSmiInstructionFromReturnAddress(pc_))) {
-      saved_value_fastsmi_ = *FastSmiInstructionFromReturnAddress(pc_);
-      *FastSmiInstructionFromReturnAddress(pc_) =
-          SimulatorBytecode::Encode(SimulatorBytecode::kNop, 0, 0, 0);
-    } else {
-      saved_value_fastsmi_ = SimulatorBytecode::kTrap;
-    }
-  });
-  is_enabled_ = true;
-}
-
-void CodeBreakpoint::RestoreCode() {
-  ASSERT(is_enabled_);
-  auto thread = Thread::Current();
-  auto zone = thread->zone();
-  const Code& code = Code::Handle(zone, code_);
-  const Instructions& instrs = Instructions::Handle(zone, code.instructions());
-  thread->isolate_group()->RunWithStoppedMutators([&]() {
-    WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
-    switch (breakpoint_kind_) {
-      case RawPcDescriptors::kIcCall:
-      case RawPcDescriptors::kUnoptStaticCall:
-      case RawPcDescriptors::kRuntimeCall: {
-        *CallInstructionFromReturnAddress(pc_) = saved_value_;
-        break;
-      }
-      default:
-        UNREACHABLE();
-    }
-
-    if (saved_value_fastsmi_ != SimulatorBytecode::kTrap) {
-      Instr current_instr = *FastSmiInstructionFromReturnAddress(pc_);
-      ASSERT(SimulatorBytecode::DecodeOpcode(current_instr) ==
-             SimulatorBytecode::kNop);
-      *FastSmiInstructionFromReturnAddress(pc_) = saved_value_fastsmi_;
-    }
-  });
-  is_enabled_ = false;
-}
-
-#endif  // !PRODUCT
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/deferred_objects.h b/runtime/vm/deferred_objects.h
index 39a335e..a46be13 100644
--- a/runtime/vm/deferred_objects.h
+++ b/runtime/vm/deferred_objects.h
@@ -219,11 +219,7 @@
   void Create();
 
   RawObject* GetArg(intptr_t index) const {
-#if !defined(TARGET_ARCH_DBC)
     return args_[index];
-#else
-    return args_[-index];
-#endif
   }
 
   RawObject* GetClass() const { return GetArg(kClassIndex); }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 4ea755a..3057977 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -77,14 +77,8 @@
 // optimized function contains FP, PP (ARM only), PC-marker and
 // return-address. This section is copied as well, so that its contained
 // values can be updated before returning to the deoptimized function.
-// Note: on DBC stack grows upwards unlike on all other architectures.
-#if defined(TARGET_ARCH_DBC)
-  ASSERT(frame->sp() >= frame->fp());
-  const intptr_t frame_size = (frame->sp() - frame->fp()) / kWordSize;
-#else
   ASSERT(frame->fp() >= frame->sp());
   const intptr_t frame_size = (frame->fp() - frame->sp()) / kWordSize;
-#endif
 
   source_frame_size_ = +kDartFrameFixedSize   // For saved values below sp.
                        + frame_size           // For frame size incl. sp.
@@ -201,40 +195,23 @@
 
 intptr_t DeoptContext::DestStackAdjustment() const {
   return dest_frame_size_ - kDartFrameFixedSize - num_args_
-#if !defined(TARGET_ARCH_DBC)
          - 1  // For fp.
-#endif
          - kParamEndSlotFromFp;
 }
 
 intptr_t DeoptContext::GetSourceFp() const {
-#if !defined(TARGET_ARCH_DBC)
   return source_frame_[source_frame_size_ - 1 - num_args_ -
                        kParamEndSlotFromFp];
-#else
-  return source_frame_[num_args_ + kDartFrameFixedSize +
-                       kSavedCallerFpSlotFromFp];
-#endif
 }
 
 intptr_t DeoptContext::GetSourcePp() const {
-#if !defined(TARGET_ARCH_DBC)
   return source_frame_[source_frame_size_ - 1 - num_args_ -
                        kParamEndSlotFromFp +
                        StackFrame::SavedCallerPpSlotFromFp()];
-#else
-  UNREACHABLE();
-  return 0;
-#endif
 }
 
 intptr_t DeoptContext::GetSourcePc() const {
-#if !defined(TARGET_ARCH_DBC)
   return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp];
-#else
-  return source_frame_[num_args_ + kDartFrameFixedSize +
-                       kSavedCallerPcSlotFromFp];
-#endif
 }
 
 intptr_t DeoptContext::GetCallerFp() const {
@@ -351,19 +328,12 @@
   intptr_t params =
       function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
   for (intptr_t i = 0; i < num_vars; i++) {
-#if defined(TARGET_ARCH_DBC)
-    const intptr_t len = deopt_instructions.length();
-    intptr_t slot = i < params ? i : i + kParamEndSlotFromFp;
-    DeoptInstr* instr = deopt_instructions[len - 1 - slot];
-    intptr_t dest_index = kNumberOfCpuRegisters - 1 - i;
-#else
     const intptr_t len = deopt_instructions.length();
     intptr_t slot = i < params ? i
                                : i + kParamEndSlotFromFp -
                                      runtime_frame_layout.first_local_from_fp;
     DeoptInstr* instr = deopt_instructions[len - 1 - slot];
     intptr_t dest_index = i - params;
-#endif
     moves->At(i) = instr->ToCatchEntryMove(this, dest_index);
   }
 
@@ -1083,10 +1053,6 @@
     Location::Kind stack_slot_kind) {
   if (loc.IsFpuRegister()) {
     return FpuRegisterSource(FpuRegisterSource::kRegister, loc.fpu_reg());
-#if defined(TARGET_ARCH_DBC)
-  } else if (loc.IsRegister()) {
-    return FpuRegisterSource(FpuRegisterSource::kRegister, loc.reg());
-#endif
   } else {
     ASSERT((stack_slot_kind == Location::kQuadStackSlot) ||
            (stack_slot_kind == Location::kDoubleStackSlot));
@@ -1133,12 +1099,7 @@
     deopt_instr = new (zone()) DeoptMaterializedObjectRefInstr(index);
   } else {
     ASSERT(!source_loc.IsInvalid());
-#if defined(TARGET_ARCH_DBC)
-    Representation rep =
-        (value == NULL) ? kTagged : value->definition()->representation();
-#else
     Representation rep = value->definition()->representation();
-#endif
     switch (rep) {
       case kTagged:
         deopt_instr =
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h
index b440413..926ea1b 100644
--- a/runtime/vm/deopt_instructions.h
+++ b/runtime/vm/deopt_instructions.h
@@ -50,23 +50,16 @@
   intptr_t* GetSourceFrameAddressAt(intptr_t index) const {
     ASSERT(source_frame_ != NULL);
     ASSERT((0 <= index) && (index < source_frame_size_));
-#if !defined(TARGET_ARCH_DBC)
     // Convert FP relative index to SP relative one.
     index = source_frame_size_ - 1 - index;
-#endif  // !defined(TARGET_ARCH_DBC)
     return &source_frame_[index];
   }
 
   // Returns index in stack slot notation where -1 is the first argument
-  // For DBC returns index directly relative to FP.
   intptr_t GetStackSlot(intptr_t index) const {
     ASSERT((0 <= index) && (index < source_frame_size_));
     index -= num_args_;
-#if defined(TARGET_ARCH_DBC)
-    return index < 0 ? index - kDartFrameFixedSize : index;
-#else
     return index < 0 ? index : index - kDartFrameFixedSize;
-#endif  // defined(TARGET_ARCH_DBC)
   }
 
   intptr_t GetSourceFp() const;
@@ -84,28 +77,16 @@
   intptr_t RegisterValue(Register reg) const {
     ASSERT(reg >= 0);
     ASSERT(reg < kNumberOfCpuRegisters);
-#if !defined(TARGET_ARCH_DBC)
     ASSERT(cpu_registers_ != NULL);
     return cpu_registers_[reg];
-#else
-    // On DBC registers and stack slots are the same.
-    const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg;
-    return *GetSourceFrameAddressAt(stack_index);
-#endif  // !defined(TARGET_ARCH_DBC)
   }
 
   double FpuRegisterValue(FpuRegister reg) const {
     ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
-#if !defined(TARGET_ARCH_DBC)
     ASSERT(fpu_registers_ != NULL);
     ASSERT(reg >= 0);
     ASSERT(reg < kNumberOfFpuRegisters);
     return *reinterpret_cast<double*>(&fpu_registers_[reg]);
-#else
-    // On DBC registers and stack slots are the same.
-    const intptr_t stack_index = num_args_ + kDartFrameFixedSize + reg;
-    return *reinterpret_cast<double*>(GetSourceFrameAddressAt(stack_index));
-#endif
   }
 
   simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const {
@@ -125,16 +106,10 @@
   // part of the frame because it contains saved caller PC and FP that
   // deoptimization will fill in.
   intptr_t* FrameBase(const StackFrame* frame) {
-#if !defined(TARGET_ARCH_DBC)
     // SP of the deoptimization frame is the lowest slot because
     // stack is growing downwards.
     return reinterpret_cast<intptr_t*>(frame->sp() -
                                        (kDartFrameFixedSize * kWordSize));
-#else
-    // First argument is the lowest slot because stack is growing upwards.
-    return reinterpret_cast<intptr_t*>(
-        frame->fp() - (kDartFrameFixedSize + num_args_) * kWordSize);
-#endif  // !defined(TARGET_ARCH_DBC)
   }
 
   void set_dest_frame(const StackFrame* frame) {
@@ -234,12 +209,6 @@
   intptr_t* GetDestFrameAddressAt(intptr_t index) const {
     ASSERT(dest_frame_ != NULL);
     ASSERT((0 <= index) && (index < dest_frame_size_));
-#if defined(TARGET_ARCH_DBC)
-    // Stack on DBC is growing upwards but we record deopt commands
-    // in the same order we record them on other architectures as if
-    // the stack was growing downwards.
-    index = dest_frame_size_ - 1 - index;
-#endif  // defined(TARGET_ARCH_DBC)
     return &dest_frame_[index];
   }
 
@@ -432,11 +401,8 @@
   }
 
   intptr_t StackSlot(DeoptContext* context) const {
-    if (is_register()) {
-      return raw_index();  // in DBC stack slots are registers.
-    } else {
-      return context->GetStackSlot(raw_index());
-    }
+    ASSERT(!is_register());
+    return context->GetStackSlot(raw_index());
   }
 
   intptr_t source_index() const { return source_index_; }
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index 2136114..cd5530d 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -6,6 +6,7 @@
 
 #include "vm/code_descriptors.h"
 #include "vm/elf.h"
+#include "vm/image_snapshot.h"
 #include "vm/object_store.h"
 
 namespace dart {
@@ -254,6 +255,8 @@
   uint8_t* buffer = nullptr;
   WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
 
+  AssemblyCodeNamer namer(zone_);
+
   if (asm_stream_) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
     Print(".section __DWARF,__debug_info,regular,debug\n");
@@ -314,8 +317,8 @@
   if (asm_stream_) {
     intptr_t last_code_index = codes_.length() - 1;
     const Code& last_code = *(codes_[last_code_index]);
-    Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
-          last_code.Size());
+    Print(FORM_ADDR " %s + %" Pd "\n",
+          namer.AssemblyNameFor(last_code_index, last_code), last_code.Size());
   } else {
     addr(elf_->NextMemoryOffset());
   }
@@ -373,6 +376,7 @@
 void Dwarf::WriteConcreteFunctions() {
   Function& function = Function::Handle(zone_);
   Script& script = Script::Handle(zone_);
+  AssemblyCodeNamer namer(zone_);
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
     RELEASE_ASSERT(!code.IsNull());
@@ -403,14 +407,13 @@
 
     // DW_AT_low_pc
     if (asm_stream_) {
-      Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+      const char* asm_name = namer.AssemblyNameFor(i, code);
+      // DW_AT_low_pc
+      Print(FORM_ADDR " %s\n", asm_name);
+      // DW_AT_high_pc
+      Print(FORM_ADDR " %s + %" Pd "\n", asm_name, code.Size());
     } else {
       addr(code_offset);
-    }
-    // DW_AT_high_pc
-    if (asm_stream_) {
-      Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
-    } else {
       addr(code_offset + code.Size());
     }
 
@@ -418,7 +421,7 @@
     if (node != NULL) {
       for (InliningNode* child = node->children_head; child != NULL;
            child = child->children_next) {
-        WriteInliningNode(child, i, script);
+        WriteInliningNode(child, i, script, &namer);
       }
     }
 
@@ -509,7 +512,8 @@
 
 void Dwarf::WriteInliningNode(InliningNode* node,
                               intptr_t root_code_index,
-                              const Script& parent_script) {
+                              const Script& parent_script,
+                              AssemblyCodeNamer* namer) {
   intptr_t file = LookupScript(parent_script);
   intptr_t line = node->call_pos.value();
   intptr_t function_index = LookupFunction(node->function);
@@ -527,20 +531,21 @@
   } else {
     u4(abstract_origins_[function_index]);
   }
-  // DW_AT_low_pc
+
   if (asm_stream_) {
-    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-          node->start_pc_offset);
+    const char* asm_name =
+        namer->AssemblyNameFor(root_code_index, *codes_[root_code_index]);
+    // DW_AT_low_pc
+    Print(FORM_ADDR " %s + %d\n", asm_name, node->start_pc_offset);
+    // DW_AT_high_pc
+    Print(FORM_ADDR " %s + %d\n", asm_name, node->end_pc_offset);
   } else {
+    // DW_AT_low_pc
     addr(root_code_index + node->start_pc_offset);
-  }
   // DW_AT_high_pc
-  if (asm_stream_) {
-    Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
-          node->end_pc_offset);
-  } else {
     addr(root_code_index + node->end_pc_offset);
   }
+
   // DW_AT_call_file
   uleb128(file);
   // DW_AT_call_line
@@ -548,7 +553,7 @@
 
   for (InliningNode* child = node->children_head; child != NULL;
        child = child->children_next) {
-    WriteInliningNode(child, root_code_index, script);
+    WriteInliningNode(child, root_code_index, script, namer);
   }
 
   uleb128(0);  // End of children.
@@ -655,10 +660,16 @@
   Array& functions = Array::Handle(zone_);
   GrowableArray<const Function*> function_stack(zone_, 8);
   GrowableArray<TokenPosition> token_positions(zone_, 8);
+  AssemblyCodeNamer namer(zone_);
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
 
+    const char* asm_name = nullptr;
+    if (asm_stream_ != nullptr) {
+      asm_name = namer.AssemblyNameFor(i, code);
+    }
+
     CodeIndexPair* pair = code_to_index_.Lookup(&code);
     RELEASE_ASSERT(pair != NULL);
     intptr_t current_code_offset = pair->index_;
@@ -723,15 +734,16 @@
             u1(1 + sizeof(void*));  // that is 5 or 9 bytes long
             u1(DW_LNE_set_address);
             if (asm_stream_) {
-              Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+              Print(FORM_ADDR " %s + %d\n", asm_name, current_pc_offset);
             } else {
               addr(current_code_offset + current_pc_offset);
             }
           } else {
             u1(DW_LNS_advance_pc);
             if (asm_stream_) {
-              Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
-                    previous_code_offset,
+              const char* previous_asm_name = namer.AssemblyNameFor(
+                  previous_code_offset, *codes_[previous_code_offset]);
+              Print(".uleb128 %s - %s + %" Pd "\n", asm_name, previous_asm_name,
                     current_pc_offset - previous_pc_offset);
             } else {
               intptr_t delta = current_code_offset - previous_code_offset +
@@ -780,8 +792,13 @@
 
   u1(DW_LNS_advance_pc);
   if (asm_stream_) {
-    Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
-          previous_code_offset, last_code.Size() - previous_pc_offset);
+    const char* last_asm_name =
+        namer.AssemblyNameFor(last_code_index, last_code);
+    ASSERT(previous_code_offset >= 0);
+    const char* previous_asm_name = namer.AssemblyNameFor(
+        previous_code_offset, *codes_[previous_code_offset]);
+    Print(".uleb128 %s - %s + %" Pd "\n", last_asm_name, previous_asm_name,
+          last_code.Size() - previous_pc_offset);
   } else {
     intptr_t delta = last_code_offset - previous_code_offset +
                      last_code.Size() - previous_pc_offset;
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 7d4f5b7..14eac01 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -16,6 +16,7 @@
 
 class Elf;
 class InliningNode;
+class AssemblyCodeNamer;
 
 struct ScriptIndexPair {
   // Typedefs needed for the DirectChainedHashMap template.
@@ -285,7 +286,8 @@
   InliningNode* ExpandInliningTree(const Code& code);
   void WriteInliningNode(InliningNode* node,
                          intptr_t root_code_index,
-                         const Script& parent_script);
+                         const Script& parent_script,
+                         AssemblyCodeNamer* namer);
   void WriteLines();
 
   Zone* const zone_;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 769f3d5..5be327b 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -132,11 +132,19 @@
 
 class SymbolTable : public Section {
  public:
-  SymbolTable() {
-    section_type = elf::SHT_DYNSYM;
-    section_flags = elf::SHF_ALLOC;
-    segment_type = elf::PT_LOAD;
-    segment_flags = elf::PF_R;
+  explicit SymbolTable(bool dynamic) {
+    if (dynamic) {
+      section_type = elf::SHT_DYNSYM;
+      section_flags = elf::SHF_ALLOC;
+      segment_type = elf::PT_LOAD;
+      segment_flags = elf::PF_R;
+    } else {
+      // No need to load the static symbol table at runtime since it's ignored
+      // by the dynamic linker.
+      section_type = elf::SHT_SYMTAB;
+      memory_offset = 0;
+      section_flags = 0;
+    }
 
     section_entry_size = kElfSymbolTableEntrySize;
     AddSymbol(NULL);
@@ -339,11 +347,17 @@
   shstrtab_ = new (zone_) StringTable(/* allocate= */ false);
   shstrtab_->section_name = shstrtab_->AddString(".shstrtab");
 
-  symstrtab_ = new (zone_) StringTable(/* allocate= */ true);
-  symstrtab_->section_name = shstrtab_->AddString(".dynstr");
+  dynstrtab_ = new (zone_) StringTable(/* allocate= */ true);
+  dynstrtab_->section_name = shstrtab_->AddString(".dynstr");
 
-  symtab_ = new (zone_) SymbolTable();
-  symtab_->section_name = shstrtab_->AddString(".dynsym");
+  dynsym_ = new (zone_) SymbolTable(/*dynamic=*/true);
+  dynsym_->section_name = shstrtab_->AddString(".dynsym");
+
+  strtab_ = new (zone_) StringTable(/* allocate= */ false);
+  strtab_->section_name = shstrtab_->AddString(".strtab");
+
+  symtab_ = new (zone_) SymbolTable(/*dynamic=*/false);
+  symtab_->section_name = shstrtab_->AddString(".symtab");
 
   // Allocate regular segments after the program table.
   memory_offset_ = kProgramTableSegmentSize;
@@ -366,10 +380,14 @@
   memory_offset_ = Utils::RoundUp(memory_offset_, kPageSize);
 }
 
-intptr_t Elf::NextMemoryOffset() {
+intptr_t Elf::NextMemoryOffset() const {
   return memory_offset_;
 }
 
+intptr_t Elf::NextSectionIndex() const {
+  return sections_.length() + kNumInvalidSections;
+}
+
 intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
   ProgramBits* image = new (zone_) ProgramBits(true, true, false, bytes, size);
   image->section_name = shstrtab_->AddString(".text");
@@ -378,18 +396,33 @@
 
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
-  symbol->name = symstrtab_->AddString(name);
+  symbol->name = dynstrtab_->AddString(name);
   symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
   symbol->offset = image->memory_offset;
   symbol->size = size;
-  symtab_->AddSymbol(symbol);
+  dynsym_->AddSymbol(symbol);
 
   return symbol->offset;
 }
 
+void Elf::AddStaticSymbol(intptr_t section,
+                          const char* name,
+                          size_t memory_offset) {
+  Symbol* symbol = new (zone_) Symbol();
+  symbol->cstr = name;
+  symbol->name = strtab_->AddString(name);
+  symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
+  symbol->section = section;
+  // For shared libraries, this is the offset from the DSO base. For static
+  // libraries, this is section relative.
+  symbol->offset = memory_offset;
+  symbol->size = 0;
+  symtab_->AddSymbol(symbol);
+}
+
 intptr_t Elf::AddBSSData(const char* name, intptr_t size) {
   // Ideally the BSS segment would take no space in the object, but Android's
   // "strip" utility truncates the memory-size of our segments to their
@@ -407,14 +440,14 @@
 
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
-  symbol->name = symstrtab_->AddString(name);
+  symbol->name = dynstrtab_->AddString(name);
   symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
   symbol->offset = image->memory_offset;
   symbol->size = size;
-  symtab_->AddSymbol(symbol);
+  dynsym_->AddSymbol(symbol);
 
   return symbol->offset;
 }
@@ -427,14 +460,14 @@
 
   Symbol* symbol = new (zone_) Symbol();
   symbol->cstr = name;
-  symbol->name = symstrtab_->AddString(name);
+  symbol->name = dynstrtab_->AddString(name);
   symbol->info = (elf::STB_GLOBAL << 4) | elf::STT_OBJECT;
   symbol->section = image->section_index;
   // For shared libraries, this is the offset from the DSO base. For static
   // libraries, this is section relative.
   symbol->offset = image->memory_offset;
   symbol->size = size;
-  symtab_->AddSymbol(symbol);
+  dynsym_->AddSymbol(symbol);
 
   return symbol->offset;
 }
@@ -447,25 +480,28 @@
 }
 
 void Elf::Finalize() {
-  SymbolHashTable* hash = new (zone_) SymbolHashTable(symstrtab_, symtab_);
+  SymbolHashTable* hash = new (zone_) SymbolHashTable(dynstrtab_, dynsym_);
   hash->section_name = shstrtab_->AddString(".hash");
 
   AddSection(hash);
+  AddSection(dynsym_);
+  AddSection(dynstrtab_);
+  AddSection(strtab_);
   AddSection(symtab_);
-  AddSection(symstrtab_);
 
-  symtab_->section_link = symstrtab_->section_index;
-  hash->section_link = symtab_->section_index;
+  dynsym_->section_link = dynstrtab_->section_index;
+  hash->section_link = dynsym_->section_index;
+  symtab_->section_link = strtab_->section_index;
 
   // Before finalizing the string table's memory size:
   intptr_t name_dynamic = shstrtab_->AddString(".dynamic");
 
   // Finalizes memory size of string and symbol tables.
   AddSegment(hash);
-  AddSegment(symtab_);
-  AddSegment(symstrtab_);
+  AddSegment(dynsym_);
+  AddSegment(dynstrtab_);
 
-  dynamic_ = new (zone_) DynamicTable(symstrtab_, symtab_, hash);
+  dynamic_ = new (zone_) DynamicTable(dynstrtab_, dynsym_, hash);
   dynamic_->section_name = name_dynamic;
   AddSection(dynamic_);
   AddSegment(dynamic_);
@@ -538,7 +574,6 @@
 #elif defined(TARGET_ARCH_ARM64)
   WriteHalf(elf::EM_AARCH64);
 #else
-  // E.g., DBC.
   FATAL("Unknown ELF architecture");
 #endif
 
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index 882c917..b328e0f 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -25,11 +25,15 @@
 
   static const intptr_t kPageSize = 4096;
 
-  intptr_t NextMemoryOffset();
+  intptr_t NextMemoryOffset() const;
+  intptr_t NextSectionIndex() const;
   intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
   intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
   intptr_t AddBSSData(const char* name, intptr_t size);
   void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
+  void AddStaticSymbol(intptr_t section,
+                       const char* name,
+                       size_t memory_offset);
 
   void Finalize();
 
@@ -79,7 +83,9 @@
   intptr_t program_table_file_offset_;
   intptr_t program_table_file_size_;
   StringTable* shstrtab_;
-  StringTable* symstrtab_;
+  StringTable* dynstrtab_;
+  SymbolTable* dynsym_;
+  StringTable* strtab_;
   SymbolTable* symtab_;
   DynamicTable* dynamic_;
 };
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0f54abd..761ea02 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -346,13 +346,9 @@
  private:
   template <typename T>
   static T* SlotAt(uword fp, int stack_slot) {
-#if defined(TARGET_ARCH_DBC)
-    return reinterpret_cast<T*>(fp + stack_slot * kWordSize);
-#else
     const intptr_t frame_slot =
         runtime_frame_layout.FrameSlotForVariableIndex(-stack_slot);
     return reinterpret_cast<T*>(fp + frame_slot * kWordSize);
-#endif
   }
 
   static RawObject** TaggedSlotAt(uword fp, int stack_slot) {
@@ -479,7 +475,6 @@
 static uword RemapExceptionPCForDeopt(Thread* thread,
                                       uword program_counter,
                                       uword frame_pointer) {
-#if !defined(TARGET_ARCH_DBC)
   MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
       thread->isolate()->pending_deopts();
   if (pending_deopts->length() > 0) {
@@ -500,12 +495,10 @@
       }
     }
   }
-#endif  // !DBC
   return program_counter;
 }
 
 static void ClearLazyDeopts(Thread* thread, uword frame_pointer) {
-#if !defined(TARGET_ARCH_DBC)
   MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
       thread->isolate()->pending_deopts();
   if (pending_deopts->length() > 0) {
@@ -548,7 +541,6 @@
     ValidateFrames();
 #endif
   }
-#endif  // !DBC
 }
 
 static void JumpToExceptionHandler(Thread* thread,
@@ -830,11 +822,7 @@
   intptr_t column = -1;
   ASSERT(!script.IsNull());
   if (location.IsReal()) {
-    if (script.HasSource() || script.kind() == RawScript::kKernelTag) {
-      script.GetTokenLocation(location, &line, &column);
-    } else {
-      script.GetTokenLocation(location, &line, NULL);
-    }
+    script.GetTokenLocation(location, &line, &column);
   }
   // Initialize '_url', '_line', and '_column' arguments.
   args.SetAt(0, String::Handle(zone, script.url()));
@@ -869,7 +857,8 @@
     if (!src_type.IsNull()) {
       src_type.EnumerateURIs(&uris);
     }
-    if (!dst_type.IsDynamicType() && !dst_type.IsVoidType()) {
+    if (!dst_type.IsDynamicType() && !dst_type.IsVoidType() &&
+        !dst_type.IsNeverType()) {
       dst_type.EnumerateURIs(&uris);
     }
     const String& formatted_uris =
diff --git a/runtime/vm/ffi_callback_trampolines.cc b/runtime/vm/ffi_callback_trampolines.cc
index af987dc..6475a3d 100644
--- a/runtime/vm/ffi_callback_trampolines.cc
+++ b/runtime/vm/ffi_callback_trampolines.cc
@@ -13,7 +13,7 @@
 
 DECLARE_FLAG(bool, disassemble_stubs);
 
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 uword NativeCallbackTrampolines::TrampolineForId(int32_t callback_id) {
 #if defined(DART_PRECOMPILER)
   ASSERT(!Enabled());
@@ -98,6 +98,6 @@
   next_callback_id_++;
 #endif  // defined(DART_PRECOMPILER)
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
diff --git a/runtime/vm/ffi_callback_trampolines.h b/runtime/vm/ffi_callback_trampolines.h
index 77822d5..7328828 100644
--- a/runtime/vm/ffi_callback_trampolines.h
+++ b/runtime/vm/ffi_callback_trampolines.h
@@ -13,7 +13,7 @@
 
 namespace dart {
 
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 // In JIT mode, when write-protection is enabled without dual-mapping, we cannot
 // rely on Instructions generated in the Isolate's heap to be executable while
 // native code is running in a safepoint. This means that native code cannot
@@ -69,7 +69,7 @@
 
   DISALLOW_COPY_AND_ASSIGN(NativeCallbackTrampolines);
 };
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index d7b0a9f..a3d9e05 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -5,20 +5,6 @@
 #ifndef RUNTIME_VM_FLAG_LIST_H_
 #define RUNTIME_VM_FLAG_LIST_H_
 
-// Don't use USING_DBC outside of this file.
-#if defined(TARGET_ARCH_DBC)
-#define USING_DBC true
-#else
-#define USING_DBC false
-#endif
-
-// Don't use USING_MULTICORE outside of this file.
-#if defined(ARCH_IS_MULTI_CORE)
-#define USING_MULTICORE true
-#else
-#define USING_MULTICORE false
-#endif
-
 // Don't use USING_PRODUCT outside of this file.
 #if defined(PRODUCT)
 #define USING_PRODUCT true
@@ -61,7 +47,7 @@
     "Abort if memory allocation fails - use only with --old-gen-heap-size")    \
   C(async_debugger, false, false, bool, true,                                  \
     "Debugger support async functions.")                                       \
-  P(background_compilation, bool, USING_MULTICORE,                             \
+  P(background_compilation, bool, true,                                        \
     "Run optimizing compilation in background")                                \
   P(causal_async_stacks, bool, !USING_PRODUCT, "Improved async stacks")        \
   P(collect_code, bool, false, "Attempt to GC infrequently used code.")        \
@@ -72,10 +58,8 @@
   P(compilation_counter_threshold, int, 10,                                    \
     "Function's usage-counter value before interpreted function is compiled, " \
     "-1 means never")                                                          \
-  P(concurrent_mark, bool, USING_MULTICORE,                                    \
-    "Concurrent mark for old generation.")                                     \
-  P(concurrent_sweep, bool, USING_MULTICORE,                                   \
-    "Concurrent sweep for old generation.")                                    \
+  P(concurrent_mark, bool, true, "Concurrent mark for old generation.")        \
+  P(concurrent_sweep, bool, true, "Concurrent sweep for old generation.")      \
   R(dedup_instructions, true, bool, false,                                     \
     "Canonicalize instructions when precompiling.")                            \
   C(deoptimize_alot, false, false, bool, false,                                \
@@ -113,12 +97,12 @@
     "Consider thread pool isolates for idle tasks after this long.")           \
   P(idle_duration_micros, int, 500 * kMicrosecondsPerMillisecond,              \
     "Allow idle tasks to run for this long.")                                  \
-  P(interpret_irregexp, bool, USING_DBC, "Use irregexp bytecode interpreter")  \
+  P(interpret_irregexp, bool, false, "Use irregexp bytecode interpreter")      \
   P(lazy_dispatchers, bool, true, "Generate dispatchers lazily")               \
   P(link_natives_lazily, bool, false, "Link native calls lazily")              \
   R(log_marker_tasks, false, bool, false,                                      \
     "Log debugging information for old gen GC marking tasks.")                 \
-  P(marker_tasks, int, USING_MULTICORE ? 2 : 0,                                \
+  P(marker_tasks, int, 2,                                                      \
     "The number of tasks to spawn during old gen GC marking (0 means "         \
     "perform all marking on main thread).")                                    \
   P(max_polymorphic_checks, int, 4,                                            \
@@ -203,8 +187,7 @@
   P(use_compactor, bool, false, "Compact the heap during old-space GC.")       \
   P(use_cha_deopt, bool, true,                                                 \
     "Use class hierarchy analysis even if it can cause deoptimization.")       \
-  P(use_field_guards, bool, !USING_DBC,                                        \
-    "Use field guards and track field types")                                  \
+  P(use_field_guards, bool, true, "Use field guards and track field types")    \
   C(use_osr, false, true, bool, true, "Use OSR")                               \
   P(use_strong_mode_types, bool, true, "Optimize based on strong mode types.") \
   R(verbose_gc, false, bool, false, "Enables verbose GC.")                     \
@@ -213,9 +196,6 @@
     "Enables heap verification after GC.")                                     \
   R(verify_before_gc, false, bool, false,                                      \
     "Enables heap verification before GC.")                                    \
-  D(verify_gc_contains, bool, false,                                           \
-    "Enables verification of address contains during GC.")                     \
-  D(verify_on_transition, bool, false, "Verify on dart <==> VM.")              \
   P(enable_slow_path_sharing, bool, true, "Enable sharing of slow-path code.") \
   P(shared_slow_path_triggers_gc, bool, false,                                 \
     "TESTING: slow-path triggers a GC.")                                       \
diff --git a/runtime/vm/gdb_helpers.cc b/runtime/vm/gdb_helpers.cc
index b32297c..a8a1a60 100644
--- a/runtime/vm/gdb_helpers.cc
+++ b/runtime/vm/gdb_helpers.cc
@@ -46,7 +46,6 @@
   }
 }
 
-#if !defined(TARGET_ARCH_DBC)
 // Like _printDartStackTrace, but works when stopped in generated code.
 // Must be called with the current fp, sp, and pc.
 DART_EXPORT
@@ -80,7 +79,6 @@
   thread->set_execution_state(Thread::kThreadInGenerated);
   thread->set_top_exit_frame_info(0);
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 class PrintObjectPointersVisitor : public ObjectPointerVisitor {
  public:
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index aa436e1..e5ef799 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -77,12 +77,6 @@
 #define NOT_IN_PRECOMPILED(code) code
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(TARGET_ARCH_DBC)
-#define NOT_IN_DBC(code)
-#else
-#define NOT_IN_DBC(code) code
-#endif  // defined(TARGET_ARCH_DBC)
-
 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) ||                  \
     defined(TARGET_ARCH_X64)
 #define ONLY_IN_ARM_ARM64_X64(code) code
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 04bfdd1..a488807 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -188,32 +188,27 @@
   const typename KeyValueTrait::Value kNoValue =
       KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
 
-  if (array_index_ < map_.array_size_) {
-    // If we're not in the middle of a list, find the next array slot.
-    if (list_index_ == kNil) {
-      while ((array_index_ < map_.array_size_) &&
-             KeyValueTrait::ValueOf(map_.array_[array_index_].kv) == kNoValue) {
-        array_index_++;
-      }
-      if (array_index_ < map_.array_size_) {
-        // When we're done with the list, we'll continue with the next array
-        // slot.
-        const intptr_t old_array_index = array_index_;
-        array_index_++;
-        list_index_ = map_.array_[old_array_index].next;
-        return &map_.array_[old_array_index].kv;
-      } else {
-        return NULL;
-      }
-    }
-
-    // Otherwise, return the current lists_ entry, advancing list_index_.
+  // Return the current lists_ entry (if any), advancing list_index_.
+  if (list_index_ != kNil) {
     intptr_t current = list_index_;
     list_index_ = map_.lists_[current].next;
     return &map_.lists_[current].kv;
   }
 
-  return NULL;
+  // When we're done with the list, we'll continue with the next array
+  // slot.
+  while ((array_index_ < map_.array_size_) &&
+         KeyValueTrait::ValueOf(map_.array_[array_index_].kv) == kNoValue) {
+    ++array_index_;
+  }
+  if (array_index_ < map_.array_size_) {
+    const intptr_t old_array_index = array_index_;
+    ++array_index_;
+    list_index_ = map_.array_[old_array_index].next;
+    return &map_.array_[old_array_index].kv;
+  }
+
+  return nullptr;
 }
 
 template <typename KeyValueTrait, typename B, typename Allocator>
@@ -281,7 +276,9 @@
   lists_ = new_lists;
 
   if (old_lists != NULL) {
-    memmove(lists_, old_lists, old_size * sizeof(HashMapListElement));
+    for (intptr_t i = 0; i < old_size; i++) {
+      lists_[i] = old_lists[i];
+    }
   }
   for (intptr_t i = old_size; i < lists_size_; ++i) {
     lists_[i].next = free_list_head_;
@@ -383,7 +380,7 @@
 
   // Finally, iterate through the rest of the bucket to see if we can find the
   // entry that matches our key.
-  intptr_t previous;
+  intptr_t previous = -1;
   while (!KeyValueTrait::IsKeyEqual(lists_[current].kv, key)) {
     previous = current;
     current = lists_[current].next;
diff --git a/runtime/vm/hash_map_test.cc b/runtime/vm/hash_map_test.cc
index a040869..b6d6f57 100644
--- a/runtime/vm/hash_map_test.cc
+++ b/runtime/vm/hash_map_test.cc
@@ -172,6 +172,40 @@
   EXPECT(sum == 15);
 }
 
+TEST_CASE(DirectChainedHashMapIteratorWithCollisionInLastBucket) {
+  intptr_t values[] = {65,  325, 329, 73,  396, 207, 215, 93,  227, 39,
+                       431, 112, 176, 313, 188, 317, 61,  127, 447};
+  IntMap<intptr_t> map;
+
+  for (intptr_t value : values) {
+    map.Insert(value, value);
+  }
+
+  bool visited[ARRAY_SIZE(values)] = {};
+  intptr_t count = 0;
+  auto it = map.GetIterator();
+  for (auto* p = it.Next(); p != nullptr; p = it.Next()) {
+    ++count;
+    bool found = false;
+    intptr_t i = 0;
+    for (intptr_t v : values) {
+      if (v == p->key) {
+        EXPECT(v == p->value);
+        EXPECT(!visited[i]);
+        visited[i] = true;
+        found = true;
+        break;
+      }
+      ++i;
+    }
+    EXPECT(found);
+  }
+  EXPECT(count == ARRAY_SIZE(values));
+  for (bool is_visited : visited) {
+    EXPECT(is_visited);
+  }
+}
+
 TEST_CASE(CStringMap) {
   const char* const kConst1 = "test";
   const char* const kConst2 = "test 2";
diff --git a/runtime/vm/heap/freelist_test.cc b/runtime/vm/heap/freelist_test.cc
index aee898f..43349e9 100644
--- a/runtime/vm/heap/freelist_test.cc
+++ b/runtime/vm/heap/freelist_test.cc
@@ -2,8 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#include "vm/heap/freelist.h"
+#include <memory>
+
 #include "platform/assert.h"
+#include "vm/heap/freelist.h"
+#include "vm/pointer_tagging.h"
 #include "vm/unit_test.h"
 
 namespace dart {
@@ -182,4 +185,51 @@
   delete[] objects;
 }
 
+static void TestRegress38528(intptr_t header_overlap) {
+  // Test the following scenario.
+  //
+  // | <------------ free list element -----------------> |
+  // | <allocated code> | <header> | <remainder - header> | <other code> |
+  //                         ^
+  //    page boundary around here, depending on header_overlap
+  //
+  // It is important that after the allocation has been re-protected, the
+  // "<other code>" region is also still executable (and not writable).
+  std::unique_ptr<FreeList> free_list(new FreeList());
+  const uword page = VirtualMemory::PageSize();
+  std::unique_ptr<VirtualMemory> blob(
+      VirtualMemory::Allocate(2 * page,
+                              /*is_executable=*/false, NULL));
+  const intptr_t remainder_size = page / 2;
+  const intptr_t alloc_size = page - header_overlap * kObjectAlignment;
+  void* const other_code =
+      reinterpret_cast<void*>(blob->start() + alloc_size + remainder_size);
+
+  // Load a simple function into the "other code" section which just returns.
+  // This is used to ensure that it's still executable.
+#if defined(HOST_ARCH_X64) || defined(HOST_ARCH_IA32)
+  const uint8_t ret[1] = {0xC3};  // ret
+#elif defined(HOST_ARCH_ARM)
+  const uint8_t ret[4] = {0x1e, 0xff, 0x2f, 0xe1};  // bx lr
+#elif defined(HOST_ARCH_ARM64)
+  const uint8_t ret[4] = {0xc0, 0x03, 0x5f, 0xd6};  // ret
+#else
+#error "Unknown architecture."
+#endif
+  memcpy(other_code, ret, sizeof(ret));  // NOLINT
+
+  free_list->Free(blob->start(), alloc_size + remainder_size);
+  blob->Protect(VirtualMemory::kReadExecute);  // not writable
+  Allocate(free_list.get(), alloc_size, /*protected=*/true);
+  VirtualMemory::Protect(blob->address(), alloc_size,
+                         VirtualMemory::kReadExecute);
+  reinterpret_cast<void (*)()>(other_code)();
+}
+
+TEST_CASE(Regress38528) {
+  for (const intptr_t i : {-2, -1, 0, 1, 2}) {
+    TestRegress38528(i);
+  }
+}
+
 }  // namespace dart
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index 2e950e9..ae2ecce 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -192,6 +192,18 @@
     } while (raw_obj != NULL);
   }
 
+  // Races: The concurrent marker is racing with the mutator, but this race is
+  // harmless. The concurrent marker will only visit objects that were created
+  // before the marker started. It will ignore all new-space objects based on
+  // pointer alignment, and it will ignore old-space objects created after the
+  // marker started because old-space objects allocated while marking is in
+  // progress are allocated black (mark bit set). When visiting object slots,
+  // the marker can see either the value it had when marking started (because
+  // spawning the marker task creates acq-rel ordering) or any value later
+  // stored into that slot. Because pointer slots always contain pointers (i.e.,
+  // we don't do any in-place unboxing like V8), any value we read from the slot
+  // is safe.
+  NO_SANITIZE_THREAD
   void VisitPointers(RawObject** first, RawObject** last) {
     for (RawObject** current = first; current <= last; current++) {
       MarkObject(*current);
@@ -457,8 +469,7 @@
 
 void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
   for (;;) {
-    intptr_t task =
-        AtomicOperations::FetchAndDecrement(&root_slices_not_started_) - 1;
+    intptr_t task = root_slices_not_started_.fetch_sub(1) - 1;
     if (task < 0) {
       return;  // No more tasks.
     }
@@ -480,8 +491,7 @@
         UNREACHABLE();
     }
 
-    intptr_t remaining =
-        AtomicOperations::FetchAndDecrement(&root_slices_not_finished_) - 1;
+    intptr_t remaining = root_slices_not_finished_.fetch_sub(1) - 1;
     if (remaining == 0) {
       MonitorLocker ml(&root_slices_monitor_);
       ml.Notify();
diff --git a/runtime/vm/heap/marker.h b/runtime/vm/heap/marker.h
index 9216445..a929ae9 100644
--- a/runtime/vm/heap/marker.h
+++ b/runtime/vm/heap/marker.h
@@ -66,8 +66,8 @@
   MarkingVisitorBase<true>** visitors_;
 
   Monitor root_slices_monitor_;
-  intptr_t root_slices_not_started_;
-  intptr_t root_slices_not_finished_;
+  RelaxedAtomic<intptr_t> root_slices_not_started_;
+  RelaxedAtomic<intptr_t> root_slices_not_finished_;
 
   Mutex stats_mutex_;
   uintptr_t marked_bytes_;
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 17446eb..60a3fd7 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -46,11 +46,7 @@
 HeapPage* HeapPage::Allocate(intptr_t size_in_words,
                              PageType type,
                              const char* name) {
-#if defined(TARGET_ARCH_DBC)
-  bool executable = false;
-#else
-  bool executable = type == kExecutable;
-#endif
+  const bool executable = type == kExecutable;
 
   VirtualMemory* memory = VirtualMemory::AllocateAligned(
       size_in_words << kWordSizeLog2, kPageSize, executable, name);
@@ -464,8 +460,7 @@
     // Start of the newly allocated page is the allocated object.
     result = page->object_start();
     // Note: usage_.capacity_in_words is increased by AllocatePage.
-    AtomicOperations::IncrementBy(&(usage_.used_in_words),
-                                  (size >> kWordSizeLog2));
+    usage_.used_in_words += (size >> kWordSizeLog2);
     // Enqueue the remainder in the free list.
     uword free_start = result + size;
     intptr_t free_size = page->object_end() - free_start;
@@ -498,8 +493,7 @@
       result = TryAllocateInFreshPage(size, type, growth_policy, is_locked);
       // usage_ is updated by the call above.
     } else {
-      AtomicOperations::IncrementBy(&(usage_.used_in_words),
-                                    (size >> kWordSizeLog2));
+      usage_.used_in_words += (size >> kWordSizeLog2);
     }
   } else {
     // Large page allocation.
@@ -517,8 +511,7 @@
       if (page != NULL) {
         result = page->object_start();
         // Note: usage_.capacity_in_words is increased by AllocateLargePage.
-        AtomicOperations::IncrementBy(&(usage_.used_in_words),
-                                      (size >> kWordSizeLog2));
+        usage_.used_in_words += (size >> kWordSizeLog2);
       }
     }
   }
@@ -542,7 +535,7 @@
 
 void PageSpace::AllocateExternal(intptr_t cid, intptr_t size) {
   intptr_t size_in_words = size >> kWordSizeLog2;
-  AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words);
+  usage_.external_in_words += size_in_words;
   NOT_IN_PRODUCT(
       heap_->isolate()->shared_class_table()->UpdateAllocatedExternalOld(cid,
                                                                          size));
@@ -550,12 +543,12 @@
 
 void PageSpace::PromoteExternal(intptr_t cid, intptr_t size) {
   intptr_t size_in_words = size >> kWordSizeLog2;
-  AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words);
+  usage_.external_in_words += size_in_words;
 }
 
 void PageSpace::FreeExternal(intptr_t size) {
   intptr_t size_in_words = size >> kWordSizeLog2;
-  AtomicOperations::DecrementBy(&(usage_.external_in_words), size_in_words);
+  usage_.external_in_words -= size_in_words;
 }
 
 // Provides exclusive access to all pages, and ensures they are walkable.
@@ -1322,6 +1315,7 @@
   // memory->end()).
   uword offset = HeapPage::ObjectStartOffset();
   pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset);
+  ASSERT(Utils::IsAligned(pointer, kObjectAlignment));
   size += offset;
 
   VirtualMemory* memory = VirtualMemory::ForImagePage(pointer, size);
@@ -1334,7 +1328,6 @@
   page->forwarding_page_ = NULL;
   page->card_table_ = NULL;
   if (is_executable) {
-    ASSERT(Utils::IsAligned(pointer, OS::PreferredCodeAlignment()));
     page->type_ = HeapPage::kExecutable;
   } else {
     page->type_ = HeapPage::kData;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index b723b63..b9b4824 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -65,7 +65,7 @@
   void WriteProtect(bool read_only);
 
   static intptr_t ObjectStartOffset() {
-    return Utils::RoundUp(sizeof(HeapPage), OS::kMaxPreferredCodeAlignment);
+    return Utils::RoundUp(sizeof(HeapPage), kMaxObjectAlignment);
   }
 
   // Warning: This does not work for objects on image pages because image pages
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index e3be0fb..9ee2adb 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -140,11 +140,6 @@
   void VisitPointers(RawObject** first, RawObject** last) {
     ASSERT(Utils::IsAligned(first, sizeof(*first)));
     ASSERT(Utils::IsAligned(last, sizeof(*last)));
-    if (FLAG_verify_gc_contains) {
-      ASSERT((visiting_old_object_ != NULL) ||
-             scavenger_->Contains(reinterpret_cast<uword>(first)) ||
-             !heap_->Contains(reinterpret_cast<uword>(first)));
-    }
     for (RawObject** current = first; current <= last; current++) {
       ScavengePointer(current);
     }
@@ -164,11 +159,6 @@
  private:
   void UpdateStoreBuffer(RawObject** p, RawObject* obj) {
     ASSERT(obj->IsHeapObject());
-    if (FLAG_verify_gc_contains) {
-      uword ptr = reinterpret_cast<uword>(p);
-      ASSERT(!scavenger_->Contains(ptr));
-      ASSERT(heap_->DataContains(ptr));
-    }
     // If the newly written object is not a new object, drop it immediately.
     if (!obj->IsNewObject() || visiting_old_object_->IsRemembered()) {
       return;
diff --git a/runtime/vm/heap/spaces.h b/runtime/vm/heap/spaces.h
index e2737e4..2dc9a03 100644
--- a/runtime/vm/heap/spaces.h
+++ b/runtime/vm/heap/spaces.h
@@ -5,6 +5,7 @@
 #ifndef RUNTIME_VM_HEAP_SPACES_H_
 #define RUNTIME_VM_HEAP_SPACES_H_
 
+#include "platform/atomic.h"
 #include "platform/globals.h"
 
 // This file contains utilities shared by old and new space.
@@ -16,9 +17,9 @@
 class SpaceUsage {
  public:
   SpaceUsage() : capacity_in_words(0), used_in_words(0), external_in_words(0) {}
-  intptr_t capacity_in_words;
-  intptr_t used_in_words;
-  intptr_t external_in_words;
+  RelaxedAtomic<intptr_t> capacity_in_words;
+  RelaxedAtomic<intptr_t> used_in_words;
+  RelaxedAtomic<intptr_t> external_in_words;
 
   intptr_t CombinedCapacityInWords() const {
     return capacity_in_words + external_in_words;
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index cd95108..f043096 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -35,11 +35,6 @@
             "Print sizes of all instruction objects to the given file");
 #endif
 
-DEFINE_FLAG(bool,
-            trace_reused_instructions,
-            false,
-            "Print code that lacks reusable instructions");
-
 intptr_t ObjectOffsetTrait::Hashcode(Key key) {
   RawObject* obj = key;
   ASSERT(!obj->IsSmi());
@@ -82,19 +77,13 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-ImageWriter::ImageWriter(Heap* heap,
-                         const void* shared_objects,
-                         const void* shared_instructions,
-                         const void* reused_instructions)
+ImageWriter::ImageWriter(Heap* heap)
     : heap_(heap),
       next_data_offset_(0),
       next_text_offset_(0),
       objects_(),
       instructions_() {
   ResetOffsets();
-  SetupShared(&shared_objects_, shared_objects);
-  SetupShared(&shared_instructions_, shared_instructions);
-  SetupShared(&reuse_instructions_, reused_instructions);
 }
 
 void ImageWriter::PrepareForSerialization(
@@ -130,25 +119,6 @@
   }
 }
 
-void ImageWriter::SetupShared(ObjectOffsetMap* map, const void* shared_image) {
-  if (shared_image == NULL) {
-    return;
-  }
-  Image image(shared_image);
-  uword obj_addr = reinterpret_cast<uword>(image.object_start());
-  uword end_addr = obj_addr + image.object_size();
-  while (obj_addr < end_addr) {
-    int32_t offset = obj_addr - reinterpret_cast<uword>(shared_image);
-    RawObject* raw_obj = RawObject::FromAddr(obj_addr);
-    ObjectOffsetPair pair;
-    pair.object = raw_obj;
-    pair.offset = offset;
-    map->Insert(pair);
-    obj_addr += SizeInSnapshot(raw_obj);
-  }
-  ASSERT(obj_addr == end_addr);
-}
-
 int32_t ImageWriter::GetTextOffsetFor(RawInstructions* instructions,
                                       RawCode* code) {
   intptr_t offset = heap_->GetObjectId(instructions);
@@ -156,25 +126,6 @@
     return offset;
   }
 
-  if (!reuse_instructions_.IsEmpty()) {
-    ObjectOffsetPair* pair = reuse_instructions_.Lookup(instructions);
-    if (pair == NULL) {
-      // Code should have been removed by DropCodeWithoutReusableInstructions.
-      return 0;
-    }
-    ASSERT(pair->offset != 0);
-    return pair->offset;
-  }
-
-  ObjectOffsetPair* pair = shared_instructions_.Lookup(instructions);
-  if (pair != NULL) {
-    // Negative offsets tell the reader the offset is w/r/t the shared
-    // instructions image instead of the app-specific instructions image.
-    // Compare ImageReader::GetInstructionsAt.
-    ASSERT(pair->offset != 0);
-    return -pair->offset;
-  }
-
   offset = next_text_offset_;
   heap_->SetObjectId(instructions, offset);
   next_text_offset_ += SizeInSnapshot(instructions);
@@ -220,12 +171,9 @@
                         compiler::target::ObjectAlignment::kObjectAlignment);
 }
 
-static constexpr intptr_t kSimarmX64InstructionsAlignment =
-    2 * compiler::target::ObjectAlignment::kObjectAlignment;
 static intptr_t InstructionsSizeInSnapshot(intptr_t len) {
-  const intptr_t header_size = Utils::RoundUp(3 * compiler::target::kWordSize,
-                                              kSimarmX64InstructionsAlignment);
-  return header_size + Utils::RoundUp(len, kSimarmX64InstructionsAlignment);
+  return Utils::RoundUp(compiler::target::Instructions::HeaderSize() + len,
+                        compiler::target::ObjectAlignment::kObjectAlignment);
 }
 
 intptr_t ImageWriter::SizeInSnapshot(RawObject* raw_object) {
@@ -268,16 +216,6 @@
 }
 #endif  // defined(IS_SIMARM_X64)
 
-bool ImageWriter::GetSharedDataOffsetFor(RawObject* raw_object,
-                                         uint32_t* offset) {
-  ObjectOffsetPair* pair = shared_objects_.Lookup(raw_object);
-  if (pair == NULL) {
-    return false;
-  }
-  *offset = pair->offset;
-  return true;
-}
-
 uint32_t ImageWriter::GetDataOffsetFor(RawObject* raw_object) {
   intptr_t snap_size = SizeInSnapshot(raw_object);
   intptr_t offset = next_data_offset_;
@@ -399,15 +337,15 @@
 }
 
 void ImageWriter::WriteROData(WriteStream* stream) {
-  stream->Align(OS::kMaxPreferredCodeAlignment);
+  stream->Align(kMaxObjectAlignment);
 
   // Heap page starts here.
 
   intptr_t section_start = stream->Position();
 
   stream->WriteWord(next_data_offset_);  // Data length.
-  COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
-  stream->Align(OS::kMaxPreferredCodeAlignment);
+  COMPILE_ASSERT(kMaxObjectAlignment >= kObjectAlignment);
+  stream->Align(kMaxObjectAlignment);
 
   ASSERT(stream->Position() - section_start == Image::kHeaderSize);
 
@@ -503,10 +441,8 @@
 
 AssemblyImageWriter::AssemblyImageWriter(Thread* thread,
                                          Dart_StreamingWriteCallback callback,
-                                         void* callback_data,
-                                         const void* shared_objects,
-                                         const void* shared_instructions)
-    : ImageWriter(thread->heap(), shared_objects, shared_instructions, nullptr),
+                                         void* callback_data)
+    : ImageWriter(thread->heap()),
       assembly_stream_(512 * KB, callback, callback_data),
       dwarf_(nullptr) {
 #if defined(DART_PRECOMPILER)
@@ -521,6 +457,7 @@
 #endif
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 static void EnsureAssemblerIdentifier(char* label) {
   for (char c = *label; c != '\0'; c = *++label) {
     if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
@@ -531,8 +468,8 @@
   }
 }
 
-const char* NameOfStubIsolateSpecificStub(ObjectStore* object_store,
-                                          const Code& code) {
+static const char* NameOfStubIsolateSpecificStub(ObjectStore* object_store,
+                                                 const Code& code) {
   if (code.raw() == object_store->build_method_extractor_code()) {
     return "_iso_stub_BuildMethodExtractorStub";
   } else if (code.raw() == object_store->null_error_stub_with_fpu_regs_stub()) {
@@ -553,8 +490,46 @@
   }
   return nullptr;
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+const char* AssemblyCodeNamer::AssemblyNameFor(intptr_t code_index,
+                                               const Code& code) {
+  ASSERT(!code.IsNull());
+  owner_ = code.owner();
+  if (owner_.IsNull()) {
+    insns_ = code.instructions();
+    const char* name = StubCode::NameOfStub(insns_.EntryPoint());
+    if (name != nullptr) {
+      return OS::SCreate(zone_, "Precompiled_Stub_%s", name);
+    } else {
+      if (name == nullptr) {
+        name = NameOfStubIsolateSpecificStub(store_, code);
+      }
+      ASSERT(name != nullptr);
+      return OS::SCreate(zone_, "Precompiled__%s", name);
+    }
+  } else if (owner_.IsClass()) {
+    string_ = Class::Cast(owner_).Name();
+    const char* name = string_.ToCString();
+    EnsureAssemblerIdentifier(const_cast<char*>(name));
+    return OS::SCreate(zone_, "Precompiled_AllocationStub_%s_%" Pd, name,
+                       code_index);
+  } else if (owner_.IsAbstractType()) {
+    const char* name = namer_.StubNameForType(AbstractType::Cast(owner_));
+    return OS::SCreate(zone_, "Precompiled_%s", name);
+  } else if (owner_.IsFunction()) {
+    const char* name = Function::Cast(owner_).ToQualifiedCString();
+    EnsureAssemblerIdentifier(const_cast<char*>(name));
+    return OS::SCreate(zone_, "Precompiled_%s_%" Pd, name, code_index);
+  } else {
+    UNREACHABLE();
+  }
+}
 
 void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  UNREACHABLE();
+#else
   Zone* zone = Thread::Current()->zone();
 
 #if defined(DART_PRECOMPILER)
@@ -568,7 +543,7 @@
   assembly_stream_.Print(".globl %s\n", instructions_symbol);
 
   // Start snapshot at page boundary.
-  ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
+  ASSERT(VirtualMemory::PageSize() >= kMaxObjectAlignment);
   assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
   assembly_stream_.Print("%s:\n", instructions_symbol);
 
@@ -591,13 +566,8 @@
 
   FrameUnwindPrologue();
 
-  Object& owner = Object::Handle(zone);
-  String& str = String::Handle(zone);
   PcDescriptors& descriptors = PcDescriptors::Handle(zone);
-
-  ObjectStore* object_store = Isolate::Current()->object_store();
-
-  TypeTestingStubNamer tts;
+  AssemblyCodeNamer namer(zone);
   intptr_t text_offset = 0;
 
   ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
@@ -639,9 +609,8 @@
                                         SizeInSnapshot(insns.raw()));
     }
 
-    ASSERT(insns.raw()->HeapSize() % sizeof(uint64_t) == 0);
-
-    // 1. Write from the header to the entry point.
+    // 1. Write from the object start to the payload start. This includes the
+    // object header and the fixed fields.
     {
       NoSafepointScope no_safepoint;
 
@@ -667,83 +636,48 @@
       text_offset += sizeof(compiler::target::uword);
       WriteWordLiteralText(insns.raw_ptr()->unchecked_entrypoint_pc_offset_);
       text_offset += sizeof(compiler::target::uword);
-      WriteWordLiteralText(0);
-      text_offset += sizeof(compiler::target::uword);
 #else   // defined(IS_SIMARM_X64)
-      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
-      uword entry = beginning + Instructions::HeaderSize();
+      uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
+      uword payload_start = insns.PayloadStart();
       WriteWordLiteralText(marked_tags);
-      beginning += sizeof(uword);
+      object_start += sizeof(uword);
       text_offset += sizeof(uword);
-      text_offset += WriteByteSequence(beginning, entry);
+      text_offset += WriteByteSequence(object_start, payload_start);
 #endif  // defined(IS_SIMARM_X64)
 
       ASSERT((text_offset - instr_start) ==
              compiler::target::Instructions::HeaderSize());
     }
 
-    // 2. Write a label at the entry point.
-    // Linux's perf uses these labels.
-    ASSERT(!code.IsNull());
-    owner = code.owner();
-    if (owner.IsNull()) {
-      const char* name = StubCode::NameOfStub(insns.EntryPoint());
-      if (name != nullptr) {
-        assembly_stream_.Print("Precompiled_Stub_%s:\n", name);
-      } else {
-        if (name == nullptr) {
-          name = NameOfStubIsolateSpecificStub(object_store, code);
-        }
-        ASSERT(name != nullptr);
-        assembly_stream_.Print("Precompiled__%s:\n", name);
-      }
-    } else if (owner.IsClass()) {
-      str = Class::Cast(owner).Name();
-      const char* name = str.ToCString();
-      EnsureAssemblerIdentifier(const_cast<char*>(name));
-      assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name,
-                             i);
-    } else if (owner.IsAbstractType()) {
-      const char* name = tts.StubNameForType(AbstractType::Cast(owner));
-      assembly_stream_.Print("Precompiled_%s:\n", name);
-    } else if (owner.IsFunction()) {
-      const char* name = Function::Cast(owner).ToQualifiedCString();
-      EnsureAssemblerIdentifier(const_cast<char*>(name));
-      assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
-    } else {
-      UNREACHABLE();
-    }
-
+    intptr_t dwarf_index = i;
 #ifdef DART_PRECOMPILER
     // Create a label for use by DWARF.
     if ((dwarf_ != nullptr) && !code.IsNull()) {
-      const intptr_t dwarf_index = dwarf_->AddCode(code);
-      assembly_stream_.Print(".Lcode%" Pd ":\n", dwarf_index);
+      dwarf_index = dwarf_->AddCode(code);
     }
 #endif
+    // 2. Write a label at the entry point.
+    // Linux's perf uses these labels.
+    assembly_stream_.Print("%s:\n", namer.AssemblyNameFor(dwarf_index, code));
 
     {
-      // 3. Write from the entry point to the end.
+      // 3. Write from the payload start to payload end.
       NoSafepointScope no_safepoint;
-      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
-      uword entry = beginning + Instructions::HeaderSize();
-      uword payload_size = insns.raw()->HeapSize() - insns.HeaderSize();
-      uword end = entry + payload_size;
-
-      ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
-      ASSERT(Utils::IsAligned(entry, sizeof(uword)));
-      ASSERT(Utils::IsAligned(end, sizeof(uword)));
+      const uword payload_start = insns.PayloadStart();
+      const uword payload_size =
+          Utils::RoundUp(insns.Size(), sizeof(compiler::target::uword));
+      const uword payload_end = payload_start + payload_size;
 
 #if defined(DART_PRECOMPILER)
       PcDescriptors::Iterator iterator(descriptors,
                                        RawPcDescriptors::kBSSRelocation);
       uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
 
-      for (uword cursor = entry; cursor < end;
+      for (uword cursor = payload_start; cursor < payload_end;
            cursor += sizeof(compiler::target::uword)) {
         compiler::target::uword data =
             *reinterpret_cast<compiler::target::uword*>(cursor);
-        if ((cursor - entry) == next_reloc_offset) {
+        if ((cursor - payload_start) == next_reloc_offset) {
           assembly_stream_.Print("%s %s - (.) + %" Pd "\n", kLiteralPrefix,
                                  bss_symbol, /*addend=*/data);
           next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
@@ -751,13 +685,31 @@
           WriteWordLiteralText(data);
         }
       }
-      text_offset += end - entry;
+      text_offset += payload_size;
 #else
-      text_offset += WriteByteSequence(entry, end);
+      text_offset += WriteByteSequence(payload_start, payload_end);
 #endif
+
+      // 4. Write from the payload end to object end. Note we can't simply copy
+      // from the object because the host object may have less alignment filler
+      // than the target object in the cross-word case.
+      uword unaligned_size =
+          compiler::target::Instructions::HeaderSize() + payload_size;
+      uword alignment_size =
+          Utils::RoundUp(unaligned_size,
+                         compiler::target::ObjectAlignment::kObjectAlignment) -
+          unaligned_size;
+      while (alignment_size > 0) {
+        WriteWordLiteralText(compiler::Assembler::GetBreakInstructionFiller());
+        alignment_size -= sizeof(compiler::target::uword);
+        text_offset += sizeof(compiler::target::uword);
+      }
+
       ASSERT(kWordSize != compiler::target::kWordSize ||
              (text_offset - instr_start) == insns.raw()->HeapSize());
     }
+
+    ASSERT((text_offset - instr_start) == SizeInSnapshot(insns.raw()));
   }
 
   FrameUnwindEpilogue();
@@ -784,12 +736,12 @@
   const char* data_symbol =
       vm ? "_kDartVmSnapshotData" : "_kDartIsolateSnapshotData";
   assembly_stream_.Print(".globl %s\n", data_symbol);
-  assembly_stream_.Print(".balign %" Pd ", 0\n",
-                         OS::kMaxPreferredCodeAlignment);
+  assembly_stream_.Print(".balign %" Pd ", 0\n", kMaxObjectAlignment);
   assembly_stream_.Print("%s:\n", data_symbol);
   uword buffer = reinterpret_cast<uword>(clustered_stream->buffer());
   intptr_t length = clustered_stream->bytes_written();
   WriteByteSequence(buffer, buffer + length);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 void AssemblyImageWriter::FrameUnwindPrologue() {
@@ -881,15 +833,9 @@
                                  uint8_t** instructions_blob_buffer,
                                  ReAlloc alloc,
                                  intptr_t initial_size,
-                                 const void* shared_objects,
-                                 const void* shared_instructions,
-                                 const void* reused_instructions,
                                  Elf* elf,
                                  Dwarf* dwarf)
-    : ImageWriter(thread->heap(),
-                  shared_objects,
-                  shared_instructions,
-                  reused_instructions),
+    : ImageWriter(thread->heap()),
       instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
       elf_(elf),
       dwarf_(dwarf) {
@@ -942,6 +888,7 @@
 
 #if defined(DART_PRECOMPILER)
   PcDescriptors& descriptors = PcDescriptors::Handle();
+  AssemblyCodeNamer namer(Thread::Current()->zone());
 #endif
 
   NoSafepointScope no_safepoint;
@@ -964,14 +911,16 @@
     const Instructions& insns = *instructions_[i].insns_;
     AutoTraceImage(insns, 0, &this->instructions_blob_stream_);
 
-    uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
-    uword entry = beginning + Instructions::HeaderSize();
-    uword payload_size = insns.Size();
-    payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment());
-    uword end = entry + payload_size;
+    uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
+    uword payload_start = insns.PayloadStart();
+    uword payload_size =
+        Utils::RoundUp(
+            compiler::target::Instructions::HeaderSize() + insns.Size(),
+            compiler::target::ObjectAlignment::kObjectAlignment) -
+        compiler::target::Instructions::HeaderSize();
+    uword object_end = payload_start + payload_size;
 
-    ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
-    ASSERT(Utils::IsAligned(entry, sizeof(uword)));
+    ASSERT(Utils::IsAligned(payload_start, sizeof(uword)));
 
 #ifdef DART_PRECOMPILER
     const Code& code = *instructions_[i].code_;
@@ -1005,25 +954,32 @@
         insns.raw_ptr()->size_and_flags_);
     instructions_blob_stream_.WriteFixed<uint32_t>(
         insns.raw_ptr()->unchecked_entrypoint_pc_offset_);
-    instructions_blob_stream_.Align(kSimarmX64InstructionsAlignment);
     payload_stream_start = instructions_blob_stream_.Position();
     instructions_blob_stream_.WriteBytes(
         reinterpret_cast<const void*>(insns.PayloadStart()), insns.Size());
-    instructions_blob_stream_.Align(kSimarmX64InstructionsAlignment);
+    instructions_blob_stream_.Align(
+        compiler::target::ObjectAlignment::kObjectAlignment);
     const intptr_t end_offset = instructions_blob_stream_.bytes_written();
     text_offset += (end_offset - start_offset);
-    USE(end);
+    USE(object_start);
+    USE(object_end);
 #else   // defined(IS_SIMARM_X64)
     payload_stream_start = instructions_blob_stream_.Position() +
-                           (insns.PayloadStart() - beginning);
+                           (insns.PayloadStart() - object_start);
 
     instructions_blob_stream_.WriteWord(marked_tags);
     text_offset += sizeof(uword);
-    beginning += sizeof(uword);
-    text_offset += WriteByteSequence(beginning, end);
+    object_start += sizeof(uword);
+    text_offset += WriteByteSequence(object_start, object_end);
 #endif  // defined(IS_SIMARM_X64)
 
 #if defined(DART_PRECOMPILER)
+    if (elf_ != nullptr && dwarf_ != nullptr) {
+      elf_->AddStaticSymbol(elf_->NextSectionIndex(),
+                            namer.AssemblyNameFor(i, code),
+                            segment_base + payload_stream_start);
+    }
+
     // Don't patch the relocation if we're not generating ELF. The regular blobs
     // format does not yet support these relocations. Use
     // Code::VerifyBSSRelocations to check whether the relocations are patched
@@ -1061,6 +1017,8 @@
       // Restore stream position after the relocation was patched.
       instructions_blob_stream_.SetPosition(current_stream_position);
     }
+#else
+    USE(payload_stream_start);
 #endif
 
     ASSERT((text_offset - instr_start) ==
@@ -1087,23 +1045,15 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 ImageReader::ImageReader(const uint8_t* data_image,
-                         const uint8_t* instructions_image,
-                         const uint8_t* shared_data_image,
-                         const uint8_t* shared_instructions_image)
-    : data_image_(data_image),
-      instructions_image_(instructions_image),
-      shared_data_image_(shared_data_image),
-      shared_instructions_image_(shared_instructions_image) {
+                         const uint8_t* instructions_image)
+    : data_image_(data_image), instructions_image_(instructions_image) {
   ASSERT(data_image != NULL);
   ASSERT(instructions_image != NULL);
 }
 
 RawApiError* ImageReader::VerifyAlignment() const {
   if (!Utils::IsAligned(data_image_, kObjectAlignment) ||
-      !Utils::IsAligned(shared_data_image_, kObjectAlignment) ||
-      !Utils::IsAligned(instructions_image_, OS::PreferredCodeAlignment()) ||
-      !Utils::IsAligned(shared_instructions_image_,
-                        OS::PreferredCodeAlignment())) {
+      !Utils::IsAligned(instructions_image_, kMaxObjectAlignment)) {
     return ApiError::New(
         String::Handle(String::New("Snapshot is misaligned", Heap::kOld)),
         Heap::kOld);
@@ -1111,17 +1061,11 @@
   return ApiError::null();
 }
 
-RawInstructions* ImageReader::GetInstructionsAt(int32_t offset) const {
-  ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
+RawInstructions* ImageReader::GetInstructionsAt(uint32_t offset) const {
+  ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
-  RawObject* result;
-  if (offset < 0) {
-    result = RawObject::FromAddr(
-        reinterpret_cast<uword>(shared_instructions_image_) - offset);
-  } else {
-    result = RawObject::FromAddr(reinterpret_cast<uword>(instructions_image_) +
-                                 offset);
-  }
+  RawObject* result = RawObject::FromAddr(
+      reinterpret_cast<uword>(instructions_image_) + offset);
   ASSERT(result->IsInstructions());
   ASSERT(result->IsMarked());
 
@@ -1138,116 +1082,4 @@
   return result;
 }
 
-RawObject* ImageReader::GetSharedObjectAt(uint32_t offset) const {
-  ASSERT(Utils::IsAligned(offset, kObjectAlignment));
-
-  RawObject* result =
-      RawObject::FromAddr(reinterpret_cast<uword>(shared_data_image_) + offset);
-  ASSERT(result->IsMarked());
-
-  return result;
-}
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-void DropCodeWithoutReusableInstructions(const void* reused_instructions) {
-  class DropCodeVisitor : public FunctionVisitor, public ClassVisitor {
-   public:
-    explicit DropCodeVisitor(const void* reused_instructions)
-        : code_(Code::Handle()),
-          instructions_(Instructions::Handle()),
-          pool_(ObjectPool::Handle()),
-          table_(Array::Handle()),
-          entry_(Object::Handle()) {
-      ImageWriter::SetupShared(&reused_instructions_, reused_instructions);
-      if (FLAG_trace_reused_instructions) {
-        OS::PrintErr("%" Pd " reusable instructions\n",
-                     reused_instructions_.Size());
-      }
-    }
-
-    void Visit(const Class& cls) {
-      code_ = cls.allocation_stub();
-      if (!code_.IsNull()) {
-        if (!CanKeep(code_)) {
-          if (FLAG_trace_reused_instructions) {
-            OS::PrintErr("No reusable instructions for %s\n", cls.ToCString());
-          }
-          cls.DisableAllocationStub();
-        }
-      }
-    }
-
-    void Visit(const Function& func) {
-      if (func.HasCode()) {
-        code_ = func.CurrentCode();
-        if (!CanKeep(code_)) {
-          if (FLAG_trace_reused_instructions) {
-            OS::PrintErr("No reusable instructions for %s\n", func.ToCString());
-          }
-          func.ClearCode();
-          func.ClearICDataArray();
-          return;
-        }
-      }
-      code_ = func.unoptimized_code();
-      if (!code_.IsNull() && !CanKeep(code_)) {
-        if (FLAG_trace_reused_instructions) {
-          OS::PrintErr("No reusable instructions for %s\n", func.ToCString());
-        }
-        func.ClearCode();
-        func.ClearICDataArray();
-      }
-    }
-
-    bool CanKeep(const Code& code) {
-      if (!IsAvailable(code)) {
-        return false;
-      }
-
-      pool_ = code.object_pool();
-      for (intptr_t i = 0; i < pool_.Length(); i++) {
-        if (pool_.TypeAt(i) == ObjectPool::EntryType::kTaggedObject) {
-          entry_ = pool_.ObjectAt(i);
-          if (entry_.IsCode() && !IsAvailable(Code::Cast(entry_))) {
-            return false;
-          }
-        }
-      }
-
-      table_ = code.static_calls_target_table();
-      if (!table_.IsNull()) {
-        StaticCallsTable static_calls(table_);
-        for (auto& view : static_calls) {
-          entry_ = view.Get<Code::kSCallTableCodeTarget>();
-          if (entry_.IsCode() && !IsAvailable(Code::Cast(entry_))) {
-            return false;
-          }
-        }
-      }
-
-      return true;
-    }
-
-   private:
-    bool IsAvailable(const Code& code) {
-      ObjectOffsetPair* pair = reused_instructions_.Lookup(code.instructions());
-      return pair != NULL;
-    }
-
-    ObjectOffsetMap reused_instructions_;
-    Code& code_;
-    Instructions& instructions_;
-    ObjectPool& pool_;
-    Array& table_;
-    Object& entry_;
-
-    DISALLOW_COPY_AND_ASSIGN(DropCodeVisitor);
-  };
-
-  DropCodeVisitor visitor(reused_instructions);
-  ProgramVisitor::VisitClasses(&visitor);
-  ProgramVisitor::VisitFunctions(&visitor);
-}
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
 }  // namespace dart
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index deb94ef..7835778 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -17,6 +17,7 @@
 #include "vm/hash_map.h"
 #include "vm/object.h"
 #include "vm/reusable_handles.h"
+#include "vm/type_testing_stubs.h"
 #include "vm/v8_snapshot_writer.h"
 
 namespace dart {
@@ -35,7 +36,7 @@
 class Image : ValueObject {
  public:
   explicit Image(const void* raw_memory) : raw_memory_(raw_memory) {
-    ASSERT(Utils::IsAligned(raw_memory, OS::kMaxPreferredCodeAlignment));
+    ASSERT(Utils::IsAligned(raw_memory, kMaxObjectAlignment));
   }
 
   void* object_start() const {
@@ -53,7 +54,8 @@
   }
 
   static constexpr intptr_t kHeaderFields = 2;
-  static const intptr_t kHeaderSize = OS::kMaxPreferredCodeAlignment;
+  static constexpr intptr_t kHeaderSize = kMaxObjectAlignment;
+  COMPILE_ASSERT((kHeaderFields * compiler::target::kWordSize) <= kHeaderSize);
 
  private:
   const void* raw_memory_;  // The symbol kInstructionsSnapshot.
@@ -63,22 +65,16 @@
 
 class ImageReader : public ZoneAllocated {
  public:
-  ImageReader(const uint8_t* data_image,
-              const uint8_t* instructions_image,
-              const uint8_t* shared_data_image,
-              const uint8_t* shared_instructions_image);
+  ImageReader(const uint8_t* data_image, const uint8_t* instructions_image);
 
   RawApiError* VerifyAlignment() const;
 
-  RawInstructions* GetInstructionsAt(int32_t offset) const;
+  RawInstructions* GetInstructionsAt(uint32_t offset) const;
   RawObject* GetObjectAt(uint32_t offset) const;
-  RawObject* GetSharedObjectAt(uint32_t offset) const;
 
  private:
   const uint8_t* data_image_;
   const uint8_t* instructions_image_;
-  const uint8_t* shared_data_image_;
-  const uint8_t* shared_instructions_image_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageReader);
 };
@@ -151,13 +147,9 @@
 
 class ImageWriter : public ValueObject {
  public:
-  ImageWriter(Heap* heap,
-              const void* shared_objects,
-              const void* shared_instructions,
-              const void* reused_instructions);
+  explicit ImageWriter(Heap* heap);
   virtual ~ImageWriter() {}
 
-  static void SetupShared(ObjectOffsetMap* map, const void* shared_image);
   void ResetOffsets() {
     next_data_offset_ = Image::kHeaderSize;
     next_text_offset_ = Image::kHeaderSize;
@@ -170,7 +162,6 @@
   void PrepareForSerialization(GrowableArray<ImageWriterCommand>* commands);
 
   int32_t GetTextOffsetFor(RawInstructions* instructions, RawCode* code);
-  bool GetSharedDataOffsetFor(RawObject* raw_object, uint32_t* offset);
   uint32_t GetDataOffsetFor(RawObject* raw_object);
 
   void Write(WriteStream* clustered_stream, bool vm);
@@ -243,9 +234,6 @@
   intptr_t next_text_offset_;
   GrowableArray<ObjectData> objects_;
   GrowableArray<InstructionsData> instructions_;
-  ObjectOffsetMap shared_objects_;
-  ObjectOffsetMap shared_instructions_;
-  ObjectOffsetMap reuse_instructions_;
 
   V8SnapshotProfileWriter::IdSpace offset_space_ =
       V8SnapshotProfileWriter::kSnapshot;
@@ -304,13 +292,33 @@
   intptr_t start_offset_;
 };
 
+class AssemblyCodeNamer {
+ public:
+  explicit AssemblyCodeNamer(Zone* zone)
+      : zone_(zone),
+        owner_(Object::Handle(zone)),
+        string_(String::Handle(zone)),
+        insns_(Instructions::Handle(zone)),
+        store_(Isolate::Current()->object_store()) {}
+
+  const char* StubNameForType(const AbstractType& type) const;
+
+  const char* AssemblyNameFor(intptr_t code_index, const Code& code);
+
+ private:
+  Zone* const zone_;
+  Object& owner_;
+  String& string_;
+  Instructions& insns_;
+  ObjectStore* const store_;
+  TypeTestingStubNamer namer_;
+};
+
 class AssemblyImageWriter : public ImageWriter {
  public:
   AssemblyImageWriter(Thread* thread,
                       Dart_StreamingWriteCallback callback,
-                      void* callback_data,
-                      const void* shared_objects,
-                      const void* shared_instructions);
+                      void* callback_data);
   void Finalize();
 
   virtual void WriteText(WriteStream* clustered_stream, bool vm);
@@ -347,9 +355,6 @@
                   uint8_t** instructions_blob_buffer,
                   ReAlloc alloc,
                   intptr_t initial_size,
-                  const void* shared_objects,
-                  const void* shared_instructions,
-                  const void* reused_instructions,
                   Elf* elf = nullptr,
                   Dwarf* dwarf = nullptr);
 
@@ -369,8 +374,6 @@
   DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
 };
 
-void DropCodeWithoutReusableInstructions(const void* reused_instructions);
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_IMAGE_SNAPSHOT_H_
diff --git a/runtime/vm/instructions.h b/runtime/vm/instructions.h
index eb39a5d..76b929d 100644
--- a/runtime/vm/instructions.h
+++ b/runtime/vm/instructions.h
@@ -15,8 +15,6 @@
 #include "vm/instructions_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/instructions_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/instructions_dbc.h"
 #else
 #error Unknown architecture.
 #endif
@@ -28,7 +26,7 @@
 
 bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj);
 
-#if !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC)
+#if !defined(TARGET_ARCH_IA32)
 
 class TypeTestingStubCallPattern : public ValueObject {
  public:
@@ -40,7 +38,7 @@
   const uword pc_;
 };
 
-#endif  // !defined(TARGET_ARCH_IA32) && !defined(TARGET_ARCH_DBC)
+#endif  // !defined(TARGET_ARCH_IA32)
 
 }  // namespace dart
 
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc
index c2be95c..2dab069 100644
--- a/runtime/vm/instructions_arm.cc
+++ b/runtime/vm/instructions_arm.cc
@@ -121,7 +121,7 @@
   int32_t instr = Instr::At(start)->InstructionBits();
   intptr_t imm = 0;
   const ARMVersion version = TargetCPUFeatures::arm_version();
-  if ((version == ARMv5TE) || (version == ARMv6)) {
+  if (version == ARMv6) {
     ASSERT((instr & 0xfff00000) == 0xe3800000);  // orr rd, rd, byte0
     imm |= (instr & 0x000000ff);
 
@@ -370,7 +370,7 @@
                         B21 | (0xfff << 8) | B4 |
                         (static_cast<int32_t>(LR) << kRmShift);
   const ARMVersion version = TargetCPUFeatures::arm_version();
-  if ((version == ARMv5TE) || (version == ARMv6)) {
+  if (version == ARMv6) {
     return bx_lr->InstructionBits() == instruction;
   } else {
     ASSERT(version == ARMv7);
diff --git a/runtime/vm/instructions_dbc.cc b/runtime/vm/instructions_dbc.cc
deleted file mode 100644
index 6d5280b..0000000
--- a/runtime/vm/instructions_dbc.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-// 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.
-
-#include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/instructions.h"
-#include "vm/instructions_dbc.h"
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/constants_dbc.h"
-#include "vm/cpu.h"
-#include "vm/object.h"
-
-namespace dart {
-
-static bool HasLoadFromPool(Instr instr) {
-  switch (SimulatorBytecode::DecodeOpcode(instr)) {
-    case SimulatorBytecode::kLoadConstant:
-    case SimulatorBytecode::kPushConstant:
-    case SimulatorBytecode::kStaticCall:
-    case SimulatorBytecode::kIndirectStaticCall:
-    case SimulatorBytecode::kInstanceCall1:
-    case SimulatorBytecode::kInstanceCall2:
-    case SimulatorBytecode::kInstanceCall1Opt:
-    case SimulatorBytecode::kInstanceCall2Opt:
-    case SimulatorBytecode::kStoreStaticTOS:
-    case SimulatorBytecode::kPushStatic:
-    case SimulatorBytecode::kAllocate:
-    case SimulatorBytecode::kInstantiateType:
-    case SimulatorBytecode::kInstantiateTypeArgumentsTOS:
-    case SimulatorBytecode::kAssertAssignable:
-      return true;
-    default:
-      return false;
-  }
-}
-
-static bool GetLoadedObjectAt(uword pc,
-                              const ObjectPool& object_pool,
-                              Object* obj) {
-  Instr instr = SimulatorBytecode::At(pc);
-  if (HasLoadFromPool(instr)) {
-    uint16_t index = SimulatorBytecode::DecodeD(instr);
-    if (object_pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
-      *obj = object_pool.ObjectAt(index);
-      return true;
-    }
-  }
-  return false;
-}
-
-CallPattern::CallPattern(uword pc, const Code& code)
-    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
-      end_(pc),
-      data_pool_index_(-1),
-      target_pool_index_(-1) {
-  ASSERT(code.ContainsInstructionAt(end_));
-  const uword call_pc = end_ - sizeof(Instr);
-  Instr call_instr = SimulatorBytecode::At(call_pc);
-  ASSERT(SimulatorBytecode::IsCallOpcode(call_instr));
-  data_pool_index_ = SimulatorBytecode::DecodeD(call_instr);
-  target_pool_index_ = SimulatorBytecode::DecodeD(call_instr);
-}
-
-NativeCallPattern::NativeCallPattern(uword pc, const Code& code)
-    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
-      end_(pc),
-      native_function_pool_index_(-1),
-      trampoline_pool_index_(-1) {
-  ASSERT(code.ContainsInstructionAt(end_));
-  const uword call_pc = end_ - sizeof(Instr);
-  Instr call_instr = SimulatorBytecode::At(call_pc);
-  ASSERT(SimulatorBytecode::DecodeOpcode(call_instr) ==
-         SimulatorBytecode::kNativeCall);
-  native_function_pool_index_ = SimulatorBytecode::DecodeB(call_instr);
-  trampoline_pool_index_ = SimulatorBytecode::DecodeA(call_instr);
-}
-
-NativeFunctionWrapper NativeCallPattern::target() const {
-  return reinterpret_cast<NativeFunctionWrapper>(
-      object_pool_.ObjectAt(trampoline_pool_index_));
-}
-
-void NativeCallPattern::set_target(NativeFunctionWrapper new_target) const {
-  object_pool_.SetRawValueAt(trampoline_pool_index_,
-                             reinterpret_cast<uword>(new_target));
-  // No need to flush the instruction cache, since the code is not modified.
-}
-
-NativeFunction NativeCallPattern::native_function() const {
-  return reinterpret_cast<NativeFunction>(
-      object_pool_.RawValueAt(native_function_pool_index_));
-}
-
-void NativeCallPattern::set_native_function(NativeFunction func) const {
-  object_pool_.SetRawValueAt(native_function_pool_index_,
-                             reinterpret_cast<uword>(func));
-}
-
-// Decodes a load sequence ending at 'end' (the last instruction of the load
-// sequence is the instruction before the one at end).  Returns a pointer to
-// the first instruction in the sequence.  Returns the register being loaded
-// and the loaded object in the output parameters 'reg' and 'obj'
-// respectively.
-uword InstructionPattern::DecodeLoadObject(uword end,
-                                           const ObjectPool& object_pool,
-                                           Register* reg,
-                                           Object* obj) {
-  UNIMPLEMENTED();
-  return 0;
-}
-
-// Decodes a load sequence ending at 'end' (the last instruction of the load
-// sequence is the instruction before the one at end).  Returns a pointer to
-// the first instruction in the sequence.  Returns the register being loaded
-// and the loaded immediate value in the output parameters 'reg' and 'value'
-// respectively.
-uword InstructionPattern::DecodeLoadWordImmediate(uword end,
-                                                  Register* reg,
-                                                  intptr_t* value) {
-  UNIMPLEMENTED();
-  return 0;
-}
-
-// Decodes a load sequence ending at 'end' (the last instruction of the load
-// sequence is the instruction before the one at end).  Returns a pointer to
-// the first instruction in the sequence.  Returns the register being loaded
-// and the index in the pool being read from in the output parameters 'reg'
-// and 'index' respectively.
-uword InstructionPattern::DecodeLoadWordFromPool(uword end,
-                                                 Register* reg,
-                                                 intptr_t* index) {
-  UNIMPLEMENTED();
-  return 0;
-}
-
-bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) {
-  ASSERT(code.ContainsInstructionAt(pc));
-  const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
-  return GetLoadedObjectAt(pc, pool, obj);
-}
-
-RawObject* CallPattern::Data() const {
-  return object_pool_.ObjectAt(data_pool_index_);
-}
-
-void CallPattern::SetData(const Object& data) const {
-  object_pool_.SetObjectAt(data_pool_index_, data);
-}
-
-RawCode* CallPattern::TargetCode() const {
-  return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_pool_index_));
-}
-
-void CallPattern::SetTargetCode(const Code& target) const {
-  object_pool_.SetObjectAt(target_pool_index_, target);
-}
-
-void CallPattern::InsertDeoptCallAt(uword pc) {
-  const uint8_t argc =
-      SimulatorBytecode::IsCallOpcode(SimulatorBytecode::At(pc))
-          ? SimulatorBytecode::DecodeArgc(SimulatorBytecode::At(pc))
-          : 0;
-  *reinterpret_cast<Instr*>(pc) =
-      SimulatorBytecode::Encode(SimulatorBytecode::kDeopt, argc, 0);
-}
-
-SwitchableCallPattern::SwitchableCallPattern(uword pc, const Code& code)
-    : object_pool_(ObjectPool::Handle(code.GetObjectPool())),
-      data_pool_index_(-1),
-      target_pool_index_(-1) {
-  UNIMPLEMENTED();
-}
-
-RawObject* SwitchableCallPattern::data() const {
-  return object_pool_.ObjectAt(data_pool_index_);
-}
-
-RawCode* SwitchableCallPattern::target() const {
-  return reinterpret_cast<RawCode*>(object_pool_.ObjectAt(target_pool_index_));
-}
-
-void SwitchableCallPattern::SetData(const Object& data) const {
-  ASSERT(!Object::Handle(object_pool_.ObjectAt(data_pool_index_)).IsCode());
-  object_pool_.SetObjectAt(data_pool_index_, data);
-}
-
-void SwitchableCallPattern::SetTarget(const Code& target) const {
-  ASSERT(Object::Handle(object_pool_.ObjectAt(target_pool_index_)).IsCode());
-  object_pool_.SetObjectAt(target_pool_index_, target);
-}
-
-ReturnPattern::ReturnPattern(uword pc) : pc_(pc) {
-  USE(pc_);
-}
-
-bool ReturnPattern::IsValid() const {
-  UNIMPLEMENTED();
-  return false;
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/instructions_dbc.h b/runtime/vm/instructions_dbc.h
deleted file mode 100644
index 3d465fa..0000000
--- a/runtime/vm/instructions_dbc.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// 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.
-// Classes that describe assembly patterns as used by inline caches.
-
-#ifndef RUNTIME_VM_INSTRUCTIONS_DBC_H_
-#define RUNTIME_VM_INSTRUCTIONS_DBC_H_
-
-#ifndef RUNTIME_VM_INSTRUCTIONS_H_
-#error Do not include instructions_dbc.h directly; use instructions.h instead.
-#endif
-
-#include "vm/constants_dbc.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-
-namespace dart {
-
-class InstructionPattern : public AllStatic {
- public:
-  // Decodes a load sequence ending at 'end' (the last instruction of the
-  // load sequence is the instruction before the one at end).  Returns the
-  // address of the first instruction in the sequence.  Returns the register
-  // being loaded and the loaded object in the output parameters 'reg' and
-  // 'obj' respectively.
-  static uword DecodeLoadObject(uword end,
-                                const ObjectPool& object_pool,
-                                Register* reg,
-                                Object* obj);
-
-  // Decodes a load sequence ending at 'end' (the last instruction of the
-  // load sequence is the instruction before the one at end).  Returns the
-  // address of the first instruction in the sequence.  Returns the register
-  // being loaded and the loaded immediate value in the output parameters
-  // 'reg' and 'value' respectively.
-  static uword DecodeLoadWordImmediate(uword end,
-                                       Register* reg,
-                                       intptr_t* value);
-
-  // Decodes a load sequence ending at 'end' (the last instruction of the
-  // load sequence is the instruction before the one at end).  Returns the
-  // address of the first instruction in the sequence.  Returns the register
-  // being loaded and the index in the pool being read from in the output
-  // parameters 'reg' and 'index' respectively.
-  static uword DecodeLoadWordFromPool(uword end,
-                                      Register* reg,
-                                      intptr_t* index);
-};
-
-class CallPattern : public ValueObject {
- public:
-  CallPattern(uword pc, const Code& caller_code);
-
-  RawObject* Data() const;
-  void SetData(const Object& data) const;
-
-  RawCode* TargetCode() const;
-  void SetTargetCode(const Code& code) const;
-
-  static void InsertDeoptCallAt(uword pc);
-
- private:
-  const ObjectPool& object_pool_;
-
-  uword end_;
-
-  intptr_t data_pool_index_;
-  intptr_t target_pool_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallPattern);
-};
-
-class NativeCallPattern : public ValueObject {
- public:
-  NativeCallPattern(uword pc, const Code& code);
-
-  NativeFunctionWrapper target() const;
-  void set_target(NativeFunctionWrapper target) const;
-
-  NativeFunction native_function() const;
-  void set_native_function(NativeFunction target) const;
-
- private:
-  const ObjectPool& object_pool_;
-
-  uword end_;
-  intptr_t native_function_pool_index_;
-  intptr_t trampoline_pool_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(NativeCallPattern);
-};
-
-// Instance call that can switch between a direct monomorphic call, an IC call,
-// and a megamorphic call.
-//   load guarded cid            load ICData             load MegamorphicCache
-//   load monomorphic target <-> load ICLookup stub  ->  load MMLookup stub
-//   call target.entry           call stub.entry         call stub.entry
-class SwitchableCallPattern : public ValueObject {
- public:
-  SwitchableCallPattern(uword pc, const Code& code);
-
-  RawObject* data() const;
-  RawCode* target() const;
-  void SetData(const Object& data) const;
-  void SetTarget(const Code& target) const;
-
- private:
-  const ObjectPool& object_pool_;
-  intptr_t data_pool_index_;
-  intptr_t target_pool_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(SwitchableCallPattern);
-};
-
-class ReturnPattern : public ValueObject {
- public:
-  explicit ReturnPattern(uword pc);
-
-  static const int kLengthInBytes = 0;
-
-  int pattern_length_in_bytes() const {
-    UNIMPLEMENTED();
-    return kLengthInBytes;
-  }
-
-  bool IsValid() const;
-
- private:
-  const uword pc_;
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_INSTRUCTIONS_DBC_H_
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index d0de7f3..3f82a4a 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -356,10 +356,6 @@
 
 Interpreter::Interpreter()
     : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL), lookup_cache_() {
-#if defined(TARGET_ARCH_DBC)
-  FATAL("Interpreter is not supported when targeting DBC\n");
-#endif  // defined(USING_SIMULATOR) || defined(TARGET_ARCH_DBC)
-
   // Setup interpreter support first. Some of this information is needed to
   // setup the architecture state.
   // We allocate the stack here, the size is computed as the sum of
@@ -603,10 +599,7 @@
   {
     InterpreterSetjmpBuffer buffer(this);
     if (!setjmp(buffer.buffer_)) {
-#if defined(TARGET_ARCH_DBC)
-      USE(entrypoint);
-      UNIMPLEMENTED();
-#elif defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR)
       // We need to beware that bouncing between the interpreter and the
       // simulator may exhaust the C stack before exhausting either the
       // interpreter or simulator stacks.
@@ -1978,9 +1971,8 @@
       RawObject** call_top = SP + 1;
 
       InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
-      RawUnlinkedCall* selector = RAW_CAST(UnlinkedCall, LOAD_CONSTANT(kidx));
-      RawString* target_name = selector->ptr()->target_name_;
-      argdesc_ = selector->ptr()->args_descriptor_;
+      RawString* target_name = RAW_CAST(String, LOAD_CONSTANT(kidx));
+      argdesc_ = RAW_CAST(Array, LOAD_CONSTANT(kidx + 1));
       if (!InstanceCall(thread, target_name, call_base, call_top, &pc, &FP,
                         &SP)) {
         HANDLE_EXCEPTION;
@@ -2255,16 +2247,6 @@
   }
 
   {
-    static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 19,
-                  "Cleanup PushStatic bytecode instruction");
-    BYTECODE(PushStatic, D);
-    RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
-    // Note: field is also on the stack, hence no increment.
-    *SP = field->ptr()->value_.static_value_;
-    DISPATCH();
-  }
-
-  {
     BYTECODE(LoadStatic, D);
     RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
     RawInstance* value = field->ptr()->value_.static_value_;
@@ -2698,7 +2680,7 @@
   }
 
   {
-    BYTECODE(CheckReceiverForNull, D);
+    BYTECODE(NullCheck, D);
     SP -= 1;
 
     if (UNLIKELY(SP[0] == null_value)) {
@@ -3071,6 +3053,22 @@
     RawObject* value =
         reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
 
+    if (UNLIKELY(value == Object::sentinel().raw())) {
+      SP[1] = 0;  // Result slot.
+      SP[2] = instance;
+      SP[3] = field;
+      Exit(thread, FP, SP + 4, pc);
+      INVOKE_RUNTIME(
+          DRT_InitInstanceField,
+          NativeArguments(thread, 2, /* argv */ SP + 2, /* ret val */ SP + 1));
+
+      function = FrameFunction(FP);
+      instance = reinterpret_cast<RawInstance*>(SP[2]);
+      field = reinterpret_cast<RawField*>(SP[3]);
+      offset_in_words = Smi::Value(field->ptr()->value_.offset_);
+      value = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+    }
+
     *++SP = value;
 
     const bool unboxing =
@@ -3132,6 +3130,7 @@
     // Perform type test of value if field type is not one of dynamic, object,
     // or void, and if the value is not null.
     RawObject* null_value = Object::null();
+    // TODO(regis): Revisit when type checking mode is not kUnaware anymore.
     if (cid != kDynamicCid && cid != kInstanceCid && cid != kVoidCid &&
         value != null_value) {
       RawSubtypeTestCache* cache = field->ptr()->type_test_cache_;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index e78124c..a39f06d 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -173,6 +173,7 @@
         group_shutdown_callback(embedder_data());
       }
     }
+    UnregisterIsolateGroup(this);
     delete this;
   }
 }
@@ -316,6 +317,110 @@
   UnscheduleThreadLocked(&ml, thread, is_mutator, bypass_safepoint);
 }
 
+#ifndef PRODUCT
+void IsolateGroup::PrintJSON(JSONStream* stream, bool ref) {
+  if (!FLAG_support_service) {
+    return;
+  }
+  JSONObject jsobj(stream);
+  PrintToJSONObject(&jsobj, ref);
+}
+
+void IsolateGroup::PrintToJSONObject(JSONObject* jsobj, bool ref) {
+  if (!FLAG_support_service) {
+    return;
+  }
+  jsobj->AddProperty("type", (ref ? "@IsolateGroup" : "IsolateGroup"));
+  jsobj->AddServiceId(ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING, id());
+
+  jsobj->AddProperty("name", "isolate_group");
+  jsobj->AddPropertyF("number", "%" Pu64 "", id());
+  if (ref) {
+    return;
+  }
+
+  {
+    JSONArray isolate_array(jsobj, "isolates");
+    for (auto it = isolates_.Begin(); it != isolates_.End(); ++it) {
+      Isolate* isolate = *it;
+      isolate_array.AddValue(isolate, /*ref=*/true);
+    }
+  }
+}
+
+void IsolateGroup::PrintMemoryUsageJSON(JSONStream* stream) {
+  if (!FLAG_support_service) {
+    return;
+  }
+  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();
+  }
+
+  JSONObject jsobj(stream);
+  // This is the same "MemoryUsage" that the isolate-specific "getMemoryUsage"
+  // rpc method returns.
+  // TODO(dartbug.com/36097): Once the heap moves from Isolate to IsolateGroup
+  // this code needs to be adjusted to not double-count memory.
+  jsobj.AddProperty("type", "MemoryUsage");
+  jsobj.AddProperty64("heapUsage", used * kWordSize);
+  jsobj.AddProperty64("heapCapacity", capacity * kWordSize);
+  jsobj.AddProperty64("externalUsage", external_used * kWordSize);
+}
+#endif
+
+void IsolateGroup::ForEach(std::function<void(IsolateGroup*)> action) {
+  ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
+  for (auto isolate_group : *isolate_groups_) {
+    action(isolate_group);
+  }
+}
+
+void IsolateGroup::RunWithIsolateGroup(
+    uint64_t id,
+    std::function<void(IsolateGroup*)> action,
+    std::function<void()> not_found) {
+  ReadRwLocker wl(Thread::Current(), isolate_groups_rwlock_);
+  for (auto isolate_group : *isolate_groups_) {
+    if (isolate_group->id() == id) {
+      action(isolate_group);
+      return;
+    }
+  }
+  not_found();
+}
+
+void IsolateGroup::RegisterIsolateGroup(IsolateGroup* isolate_group) {
+  WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
+  isolate_groups_->Append(isolate_group);
+}
+
+void IsolateGroup::UnregisterIsolateGroup(IsolateGroup* isolate_group) {
+  WriteRwLocker wl(ThreadState::Current(), isolate_groups_rwlock_);
+  isolate_groups_->Remove(isolate_group);
+}
+
+void IsolateGroup::Init() {
+  ASSERT(isolate_groups_rwlock_ == nullptr);
+  isolate_groups_rwlock_ = new RwLock();
+  ASSERT(isolate_groups_ == nullptr);
+  isolate_groups_ = new IntrusiveDList<IsolateGroup>();
+}
+
+void IsolateGroup::Cleanup() {
+  delete isolate_groups_rwlock_;
+  isolate_groups_rwlock_ = nullptr;
+  ASSERT(isolate_groups_->IsEmpty());
+  delete isolate_groups_;
+  isolate_groups_ = nullptr;
+}
+
 bool IsolateVisitor::IsVMInternalIsolate(Isolate* isolate) const {
   return Isolate::IsVMInternalIsolate(isolate);
 }
@@ -333,17 +438,15 @@
     : ThreadStackResource(thread), isolate_(isolate) {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
   ASSERT(isolate_ != NULL);
-  AtomicOperations::FetchAndIncrement(&(isolate_->no_reload_scope_depth_));
-  ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >=
-         0);
+  isolate_->no_reload_scope_depth_.fetch_add(1);
+  ASSERT(isolate_->no_reload_scope_depth_ >= 0);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 NoReloadScope::~NoReloadScope() {
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-  AtomicOperations::FetchAndDecrement(&(isolate_->no_reload_scope_depth_));
-  ASSERT(AtomicOperations::LoadRelaxed(&(isolate_->no_reload_scope_depth_)) >=
-         0);
+  isolate_->no_reload_scope_depth_.fetch_sub(1);
+  ASSERT(isolate_->no_reload_scope_depth_ >= 0);
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 }
 
@@ -1061,7 +1164,7 @@
       shared_class_table_(new SharedClassTable()),
       class_table_(shared_class_table_.get()),
       store_buffer_(new StoreBuffer()),
-#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(DART_PRECOMPILED_RUNTIME)
       native_callback_trampolines_(),
 #endif
 #if !defined(PRODUCT)
@@ -1424,8 +1527,7 @@
 #if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 bool Isolate::CanReload() const {
   return !Isolate::IsVMInternalIsolate(this) && is_runnable() &&
-         !IsReloading() &&
-         (AtomicOperations::LoadRelaxed(&no_reload_scope_depth_) == 0) &&
+         !IsReloading() && (no_reload_scope_depth_ == 0) &&
          IsolateCreationEnabled() &&
          OSThread::Current()->HasStackHeadroom(64 * KB);
 }
@@ -2037,13 +2139,6 @@
   delete optimizing_background_compiler_;
   optimizing_background_compiler_ = nullptr;
 
-#if defined(DEBUG)
-  if (heap_ != nullptr && FLAG_verify_on_transition) {
-    // The VM isolate keeps all objects marked.
-    heap_->Verify(this == Dart::vm_isolate() ? kRequireMarked : kForbidMarked);
-  }
-#endif  // DEBUG
-
   Thread* thread = Thread::Current();
 
   // Don't allow anymore dart code to execution on this isolate.
@@ -2124,6 +2219,9 @@
 Isolate* Isolate::isolates_list_head_ = nullptr;
 bool Isolate::creation_enabled_ = false;
 
+RwLock* IsolateGroup::isolate_groups_rwlock_ = nullptr;
+IntrusiveDList<IsolateGroup>* IsolateGroup::isolate_groups_ = nullptr;
+
 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                   ValidationPolicy validate_frames) {
   ASSERT(visitor != nullptr);
@@ -2189,11 +2287,6 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-#if defined(TARGET_ARCH_DBC)
-  if (simulator() != nullptr) {
-    simulator()->VisitObjectPointers(visitor);
-  }
-#endif  // defined(TARGET_ARCH_DBC)
 
   VisitStackPointers(visitor, validate_frames);
 }
@@ -2487,6 +2580,11 @@
   }
 
   jsobj.AddProperty("_threads", thread_registry());
+
+  {
+    JSONObject isolate_group(&jsobj, "isolate_group");
+    group()->PrintToJSONObject(&isolate_group, /*ref=*/true);
+  }
 }
 
 void Isolate::PrintMemoryUsageJSON(JSONStream* stream) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 701d58f..99a58a0 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -184,8 +184,6 @@
                      const char* name,
                      const uint8_t* snapshot_data,
                      const uint8_t* snapshot_instructions,
-                     const uint8_t* shared_data,
-                     const uint8_t* shared_instructions,
                      const uint8_t* kernel_buffer,
                      intptr_t kernel_buffer_size,
                      Dart_IsolateFlags flags)
@@ -193,8 +191,6 @@
         name(strdup(name)),
         snapshot_data(snapshot_data),
         snapshot_instructions(snapshot_instructions),
-        shared_data(shared_data),
-        shared_instructions(shared_instructions),
         kernel_buffer(kernel_buffer),
         kernel_buffer_size(kernel_buffer_size),
         flags(flags),
@@ -208,8 +204,6 @@
   char* name;
   const uint8_t* snapshot_data;
   const uint8_t* snapshot_instructions;
-  const uint8_t* shared_data;
-  const uint8_t* shared_instructions;
   const uint8_t* kernel_buffer;
   const intptr_t kernel_buffer_size;
   Dart_IsolateFlags flags;
@@ -220,7 +214,7 @@
 };
 
 // Represents an isolate group and is shared among all isolates within a group.
-class IsolateGroup {
+class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
  public:
   IsolateGroup(std::unique_ptr<IsolateGroupSource> source, void* embedder_data);
   ~IsolateGroup();
@@ -282,6 +276,29 @@
     RunWithStoppedMutators(function, function);
   }
 
+#ifndef PRODUCT
+  void PrintJSON(JSONStream* stream, bool ref = true);
+  void PrintToJSONObject(JSONObject* jsobj, bool ref);
+
+  // Creates an object with the total heap memory usage statistics for this
+  // isolate group.
+  void PrintMemoryUsageJSON(JSONStream* stream);
+#endif
+
+  uint64_t id() { return id_; }
+
+  static void Init();
+  static void Cleanup();
+
+  static void ForEach(std::function<void(IsolateGroup*)> action);
+  static void RunWithIsolateGroup(uint64_t id,
+                                  std::function<void(IsolateGroup*)> action,
+                                  std::function<void()> not_found);
+
+  // Manage list of existing isolate groups.
+  static void RegisterIsolateGroup(IsolateGroup* isolate_group);
+  static void UnregisterIsolateGroup(IsolateGroup* isolate_group);
+
  private:
   void* embedder_data_ = nullptr;
 
@@ -294,6 +311,12 @@
   std::unique_ptr<IsolateGroupSource> source_;
   std::unique_ptr<ThreadRegistry> thread_registry_;
   std::unique_ptr<SafepointHandler> safepoint_handler_;
+
+  static RwLock* isolate_groups_rwlock_;
+  static IntrusiveDList<IsolateGroup>* isolate_groups_;
+
+  Random isolate_group_random_;
+  uint64_t id_ = isolate_group_random_.NextUInt64();
 };
 
 class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
@@ -432,7 +455,7 @@
   void set_init_callback_data(void* value) { init_callback_data_ = value; }
   void* init_callback_data() const { return init_callback_data_; }
 
-#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   NativeCallbackTrampolines* native_callback_trampolines() {
     return &native_callback_trampolines_;
   }
@@ -1060,7 +1083,7 @@
   Heap* heap_ = nullptr;
   IsolateGroup* isolate_group_ = nullptr;
 
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   NativeCallbackTrampolines native_callback_trampolines_;
 #endif
 
@@ -1140,7 +1163,8 @@
   ISOLATE_METRIC_LIST(ISOLATE_METRIC_VARIABLE);
 #undef ISOLATE_METRIC_VARIABLE
 
-  intptr_t no_reload_scope_depth_ = 0;  // we can only reload when this is 0.
+  RelaxedAtomic<intptr_t> no_reload_scope_depth_ =
+      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;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 17fa30e..4b7914b 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -137,6 +137,9 @@
     if (new_field) {
       const Field& field = Field::Handle(to_field.raw());
       new_fields_->Add(&field);
+
+      field.set_needs_load_guard(true);
+      field.set_is_unboxing_candidate(false);
     }
   }
 }
@@ -151,61 +154,15 @@
         Object::Handle(instance.RawGetFieldAtOffset(from_offset));
     result.RawSetFieldAtOffset(to_offset, value);
   }
-  // Convert the instance into a filler object.
-  Become::MakeDummyObject(instance);
-  return result.raw();
-}
-
-void InstanceMorpher::RunNewFieldInitializers() const {
-  if ((new_fields_->length() == 0) || (after_->length() == 0)) {
-    return;
-  }
-
-  TIR_Print("Running new field initializers for class: %s\n", to_.ToCString());
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
-  Function& init_func = Function::Handle(zone);
-  Object& result = Object::Handle(zone);
-  // For each new field.
   for (intptr_t i = 0; i < new_fields_->length(); i++) {
     // Create a function that returns the expression.
     const Field* field = new_fields_->At(i);
-    if (field->has_initializer()) {
-      if (field->is_declared_in_bytecode() && (field->bytecode_offset() == 0)) {
-        FATAL1(
-            "Missing field initializer for '%s'. Reload requires bytecode "
-            "to be generated with 'instance-field-initializers'",
-            field->ToCString());
-      }
-      init_func = kernel::CreateFieldInitializerFunction(thread, zone, *field);
-      const Array& args = Array::Handle(zone, Array::New(1));
-      for (intptr_t j = 0; j < after_->length(); j++) {
-        const Instance* instance = after_->At(j);
-        TIR_Print("Initializing instance %" Pd " / %" Pd "\n", j + 1,
-                  after_->length());
-        // Run the function and assign the field.
-        args.SetAt(0, *instance);
-        result = DartEntry::InvokeFunction(init_func, args);
-        if (result.IsError()) {
-          // TODO(johnmccutchan): Report this error in the reload response?
-          OS::PrintErr(
-              "RELOAD: Running initializer for new field `%s` resulted in "
-              "an error: %s\n",
-              field->ToCString(), Error::Cast(result).ToErrorCString());
-          continue;
-        }
-        instance->RawSetFieldAtOffset(field->Offset(), result);
-      }
-    } else {
-      result = field->saved_initial_value();
-      for (intptr_t j = 0; j < after_->length(); j++) {
-        const Instance* instance = after_->At(j);
-        TIR_Print("Initializing instance %" Pd " / %" Pd "\n", j + 1,
-                  after_->length());
-        instance->RawSetFieldAtOffset(field->Offset(), result);
-      }
-    }
+    ASSERT(field->needs_load_guard());
+    result.RawSetFieldAtOffset(field->Offset(), Object::sentinel());
   }
+  // Convert the instance into a filler object.
+  Become::MakeDummyObject(instance);
+  return result.raw();
 }
 
 void InstanceMorpher::CreateMorphedCopies() const {
@@ -451,7 +408,7 @@
       reload_finalized_(false),
       js_(js),
       saved_num_cids_(-1),
-      saved_class_table_(NULL),
+      saved_class_table_(nullptr),
       num_saved_libs_(-1),
       instance_morphers_(zone_, 0),
       reasons_to_cancel_reload_(zone_, 0),
@@ -478,7 +435,7 @@
 
 IsolateReloadContext::~IsolateReloadContext() {
   ASSERT(zone_ == Thread::Current()->zone());
-  ASSERT(saved_class_table_ == NULL);
+  ASSERT(saved_class_table_.load(std::memory_order_relaxed) == nullptr);
 }
 
 void IsolateReloadContext::ReportError(const Error& error) {
@@ -977,7 +934,7 @@
     NoSafepointScope no_safepoint_scope(Thread::Current());
 
     // The saved_class_table_ is now source of truth for GC.
-    AtomicOperations::StoreRelease(&saved_class_table_, saved_class_table);
+    saved_class_table_.store(saved_class_table, std::memory_order_release);
 
     // We can therefore wipe out all of the old entries (if that table is used
     // for GC during the hot-reload we have a bug).
@@ -1142,7 +1099,7 @@
 void IsolateReloadContext::RollbackClasses() {
   TIR_Print("---- ROLLING BACK CLASS TABLE\n");
   ASSERT(saved_num_cids_ > 0);
-  ASSERT(saved_class_table_ != NULL);
+  ASSERT(saved_class_table_.load(std::memory_order_relaxed) != nullptr);
 
   DiscardSavedClassTable(/*is_rollback=*/true);
 }
@@ -1378,9 +1335,6 @@
                 saved_libs.Length(), libs.Length());
     }
   }
-
-  // Run the initializers for new instance fields.
-  RunNewFieldInitializers();
 }
 
 bool IsolateReloadContext::IsDirty(const Library& lib) {
@@ -1514,7 +1468,8 @@
   ASSERT(HasNoTasks(I->heap()));
 #if defined(DEBUG)
   for (intptr_t i = 0; i < saved_num_cids_; i++) {
-    saved_class_table_[i] = ClassAndSize(nullptr, -1);
+    saved_class_table_.load(std::memory_order_relaxed)[i] =
+        ClassAndSize(nullptr, -1);
   }
 #endif
 
@@ -1527,13 +1482,6 @@
   // again.
 }
 
-void IsolateReloadContext::RunNewFieldInitializers() {
-  // Run new field initializers on all instances.
-  for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
-    instance_morphers_.At(i)->RunNewFieldInitializers();
-  }
-}
-
 bool IsolateReloadContext::ValidateReload() {
   TIMELINE_SCOPE(ValidateReload);
   if (reload_aborted()) return false;
@@ -1585,7 +1533,7 @@
 
 RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) {
   ClassAndSize* class_table =
-      AtomicOperations::LoadAcquire(&saved_class_table_);
+      saved_class_table_.load(std::memory_order_acquire);
   if (class_table != NULL) {
     ASSERT(cid > 0);
     ASSERT(cid < saved_num_cids_);
@@ -1597,7 +1545,7 @@
 
 intptr_t IsolateReloadContext::GetClassSizeForHeapWalkAt(intptr_t cid) {
   ClassAndSize* class_table =
-      AtomicOperations::LoadAcquire(&saved_class_table_);
+      saved_class_table_.load(std::memory_order_acquire);
   if (class_table != NULL) {
     ASSERT(cid > 0);
     ASSERT(cid < saved_num_cids_);
@@ -1608,11 +1556,11 @@
 }
 
 void IsolateReloadContext::DiscardSavedClassTable(bool is_rollback) {
-  ClassAndSize* local_saved_class_table = saved_class_table_;
+  ClassAndSize* local_saved_class_table =
+      saved_class_table_.load(std::memory_order_relaxed);
   I->class_table()->ResetAfterHotReload(local_saved_class_table,
                                         saved_num_cids_, is_rollback);
-  AtomicOperations::StoreRelease(&saved_class_table_,
-                                 static_cast<ClassAndSize*>(nullptr));
+  saved_class_table_.store(nullptr, std::memory_order_release);
 }
 
 RawLibrary* IsolateReloadContext::saved_root_library() const {
@@ -1634,10 +1582,13 @@
 
 void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointers(from(), to());
-  if (saved_class_table_ != NULL) {
+
+  ClassAndSize* saved_class_table =
+      saved_class_table_.load(std::memory_order_relaxed);
+  if (saved_class_table != nullptr) {
     for (intptr_t i = 0; i < saved_num_cids_; i++) {
       visitor->VisitPointer(
-          reinterpret_cast<RawObject**>(&(saved_class_table_[i].class_)));
+          reinterpret_cast<RawObject**>(&(saved_class_table[i].class_)));
     }
   }
 }
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index b6e0553..a8c0d0a 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -60,8 +60,6 @@
   // Called on each instance that needs to be morphed.
   RawInstance* Morph(const Instance& instance) const;
 
-  void RunNewFieldInitializers() const;
-
   // Adds an object to be morphed.
   void AddObject(RawObject* object) const;
 
@@ -145,7 +143,9 @@
   // All zone allocated objects must be allocated from this zone.
   Zone* zone() const { return zone_; }
 
-  bool UseSavedClassTableForGC() const { return saved_class_table_ != nullptr; }
+  bool UseSavedClassTableForGC() const {
+    return saved_class_table_.load(std::memory_order_relaxed) != nullptr;
+  }
 
   bool reload_skipped() const { return reload_skipped_; }
   bool reload_aborted() const { return reload_aborted_; }
@@ -248,8 +248,6 @@
 
   void MorphInstancesAndApplyNewClassTable();
 
-  void RunNewFieldInitializers();
-
   bool ValidateReload();
 
   void Rollback();
@@ -285,7 +283,7 @@
   JSONStream* js_;
 
   intptr_t saved_num_cids_;
-  ClassAndSize* saved_class_table_;
+  std::atomic<ClassAndSize*> saved_class_table_;
   intptr_t num_saved_libs_;
   intptr_t num_received_libs_;
   intptr_t bytes_received_libs_;
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 42d125f..575c061 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -3299,7 +3299,7 @@
   EXPECT_EQ(56, SimpleInvoke(lib, "main"));
 }
 
-TEST_CASE(IsolateReload_RunNewFieldInitializersMutateStaticField) {
+TEST_CASE(IsolateReload_RunNewFieldInitializersLazy) {
   const char* kScript =
       "int myInitialValue = 8 * 7;\n"
       "class Foo {\n"
@@ -3327,17 +3327,119 @@
       "Foo value;\n"
       "Foo value1;\n"
       "main() {\n"
-      "  return myInitialValue;\n"
+      "  return '${myInitialValue} ${value.y} ${value1.y} ${myInitialValue}';\n"
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
-  // Verify that we ran field initializers on existing instances and that
-  // they affected the value of the field myInitialValue.
-  EXPECT_EQ(58, SimpleInvoke(lib, "main"));
+  // Verify that field initializers ran lazily.
+  EXPECT_STREQ("56 56 57 58", SimpleInvokeStr(lib, "main"));
 }
 
-// When an initializer expression throws, we leave the field as null.
+TEST_CASE(IsolateReload_RunNewFieldInitializersLazyConst) {
+  const char* kScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y. Do not read it. Note field y does not get an initializer
+  // function in the VM because the initializer is a literal, but we should not
+  // eagerly initialize with the literal so that the behavior doesn't depend on
+  // this optimization.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = 5;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return 0;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(0, SimpleInvoke(lib, "main"));
+
+  // Change y's initializer and check this new initializer is used.
+  const char* kReloadScript2 =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = 6;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  return value.y;\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript2);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(6, SimpleInvoke(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_RunNewFieldInitializersLazyTransitive) {
+  const char* kScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "Foo value1;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  value1 = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y. Do not touch y.
+  const char* kReloadScript =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = myInitialValue++;\n"
+      "}\n"
+      "Foo value;\n"
+      "Foo value1;\n"
+      "main() {\n"
+      "  return '${myInitialValue}';\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("56", SimpleInvokeStr(lib, "main"));
+
+  // Reload again. Field y's getter still needs to keep for initialization even
+  // though it is no longer new.
+  const char* kReloadScript2 =
+      "int myInitialValue = 8 * 7;\n"
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = myInitialValue++;\n"
+      "}\n"
+      "Foo value;\n"
+      "Foo value1;\n"
+      "main() {\n"
+      "  return '${myInitialValue} ${value.y} ${value1.y} ${myInitialValue}';\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript2);
+  EXPECT_VALID(lib);
+  // Verify that field initializers ran lazily.
+  EXPECT_STREQ("56 56 57 58", SimpleInvokeStr(lib, "main"));
+}
+
 TEST_CASE(IsolateReload_RunNewFieldInitializersThrows) {
   const char* kScript =
       "class Foo {\n"
@@ -3357,17 +3459,56 @@
   const char* kReloadScript =
       "class Foo {\n"
       "  int x = 4;\n"
-      "  int y = throw 'a';\n"
+      "  int y = throw 'exception';\n"
       "}\n"
       "Foo value;\n"
       "main() {\n"
-      "  return '${value.y == null}';"
+      "  try {\n"
+      "    return value.y.toString();\n"
+      "  } catch (e) {\n"
+      "    return e.toString();\n"
+      "  }\n"
       "}\n";
 
   lib = TestCase::ReloadTestScript(kReloadScript);
   EXPECT_VALID(lib);
   // Verify that we ran field initializers on existing instances.
-  EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
+  EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_RunNewFieldInitializersCyclicInitialization) {
+  const char* kScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  value = new Foo();\n"
+      "  return value.x;\n"
+      "}\n";
+
+  Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+  EXPECT_VALID(lib);
+  EXPECT_EQ(4, SimpleInvoke(lib, "main"));
+
+  // Add the field y.
+  const char* kReloadScript =
+      "class Foo {\n"
+      "  int x = 4;\n"
+      "  int y = value.y;\n"
+      "}\n"
+      "Foo value;\n"
+      "main() {\n"
+      "  try {\n"
+      "    return value.y.toString();\n"
+      "  } catch (e) {\n"
+      "    return e.toString();\n"
+      "  }\n"
+      "}\n";
+
+  lib = TestCase::ReloadTestScript(kReloadScript);
+  EXPECT_VALID(lib);
+  EXPECT_STREQ("Stack Overflow", SimpleInvokeStr(lib, "main"));
 }
 
 // When an initializer expression has a syntax error, we detect it at reload
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 2b0f84f..05170a7 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -94,8 +94,9 @@
       // Busy wait for interrupts.
       uword limit = 0;
       do {
-        limit = AtomicOperations::LoadRelaxed(
-            reinterpret_cast<uword*>(thread_->stack_limit_address()));
+        limit = reinterpret_cast<RelaxedAtomic<uword>*>(
+                    thread_->stack_limit_address())
+                    ->load();
       } while (
           (limit == thread_->saved_stack_limit_) ||
           (((limit & Thread::kInterruptsMask) & Thread::kVMInterrupt) == 0));
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 33a990c..07035fe 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -346,6 +346,11 @@
   isolate->PrintJSON(this, ref);
 }
 
+void JSONStream::PrintValue(IsolateGroup* isolate_group, bool ref) {
+  PrintCommaIfNeeded();
+  isolate_group->PrintJSON(this, ref);
+}
+
 void JSONStream::PrintValue(ThreadRegistry* reg) {
   PrintCommaIfNeeded();
   reg->PrintJSON(this);
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index b9fdef7..f0ee450 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -203,6 +203,7 @@
   void PrintValue(Metric* metric);
   void PrintValue(MessageQueue* queue);
   void PrintValue(Isolate* isolate, bool ref = true);
+  void PrintValue(IsolateGroup* isolate, bool ref = true);
   void PrintValue(ThreadRegistry* reg);
   void PrintValue(Thread* thread);
   void PrintValue(const TimelineEvent* timeline_event);
@@ -438,6 +439,9 @@
   void AddValue(Isolate* isolate, bool ref = true) const {
     stream_->PrintValue(isolate, ref);
   }
+  void AddValue(IsolateGroup* isolate_group, bool ref = true) const {
+    stream_->PrintValue(isolate_group, ref);
+  }
   void AddValue(ThreadRegistry* reg) const { stream_->PrintValue(reg); }
   void AddValue(Thread* thread) const { stream_->PrintValue(thread); }
   void AddValue(Breakpoint* bpt) const { stream_->PrintValue(bpt); }
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 24c4c01..6bf5371 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 
 // Both version numbers are inclusive.
 static const uint32_t kMinSupportedKernelFormatVersion = 18;
-static const uint32_t kMaxSupportedKernelFormatVersion = 35;
+static const uint32_t kMaxSupportedKernelFormatVersion = 36;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -118,6 +118,7 @@
   V(AssertBlock, 81)                                                           \
   V(TypedefType, 87)                                                           \
   V(BottomType, 89)                                                            \
+  V(NeverType, 98)                                                             \
   V(InvalidType, 90)                                                           \
   V(DynamicType, 91)                                                           \
   V(VoidType, 92)                                                              \
@@ -163,19 +164,12 @@
 };
 
 // Keep in sync with package:kernel/lib/ast.dart
-enum Nullability {
-  kNullable = 0,
-  kNonNullable = 1,
-  kNeither = 2,
-  kLegacy = 3,
-};
-
-// Keep in sync with package:kernel/lib/ast.dart
 enum Variance {
   kUnrelated = 0,
   kCovariant = 1,
   kContravariant = 2,
   kInvariant = 3,
+  kLegacyCovariant = 4,
 };
 
 static const int SpecializedIntLiteralBias = 3;
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 82da67c..fa5e4ee 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -61,7 +61,7 @@
 const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME;
 Dart_IsolateGroupCreateCallback KernelIsolate::create_group_callback_ = NULL;
 Monitor* KernelIsolate::monitor_ = new Monitor();
-KernelIsolate::State KernelIsolate::state_ = KernelIsolate::kStopped;
+KernelIsolate::State KernelIsolate::state_ = KernelIsolate::kNotStarted;
 Isolate* KernelIsolate::isolate_ = NULL;
 Dart_Port KernelIsolate::kernel_port_ = ILLEGAL_PORT;
 
@@ -85,7 +85,7 @@
     Isolate::FlagsInitialize(&api_flags);
     api_flags.enable_asserts = false;
     api_flags.unsafe_trust_strong_mode_types = false;
-#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILER)
     api_flags.use_field_guards = true;
 #endif
 #if !defined(DART_PRECOMPILER)
@@ -217,22 +217,37 @@
   }
 };
 
-void KernelIsolate::Run() {
-  {
-    MonitorLocker ml(monitor_);
-    ASSERT(state_ == kStopped);
-    state_ = kStarting;
-    ml.NotifyAll();
-  }
+void KernelIsolate::InitializeState() {
   // Grab the isolate create callback here to avoid race conditions with tests
   // that change this after Dart_Initialize returns.
+  if (FLAG_trace_kernel) {
+    OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": InitializeState\n");
+  }
   create_group_callback_ = Isolate::CreateGroupCallback();
   if (create_group_callback_ == NULL) {
     KernelIsolate::InitializingFailed();
     return;
   }
-  bool task_started = Dart::thread_pool()->Run<RunKernelTask>();
-  ASSERT(task_started);
+}
+
+bool KernelIsolate::Start() {
+  bool start_task = false;
+  {
+    MonitorLocker ml(monitor_);
+    if (state_ == kNotStarted) {
+      if (FLAG_trace_kernel) {
+        OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Start\n");
+      }
+      start_task = true;
+      state_ = kStarting;
+      ml.NotifyAll();
+    }
+  }
+  bool task_started = true;
+  if (start_task) {
+    task_started = Dart::thread_pool()->Run<RunKernelTask>();
+  }
+  return task_started;
 }
 
 void KernelIsolate::Shutdown() {
@@ -240,7 +255,7 @@
   while (state_ == kStarting) {
     ml.Wait();
   }
-  if (state_ == kStopped) {
+  if (state_ == kStopped || state_ == kNotStarted) {
     return;
   }
   ASSERT(state_ == kStarted);
@@ -380,6 +395,15 @@
   experimental_flags_->Add(strdup(value));
 }
 
+bool KernelIsolate::GetExperimentalFlag(const char* value) {
+  for (const char* str : *experimental_flags_) {
+    if (strcmp(str, value) == 0) {
+      return true;
+    }
+  }
+  return false;
+}
+
 DEFINE_OPTION_HANDLER(KernelIsolate::AddExperimentalFlag,
                       enable_experiment,
                       "Comma separated list of experimental features.");
@@ -626,14 +650,8 @@
 
     Dart_CObject bytecode;
     bytecode.type = Dart_CObject_kBool;
-    // Interpreter is not supported with DBC.
-#if !defined(TARGET_ARCH_DBC)
     bytecode.value.as_bool =
         FLAG_enable_interpreter || FLAG_use_bytecode_compiler;
-#else
-    bytecode.value.as_bool =
-        FLAG_use_bytecode_compiler && !FLAG_enable_interpreter;
-#endif
 
     Dart_CObject package_config_uri;
     if (package_config != NULL) {
@@ -824,6 +842,14 @@
     const char* package_config,
     const char* multiroot_filepaths,
     const char* multiroot_scheme) {
+  // Start the kernel Isolate if it is not already running.
+  if (!Start()) {
+    Dart_KernelCompilationResult result = {};
+    result.status = Dart_KernelCompilationStatus_Unknown;
+    result.error = strdup("Error while starting Kernel isolate task");
+    return result;
+  }
+
   // This must be the main script to be loaded. Wait for Kernel isolate
   // to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
diff --git a/runtime/vm/kernel_isolate.h b/runtime/vm/kernel_isolate.h
index fe457dd..be046f8 100644
--- a/runtime/vm/kernel_isolate.h
+++ b/runtime/vm/kernel_isolate.h
@@ -29,7 +29,8 @@
   static const int kListDependenciesTag;
   static const int kNotifyIsolateShutdown;
 
-  static void Run();
+  static void InitializeState();
+  static bool Start();
   static void Shutdown();
 
   static bool NameEquals(const char* name);
@@ -68,6 +69,7 @@
   static void NotifyAboutIsolateShutdown(const Isolate* isolate);
 
   static void AddExperimentalFlag(const char* value);
+  static bool GetExperimentalFlag(const char* value);
 
  protected:
   static void InitCallback(Isolate* I);
@@ -83,6 +85,7 @@
   static Dart_IsolateGroupCreateCallback create_group_callback_;
   static Monitor* monitor_;
   enum State {
+    kNotStarted,
     kStopped,
     kStarting,
     kStarted,
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index fce72a9..28d4ffe 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -430,9 +430,7 @@
     scripts.SetAt(index, script);
   }
 
-  if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-    bytecode_metadata_helper_.ReadBytecodeComponent();
-  }
+  bytecode_metadata_helper_.ReadBytecodeComponent();
 }
 
 KernelLoader::KernelLoader(const Script& script,
@@ -734,12 +732,7 @@
 
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
-    bool libraries_loaded = false;
-    if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-      libraries_loaded = bytecode_metadata_helper_.ReadLibraries();
-    }
-
-    if (!libraries_loaded) {
+    if (!bytecode_metadata_helper_.ReadLibraries()) {
       // Note that `problemsAsJson` on Component is implicitly skipped.
       const intptr_t length = program_->library_count();
       for (intptr_t i = 0; i < length; i++) {
@@ -785,11 +778,9 @@
 void KernelLoader::LoadLibrary(const Library& library) {
   ASSERT(!library.Loaded());
 
-  if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-    bytecode_metadata_helper_.ReadLibrary(library);
-    if (library.Loaded()) {
-      return;
-    }
+  bytecode_metadata_helper_.ReadLibrary(library);
+  if (library.Loaded()) {
+    return;
   }
   const auto& uri = String::Handle(Z, library.url());
   const intptr_t num_libraries = program_->library_count();
@@ -916,11 +907,9 @@
                                            bool* is_empty_program,
                                            intptr_t* p_num_classes,
                                            intptr_t* p_num_procedures) {
-  if (FLAG_enable_interpreter || FLAG_use_bytecode_compiler) {
-    if (bytecode_metadata_helper_.FindModifiedLibrariesForHotReload(
-            modified_libs, is_empty_program, p_num_classes, p_num_procedures)) {
-      return;
-    }
+  if (bytecode_metadata_helper_.FindModifiedLibrariesForHotReload(
+          modified_libs, is_empty_program, p_num_classes, p_num_procedures)) {
+    return;
   }
   intptr_t length = program_->library_count();
   *is_empty_program = *is_empty_program && (length == 0);
@@ -2070,7 +2059,7 @@
       for (intptr_t i = 0; i < libs.Length(); i++) {
         lib ^= libs.At(i);
         script = lib.LookupScript(uri_string, /* useResolvedUri = */ true);
-        if (!script.IsNull() && script.kind() == RawScript::kKernelTag) {
+        if (!script.IsNull()) {
           sources = script.Source();
           line_starts = script.line_starts();
           break;
@@ -2082,8 +2071,7 @@
   }
 
   const Script& script =
-      Script::Handle(Z, Script::New(import_uri_string, uri_string, sources,
-                                    RawScript::kKernelTag));
+      Script::Handle(Z, Script::New(import_uri_string, uri_string, sources));
   script.set_kernel_script_index(index);
   script.set_kernel_program_info(kernel_program_info_);
   script.set_line_starts(line_starts);
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 6f3dea7..cf01099 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -228,6 +228,7 @@
 
   void ReadObfuscationProhibitions();
 
+ private:
   // Check for the presence of a (possibly const) constructor for the
   // 'ExternalName' class. If found, returns the name parameter to the
   // constructor.
@@ -250,14 +251,6 @@
                          bool* is_potential_native,
                          bool* has_pragma_annotation);
 
-  const String& DartSymbolPlain(StringIndex index) {
-    return translation_helper_.DartSymbolPlain(index);
-  }
-  const String& DartSymbolObfuscate(StringIndex index) {
-    return translation_helper_.DartSymbolObfuscate(index);
-  }
-
- private:
   KernelLoader(const Script& script,
                const ExternalTypedData& kernel_data,
                intptr_t data_program_offset,
diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc
index 80dc9d1..76b789b 100644
--- a/runtime/vm/malloc_hooks_test.cc
+++ b/runtime/vm/malloc_hooks_test.cc
@@ -4,7 +4,7 @@
 
 #include "platform/globals.h"
 
-#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && !defined(TARGET_ARCH_DBC)
+#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
 
 #include "platform/assert.h"
 #include "vm/globals.h"
diff --git a/runtime/vm/metrics.h b/runtime/vm/metrics.h
index b54fc12..36d9e4b 100644
--- a/runtime/vm/metrics.h
+++ b/runtime/vm/metrics.h
@@ -88,7 +88,6 @@
 
   static Metric* vm_head() { return vm_list_head_; }
 
- protected:
   // Override to get a callback when value is serialized to JSON.
   // Use this for metrics that produce their value on demand.
   virtual int64_t Value() const { return value(); }
@@ -131,52 +130,52 @@
 };
 
 class MetricHeapOldUsed : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapOldCapacity : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapOldExternal : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapNewUsed : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapNewCapacity : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapNewExternal : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricIsolateCount : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricCurrentRSS : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricPeakRSS : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
 class MetricHeapUsed : public Metric {
- protected:
+ public:
   virtual int64_t Value() const;
 };
 
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 4482a6d..aceb5a7 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -4,6 +4,9 @@
 
 #include "platform/assert.h"
 
+#include "include/dart_api.h"
+#include "include/dart_tools_api.h"
+
 #include "vm/dart_api_impl.h"
 #include "vm/dart_api_state.h"
 #include "vm/globals.h"
@@ -73,6 +76,42 @@
   Dart_ShutdownIsolate();
 }
 
+ISOLATE_UNIT_TEST_CASE(Metric_EmbedderAPI) {
+  {
+    TransitionVMToNative transition(Thread::Current());
+
+    const char* kScript = "void main() {}";
+    Dart_Handle api_lib = TestCase::LoadTestScript(
+        kScript, /*resolver=*/nullptr, RESOLVED_USER_TEST_URI);
+    EXPECT_VALID(api_lib);
+  }
+
+  // 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);
+
+  // Ensure we've something live in new space.
+  String::New("<land-in-new-space2>", Heap::kNew);
+
+  {
+    TransitionVMToNative transition(Thread::Current());
+
+    Dart_Isolate isolate = Dart_CurrentIsolate();
+    EXPECT(Dart_VMIsolateCountMetric() > 0);
+    EXPECT(Dart_IsolateHeapOldUsedMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapOldUsedMaxMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapOldCapacityMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapOldCapacityMaxMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapNewUsedMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapNewUsedMaxMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapNewCapacityMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapNewCapacityMaxMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapGlobalUsedMetric(isolate) > 0);
+    EXPECT(Dart_IsolateHeapGlobalUsedMaxMetric(isolate) > 0);
+  }
+}
+
 #endif  // !PRODUCT
 
 }  // namespace dart
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 8d07143..a7ff77d 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -22,10 +22,7 @@
 
 #if defined(TESTING) || defined(DEBUG)
 
-#if defined(TARGET_ARCH_DBC)
-// C-stack is always aligned on DBC because we don't have any native code.
-#define CHECK_STACK_ALIGNMENT
-#elif defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR)
 #define CHECK_STACK_ALIGNMENT                                                  \
   {                                                                            \
     uword current_sp = Simulator::Current()->get_register(SPREG);              \
@@ -47,10 +44,6 @@
 
 void VerifyOnTransition();
 
-#define VERIFY_ON_TRANSITION                                                   \
-  if (FLAG_verify_on_transition) {                                             \
-    VerifyOnTransition();                                                      \
-  }
 #define DEOPTIMIZE_ALOT                                                        \
   if (FLAG_deoptimize_alot) {                                                  \
     DeoptimizeFunctionsOnStack();                                              \
@@ -60,8 +53,6 @@
 
 #define CHECK_STACK_ALIGNMENT                                                  \
   {}
-#define VERIFY_ON_TRANSITION                                                   \
-  {}
 #define DEOPTIMIZE_ALOT                                                        \
   {}
 
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 769fb1b..3176706 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -121,8 +121,7 @@
 
 uword NativeEntry::NoScopeNativeCallWrapperEntry() {
   uword entry = reinterpret_cast<uword>(NativeEntry::NoScopeNativeCallWrapper);
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
-  // DBC does not use redirections unlike other simulators.
+#if defined(USING_SIMULATOR)
   entry = Simulator::RedirectExternalReference(
       entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
 #endif
@@ -138,7 +137,6 @@
 void NativeEntry::NoScopeNativeCallWrapperNoStackCheck(
     Dart_NativeArguments args,
     Dart_NativeFunction func) {
-  VERIFY_ON_TRANSITION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   // Tell MemorySanitizer 'arguments' is initialized by generated code.
   MSAN_UNPOISON(arguments, sizeof(*arguments));
@@ -152,14 +150,12 @@
     }
   }
   ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
-  VERIFY_ON_TRANSITION;
 }
 
 uword NativeEntry::AutoScopeNativeCallWrapperEntry() {
   uword entry =
       reinterpret_cast<uword>(NativeEntry::AutoScopeNativeCallWrapper);
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
-  // DBC does not use redirections unlike other simulators.
+#if defined(USING_SIMULATOR)
   entry = Simulator::RedirectExternalReference(
       entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
 #endif
@@ -175,7 +171,6 @@
 void NativeEntry::AutoScopeNativeCallWrapperNoStackCheck(
     Dart_NativeArguments args,
     Dart_NativeFunction func) {
-  VERIFY_ON_TRANSITION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   // Tell MemorySanitizer 'arguments' is initialized by generated code.
   MSAN_UNPOISON(arguments, sizeof(*arguments));
@@ -198,7 +193,6 @@
     DEOPTIMIZE_ALOT;
   }
   ASSERT(thread->execution_state() == Thread::kThreadInGenerated);
-  VERIFY_ON_TRANSITION;
 }
 
 static NativeFunction ResolveNativeFunction(Zone* zone,
@@ -226,8 +220,7 @@
 
 uword NativeEntry::LinkNativeCallEntry() {
   uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall);
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
-  // DBC does not use redirections unlike other simulators.
+#if defined(USING_SIMULATOR)
   entry = Simulator::RedirectExternalReference(
       entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
 #endif
@@ -236,7 +229,6 @@
 
 void NativeEntry::LinkNativeCall(Dart_NativeArguments args) {
   CHECK_STACK_ALIGNMENT;
-  VERIFY_ON_TRANSITION;
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
   // Tell MemorySanitizer 'arguments' is initialized by generated code.
   MSAN_UNPOISON(arguments, sizeof(*arguments));
@@ -275,7 +267,7 @@
                               &is_bootstrap_native, &is_auto_scope);
     ASSERT(target_function != NULL);
 
-#if defined(DEBUG) && !defined(TARGET_ARCH_DBC)
+#if defined(DEBUG)
     NativeFunction current_function = NULL;
     if (caller_frame->is_interpreted()) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -309,18 +301,6 @@
 #endif
 
     NativeFunction patch_target_function = target_function;
-#if defined(TARGET_ARCH_DBC)
-    NativeFunctionWrapper trampoline;
-    if (is_bootstrap_native) {
-      trampoline = &BootstrapNativeCallWrapper;
-    } else if (is_auto_scope) {
-      trampoline = &AutoScopeNativeCallWrapper;
-    } else {
-      trampoline = &NoScopeNativeCallWrapper;
-    }
-    CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
-                                   patch_target_function, trampoline);
-#else
     if (caller_frame->is_interpreted()) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
       ASSERT(FLAG_enable_interpreter);
@@ -355,14 +335,12 @@
       CodePatcher::PatchNativeCallAt(caller_frame->pc(), code,
                                      patch_target_function, trampoline);
     }
-#endif  // defined TARGET_ARCH_DBC
 
     if (FLAG_trace_natives) {
       THR_Print("    -> %p (%s)\n", target_function,
                 is_bootstrap_native ? "bootstrap" : "non-bootstrap");
     }
   }
-  VERIFY_ON_TRANSITION;
 
   // Tail-call resolved target.
   if (is_bootstrap_native) {
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index 6878c45..52e83a5 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -40,7 +40,6 @@
                                     Zone* zone, NativeArguments* arguments);   \
   void NATIVE_ENTRY_FUNCTION(name)(Dart_NativeArguments args) {                \
     CHECK_STACK_ALIGNMENT;                                                     \
-    VERIFY_ON_TRANSITION;                                                      \
     NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);     \
     /* Tell MemorySanitizer 'arguments' is initialized by generated code. */   \
     MSAN_UNPOISON(arguments, sizeof(*arguments));                              \
@@ -65,7 +64,6 @@
       }                                                                        \
       DEOPTIMIZE_ALOT;                                                         \
     }                                                                          \
-    VERIFY_ON_TRANSITION;                                                      \
   }                                                                            \
   static RawObject* DN_Helper##name(Isolate* isolate, Thread* thread,          \
                                     Zone* zone, NativeArguments* arguments)
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ca5c1b5..6087194 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -74,6 +74,8 @@
     false,
     "Show names of internal classes (e.g. \"OneByteString\") in error messages "
     "instead of showing the corresponding interface names (e.g. \"String\")");
+// TODO(regis): Remove this temporary flag used to debug nullability.
+DEFINE_FLAG(bool, show_nullability, false, "Show nullability in type names");
 DEFINE_FLAG(bool, use_lib_cache, false, "Use library name cache");
 DEFINE_FLAG(bool, use_exp_cache, false, "Use library exported name cache");
 
@@ -131,6 +133,7 @@
 RawClass* Object::class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::never_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -928,6 +931,13 @@
   cls.set_is_type_finalized();
   void_class_ = cls.raw();
 
+  cls = Class::New<Instance>(kNeverCid, isolate);
+  cls.set_num_type_arguments(0);
+  cls.set_is_finalized();
+  cls.set_is_declaration_loaded();
+  cls.set_is_type_finalized();
+  never_class_ = cls.raw();
+
   cls = Class::New<Type>(isolate);
   cls.set_is_finalized();
   cls.set_is_declaration_loaded();
@@ -939,6 +949,9 @@
   cls = void_class_;
   *void_type_ = Type::NewNonParameterizedType(cls);
 
+  cls = never_class_;
+  *never_type_ = Type::NewNonParameterizedType(cls);
+
   // Since TypeArguments objects are passed as function arguments, make them
   // behave as Dart instances, although they are just VM objects.
   // Note that we cannot set the super type to ObjectType, which does not live
@@ -1082,7 +1095,7 @@
 
 void Object::FinishInit(Isolate* isolate) {
   // The type testing stubs we initialize in AbstractType objects for the
-  // canonical type of kDynamicCid/kVoidCid need to be set in this
+  // canonical type of kDynamicCid/kVoidCid/kNeverCid need to be set in this
   // method, which is called after StubCode::InitOnce().
   Code& code = Code::Handle();
 
@@ -1091,6 +1104,9 @@
 
   code = TypeTestingStubGenerator::DefaultCodeForType(*void_type_);
   void_type_->SetTypeTestingStub(code);
+
+  code = TypeTestingStubGenerator::DefaultCodeForType(*never_type_);
+  never_type_->SetTypeTestingStub(code);
 }
 
 void Object::Cleanup() {
@@ -1098,6 +1114,7 @@
   class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+  never_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -1198,6 +1215,7 @@
   SET_CLASS_NAME(class, Class);
   SET_CLASS_NAME(dynamic, Dynamic);
   SET_CLASS_NAME(void, Void);
+  SET_CLASS_NAME(never, Never);
   SET_CLASS_NAME(type_arguments, TypeArguments);
   SET_CLASS_NAME(patch_class, PatchClass);
   SET_CLASS_NAME(function, Function);
@@ -1918,6 +1936,7 @@
     cls = object_store->null_class();
     type = Type::NewNonParameterizedType(cls);
     object_store->set_null_type(type);
+    ASSERT(type.IsNullable());
 
     // Consider removing when/if Null becomes an ordinary class.
     type = object_store->object_type();
@@ -2202,7 +2221,11 @@
 }
 
 void Object::InitializeObject(uword address, intptr_t class_id, intptr_t size) {
-  uword cur = address;
+  // Note: we skip the header word here because it confuses TSAN. TSAN records
+  // an 8-byte write from the this loop, but doesn't overwrite that entry with
+  // the 4-byte relaxed store of the header below, then reports false data races
+  // based on the record of the 8-byte write.
+  uword cur = address + sizeof(RawObject);
   uword end = address + size;
   if (class_id == kInstructionsCid) {
     compiler::target::uword initial_value =
@@ -2306,12 +2329,16 @@
   InitializeObject(address, cls_id, size);
   RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
   ASSERT(cls_id == RawObject::ClassIdTag::decode(raw_obj->ptr()->tags_));
-  if (raw_obj->IsOldObject() && thread->is_marking()) {
+  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->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.
+    std::atomic_thread_fence(std::memory_order_release);
     heap->old_space()->AllocateBlack(size);
   }
   return raw_obj;
@@ -4046,6 +4073,8 @@
       return Symbols::Dynamic().raw();
     case kVoidCid:
       return Symbols::Void().raw();
+    case kNeverCid:
+      return Symbols::Never().raw();
     case kClassCid:
       return Symbols::Class().raw();
     case kTypeArgumentsCid:
@@ -4303,6 +4332,11 @@
   ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
   ASSERT((declaration_type() == Object::null()) ||
          (declaration_type() == value.raw()));  // Set during own finalization.
+  // TODO(regis): Since declaration type is used as the runtime type of
+  // instances of a non-generic class, the nullability should be set to
+  // kNonNullable instead of kLegacy.
+  // For now, we set the nullability to kLegacy, except for Null.
+  ASSERT(value.IsLegacy() || (value.IsNullType() && value.IsNullable()));
   StorePointer(&raw_ptr()->declaration_type_, value.raw());
 }
 
@@ -5853,7 +5887,6 @@
 
 void Function::AttachBytecode(const Bytecode& value) const {
   DEBUG_ASSERT(IsMutatorOrAtSafepoint());
-  ASSERT(FLAG_enable_interpreter || FLAG_use_bytecode_compiler);
   ASSERT(!value.IsNull());
   // Finish setting up code before activating it.
   if (!value.InVMIsolateHeap()) {
@@ -6251,7 +6284,7 @@
   FfiTrampolineData::Cast(obj).set_callback_exceptional_return(value);
 }
 
-RawType* Function::SignatureType() const {
+RawType* 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
@@ -6286,10 +6319,11 @@
         TypeArguments::Handle(scope_class.type_parameters());
     // Return the still unfinalized signature type.
     type = Type::New(scope_class, signature_type_arguments, token_pos());
+    type.set_nullability(nullability);
     type.set_signature(*this);
     SetSignatureType(type);
   }
-  return type.raw();
+  return type.ToNullability(nullability, Heap::kOld);
 }
 
 void Function::SetSignatureType(const Type& value) const {
@@ -6696,7 +6730,7 @@
   set_is_optimizable(value);
   if (!value) {
     set_is_inlinable(false);
-    set_usage_counter(INT_MIN);
+    set_usage_counter(INT32_MIN);
   }
 }
 
@@ -8033,43 +8067,36 @@
   Zone* zone = Thread::Current()->zone();
   const Script& func_script = Script::Handle(zone, script());
 
-  if (func_script.kind() == RawScript::kKernelTag) {
-    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;
+  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);
 
-    if (to_length == 1) {
-      // Handle special cases for end tokens of closures (where we exclude the
-      // last token):
-      // (1) "foo(() => null, bar);": End token is `,', but we don't print it.
-      // (2) "foo(() => null);": End token is ')`, but we don't print it.
-      // (3) "var foo = () => null;": End token is `;', but in this case the
-      // 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();
-      }
-      uint16_t end_char = src.CharAt(end_token_pos().value());
-      if ((end_char == ',') ||  // Case 1.
-          (end_char == ')') ||  // Case 2.
-          (end_char == ';' &&
-           String::Handle(zone, name())
-               .Equals("<anonymous closure>"))) {  // Case 3.
-        to_length = 0;
-      }
+  if (to_length == 1) {
+    // Handle special cases for end tokens of closures (where we exclude the
+    // last token):
+    // (1) "foo(() => null, bar);": End token is `,', but we don't print it.
+    // (2) "foo(() => null);": End token is ')`, but we don't print it.
+    // (3) "var foo = () => null;": End token is `;', but in this case the
+    // 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 func_script.GetSnippet(from_line, from_col, to_line,
-                                  to_col + to_length);
+    uint16_t end_char = src.CharAt(end_token_pos().value());
+    if ((end_char == ',') ||  // Case 1.
+        (end_char == ')') ||  // Case 2.
+        (end_char == ';' && String::Handle(zone, name())
+                                .Equals("<anonymous closure>"))) {  // Case 3.
+      to_length = 0;
+    }
   }
 
-  UNREACHABLE();
-  return String::null();
+  return func_script.GetSnippet(from_line, from_col, to_line,
+                                to_col + to_length);
 }
 
 // Construct fingerprint from token stream. The token stream contains also
@@ -8157,12 +8184,13 @@
 }
 
 void Function::set_ic_data_array(const Array& value) const {
-  StorePointer<RawArray*, MemoryOrder::kRelease>(&raw_ptr()->ic_data_array_,
-                                                 value.raw());
+  StorePointer<RawArray*, std::memory_order_release>(&raw_ptr()->ic_data_array_,
+                                                     value.raw());
 }
 
 RawArray* Function::ic_data_array() const {
-  return AtomicOperations::LoadAcquire(&raw_ptr()->ic_data_array_);
+  return LoadPointer<RawArray*, std::memory_order_acquire>(
+      &raw_ptr()->ic_data_array_);
 }
 
 void Function::ClearICDataArray() const {
@@ -8205,6 +8233,12 @@
     return true;
   }
 
+  if (KernelIsolate::GetExperimentalFlag("non-nullable")) {
+    // The non-nullable experiment changes the fingerprints, and we only track
+    // one fingerprint set.
+    return true;
+  }
+
   if (SourceFingerprint() != fp) {
     const bool recalculatingFingerprints = false;
     if (recalculatingFingerprints) {
@@ -8916,7 +8950,7 @@
 }
 
 RawFunction* Field::EnsureInitializerFunction() const {
-  ASSERT(is_static() && has_initializer());
+  ASSERT(has_initializer());
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Function& initializer = Function::Handle(zone, InitializerFunction());
@@ -8940,7 +8974,32 @@
   return raw_ptr()->initializer_function_ != Function::null();
 }
 
-RawError* Field::Initialize() const {
+RawError* Field::InitializeInstance(const Instance& instance) const {
+  ASSERT(IsOriginal());
+  ASSERT(is_instance());
+  ASSERT(instance.GetField(*this) == Object::sentinel().raw());
+  Object& value = Object::Handle();
+  if (has_initializer()) {
+    const Function& initializer = Function::Handle(EnsureInitializerFunction());
+    const Array& args = Array::Handle(Array::New(1));
+    args.SetAt(0, instance);
+    value = DartEntry::InvokeFunction(initializer, args);
+    if (!value.IsNull() && value.IsError()) {
+      return Error::Cast(value).raw();
+    }
+  } else {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    UNREACHABLE();
+#else
+    value = saved_initial_value();
+#endif
+  }
+  ASSERT(value.IsNull() || value.IsInstance());
+  instance.SetField(*this, value);
+  return Error::null();
+}
+
+RawError* Field::InitializeStatic() const {
   ASSERT(IsOriginal());
   ASSERT(is_static());
   if (StaticValue() == Object::sentinel().raw()) {
@@ -9477,7 +9536,7 @@
     for (intptr_t i = 0; i < libs.Length(); i++) {
       lib ^= libs.At(i);
       script = lib.LookupScript(uri, /* useResolvedUri = */ true);
-      if (!script.IsNull() && script.kind() == RawScript::kKernelTag) {
+      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()) {
@@ -9493,7 +9552,6 @@
 }
 
 RawGrowableObjectArray* Script::GenerateLineNumberArray() const {
-  ASSERT(kind() == RawScript::kKernelTag);
   Zone* zone = Thread::Current()->zone();
   const GrowableObjectArray& info =
       GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
@@ -9548,25 +9606,6 @@
   return info.raw();
 }
 
-const char* Script::GetKindAsCString() const {
-  switch (kind()) {
-    case RawScript::kScriptTag:
-      return "script";
-    case RawScript::kLibraryTag:
-      return "library";
-    case RawScript::kSourceTag:
-      return "source";
-    case RawScript::kEvaluateTag:
-      return "evaluate";
-    case RawScript::kKernelTag:
-      return "kernel";
-    default:
-      UNIMPLEMENTED();
-  }
-  UNREACHABLE();
-  return NULL;
-}
-
 void Script::set_url(const String& value) const {
   StorePointer(&raw_ptr()->url_, value.raw());
 }
@@ -9621,7 +9660,7 @@
 RawArray* Script::debug_positions() const {
 #if !defined(DART_PRECOMPILED_RUNTIME)
   Array& debug_positions_array = Array::Handle(raw_ptr()->debug_positions_);
-  if (debug_positions_array.IsNull() && kind() == RawScript::kKernelTag) {
+  if (debug_positions_array.IsNull()) {
     // This is created lazily. Now we need it.
     kernel::CollectTokenPositionsFor(*this);
   }
@@ -9629,23 +9668,17 @@
   return raw_ptr()->debug_positions_;
 }
 
-void Script::set_kind(RawScript::Kind value) const {
-  set_kind_and_tags(
-      RawScript::KindBits::update(value, raw_ptr()->kind_and_tags_));
-}
-
-void Script::set_kind_and_tags(uint8_t value) const {
-  StoreNonPointer(&raw_ptr()->kind_and_tags_, value);
+void Script::set_flags(uint8_t value) const {
+  StoreNonPointer(&raw_ptr()->flags_, value);
 }
 
 void Script::SetLazyLookupSourceAndLineStarts(bool value) const {
-  set_kind_and_tags(RawScript::LazyLookupSourceAndLineStartsBit::update(
-      value, raw_ptr()->kind_and_tags_));
+  set_flags(RawScript::LazyLookupSourceAndLineStartsBit::update(
+      value, raw_ptr()->flags_));
 }
 
 bool Script::IsLazyLookupSourceAndLineStarts() const {
-  return RawScript::LazyLookupSourceAndLineStartsBit::decode(
-      raw_ptr()->kind_and_tags_);
+  return RawScript::LazyLookupSourceAndLineStartsBit::decode(raw_ptr()->flags_);
 }
 
 void Script::set_load_timestamp(int64_t value) const {
@@ -9669,36 +9702,17 @@
   }
   Zone* zone = Thread::Current()->zone();
   TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
+  // Scripts loaded from bytecode may have null line_starts().
   if (line_starts_data.IsNull()) {
-    ASSERT(kind() != RawScript::kKernelTag);
-    UNREACHABLE();
-  }
-
-  if (kind() == RawScript::kKernelTag) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-    kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
-    return line_starts_reader.LineNumberForPosition(target_token_pos.value());
-#else
     return 0;
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-  } else {
-    ASSERT(line_starts_data.Length() > 0);
-    intptr_t offset = target_token_pos.Pos();
-    intptr_t min = 0;
-    intptr_t max = line_starts_data.Length() - 1;
-
-    // Binary search to find the line containing this offset.
-    while (min < max) {
-      int midpoint = (max - min + 1) / 2 + min;
-      int32_t token_pos = line_starts_data.GetInt32(midpoint * 4);
-      if (token_pos > offset) {
-        max = midpoint - 1;
-      } else {
-        min = midpoint;
-      }
-    }
-    return min + 1;  // Line numbers start at 1.
   }
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+  kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
+  return line_starts_reader.LineNumberForPosition(target_token_pos.value());
+#else
+  return 0;
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -9726,7 +9740,6 @@
   ASSERT(line != NULL);
   Zone* zone = Thread::Current()->zone();
 
-  ASSERT(kind() == RawScript::kKernelTag);
   LookupSourceAndLineStarts(zone);
   if (line_starts() == TypedData::null()) {
     // Scripts in the AOT snapshot do not have a line starts array.
@@ -9765,7 +9778,6 @@
 void Script::TokenRangeAtLine(intptr_t line_number,
                               TokenPosition* first_token_index,
                               TokenPosition* last_token_index) const {
-  ASSERT(kind() == RawScript::kKernelTag);
   ASSERT(first_token_index != NULL && last_token_index != NULL);
   ASSERT(line_number > 0);
 
@@ -9903,16 +9915,13 @@
   return reinterpret_cast<RawScript*>(raw);
 }
 
-RawScript* Script::New(const String& url,
-                       const String& source,
-                       RawScript::Kind kind) {
-  return Script::New(url, url, source, kind);
+RawScript* Script::New(const String& url, const String& source) {
+  return Script::New(url, url, source);
 }
 
 RawScript* Script::New(const String& url,
                        const String& resolved_url,
-                       const String& source,
-                       RawScript::Kind kind) {
+                       const String& source) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Script& result = Script::Handle(zone, Script::New());
@@ -9921,8 +9930,7 @@
       String::Handle(zone, Symbols::New(thread, resolved_url)));
   result.set_source(source);
   result.SetLocationOffset(0, 0);
-  result.set_kind_and_tags(0);
-  result.set_kind(kind);
+  result.set_flags(0);
   result.set_kernel_script_index(0);
   result.set_load_timestamp(
       FLAG_remove_script_timestamps_for_test ? 0 : OS::GetCurrentTimeMillis());
@@ -12587,6 +12595,21 @@
   return "Instructions";
 }
 
+CodeStatistics* Instructions::stats() const {
+#if defined(DART_PRECOMPILER)
+  return reinterpret_cast<CodeStatistics*>(
+      Thread::Current()->heap()->GetPeer(raw()));
+#else
+  return nullptr;
+#endif
+}
+
+void Instructions::set_stats(CodeStatistics* stats) const {
+#if defined(DART_PRECOMPILER)
+  Thread::Current()->heap()->SetPeer(raw(), stats);
+#endif
+}
+
 // Encode integer |value| in SLEB128 format and store into |data|.
 static void EncodeSLEB128(GrowableArray<uint8_t>* data, intptr_t value) {
   bool is_last_part = false;
@@ -13427,8 +13450,8 @@
 
 void ICData::set_entries(const Array& value) const {
   ASSERT(!value.IsNull());
-  StorePointer<RawArray*, MemoryOrder::kRelease>(&raw_ptr()->entries_,
-                                                 value.raw());
+  StorePointer<RawArray*, std::memory_order_release>(&raw_ptr()->entries_,
+                                                     value.raw());
 }
 
 intptr_t ICData::NumArgsTested() const {
@@ -15164,17 +15187,12 @@
 }
 
 void Code::DisableStubCode() const {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(Thread::Current()->IsMutatorThread());
   ASSERT(IsAllocationStubCode());
   ASSERT(instructions() == active_instructions());
   const Code& new_code = StubCode::FixAllocationStubTarget();
   SetActiveInstructions(Instructions::Handle(new_code.instructions()));
   StoreNonPointer(&raw_ptr()->unchecked_entry_point_, raw_ptr()->entry_point_);
-#else
-  // DBC does not use allocation stubs.
-  UNIMPLEMENTED();
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 void Code::SetActiveInstructions(const Instructions& instructions) const {
@@ -16993,6 +17011,12 @@
   return TokenPosition::kNoSource;
 }
 
+Nullability AbstractType::nullability() const {
+  // AbstractType is an abstract class.
+  UNREACHABLE();
+  return kNullable;
+}
+
 bool AbstractType::IsInstantiated(Genericity genericity,
                                   intptr_t num_free_fun_type_params,
                                   TrailPtr trail) const {
@@ -17172,11 +17196,19 @@
   return Symbols::FromConcatAll(thread, pieces);
 }
 
+// Keep in sync with Nullability enum in runtime/vm/object.h.
+static const char* nullability_suffix[4] = {"%", "?", "", "*"};
+
 RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
   ASSERT(name_visibility != kScrubbedName);
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   if (IsTypeParameter()) {
+    if (FLAG_show_nullability) {
+      return Symbols::FromConcat(
+          thread, String::Handle(zone, TypeParameter::Cast(*this).name()),
+          String::Handle(zone, String::New(nullability_suffix[nullability()])));
+    }
     return TypeParameter::Cast(*this).name();
   }
   const TypeArguments& args = TypeArguments::Handle(zone, arguments());
@@ -17189,6 +17221,13 @@
     const Function& signature_function =
         Function::Handle(zone, Type::Cast(*this).signature());
     if (!cls.IsTypedefClass()) {
+      if (FLAG_show_nullability) {
+        return Symbols::FromConcat(
+            thread,
+            String::Handle(zone, signature_function.UserVisibleSignature()),
+            String::Handle(zone,
+                           String::New(nullability_suffix[nullability()])));
+      }
       return signature_function.UserVisibleSignature();
     }
     // Instead of printing the actual signature, use the typedef name with
@@ -17196,6 +17235,12 @@
     class_name = cls.Name();  // Typedef name.
     if (!IsFinalized() || IsBeingFinalized()) {
       // TODO(regis): Check if this is dead code.
+      if (FLAG_show_nullability) {
+        return Symbols::FromConcat(
+            thread, String::Handle(zone, class_name.raw()),
+            String::Handle(zone,
+                           String::New(nullability_suffix[nullability()])));
+      }
       return class_name.raw();
     }
     // Print the name of a typedef as a regular, possibly parameterized, class.
@@ -17236,6 +17281,10 @@
                                  name_visibility));
     pieces.Add(args_name);
   }
+  if (FLAG_show_nullability) {
+    pieces.Add(
+        String::Handle(zone, String::New(nullability_suffix[nullability()])));
+  }
   // The name is only used for type checking and debugging purposes.
   // Unless profiling data shows otherwise, it is not worth caching the name in
   // the type.
@@ -17252,30 +17301,28 @@
 }
 
 bool AbstractType::IsDynamicType() const {
-  if (IsCanonical()) {
-    return raw() == Object::dynamic_type().raw();
-  }
   return type_class_id() == kDynamicCid;
 }
 
 bool AbstractType::IsVoidType() const {
-  // The void type is always canonical, because void is a keyword.
-  return raw() == Object::void_type().raw();
+  return type_class_id() == kVoidCid;
+}
+
+bool AbstractType::IsNeverType() const {
+  return type_class_id() == kNeverCid;
 }
 
 bool AbstractType::IsObjectType() const {
   return type_class_id() == kInstanceCid;
 }
 
-bool AbstractType::IsTopType() const {
-  if (IsVoidType()) {
-    return true;
-  }
+bool AbstractType::IsTopType(NNBDMode mode) const {
   const classid_t cid = type_class_id();
   if (cid == kIllegalCid) {
     return false;
   }
-  if ((cid == kDynamicCid) || (cid == kInstanceCid)) {
+  if (cid == kDynamicCid || cid == kVoidCid ||
+      (cid == kInstanceCid && (mode != kStrong || IsNullable()))) {
     return true;
   }
   // FutureOr<T> where T is a top type behaves as a top type.
@@ -17289,7 +17336,7 @@
         TypeArguments::Handle(zone, arguments());
     const AbstractType& type_arg =
         AbstractType::Handle(zone, type_arguments.TypeAt(0));
-    if (type_arg.IsTopType()) {
+    if (type_arg.IsTopType(mode)) {
       return true;
     }
   }
@@ -17516,7 +17563,8 @@
   if (stub.IsNull()) {
     // This only happens during bootstrapping when creating Type objects before
     // we have the instructions.
-    ASSERT(type_class_id() == kDynamicCid || type_class_id() == kVoidCid);
+    ASSERT(type_class_id() == kDynamicCid || type_class_id() == kVoidCid ||
+           type_class_id() == kNeverCid);
     StoreNonPointer(&raw_ptr()->type_test_stub_entry_point_, 0);
   } else {
     StoreNonPointer(&raw_ptr()->type_test_stub_entry_point_, stub.EntryPoint());
@@ -17536,6 +17584,10 @@
   return Object::void_type().raw();
 }
 
+RawType* Type::NeverType() {
+  return Object::never_type().raw();
+}
+
 RawType* Type::ObjectType() {
   return Isolate::Current()->object_store()->object_type();
 }
@@ -17628,6 +17680,24 @@
   set_type_state(RawType::kBeingFinalized);
 }
 
+RawType* Type::ToNullability(Nullability value, Heap::Space space) const {
+  if (nullability() == value) {
+    return raw();
+  }
+  // Clone type and set new nullability.
+  Type& type = Type::Handle();
+  type ^= Object::Clone(*this, space);
+  type.set_nullability(value);
+  type.SetHash(0);
+  if (IsCanonical()) {
+    // Object::Clone does not clone canonical bit.
+    ASSERT(!type.IsCanonical());
+    type ^= type.Canonicalize();
+  }
+  // TODO(regis): Should we link canonical types of different nullability?
+  return type.raw();
+}
+
 RawFunction* Type::signature() const {
   intptr_t cid = raw_ptr()->signature_->GetClassId();
   if (cid == kNullCid) {
@@ -17783,6 +17853,9 @@
   if (type_class_id() != other_type.type_class_id()) {
     return false;
   }
+  if (nullability() != other_type.nullability()) {
+    return false;
+  }
   if (!IsFinalized() || !other_type.IsFinalized()) {
     return false;  // Too early to decide if equal.
   }
@@ -17932,11 +18005,18 @@
     return Object::dynamic_type().raw();
   }
 
+  if ((type_class_id() == kNeverCid) && (isolate != Dart::vm_isolate())) {
+    ASSERT(Object::never_type().IsCanonical());
+    return Object::never_type().raw();
+  }
+
   const Class& cls = Class::Handle(zone, type_class());
 
   // Fast canonical lookup/registry for simple types.
-  if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
+  if (IsNullType() || (IsLegacy() && !cls.IsGeneric() &&
+                       !cls.IsClosureClass() && !cls.IsTypedefClass())) {
     ASSERT(!IsFunctionType());
+    ASSERT(!IsNullType() || IsNullable());
     Type& type = Type::Handle(zone, cls.declaration_type());
     if (type.IsNull()) {
       ASSERT(!cls.raw()->InVMIsolateHeap() || (isolate == Dart::vm_isolate()));
@@ -18060,8 +18140,10 @@
   const Class& cls = Class::Handle(zone, type_class());
 
   // Fast canonical lookup/registry for simple types.
-  if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
+  if (IsNullType() || (IsLegacy() && !cls.IsGeneric() &&
+                       !cls.IsClosureClass() && !cls.IsTypedefClass())) {
     ASSERT(!IsFunctionType());
+    ASSERT(!IsNullType() || IsNullable());
     type = cls.declaration_type();
     return (raw() == type.raw());
   }
@@ -18112,6 +18194,7 @@
   ASSERT(IsFinalized());
   uint32_t result = 1;
   result = CombineHashes(result, type_class_id());
+  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
   result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
   if (IsFunctionType()) {
     const Function& sig_fun = Function::Handle(signature());
@@ -18163,6 +18246,11 @@
   result.SetHash(0);
   result.set_token_pos(token_pos);
   result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
+  if (clazz.id() == kNullCid) {
+    result.set_nullability(kNullable);
+  } else {
+    result.set_nullability(kLegacy);
+  }
 
   result.SetTypeTestingStub(
       Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
@@ -18323,7 +18411,8 @@
   //    type arguments are set).
   const AbstractType& ref_type = AbstractType::Handle(type());
   ASSERT(!ref_type.IsNull());
-  const uint32_t result = Class::Handle(ref_type.type_class()).id();
+  uint32_t result = Class::Handle(ref_type.type_class()).id();
+  result = CombineHashes(result, static_cast<uint32_t>(ref_type.nullability()));
   return FinalizeHash(result, kHashBits);
 }
 
@@ -18368,6 +18457,24 @@
       value, raw_ptr()->flags_));
 }
 
+void TypeParameter::set_nullability(Nullability value) const {
+  StoreNonPointer(&raw_ptr()->nullability_, value);
+}
+
+RawTypeParameter* TypeParameter::ToNullability(Nullability value,
+                                               Heap::Space space) const {
+  if (nullability() == value) {
+    return raw();
+  }
+  // Clone type and set new nullability.
+  TypeParameter& type_parameter = TypeParameter::Handle();
+  type_parameter ^= Object::Clone(*this, space);
+  type_parameter.set_nullability(value);
+  type_parameter.SetHash(0);
+  // TODO(regis): Should we link type parameters of different nullability?
+  return type_parameter.raw();
+}
+
 bool TypeParameter::IsInstantiated(Genericity genericity,
                                    intptr_t num_free_fun_type_params,
                                    TrailPtr trail) const {
@@ -18401,6 +18508,9 @@
   if (parameterized_function() != other_type_param.parameterized_function()) {
     return false;
   }
+  if (nullability() != other_type_param.nullability()) {
+    return false;
+  }
   if (IsFinalized() == other_type_param.IsFinalized()) {
     return (index() == other_type_param.index());
   }
@@ -18519,6 +18629,7 @@
   // No need to include the hash of the bound, since the type parameter is fully
   // identified by its class and index.
   result = CombineHashes(result, index());
+  result = CombineHashes(result, static_cast<uint32_t>(nullability()));
   result = FinalizeHash(result, kHashBits);
   SetHash(result);
   return result;
@@ -18546,6 +18657,7 @@
   result.set_name(name);
   result.set_bound(bound);
   result.set_flags(0);
+  result.set_nullability(kLegacy);
   result.SetGenericCovariantImpl(is_generic_covariant_impl);
   result.SetHash(0);
   result.set_token_pos(token_pos);
@@ -21696,7 +21808,9 @@
                          const Context& context,
                          Heap::Space space) {
   return Closure::New(instantiator_type_arguments, function_type_arguments,
-                      Object::empty_type_arguments(), function, context, space);
+                      function.IsGeneric() ? Object::empty_type_arguments()
+                                           : Object::null_type_arguments(),
+                      function, context, space);
 }
 
 RawClosure* Closure::New(const TypeArguments& instantiator_type_arguments,
@@ -21862,11 +21976,7 @@
     line = token_pos.value();
   } else {
     if (!script.IsNull() && token_pos.IsSourcePosition()) {
-      if (script.HasSource() || script.kind() == RawScript::kKernelTag) {
-        script.GetTokenLocation(token_pos.SourcePosition(), &line, &column);
-      } else {
-        script.GetTokenLocation(token_pos.SourcePosition(), &line, NULL);
-      }
+      script.GetTokenLocation(token_pos.SourcePosition(), &line, &column);
     }
   }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1595e42..f64b4b0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -433,6 +433,7 @@
   V(Array, vm_isolate_snapshot_object_table)                                   \
   V(Type, dynamic_type)                                                        \
   V(Type, void_type)                                                           \
+  V(Type, never_type)                                                          \
   V(AbstractType, null_abstract_type)
 
 #define DEFINE_SHARED_READONLY_HANDLE_GETTER(Type, name)                       \
@@ -448,6 +449,7 @@
   static RawClass* class_class() { return class_class_; }
   static RawClass* dynamic_class() { return dynamic_class_; }
   static RawClass* void_class() { return void_class_; }
+  static RawClass* never_class() { return never_class_; }
   static RawClass* type_arguments_class() { return type_arguments_class_; }
   static RawClass* patch_class_class() { return patch_class_class_; }
   static RawClass* function_class() { return function_class_; }
@@ -590,7 +592,12 @@
   // methods below or their counterparts in RawObject, to ensure that the
   // write barrier is correctly applied.
 
-  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
+  type LoadPointer(type const* addr) const {
+    return raw()->LoadPointer<type, order>(addr);
+  }
+
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StorePointer(type const* addr, type value) const {
     raw()->StorePointer<type, order>(addr, value);
   }
@@ -615,27 +622,20 @@
     *const_cast<FieldType*>(addr) = value;
   }
 
-  template <typename FieldType, typename ValueType, MemoryOrder order>
+  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) >= RawObject::ToAddr(raw()));
-
-    if (order == MemoryOrder::kRelease) {
-      AtomicOperations::StoreRelease(const_cast<FieldType*>(addr), value);
-    } else {
-      ASSERT(order == MemoryOrder::kRelaxed);
-      StoreNonPointer<FieldType, ValueType>(addr, value);
-    }
+    reinterpret_cast<std::atomic<FieldType>*>(const_cast<FieldType*>(addr))
+        ->store(value, order);
   }
 
-  template <typename FieldType, MemoryOrder order = MemoryOrder::kRelaxed>
+  template <typename FieldType,
+            std::memory_order order = std::memory_order_relaxed>
   FieldType LoadNonPointer(const FieldType* addr) const {
-    if (order == MemoryOrder::kAcquire) {
-      return AtomicOperations::LoadAcquire(const_cast<FieldType*>(addr));
-    } else {
-      ASSERT(order == MemoryOrder::kRelaxed);
-      return *const_cast<FieldType*>(addr);
-    }
+    return reinterpret_cast<std::atomic<FieldType>*>(
+               const_cast<FieldType*>(addr))
+        ->load(order);
   }
 
   // Provides non-const access to non-pointer fields within the object. Such
@@ -721,6 +721,7 @@
   static RawClass* class_class_;             // Class of the Class vm object.
   static RawClass* dynamic_class_;           // Class of the 'dynamic' type.
   static RawClass* void_class_;              // Class of the 'void' type.
+  static RawClass* never_class_;             // Class of the 'Never' type.
   static RawClass* type_arguments_class_;  // Class of TypeArguments vm object.
   static RawClass* patch_class_class_;     // Class of the PatchClass vm object.
   static RawClass* function_class_;        // Class of the Function vm object.
@@ -1041,6 +1042,9 @@
   // Check if this class represents the 'void' class.
   bool IsVoidClass() const { return id() == kVoidCid; }
 
+  // Check if this class represents the 'Never' class.
+  bool IsNeverClass() const { return id() == kNeverCid; }
+
   // Check if this class represents the 'Object' class.
   bool IsObjectClass() const { return id() == kInstanceCid; }
 
@@ -1828,7 +1832,7 @@
 
     // 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, MemoryOrder::kRelease>(
+    StoreNonPointer<uint32_t, uint32_t, std::memory_order_release>(
         &raw_ptr()->state_bits_, updated_bits);
   }
 
@@ -2020,7 +2024,8 @@
   intptr_t FindCheck(const GrowableArray<intptr_t>& cids) const;
 
   RawArray* entries() const {
-    return AtomicOperations::LoadAcquire(&raw_ptr()->entries_);
+    return LoadPointer<RawArray*, std::memory_order_acquire>(
+        &raw_ptr()->entries_);
   }
 
  private:
@@ -2049,7 +2054,7 @@
   bool is_megamorphic() const {
     // Ensure any following load instructions do not get performed before this
     // one.
-    const uint32_t bits = LoadNonPointer<uint32_t, MemoryOrder::kAcquire>(
+    const uint32_t bits = LoadNonPointer<uint32_t, std::memory_order_acquire>(
         &raw_ptr()->state_bits_);
     return MegamorphicBit::decode(bits);
   }
@@ -2125,6 +2130,21 @@
   friend class SnapshotWriter;
 };
 
+// Keep in sync with package:kernel/lib/ast.dart
+enum Nullability {
+  kUndetermined = 0,
+  kNullable = 1,
+  kNonNullable = 2,
+  kLegacy = 3,
+};
+
+// Nullability aware subtype checking modes.
+enum NNBDMode {
+  kUnaware,
+  kWeak,
+  kStrong,
+};
+
 // Often used constants for number of free function type parameters.
 enum {
   kNoneFree = 0,
@@ -2164,7 +2184,8 @@
   // 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.
-  RawType* SignatureType() const;
+  // A function type is non-nullable by default.
+  RawType* SignatureType(Nullability nullability = kNonNullable) const;
   RawType* ExistingSignatureType() const;
 
   // Update the signature type (with a canonical version).
@@ -2730,14 +2751,10 @@
     if (IsFfiTrampoline()) {
       return true;
     }
-    // On DBC we use native calls instead of IR for the view factories (see
-    // kernel_to_il.cc)
-#if !defined(TARGET_ARCH_DBC)
     if (IsTypedDataViewFactory() || IsFfiLoad() || IsFfiStore() ||
         IsFfiFromAddress() || IsFfiGetAddress()) {
       return true;
     }
-#endif
     return false;
   }
 
@@ -3407,6 +3424,9 @@
   bool is_extension_member() const {
     return IsExtensionMemberBit::decode(raw_ptr()->kind_bits_);
   }
+  bool needs_load_guard() const {
+    return NeedsLoadGuardBit::decode(raw_ptr()->kind_bits_);
+  }
   bool is_reflectable() const {
     return ReflectableBit::decode(raw_ptr()->kind_bits_);
   }
@@ -3693,6 +3713,9 @@
   void set_is_extension_member(bool value) const {
     set_kind_bits(IsExtensionMemberBit::update(value, raw_ptr()->kind_bits_));
   }
+  void set_needs_load_guard(bool value) const {
+    set_kind_bits(NeedsLoadGuardBit::update(value, raw_ptr()->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
@@ -3744,7 +3767,9 @@
   bool IsUninitialized() const;
 
   // Run initializer and set field value.
-  DART_WARN_UNUSED_RESULT RawError* Initialize() const;
+  DART_WARN_UNUSED_RESULT RawError* InitializeInstance(
+      const Instance& instance) const;
+  DART_WARN_UNUSED_RESULT RawError* InitializeStatic() const;
 
   // Run initializer only.
   DART_WARN_UNUSED_RESULT RawObject* EvaluateInitializer() const;
@@ -3805,6 +3830,7 @@
     kGenericCovariantImplBit,
     kIsLateBit,
     kIsExtensionMemberBit,
+    kNeedsLoadGuardBit,
   };
   class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
   class StaticBit : public BitField<uint16_t, bool, kStaticBit, 1> {};
@@ -3828,6 +3854,8 @@
   class IsLateBit : public BitField<uint16_t, bool, kIsLateBit, 1> {};
   class IsExtensionMemberBit
       : public BitField<uint16_t, bool, kIsExtensionMemberBit, 1> {};
+  class NeedsLoadGuardBit
+      : public BitField<uint16_t, bool, kNeedsLoadGuardBit, 1> {};
 
   // Update guarded cid and guarded length for this field. Returns true, if
   // deoptimization of dependent code is required.
@@ -3887,11 +3915,6 @@
   void LookupSourceAndLineStarts(Zone* zone) const;
   RawGrowableObjectArray* GenerateLineNumberArray() const;
 
-  RawScript::Kind kind() const {
-    return RawScript::KindBits::decode(raw_ptr()->kind_and_tags_);
-  }
-
-  const char* GetKindAsCString() const;
   intptr_t line_offset() const { return raw_ptr()->line_offset_; }
   intptr_t col_offset() const { return raw_ptr()->col_offset_; }
 
@@ -3956,14 +3979,11 @@
     return RoundedAllocationSize(sizeof(RawScript));
   }
 
-  static RawScript* New(const String& url,
-                        const String& source,
-                        RawScript::Kind kind);
+  static RawScript* New(const String& url, const String& source);
 
   static RawScript* New(const String& url,
                         const String& resolved_url,
-                        const String& source,
-                        RawScript::Kind kind);
+                        const String& source);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   void LoadSourceFromKernel(const uint8_t* kernel_buffer,
@@ -3976,8 +3996,7 @@
  private:
   void set_resolved_url(const String& value) const;
   void set_source(const String& value) const;
-  void set_kind(RawScript::Kind value) const;
-  void set_kind_and_tags(uint8_t value) const;
+  void set_flags(uint8_t value) const;
   void set_load_timestamp(int64_t value) const;
   RawArray* debug_positions() const;
 
@@ -4793,11 +4812,6 @@
   static const intptr_t kPolymorphicEntryOffsetJIT = 48;
   static const intptr_t kMonomorphicEntryOffsetAOT = 8;
   static const intptr_t kPolymorphicEntryOffsetAOT = 28;
-#elif defined(TARGET_ARCH_DBC)
-  static const intptr_t kMonomorphicEntryOffsetJIT = 0;
-  static const intptr_t kPolymorphicEntryOffsetJIT = 0;
-  static const intptr_t kMonomorphicEntryOffsetAOT = 0;
-  static const intptr_t kPolymorphicEntryOffsetAOT = 0;
 #else
 #error Missing entry offsets for current architecture
 #endif
@@ -4842,7 +4856,7 @@
 
   static const intptr_t kMaxElements =
       (kMaxInt32 - (sizeof(RawInstructions) + sizeof(RawObject) +
-                    (2 * OS::kMaxPreferredCodeAlignment)));
+                    (2 * kMaxObjectAlignment)));
 
   static intptr_t InstanceSize() {
     ASSERT(sizeof(RawInstructions) ==
@@ -4851,18 +4865,11 @@
   }
 
   static intptr_t InstanceSize(intptr_t size) {
-    intptr_t instructions_size =
-        Utils::RoundUp(size, OS::PreferredCodeAlignment());
-    intptr_t result = instructions_size + HeaderSize();
-    ASSERT(result % OS::PreferredCodeAlignment() == 0);
-    return result;
+    return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
   }
 
   static intptr_t HeaderSize() {
-    const intptr_t alignment = OS::PreferredCodeAlignment();
-    const intptr_t aligned_size =
-        Utils::RoundUp(sizeof(RawInstructions), alignment);
-    return aligned_size;
+    return Utils::RoundUp(sizeof(RawInstructions), kWordSize);
   }
 
   static RawInstructions* FromPayloadStart(uword payload_start) {
@@ -4880,19 +4887,8 @@
     return memcmp(a->ptr(), b->ptr(), InstanceSize(Size(a))) == 0;
   }
 
-  CodeStatistics* stats() const {
-#if defined(DART_PRECOMPILER)
-    return raw_ptr()->stats_;
-#else
-    return nullptr;
-#endif
-  }
-
-  void set_stats(CodeStatistics* stats) const {
-#if defined(DART_PRECOMPILER)
-    StoreNonPointer(&raw_ptr()->stats_, stats);
-#endif
-  }
+  CodeStatistics* stats() const;
+  void set_stats(CodeStatistics* stats) const;
 
   uword unchecked_entrypoint_pc_offset() const {
     return raw_ptr()->unchecked_entrypoint_pc_offset_;
@@ -6799,6 +6795,13 @@
   virtual void SetIsFinalized() const;
   virtual bool IsBeingFinalized() const;
   virtual void SetIsBeingFinalized() const;
+
+  virtual Nullability nullability() const;
+  virtual bool IsUndetermined() const { return nullability() == kUndetermined; }
+  virtual bool IsNullable() const { return nullability() == kNullable; }
+  virtual bool IsNonNullable() const { return nullability() == kNonNullable; }
+  virtual bool IsLegacy() const { return nullability() == kLegacy; }
+
   virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
   virtual classid_t type_class_id() const;
   virtual RawClass* type_class() const;
@@ -6911,12 +6914,15 @@
   // Check if this type represents the 'Null' type.
   bool IsNullType() const;
 
+  // Check if this type represents the 'Never' type.
+  bool IsNeverType() const;
+
   // Check if this type represents the 'Object' type.
   bool IsObjectType() const;
 
-  // Check if this type represents a top type, i.e. 'dynamic', 'Object', or
-  // 'void' type.
-  bool IsTopType() const;
+  // Check if this type represents a top type.
+  // TODO(regis): Remove default kUnaware mode as implementation progresses.
+  bool IsTopType(NNBDMode mode = kUnaware) const;
 
   // Check if this type represents the 'bool' type.
   bool IsBoolType() const;
@@ -7024,6 +7030,15 @@
     ASSERT(type_class_id() != kIllegalCid);
     return true;
   }
+  virtual Nullability nullability() const {
+    return static_cast<Nullability>(raw_ptr()->nullability_);
+  }
+  void set_nullability(Nullability value) const {
+    ASSERT(!IsCanonical());
+    ASSERT(value != kUndetermined);
+    StoreNonPointer(&raw_ptr()->nullability_, value);
+  }
+  RawType* ToNullability(Nullability value, Heap::Space space) const;
   virtual classid_t type_class_id() const;
   virtual RawClass* type_class() const;
   void set_type_class(const Class& value) const;
@@ -7074,6 +7089,9 @@
   // The 'void' type.
   static RawType* VoidType();
 
+  // The 'Never' type.
+  static RawType* NeverType();
+
   // The 'Object' type.
   static RawType* ObjectType();
 
@@ -7155,6 +7173,11 @@
     const AbstractType& ref_type = AbstractType::Handle(type());
     return ref_type.IsNull() || ref_type.IsBeingFinalized();
   }
+  virtual Nullability nullability() const {
+    const AbstractType& ref_type = AbstractType::Handle(type());
+    ASSERT(!ref_type.IsNull());
+    return ref_type.nullability();
+  }
   virtual bool HasTypeClass() const {
     return (type() != AbstractType::null()) &&
            AbstractType::Handle(type()).HasTypeClass();
@@ -7231,6 +7254,11 @@
     return RawTypeParameter::GenericCovariantImplBit::decode(raw_ptr()->flags_);
   }
   void SetGenericCovariantImpl(bool value) const;
+  virtual Nullability nullability() const {
+    return static_cast<Nullability>(raw_ptr()->nullability_);
+  }
+  void set_nullability(Nullability value) const;
+  RawTypeParameter* 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;
@@ -8425,12 +8453,13 @@
 
   // Access to the array with acquire release semantics.
   RawObject* AtAcquire(intptr_t index) const {
-    return AtomicOperations::LoadAcquire(ObjectAddr(index));
+    return LoadPointer<RawObject*, std::memory_order_acquire>(
+        ObjectAddr(index));
   }
   void SetAtRelease(intptr_t index, const Object& value) const {
     // TODO(iposva): Add storing NoSafepointScope.
-    StoreArrayPointer<RawObject*, MemoryOrder::kRelease>(ObjectAddr(index),
-                                                         value.raw());
+    StoreArrayPointer<RawObject*, std::memory_order_release>(ObjectAddr(index),
+                                                             value.raw());
   }
 
   bool IsImmutable() const { return raw()->GetClassId() == kImmutableArrayCid; }
@@ -8537,7 +8566,7 @@
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
   }
 
-  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StoreArrayPointer(type const* addr, type value) const {
     raw()->StoreArrayPointer<type, order>(addr, value);
   }
diff --git a/runtime/vm/object_dbc_test.cc b/runtime/vm/object_dbc_test.cc
deleted file mode 100644
index 8ba27da..0000000
--- a/runtime/vm/object_dbc_test.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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.
-
-#include "platform/assert.h"
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/object.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#define __ assembler->
-
-// Generate a simple dart code sequence.
-// This is used to test Code and Instruction object creation.
-// For other architectures, this sequence does do an increment, hence the name.
-// On DBC, we don't do an increment because generating an instance call here
-// would be too complex.
-void GenerateIncrement(compiler::Assembler* assembler) {
-  __ Frame(1);
-  __ LoadConstant(0, Smi::Handle(Smi::New(1)));
-  __ Return(0);
-}
-
-// Generate a dart code sequence that embeds a string object in it.
-// This is used to test Embedded String objects in the instructions.
-void GenerateEmbedStringInCode(compiler::Assembler* assembler,
-                               const char* str) {
-  const String& string_object =
-      String::ZoneHandle(String::New(str, Heap::kOld));
-  __ PushConstant(string_object);
-  __ ReturnTOS();
-}
-
-// Generate a dart code sequence that embeds a smi object in it.
-// 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));
-  __ PushConstant(smi_object);
-  __ ReturnTOS();
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 6857b57..22591a2 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -93,7 +93,6 @@
 #endif
 }
 
-#if !defined(TARGET_ARCH_DBC)
 static void FindICData(const Array& ic_data_array,
                        intptr_t deopt_id,
                        ICData* ic_data) {
@@ -116,10 +115,8 @@
   }
   FATAL1("Missing deopt id %" Pd "\n", deopt_id);
 }
-#endif  // !defined(TARGET_ARCH_DBC)
 
 void CallSiteResetter::ResetSwitchableCalls(const Code& code) {
-#if !defined(TARGET_ARCH_DBC)
   if (code.is_optimized()) {
     return;  // No switchable calls in optimized code.
   }
@@ -177,7 +174,6 @@
       }
     }
   }
-#endif
 }
 
 void CallSiteResetter::RebindStaticTargets(const Bytecode& bytecode) {
@@ -263,13 +259,13 @@
   for (intptr_t i = 0; i < field_list.Length(); i++) {
     field = Field::RawCast(field_list.At(i));
     name = field.name();
-    if (field.is_static()) {
-      // Find the corresponding old field, if it exists, and migrate
-      // over the field value.
-      for (intptr_t j = 0; j < old_field_list.Length(); j++) {
-        old_field = Field::RawCast(old_field_list.At(j));
-        old_name = old_field.name();
-        if (name.Equals(old_name)) {
+    // Find the corresponding old field, if it exists, and migrate
+    // over the field value.
+    for (intptr_t j = 0; j < old_field_list.Length(); j++) {
+      old_field = Field::RawCast(old_field_list.At(j));
+      old_name = old_field.name();
+      if (name.Equals(old_name)) {
+        if (field.is_static()) {
           // We only copy values if requested and if the field is not a const
           // field. We let const fields be updated with a reload.
           if (update_values && !field.is_const()) {
@@ -277,6 +273,12 @@
             field.SetStaticValue(value);
           }
           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);
+          }
         }
       }
     }
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 02c90ac..7685888 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -426,7 +426,7 @@
                             lib_id.ToCString(), encoded_uri, load_timestamp());
   }
   jsobj.AddPropertyStr("uri", uri);
-  jsobj.AddProperty("_kind", GetKindAsCString());
+  jsobj.AddProperty("_kind", "kernel");
   if (ref) {
     return;
   }
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index a0ce9f9..684e06b 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -125,6 +125,7 @@
   RW(Function, complete_on_async_return)                                       \
   RW(Class, async_star_stream_controller)                                      \
   RW(Array, bytecode_attributes)                                               \
+  RW(Array, saved_unlinked_calls)                                              \
   RW(GrowableObjectArray, llvm_constant_pool)                                  \
   RW(GrowableObjectArray, llvm_function_pool)                                  \
   RW(Array, llvm_constant_hash_table)                                          \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index f748ed2..41a77bc 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2262,8 +2262,7 @@
   const char* source_chars = "This will not compile.";
   const String& url = String::Handle(String::New(url_chars));
   const String& source = String::Handle(String::New(source_chars));
-  const Script& script =
-      Script::Handle(Script::New(url, source, RawScript::kScriptTag));
+  const Script& script = Script::Handle(Script::New(url, source));
   EXPECT(!script.IsNull());
   EXPECT(script.IsScript());
   String& str = String::Handle(script.url());
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index af98eb1..a5fb739 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -67,14 +67,6 @@
   // the platform doesn't care. Guaranteed to be a power of two.
   static intptr_t ActivationFrameAlignment();
 
-  // This constant is guaranteed to be greater or equal to the
-  // preferred code alignment on all platforms.
-  static const int kMaxPreferredCodeAlignment = 32;
-
-  // Returns the preferred code alignment or zero if
-  // the platform doesn't care. Guaranteed to be a power of two.
-  static intptr_t PreferredCodeAlignment();
-
   // Returns number of available processor cores.
   static int NumberOfAvailableProcessors();
 
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 38168ad..7ac97ec4 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -181,13 +181,9 @@
 // into a architecture specific file e.g: os_ia32_linux.cc
 intptr_t OS::ActivationFrameAlignment() {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) ||                                              \
-    defined(TARGET_ARCH_DBC) &&                                                \
-        (defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) ||                  \
-         defined(HOST_ARCH_ARM64))
+    defined(TARGET_ARCH_ARM64)
   const int kMinimumAlignment = 16;
-#elif defined(TARGET_ARCH_ARM) ||                                              \
-    defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM)
+#elif defined(TARGET_ARCH_ARM)
   const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
@@ -201,25 +197,6 @@
   return alignment;
 }
 
-intptr_t OS::PreferredCodeAlignment() {
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  const int kMinimumAlignment = 32;
-#elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 16;
-#else
-#error Unsupported architecture.
-#endif
-  intptr_t alignment = kMinimumAlignment;
-  // TODO(5411554): Allow overriding default code alignment for
-  // testing purposes.
-  // Flags::DebugIsInt("codealign", &alignment);
-  ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(alignment >= kMinimumAlignment);
-  ASSERT(alignment <= OS::kMaxPreferredCodeAlignment);
-  return alignment;
-}
-
 int OS::NumberOfAvailableProcessors() {
   return sysconf(_SC_NPROCESSORS_ONLN);
 }
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 2641103..055a382 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -8,14 +8,7 @@
 #include "vm/os.h"
 
 #include <errno.h>
-#if defined(FUCHSIA_SDK)
 #include <fuchsia/deprecatedtimezone/cpp/fidl.h>
-namespace fuchsia {
-namespace timezone = deprecatedtimezone;
-}
-#else
-#include <fuchsia/timezone/cpp/fidl.h>
-#endif  //  defined(FUCHSIA_SDK)
 #include <lib/sys/cpp/service_directory.h>
 #include <zircon/process.h>
 #include <zircon/syscalls.h>
@@ -50,7 +43,7 @@
 // Putting this hack right now due to CP-120 as I need to remove
 // component:ConnectToEnvironmentServices and this is the only thing that is
 // blocking it and FL-98 will take time.
-static fuchsia::timezone::TimezoneSyncPtr tz;
+static fuchsia::deprecatedtimezone::TimezoneSyncPtr tz;
 
 static zx_status_t GetLocalAndDstOffsetInSeconds(int64_t seconds_since_epoch,
                                                  int32_t* local_offset,
@@ -125,13 +118,9 @@
 // into a architecture specific file e.g: os_ia32_fuchsia.cc
 intptr_t OS::ActivationFrameAlignment() {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) ||                                              \
-    defined(TARGET_ARCH_DBC) &&                                                \
-        (defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64) ||                  \
-         defined(HOST_ARCH_ARM64))
+    defined(TARGET_ARCH_ARM64)
   const int kMinimumAlignment = 16;
-#elif defined(TARGET_ARCH_ARM) ||                                              \
-    defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM)
+#elif defined(TARGET_ARCH_ARM)
   const int kMinimumAlignment = 8;
 #else
 #error Unsupported architecture.
@@ -145,25 +134,6 @@
   return alignment;
 }
 
-intptr_t OS::PreferredCodeAlignment() {
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  const int kMinimumAlignment = 32;
-#elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 16;
-#else
-#error Unsupported architecture.
-#endif
-  intptr_t alignment = kMinimumAlignment;
-  // TODO(5411554): Allow overriding default code alignment for
-  // testing purposes.
-  // Flags::DebugIsInt("codealign", &alignment);
-  ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(alignment >= kMinimumAlignment);
-  ASSERT(alignment <= OS::kMaxPreferredCodeAlignment);
-  return alignment;
-}
-
 int OS::NumberOfAvailableProcessors() {
   return sysconf(_SC_NPROCESSORS_CONF);
 }
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index 9baba7e..7034106 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -496,8 +496,7 @@
 // into a architecture specific file e.g: os_ia32_linux.cc
 intptr_t OS::ActivationFrameAlignment() {
 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  // DBC alignment should be at least as much as host architecture.
+    defined(TARGET_ARCH_ARM64)
   const int kMinimumAlignment = 16;
 #elif defined(TARGET_ARCH_ARM)
   const int kMinimumAlignment = 8;
@@ -513,25 +512,6 @@
   return alignment;
 }
 
-intptr_t OS::PreferredCodeAlignment() {
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  const int kMinimumAlignment = 32;
-#elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 16;
-#else
-#error Unsupported architecture.
-#endif
-  intptr_t alignment = kMinimumAlignment;
-  // TODO(5411554): Allow overriding default code alignment for
-  // testing purposes.
-  // Flags::DebugIsInt("codealign", &alignment);
-  ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(alignment >= kMinimumAlignment);
-  ASSERT(alignment <= OS::kMaxPreferredCodeAlignment);
-  return alignment;
-}
-
 int OS::NumberOfAvailableProcessors() {
   return sysconf(_SC_NPROCESSORS_ONLN);
 }
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 4788b6c..c18ca45 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -139,8 +139,6 @@
   return 16;  // iOS simulator
 #elif TARGET_ARCH_X64
   return 16;  // iOS simulator
-#elif TARGET_ARCH_DBC
-  return 16;  // Should be at least as much as any host architecture.
 #else
 #error Unimplemented
 #endif
@@ -151,25 +149,6 @@
 #endif  // HOST_OS_IOS
 }
 
-intptr_t OS::PreferredCodeAlignment() {
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  const int kMinimumAlignment = 32;
-#elif defined(TARGET_ARCH_ARM)
-  const int kMinimumAlignment = 16;
-#else
-#error Unsupported architecture.
-#endif
-  intptr_t alignment = kMinimumAlignment;
-  // TODO(5411554): Allow overriding default code alignment for
-  // testing purposes.
-  // Flags::DebugIsInt("codealign", &alignment);
-  ASSERT(Utils::IsPowerOfTwo(alignment));
-  ASSERT(alignment >= kMinimumAlignment);
-  ASSERT(alignment <= OS::kMaxPreferredCodeAlignment);
-  return alignment;
-}
-
 int OS::NumberOfAvailableProcessors() {
   return sysconf(_SC_NPROCESSORS_ONLN);
 }
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index 406edf6..331b3d2 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -35,7 +35,6 @@
 
 VM_UNIT_TEST_CASE(OsFuncs) {
   EXPECT(Utils::IsPowerOfTwo(OS::ActivationFrameAlignment()));
-  EXPECT(Utils::IsPowerOfTwo(OS::PreferredCodeAlignment()));
   int procs = OS::NumberOfAvailableProcessors();
   EXPECT_LE(1, procs);
 }
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 4185a08..3ef9f8f 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -44,8 +44,7 @@
       thread_(NULL) {
   // Try to get accurate stack bounds from pthreads, etc.
   if (!GetCurrentStackBounds(&stack_limit_, &stack_base_)) {
-    // Fall back to a guess based on the stack pointer.
-    RefineStackBoundsFromSP(GetCurrentStackPointer());
+    FATAL("Failed to retrieve stack bounds");
   }
 
   stack_headroom_ = CalculateHeadroom(stack_base_ - stack_limit_);
diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h
index 2479dfa..849d472 100644
--- a/runtime/vm/os_thread.h
+++ b/runtime/vm/os_thread.h
@@ -138,14 +138,7 @@
     return GetCurrentStackPointer() > (stack_limit_ + headroom);
   }
 
-  void RefineStackBoundsFromSP(uword sp) {
-    if (sp > stack_base_) {
-      stack_base_ = sp;
-      stack_limit_ = sp - GetSpecifiedStackSize();
-    }
-  }
-
-  // May fail for the main thread on Linux and Android.
+  // May fail for the main thread on Linux if resources are low.
   static bool GetCurrentStackBounds(uword* lower, uword* upper);
 
   // Returns the current C++ stack pointer. Equivalent taking the address of a
diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc
index 093795d..b8354e7 100644
--- a/runtime/vm/os_thread_android.cc
+++ b/runtime/vm/os_thread_android.cc
@@ -215,7 +215,7 @@
 }
 
 intptr_t OSThread::ThreadIdToIntPtr(ThreadId id) {
-  ASSERT(sizeof(id) == sizeof(intptr_t));
+  ASSERT(sizeof(id) <= sizeof(intptr_t));
   return static_cast<intptr_t>(id);
 }
 
@@ -229,7 +229,6 @@
 
 bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
   pthread_attr_t attr;
-  // May fail on the main thread.
   if (pthread_getattr_np(pthread_self(), &attr) != 0) {
     return false;
   }
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index c0f8e39..2ed4d87 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -175,11 +175,9 @@
 }
 
 intptr_t OS::ActivationFrameAlignment() {
-#if defined(TARGET_ARCH_ARM64) ||                                              \
-    defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM64)
+#if defined(TARGET_ARCH_ARM64)
   return 16;
-#elif defined(TARGET_ARCH_ARM) ||                                              \
-    defined(TARGET_ARCH_DBC) && defined(HOST_ARCH_ARM)
+#elif defined(TARGET_ARCH_ARM)
   return 8;
 #elif defined(_WIN64)
   // Windows 64-bit ABI requires the stack to be 16-byte aligned.
@@ -190,18 +188,6 @@
 #endif
 }
 
-intptr_t OS::PreferredCodeAlignment() {
-  ASSERT(32 <= OS::kMaxPreferredCodeAlignment);
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) ||                   \
-    defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC)
-  return 32;
-#elif defined(TARGET_ARCH_ARM)
-  return 16;
-#else
-#error Unsupported architecture.
-#endif
-}
-
 int OS::NumberOfAvailableProcessors() {
   SYSTEM_INFO info;
   GetSystemInfo(&info);
diff --git a/runtime/vm/pointer_tagging.h b/runtime/vm/pointer_tagging.h
index e4a59e6..487f3f8 100644
--- a/runtime/vm/pointer_tagging.h
+++ b/runtime/vm/pointer_tagging.h
@@ -51,6 +51,10 @@
 static constexpr intptr_t kObjectAlignmentMask =
     HostObjectAlignment::kObjectAlignmentMask;
 
+// The largest value of kObjectAlignment across all configurations.
+static constexpr intptr_t kMaxObjectAlignment = 16;
+COMPILE_ASSERT(kMaxObjectAlignment >= kObjectAlignment);
+
 // On all targets heap pointers are tagged by set least significant bit.
 //
 // To recover address of the actual heap object kHeapObjectTag needs to be
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 4362617..9b4e734 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -32,7 +32,7 @@
 
 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
 
-#if defined(TARGET_ARCH_ARM_6) || defined(TARGET_ARCH_ARM_5TE)
+#if defined(TARGET_ARCH_ARM_6)
 DEFINE_FLAG(int,
             profile_period,
             10000,
@@ -68,10 +68,10 @@
 
 #ifndef PRODUCT
 
-bool Profiler::initialized_ = false;
+RelaxedAtomic<bool> Profiler::initialized_ = false;
 SampleBuffer* Profiler::sample_buffer_ = NULL;
 AllocationSampleBuffer* Profiler::allocation_sample_buffer_ = NULL;
-ProfilerCounters Profiler::counters_;
+ProfilerCounters Profiler::counters_ = {};
 
 void Profiler::Init() {
   // Place some sane restrictions on user controlled flags.
@@ -82,11 +82,13 @@
   }
   ASSERT(!initialized_);
   SetSamplePeriod(FLAG_profile_period);
-  intptr_t capacity = CalculateSampleBufferCapacity();
-  sample_buffer_ = new SampleBuffer(capacity);
-  Profiler::InitAllocationSampleBuffer();
-  // Zero counters.
-  memset(&counters_, 0, sizeof(counters_));
+  // The profiler may have been shutdown previously, in which case the sample
+  // buffer will have already been initialized.
+  if (sample_buffer_ == NULL) {
+    intptr_t capacity = CalculateSampleBufferCapacity();
+    sample_buffer_ = new SampleBuffer(capacity);
+    Profiler::InitAllocationSampleBuffer();
+  }
   ThreadInterrupter::Init();
   ThreadInterrupter::Startup();
   initialized_ = true;
@@ -112,6 +114,15 @@
   delete sample_buffer_;
   sample_buffer_ = NULL;
 #endif
+  initialized_ = false;
+}
+
+void Profiler::UpdateRunningState() {
+  if (!FLAG_profiler && initialized_) {
+    Cleanup();
+  } else if (FLAG_profiler && !initialized_) {
+    Init();
+  }
 }
 
 void Profiler::SetSampleDepth(intptr_t depth) {
@@ -421,11 +432,6 @@
   ASSERT(return_address != NULL);
   return false;
 }
-#elif defined(TARGET_ARCH_DBC)
-bool ReturnAddressLocator::LocateReturnAddress(uword* return_address) {
-  ASSERT(return_address != NULL);
-  return false;
-}
 #else
 #error ReturnAddressLocator implementation missing for this architecture.
 #endif
@@ -1016,13 +1022,8 @@
     Isolate* isolate = thread->isolate();
     ASSERT(isolate != NULL);
     Simulator* simulator = isolate->simulator();
-#if defined(TARGET_ARCH_DBC)
-    *stack_lower = simulator->stack_base();
-    *stack_upper = simulator->stack_limit();
-#else
     *stack_lower = simulator->stack_limit();
     *stack_upper = simulator->stack_base();
-#endif  // defined(TARGET_ARCH_DBC)
   }
 #else
   const bool use_simulator_stack_bounds = false;
@@ -1070,7 +1071,7 @@
   Sample* sample = sample_buffer->ReserveSample();
   sample->Init(isolate->main_port(), OS::GetCurrentMonotonicMicros(), tid);
   uword vm_tag = thread->vm_tag();
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
+#if defined(USING_SIMULATOR)
   // When running in the simulator, the runtime entry function address
   // (stored as the vm tag) is the address of a redirect function.
   // Attempt to find the real runtime entry function address and use that.
@@ -1159,8 +1160,8 @@
   if (for_crash) {
     // Allow only one stack trace to prevent recursively printing stack traces
     // if we hit an assert while printing the stack.
-    static uintptr_t started_dump = 0;
-    if (AtomicOperations::FetchAndIncrement(&started_dump) != 0) {
+    static RelaxedAtomic<uintptr_t> started_dump = 0;
+    if (started_dump.fetch_add(1u) != 0) {
       OS::PrintErr("Aborting re-entrant request for stack trace.\n");
       return;
     }
@@ -1364,12 +1365,7 @@
 
   if (in_dart_code) {
 // If we're in Dart code, use the Dart stack pointer.
-#if defined(TARGET_ARCH_DBC)
-    simulator = isolate->simulator();
-    sp = simulator->get_sp();
-    fp = simulator->get_fp();
-    pc = simulator->get_pc();
-#elif defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR)
     simulator = isolate->simulator();
     sp = simulator->get_register(SPREG);
     fp = simulator->get_register(FPREG);
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 07355ef..1badec7 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_PROFILER_H_
 #define RUNTIME_VM_PROFILER_H_
 
+#include "platform/atomic.h"
+
 #include "vm/allocation.h"
 #include "vm/bitfield.h"
 #include "vm/code_observers.h"
@@ -63,6 +65,9 @@
   // Restarts sampling with a given profile period. This is called after the
   // profile period is changed via the service protocol.
   static void UpdateSamplePeriod();
+  // Starts or shuts down the profiler after --profiler is changed via the
+  // service protocol.
+  static void UpdateRunningState();
 
   static SampleBuffer* sample_buffer() { return sample_buffer_; }
   static AllocationSampleBuffer* allocation_sample_buffer() {
@@ -104,7 +109,7 @@
 
   // Does not walk the thread's stack.
   static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
-  static bool initialized_;
+  static RelaxedAtomic<bool> initialized_;
 
   static SampleBuffer* sample_buffer_;
   static AllocationSampleBuffer* allocation_sample_buffer_;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index e39faf0..d067f5f 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -290,14 +290,10 @@
       token_pos = token_pos.FromSynthetic();
     }
 
-    String& str = String::Handle(zone);
-    if (script.kind() == RawScript::kKernelTag) {
-      intptr_t line = 0, column = 0, token_len = 0;
-      script.GetTokenLocation(token_pos, &line, &column, &token_len);
-      str = script.GetSnippet(line, column, line, column + token_len);
-    } else {
-      UNREACHABLE();
-    }
+    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();
   }
 
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 1b827d7..5edf8e3 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -117,7 +117,6 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void ProgramVisitor::BindStaticCalls() {
-#if !defined(TARGET_ARCH_DBC)
   if (FLAG_precompiled_mode) {
     return;
   }
@@ -173,7 +172,6 @@
 
   BindJITStaticCallsVisitor visitor(Thread::Current()->zone());
   ProgramVisitor::VisitFunctions(&visitor);
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 void ProgramVisitor::ShareMegamorphicBuckets() {
@@ -859,12 +857,6 @@
 
     RawInstructions* DedupOneInstructions(const Function& function,
                                           const Code& code) {
-      // Switchable calls rely on a unique PC -> Code mapping atm, so we do not
-      // dedup any instructions for instance methods.
-      if (function.IsDynamicFunction()) {
-        return code.instructions();
-      }
-
       const Code* canonical = canonical_set_.LookupValue(&code);
       if (canonical == nullptr) {
         canonical_set_.Insert(&Code::ZoneHandle(zone_, code.raw()));
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index c624330..d3dd8b9 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -62,12 +62,6 @@
 #undef V
 };
 
-enum class MemoryOrder {
-  kRelaxed,
-  kRelease,
-  kAcquire,
-};
-
 #define SNAPSHOT_WRITER_SUPPORT()                                              \
   void WriteTo(SnapshotWriter* writer, intptr_t object_id,                     \
                Snapshot::Kind kind, bool as_reference);                        \
@@ -539,14 +533,16 @@
   // methods below or their counterparts in Object, to ensure that the
   // write barrier is correctly applied.
 
-  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
+  type LoadPointer(type const* addr) {
+    return reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
+        ->load(order);
+  }
+
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StorePointer(type const* addr, type value) {
-    if (order == MemoryOrder::kRelease) {
-      AtomicOperations::StoreRelease(const_cast<type*>(addr), value);
-    } else {
-      ASSERT(order == MemoryOrder::kRelaxed);
-      *const_cast<type*>(addr) = value;
-    }
+    reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
+        ->store(value, order);
     if (value->IsHeapObject()) {
       CheckHeapPointerStore(value, Thread::Current());
     }
@@ -588,14 +584,10 @@
     }
   }
 
-  template <typename type, MemoryOrder order = MemoryOrder::kRelaxed>
+  template <typename type, std::memory_order order = std::memory_order_relaxed>
   void StoreArrayPointer(type const* addr, type value) {
-    if (order == MemoryOrder::kRelease) {
-      AtomicOperations::StoreRelease(const_cast<type*>(addr), value);
-    } else {
-      ASSERT(order == MemoryOrder::kRelaxed);
-      *const_cast<type*>(addr) = value;
-    }
+    reinterpret_cast<std::atomic<type>*>(const_cast<type*>(addr))
+        ->store(value, order);
     if (value->IsHeapObject()) {
       CheckArrayPointerStore(addr, value, Thread::Current());
     }
@@ -1147,17 +1139,8 @@
 
 class RawScript : public RawObject {
  public:
-  enum Kind {
-    kScriptTag = 0,
-    kLibraryTag,
-    kSourceTag,
-    kEvaluateTag,
-    kKernelTag,
-  };
   enum {
-    kKindPos = 0,
-    kKindSize = 3,
-    kLazyLookupSourceAndLineStartsPos = kKindPos + kKindSize,
+    kLazyLookupSourceAndLineStartsPos = 0,
     kLazyLookupSourceAndLineStartsSize = 1,
   };
 
@@ -1193,13 +1176,12 @@
   int32_t line_offset_;
   int32_t col_offset_;
 
-  using KindBits = BitField<uint8_t, Kind, kKindPos, kKindSize>;
   using LazyLookupSourceAndLineStartsBit =
       BitField<uint8_t,
                bool,
                kLazyLookupSourceAndLineStartsPos,
                kLazyLookupSourceAndLineStartsSize>;
-  uint8_t kind_and_tags_;
+  uint8_t flags_;
 
   intptr_t kernel_script_index_;
   int64_t load_timestamp_;
@@ -1482,15 +1464,6 @@
   uint32_t size_and_flags_;
   uint32_t unchecked_entrypoint_pc_offset_;
 
-  // There is a gap between size_and_flags_ and the entry point
-  // because we align entry point by 4 words on all platforms.
-  // This allows us to have a free field here without affecting
-  // the aligned size of the Instructions object header.
-  // This also means that entry point offset is the same
-  // whether this field is included or excluded.
-  // TODO(37103): This field should be removed.
-  CodeStatistics* stats_;
-
   // Variable length data follows here.
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
 
@@ -2027,6 +2000,7 @@
   VISIT_TO(RawObject*, signature_)
   TokenPosition token_pos_;
   int8_t type_state_;
+  int8_t nullability_;
 
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
@@ -2067,6 +2041,7 @@
   TokenPosition token_pos_;
   int16_t index_;
   uint8_t flags_;
+  int8_t nullability_;
 
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 56e29f1..2ebcd9e 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -89,6 +89,7 @@
   // Set all non object fields.
   type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
   type.set_type_state(reader->Read<int8_t>());
+  type.set_nullability(static_cast<Nullability>(reader->Read<int8_t>()));
 
   // Read the code object for the type testing stub and set its entrypoint.
   reader->EnqueueTypePostprocessing(type);
@@ -152,6 +153,7 @@
   // Write out all the non object pointer fields.
   writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
   writer->Write<int8_t>(ptr()->type_state_);
+  writer->Write<int8_t>(ptr()->nullability_);
 
   // Write out all the object pointer fields.
   ASSERT(ptr()->type_class_id_ != Object::null());
@@ -223,6 +225,8 @@
       TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
   type_parameter.set_index(reader->Read<int16_t>());
   type_parameter.set_flags(reader->Read<uint8_t>());
+  type_parameter.set_nullability(
+      static_cast<Nullability>(reader->Read<int8_t>()));
 
   // Read the code object for the type testing stub and set its entrypoint.
   reader->EnqueueTypePostprocessing(type_parameter);
@@ -264,6 +268,7 @@
   writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
   writer->Write<int16_t>(ptr()->index_);
   writer->Write<uint8_t>(ptr()->flags_);
+  writer->Write<int8_t>(ptr()->nullability_);
 
   // Write out all the object pointer fields.
   SnapshotWriterVisitor visitor(writer, kAsReference);
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index f45a199..28365d1 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -392,7 +392,8 @@
   DEBUG_ASSERT(Thread::Current()->TopErrorHandlerIsSetJump());
   if (word_character_field.IsUninitialized()) {
     ASSERT(!Compiler::IsBackgroundCompilation());
-    const Error& error = Error::Handle(Z, word_character_field.Initialize());
+    const Error& error =
+        Error::Handle(Z, word_character_field.InitializeStatic());
     if (!error.IsNull()) {
       Report::LongJump(error);
     }
diff --git a/runtime/vm/regexp_parser.cc b/runtime/vm/regexp_parser.cc
index 3f3bdf3..c9987e3 100644
--- a/runtime/vm/regexp_parser.cc
+++ b/runtime/vm/regexp_parser.cc
@@ -683,8 +683,8 @@
               Advance(2);
               break;
             }
-            FALL_THROUGH;
           }
+            FALL_THROUGH;
           case '0': {
             Advance();
             if (is_unicode() && Next() >= '0' && Next() <= '9') {
@@ -802,8 +802,8 @@
           ReportError("Nothing to repeat");
           UNREACHABLE();
         }
-        FALL_THROUGH;
       }
+        FALL_THROUGH;
       case '}':
       case ']':
         if (is_unicode()) {
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 9fd4ab7..1bca9a1 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -153,6 +153,17 @@
 }
 
 static void NullErrorHelper(Zone* zone, const String& selector) {
+  // If the selector is null, this must be a null check that wasn't due to a
+  // method invocation, so was due to the null check operator.
+  if (selector.IsNull()) {
+    const Array& args = Array::Handle(zone, Array::New(4));
+    args.SetAt(
+        3, String::Handle(
+               zone, String::New("Null check operator used on a null value")));
+    Exceptions::ThrowByType(Exceptions::kCast, args);
+    return;
+  }
+
   InvocationMirror::Kind kind = InvocationMirror::kMethod;
   if (Field::IsGetterName(selector)) {
     kind = InvocationMirror::kGetter;
@@ -781,7 +792,7 @@
   const TypeCheckMode mode = static_cast<TypeCheckMode>(
       Smi::CheckedHandle(zone, arguments.ArgAt(6)).Value());
 
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_DBC)
+#if defined(TARGET_ARCH_IA32)
   ASSERT(mode == kTypeCheckFromInline);
 #endif
 
@@ -809,7 +820,7 @@
       // Note that instantiated dst_type may be malbounded.
     }
     if (dst_name.IsNull()) {
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
       // Can only come here from type testing stub.
       ASSERT(mode != kTypeCheckFromInline);
 
@@ -837,8 +848,7 @@
   }
 
   bool should_update_cache = true;
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32) &&                 \
-    !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
   if (mode == kTypeCheckFromLazySpecializeStub) {
     if (FLAG_trace_type_checks) {
       OS::PrintErr("  Specializing type testing stub for %s\n",
@@ -875,7 +885,7 @@
 
   if (should_update_cache) {
     if (cache.IsNull()) {
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
       ASSERT(mode == kTypeCheckFromSlowStub);
       // We lazily create [SubtypeTestCache] for those call sites which actually
       // need one and will patch the pool entry.
@@ -1013,7 +1023,7 @@
   UNREACHABLE();
   return;
 }
-#elif !defined(TARGET_ARCH_DBC)
+#else
 // Gets called from debug stub when code reaches a breakpoint
 // set on a runtime stub call.
 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
@@ -1030,13 +1040,7 @@
   ThrowIfError(error);
   arguments.SetReturn(orig_stub);
 }
-#else
-// Gets called from the simulator when the breakpoint is reached.
-DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) {
-  const Error& error = Error::Handle(isolate->debugger()->PauseBreakpoint());
-  ThrowIfError(error);
-}
-#endif  // !defined(TARGET_ARCH_DBC)
+#endif
 
 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) {
 #if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
@@ -1052,8 +1056,7 @@
 // there is a getter with the same name.  If so, invoke it.  If the value is
 // a closure, invoke it with the given arguments.  If the value is a
 // non-closure, attempt to invoke "call" on it.
-static bool ResolveCallThroughGetter(const Instance& receiver,
-                                     const Class& receiver_class,
+static bool ResolveCallThroughGetter(const Class& receiver_class,
                                      const String& target_name,
                                      const Array& arguments_descriptor,
                                      Function* result) {
@@ -1077,7 +1080,7 @@
   if (FLAG_trace_ic) {
     OS::PrintErr(
         "InvokeField IC miss: adding <%s> id:%" Pd " -> <%s>\n",
-        Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(),
+        receiver_class.ToCString(), receiver_class.id(),
         target_function.IsNull() ? "null" : target_function.ToCString());
   }
   *result = target_function.raw();
@@ -1085,22 +1088,20 @@
 }
 
 // Handle other invocations (implicit closures, noSuchMethod).
-RawFunction* InlineCacheMissHelper(const Instance& receiver,
+RawFunction* InlineCacheMissHelper(const Class& receiver_class,
                                    const Array& args_descriptor,
                                    const String& target_name) {
-  const Class& receiver_class = Class::Handle(receiver.clazz());
-
   // Handle noSuchMethod for dyn:methodName by getting a noSuchMethod dispatcher
   // (or a call-through getter for methodName).
   if (Function::IsDynamicInvocationForwarderName(target_name)) {
     const String& demangled = String::Handle(
         Function::DemangleDynamicInvocationForwarderName(target_name));
-    return InlineCacheMissHelper(receiver, args_descriptor, demangled);
+    return InlineCacheMissHelper(receiver_class, args_descriptor, demangled);
   }
 
   Function& result = Function::Handle();
-  if (!ResolveCallThroughGetter(receiver, receiver_class, target_name,
-                                args_descriptor, &result)) {
+  if (!ResolveCallThroughGetter(receiver_class, target_name, args_descriptor,
+                                &result)) {
     ArgumentsDescriptor desc(args_descriptor);
     const Function& target_function =
         Function::Handle(receiver_class.GetInvocationDispatcher(
@@ -1109,7 +1110,7 @@
     if (FLAG_trace_ic) {
       OS::PrintErr(
           "NoSuchMethod IC miss: adding <%s> id:%" Pd " -> <%s>\n",
-          Class::Handle(receiver.clazz()).ToCString(), receiver.GetClassId(),
+          receiver_class.ToCString(), receiver_class.id(),
           target_function.IsNull() ? "null" : target_function.ToCString());
     }
     result = target_function.raw();
@@ -1122,7 +1123,7 @@
 
 static void TrySwitchInstanceCall(const ICData& ic_data,
                                   const Function& target_function) {
-#if !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   // Monomorphic/megamorphic calls only check the receiver CID.
   if (ic_data.NumArgsTested() != 1) return;
 
@@ -1213,7 +1214,7 @@
     return;  // Success.
   }
 
-#endif  // !defined(TARGET_ARCH_DBC) && !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 // Perform the subtype and return constant function based on the result.
@@ -1260,8 +1261,9 @@
     const Array& args_descriptor =
         Array::Handle(ic_data.arguments_descriptor());
     const String& target_name = String::Handle(ic_data.target_name());
+    const Class& receiver_class = Class::Handle(receiver.clazz());
     target_function =
-        InlineCacheMissHelper(receiver, args_descriptor, target_name);
+        InlineCacheMissHelper(receiver_class, args_descriptor, target_name);
   }
   if (target_function.IsNull()) {
     ASSERT(!FLAG_lazy_dispatchers);
@@ -1408,7 +1410,6 @@
   arguments.SetReturn(target);
 }
 
-#if !defined(TARGET_ARCH_DBC)
 static bool IsSingleTarget(Isolate* isolate,
                            Zone* zone,
                            intptr_t lower_cid,
@@ -1431,17 +1432,12 @@
   }
   return true;
 }
-#endif
 
 // Handle a miss of a single target cache.
 //   Arg1: Receiver.
 //   Arg0: Stub out.
 //   Returns: the ICData used to continue with a polymorphic call.
 DEFINE_RUNTIME_ENTRY(SingleTargetMiss, 2) {
-#if defined(TARGET_ARCH_DBC)
-  // DBC does not use switchable calls.
-  UNREACHABLE();
-#else
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
 
   DartFrameIterator iterator(thread,
@@ -1478,7 +1474,7 @@
   Function& target_function = Function::Handle(
       zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(receiver, descriptor, name);
+    target_function = InlineCacheMissHelper(cls, descriptor, name);
   }
   if (target_function.IsNull()) {
     ASSERT(!FLAG_lazy_dispatchers);
@@ -1522,19 +1518,78 @@
   // IC call stub.
   arguments.SetArgAt(0, stub);
   arguments.SetReturn(ic_data);
-#endif
 }
 
+#if defined(DART_PRECOMPILED_RUNTIME)
+
+class SavedUnlinkedCallMapKeyEqualsTraits : public AllStatic {
+ public:
+  static const char* Name() { return "SavedUnlinkedCallMapKeyEqualsTraits "; }
+  static bool ReportStats() { return false; }
+
+  static bool IsMatch(const Object& key1, const Object& key2) {
+    if (!key1.IsInteger() || !key2.IsInteger()) return false;
+    return Integer::Cast(key1).Equals(Integer::Cast(key2));
+  }
+  static uword Hash(const Object& key) {
+    return Integer::Cast(key).CanonicalizeHash();
+  }
+};
+
+using UnlinkedCallMap = UnorderedHashMap<SavedUnlinkedCallMapKeyEqualsTraits>;
+
+static void SaveUnlinkedCall(Zone* zone,
+                             Isolate* isolate,
+                             uword frame_pc,
+                             const UnlinkedCall& unlinked_call) {
+  auto object_store = isolate->object_store();
+  if (object_store->saved_unlinked_calls() == Array::null()) {
+    const auto& initial_map =
+        Array::Handle(zone, HashTables::New<UnlinkedCallMap>(16, Heap::kOld));
+    object_store->set_saved_unlinked_calls(initial_map);
+  }
+
+  UnlinkedCallMap unlinked_call_map(zone, object_store->saved_unlinked_calls());
+  const auto& pc = Integer::Handle(Integer::NewFromUint64(frame_pc));
+  const bool was_present = unlinked_call_map.UpdateOrInsert(pc, unlinked_call);
+  // We transition at most once out of UnlinkedCall state.
+  RELEASE_ASSERT(!was_present);
+  object_store->set_saved_unlinked_calls(unlinked_call_map.Release());
+}
+
+static RawUnlinkedCall* LoadUnlinkedCall(Zone* zone,
+                                         Isolate* isolate,
+                                         uword pc) {
+  auto object_store = isolate->object_store();
+  ASSERT(object_store->saved_unlinked_calls() != Array::null());
+
+  UnlinkedCallMap unlinked_call_map(zone, object_store->saved_unlinked_calls());
+  const auto& pc_integer = Integer::Handle(Integer::NewFromUint64(pc));
+  const auto& unlinked_call = UnlinkedCall::Cast(
+      Object::Handle(zone, unlinked_call_map.GetOrDie(pc_integer)));
+  // Since we transition out of the monomorphic state only once, we should not
+  // need the saved unlinked call anymore.
+  unlinked_call_map.Remove(pc_integer);
+  object_store->set_saved_unlinked_calls(unlinked_call_map.Release());
+
+  return unlinked_call.raw();
+}
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
+#if !defined(TARGET_ARCH_DBC)
+#if defined(PRODUCT)
+const bool kInstructionsCanBeDeduped = true;
+#else
+const bool kInstructionsCanBeDeduped = false;
+#endif  // defined(PRODUCT)
+#endif  // !defined(TARGET_ARCH_DBC)
+
 // Handle the first use of an instance call
 //   Arg2: UnlinkedCall.
 //   Arg1: Receiver.
 //   Arg0: Stub out.
 //   Returns: the ICData used to continue with a polymorphic call.
 DEFINE_RUNTIME_ENTRY(UnlinkedCall, 3) {
-#if defined(TARGET_ARCH_DBC)
-  // DBC does not use switchable calls.
-  UNREACHABLE();
-#else
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
   const UnlinkedCall& unlinked =
       UnlinkedCall::CheckedHandle(zone, arguments.ArgAt(2));
@@ -1559,7 +1614,7 @@
   Function& target_function = Function::Handle(
       zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(receiver, descriptor, name);
+    target_function = InlineCacheMissHelper(cls, descriptor, name);
   }
   if (target_function.IsNull()) {
     ASSERT(!FLAG_lazy_dispatchers);
@@ -1567,6 +1622,40 @@
     ic_data.AddReceiverCheck(receiver.GetClassId(), target_function);
   }
 
+  // In AOT bare mode, the PC -> Code mapping is ambiguous, since multiple code
+  // objects can have the same deduped instructions and bare frames are compact
+  // (i.e. have only PC but no code object in the frame)
+  //
+  // In JIT and AOT non-bare mode, instructions will push the unique code
+  // object on the frame.
+  //
+  // If we can find the unique code object of the callee, we can find it's
+  // owner function. If the callee function is non-generic and has no optional
+  // parameters, we can and thereby deduce the call-site argument descriptor +
+  // name from it.
+  //
+  // If not, we'll save the unlinked call object in a map.
+  //
+  // See [MonomorphicMiss]
+  const bool need_saved_unlinked_call =
+      (FLAG_use_bare_instructions && kInstructionsCanBeDeduped);
+
+  // We transition from an unlinked call to a monomorphic call. This transition
+  // will cause us to loose the argument descriptor information on the call
+  // site.
+  //
+  // Though if the monomorphic call site transitions to a
+  // polymorphic/megamorphic we need to reconstruct the arguments descriptor.
+  //
+  // We assume here that generated code never moves.
+  if (need_saved_unlinked_call) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    SaveUnlinkedCall(zone, isolate, caller_frame->pc(), unlinked);
+#else
+    UNREACHABLE();
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+  }
+
   // 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
@@ -1602,10 +1691,9 @@
   // stub.
   arguments.SetArgAt(0, stub);
   arguments.SetReturn(ic_data);
-#endif  // !DBC
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
 static RawICData* FindICDataForInstanceCall(Zone* zone,
                                             const Code& code,
                                             uword pc) {
@@ -1623,17 +1711,14 @@
   ASSERT(deopt_id != -1);
   return Function::Handle(zone, code.function()).FindICData(deopt_id);
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 // Handle a miss of a megamorphic cache.
 //   Arg1: Receiver.
 //   Arg0: continuation Code (out parameter).
 //   Returns: the ICData used to continue with a polymorphic call.
 DEFINE_RUNTIME_ENTRY(MonomorphicMiss, 2) {
-#if defined(TARGET_ARCH_DBC)
-  // DBC does not use switchable calls.
-  UNREACHABLE();
-#elif defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_PRECOMPILED_RUNTIME)
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(1));
 
   DartFrameIterator iterator(thread,
@@ -1647,33 +1732,63 @@
   Smi& old_expected_cid = Smi::Handle(zone);
   old_expected_cid ^=
       CodePatcher::GetSwitchableCallDataAt(caller_frame->pc(), caller_code);
-  const Code& old_target_code = Code::Handle(
-      CodePatcher::GetSwitchableCallTargetAt(caller_frame->pc(), caller_code));
-  Function& old_target = Function::Handle(zone);
-  old_target ^= old_target_code.owner();
 
-  // We lost the original ICData when we patched to the monomorphic case.
-  const String& name = String::Handle(zone, old_target.name());
-  ASSERT(!old_target.HasOptionalParameters());
-  const int kTypeArgsLen = 0;
-  const Array& descriptor =
-      Array::Handle(zone, ArgumentsDescriptor::New(
-                              kTypeArgsLen, old_target.num_fixed_parameters()));
+  String& name = String::Handle(zone);
+  Array& descriptor = Array::Handle(zone);
+  Function& old_target = Function::Handle(zone);
+  if (FLAG_use_bare_instructions && kInstructionsCanBeDeduped) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    const auto& unlinked_call = UnlinkedCall::Handle(
+        zone, LoadUnlinkedCall(zone, isolate, caller_frame->pc()));
+    name = unlinked_call.target_name();
+    descriptor = unlinked_call.args_descriptor();
+
+    ArgumentsDescriptor args_desc(descriptor);
+    const auto& old_receiver_class = Class::Handle(
+        zone, isolate->class_table()->At(old_expected_cid.Value()));
+    old_target = Resolver::ResolveDynamicForReceiverClass(old_receiver_class,
+                                                          name, args_desc);
+    if (old_target.IsNull()) {
+      old_target = InlineCacheMissHelper(old_receiver_class, descriptor, name);
+    }
+#else
+    UNREACHABLE();
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+  } else {
+    // We lost the original UnlinkedCall (and the name + arg descriptor inside
+    // it) when the call site transitioned from unlinked to monomorphic.
+    //
+    // Though we can deduce name + arg descriptor based on the first
+    // monomorphic callee (we are guaranteed it is not generic and does not have
+    // optional parameters, see DEFINE_RUNTIME_ENTRY(UnlinkedCall) above).
+    const Code& old_target_code =
+        Code::Handle(zone, CodePatcher::GetSwitchableCallTargetAt(
+                               caller_frame->pc(), caller_code));
+    old_target ^= old_target_code.owner();
+
+    const int kTypeArgsLen = 0;
+    name = old_target.name();
+    descriptor = ArgumentsDescriptor::New(kTypeArgsLen,
+                                          old_target.num_fixed_parameters());
+  }
+
   const ICData& ic_data =
       ICData::Handle(zone, ICData::New(caller_function, name, descriptor,
                                        DeoptId::kNone, 1, /* args_tested */
                                        ICData::kInstance));
 
   // Add the first target.
-  ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target);
+  if (!old_target.IsNull()) {
+    ic_data.AddReceiverCheck(old_expected_cid.Value(), old_target);
+  }
 
   // Maybe add the new target.
-  Class& cls = Class::Handle(zone, receiver.clazz());
   ArgumentsDescriptor args_desc(descriptor);
+  const Class& cls = Class::Handle(zone, receiver.clazz());
   Function& target_function = Function::Handle(
       zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(receiver, descriptor, name);
+    target_function = InlineCacheMissHelper(cls, descriptor, name);
   }
   if (target_function.IsNull()) {
     ASSERT(!FLAG_lazy_dispatchers);
@@ -1759,7 +1874,7 @@
   }
   arguments.SetArgAt(0, stub);
   arguments.SetReturn(ic_data);
-#endif  // !defined(TARGET_ARCH_DBC)
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
 // Handle a miss of a megamorphic cache.
@@ -1768,10 +1883,6 @@
 //   Arg2: Arguments descriptor array.
 //   Returns: target function to call.
 DEFINE_RUNTIME_ENTRY(MegamorphicCacheMissHandler, 3) {
-#if defined(TARGET_ARCH_DBC)
-  // DBC does not use megamorphic calls right now.
-  UNREACHABLE();
-#else
   const Instance& receiver = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   const Object& ic_data_or_cache = Object::Handle(zone, arguments.ArgAt(1));
   const Array& descriptor = Array::CheckedHandle(zone, arguments.ArgAt(2));
@@ -1793,7 +1904,7 @@
   Function& target_function = Function::Handle(
       zone, Resolver::ResolveDynamicForReceiverClass(cls, name, args_desc));
   if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(receiver, descriptor, name);
+    target_function = InlineCacheMissHelper(cls, descriptor, name);
     if (target_function.IsNull()) {
       ASSERT(!FLAG_lazy_dispatchers);
       arguments.SetReturn(target_function);
@@ -1858,7 +1969,6 @@
     cache.Insert(class_id, target_function);
   }
   arguments.SetReturn(target_function);
-#endif  // !defined(TARGET_ARCH_DBC)
 }
 
 // Handles interpreted interface call cache miss.
@@ -1885,7 +1995,9 @@
   // arg to the call, the type, is needed.
 
   if (target_function.IsNull()) {
-    target_function = InlineCacheMissHelper(receiver, arg_desc, target_name);
+    const Class& receiver_class = Class::Handle(zone, receiver.clazz());
+    target_function =
+        InlineCacheMissHelper(receiver_class, arg_desc, target_name);
   }
   ASSERT(!target_function.IsNull());
   arguments.SetReturn(target_function);
@@ -2309,7 +2421,6 @@
   // If an interrupt happens at the same time as a stack overflow, we
   // process the stack overflow now and leave the interrupt for next
   // time.
-  // TODO(regis): Warning: IsCalleeFrameOf is overridden in stack_frame_dbc.h.
   if (interpreter_stack_overflow || !thread->os_thread()->HasStackHeadroom() ||
       IsCalleeFrameOf(thread->saved_stack_limit(), stack_pos)) {
     if (FLAG_verbose_stack_overflow) {
@@ -2405,10 +2516,10 @@
       // Ensure background compiler is running, if not start it.
       BackgroundCompiler::Start(isolate);
       // Reduce the chance of triggering a compilation while the function is
-      // being compiled in the background. INT_MIN should ensure that it
+      // being compiled in the background. INT32_MIN should ensure that it
       // takes long time to trigger a compilation.
       // Note that the background compilation queue rejects duplicate entries.
-      function.SetUsageCounter(INT_MIN);
+      function.SetUsageCounter(INT32_MIN);
       isolate->background_compiler()->Compile(function);
       return;
     }
@@ -2451,10 +2562,10 @@
         // Ensure background compiler is running, if not start it.
         BackgroundCompiler::Start(isolate);
         // Reduce the chance of triggering a compilation while the function is
-        // being compiled in the background. INT_MIN should ensure that it
+        // being compiled in the background. INT32_MIN should ensure that it
         // takes long time to trigger a compilation.
         // Note that the background compilation queue rejects duplicate entries.
-        function.SetUsageCounter(INT_MIN);
+        function.SetUsageCounter(INT32_MIN);
         isolate->optimizing_background_compiler()->Compile(function);
         // Continue in the same code.
         arguments.SetReturn(function);
@@ -2648,30 +2759,6 @@
     function.SwitchToUnoptimizedCode();
   }
 
-#if defined(TARGET_ARCH_DBC)
-  const Instructions& instrs =
-      Instructions::Handle(zone, optimized_code.instructions());
-  {
-    WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size());
-    CodePatcher::InsertDeoptimizationCallAt(frame->pc());
-    if (FLAG_trace_patching) {
-      const String& name = String::Handle(function.name());
-      OS::PrintErr("InsertDeoptimizationCallAt: 0x%" Px " for %s\n",
-                   frame->pc(), name.ToCString());
-    }
-    const ExceptionHandlers& handlers =
-        ExceptionHandlers::Handle(zone, optimized_code.exception_handlers());
-    ExceptionHandlerInfo info;
-    for (intptr_t i = 0; i < handlers.num_entries(); ++i) {
-      handlers.GetHandlerInfo(i, &info);
-      const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset;
-      CodePatcher::InsertDeoptimizationCallAt(patch_pc);
-      if (FLAG_trace_patching) {
-        OS::PrintErr("  at handler 0x%" Px "\n", patch_pc);
-      }
-    }
-  }
-#else  // !DBC
   if (frame->IsMarkedForLazyDeopt()) {
     // Deopt already scheduled.
     if (FLAG_trace_deoptimization) {
@@ -2696,7 +2783,6 @@
                 frame->fp(), deopt_pc);
     }
   }
-#endif  // !DBC
 
   // Mark code as dead (do not GC its embedded objects).
   optimized_code.set_is_alive(false);
@@ -2722,13 +2808,8 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-#if !defined(TARGET_ARCH_DBC)
 static const intptr_t kNumberOfSavedCpuRegisters = kNumberOfCpuRegisters;
 static const intptr_t kNumberOfSavedFpuRegisters = kNumberOfFpuRegisters;
-#else
-static const intptr_t kNumberOfSavedCpuRegisters = 0;
-static const intptr_t kNumberOfSavedFpuRegisters = 0;
-#endif
 
 static void CopySavedRegisters(uword saved_registers_address,
                                fpu_register_t** fpu_registers,
@@ -2797,7 +2878,6 @@
               (is_lazy_deopt != 0u) ? "lazy-deopt" : "");
   }
 
-#if !defined(TARGET_ARCH_DBC)
   if (is_lazy_deopt != 0u) {
     uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp());
     if (FLAG_trace_deoptimization) {
@@ -2817,7 +2897,6 @@
                 caller_frame->pc());
     }
   }
-#endif  // !DBC
 
   // Copy the saved registers from the stack.
   fpu_register_t* fpu_registers;
@@ -2946,9 +3025,16 @@
 #endif
 }
 
+DEFINE_RUNTIME_ENTRY(InitInstanceField, 2) {
+  const Instance& instance = Instance::CheckedHandle(zone, arguments.ArgAt(0));
+  const Field& field = Field::CheckedHandle(zone, arguments.ArgAt(1));
+  const Error& result = Error::Handle(zone, field.InitializeInstance(instance));
+  ThrowIfError(result);
+}
+
 DEFINE_RUNTIME_ENTRY(InitStaticField, 1) {
   const Field& field = Field::CheckedHandle(zone, arguments.ArgAt(0));
-  const Error& result = Error::Handle(zone, field.Initialize());
+  const Error& result = Error::Handle(zone, field.InitializeStatic());
   ThrowIfError(result);
 }
 
@@ -3044,8 +3130,7 @@
 
 uword RuntimeEntry::InterpretCallEntry() {
   uword entry = reinterpret_cast<uword>(RuntimeEntry::InterpretCall);
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
-  // DBC does not use redirections unlike other simulators.
+#if defined(USING_SIMULATOR)
   entry = Simulator::RedirectExternalReference(entry,
                                                Simulator::kLeafRuntimeCall, 5);
 #endif
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index 4206b1e..c29e6e4 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -99,7 +99,8 @@
                                NativeArguments arguments);                     \
   void DRT_##name(NativeArguments arguments) {                                 \
     CHECK_STACK_ALIGNMENT;                                                     \
-    VERIFY_ON_TRANSITION;                                                      \
+    /* Tell MemorySanitizer 'arguments' is initialized by generated code. */   \
+    MSAN_UNPOISON(&arguments, sizeof(arguments));                              \
     ASSERT(arguments.ArgCount() == argument_count);                            \
     TRACE_RUNTIME_CALL("%s", "" #name);                                        \
     {                                                                          \
@@ -111,7 +112,6 @@
       HANDLESCOPE(thread);                                                     \
       DRT_Helper##name(isolate, thread, zone.GetZone(), arguments);            \
     }                                                                          \
-    VERIFY_ON_TRANSITION;                                                      \
   }                                                                            \
   static void DRT_Helper##name(Isolate* isolate, Thread* thread, Zone* zone,   \
                                NativeArguments arguments)
diff --git a/runtime/vm/runtime_entry_dbc.cc b/runtime/vm/runtime_entry_dbc.cc
deleted file mode 100644
index c8636a2..0000000
--- a/runtime/vm/runtime_entry_dbc.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/runtime_entry.h"
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/simulator.h"
-#include "vm/stub_code.h"
-
-namespace dart {
-
-uword RuntimeEntry::GetEntryPoint() const {
-  return reinterpret_cast<uword>(function());
-}
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
-                                compiler::Assembler* assembler,
-                                intptr_t argument_count) {
-  UNIMPLEMENTED();
-}
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index 3ede9d3..26e687b 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -52,6 +52,7 @@
   V(DeoptimizeMaterialize)                                                     \
   V(RewindPostDeopt)                                                           \
   V(UpdateFieldCid)                                                            \
+  V(InitInstanceField)                                                         \
   V(InitStaticField)                                                           \
   V(CompileFunction)                                                           \
   V(CompileInterpretedFunction)                                                \
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 43225fb..69eec8e 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -260,13 +260,25 @@
 }
 
 static bool CheckProfilerDisabled(Thread* thread, JSONStream* js) {
-  if (Profiler::sample_buffer() == NULL) {
+  if (!FLAG_profiler) {
     js->PrintError(kFeatureDisabled, "Profiler is disabled.");
     return true;
   }
   return false;
 }
 
+static bool CheckNativeAllocationProfilerDisabled(Thread* thread,
+                                                  JSONStream* js) {
+  if (CheckProfilerDisabled(thread, js)) {
+    return true;
+  }
+  if (!FLAG_profiler_native_memory) {
+    js->PrintError(kFeatureDisabled, "Native memory profiling is disabled.");
+    return true;
+  }
+  return false;
+}
+
 static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
   if ((s == NULL) || (*s == '\0')) {
     // Empty string.
@@ -556,6 +568,34 @@
   }
 };
 
+class UInt64Parameter : public MethodParameter {
+ public:
+  UInt64Parameter(const char* name, bool required)
+      : MethodParameter(name, required) {}
+
+  virtual bool Validate(const char* value) const {
+    if (value == NULL) {
+      return false;
+    }
+    for (const char* cp = value; *cp != '\0'; cp++) {
+      if ((*cp < '0' || *cp > '9') && (*cp != '-')) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  static uint64_t Parse(const char* value, uint64_t default_value = 0) {
+    if ((value == NULL) || (*value == '\0')) {
+      return default_value;
+    }
+    char* end_ptr = NULL;
+    uint64_t result = strtoull(value, &end_ptr, 10);
+    ASSERT(*end_ptr == '\0');  // Parsed full string
+    return result;
+  }
+};
+
 class IdParameter : public MethodParameter {
  public:
   IdParameter(const char* name, bool required)
@@ -591,6 +631,7 @@
 };
 
 #define ISOLATE_PARAMETER new IdParameter("isolateId", true)
+#define ISOLATE_GROUP_PARAMETER new IdParameter("isolateGroupId", true)
 #define NO_ISOLATE_PARAMETER new NoSuchParameter("isolateId")
 #define RUNNABLE_ISOLATE_PARAMETER new RunnableIsolateParameter("isolateId")
 
@@ -1370,6 +1411,65 @@
   return true;
 }
 
+static const MethodParameter* get_isolate_group_params[] = {
+    ISOLATE_GROUP_PARAMETER,
+    NULL,
+};
+
+enum SentinelType {
+  kCollectedSentinel,
+  kExpiredSentinel,
+  kFreeSentinel,
+};
+
+static void PrintSentinel(JSONStream* js, SentinelType sentinel_type) {
+  JSONObject jsobj(js);
+  jsobj.AddProperty("type", "Sentinel");
+  switch (sentinel_type) {
+    case kCollectedSentinel:
+      jsobj.AddProperty("kind", "Collected");
+      jsobj.AddProperty("valueAsString", "<collected>");
+      break;
+    case kExpiredSentinel:
+      jsobj.AddProperty("kind", "Expired");
+      jsobj.AddProperty("valueAsString", "<expired>");
+      break;
+    case kFreeSentinel:
+      jsobj.AddProperty("kind", "Free");
+      jsobj.AddProperty("valueAsString", "<free>");
+      break;
+    default:
+      UNIMPLEMENTED();
+      break;
+  }
+}
+
+static void ActOnIsolateGroup(JSONStream* js,
+                              std::function<void(IsolateGroup*)> visitor) {
+  const String& prefix =
+      String::Handle(String::New(ISOLATE_GROUP_SERVICE_ID_PREFIX));
+
+  const String& s =
+      String::Handle(String::New(js->LookupParam("isolateGroupId")));
+  if (!s.StartsWith(prefix)) {
+    PrintInvalidParamError(js, "isolateGroupId");
+    return;
+  }
+  uint64_t isolate_group_id = UInt64Parameter::Parse(
+      String::Handle(String::SubString(s, prefix.Length())).ToCString());
+  IsolateGroup::RunWithIsolateGroup(
+      isolate_group_id,
+      [&visitor](IsolateGroup* isolate_group) { visitor(isolate_group); },
+      /*if_not_found=*/[&js]() { PrintSentinel(js, kExpiredSentinel); });
+}
+
+static bool GetIsolateGroup(Thread* thread, JSONStream* js) {
+  ActOnIsolateGroup(js, [&](IsolateGroup* isolate_group) {
+    isolate_group->PrintJSON(js, false);
+  });
+  return true;
+}
+
 static const MethodParameter* get_memory_usage_params[] = {
     ISOLATE_PARAMETER,
     NULL,
@@ -1380,6 +1480,18 @@
   return true;
 }
 
+static const MethodParameter* get_isolate_group_memory_usage_params[] = {
+    ISOLATE_GROUP_PARAMETER,
+    NULL,
+};
+
+static bool GetIsolateGroupMemoryUsage(Thread* thread, JSONStream* js) {
+  ActOnIsolateGroup(js, [&](IsolateGroup* isolate_group) {
+    isolate_group->PrintMemoryUsageJSON(js);
+  });
+  return true;
+}
+
 static const MethodParameter* get_scripts_params[] = {
     RUNNABLE_ISOLATE_PARAMETER,
     NULL,
@@ -1936,34 +2048,6 @@
   return Object::sentinel().raw();
 }
 
-enum SentinelType {
-  kCollectedSentinel,
-  kExpiredSentinel,
-  kFreeSentinel,
-};
-
-static void PrintSentinel(JSONStream* js, SentinelType sentinel_type) {
-  JSONObject jsobj(js);
-  jsobj.AddProperty("type", "Sentinel");
-  switch (sentinel_type) {
-    case kCollectedSentinel:
-      jsobj.AddProperty("kind", "Collected");
-      jsobj.AddProperty("valueAsString", "<collected>");
-      break;
-    case kExpiredSentinel:
-      jsobj.AddProperty("kind", "Expired");
-      jsobj.AddProperty("valueAsString", "<expired>");
-      break;
-    case kFreeSentinel:
-      jsobj.AddProperty("kind", "Free");
-      jsobj.AddProperty("valueAsString", "<free>");
-      break;
-    default:
-      UNIMPLEMENTED();
-      break;
-  }
-}
-
 static Breakpoint* LookupBreakpoint(Isolate* isolate,
                                     const char* id,
                                     ObjectIdRing::LookupResult* result) {
@@ -3834,7 +3918,7 @@
 #if defined(DEBUG)
   Isolate::Current()->heap()->CollectAllGarbage();
 #endif
-  if (CheckProfilerDisabled(thread, js)) {
+  if (CheckNativeAllocationProfilerDisabled(thread, js)) {
     return true;
   }
   ProfilerService::PrintNativeAllocationJSON(
@@ -3848,9 +3932,6 @@
 };
 
 static bool ClearCpuSamples(Thread* thread, JSONStream* js) {
-  if (CheckProfilerDisabled(thread, js)) {
-    return true;
-  }
   ProfilerService::ClearSamples();
   PrintSuccess(js);
   return true;
@@ -4336,12 +4417,18 @@
       "startTime", OS::GetCurrentTimeMillis() - Dart::UptimeMillis());
   MallocHooks::PrintToJSONObject(&jsobj);
   PrintJSONForEmbedderInformation(&jsobj);
-  // Construct the isolate list.
+  // Construct the isolate and isolate_groups list.
   {
     JSONArray jsarr(&jsobj, "isolates");
     ServiceIsolateVisitor visitor(&jsarr);
     Isolate::VisitIsolates(&visitor);
   }
+  {
+    JSONArray jsarr_isolate_groups(&jsobj, "isolateGroups");
+    IsolateGroup::ForEach([&jsarr_isolate_groups](IsolateGroup* isolate_group) {
+      jsarr_isolate_groups.AddValue(isolate_group);
+    });
+  }
 }
 
 static bool GetVM(Thread* thread, JSONStream* js) {
@@ -4420,19 +4507,23 @@
   // Changing most flags at runtime is dangerous because e.g., it may leave the
   // behavior generated code and the runtime out of sync.
   const uintptr_t kProfilePeriodIndex = 3;
+  const uintptr_t kProfilerIndex = 4;
   const char* kAllowedFlags[] = {
       "pause_isolates_on_start",
       "pause_isolates_on_exit",
       "pause_isolates_on_unhandled_exceptions",
       "profile_period",
+      "profiler",
   };
 
   bool allowed = false;
   bool profile_period = false;
+  bool profiler = false;
   for (size_t i = 0; i < ARRAY_SIZE(kAllowedFlags); i++) {
     if (strcmp(flag_name, kAllowedFlags[i]) == 0) {
       allowed = true;
       profile_period = (i == kProfilePeriodIndex);
+      profiler = (i == kProfilerIndex);
       break;
     }
   }
@@ -4451,6 +4542,9 @@
       // FLAG_profile_period has already been set to the new value. Now we need
       // to notify the ThreadInterrupter to pick up the change.
       Profiler::UpdateSamplePeriod();
+    } else if (profiler) {
+      // FLAG_profiler has already been set to the new value.
+      Profiler::UpdateRunningState();
     }
     if (Service::vm_stream.enabled()) {
       ServiceEvent event(NULL, ServiceEvent::kVMFlagUpdate);
@@ -4687,8 +4781,12 @@
     get_instances_params },
   { "getIsolate", GetIsolate,
     get_isolate_params },
+  { "getIsolateGroup", GetIsolateGroup,
+    get_isolate_group_params },
   { "getMemoryUsage", GetMemoryUsage,
     get_memory_usage_params },
+  { "getIsolateGroupMemoryUsage", GetIsolateGroupMemoryUsage,
+    get_isolate_group_memory_usage_params },
   { "_getIsolateMetric", GetIsolateMetric,
     get_isolate_metric_params },
   { "_getIsolateMetricList", GetIsolateMetricList,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index d1ce7a7..f283627 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 27
+#define SERVICE_PROTOCOL_MINOR_VERSION 28
 
 class Array;
 class EmbedderServiceHandler;
@@ -24,6 +24,7 @@
 class GrowableObjectArray;
 class Instance;
 class Isolate;
+class IsolateGroup;
 class JSONStream;
 class JSONObject;
 class Object;
@@ -44,6 +45,9 @@
 };
 
 #define ISOLATE_SERVICE_ID_FORMAT_STRING "isolates/%" Pd64 ""
+#define ISOLATE_GROUP_SERVICE_ID_PREFIX "isolateGroups/"
+#define ISOLATE_GROUP_SERVICE_ID_FORMAT_STRING                                 \
+  ISOLATE_GROUP_SERVICE_ID_PREFIX "%" Pu64 ""
 
 class RingServiceIdZone : public ServiceIdZone {
  public:
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 25b08e9..671d781 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -37,6 +37,7 @@
   - [getInstances](#getinstances)
   - [getInboundReferences](#getinboundreferences)
   - [getIsolate](#getisolate)
+  - [getIsolateGroup](#getisolategroup)
   - [getMemoryUsage](#getmemoryusage)
   - [getObject](#getobject)
   - [getRetainingPath](#getretainingpath)
@@ -92,6 +93,7 @@
   - [Instance](#instance)
   - [InstanceSet](#instanceset)
   - [Isolate](#isolate)
+  - [IsolateGroup](#isolategroup)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
   - [LogRecord](#logrecord)
@@ -760,6 +762,22 @@
 
 See [Isolate](#isolate).
 
+### getIsolateGroup
+
+```
+IsolateGroup|Sentinel getIsolateGroup(string isolateGroupId)
+```
+
+The _getIsolateGroup_ RPC is used to lookup an _IsolateGroup_ object by its _id_.
+
+If _isolateGroupId_ refers to an isolate group which has exited, then the
+_Expired_ [Sentinel](#sentinel) is returned.
+
+_IsolateGroup_ _id_ is an opaque identifier that can be fetched from an
+ _IsolateGroup_. List of active _IsolateGroup_'s, for example, is available on _VM_ object.
+
+See [IsolateGroup](#isolategroup), [VM](#vm).
+
 ### getMemoryUsage
 
 ```
@@ -774,6 +792,19 @@
 
 See [Isolate](#isolate).
 
+### getIsolateGroupMemoryUsage
+
+```
+MemoryUsage|Sentinel getIsolateGroupMemoryUsage(string isolateGroupId)
+```
+
+The _getIsolateGroupMemoryUsage_ RPC is used to lookup an isolate
+group's memory usage statistics by its _id_.
+
+If _isolateGroupId_ refers to an isolate group which has exited, then the _Expired_ [Sentinel](#sentinel) is returned.
+
+See [IsolateGroup](#isolategroup).
+
 ### getScripts
 
 ```
@@ -1124,9 +1155,15 @@
  * pause_isolates_on_exit
  * pause_isolates_on_unhandled_exceptions
  * profile_period
+ * profiler
 
-Note: `profile_period` can be set to a minimum value of 50. Attempting to set
-`profile_period` to a lower value will result in a value of 50 being set.
+Notes:
+ * `profile_period` can be set to a minimum value of 50. Attempting to set
+   `profile_period` to a lower value will result in a value of 50 being set.
+ * Setting `profiler` will enable or disable the profiler depending on the
+   provided value. If set to false when the profiler is already running, the
+   profiler will be stopped but may not free its sample buffer depending on
+   platform limitations.
 
 See [Success](#success).
 
@@ -2598,6 +2635,42 @@
 
 An _Isolate_ object provides information about one isolate in the VM.
 
+### IsolateGroup
+
+```
+class @IsolateGroup extends Response {
+  // The id which is passed to the getIsolateGroup RPC to load this isolate group.
+  string id;
+
+  // A numeric id for this isolate group, represented as a string. Unique.
+  string number;
+
+  // A name identifying this isolate group. Not guaranteed to be unique.
+  string name;
+}
+```
+
+_@IsolateGroup_ is a reference to an _IsolateGroup_ object.
+
+```
+class IsolateGroup extends Response {
+  // The id which is passed to the getIsolate RPC to reload this
+  // isolate.
+  string id;
+
+  // A numeric id for this isolate, represented as a string. Unique.
+  string number;
+
+  // A name identifying this isolate. Not guaranteed to be unique.
+  string name;
+
+  // A list of all isolates in this isolate group.
+  @Isolate[] isolates;
+}
+```
+
+An _Isolate_ object provides information about one isolate in the VM.
+
 ### InboundReferences
 
 ```
@@ -3438,6 +3511,9 @@
 
   // A list of isolates running in the VM.
   @Isolate[] isolates;
+
+  // A list of isolate groups running in the VM.
+  @IsolateGroup[] isolateGroups;
 }
 ```
 
diff --git a/runtime/vm/simulator.h b/runtime/vm/simulator.h
index c746d45..3194aa9 100644
--- a/runtime/vm/simulator.h
+++ b/runtime/vm/simulator.h
@@ -15,8 +15,6 @@
 #include "vm/simulator_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/simulator_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/simulator_dbc.h"
 #else
 #error Unknown architecture.
 #endif  // defined(TARGET_ARCH_...)
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 1b514fe..1c5db00 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -751,23 +751,20 @@
                           int argument_count) {
     MutexLocker ml(mutex_);
 
-    for (Redirection* current = list_; current != NULL;
+    Redirection* old_head = list_.load(std::memory_order_relaxed);
+    for (Redirection* current = old_head; current != nullptr;
          current = current->next_) {
       if (current->external_function_ == external_function) return current;
     }
 
     Redirection* redirection =
         new Redirection(external_function, call_kind, argument_count);
-    redirection->next_ = list_;
+    redirection->next_ = old_head;
 
     // Use a memory fence to ensure all pending writes are written at the time
     // of updating the list head, so the profiling thread always has a valid
     // list to look at.
-    Redirection* old_head = list_;
-    Redirection* replaced_list_head =
-        AtomicOperations::CompareAndSwapPointer<Redirection>(&list_, old_head,
-                                                             redirection);
-    ASSERT(old_head == replaced_list_head);
+    list_.store(redirection, std::memory_order_release);
 
     return redirection;
   }
@@ -784,8 +781,8 @@
   // allowed to hold any locks - which is precisely the reason why the list is
   // prepend-only and a memory fence is used when writing the list head [list_]!
   static uword FunctionForRedirect(uword address_of_svc) {
-    Redirection* current;
-    for (current = list_; current != NULL; current = current->next_) {
+    for (Redirection* current = list_.load(std::memory_order_acquire);
+         current != nullptr; current = current->next_) {
       if (current->address_of_svc_instruction() == address_of_svc) {
         return current->external_function_;
       }
@@ -808,11 +805,11 @@
   int argument_count_;
   uint32_t svc_instruction_;
   Redirection* next_;
-  static Redirection* list_;
+  static std::atomic<Redirection*> list_;
   static Mutex* mutex_;
 };
 
-Redirection* Redirection::list_ = NULL;
+std::atomic<Redirection*> Redirection::list_ = {nullptr};
 Mutex* Redirection::mutex_ = new Mutex();
 
 uword Simulator::RedirectExternalReference(uword function,
@@ -1047,11 +1044,11 @@
     return 1;  // Failure.
   }
 
-  uword old_value = exclusive_access_value_;
+  int32_t old_value = static_cast<uint32_t>(exclusive_access_value_);
   ClearExclusive();
 
-  if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr),
-                                           old_value, value) == old_value) {
+  auto atomic_addr = reinterpret_cast<RelaxedAtomic<int32_t>*>(addr);
+  if (atomic_addr->compare_exchange_weak(old_value, value)) {
     return 0;  // Success.
   }
   return 1;  // Failure.
@@ -1642,14 +1639,11 @@
           case 2:
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "umaal'cond's 'rd, 'rn, 'rm, 'rs");
-            if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-              // umaal is only in ARMv6 and above.
-              UnimplementedInstruction(instr);
-            }
             FALL_THROUGH;
           case 5:
-          // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
-          // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
+            // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
+            // Format(instr, "umlal'cond's 'rd, 'rn, 'rm, 'rs");
+            FALL_THROUGH;
           case 7: {
             // Registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
             // Format(instr, "smlal'cond's 'rd, 'rn, 'rm, 'rs");
@@ -1697,10 +1691,6 @@
           }
         }
       } else {
-        if (TargetCPUFeatures::arm_version() == ARMv5TE) {
-          UnimplementedInstruction(instr);
-          return;
-        }
         // synchronization primitives
         Register rd = instr->RdField();
         Register rn = instr->RnField();
@@ -2744,17 +2734,17 @@
                 float sm_val = get_sregister(sm);
                 if (instr->Bit(16) == 0) {
                   // Format(instr, "vcvtus'cond 'sd, 'sm");
-                  if (sm_val >= INT_MAX) {
-                    ud_val = INT_MAX;
+                  if (sm_val >= static_cast<float>(INT32_MAX)) {
+                    ud_val = INT32_MAX;
                   } else if (sm_val > 0.0) {
                     ud_val = static_cast<uint32_t>(sm_val);
                   }
                 } else {
                   // Format(instr, "vcvtis'cond 'sd, 'sm");
-                  if (sm_val <= INT_MIN) {
-                    id_val = INT_MIN;
-                  } else if (sm_val >= INT_MAX) {
-                    id_val = INT_MAX;
+                  if (sm_val <= static_cast<float>(INT32_MIN)) {
+                    id_val = INT32_MIN;
+                  } else if (sm_val >= static_cast<float>(INT32_MAX)) {
+                    id_val = INT32_MAX;
                   } else {
                     id_val = static_cast<int32_t>(sm_val);
                   }
@@ -2765,17 +2755,17 @@
                 double dm_val = get_dregister(dm);
                 if (instr->Bit(16) == 0) {
                   // Format(instr, "vcvtud'cond 'sd, 'dm");
-                  if (dm_val >= INT_MAX) {
-                    ud_val = INT_MAX;
+                  if (dm_val >= static_cast<double>(INT32_MAX)) {
+                    ud_val = INT32_MAX;
                   } else if (dm_val > 0.0) {
                     ud_val = static_cast<uint32_t>(dm_val);
                   }
                 } else {
                   // Format(instr, "vcvtid'cond 'sd, 'dm");
-                  if (dm_val <= INT_MIN) {
-                    id_val = INT_MIN;
-                  } else if (dm_val >= INT_MAX) {
-                    id_val = INT_MAX;
+                  if (dm_val <= static_cast<double>(INT32_MIN)) {
+                    id_val = INT32_MIN;
+                  } else if (dm_val >= static_cast<double>(INT32_MAX)) {
+                    id_val = INT32_MAX;
                   } else if (isnan(dm_val)) {
                     id_val = 0;
                   } else {
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 235a296..1618d73 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -796,23 +796,20 @@
                           int argument_count) {
     MutexLocker ml(mutex_);
 
-    for (Redirection* current = list_; current != NULL;
+    Redirection* old_head = list_.load(std::memory_order_relaxed);
+    for (Redirection* current = old_head; current != nullptr;
          current = current->next_) {
       if (current->external_function_ == external_function) return current;
     }
 
     Redirection* redirection =
         new Redirection(external_function, call_kind, argument_count);
-    redirection->next_ = list_;
+    redirection->next_ = old_head;
 
     // Use a memory fence to ensure all pending writes are written at the time
     // of updating the list head, so the profiling thread always has a valid
     // list to look at.
-    Redirection* old_head = list_;
-    Redirection* replaced_list_head =
-        AtomicOperations::CompareAndSwapPointer<Redirection>(&list_, old_head,
-                                                             redirection);
-    ASSERT(old_head == replaced_list_head);
+    list_.store(redirection, std::memory_order_release);
 
     return redirection;
   }
@@ -829,8 +826,8 @@
   // allowed to hold any locks - which is precisely the reason why the list is
   // prepend-only and a memory fence is used when writing the list head [list_]!
   static uword FunctionForRedirect(uword address_of_hlt) {
-    Redirection* current;
-    for (current = list_; current != NULL; current = current->next_) {
+    for (Redirection* current = list_.load(std::memory_order_acquire);
+         current != nullptr; current = current->next_) {
       if (current->address_of_hlt_instruction() == address_of_hlt) {
         return current->external_function_;
       }
@@ -853,11 +850,11 @@
   int argument_count_;
   uint32_t hlt_instruction_;
   Redirection* next_;
-  static Redirection* list_;
+  static std::atomic<Redirection*> list_;
   static Mutex* mutex_;
 };
 
-Redirection* Redirection::list_ = NULL;
+std::atomic<Redirection*> Redirection::list_ = {nullptr};
 Mutex* Redirection::mutex_ = new Mutex();
 
 uword Simulator::RedirectExternalReference(uword function,
@@ -1153,11 +1150,11 @@
     return 1;  // Failure.
   }
 
-  uword old_value = exclusive_access_value_;
+  int64_t old_value = exclusive_access_value_;
   ClearExclusive();
 
-  if (AtomicOperations::CompareAndSwapWord(reinterpret_cast<uword*>(addr),
-                                           old_value, value) == old_value) {
+  auto atomic_addr = reinterpret_cast<RelaxedAtomic<int64_t>*>(addr);
+  if (atomic_addr->compare_exchange_weak(old_value, value)) {
     return 0;  // Success.
   }
   return 1;  // Failure.
@@ -1171,11 +1168,11 @@
     return 1;  // Failure.
   }
 
-  uint32_t old_value = static_cast<uint32_t>(exclusive_access_value_);
+  int32_t old_value = static_cast<uint32_t>(exclusive_access_value_);
   ClearExclusive();
 
-  if (AtomicOperations::CompareAndSwapUint32(reinterpret_cast<uint32_t*>(addr),
-                                             old_value, value) == old_value) {
+  auto atomic_addr = reinterpret_cast<RelaxedAtomic<int32_t>*>(addr);
+  if (atomic_addr->compare_exchange_weak(old_value, value)) {
     return 0;  // Success.
   }
   return 1;  // Failure.
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
deleted file mode 100644
index a0993b7..0000000
--- a/runtime/vm/simulator_dbc.cc
+++ /dev/null
@@ -1,4249 +0,0 @@
-// 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.
-
-#include <setjmp.h>  // NOLINT
-#include <stdlib.h>
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#if !defined(USING_SIMULATOR)
-#error "DBC is a simulated architecture"
-#endif
-
-#include "vm/simulator.h"
-
-#include "lib/ffi.h"
-#include "platform/assert.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/assembler/disassembler.h"
-#include "vm/compiler/backend/il.h"
-#include "vm/compiler/backend/locations.h"
-#include "vm/compiler/ffi.h"
-#include "vm/compiler/ffi_dbc_trampoline.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/constants_dbc.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/debugger.h"
-#include "vm/heap/safepoint.h"
-#include "vm/lockers.h"
-#include "vm/native_arguments.h"
-#include "vm/native_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/os_thread.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-
-namespace dart {
-
-DEFINE_FLAG(uint64_t,
-            trace_sim_after,
-            ULLONG_MAX,
-            "Trace simulator execution after instruction count reached.");
-DEFINE_FLAG(uint64_t,
-            stop_sim_at,
-            ULLONG_MAX,
-            "Instruction address or instruction count to stop simulator at.");
-
-// SimulatorSetjmpBuffer are linked together, and the last created one
-// is referenced by the Simulator. When an exception is thrown, the exception
-// runtime looks at where to jump and finds the corresponding
-// SimulatorSetjmpBuffer based on the stack pointer of the exception handler.
-// The runtime then does a Longjmp on that buffer to return to the simulator.
-class SimulatorSetjmpBuffer {
- public:
-  void Longjmp() {
-    // "This" is now the last setjmp buffer.
-    simulator_->set_last_setjmp_buffer(this);
-    longjmp(buffer_, 1);
-  }
-
-  explicit SimulatorSetjmpBuffer(Simulator* sim) {
-    simulator_ = sim;
-    link_ = sim->last_setjmp_buffer();
-    sim->set_last_setjmp_buffer(this);
-    fp_ = sim->fp_;
-  }
-
-  ~SimulatorSetjmpBuffer() {
-    ASSERT(simulator_->last_setjmp_buffer() == this);
-    simulator_->set_last_setjmp_buffer(link_);
-  }
-
-  SimulatorSetjmpBuffer* link() const { return link_; }
-
-  uword fp() const { return reinterpret_cast<uword>(fp_); }
-
-  jmp_buf buffer_;
-
- private:
-  RawObject** fp_;
-  Simulator* simulator_;
-  SimulatorSetjmpBuffer* link_;
-
-  friend class Simulator;
-
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(SimulatorSetjmpBuffer);
-};
-
-DART_FORCE_INLINE static RawObject** SavedCallerFP(RawObject** FP) {
-  return reinterpret_cast<RawObject**>(FP[kSavedCallerFpSlotFromFp]);
-}
-
-DART_FORCE_INLINE static RawObject** FrameArguments(RawObject** FP,
-                                                    intptr_t argc) {
-  return FP - (kDartFrameFixedSize + argc);
-}
-
-#define RAW_CAST(Type, val) (SimulatorHelpers::CastTo##Type(val))
-
-class SimulatorHelpers {
- public:
-#define DEFINE_CASTS(Type)                                                     \
-  DART_FORCE_INLINE static Raw##Type* CastTo##Type(RawObject* obj) {           \
-    ASSERT((k##Type##Cid == kSmiCid) ? !obj->IsHeapObject()                    \
-                                     : obj->Is##Type());                       \
-    return reinterpret_cast<Raw##Type*>(obj);                                  \
-  }
-  CLASS_LIST(DEFINE_CASTS)
-#undef DEFINE_CASTS
-
-  DART_FORCE_INLINE static RawSmi* GetClassIdAsSmi(RawObject* obj) {
-    return Smi::New(obj->IsHeapObject() ? obj->GetClassId()
-                                        : static_cast<intptr_t>(kSmiCid));
-  }
-
-  DART_FORCE_INLINE static intptr_t GetClassId(RawObject* obj) {
-    return obj->IsHeapObject() ? obj->GetClassId()
-                               : static_cast<intptr_t>(kSmiCid);
-  }
-
-  DART_FORCE_INLINE static void IncrementUsageCounter(RawFunction* f) {
-    f->ptr()->usage_counter_++;
-  }
-
-  DART_FORCE_INLINE static void IncrementICUsageCount(RawObject** entries,
-                                                      intptr_t offset,
-                                                      intptr_t args_tested) {
-    const intptr_t count_offset = ICData::CountIndexFor(args_tested);
-    const intptr_t raw_smi_old =
-        reinterpret_cast<intptr_t>(entries[offset + count_offset]);
-    const intptr_t raw_smi_new = raw_smi_old + Smi::RawValue(1);
-    *reinterpret_cast<intptr_t*>(&entries[offset + count_offset]) = raw_smi_new;
-  }
-
-  DART_FORCE_INLINE static bool IsStrictEqualWithNumberCheck(RawObject* lhs,
-                                                             RawObject* rhs) {
-    if (lhs == rhs) {
-      return true;
-    }
-
-    if (lhs->IsHeapObject() && rhs->IsHeapObject()) {
-      const intptr_t lhs_cid = lhs->GetClassId();
-      const intptr_t rhs_cid = rhs->GetClassId();
-      if (lhs_cid == rhs_cid) {
-        switch (lhs_cid) {
-          case kDoubleCid:
-            return (bit_cast<uint64_t, double>(
-                        static_cast<RawDouble*>(lhs)->ptr()->value_) ==
-                    bit_cast<uint64_t, double>(
-                        static_cast<RawDouble*>(rhs)->ptr()->value_));
-
-          case kMintCid:
-            return (static_cast<RawMint*>(lhs)->ptr()->value_ ==
-                    static_cast<RawMint*>(rhs)->ptr()->value_);
-        }
-      }
-    }
-
-    return false;
-  }
-
-  template <typename T>
-  DART_FORCE_INLINE static T* Untag(T* tagged) {
-    return tagged->ptr();
-  }
-
-  DART_FORCE_INLINE static bool CheckIndex(RawSmi* index, RawSmi* length) {
-    return !index->IsHeapObject() && (reinterpret_cast<intptr_t>(index) >= 0) &&
-           (reinterpret_cast<intptr_t>(index) <
-            reinterpret_cast<intptr_t>(length));
-  }
-
-  DART_FORCE_INLINE static intptr_t ArgDescTypeArgsLen(RawArray* argdesc) {
-    return Smi::Value(*reinterpret_cast<RawSmi**>(
-        reinterpret_cast<uword>(argdesc->ptr()) +
-        Array::element_offset(ArgumentsDescriptor::kTypeArgsLenIndex)));
-  }
-
-  DART_FORCE_INLINE static intptr_t ArgDescArgCount(RawArray* argdesc) {
-    return Smi::Value(*reinterpret_cast<RawSmi**>(
-        reinterpret_cast<uword>(argdesc->ptr()) +
-        Array::element_offset(ArgumentsDescriptor::kCountIndex)));
-  }
-
-  DART_FORCE_INLINE static intptr_t ArgDescPosCount(RawArray* argdesc) {
-    return Smi::Value(*reinterpret_cast<RawSmi**>(
-        reinterpret_cast<uword>(argdesc->ptr()) +
-        Array::element_offset(ArgumentsDescriptor::kPositionalCountIndex)));
-  }
-
-  static bool ObjectArraySetIndexed(Thread* thread,
-                                    RawObject** FP,
-                                    RawObject** result) {
-    return ObjectArraySetIndexedUnchecked(thread, FP, result);
-  }
-
-  static bool ObjectArraySetIndexedUnchecked(Thread* thread,
-                                             RawObject** FP,
-                                             RawObject** result) {
-    RawObject** args = FrameArguments(FP, 3);
-    RawSmi* index = static_cast<RawSmi*>(args[1]);
-    RawArray* array = static_cast<RawArray*>(args[0]);
-    if (CheckIndex(index, array->ptr()->length_)) {
-      array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index),
-                               args[2], thread);
-      return true;
-    }
-    return false;
-  }
-
-  static bool ObjectArrayGetIndexed(Thread* thread,
-                                    RawObject** FP,
-                                    RawObject** result) {
-    RawObject** args = FrameArguments(FP, 2);
-    RawSmi* index = static_cast<RawSmi*>(args[1]);
-    RawArray* array = static_cast<RawArray*>(args[0]);
-    if (CheckIndex(index, array->ptr()->length_)) {
-      *result = array->ptr()->data()[Smi::Value(index)];
-      return true;
-    }
-    return false;
-  }
-
-  static bool GrowableArraySetIndexed(Thread* thread,
-                                      RawObject** FP,
-                                      RawObject** result) {
-    return GrowableArraySetIndexedUnchecked(thread, FP, result);
-  }
-
-  static bool GrowableArraySetIndexedUnchecked(Thread* thread,
-                                               RawObject** FP,
-                                               RawObject** result) {
-    RawObject** args = FrameArguments(FP, 3);
-    RawSmi* index = static_cast<RawSmi*>(args[1]);
-    RawGrowableObjectArray* array =
-        static_cast<RawGrowableObjectArray*>(args[0]);
-    if (CheckIndex(index, array->ptr()->length_)) {
-      RawArray* data = array->ptr()->data_;
-      data->StoreArrayPointer(data->ptr()->data() + Smi::Value(index), args[2],
-                              thread);
-      return true;
-    }
-    return false;
-  }
-
-  static bool GrowableArrayGetIndexed(Thread* thread,
-                                      RawObject** FP,
-                                      RawObject** result) {
-    RawObject** args = FrameArguments(FP, 2);
-    RawSmi* index = static_cast<RawSmi*>(args[1]);
-    RawGrowableObjectArray* array =
-        static_cast<RawGrowableObjectArray*>(args[0]);
-    if (CheckIndex(index, array->ptr()->length_)) {
-      *result = array->ptr()->data_->ptr()->data()[Smi::Value(index)];
-      return true;
-    }
-    return false;
-  }
-
-  static bool Double_getIsNan(Thread* thread,
-                              RawObject** FP,
-                              RawObject** result) {
-    RawObject** args = FrameArguments(FP, 1);
-    RawDouble* d = static_cast<RawDouble*>(args[0]);
-    *result =
-        isnan(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool Double_getIsInfinite(Thread* thread,
-                                   RawObject** FP,
-                                   RawObject** result) {
-    RawObject** args = FrameArguments(FP, 1);
-    RawDouble* d = static_cast<RawDouble*>(args[0]);
-    *result =
-        isinf(d->ptr()->value_) ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool ObjectEquals(Thread* thread, RawObject** FP, RawObject** result) {
-    RawObject** args = FrameArguments(FP, 2);
-    *result = args[0] == args[1] ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool ObjectRuntimeType(Thread* thread,
-                                RawObject** FP,
-                                RawObject** result) {
-    RawObject** args = FrameArguments(FP, 1);
-    const intptr_t cid = GetClassId(args[0]);
-    if (cid == kClosureCid) {
-      return false;
-    }
-    if (cid < kNumPredefinedCids) {
-      if (cid == kDoubleCid) {
-        *result = thread->isolate()->object_store()->double_type();
-        return true;
-      } else if (RawObject::IsStringClassId(cid)) {
-        *result = thread->isolate()->object_store()->string_type();
-        return true;
-      } else if (RawObject::IsIntegerClassId(cid)) {
-        *result = thread->isolate()->object_store()->int_type();
-        return true;
-      }
-    }
-    RawClass* cls = thread->isolate()->class_table()->At(cid);
-    if (cls->ptr()->num_type_arguments_ != 0) {
-      return false;
-    }
-    RawType* typ = cls->ptr()->declaration_type_;
-    if (typ == Object::null()) {
-      return false;
-    }
-    *result = static_cast<RawObject*>(typ);
-    return true;
-  }
-
-  static bool GetDoubleOperands(RawObject** args, double* d1, double* d2) {
-    RawObject* obj2 = args[1];
-    if (!obj2->IsHeapObject()) {
-      *d2 =
-          static_cast<double>(reinterpret_cast<intptr_t>(obj2) >> kSmiTagSize);
-    } else if (obj2->GetClassId() == kDoubleCid) {
-      RawDouble* obj2d = static_cast<RawDouble*>(obj2);
-      *d2 = obj2d->ptr()->value_;
-    } else {
-      return false;
-    }
-    RawDouble* obj1 = static_cast<RawDouble*>(args[0]);
-    *d1 = obj1->ptr()->value_;
-    return true;
-  }
-
-  static RawObject* AllocateDouble(Thread* thread, double value) {
-    const intptr_t instance_size = Double::InstanceSize();
-    const uword start =
-        thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
-    if (LIKELY(start != 0)) {
-      uword tags = 0;
-      tags = RawObject::ClassIdTag::update(kDoubleCid, tags);
-      tags = RawObject::SizeTag::update(instance_size, tags);
-      tags = RawObject::NewBit::update(true, tags);
-      // Also writes zero in the hash_ field.
-      *reinterpret_cast<uword*>(start + Double::tags_offset()) = tags;
-      *reinterpret_cast<double*>(start + Double::value_offset()) = value;
-      return reinterpret_cast<RawObject*>(start + kHeapObjectTag);
-    }
-    return NULL;
-  }
-
-  static bool Double_add(Thread* thread, RawObject** FP, RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    RawObject* new_double = AllocateDouble(thread, d1 + d2);
-    if (new_double != NULL) {
-      *result = new_double;
-      return true;
-    }
-    return false;
-  }
-
-  static bool Double_mul(Thread* thread, RawObject** FP, RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    RawObject* new_double = AllocateDouble(thread, d1 * d2);
-    if (new_double != NULL) {
-      *result = new_double;
-      return true;
-    }
-    return false;
-  }
-
-  static bool Double_sub(Thread* thread, RawObject** FP, RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    RawObject* new_double = AllocateDouble(thread, d1 - d2);
-    if (new_double != NULL) {
-      *result = new_double;
-      return true;
-    }
-    return false;
-  }
-
-  static bool Double_div(Thread* thread, RawObject** FP, RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    RawObject* new_double = AllocateDouble(thread, d1 / d2);
-    if (new_double != NULL) {
-      *result = new_double;
-      return true;
-    }
-    return false;
-  }
-
-  static bool Double_greaterThan(Thread* thread,
-                                 RawObject** FP,
-                                 RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    *result = d1 > d2 ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool Double_greaterEqualThan(Thread* thread,
-                                      RawObject** FP,
-                                      RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    *result = d1 >= d2 ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool Double_lessThan(Thread* thread,
-                              RawObject** FP,
-                              RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    *result = d1 < d2 ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool Double_equal(Thread* thread, RawObject** FP, RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    *result = d1 == d2 ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool Double_lessEqualThan(Thread* thread,
-                                   RawObject** FP,
-                                   RawObject** result) {
-    double d1, d2;
-    if (!GetDoubleOperands(FrameArguments(FP, 2), &d1, &d2)) {
-      return false;
-    }
-    *result = d1 <= d2 ? Bool::True().raw() : Bool::False().raw();
-    return true;
-  }
-
-  static bool ClearAsyncThreadStack(Thread* thread,
-                                    RawObject** FP,
-                                    RawObject** result) {
-    thread->clear_async_stack_trace();
-    *result = Object::null();
-    return true;
-  }
-
-  static bool SetAsyncThreadStackTrace(Thread* thread,
-                                       RawObject** FP,
-                                       RawObject** result) {
-    RawObject** args = FrameArguments(FP, 1);
-    thread->set_raw_async_stack_trace(
-        reinterpret_cast<RawStackTrace*>(args[0]));
-    *result = Object::null();
-    return true;
-  }
-
-  DART_FORCE_INLINE static RawCode* FrameCode(RawObject** FP) {
-    ASSERT(GetClassId(FP[kPcMarkerSlotFromFp]) == kCodeCid);
-    return static_cast<RawCode*>(FP[kPcMarkerSlotFromFp]);
-  }
-
-  DART_FORCE_INLINE static void SetFrameCode(RawObject** FP, RawCode* code) {
-    ASSERT(GetClassId(code) == kCodeCid);
-    FP[kPcMarkerSlotFromFp] = code;
-  }
-
-  DART_FORCE_INLINE static uint8_t* GetTypedData(RawObject* obj,
-                                                 RawObject* index) {
-    ASSERT(RawObject::IsTypedDataClassId(obj->GetClassId()));
-    RawTypedData* array = reinterpret_cast<RawTypedData*>(obj);
-    const intptr_t byte_offset = Smi::Value(RAW_CAST(Smi, index));
-    ASSERT(byte_offset >= 0);
-    return array->ptr()->data() + byte_offset;
-  }
-};
-
-DART_FORCE_INLINE static uint32_t* SavedCallerPC(RawObject** FP) {
-  return reinterpret_cast<uint32_t*>(FP[kSavedCallerPcSlotFromFp]);
-}
-
-DART_FORCE_INLINE static RawFunction* FrameFunction(RawObject** FP) {
-  RawFunction* function = static_cast<RawFunction*>(FP[kFunctionSlotFromFp]);
-  ASSERT(SimulatorHelpers::GetClassId(function) == kFunctionCid ||
-         SimulatorHelpers::GetClassId(function) == kNullCid);
-  return function;
-}
-
-IntrinsicHandler Simulator::intrinsics_[Simulator::kIntrinsicCount];
-
-// Synchronization primitives support.
-void Simulator::Init() {
-  for (intptr_t i = 0; i < kIntrinsicCount; i++) {
-    intrinsics_[i] = 0;
-  }
-
-  intrinsics_[kObjectArraySetIndexedIntrinsic] =
-      SimulatorHelpers::ObjectArraySetIndexed;
-  intrinsics_[kObjectArraySetIndexedUncheckedIntrinsic] =
-      SimulatorHelpers::ObjectArraySetIndexedUnchecked;
-  intrinsics_[kObjectArrayGetIndexedIntrinsic] =
-      SimulatorHelpers::ObjectArrayGetIndexed;
-  intrinsics_[kGrowableArraySetIndexedIntrinsic] =
-      SimulatorHelpers::GrowableArraySetIndexed;
-  intrinsics_[kGrowableArraySetIndexedUncheckedIntrinsic] =
-      SimulatorHelpers::GrowableArraySetIndexedUnchecked;
-  intrinsics_[kGrowableArrayGetIndexedIntrinsic] =
-      SimulatorHelpers::GrowableArrayGetIndexed;
-  intrinsics_[kObjectEqualsIntrinsic] = SimulatorHelpers::ObjectEquals;
-  intrinsics_[kObjectRuntimeTypeIntrinsic] =
-      SimulatorHelpers::ObjectRuntimeType;
-
-  intrinsics_[kDouble_getIsNaNIntrinsic] = SimulatorHelpers::Double_getIsNan;
-  intrinsics_[kDouble_getIsInfiniteIntrinsic] =
-      SimulatorHelpers::Double_getIsInfinite;
-  intrinsics_[kDouble_addIntrinsic] = SimulatorHelpers::Double_add;
-  intrinsics_[kDouble_mulIntrinsic] = SimulatorHelpers::Double_mul;
-  intrinsics_[kDouble_subIntrinsic] = SimulatorHelpers::Double_sub;
-  intrinsics_[kDouble_divIntrinsic] = SimulatorHelpers::Double_div;
-  intrinsics_[kDouble_greaterThanIntrinsic] =
-      SimulatorHelpers::Double_greaterThan;
-  intrinsics_[kDouble_greaterEqualThanIntrinsic] =
-      SimulatorHelpers::Double_greaterEqualThan;
-  intrinsics_[kDouble_lessThanIntrinsic] = SimulatorHelpers::Double_lessThan;
-  intrinsics_[kDouble_equalIntrinsic] = SimulatorHelpers::Double_equal;
-  intrinsics_[kDouble_lessEqualThanIntrinsic] =
-      SimulatorHelpers::Double_lessEqualThan;
-  intrinsics_[kClearAsyncThreadStackTraceIntrinsic] =
-      SimulatorHelpers::ClearAsyncThreadStack;
-  intrinsics_[kSetAsyncThreadStackTraceIntrinsic] =
-      SimulatorHelpers::SetAsyncThreadStackTrace;
-}
-
-Simulator::Simulator() : stack_(NULL), fp_(NULL), pp_(NULL), argdesc_(NULL) {
-  // Setup simulator support first. Some of this information is needed to
-  // setup the architecture state.
-  // We allocate the stack here, the size is computed as the sum of
-  // the size specified by the user and the buffer space needed for
-  // handling stack overflow exceptions. To be safe in potential
-  // stack underflows we also add some underflow buffer space.
-  stack_ = new uintptr_t[(OSThread::GetSpecifiedStackSize() +
-                          OSThread::kStackSizeBufferMax +
-                          kSimulatorStackUnderflowSize) /
-                         sizeof(uintptr_t)];
-  // Low address.
-  stack_base_ = reinterpret_cast<uword>(stack_) + kSimulatorStackUnderflowSize;
-  // Limit for StackOverflowError.
-  overflow_stack_limit_ = stack_base_ + OSThread::GetSpecifiedStackSize();
-  // High address.
-  stack_limit_ = overflow_stack_limit_ + OSThread::kStackSizeBufferMax;
-
-  last_setjmp_buffer_ = NULL;
-
-  DEBUG_ONLY(icount_ = 0);
-}
-
-Simulator::~Simulator() {
-  delete[] stack_;
-  Isolate* isolate = Isolate::Current();
-  if (isolate != NULL) {
-    isolate->set_simulator(NULL);
-  }
-}
-
-// Get the active Simulator for the current isolate.
-Simulator* Simulator::Current() {
-  Isolate* isolate = Isolate::Current();
-  Simulator* simulator = isolate->simulator();
-  if (simulator == NULL) {
-    NoSafepointScope no_safepoint;
-    simulator = new Simulator();
-    isolate->set_simulator(simulator);
-  }
-  return simulator;
-}
-
-#if defined(DEBUG)
-// Returns true if tracing of executed instructions is enabled.
-DART_FORCE_INLINE bool Simulator::IsTracingExecution() const {
-  return icount_ > FLAG_trace_sim_after;
-}
-
-// Prints bytecode instruction at given pc for instruction tracing.
-DART_NOINLINE void Simulator::TraceInstruction(uint32_t* pc) const {
-  THR_Print("%" Pu64 " ", icount_);
-  if (FLAG_support_disassembler) {
-    Disassembler::Disassemble(reinterpret_cast<uword>(pc),
-                              reinterpret_cast<uword>(pc + 1));
-  } else {
-    THR_Print("Disassembler not supported in this mode.\n");
-  }
-}
-#endif  // defined(DEBUG)
-
-// Calls into the Dart runtime are based on this interface.
-typedef void (*SimulatorRuntimeCall)(NativeArguments arguments);
-
-// Calls to leaf Dart runtime functions are based on this interface.
-typedef intptr_t (*SimulatorLeafRuntimeCall)(intptr_t r0,
-                                             intptr_t r1,
-                                             intptr_t r2,
-                                             intptr_t r3);
-
-// Calls to leaf float Dart runtime functions are based on this interface.
-typedef double (*SimulatorLeafFloatRuntimeCall)(double d0, double d1);
-
-// Set up an exit frame for the garbage collector.
-void Simulator::Exit(Thread* thread,
-                     RawObject** base,
-                     RawObject** frame,
-                     uint32_t* pc) {
-  frame[0] = Function::null();
-  frame[1] = Code::null();
-  frame[2] = reinterpret_cast<RawObject*>(pc);
-  frame[3] = reinterpret_cast<RawObject*>(base);
-  fp_ = frame + kDartFrameFixedSize;
-  thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_));
-}
-
-// TODO(vegorov): Investigate advantages of using
-// __builtin_s{add,sub,mul}_overflow() intrinsics here and below.
-// Note that they may clobber the output location even when there is overflow:
-// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
-                                                    intptr_t* out) {
-  intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
-  asm volatile(
-      "add %2, %1\n"
-      "jo 1f;\n"
-      "xor %0, %0\n"
-      "mov %1, 0(%3)\n"
-      "1: "
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
-#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
-  asm volatile(
-      "adds %1, %1, %2;\n"
-      "bvs 1f;\n"
-      "mov %0, #0;\n"
-      "str %1, [%3, #0]\n"
-      "1:"
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
-#else
-#error "Unsupported platform"
-#endif
-  return (res != 0);
-}
-
-DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
-                                                    intptr_t* out) {
-  intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
-  asm volatile(
-      "sub %2, %1\n"
-      "jo 1f;\n"
-      "xor %0, %0\n"
-      "mov %1, 0(%3)\n"
-      "1: "
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
-#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
-  asm volatile(
-      "subs %1, %1, %2;\n"
-      "bvs 1f;\n"
-      "mov %0, #0;\n"
-      "str %1, [%3, #0]\n"
-      "1:"
-      : "+r"(res), "+r"(lhs)
-      : "r"(rhs), "r"(out)
-      : "cc");
-#else
-#error "Unsupported platform"
-#endif
-  return (res != 0);
-}
-
-DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs,
-                                                    intptr_t rhs,
-                                                    intptr_t* out) {
-  const intptr_t kMaxBits = (sizeof(intptr_t) * 8) - 2;
-  if ((Utils::HighestBit(lhs) + Utils::HighestBit(rhs)) < kMaxBits) {
-    *out = lhs * rhs;
-    return false;
-  }
-  return true;
-}
-
-DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) {
-  return ((a | b) & kHeapObjectTag) == 0;
-}
-
-#define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres)
-#define SMI_COND(cond, lhs, rhs, pres)                                         \
-  ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false)
-#define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres)
-#define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres)
-#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres)
-#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false)
-#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false)
-#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false)
-
-void Simulator::CallRuntime(Thread* thread,
-                            RawObject** base,
-                            RawObject** exit_frame,
-                            uint32_t* pc,
-                            intptr_t argc_tag,
-                            RawObject** args,
-                            RawObject** result,
-                            uword target) {
-  Exit(thread, base, exit_frame, pc);
-  NativeArguments native_args(thread, argc_tag, args, result);
-  reinterpret_cast<RuntimeFunction>(target)(native_args);
-}
-
-DART_FORCE_INLINE static void EnterSyntheticFrame(RawObject*** FP,
-                                                  RawObject*** SP,
-                                                  uint32_t* pc) {
-  RawObject** fp = *SP + kDartFrameFixedSize;
-  fp[kPcMarkerSlotFromFp] = 0;
-  fp[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(pc);
-  fp[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
-  *FP = fp;
-  *SP = fp - 1;
-}
-
-DART_FORCE_INLINE static void LeaveSyntheticFrame(RawObject*** FP,
-                                                  RawObject*** SP) {
-  RawObject** fp = *FP;
-  *FP = reinterpret_cast<RawObject**>(fp[kSavedCallerFpSlotFromFp]);
-  *SP = fp - kDartFrameFixedSize;
-}
-
-DART_FORCE_INLINE void Simulator::Invoke(Thread* thread,
-                                         RawObject** call_base,
-                                         RawObject** call_top,
-                                         uint32_t** pc,
-                                         RawObject*** FP,
-                                         RawObject*** SP) {
-  RawObject** callee_fp = call_top + kDartFrameFixedSize;
-
-  RawFunction* function = FrameFunction(callee_fp);
-  RawCode* code = function->ptr()->code_;
-  callee_fp[kPcMarkerSlotFromFp] = code;
-  callee_fp[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
-  callee_fp[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
-  pp_ = code->ptr()->object_pool_;
-  *pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
-  pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
-  *FP = callee_fp;
-  *SP = *FP - 1;
-}
-
-void Simulator::InlineCacheMiss(int checked_args,
-                                Thread* thread,
-                                RawICData* icdata,
-                                RawObject** args,
-                                RawObject** top,
-                                uint32_t* pc,
-                                RawObject** FP,
-                                RawObject** SP) {
-  RawObject** result = top;
-  top[0] = 0;  // Clean up result slot.
-
-  // Save arguments descriptor as it may be clobbered by running Dart code
-  // during the call to miss handler (class finalization).
-  top[1] = argdesc_;
-
-  RawObject** miss_handler_args = top + 2;
-  for (intptr_t i = 0; i < checked_args; i++) {
-    miss_handler_args[i] = args[i];
-  }
-  miss_handler_args[checked_args] = icdata;
-  RuntimeFunction handler = NULL;
-  switch (checked_args) {
-    case 1:
-      handler = DRT_InlineCacheMissHandlerOneArg;
-      break;
-    case 2:
-      handler = DRT_InlineCacheMissHandlerTwoArgs;
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
-
-  // Handler arguments: arguments to check and an ICData object.
-  const intptr_t miss_handler_argc = checked_args + 1;
-  RawObject** exit_frame = miss_handler_args + miss_handler_argc;
-  CallRuntime(thread, FP, exit_frame, pc, miss_handler_argc, miss_handler_args,
-              result, reinterpret_cast<uword>(handler));
-
-  argdesc_ = Array::RawCast(top[1]);
-}
-
-DART_FORCE_INLINE void Simulator::InstanceCall1(Thread* thread,
-                                                RawICData* icdata,
-                                                RawObject** call_base,
-                                                RawObject** top,
-                                                uint32_t** pc,
-                                                RawObject*** FP,
-                                                RawObject*** SP,
-                                                bool optimized) {
-  ASSERT(icdata->GetClassId() == kICDataCid);
-
-  const intptr_t kCheckedArgs = 1;
-  RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->entries_->ptr();
-
-  const intptr_t type_args_len =
-      SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
-  const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
-  RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx]);
-
-  bool found = false;
-  const intptr_t length = Smi::Value(cache->length_);
-  intptr_t i;
-  for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
-    if (cache->data()[i + 0] == receiver_cid) {
-      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
-      found = true;
-      break;
-    }
-  }
-
-  argdesc_ = icdata->ptr()->args_descriptor_;
-
-  if (found) {
-    if (!optimized) {
-      SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs);
-    }
-  } else {
-    InlineCacheMiss(kCheckedArgs, thread, icdata, call_base + receiver_idx, top,
-                    *pc, *FP, *SP);
-  }
-
-  Invoke(thread, call_base, top, pc, FP, SP);
-}
-
-DART_FORCE_INLINE void Simulator::InstanceCall2(Thread* thread,
-                                                RawICData* icdata,
-                                                RawObject** call_base,
-                                                RawObject** top,
-                                                uint32_t** pc,
-                                                RawObject*** FP,
-                                                RawObject*** SP,
-                                                bool optimized) {
-  ASSERT(icdata->GetClassId() == kICDataCid);
-
-  const intptr_t kCheckedArgs = 2;
-  RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->entries_->ptr();
-
-  const intptr_t type_args_len =
-      SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
-  const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
-  RawSmi* receiver_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx]);
-  RawSmi* arg0_cid = SimulatorHelpers::GetClassIdAsSmi(args[receiver_idx + 1]);
-
-  bool found = false;
-  const intptr_t length = Smi::Value(cache->length_);
-  intptr_t i;
-  for (i = 0; i < (length - (kCheckedArgs + 2)); i += (kCheckedArgs + 2)) {
-    if ((cache->data()[i + 0] == receiver_cid) &&
-        (cache->data()[i + 1] == arg0_cid)) {
-      top[0] = cache->data()[i + ICData::TargetIndexFor(kCheckedArgs)];
-      found = true;
-      break;
-    }
-  }
-
-  argdesc_ = icdata->ptr()->args_descriptor_;
-
-  if (found) {
-    if (!optimized) {
-      SimulatorHelpers::IncrementICUsageCount(cache->data(), i, kCheckedArgs);
-    }
-  } else {
-    InlineCacheMiss(kCheckedArgs, thread, icdata, call_base + receiver_idx, top,
-                    *pc, *FP, *SP);
-  }
-
-  Invoke(thread, call_base, top, pc, FP, SP);
-}
-
-DART_FORCE_INLINE void Simulator::PrepareForTailCall(
-    RawCode* code,
-    RawImmutableArray* args_desc,
-    RawObject** FP,
-    RawObject*** SP,
-    uint32_t** pc) {
-  // Drop all stack locals.
-  *SP = FP - 1;
-
-  // Replace the callee with the new [code].
-  FP[kFunctionSlotFromFp] = Object::null();
-  FP[kPcMarkerSlotFromFp] = code;
-  *pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
-  pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-  pp_ = code->ptr()->object_pool_;
-  argdesc_ = args_desc;
-}
-
-// Note: functions below are marked DART_NOINLINE to recover performance where
-// inlining these functions into the interpreter loop seemed to cause some code
-// quality issues. Functions with the "returns_twice" attribute, such as setjmp,
-// prevent reusing spill slots and large frame sizes.
-DART_NOINLINE static bool InvokeRuntime(Thread* thread,
-                                        Simulator* sim,
-                                        RuntimeFunction drt,
-                                        const NativeArguments& args) {
-  SimulatorSetjmpBuffer buffer(sim);
-  if (!setjmp(buffer.buffer_)) {
-    thread->set_vm_tag(reinterpret_cast<uword>(drt));
-    drt(args);
-    thread->set_vm_tag(VMTag::kDartCompiledTagId);
-    thread->set_top_exit_frame_info(0);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-DART_NOINLINE static bool InvokeNative(Thread* thread,
-                                       Simulator* sim,
-                                       NativeFunctionWrapper wrapper,
-                                       Dart_NativeFunction function,
-                                       Dart_NativeArguments args) {
-  SimulatorSetjmpBuffer buffer(sim);
-  if (!setjmp(buffer.buffer_)) {
-    thread->set_vm_tag(reinterpret_cast<uword>(function));
-    wrapper(args, function);
-    thread->set_vm_tag(VMTag::kDartCompiledTagId);
-    thread->set_top_exit_frame_info(0);
-    return true;
-  } else {
-    return false;
-  }
-}
-
-// Note: all macro helpers are intended to be used only inside Simulator::Call.
-
-// Counts and prints executed bytecode instructions (in DEBUG mode).
-#if defined(DEBUG)
-#define TRACE_INSTRUCTION                                                      \
-  icount_++;                                                                   \
-  if (IsTracingExecution()) {                                                  \
-    TraceInstruction(pc - 1);                                                  \
-  }
-#else
-#define TRACE_INSTRUCTION
-#endif  // defined(DEBUG)
-
-// Decode opcode and A part of the given value and dispatch to the
-// corresponding bytecode handler.
-#ifdef DART_HAS_COMPUTED_GOTO
-#define DISPATCH_OP(val)                                                       \
-  do {                                                                         \
-    op = (val);                                                                \
-    rA = ((op >> 8) & 0xFF);                                                   \
-    TRACE_INSTRUCTION                                                          \
-    goto* dispatch[op & 0xFF];                                                 \
-  } while (0)
-#else
-#define DISPATCH_OP(val)                                                       \
-  do {                                                                         \
-    op = (val);                                                                \
-    rA = ((op >> 8) & 0xFF);                                                   \
-    TRACE_INSTRUCTION                                                          \
-    goto SwitchDispatch;                                                       \
-  } while (0)
-#endif
-
-// Fetch next operation from PC, increment program counter and dispatch.
-#define DISPATCH() DISPATCH_OP(*pc++)
-
-// Define entry point that handles bytecode Name with the given operand format.
-#define BYTECODE(Name, Operands)                                               \
-  BYTECODE_HEADER(Name, DECLARE_##Operands, DECODE_##Operands)
-
-#define BYTECODE_HEADER(Name, Declare, Decode)                                 \
-  Declare;                                                                     \
-  bc##Name : Decode
-
-// Helpers to decode common instruction formats. Used in conjunction with
-// BYTECODE() macro.
-#define DECLARE_A_B_C                                                          \
-  uint16_t rB, rC;                                                             \
-  USE(rB);                                                                     \
-  USE(rC)
-#define DECODE_A_B_C                                                           \
-  rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask);       \
-  rC = ((op >> SimulatorBytecode::kCShift) & SimulatorBytecode::kCMask);
-
-#define DECLARE_A_B_Y                                                          \
-  uint16_t rB;                                                                 \
-  int8_t rY;                                                                   \
-  USE(rB);                                                                     \
-  USE(rY)
-#define DECODE_A_B_Y                                                           \
-  rB = ((op >> SimulatorBytecode::kBShift) & SimulatorBytecode::kBMask);       \
-  rY = ((op >> SimulatorBytecode::kYShift) & SimulatorBytecode::kYMask);
-
-#define DECLARE_0
-#define DECODE_0
-
-#define DECLARE_A
-#define DECODE_A
-
-#define DECLARE___D                                                            \
-  uint32_t rD;                                                                 \
-  USE(rD)
-#define DECODE___D rD = (op >> SimulatorBytecode::kDShift);
-
-#define DECLARE_A_D DECLARE___D
-#define DECODE_A_D DECODE___D
-
-#define DECLARE_A_X                                                            \
-  int32_t rD;                                                                  \
-  USE(rD)
-#define DECODE_A_X                                                             \
-  rD = (static_cast<int32_t>(op) >> SimulatorBytecode::kDShift);
-
-#define SMI_FASTPATH_ICDATA_INC                                                \
-  do {                                                                         \
-    ASSERT(SimulatorBytecode::IsCallOpcode(*pc));                              \
-    const uint16_t kidx = SimulatorBytecode::DecodeD(*pc);                     \
-    const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));           \
-    RawObject** entries = icdata->ptr()->entries_->ptr()->data();              \
-    SimulatorHelpers::IncrementICUsageCount(entries, 0, 2);                    \
-  } while (0);
-
-// Declare bytecode handler for a smi operation (e.g. AddTOS) with the
-// given result type and the given behavior specified as a function
-// that takes left and right operands and result slot and returns
-// true if fast-path succeeds.
-#define SMI_FASTPATH_TOS(ResultT, Func)                                        \
-  {                                                                            \
-    const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]);                   \
-    const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]);                   \
-    ResultT* slot = reinterpret_cast<ResultT*>(SP - 1);                        \
-    if (NOT_IN_PRODUCT(LIKELY(!thread->isolate()->single_step()) &&)           \
-            LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) {          \
-      SMI_FASTPATH_ICDATA_INC;                                                 \
-      /* Fast path succeeded. Skip the generic call that follows. */           \
-      pc++;                                                                    \
-      /* We dropped 2 arguments and push result                   */           \
-      SP--;                                                                    \
-    }                                                                          \
-  }
-
-// Skip the next instruction if there is no overflow.
-#define SMI_OP_CHECK(ResultT, Func)                                            \
-  {                                                                            \
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);                   \
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);                   \
-    ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]);                       \
-    if (LIKELY(!Func(lhs, rhs, slot))) {                                       \
-      /* Success. Skip the instruction that follows. */                        \
-      pc++;                                                                    \
-    }                                                                          \
-  }
-
-// Do not check for overflow.
-#define SMI_OP_NOCHECK(ResultT, Func)                                          \
-  {                                                                            \
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);                   \
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);                   \
-    ResultT* slot = reinterpret_cast<ResultT*>(&FP[rA]);                       \
-    Func(lhs, rhs, slot);                                                      \
-  }
-
-// Exception handling helper. Gets handler FP and PC from the Simulator where
-// they were stored by Simulator::Longjmp and proceeds to execute the handler.
-// Corner case: handler PC can be a fake marker that marks entry frame, which
-// means exception was not handled in the Dart code. In this case we return
-// caught exception from Simulator::Call.
-#define HANDLE_EXCEPTION                                                       \
-  do {                                                                         \
-    FP = reinterpret_cast<RawObject**>(fp_);                                   \
-    pc = reinterpret_cast<uint32_t*>(pc_);                                     \
-    if ((reinterpret_cast<uword>(pc) & 2) != 0) { /* Entry frame? */           \
-      fp_ = reinterpret_cast<RawObject**>(fp_[0]);                             \
-      thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_));           \
-      thread->set_top_resource(top_resource);                                  \
-      thread->set_vm_tag(vm_tag);                                              \
-      return special_[kExceptionSpecialIndex];                                 \
-    }                                                                          \
-    pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_;                \
-    goto DispatchAfterException;                                               \
-  } while (0)
-
-#define HANDLE_RETURN                                                          \
-  do {                                                                         \
-    pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_;                \
-  } while (0)
-
-// Runtime call helpers: handle invocation and potential exception after return.
-#define INVOKE_RUNTIME(Func, Args)                                             \
-  if (!InvokeRuntime(thread, this, Func, Args)) {                              \
-    HANDLE_EXCEPTION;                                                          \
-  } else {                                                                     \
-    HANDLE_RETURN;                                                             \
-  }
-
-#define INVOKE_NATIVE(Wrapper, Func, Args)                                     \
-  if (!InvokeNative(thread, this, Wrapper, Func, Args)) {                      \
-    HANDLE_EXCEPTION;                                                          \
-  } else {                                                                     \
-    HANDLE_RETURN;                                                             \
-  }
-
-#define LOAD_CONSTANT(index) (pp_->ptr()->data()[(index)].raw_obj_)
-
-// Returns true if deoptimization succeeds.
-DART_FORCE_INLINE bool Simulator::Deoptimize(Thread* thread,
-                                             uint32_t** pc,
-                                             RawObject*** FP,
-                                             RawObject*** SP,
-                                             bool is_lazy) {
-  // Note: frame translation will take care of preserving result at the
-  // top of the stack. See CompilerDeoptInfo::CreateDeoptInfo.
-
-  // Make sure we preserve SP[0] when entering synthetic frame below.
-  (*SP)++;
-
-  // Leaf runtime function DeoptimizeCopyFrame expects a Dart frame.
-  // The code in this frame may not cause GC.
-  // DeoptimizeCopyFrame and DeoptimizeFillFrame are leaf runtime calls.
-  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
-  const intptr_t frame_size_in_bytes =
-      DLRT_DeoptimizeCopyFrame(reinterpret_cast<uword>(*FP), is_lazy ? 1 : 0);
-  LeaveSyntheticFrame(FP, SP);
-
-  *SP = *FP + (frame_size_in_bytes / kWordSize);
-  EnterSyntheticFrame(FP, SP, *pc - (is_lazy ? 1 : 0));
-  DLRT_DeoptimizeFillFrame(reinterpret_cast<uword>(*FP));
-
-  // We are now inside a valid frame.
-  {
-    *++(*SP) = 0;  // Space for the result: number of materialization args.
-    Exit(thread, *FP, *SP + 1, /*pc=*/0);
-    NativeArguments native_args(thread, 0, *SP, *SP);
-    if (!InvokeRuntime(thread, this, DRT_DeoptimizeMaterialize, native_args)) {
-      return false;
-    }
-  }
-  const intptr_t materialization_arg_count =
-      Smi::Value(RAW_CAST(Smi, *(*SP)--)) / kWordSize;
-
-  // Restore caller PC.
-  *pc = SavedCallerPC(*FP);
-  pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
-
-  // Check if it is a fake PC marking the entry frame.
-  ASSERT((reinterpret_cast<uword>(*pc) & 2) == 0);
-
-  // Restore SP, FP and PP.
-  // Unoptimized frame SP is one below FrameArguments(...) because
-  // FrameArguments(...) returns a pointer to the first argument.
-  *SP = FrameArguments(*FP, materialization_arg_count) - 1;
-  *FP = SavedCallerFP(*FP);
-
-  // Restore pp.
-  pp_ = SimulatorHelpers::FrameCode(*FP)->ptr()->object_pool_;
-
-  return true;
-}
-
-RawObject* Simulator::Call(const Code& code,
-                           const Array& arguments_descriptor,
-                           const Array& arguments,
-                           Thread* thread) {
-  // Interpreter state (see constants_dbc.h for high-level overview).
-  uint32_t* pc;    // Program Counter: points to the next op to execute.
-  RawObject** FP;  // Frame Pointer.
-  RawObject** SP;  // Stack Pointer.
-
-  uint32_t op;  // Currently executing op.
-  uint16_t rA;  // A component of the currently executing op.
-
-  if (fp_ == NULL) {
-    fp_ = reinterpret_cast<RawObject**>(stack_base_);
-  }
-
-  // Save current VM tag and mark thread as executing Dart code.
-  const uword vm_tag = thread->vm_tag();
-  thread->set_vm_tag(VMTag::kDartCompiledTagId);
-
-  // Save current top stack resource and reset the list.
-  StackResource* top_resource = thread->top_resource();
-  thread->set_top_resource(NULL);
-
-  // Setup entry frame:
-  //
-  //                        ^
-  //                        |  previous Dart frames
-  //       ~~~~~~~~~~~~~~~  |
-  //       | ........... | -+
-  // fp_ > |             |     saved top_exit_frame_info
-  //       | arg 0       | -+
-  //       ~~~~~~~~~~~~~~~  |
-  //                         > incoming arguments
-  //       ~~~~~~~~~~~~~~~  |
-  //       | arg 1       | -+
-  //       | function    | -+
-  //       | code        |  |
-  //       | caller PC   | ---> special fake PC marking an entry frame
-  //  SP > | fp_         |  |
-  //  FP > | ........... |   > normal Dart frame (see stack_frame_dbc.h)
-  //                        |
-  //                        v
-  //
-  FP = fp_ + 1 + arguments.Length() + kDartFrameFixedSize;
-  SP = FP - 1;
-
-  // Save outer top_exit_frame_info.
-  fp_[0] = reinterpret_cast<RawObject*>(thread->top_exit_frame_info());
-  thread->set_top_exit_frame_info(0);
-
-  // Copy arguments and setup the Dart frame.
-  const intptr_t argc = arguments.Length();
-  for (intptr_t i = 0; i < argc; i++) {
-    fp_[1 + i] = arguments.At(i);
-  }
-
-  FP[kFunctionSlotFromFp] = code.function();
-  FP[kPcMarkerSlotFromFp] = code.raw();
-  FP[kSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>((argc << 2) | 2);
-  FP[kSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(fp_);
-
-  // Load argument descriptor.
-  argdesc_ = arguments_descriptor.raw();
-
-  // Ready to start executing bytecode. Load entry point and corresponding
-  // object pool.
-  pc = reinterpret_cast<uint32_t*>(code.raw()->ptr()->entry_point_);
-  pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-  pp_ = code.object_pool();
-
-  // Cache some frequently used values in the frame.
-  RawBool* true_value = Bool::True().raw();
-  RawBool* false_value = Bool::False().raw();
-  RawObject* null_value = Object::null();
-
-#if defined(DEBUG)
-  Function& function_h = Function::Handle();
-#endif
-
-#ifdef DART_HAS_COMPUTED_GOTO
-  static const void* dispatch[] = {
-#define TARGET(name, fmt, fmta, fmtb, fmtc) &&bc##name,
-      BYTECODES_LIST(TARGET)
-#undef TARGET
-  };
-  DISPATCH();  // Enter the dispatch loop.
-#else
-  DISPATCH();  // Enter the dispatch loop.
-SwitchDispatch:
-  switch (op & 0xFF) {
-#define TARGET(name, fmt, fmta, fmtb, fmtc)                                    \
-  case SimulatorBytecode::k##name:                                             \
-    goto bc##name;
-    BYTECODES_LIST(TARGET)
-#undef TARGET
-    default:
-      FATAL1("Undefined opcode: %d\n", op);
-  }
-#endif
-
-  // Bytecode handlers (see constants_dbc.h for bytecode descriptions).
-  {
-    BYTECODE(Entry, A_D);
-    const uint16_t num_locals = rD;
-
-    // Initialize locals with null & set SP.
-    for (intptr_t i = 0; i < num_locals; i++) {
-      FP[i] = null_value;
-    }
-    SP = FP + num_locals - 1;
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(EntryOptimized, A_D);
-    const uint16_t num_registers = rD;
-
-    // Reserve space for registers used by the optimized code.
-    SP = FP + num_registers - 1;
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Frame, A_D);
-    // Initialize locals with null and increment SP.
-    const uint16_t num_locals = rD;
-    for (intptr_t i = 1; i <= num_locals; i++) {
-      SP[i] = null_value;
-    }
-    SP += num_locals;
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(SetFrame, A);
-    SP = FP + rA - 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Compile, 0);
-    FP[0] = argdesc_;
-    FP[1] = FrameFunction(FP);
-    FP[2] = 0;
-    Exit(thread, FP, FP + 3, pc);
-    NativeArguments args(thread, 1, FP + 1, FP + 2);
-    INVOKE_RUNTIME(DRT_CompileFunction, args);
-    {
-      // Function should be compiled now, dispatch to its entry point.
-      RawCode* code = FrameFunction(FP)->ptr()->code_;
-      SimulatorHelpers::SetFrameCode(FP, code);
-      pp_ = code->ptr()->object_pool_;
-      pc = reinterpret_cast<uint32_t*>(code->ptr()->entry_point_);
-      pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-      argdesc_ = static_cast<RawArray*>(FP[0]);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(HotCheck, A_D);
-    const uint8_t increment = rA;
-    const uint16_t threshold = rD;
-    RawFunction* f = FrameFunction(FP);
-    int32_t counter = f->ptr()->usage_counter_;
-    // Note: we don't increment usage counter in the prologue of optimized
-    // functions.
-    if (increment) {
-      counter += increment;
-      f->ptr()->usage_counter_ = counter;
-    }
-    if (UNLIKELY(counter >= threshold)) {
-      FP[0] = f;
-      FP[1] = 0;
-
-      // Save the args desriptor which came in.
-      FP[2] = argdesc_;
-
-      // Make the DRT_OptimizeInvokedFunction see a stub as its caller for
-      // consistency with the other architectures, and to avoid needing to
-      // generate a stackmap for the HotCheck pc.
-      const Code& stub = StubCode::OptimizeFunction();
-      FP[kPcMarkerSlotFromFp] = stub.raw();
-      pc = reinterpret_cast<uint32_t*>(stub.EntryPoint());
-
-      Exit(thread, FP, FP + 3, pc);
-      NativeArguments args(thread, 1, /*argv=*/FP, /*retval=*/FP + 1);
-      INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, args);
-      {
-        // DRT_OptimizeInvokedFunction returns the code object to execute.
-        ASSERT(FP[1]->GetClassId() == kFunctionCid);
-        RawFunction* function = static_cast<RawFunction*>(FP[1]);
-        RawCode* code = function->ptr()->code_;
-        SimulatorHelpers::SetFrameCode(FP, code);
-
-        // Restore args descriptor which came in.
-        argdesc_ = Array::RawCast(FP[2]);
-
-        pp_ = code->ptr()->object_pool_;
-        pc = reinterpret_cast<uint32_t*>(function->ptr()->entry_point_);
-        pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckStack, A);
-    {
-      if (reinterpret_cast<uword>(SP) >= thread->stack_limit()) {
-        Exit(thread, FP, SP + 1, pc);
-        NativeArguments args(thread, 0, NULL, NULL);
-        INVOKE_RUNTIME(DRT_StackOverflow, args);
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckStackAlwaysExit, A);
-    {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_StackOverflow, args);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckFunctionTypeArgs, A_D);
-    const uint16_t declared_type_args_len = rA;
-    const uint16_t first_stack_local_index = rD;
-
-    // Decode arguments descriptor's type args len.
-    const intptr_t type_args_len =
-        SimulatorHelpers::ArgDescTypeArgsLen(argdesc_);
-    if ((type_args_len != declared_type_args_len) && (type_args_len != 0)) {
-      goto ClosureNoSuchMethod;
-    }
-    if (type_args_len > 0) {
-      // Decode arguments descriptor's argument count (excluding type args).
-      const intptr_t arg_count = SimulatorHelpers::ArgDescArgCount(argdesc_);
-      // Copy passed-in type args to first local slot.
-      FP[first_stack_local_index] = *FrameArguments(FP, arg_count + 1);
-    } else if (declared_type_args_len > 0) {
-      FP[first_stack_local_index] = Object::null();
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DebugStep, A);
-#ifdef PRODUCT
-    FATAL("No debugging in PRODUCT mode");
-#else
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DebugBreak, A);
-#ifdef PRODUCT
-    FATAL("No debugging in PRODUCT mode");
-#else
-    {
-      const uint32_t original_bc =
-          static_cast<uint32_t>(reinterpret_cast<uintptr_t>(
-              thread->isolate()->debugger()->GetPatchedStubAddress(
-                  reinterpret_cast<uword>(pc))));
-
-      SP[1] = null_value;
-      Exit(thread, FP, SP + 2, pc);
-      NativeArguments args(thread, 0, NULL, SP + 1);
-      INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args)
-      DISPATCH_OP(original_bc);
-    }
-#endif
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstantiateType, A_D);
-    // Stack: instantiator type args, function type args
-    RawObject* type = LOAD_CONSTANT(rD);
-    SP[1] = type;
-    SP[2] = SP[-1];
-    SP[3] = SP[0];
-    Exit(thread, FP, SP + 4, pc);
-    {
-      NativeArguments args(thread, 3, SP + 1, SP - 1);
-      INVOKE_RUNTIME(DRT_InstantiateType, args);
-    }
-    SP -= 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstantiateTypeArgumentsTOS, A_D);
-    // Stack: instantiator type args, function type args
-    RawTypeArguments* type_arguments =
-        static_cast<RawTypeArguments*>(LOAD_CONSTANT(rD));
-
-    RawObject* instantiator_type_args = SP[-1];
-    RawObject* function_type_args = SP[0];
-    // If both instantiators are null and if the type argument vector
-    // instantiated from null becomes a vector of dynamic, then use null as
-    // the type arguments.
-    if ((rA == 0) || (null_value != instantiator_type_args) ||
-        (null_value != function_type_args)) {
-      // First lookup in the cache.
-      RawArray* instantiations = type_arguments->ptr()->instantiations_;
-      for (intptr_t i = 0;
-           instantiations->ptr()->data()[i] != NULL;  // kNoInstantiator
-           i += 3) {  // kInstantiationSizeInWords
-        if ((instantiations->ptr()->data()[i] == instantiator_type_args) &&
-            (instantiations->ptr()->data()[i + 1] == function_type_args)) {
-          // Found in the cache.
-          SP[-1] = instantiations->ptr()->data()[i + 2];
-          goto InstantiateTypeArgumentsTOSDone;
-        }
-      }
-
-      // Cache lookup failed, call runtime.
-      SP[1] = type_arguments;
-      SP[2] = instantiator_type_args;
-      SP[3] = function_type_args;
-
-      Exit(thread, FP, SP + 4, pc);
-      NativeArguments args(thread, 3, SP + 1, SP - 1);
-      INVOKE_RUNTIME(DRT_InstantiateTypeArguments, args);
-    }
-
-  InstantiateTypeArgumentsTOSDone:
-    SP -= 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Throw, A);
-    {
-      SP[1] = 0;  // Space for result.
-      Exit(thread, FP, SP + 2, pc);
-      if (rA == 0) {  // Throw
-        NativeArguments args(thread, 1, SP, SP + 1);
-        INVOKE_RUNTIME(DRT_Throw, args);
-      } else {  // ReThrow
-        NativeArguments args(thread, 2, SP - 1, SP + 1);
-        INVOKE_RUNTIME(DRT_ReThrow, args);
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Drop1, 0);
-    SP--;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Drop, 0);
-    SP -= rA;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DropR, 0);
-    RawObject* result = SP[0];
-    SP -= rA;
-    SP[0] = result;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadConstant, A_D);
-    FP[rA] = LOAD_CONSTANT(rD);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(PushConstant, __D);
-    *++SP = LOAD_CONSTANT(rD);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Push, A_X);
-    *++SP = FP[rD];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Move, A_X);
-    FP[rA] = FP[rD];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Swap, A_X);
-    RawObject* tmp = FP[rD];
-    FP[rD] = FP[rA];
-    FP[rA] = tmp;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreLocal, A_X);
-    FP[rD] = *SP;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(PopLocal, A_X);
-    FP[rD] = *SP--;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(MoveSpecial, A_D);
-    FP[rA] = special_[rD];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BooleanNegateTOS, 0);
-    SP[0] = (SP[0] == true_value) ? false_value : true_value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BooleanNegate, A_D);
-    FP[rA] = (FP[rD] == true_value) ? false_value : true_value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IndirectStaticCall, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    // Invoke target function.
-    {
-      const uint16_t argc = rA;
-      // Look up the function in the ICData.
-      RawObject* ic_data_obj = SP[0];
-      RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
-      RawObject** data = ic_data->ptr()->entries_->ptr()->data();
-      SimulatorHelpers::IncrementICUsageCount(data, 0, 0);
-      SP[0] = data[ICData::TargetIndexFor(ic_data->ptr()->state_bits_ & 0x3)];
-      RawObject** call_base = SP - argc;
-      RawObject** call_top = SP;  // *SP contains function
-      argdesc_ = static_cast<RawArray*>(LOAD_CONSTANT(rD));
-      Invoke(thread, call_base, call_top, &pc, &FP, &SP);
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StaticCall, A_D);
-    const uint16_t argc = rA;
-    RawObject** call_base = SP - argc;
-    RawObject** call_top = SP;  // *SP contains function
-    argdesc_ = static_cast<RawArray*>(LOAD_CONSTANT(rD));
-    Invoke(thread, call_base, call_top, &pc, &FP, &SP);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstanceCall1, A_D);
-
-#ifndef PRODUCT
-    // Check if single stepping.
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
-
-      RawObject** call_base = SP - argc + 1;
-      RawObject** call_top = SP + 1;
-
-      RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
-      SimulatorHelpers::IncrementUsageCounter(
-          RAW_CAST(Function, icdata->ptr()->owner_));
-      InstanceCall1(thread, icdata, call_base, call_top, &pc, &FP, &SP,
-                    false /* optimized */);
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstanceCall2, A_D);
-
-#ifndef PRODUCT
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
-
-      RawObject** call_base = SP - argc + 1;
-      RawObject** call_top = SP + 1;
-
-      RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
-      SimulatorHelpers::IncrementUsageCounter(
-          RAW_CAST(Function, icdata->ptr()->owner_));
-      InstanceCall2(thread, icdata, call_base, call_top, &pc, &FP, &SP,
-                    false /* optimized */);
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstanceCall1Opt, A_D);
-
-    {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
-
-      RawObject** call_base = SP - argc + 1;
-      RawObject** call_top = SP + 1;
-
-      RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
-      SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP));
-      InstanceCall1(thread, icdata, call_base, call_top, &pc, &FP, &SP,
-                    true /* optimized */);
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstanceCall2Opt, A_D);
-
-    {
-      const uint16_t argc = rA;
-      const uint16_t kidx = rD;
-
-      RawObject** call_base = SP - argc + 1;
-      RawObject** call_top = SP + 1;
-
-      RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));
-      SimulatorHelpers::IncrementUsageCounter(FrameFunction(FP));
-      InstanceCall2(thread, icdata, call_base, call_top, &pc, &FP, &SP,
-                    true /* optimized */);
-    }
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(PushPolymorphicInstanceCall, A_D);
-    const uint8_t argc = rA;
-    const intptr_t cids_length = rD;
-    RawObject** args = SP - argc + 1;
-    const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]);
-    for (intptr_t i = 0; i < 2 * cids_length; i += 2) {
-      const intptr_t icdata_cid = SimulatorBytecode::DecodeD(*(pc + i));
-      if (receiver_cid == icdata_cid) {
-        RawFunction* target = RAW_CAST(
-            Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 1))));
-        *++SP = target;
-        pc++;
-        break;
-      }
-    }
-    pc += 2 * cids_length;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(PushPolymorphicInstanceCallByRange, A_D);
-    const uint8_t argc = rA;
-    const intptr_t cids_length = rD;
-    RawObject** args = SP - argc + 1;
-    const intptr_t receiver_cid = SimulatorHelpers::GetClassId(args[0]);
-    for (intptr_t i = 0; i < 3 * cids_length; i += 3) {
-      // Note unsigned types to get an unsigned range compare.
-      const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i));
-      const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1));
-      if (receiver_cid - cid_start < cids) {
-        RawFunction* target = RAW_CAST(
-            Function, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + i + 2))));
-        *++SP = target;
-        pc++;
-        break;
-      }
-    }
-    pc += 3 * cids_length;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(NativeCall, A_B_C);
-    NativeFunctionWrapper trampoline =
-        reinterpret_cast<NativeFunctionWrapper>(LOAD_CONSTANT(rA));
-    Dart_NativeFunction function =
-        reinterpret_cast<Dart_NativeFunction>(LOAD_CONSTANT(rB));
-    intptr_t argc_tag = reinterpret_cast<intptr_t>(LOAD_CONSTANT(rC));
-    const intptr_t num_arguments = NativeArguments::ArgcBits::decode(argc_tag);
-
-    *++SP = null_value;  // Result slot.
-
-    RawObject** incoming_args = SP - num_arguments;
-    RawObject** return_slot = SP;
-    Exit(thread, FP, SP, pc);
-    NativeArguments args(thread, argc_tag, incoming_args, return_slot);
-    INVOKE_NATIVE(trampoline, function,
-                  reinterpret_cast<Dart_NativeArguments>(&args));
-
-    *(SP - num_arguments) = *return_slot;
-    SP -= num_arguments;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(FfiCall, __D);
-    {
-      const auto& sig_desc = compiler::ffi::FfiSignatureDescriptor(
-          TypedData::Cast(Object::Handle(LOAD_CONSTANT(rD))));
-
-      // The arguments to this ffi call are on the stack at FP.
-      // kFirstLocalSlotFromFp is 0 in DBC, but the const is -1.
-      uint64_t* arg_values = reinterpret_cast<uint64_t*>(FP);
-
-      uint64_t* marshalled_args_data =
-          FfiMarshalledArguments::New(sig_desc, arg_values);
-      const auto& marshalled_args =
-          FfiMarshalledArguments(marshalled_args_data);
-
-      Exit(thread, FP, SP, pc);
-      {
-        thread->set_execution_state(Thread::kThreadInNative);
-        thread->EnterSafepoint();
-
-        FfiTrampolineCall(marshalled_args_data);
-
-        // We set the execution state to kThreadInVM before waiting for the
-        // safepoint to end for the benefit of tests like ffi/function_gc_test.
-        thread->set_execution_state(Thread::kThreadInVM);
-        thread->ExitSafepoint();
-        thread->set_execution_state(Thread::kThreadInGenerated);
-      }
-
-      const Representation result_rep = sig_desc.ResultRepresentation();
-      intptr_t result;
-      if (result_rep == kUnboxedDouble || result_rep == kUnboxedFloat) {
-        result = marshalled_args.DoubleResult();
-      } else {
-        result = marshalled_args.IntResult();
-      }
-      FP[0] = reinterpret_cast<RawObject*>(result);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(OneByteStringFromCharCode, A_X);
-    const intptr_t char_code = Smi::Value(RAW_CAST(Smi, FP[rD]));
-    ASSERT(char_code >= 0);
-    ASSERT(char_code <= 255);
-    RawString** strings = Symbols::PredefinedAddress();
-    const intptr_t index = char_code + Symbols::kNullCharCodeSymbolOffset;
-    FP[rA] = strings[index];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StringToCharCode, A_X);
-    RawOneByteString* str = RAW_CAST(OneByteString, FP[rD]);
-    if (str->ptr()->length_ == Smi::New(1)) {
-      FP[rA] = Smi::New(str->ptr()->data()[0]);
-    } else {
-      FP[rA] = Smi::New(-1);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AddTOS, A_B_C);
-    SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow);
-    DISPATCH();
-  }
-  {
-    BYTECODE(SubTOS, A_B_C);
-    SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow);
-    DISPATCH();
-  }
-  {
-    BYTECODE(MulTOS, A_B_C);
-    SMI_FASTPATH_TOS(intptr_t, SMI_MUL);
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitOrTOS, A_B_C);
-    SMI_FASTPATH_TOS(intptr_t, SMI_BITOR);
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitAndTOS, A_B_C);
-    SMI_FASTPATH_TOS(intptr_t, SMI_BITAND);
-    DISPATCH();
-  }
-  {
-    BYTECODE(EqualTOS, A_B_C);
-    SMI_FASTPATH_TOS(RawObject*, SMI_EQ);
-    DISPATCH();
-  }
-  {
-    BYTECODE(LessThanTOS, A_B_C);
-    SMI_FASTPATH_TOS(RawObject*, SMI_LT);
-    DISPATCH();
-  }
-  {
-    BYTECODE(GreaterThanTOS, A_B_C);
-    SMI_FASTPATH_TOS(RawObject*, SMI_GT);
-    DISPATCH();
-  }
-  {
-    BYTECODE(SmiAddTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    SP--;
-    SP[0] = Smi::New(Smi::Value(left) + Smi::Value(right));
-    DISPATCH();
-  }
-  {
-    BYTECODE(SmiSubTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    SP--;
-    SP[0] = Smi::New(Smi::Value(left) - Smi::Value(right));
-    DISPATCH();
-  }
-  {
-    BYTECODE(SmiMulTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    SP--;
-    SP[0] = Smi::New(Smi::Value(left) * Smi::Value(right));
-    DISPATCH();
-  }
-  {
-    BYTECODE(SmiBitAndTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    SP--;
-    SP[0] = Smi::New(Smi::Value(left) & Smi::Value(right));
-    DISPATCH();
-  }
-  {
-    BYTECODE(Add, A_B_C);
-    SMI_OP_CHECK(intptr_t, SignedAddWithOverflow);
-    DISPATCH();
-  }
-  {
-    BYTECODE(Sub, A_B_C);
-    SMI_OP_CHECK(intptr_t, SignedSubWithOverflow);
-    DISPATCH();
-  }
-  {
-    BYTECODE(Mul, A_B_C);
-    SMI_OP_CHECK(intptr_t, SMI_MUL);
-    DISPATCH();
-  }
-  {
-    BYTECODE(Neg, A_D);
-    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
-    intptr_t* out = reinterpret_cast<intptr_t*>(&FP[rA]);
-    if (LIKELY(!SignedSubWithOverflow(0, value, out))) {
-      pc++;
-    }
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitOr, A_B_C);
-    SMI_OP_NOCHECK(intptr_t, SMI_BITOR);
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitAnd, A_B_C);
-    SMI_OP_NOCHECK(intptr_t, SMI_BITAND);
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitXor, A_B_C);
-    SMI_OP_NOCHECK(intptr_t, SMI_BITXOR);
-    DISPATCH();
-  }
-  {
-    BYTECODE(BitNot, A_D);
-    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
-    *reinterpret_cast<intptr_t*>(&FP[rA]) = ~value & (~kSmiTagMask);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Div, A_B_C);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
-    if (rhs != 0) {
-      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-      const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
-#if defined(ARCH_IS_64_BIT)
-      const intptr_t untaggable = 0x4000000000000000LL;
-#else
-      const intptr_t untaggable = 0x40000000L;
-#endif  // defined(ARCH_IS_64_BIT)
-      if (res != untaggable) {
-        *reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
-        pc++;
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Mod, A_B_C);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
-    if (rhs != 0) {
-      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-      const intptr_t res = ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize))
-                           << kSmiTagSize;
-      *reinterpret_cast<intptr_t*>(&FP[rA]) =
-          (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res;
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Shl, A_B_C);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
-    if (static_cast<uintptr_t>(rhs) < kBitsPerWord) {
-      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-      const intptr_t res = lhs << rhs;
-      if (lhs == (res >> rhs)) {
-        *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
-        pc++;
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Shr, A_B_C);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
-    if (rhs >= 0) {
-      const intptr_t shift_amount =
-          (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
-      const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
-      *reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift_amount)
-                                              << kSmiTagSize;
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(ShlImm, A_B_C);
-    const uint8_t shift = rC;
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-    FP[rA] = reinterpret_cast<RawObject*>(lhs << shift);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Min, A_B_C);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
-    FP[rA] = reinterpret_cast<RawObject*>((lhs < rhs) ? lhs : rhs);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Max, A_B_C);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]);
-    FP[rA] = reinterpret_cast<RawObject*>((lhs > rhs) ? lhs : rhs);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxInt32, A_B_C);
-    const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rB]);
-    const bool may_truncate = rC == 1;
-    if (box_cid == kSmiCid) {
-      const intptr_t value = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
-      const int32_t value32 = static_cast<int32_t>(value);
-      if (may_truncate || (value == static_cast<intptr_t>(value32))) {
-        FP[rA] = reinterpret_cast<RawObject*>(value);
-        pc++;
-      }
-    } else if (box_cid == kMintCid) {
-      RawMint* mint = RAW_CAST(Mint, FP[rB]);
-      const int64_t value = mint->ptr()->value_;
-      const int32_t value32 = static_cast<int32_t>(value);
-      if (may_truncate || (value == static_cast<int64_t>(value32))) {
-        FP[rA] = reinterpret_cast<RawObject*>(value);
-        pc++;
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxedWidthExtender, A_B_C);
-    auto rep = static_cast<SmallRepresentation>(rC);
-    const intptr_t value_32_or_64_bit = reinterpret_cast<intptr_t>(FP[rB]);
-    int32_t value = value_32_or_64_bit & kMaxUint32;  // Prevent overflow.
-    switch (rep) {
-      case kSmallUnboxedInt8:
-        // Sign extend the top 24 bits from the sign bit.
-        value <<= 24;
-        value >>= 24;
-        break;
-      case kSmallUnboxedUint8:
-        value &= 0x000000FF;  // Throw away upper bits.
-        break;
-      case kSmallUnboxedInt16:
-        // Sign extend the top 16 bits from the sign bit.
-        value <<= 16;
-        value >>= 16;
-        break;
-      case kSmallUnboxedUint16:
-        value &= 0x0000FFFF;  // Throw away upper bits.
-        break;
-      default:
-        UNREACHABLE();
-    }
-    FP[rA] = reinterpret_cast<RawObject*>(value);
-    DISPATCH();
-  }
-
-#if defined(ARCH_IS_64_BIT)
-  {
-    BYTECODE(WriteIntoDouble, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    RawDouble* box = RAW_CAST(Double, FP[rA]);
-    box->ptr()->value_ = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxDouble, A_D);
-    const RawDouble* box = RAW_CAST(Double, FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(box->ptr()->value_);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckedUnboxDouble, A_D);
-    const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]);
-    if (box_cid == kSmiCid) {
-      const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]) >> kSmiTagSize;
-      const double result = static_cast<double>(value);
-      FP[rA] = bit_cast<RawObject*, double>(result);
-      pc++;
-    } else if (box_cid == kDoubleCid) {
-      const RawDouble* box = RAW_CAST(Double, FP[rD]);
-      FP[rA] = bit_cast<RawObject*, double>(box->ptr()->value_);
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleToSmi, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    if (!isnan(value)) {
-      const intptr_t result = static_cast<intptr_t>(value);
-      if ((result <= Smi::kMaxValue) && (result >= Smi::kMinValue)) {
-        FP[rA] = reinterpret_cast<RawObject*>(result << kSmiTagSize);
-        pc++;
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(SmiToDouble, A_D);
-    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]) >> kSmiTagSize;
-    const double result = static_cast<double>(value);
-    FP[rA] = bit_cast<RawObject*, double>(result);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DAdd, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    FP[rA] = bit_cast<RawObject*, double>(lhs + rhs);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSub, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    FP[rA] = bit_cast<RawObject*, double>(lhs - rhs);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMul, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    FP[rA] = bit_cast<RawObject*, double>(lhs * rhs);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DDiv, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    const double result = lhs / rhs;
-    FP[rA] = bit_cast<RawObject*, double>(result);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DNeg, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(-value);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSqrt, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(sqrt(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSin, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(sin(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DCos, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(cos(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DPow, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    const double result = pow(lhs, rhs);
-    FP[rA] = bit_cast<RawObject*, double>(result);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMod, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    const double result = DartModulo(lhs, rhs);
-    FP[rA] = bit_cast<RawObject*, double>(result);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMin, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    FP[rA] = bit_cast<RawObject*, double>(fmin(lhs, rhs));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMax, A_B_C);
-    const double lhs = bit_cast<double, RawObject*>(FP[rB]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rC]);
-    FP[rA] = bit_cast<RawObject*, double>(fmax(lhs, rhs));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DTruncate, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(trunc(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DFloor, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(floor(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DCeil, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    FP[rA] = bit_cast<RawObject*, double>(ceil(value));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleToFloat, A_D);
-    const double value = bit_cast<double, RawObject*>(FP[rD]);
-    const float valuef = static_cast<float>(value);
-    *reinterpret_cast<float*>(&FP[rA]) = valuef;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(FloatToDouble, A_D);
-    const float valuef = *reinterpret_cast<float*>(&FP[rD]);
-    const double value = static_cast<double>(valuef);
-    FP[rA] = bit_cast<RawObject*, double>(value);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleIsNaN, A);
-    const double v = bit_cast<double, RawObject*>(FP[rA]);
-    if (!isnan(v)) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleIsInfinite, A);
-    const double v = bit_cast<double, RawObject*>(FP[rA]);
-    if (!isinf(v)) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedFloat32, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    const uint32_t value = *reinterpret_cast<uint32_t*>(data);
-    const uint64_t value64 = value;
-    FP[rA] = reinterpret_cast<RawObject*>(value64);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexed4Float32, A_B_C);
-    ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId()));
-    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    const uint32_t value =
-        reinterpret_cast<uint32_t*>(array->ptr()->data())[Smi::Value(index)];
-    const uint64_t value64 = value;  // sign extend to clear high bits.
-    FP[rA] = reinterpret_cast<RawObject*>(value64);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedFloat64, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    *reinterpret_cast<uint64_t*>(&FP[rA]) = *reinterpret_cast<uint64_t*>(data);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexed8Float64, A_B_C);
-    ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId()));
-    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    const int64_t value =
-        reinterpret_cast<int64_t*>(array->ptr()->data())[Smi::Value(index)];
-    FP[rA] = reinterpret_cast<RawObject*>(value);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedFloat32, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    const float value = *reinterpret_cast<float*>(&FP[rC]);
-    *reinterpret_cast<float*>(data) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexed4Float32, A_B_C);
-    ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId()));
-    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    const float value = *reinterpret_cast<float*>(&FP[rC]);
-    reinterpret_cast<float*>(array->ptr()->data())[Smi::Value(index)] = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedFloat64, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    *reinterpret_cast<uint64_t*>(data) = reinterpret_cast<uint64_t>(FP[rC]);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexed8Float64, A_B_C);
-    ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId()));
-    RawTypedData* array = reinterpret_cast<RawTypedData*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    const int64_t value = reinterpret_cast<int64_t>(FP[rC]);
-    reinterpret_cast<int64_t*>(array->ptr()->data())[Smi::Value(index)] = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxInt32, A_D);
-    // Casts sign-extend high 32 bits from low 32 bits.
-    const intptr_t value = reinterpret_cast<intptr_t>(FP[rD]);
-    const int32_t value32 = static_cast<int32_t>(value);
-    FP[rA] = Smi::New(static_cast<intptr_t>(value32));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxUint32, A_D);
-    // Casts to zero out high 32 bits.
-    const uintptr_t value = reinterpret_cast<uintptr_t>(FP[rD]);
-    const uint32_t value32 = static_cast<uint32_t>(value);
-    FP[rA] = Smi::New(static_cast<intptr_t>(value32));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxInt64, A_D);
-    const intptr_t box_cid = SimulatorHelpers::GetClassId(FP[rD]);
-    if (box_cid == kSmiCid) {
-      const int64_t value = Smi::Value(RAW_CAST(Smi, FP[rD]));
-      FP[rA] = reinterpret_cast<RawObject*>(value);
-    } else if (box_cid == kMintCid) {
-      RawMint* mint = RAW_CAST(Mint, FP[rD]);
-      const int64_t value = mint->ptr()->value_;
-      FP[rA] = reinterpret_cast<RawObject*>(value);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxInt64, A_D);
-    const int64_t value = reinterpret_cast<int64_t>(FP[rD]);
-    if (Smi::IsValid(value)) {
-      FP[rA] = Smi::New(static_cast<intptr_t>(value));
-    } else {
-      // If the value does not fit into a Smi the following instruction is
-      // skipped. (The following instruction should be a jump to a label after
-      // the slow path allocating a Mint box and writing into the Mint box.)
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(WriteIntoMint, A_D);
-    const int64_t value = bit_cast<int64_t, RawObject*>(FP[rD]);
-    RawMint* box = RAW_CAST(Mint, FP[rA]);
-    box->ptr()->value_ = value;
-    DISPATCH();
-  }
-
-#else   // defined(ARCH_IS_64_BIT)
-  {
-    BYTECODE(WriteIntoDouble, A_D);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxDouble, A_D);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckedUnboxDouble, A_D);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleToSmi, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(SmiToDouble, A_D);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DAdd, A_B_C);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSub, A_B_C);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMul, A_B_C);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DDiv, A_B_C);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DNeg, A_D);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSqrt, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DSin, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DCos, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DPow, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMod, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMin, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DMax, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DTruncate, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DFloor, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DCeil, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleToFloat, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(FloatToDouble, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleIsNaN, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DoubleIsInfinite, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedFloat32, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexed4Float32, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedFloat64, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexed8Float64, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedFloat32, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexed4Float32, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedFloat64, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexed8Float64, A_B_C);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxInt32, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxUint32, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(UnboxInt64, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(BoxInt64, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(WriteIntoMint, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-#endif  // defined(ARCH_IS_64_BIT)
-
-  // Return and return like instructions (Instrinsic).
-  {
-    RawObject* result;  // result to return to the caller.
-
-    BYTECODE(Intrinsic, A);
-    // Try invoking intrinsic handler. If it succeeds (returns true)
-    // then just return the value it returned to the caller.
-    result = null_value;
-    if (!intrinsics_[rA](thread, FP, &result)) {
-      DISPATCH();
-    }
-    goto ReturnImpl;
-
-    BYTECODE(Return, A);
-    result = FP[rA];
-    goto ReturnImpl;
-
-    BYTECODE(ReturnTOS, 0);
-    result = *SP;
-    // Fall through to the ReturnImpl.
-
-  ReturnImpl:
-    // Restore caller PC.
-    pc = SavedCallerPC(FP);
-    pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
-
-    // Check if it is a fake PC marking the entry frame.
-    if ((reinterpret_cast<uword>(pc) & 2) != 0) {
-      const intptr_t argc = reinterpret_cast<uword>(pc) >> 2;
-      fp_ = reinterpret_cast<RawObject**>(FrameArguments(FP, argc + 1)[0]);
-      thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_));
-      thread->set_top_resource(top_resource);
-      thread->set_vm_tag(vm_tag);
-      return result;
-    }
-
-    // Look at the caller to determine how many arguments to pop.
-    const uint8_t argc = SimulatorBytecode::DecodeArgc(pc[-1]);
-
-    // Restore SP, FP and PP. Push result and dispatch.
-    SP = FrameArguments(FP, argc);
-    FP = SavedCallerFP(FP);
-    pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_;
-    *SP = result;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreStaticTOS, A_D);
-    RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
-    RawInstance* value = static_cast<RawInstance*>(*SP--);
-    field->StorePointer(&field->ptr()->value_.static_value_, value, thread);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(PushStatic, A_D);
-    RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
-    // Note: field is also on the stack, hence no increment.
-    *SP = field->ptr()->value_.static_value_;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreField, A_B_C);
-    const uint16_t offset_in_words = rB;
-    const uint16_t value_reg = rC;
-
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[rA]);
-    RawObject* value = FP[value_reg];
-
-    instance->StorePointer(
-        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
-        thread);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreFieldExt, A_D);
-    // The offset is stored in the following nop-instruction which is skipped.
-    const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++);
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[rA]);
-    RawObject* value = FP[rD];
-
-    instance->StorePointer(
-        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
-        thread);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreUntagged, A_B_C);
-    const uint16_t offset_in_words = rB;
-    const uint16_t value_reg = rC;
-
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[rA]);
-    word value = reinterpret_cast<word>(FP[value_reg]);
-    reinterpret_cast<word*>(instance->ptr())[offset_in_words] = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreFieldTOS, __D);
-    const uint16_t offset_in_words = rD;
-    RawInstance* instance = reinterpret_cast<RawInstance*>(SP[-1]);
-    RawObject* value = reinterpret_cast<RawObject*>(SP[0]);
-    SP -= 2;  // Drop instance and value.
-    instance->StorePointer(
-        reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words, value,
-        thread);
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadField, A_B_C);
-    const uint16_t instance_reg = rB;
-    const uint16_t offset_in_words = rC;
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[instance_reg]);
-    FP[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadFieldExt, A_D);
-    // The offset is stored in the following nop-instruction which is skipped.
-    const uint16_t offset_in_words = SimulatorBytecode::DecodeD(*pc++);
-    const uint16_t instance_reg = rD;
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[instance_reg]);
-    FP[rA] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadUntagged, A_B_C);
-    const uint16_t instance_reg = rB;
-    const uint16_t offset_in_words = rC;
-    RawInstance* instance = reinterpret_cast<RawInstance*>(FP[instance_reg]);
-    FP[rA] = reinterpret_cast<RawObject**>(instance)[offset_in_words];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadFieldTOS, __D);
-    const uint16_t offset_in_words = rD;
-    RawInstance* instance = static_cast<RawInstance*>(SP[0]);
-    SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InitStaticTOS, 0);
-    RawField* field = static_cast<RawField*>(*SP--);
-    RawObject* value = field->ptr()->value_.static_value_;
-    if ((value == Object::sentinel().raw()) ||
-        (value == Object::transition_sentinel().raw())) {
-      // Note: SP[1] already contains the field object.
-      SP[2] = 0;
-      Exit(thread, FP, SP + 3, pc);
-      NativeArguments args(thread, 1, SP + 1, SP + 2);
-      INVOKE_RUNTIME(DRT_InitStaticField, args);
-    }
-    DISPATCH();
-  }
-
-  // TODO(vegorov) allocation bytecodes can benefit from the new-space
-  // allocation fast-path that does not transition into the runtime system.
-  {
-    BYTECODE(AllocateUninitializedContext, A_D);
-    const uint16_t num_context_variables = rD;
-    const intptr_t instance_size = Context::InstanceSize(num_context_variables);
-    const uword start =
-        thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
-    if (LIKELY(start != 0)) {
-      uint32_t tags = 0;
-      tags = RawObject::ClassIdTag::update(kContextCid, tags);
-      tags = RawObject::SizeTag::update(instance_size, tags);
-      tags = RawObject::NewBit::update(true, tags);
-      // Also writes 0 in the hash_ field of the header.
-      *reinterpret_cast<uword*>(start + Array::tags_offset()) = tags;
-      *reinterpret_cast<uword*>(start + Context::num_variables_offset()) =
-          num_context_variables;
-      FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
-      pc += 2;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AllocateContext, A_D);
-    const uint16_t num_context_variables = rD;
-    {
-      *++SP = 0;
-      SP[1] = Smi::New(num_context_variables);
-      Exit(thread, FP, SP + 2, pc);
-      NativeArguments args(thread, 1, SP + 1, SP);
-      INVOKE_RUNTIME(DRT_AllocateContext, args);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CloneContext, A);
-    {
-      SP[1] = SP[0];  // Context to clone.
-      Exit(thread, FP, SP + 2, pc);
-      NativeArguments args(thread, 1, SP + 1, SP);
-      INVOKE_RUNTIME(DRT_CloneContext, args);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AllocateOpt, A_D);
-    uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD)));
-    const intptr_t instance_size = RawObject::SizeTag::decode(tags);
-    const uword start =
-        thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
-    if (LIKELY(start != 0)) {
-      // Writes both the tags and the initial identity hash on 64 bit platforms.
-      tags = RawObject::NewBit::update(true, tags);
-      *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
-      for (intptr_t current_offset = sizeof(RawInstance);
-           current_offset < instance_size; current_offset += kWordSize) {
-        *reinterpret_cast<RawObject**>(start + current_offset) = null_value;
-      }
-      FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
-      pc += 2;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Allocate, A_D);
-    SP[1] = 0;                  // Space for the result.
-    SP[2] = LOAD_CONSTANT(rD);  // Class object.
-    SP[3] = null_value;         // Type arguments.
-    Exit(thread, FP, SP + 4, pc);
-    NativeArguments args(thread, 2, SP + 2, SP + 1);
-    INVOKE_RUNTIME(DRT_AllocateObject, args);
-    SP++;  // Result is in SP[1].
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AllocateTOpt, A_D);
-    uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD)));
-    const intptr_t instance_size = RawObject::SizeTag::decode(tags);
-    const uword start =
-        thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size);
-    if (LIKELY(start != 0)) {
-      RawObject* type_args = SP[0];
-      const intptr_t type_args_offset = SimulatorBytecode::DecodeD(*pc);
-      // Writes both the tags and the initial identity hash on 64 bit platforms.
-      tags = RawObject::NewBit::update(true, tags);
-      *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
-      for (intptr_t current_offset = sizeof(RawInstance);
-           current_offset < instance_size; current_offset += kWordSize) {
-        *reinterpret_cast<RawObject**>(start + current_offset) = null_value;
-      }
-      *reinterpret_cast<RawObject**>(start + type_args_offset) = type_args;
-      FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
-      SP -= 1;  // Consume the type arguments on the stack.
-      pc += 4;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AllocateT, 0);
-    SP[1] = SP[-0];  // Class object.
-    SP[2] = SP[-1];  // Type arguments
-    Exit(thread, FP, SP + 3, pc);
-    NativeArguments args(thread, 2, SP + 1, SP - 1);
-    INVOKE_RUNTIME(DRT_AllocateObject, args);
-    SP -= 1;  // Result is in SP - 1.
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CreateArrayOpt, A_B_C);
-    if (LIKELY(!FP[rB]->IsHeapObject())) {
-      const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB]));
-      if (LIKELY(static_cast<uintptr_t>(length) <= Array::kMaxElements)) {
-        const intptr_t fixed_size_plus_alignment_padding =
-            sizeof(RawArray) + kObjectAlignment - 1;
-        const intptr_t instance_size =
-            (fixed_size_plus_alignment_padding + length * kWordSize) &
-            ~(kObjectAlignment - 1);
-        const uword start = thread->heap()->new_space()->TryAllocateInTLAB(
-            thread, instance_size);
-        if (LIKELY(start != 0)) {
-          const intptr_t cid = kArrayCid;
-          uword tags = 0;
-          if (LIKELY(instance_size <= RawObject::SizeTag::kMaxSizeTag)) {
-            tags = RawObject::SizeTag::update(instance_size, tags);
-          }
-          tags = RawObject::ClassIdTag::update(cid, tags);
-          tags = RawObject::NewBit::update(true, tags);
-          // Writes both the tags and the initial identity hash on 64 bit
-          // platforms.
-          *reinterpret_cast<uword*>(start + Instance::tags_offset()) = tags;
-          *reinterpret_cast<RawObject**>(start + Array::length_offset()) =
-              FP[rB];
-          *reinterpret_cast<RawObject**>(
-              start + Array::type_arguments_offset()) = FP[rC];
-          RawObject** data =
-              reinterpret_cast<RawObject**>(start + Array::data_offset());
-          for (intptr_t i = 0; i < length; i++) {
-            data[i] = null_value;
-          }
-          FP[rA] = reinterpret_cast<RawObject*>(start + kHeapObjectTag);
-          pc += 4;
-        }
-      }
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CreateArrayTOS, 0);
-    SP[1] = SP[-0];  // Length.
-    SP[2] = SP[-1];  // Type.
-    Exit(thread, FP, SP + 3, pc);
-    NativeArguments args(thread, 2, SP + 1, SP - 1);
-    INVOKE_RUNTIME(DRT_AllocateArray, args);
-    SP -= 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(InstanceOf, 0);
-    // Stack: instance, instantiator type args, function type args, type, cache
-    RawInstance* instance = static_cast<RawInstance*>(SP[-4]);
-    RawTypeArguments* instantiator_type_arguments =
-        static_cast<RawTypeArguments*>(SP[-3]);
-    RawTypeArguments* function_type_arguments =
-        static_cast<RawTypeArguments*>(SP[-2]);
-    RawAbstractType* type = static_cast<RawAbstractType*>(SP[-1]);
-    RawSubtypeTestCache* cache = static_cast<RawSubtypeTestCache*>(SP[0]);
-
-    if (cache != null_value) {
-      const intptr_t cid = SimulatorHelpers::GetClassId(instance);
-
-      RawTypeArguments* instance_type_arguments =
-          static_cast<RawTypeArguments*>(null_value);
-      RawObject* instance_cid_or_function;
-      RawTypeArguments* parent_function_type_arguments;
-      RawTypeArguments* delayed_function_type_arguments;
-      if (cid == kClosureCid) {
-        RawClosure* closure = static_cast<RawClosure*>(instance);
-        instance_type_arguments = closure->ptr()->instantiator_type_arguments_;
-        parent_function_type_arguments =
-            closure->ptr()->function_type_arguments_;
-        delayed_function_type_arguments =
-            closure->ptr()->delayed_type_arguments_;
-        instance_cid_or_function = closure->ptr()->function_;
-      } else {
-        instance_cid_or_function = Smi::New(cid);
-
-        RawClass* instance_class = thread->isolate()->class_table()->At(cid);
-        if (instance_class->ptr()->num_type_arguments_ < 0) {
-          goto InstanceOfCallRuntime;
-        } else if (instance_class->ptr()->num_type_arguments_ > 0) {
-          instance_type_arguments = reinterpret_cast<RawTypeArguments**>(
-              instance->ptr())[instance_class->ptr()
-                                   ->type_arguments_field_offset_in_words_];
-        }
-        parent_function_type_arguments =
-            static_cast<RawTypeArguments*>(null_value);
-        delayed_function_type_arguments =
-            static_cast<RawTypeArguments*>(null_value);
-      }
-
-      for (RawObject** entries = cache->ptr()->cache_->ptr()->data();
-           entries[0] != null_value;
-           entries += SubtypeTestCache::kTestEntryLength) {
-        if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] ==
-             instance_cid_or_function) &&
-            (entries[SubtypeTestCache::kInstanceTypeArguments] ==
-             instance_type_arguments) &&
-            (entries[SubtypeTestCache::kInstantiatorTypeArguments] ==
-             instantiator_type_arguments) &&
-            (entries[SubtypeTestCache::kFunctionTypeArguments] ==
-             function_type_arguments) &&
-            (entries[SubtypeTestCache::kInstanceParentFunctionTypeArguments] ==
-             parent_function_type_arguments) &&
-            (entries[SubtypeTestCache::kInstanceDelayedFunctionTypeArguments] ==
-             delayed_function_type_arguments)) {
-          SP[-4] = entries[SubtypeTestCache::kTestResult];
-          goto InstanceOfOk;
-        }
-      }
-    }
-
-  // clang-format off
-  InstanceOfCallRuntime:
-    {
-      SP[1] = instance;
-      SP[2] = type;
-      SP[3] = instantiator_type_arguments;
-      SP[4] = function_type_arguments;
-      SP[5] = cache;
-      Exit(thread, FP, SP + 6, pc);
-      NativeArguments native_args(thread, 5, SP + 1, SP - 4);
-      INVOKE_RUNTIME(DRT_Instanceof, native_args);
-    }
-      // clang-format on
-
-  InstanceOfOk:
-    SP -= 4;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(NullError, 0);
-    Exit(thread, FP, SP, pc);
-    NativeArguments native_args(thread, 0, SP, SP);
-    INVOKE_RUNTIME(DRT_NullError, native_args);
-    UNREACHABLE();
-  }
-
-  {
-    BYTECODE(BadTypeError, 0);
-    // Stack: instance, instantiator type args, function type args, type, name
-    RawObject** args = SP - 4;
-    if (args[0] != null_value) {
-      SP[1] = args[0];  // instance.
-      SP[2] = args[4];  // name.
-      SP[3] = args[3];  // type.
-      Exit(thread, FP, SP + 4, pc);
-      NativeArguments native_args(thread, 3, SP + 1, SP - 4);
-      INVOKE_RUNTIME(DRT_BadTypeError, native_args);
-      UNREACHABLE();
-    }
-    SP -= 4;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AssertAssignable, A_D);
-    // Stack: instance, instantiator type args, function type args, type, name
-    RawObject** args = SP - 4;
-    const bool may_be_smi = (rA == 1);
-    const bool is_smi =
-        ((reinterpret_cast<intptr_t>(args[0]) & kSmiTagMask) == kSmiTag);
-    const bool smi_ok = is_smi && may_be_smi;
-    if (!smi_ok && (args[0] != null_value)) {
-      RawSubtypeTestCache* cache =
-          static_cast<RawSubtypeTestCache*>(LOAD_CONSTANT(rD));
-      if (cache != null_value) {
-        RawInstance* instance = static_cast<RawInstance*>(args[0]);
-        RawTypeArguments* instantiator_type_arguments =
-            static_cast<RawTypeArguments*>(args[1]);
-        RawTypeArguments* function_type_arguments =
-            static_cast<RawTypeArguments*>(args[2]);
-
-        const intptr_t cid = SimulatorHelpers::GetClassId(instance);
-
-        RawTypeArguments* instance_type_arguments =
-            static_cast<RawTypeArguments*>(null_value);
-        RawObject* instance_cid_or_function;
-
-        RawTypeArguments* parent_function_type_arguments;
-        RawTypeArguments* delayed_function_type_arguments;
-        if (cid == kClosureCid) {
-          RawClosure* closure = static_cast<RawClosure*>(instance);
-          instance_type_arguments =
-              closure->ptr()->instantiator_type_arguments_;
-          parent_function_type_arguments =
-              closure->ptr()->function_type_arguments_;
-          delayed_function_type_arguments =
-              closure->ptr()->delayed_type_arguments_;
-          instance_cid_or_function = closure->ptr()->function_;
-        } else {
-          instance_cid_or_function = Smi::New(cid);
-
-          RawClass* instance_class = thread->isolate()->class_table()->At(cid);
-          if (instance_class->ptr()->num_type_arguments_ < 0) {
-            goto AssertAssignableCallRuntime;
-          } else if (instance_class->ptr()->num_type_arguments_ > 0) {
-            instance_type_arguments = reinterpret_cast<RawTypeArguments**>(
-                instance->ptr())[instance_class->ptr()
-                                     ->type_arguments_field_offset_in_words_];
-          }
-          parent_function_type_arguments =
-              static_cast<RawTypeArguments*>(null_value);
-          delayed_function_type_arguments =
-              static_cast<RawTypeArguments*>(null_value);
-        }
-
-        for (RawObject** entries = cache->ptr()->cache_->ptr()->data();
-             entries[0] != null_value;
-             entries += SubtypeTestCache::kTestEntryLength) {
-          if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] ==
-               instance_cid_or_function) &&
-              (entries[SubtypeTestCache::kInstanceTypeArguments] ==
-               instance_type_arguments) &&
-              (entries[SubtypeTestCache::kInstantiatorTypeArguments] ==
-               instantiator_type_arguments) &&
-              (entries[SubtypeTestCache::kFunctionTypeArguments] ==
-               function_type_arguments) &&
-              (entries
-                   [SubtypeTestCache::kInstanceParentFunctionTypeArguments] ==
-               parent_function_type_arguments) &&
-              (entries
-                   [SubtypeTestCache::kInstanceDelayedFunctionTypeArguments] ==
-               delayed_function_type_arguments)) {
-            if (true_value == entries[SubtypeTestCache::kTestResult]) {
-              goto AssertAssignableOk;
-            } else {
-              break;
-            }
-          }
-        }
-      }
-
-    AssertAssignableCallRuntime:
-      SP[1] = args[0];  // instance
-      SP[2] = args[3];  // type
-      SP[3] = args[1];  // instantiator type args
-      SP[4] = args[2];  // function type args
-      SP[5] = args[4];  // name
-      SP[6] = cache;
-      SP[7] = Smi::New(kTypeCheckFromInline);
-      Exit(thread, FP, SP + 8, pc);
-      NativeArguments native_args(thread, 7, SP + 1, SP - 4);
-      INVOKE_RUNTIME(DRT_TypeCheck, native_args);
-    }
-
-  AssertAssignableOk:
-    SP -= 4;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AssertSubtype, A);
-    RawObject** args = SP - 4;
-
-    // TODO(kustermann): Implement fast case for common arguments.
-
-    // The arguments on the stack look like:
-    //     args[0]  instantiator type args
-    //     args[1]  function type args
-    //     args[2]  sub_type
-    //     args[3]  super_type
-    //     args[4]  name
-
-    // This is unused, since the negative case throws an exception.
-    SP++;
-    RawObject** result_slot = SP;
-
-    Exit(thread, FP, SP + 1, pc);
-    NativeArguments native_args(thread, 5, args, result_slot);
-    INVOKE_RUNTIME(DRT_SubtypeCheck, native_args);
-
-    // Result slot not used anymore.
-    SP--;
-
-    // Drop all arguments.
-    SP -= 5;
-
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(AssertBoolean, A);
-    RawObject* value = SP[0];
-    if (rA) {  // Should we perform type check?
-      if ((value == true_value) || (value == false_value)) {
-        goto AssertBooleanOk;
-      }
-    } else if (value != null_value) {
-      goto AssertBooleanOk;
-    }
-
-    // Assertion failed.
-    {
-      SP[1] = SP[0];  // instance
-      Exit(thread, FP, SP + 2, pc);
-      NativeArguments args(thread, 1, SP + 1, SP);
-      INVOKE_RUNTIME(DRT_NonBoolTypeError, args);
-    }
-
-  AssertBooleanOk:
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(TestSmi, A_D);
-    intptr_t left = reinterpret_cast<intptr_t>(RAW_CAST(Smi, FP[rA]));
-    intptr_t right = reinterpret_cast<intptr_t>(RAW_CAST(Smi, FP[rD]));
-    if ((left & right) != 0) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(TestCids, A_D);
-    const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
-    const intptr_t num_cases = rD;
-    for (intptr_t i = 0; i < num_cases; i++) {
-      ASSERT(SimulatorBytecode::DecodeOpcode(pc[i]) == SimulatorBytecode::kNop);
-      intptr_t test_target = SimulatorBytecode::DecodeA(pc[i]);
-      intptr_t test_cid = SimulatorBytecode::DecodeD(pc[i]);
-      if (cid == test_cid) {
-        if (test_target != 0) {
-          pc += 1;  // Match true.
-        } else {
-          pc += 2;  // Match false.
-        }
-        break;
-      }
-    }
-    pc += num_cases;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckSmi, 0);
-    intptr_t obj = reinterpret_cast<intptr_t>(FP[rA]);
-    if ((obj & kSmiTagMask) == kSmiTag) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckEitherNonSmi, A_D);
-    const intptr_t obj1 = reinterpret_cast<intptr_t>(FP[rA]);
-    const intptr_t obj2 = reinterpret_cast<intptr_t>(FP[rD]);
-    const intptr_t tag = (obj1 | obj2) & kSmiTagMask;
-    if (tag != kSmiTag) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckClassId, A_D);
-    const intptr_t actual_cid =
-        reinterpret_cast<intptr_t>(FP[rA]) >> kSmiTagSize;
-    const intptr_t desired_cid = rD;
-    pc += (actual_cid == desired_cid) ? 1 : 0;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckClassIdRange, A_D);
-    const intptr_t actual_cid =
-        reinterpret_cast<intptr_t>(FP[rA]) >> kSmiTagSize;
-    const uintptr_t cid_start = rD;
-    const uintptr_t cid_range = SimulatorBytecode::DecodeD(*pc);
-    // Unsigned comparison.  Skip either just the nop or both the nop and the
-    // following instruction.
-    pc += (actual_cid - cid_start <= cid_range) ? 2 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckBitTest, A_D);
-    const intptr_t raw_value = reinterpret_cast<intptr_t>(FP[rA]);
-    const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag);
-    const intptr_t cid_min = SimulatorBytecode::DecodeD(*pc);
-    const intptr_t cid_mask = Smi::Value(
-        RAW_CAST(Smi, LOAD_CONSTANT(SimulatorBytecode::DecodeD(*(pc + 1)))));
-    if (LIKELY(!is_smi)) {
-      const intptr_t cid_max = Utils::HighestBit(cid_mask) + cid_min;
-      const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
-      // The cid is in-bounds, and the bit is set in the mask.
-      if ((cid >= cid_min) && (cid <= cid_max) &&
-          ((cid_mask & (1 << (cid - cid_min))) != 0)) {
-        pc += 3;
-      } else {
-        pc += 2;
-      }
-    } else {
-      const bool may_be_smi = (rD == 1);
-      pc += (may_be_smi ? 3 : 2);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckCids, A_B_C);
-    const intptr_t raw_value = reinterpret_cast<intptr_t>(FP[rA]);
-    const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag);
-    const bool may_be_smi = (rB == 1);
-    const intptr_t cids_length = rC;
-    if (LIKELY(!is_smi)) {
-      const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
-      for (intptr_t i = 0; i < cids_length; i++) {
-        const intptr_t desired_cid = SimulatorBytecode::DecodeD(*(pc + i));
-        if (cid == desired_cid) {
-          pc++;
-          break;
-        }
-      }
-      pc += cids_length;
-    } else {
-      pc += cids_length;
-      pc += (may_be_smi ? 1 : 0);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(CheckCidsByRange, A_B_C);
-    const intptr_t raw_value = reinterpret_cast<intptr_t>(FP[rA]);
-    const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag);
-    const bool may_be_smi = (rB == 1);
-    const intptr_t cids_length = rC;
-    if (LIKELY(!is_smi)) {
-      const intptr_t cid = SimulatorHelpers::GetClassId(FP[rA]);
-      for (intptr_t i = 0; i < cids_length; i += 2) {
-        // Note unsigned type to get unsigned range check below.
-        const uintptr_t cid_start = SimulatorBytecode::DecodeD(*(pc + i));
-        const uintptr_t cids = SimulatorBytecode::DecodeD(*(pc + i + 1));
-        if (cid - cid_start < cids) {
-          pc++;
-          break;
-        }
-      }
-      pc += cids_length;
-    } else {
-      pc += cids_length;
-      pc += (may_be_smi ? 1 : 0);
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfEqStrictTOS, 0);
-    SP -= 2;
-    if (SP[1] != SP[2]) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeStrictTOS, 0);
-    SP -= 2;
-    if (SP[1] == SP[2]) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfEqStrictNumTOS, 0);
-
-#ifndef PRODUCT
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    SP -= 2;
-    if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeStrictNumTOS, 0);
-
-#ifndef PRODUCT
-    if (thread->isolate()->single_step()) {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
-    }
-#endif  // !PRODUCT
-
-    SP -= 2;
-    if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfSmiLtTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    if (!(Smi::Value(left) < Smi::Value(right))) {
-      pc++;
-    }
-    SP -= 2;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfSmiLeTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    if (!(Smi::Value(left) <= Smi::Value(right))) {
-      pc++;
-    }
-    SP -= 2;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfSmiGeTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    if (!(Smi::Value(left) >= Smi::Value(right))) {
-      pc++;
-    }
-    SP -= 2;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfSmiGtTOS, 0);
-    RawSmi* left = Smi::RawCast(SP[-1]);
-    RawSmi* right = Smi::RawCast(SP[-0]);
-    if (!(Smi::Value(left) > Smi::Value(right))) {
-      pc++;
-    }
-    SP -= 2;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfEqStrict, A_D);
-    RawObject* lhs = FP[rA];
-    RawObject* rhs = FP[rD];
-    if (lhs != rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeStrict, A_D);
-    RawObject* lhs = FP[rA];
-    RawObject* rhs = FP[rD];
-    if (lhs == rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfLe, A_D);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
-    if (lhs > rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfLt, A_D);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
-    if (lhs >= rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfGe, A_D);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
-    if (lhs < rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfGt, A_D);
-    const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rA]);
-    const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rD]);
-    if (lhs <= rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfULe, A_D);
-    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
-    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
-    if (lhs > rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfULt, A_D);
-    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
-    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
-    if (lhs >= rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfUGe, A_D);
-    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
-    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
-    if (lhs < rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfUGt, A_D);
-    const uintptr_t lhs = reinterpret_cast<uintptr_t>(FP[rA]);
-    const uintptr_t rhs = reinterpret_cast<uintptr_t>(FP[rD]);
-    if (lhs <= rhs) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-#if defined(ARCH_IS_64_BIT)
-  {
-    BYTECODE(IfDEq, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs == rhs) ? 0 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDNe, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs != rhs) ? 0 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDLe, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs <= rhs) ? 0 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDLt, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs < rhs) ? 0 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDGe, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs >= rhs) ? 0 : 1;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDGt, A_D);
-    const double lhs = bit_cast<double, RawObject*>(FP[rA]);
-    const double rhs = bit_cast<double, RawObject*>(FP[rD]);
-    pc += (lhs > rhs) ? 0 : 1;
-    DISPATCH();
-  }
-#else   // defined(ARCH_IS_64_BIT)
-  {
-    BYTECODE(IfDEq, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDNe, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDLe, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDLt, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDGe, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfDGt, A_D);
-    UNREACHABLE();
-    DISPATCH();
-  }
-#endif  // defined(ARCH_IS_64_BIT)
-
-  {
-    BYTECODE(IfEqStrictNum, A_D);
-    RawObject* lhs = FP[rA];
-    RawObject* rhs = FP[rD];
-    if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeStrictNum, A_D);
-    RawObject* lhs = FP[rA];
-    RawObject* rhs = FP[rD];
-    if (SimulatorHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfEqNull, A);
-    if (FP[rA] != null_value) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeNull, A_D);
-    if (FP[rA] == null_value) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfEqNullTOS, 0);
-    if (SP[0] != null_value) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(IfNeNullTOS, 0);
-    if (SP[0] == null_value) {
-      pc++;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Jump, 0);
-    const int32_t target = static_cast<int32_t>(op) >> 8;
-    pc += (target - 1);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadClassId, A_D);
-    const uint16_t object_reg = rD;
-    RawObject* obj = static_cast<RawObject*>(FP[object_reg]);
-    FP[rA] = SimulatorHelpers::GetClassIdAsSmi(obj);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadClassIdTOS, 0);
-    RawObject* obj = static_cast<RawObject*>(SP[0]);
-    SP[0] = SimulatorHelpers::GetClassIdAsSmi(obj);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedTOS, 0);
-    SP -= 3;
-    RawArray* array = RAW_CAST(Array, SP[1]);
-    RawSmi* index = RAW_CAST(Smi, SP[2]);
-    RawObject* value = SP[3];
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value,
-                             thread);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexed, A_B_C);
-    RawArray* array = RAW_CAST(Array, FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    RawObject* value = FP[rC];
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->StoreArrayPointer(array->ptr()->data() + Smi::Value(index), value,
-                             thread);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUint8, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    *data = static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUntaggedUint8, A_B_C);
-    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    array[Smi::Value(index)] =
-        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUntaggedUint32, A_B_C);
-    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    const uint32_t value = *reinterpret_cast<uint32_t*>(&FP[rC]);
-    *reinterpret_cast<uint32_t*>(array + Smi::Value(index)) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUntaggedFloat32, A_B_C);
-    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    const float value = *reinterpret_cast<float*>(&FP[rC]);
-    *reinterpret_cast<float*>(array + Smi::Value(index)) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUntaggedFloat64, A_B_C);
-    uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    const double value = *reinterpret_cast<double*>(&FP[rC]);
-    *reinterpret_cast<double*>(array + Smi::Value(index)) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedOneByteString, A_B_C);
-    RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    array->ptr()->data()[Smi::Value(index)] =
-        static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreIndexedUint32, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
-    const uintptr_t value = reinterpret_cast<uintptr_t>(FP[rC]);
-    *reinterpret_cast<uint32_t*>(data) = static_cast<uint32_t>(value);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(TailCall, 0);
-    RawCode* code = RAW_CAST(Code, SP[-0]);
-    RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, SP[-1]);
-    PrepareForTailCall(code, args_desc, FP, &SP, &pc);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(TailCallOpt, A_D);
-    RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, FP[rA]);
-    RawCode* code = RAW_CAST(Code, FP[rD]);
-    PrepareForTailCall(code, args_desc, FP, &SP, &pc);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadArgDescriptor, 0);
-    SP++;
-    SP[0] = argdesc_;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadArgDescriptorOpt, A);
-    FP[rA] = argdesc_;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(NoSuchMethod, 0);
-    goto ClosureNoSuchMethod;
-  }
-
-  {
-    BYTECODE(LoadFpRelativeSlot, A_X);
-    RawSmi* index = RAW_CAST(Smi, SP[-0]);
-    const int16_t offset = rD;
-    SP[-0] = FP[-(Smi::Value(index) + offset)];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadFpRelativeSlotOpt, A_B_Y);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    const int8_t offset = rY;
-    FP[rA] = FP[-(Smi::Value(index) + offset)];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreFpRelativeSlot, A_X);
-    RawSmi* index = RAW_CAST(Smi, SP[-1]);
-    const int16_t offset = rD;
-    FP[-(Smi::Value(index) + offset) - 0] = SP[-0];
-    SP -= 2;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(StoreFpRelativeSlotOpt, A_B_Y);
-    RawSmi* index = RAW_CAST(Smi, FP[rB]);
-    const int8_t offset = rY;
-    FP[-(Smi::Value(index) + offset) - 0] = FP[rA];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedTOS, 0);
-    // Currently this instruction is only emitted if it's safe to do.
-    ASSERT(!SP[0]->IsHeapObject());
-    ASSERT(SP[-1]->IsArray() || SP[-1]->IsImmutableArray());
-
-    const intptr_t index_scale = rA;
-    RawSmi* index = RAW_CAST(Smi, SP[-0]);
-    RawArray* array = Array::RawCast(SP[-1]);
-
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    SP[-1] = array->ptr()->data()[Smi::Value(index) << index_scale];
-    SP--;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexed, A_B_C);
-    RawObject* obj = FP[rB];
-    ASSERT(obj->IsArray() || obj->IsImmutableArray());
-    RawArray* array = reinterpret_cast<RawArray*>(obj);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    FP[rA] = array->ptr()->data()[Smi::Value(index)];
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUint8, A_B_C);
-    uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedInt8, A_B_C);
-    int8_t* data = reinterpret_cast<int8_t*>(
-        SimulatorHelpers::GetTypedData(FP[rB], FP[rC]));
-    FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUint32, A_B_C);
-    const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    const uint32_t value = *reinterpret_cast<const uint32_t*>(data);
-    *reinterpret_cast<uint32_t*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedInt32, A_B_C);
-    const uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
-    const int32_t value = *reinterpret_cast<const int32_t*>(data);
-    *reinterpret_cast<int32_t*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedInt8, A_B_C);
-    int8_t* data = reinterpret_cast<int8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = reinterpret_cast<RawObject*>(
-        static_cast<word>(data[Smi::Value(index)]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedUint8, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    FP[rA] = reinterpret_cast<RawObject*>(
-        static_cast<word>(data[Smi::Value(index)]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedInt32, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    const int32_t value = *reinterpret_cast<int32_t*>(data + Smi::Value(index));
-    *reinterpret_cast<int32_t*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedUint32, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    const uint32_t value =
-        *reinterpret_cast<uint32_t*>(data + Smi::Value(index));
-    *reinterpret_cast<uint32_t*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedFloat32, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    const float value = *reinterpret_cast<float*>(data + Smi::Value(index));
-    *reinterpret_cast<float*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedUntaggedFloat64, A_B_C);
-    uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    const double value = *reinterpret_cast<double*>(data + Smi::Value(index));
-    *reinterpret_cast<double*>(&FP[rA]) = value;
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedOneByteString, A_B_C);
-    RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    FP[rA] = reinterpret_cast<RawObject*>(
-        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(LoadIndexedTwoByteString, A_B_C);
-    RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]);
-    RawSmi* index = RAW_CAST(Smi, FP[rC]);
-    ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
-    FP[rA] = reinterpret_cast<RawObject*>(
-        static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Deopt, A_D);
-    const bool is_lazy = rD == 0;
-    if (!Deoptimize(thread, &pc, &FP, &SP, is_lazy)) {
-      HANDLE_EXCEPTION;
-    }
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(DeoptRewind, 0);
-    pc = reinterpret_cast<uint32_t*>(thread->resume_pc());
-    if (!Deoptimize(thread, &pc, &FP, &SP, false /* eager */)) {
-      HANDLE_EXCEPTION;
-    }
-    {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments args(thread, 0, NULL, NULL);
-      INVOKE_RUNTIME(DRT_RewindPostDeopt, args);
-    }
-    UNREACHABLE();  // DRT_RewindPostDeopt does not exit normally.
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Nop, 0);
-    DISPATCH();
-  }
-
-  {
-    BYTECODE(Trap, 0);
-    UNIMPLEMENTED();
-    DISPATCH();
-  }
-
-  // Helper used to handle noSuchMethod on closures.
-  {
-  ClosureNoSuchMethod:
-#if defined(DEBUG)
-    function_h ^= FrameFunction(FP);
-    ASSERT(function_h.IsNull() || function_h.IsClosureFunction());
-#endif
-
-    // Restore caller context as we are going to throw NoSuchMethod.
-    pc = SavedCallerPC(FP);
-
-    const bool has_dart_caller = (reinterpret_cast<uword>(pc) & 2) == 0;
-    const intptr_t argc = has_dart_caller
-                              ? SimulatorBytecode::DecodeArgc(pc[-1])
-                              : (reinterpret_cast<uword>(pc) >> 2);
-    const bool has_function_type_args =
-        has_dart_caller && SimulatorHelpers::ArgDescTypeArgsLen(argdesc_) > 0;
-
-    SP = FrameArguments(FP, 0);
-    RawObject** args = SP - argc;
-    FP = SavedCallerFP(FP);
-    if (has_dart_caller) {
-      pp_ = SimulatorHelpers::FrameCode(FP)->ptr()->object_pool_;
-    }
-
-    RawClosure* closure =
-        Closure::RawCast(args[has_function_type_args ? 1 : 0]);
-    *++SP = null_value;
-    *++SP = closure;
-    *++SP = closure->ptr()->function_;
-    *++SP = argdesc_;
-    *++SP = null_value;  // Array of arguments (will be filled).
-
-    // Allocate array of arguments.
-    {
-      SP[1] = Smi::New(argc);  // length
-      SP[2] = null_value;      // type
-      Exit(thread, FP, SP + 3, pc);
-      NativeArguments native_args(thread, 2, SP + 1, SP);
-      if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
-        HANDLE_EXCEPTION;
-      } else if (has_dart_caller) {
-        HANDLE_RETURN;
-      }
-
-      // Copy arguments into the newly allocated array.
-      RawArray* array = static_cast<RawArray*>(SP[0]);
-      ASSERT(array->GetClassId() == kArrayCid);
-      for (intptr_t i = 0; i < argc; i++) {
-        array->ptr()->data()[i] = args[i];
-      }
-    }
-
-    // Invoke noSuchMethod passing down closure, argument descriptor and
-    // array of arguments.
-    {
-      Exit(thread, FP, SP + 1, pc);
-      NativeArguments native_args(thread, 4, SP - 3, SP - 4);
-      INVOKE_RUNTIME(DRT_NoSuchMethodFromPrologue, native_args);
-      UNREACHABLE();
-    }
-
-    DISPATCH();
-  }
-
-  // Single dispatch point used by exception handling macros.
-  {
-  DispatchAfterException:
-    DISPATCH();
-  }
-
-  UNREACHABLE();
-  return 0;
-}
-
-void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
-  // Walk over all setjmp buffers (simulated --> C++ transitions)
-  // and try to find the setjmp associated with the simulated frame pointer.
-  SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
-  while ((buf->link() != NULL) && (buf->link()->fp() > fp)) {
-    buf = buf->link();
-  }
-  ASSERT(buf != NULL);
-  ASSERT(last_setjmp_buffer() == buf);
-
-  // The C++ caller has not cleaned up the stack memory of C++ frames.
-  // Prepare for unwinding frames by destroying all the stack resources
-  // in the previous C++ frames.
-  StackResource::Unwind(thread);
-
-  fp_ = reinterpret_cast<RawObject**>(fp);
-
-  if (pc == StubCode::RunExceptionHandler().EntryPoint()) {
-    // The RunExceptionHandler stub is a placeholder.  We implement
-    // its behavior here.
-    RawObject* raw_exception = thread->active_exception();
-    RawObject* raw_stacktrace = thread->active_stacktrace();
-    ASSERT(raw_exception != Object::null());
-    thread->set_active_exception(Object::null_object());
-    thread->set_active_stacktrace(Object::null_object());
-    special_[kExceptionSpecialIndex] = raw_exception;
-    special_[kStackTraceSpecialIndex] = raw_stacktrace;
-    pc_ = thread->resume_pc();
-  } else {
-    pc_ = pc;
-  }
-
-  // Set the tag.
-  thread->set_vm_tag(VMTag::kDartCompiledTagId);
-  // Clear top exit frame.
-  thread->set_top_exit_frame_info(0);
-
-  buf->Longjmp();
-  UNREACHABLE();
-}
-
-void Simulator::VisitObjectPointers(ObjectPointerVisitor* visitor) {
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&pp_));
-  visitor->VisitPointer(reinterpret_cast<RawObject**>(&argdesc_));
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/simulator_dbc.h b/runtime/vm/simulator_dbc.h
deleted file mode 100644
index 7ed6fce..0000000
--- a/runtime/vm/simulator_dbc.h
+++ /dev/null
@@ -1,192 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_SIMULATOR_DBC_H_
-#define RUNTIME_VM_SIMULATOR_DBC_H_
-
-#ifndef RUNTIME_VM_SIMULATOR_H_
-#error Do not include simulator_dbc.h directly; use simulator.h.
-#endif
-
-#include "vm/compiler/method_recognizer.h"
-#include "vm/constants_dbc.h"
-
-namespace dart {
-
-class Array;
-class Code;
-class Isolate;
-class ObjectPointerVisitor;
-class RawArray;
-class RawCode;
-class RawFunction;
-class RawICData;
-class RawImmutableArray;
-class RawObject;
-class RawObjectPool;
-class SimulatorSetjmpBuffer;
-class Thread;
-
-// Simulator intrinsic handler. It is invoked on entry to the intrinsified
-// function via Intrinsic bytecode before the frame is setup.
-// If the handler returns true then Intrinsic bytecode works as a return
-// instruction returning the value in result. Otherwise interpreter proceeds to
-// execute the body of the function.
-typedef bool (*IntrinsicHandler)(Thread* thread,
-                                 RawObject** FP,
-                                 RawObject** result);
-
-class Simulator {
- public:
-  static const uword kSimulatorStackUnderflowSize = 0x80;
-
-  Simulator();
-  ~Simulator();
-
-  // The currently executing Simulator instance, which is associated to the
-  // current isolate
-  static Simulator* Current();
-
-  // Low address (DBC stack grows up).
-  uword stack_base() const { return stack_base_; }
-  // Limit for StackOverflowError.
-  uword overflow_stack_limit() const { return overflow_stack_limit_; }
-  // High address (DBC stack grows up).
-  uword stack_limit() const { return stack_limit_; }
-
-  // Call on program start.
-  static void Init();
-
-  RawObject* Call(const Code& code,
-                  const Array& arguments_descriptor,
-                  const Array& arguments,
-                  Thread* thread);
-
-  void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
-
-  uword get_sp() const { return reinterpret_cast<uword>(fp_); }
-  uword get_fp() const { return reinterpret_cast<uword>(fp_); }
-  uword get_pc() const { return reinterpret_cast<uword>(pc_); }
-
-  enum IntrinsicId {
-#define V(test_class_name, test_function_name, enum_name, fp)                  \
-  k##enum_name##Intrinsic,
-    ALL_INTRINSICS_LIST(V) GRAPH_INTRINSICS_LIST(V)
-#undef V
-        kIntrinsicCount,
-  };
-
-  static bool IsSupportedIntrinsic(IntrinsicId id) {
-    return intrinsics_[id] != NULL;
-  }
-
-  enum SpecialIndex {
-    kExceptionSpecialIndex,
-    kStackTraceSpecialIndex,
-    kSpecialIndexCount
-  };
-
-  void VisitObjectPointers(ObjectPointerVisitor* visitor);
-
- private:
-  uintptr_t* stack_;
-  uword stack_base_;
-  uword overflow_stack_limit_;
-  uword stack_limit_;
-
-  RawObject** fp_;
-  uword pc_;
-  DEBUG_ONLY(uint64_t icount_;)
-
-  SimulatorSetjmpBuffer* last_setjmp_buffer_;
-
-  RawObjectPool* pp_;  // Pool Pointer.
-  RawArray* argdesc_;  // Arguments Descriptor: used to pass information between
-                       // call instruction and the function entry.
-  RawObject* special_[kSpecialIndexCount];
-
-  static IntrinsicHandler intrinsics_[kIntrinsicCount];
-
-  // Set up an exit frame for the garbage collector.
-  void Exit(Thread* thread,
-            RawObject** base,
-            RawObject** exit_frame,
-            uint32_t* pc);
-
-  void CallRuntime(Thread* thread,
-                   RawObject** base,
-                   RawObject** exit_frame,
-                   uint32_t* pc,
-                   intptr_t argc_tag,
-                   RawObject** args,
-                   RawObject** result,
-                   uword target);
-
-  void Invoke(Thread* thread,
-              RawObject** call_base,
-              RawObject** call_top,
-              uint32_t** pc,
-              RawObject*** FP,
-              RawObject*** SP);
-
-  bool Deoptimize(Thread* thread,
-                  uint32_t** pc,
-                  RawObject*** FP,
-                  RawObject*** SP,
-                  bool is_lazy);
-
-  void InlineCacheMiss(int checked_args,
-                       Thread* thread,
-                       RawICData* icdata,
-                       RawObject** call_base,
-                       RawObject** top,
-                       uint32_t* pc,
-                       RawObject** FP,
-                       RawObject** SP);
-
-  void InstanceCall1(Thread* thread,
-                     RawICData* icdata,
-                     RawObject** call_base,
-                     RawObject** call_top,
-                     uint32_t** pc,
-                     RawObject*** FP,
-                     RawObject*** SP,
-                     bool optimized);
-
-  void InstanceCall2(Thread* thread,
-                     RawICData* icdata,
-                     RawObject** call_base,
-                     RawObject** call_top,
-                     uint32_t** pc,
-                     RawObject*** FP,
-                     RawObject*** SP,
-                     bool optimized);
-
-  void PrepareForTailCall(RawCode* code,
-                          RawImmutableArray* args_desc,
-                          RawObject** FP,
-                          RawObject*** SP,
-                          uint32_t** pc);
-
-#if !defined(PRODUCT)
-  // Returns true if tracing of executed instructions is enabled.
-  bool IsTracingExecution() const;
-
-  // Prints bytecode instruction at given pc for instruction tracing.
-  void TraceInstruction(uint32_t* pc) const;
-#endif  // !defined(PRODUCT)
-
-  // Longjmp support for exceptions.
-  SimulatorSetjmpBuffer* last_setjmp_buffer() { return last_setjmp_buffer_; }
-  void set_last_setjmp_buffer(SimulatorSetjmpBuffer* buffer) {
-    last_setjmp_buffer_ = buffer;
-  }
-
-  friend class SimulatorSetjmpBuffer;
-  DISALLOW_COPY_AND_ASSIGN(Simulator);
-};
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_SIMULATOR_DBC_H_
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 7fbc4d5..4d7bfea 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -34,7 +34,7 @@
   // Check if this is a singleton object class which is shared by all isolates.
   return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
           (class_id == kTypeArgumentsCid) ||
-          (class_id >= kNullCid && class_id <= kVoidCid));
+          (class_id >= kNullCid && class_id <= kNeverCid));
 }
 
 static bool IsBootstrapedClassId(intptr_t class_id) {
@@ -721,6 +721,7 @@
   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());
+  READ_VM_SINGLETON_OBJ(kNeverType, Object::never_type().raw());
   READ_VM_SINGLETON_OBJ(kEmptyTypeArguments,
                         Object::empty_type_arguments().raw());
   READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().raw());
@@ -878,6 +879,7 @@
   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::never_type().raw(), kNeverType);
   WRITE_VM_SINGLETON_OBJ(Object::empty_type_arguments().raw(),
                          kEmptyTypeArguments);
   WRITE_VM_SINGLETON_OBJ(Bool::True().raw(), kTrueValue);
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 61b90a9..1242943 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -199,7 +199,7 @@
     if (!IncludesCode(kind())) {
       return NULL;
     }
-    uword offset = Utils::RoundUp(length(), OS::kMaxPreferredCodeAlignment);
+    uword offset = Utils::RoundUp(length(), kMaxObjectAlignment);
     return Addr() + offset;
   }
 
diff --git a/runtime/vm/snapshot_ids.h b/runtime/vm/snapshot_ids.h
index c4fa6b7..f81f6e7 100644
--- a/runtime/vm/snapshot_ids.h
+++ b/runtime/vm/snapshot_ids.h
@@ -33,6 +33,7 @@
   kNullType,
   kDynamicType,
   kVoidType,
+  kNeverType,
   kFunctionType,
   kNumberType,
   kSmiType,
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 5e161d9..2b07d46 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -218,14 +218,7 @@
       RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
   while (iter.MoveNext()) {
     HANDLESCOPE(thread());
-// TODO(zra): Remove this bailout once DBC has reliable ICData.
-#if defined(TARGET_ARCH_DBC)
-    if (iter.DeoptId() >= ic_data_array->length()) {
-      continue;
-    }
-#else
     ASSERT(iter.DeoptId() < ic_data_array->length());
-#endif
     const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
     if (ic_data != NULL) {
       const TokenPosition token_pos = iter.TokenPos();
@@ -276,14 +269,7 @@
       RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
   while (iter.MoveNext()) {
     HANDLESCOPE(thread());
-// TODO(zra): Remove this bailout once DBC has reliable ICData.
-#if defined(TARGET_ARCH_DBC)
-    if (iter.DeoptId() >= ic_data_array->length()) {
-      continue;
-    }
-#else
     ASSERT(iter.DeoptId() < ic_data_array->length());
-#endif
     const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
     if (ic_data != NULL) {
       const TokenPosition token_pos = iter.TokenPos();
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index defc700..260e99f 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -220,23 +220,17 @@
       reinterpret_cast<RawObject**>(fp()) +
       (is_interpreted() ? kKBCFirstObjectSlotFromFp
                         : runtime_frame_layout.last_fixed_object_from_fp);
-#if !defined(TARGET_ARCH_DBC)
   if (first_fixed <= last_fixed) {
     visitor->VisitPointers(first_fixed, last_fixed);
   } else {
     ASSERT(runtime_frame_layout.first_object_from_fp ==
            runtime_frame_layout.first_local_from_fp);
   }
-#else
-  ASSERT(last_fixed <= first_fixed);
-  visitor->VisitPointers(last_fixed, first_fixed);
-#endif
 }
 
 void EntryFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   ASSERT(visitor != NULL);
   // Visit objects between SP and (FP - callee_save_area).
-#if !defined(TARGET_ARCH_DBC)
   RawObject** first = is_interpreted() ? reinterpret_cast<RawObject**>(fp()) +
                                              kKBCSavedArgDescSlotFromEntryFp
                                        : reinterpret_cast<RawObject**>(sp());
@@ -245,13 +239,6 @@
                                             kExitLinkSlotFromEntryFp - 1;
   // There may not be any pointer to visit; in this case, first > last.
   visitor->VisitPointers(first, last);
-#else
-  // On DBC stack is growing upwards which implies fp() <= sp().
-  RawObject** first = reinterpret_cast<RawObject**>(fp());
-  RawObject** last = reinterpret_cast<RawObject**>(sp());
-  ASSERT(first <= last);
-  visitor->VisitPointers(first, last);
-#endif
 }
 
 void StackFrame::VisitObjectPointers(ObjectPointerVisitor* visitor) {
@@ -293,7 +280,6 @@
     const uword start = Instructions::PayloadStart(code.instructions());
     const uint32_t pc_offset = pc() - start;
     if (it.Find(pc_offset)) {
-#if !defined(TARGET_ARCH_DBC)
       if (is_interpreted()) {
         UNIMPLEMENTED();
       }
@@ -341,42 +327,6 @@
       last = reinterpret_cast<RawObject**>(
           fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
       visitor->VisitPointers(first, last);
-#else
-      RawObject** first = reinterpret_cast<RawObject**>(fp());
-      RawObject** last = reinterpret_cast<RawObject**>(sp());
-
-      // Visit fixed prefix of the frame.
-      RawObject** first_fixed =
-          first + runtime_frame_layout.first_object_from_fp;
-      RawObject** last_fixed =
-          first + (runtime_frame_layout.first_object_from_fp + 1);
-      ASSERT(first_fixed <= last_fixed);
-      visitor->VisitPointers(first_fixed, last_fixed);
-
-      // A stack map is present in the code object, use the stack map to
-      // visit frame slots which are marked as having objects.
-      //
-      // The layout of the frame is (lower addresses to the left):
-      // | registers | outgoing arguments |
-      // |XXXXXXXXXXX|--------------------|
-      //
-      // The DBC registers are described in the stack map.
-      // The outgoing arguments are assumed to be tagged; the number
-      // of outgoing arguments is not explicitly tracked.
-
-      // Visit DBC registers that contain tagged values.
-      intptr_t length = it.length();
-      for (intptr_t bit = 0; bit < length; ++bit) {
-        if (it.IsObject(bit)) {
-          visitor->VisitPointer(first + bit);
-        }
-      }
-
-      // Visit outgoing arguments.
-      if ((first + length) <= last) {
-        visitor->VisitPointers(first + length, last);
-      }
-#endif  // !defined(TARGET_ARCH_DBC)
       return;
     }
 
@@ -388,7 +338,6 @@
            (pc_offset == code.EntryPoint() - code.PayloadStart()));
   }
 
-#if !defined(TARGET_ARCH_DBC)
   // For normal unoptimized Dart frames and Stub frames each slot
   // between the first and last included are tagged objects.
   if (is_interpreted()) {
@@ -406,12 +355,6 @@
       is_interpreted()
           ? sp()
           : fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
-#else
-  // On DBC stack grows upwards: fp() <= sp().
-  RawObject** first = reinterpret_cast<RawObject**>(
-      fp() + (runtime_frame_layout.first_object_from_fp * kWordSize));
-  RawObject** last = reinterpret_cast<RawObject**>(sp());
-#endif  // !defined(TARGET_ARCH_DBC)
 
   visitor->VisitPointers(first, last);
 }
@@ -655,7 +598,6 @@
   }
 }
 
-#if !defined(TARGET_ARCH_DBC)
 StackFrameIterator::StackFrameIterator(uword fp,
                                        uword sp,
                                        uword pc,
@@ -677,7 +619,6 @@
     frames_.CheckIfInterpreted(fp);
   }
 }
-#endif
 
 StackFrame* StackFrameIterator::NextFrame() {
   // When we are at the start of iteration after having created an
@@ -697,7 +638,6 @@
       return NULL;
     }
     UnpoisonStack(frames_.fp_);
-#if !defined(TARGET_ARCH_DBC)
     if (frames_.pc_ == 0) {
       // Iteration starts from an exit frame given by its fp.
       current_frame_ = NextExitFrame();
@@ -712,12 +652,6 @@
       // Iteration starts from a Dart or stub frame given by its fp, sp, and pc.
       current_frame_ = frames_.NextFrame(validate_);
     }
-#else
-    // Iteration starts from an exit frame given by its fp. This is the only
-    // mode supported on DBC.
-    ASSERT(frames_.pc_ == 0);
-    current_frame_ = NextExitFrame();
-#endif  // !defined(TARGET_ARCH_DBC)
     return current_frame_;
   }
   ASSERT(!validate_ || current_frame_->IsValid());
@@ -865,14 +799,7 @@
   for (intptr_t index = index_; index < deopt_instructions_.length(); index++) {
     DeoptInstr* deopt_instr = deopt_instructions_[index];
     if (deopt_instr->kind() == DeoptInstr::kCallerFp) {
-      intptr_t fp_offset = (index - num_materializations_);
-#if defined(TARGET_ARCH_DBC)
-      // Stack on DBC is growing upwards but we record deopt commands
-      // in the same order we record them on other architectures as if
-      // the stack was growing downwards.
-      fp_offset = dest_frame_size_ - fp_offset;
-#endif
-      return fp_offset;
+      return index - num_materializations_;
     }
   }
   UNREACHABLE();
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index b36721d..69368fe 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -20,8 +20,6 @@
 #include "vm/stack_frame_arm.h"
 #elif defined(TARGET_ARCH_ARM64)
 #include "vm/stack_frame_arm64.h"
-#elif defined(TARGET_ARCH_DBC)
-#include "vm/stack_frame_dbc.h"
 #else
 #error Unknown architecture.
 #endif
@@ -258,7 +256,6 @@
                      Thread* thread,
                      CrossThreadPolicy cross_thread_policy);
 
-#if !defined(TARGET_ARCH_DBC)
   // Iterator for iterating over all frames from the current frame (given by its
   // fp, sp, and pc) to the first EntryFrame.
   StackFrameIterator(uword fp,
@@ -267,7 +264,6 @@
                      ValidationPolicy validation_policy,
                      Thread* thread,
                      CrossThreadPolicy cross_thread_policy);
-#endif
 
   // Checks if a next frame exists.
   bool HasNextFrame() const { return frames_.fp_ != 0; }
@@ -371,7 +367,6 @@
                 thread,
                 cross_thread_policy) {}
 
-#if !defined(TARGET_ARCH_DBC)
   DartFrameIterator(uword fp,
                     uword sp,
                     uword pc,
@@ -383,7 +378,6 @@
                 ValidationPolicy::kDontValidateFrames,
                 thread,
                 cross_thread_policy) {}
-#endif
 
   // Get next dart frame.
   StackFrame* NextFrame() {
@@ -446,7 +440,6 @@
 void ValidateFrames();
 #endif
 
-#if !defined(TARGET_ARCH_DBC)
 DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
                                                 intptr_t var_index) {
   return fp_offset + var_index;
@@ -457,7 +450,6 @@
 }
 
 // Both fp and other_fp are compiled code frame pointers.
-// See stack_frame_dbc.h for the DBC version.
 DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) {
   return other_fp < fp;
 }
@@ -469,10 +461,7 @@
 }
 
 // Value for stack limit that is used to cause an interrupt.
-// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike
-// on all other architectures.
 static const uword kInterruptStackLimit = ~static_cast<uword>(0);
-#endif
 
 DART_FORCE_INLINE static uword LocalVarAddress(uword fp, intptr_t index) {
   return fp + LocalVarIndex(0, index) * kWordSize;
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
deleted file mode 100644
index 616b012..0000000
--- a/runtime/vm/stack_frame_dbc.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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.
-
-#ifndef RUNTIME_VM_STACK_FRAME_DBC_H_
-#define RUNTIME_VM_STACK_FRAME_DBC_H_
-
-#if !defined(RUNTIME_VM_STACK_FRAME_H_)
-#error Do not include stack_frame_dbc.h directly; use stack_frame.h instead.
-#endif
-
-namespace dart {
-
-/* DBC Frame Layout
-
-IMPORTANT: On DBC stack is growing upwards which is different from all other
-architectures. This enables efficient addressing for locals via unsigned index.
-
-               |                    | <- TOS
-Callee frame   | ...                |
-               | saved FP           |    (FP of current frame)
-               | saved PC           |    (PC of current frame)
-               | code object        |
-               | function object    |
-               +--------------------+
-Current frame  | ...               T| <- SP of current frame
-               | ...               T|
-               | first local       T| <- FP of current frame
-               | caller's FP       *|
-               | caller's PC       *|
-               | code object       T|    (current frame's code object)
-               | function object   T|    (current frame's function object)
-               +--------------------+
-Caller frame   | last parameter     | <- SP of caller frame
-               |  ...               |
-
-               T against a slot indicates it needs to be traversed during GC.
-               * against a slot indicates that it can be traversed during GC
-                 because it will look like a smi to the visitor.
-*/
-
-static const int kDartFrameFixedSize = 4;  // Function, Code, PC, FP
-static const int kSavedPcSlotFromSp = 3;
-
-static const int kFirstObjectSlotFromFp = -4;  // Used by GC to traverse stack.
-static const int kLastFixedObjectSlotFromFp = -3;
-
-static const int kSavedCallerFpSlotFromFp = -1;
-static const int kSavedCallerPpSlotFromFp = kSavedCallerFpSlotFromFp;
-static const int kSavedCallerPcSlotFromFp = -2;
-static const int kCallerSpSlotFromFp = -kDartFrameFixedSize - 1;
-static const int kPcMarkerSlotFromFp = -3;
-static const int kFunctionSlotFromFp = -4;
-
-// Note: These constants don't match actual DBC behavior. This is done because
-// setting kFirstLocalSlotFromFp to 0 breaks assumptions spread across the code.
-// Instead for the purposes of local variable allocation we pretend that DBC
-// behaves as other architectures (stack growing downwards) and later fix
-// these indices during code generation in the backend.
-static const int kParamEndSlotFromFp = 4;  // One slot past last parameter.
-static const int kFirstLocalSlotFromFp = -1;
-static const int kLastParamSlotFromEntrySp = 0;  // Should not be used on DBC.
-
-DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
-                                                intptr_t var_index) {
-  if (var_index > 0) {
-    return fp_offset - var_index;
-  } else {
-    return fp_offset - (var_index + 1);
-  }
-}
-
-DART_FORCE_INLINE static uword ParamAddress(uword fp, intptr_t reverse_index) {
-  return fp - (kDartFrameFixedSize + reverse_index) * kWordSize;
-}
-
-DART_FORCE_INLINE static bool IsCalleeFrameOf(uword fp, uword other_fp) {
-  return other_fp > fp;
-}
-
-DART_FORCE_INLINE static bool IsBytecodeCalleeFrameOf(uword fp,
-                                                      uword other_fp) {
-  UNREACHABLE();
-  return false;
-}
-
-static const int kExitLinkSlotFromEntryFp = 0;
-
-// Value for stack limit that is used to cause an interrupt.
-// Note that on DBC stack is growing upwards so interrupt limit is 0 unlike
-// on all other architectures.
-static const uword kInterruptStackLimit = 0;
-
-// TODO(37140): For FFI native -> Dart callbacks, the number of stack slots
-// between arguments passed on stack and arguments saved in callback prologue.
-constexpr intptr_t kCallbackSlotsBeforeSavedArguments = -1;
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_STACK_FRAME_DBC_H_
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 097510e..739e4fd 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -103,7 +103,6 @@
 }
 
 bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(HasBeenInitialized());
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_enable_interpreter) {
@@ -124,33 +123,16 @@
   uword entry = StubCode::InvokeDartCode().EntryPoint();
   uword size = StubCode::InvokeDartCodeSize();
   return (pc >= entry) && (pc < (entry + size));
-#else
-  if (FLAG_enable_interpreter) {
-    FATAL(
-        "Simultaneous usage of DBC simulator "
-        "and interpreter not yet supported.");
-  }
-  // On DBC we use a special marker PC to signify entry frame because there is
-  // no such thing as invocation stub.
-  return (pc & 2) != 0;
-#endif
 }
 
 bool StubCode::InJumpToFrameStub(uword pc) {
-#if !defined(TARGET_ARCH_DBC)
   ASSERT(HasBeenInitialized());
   uword entry = StubCode::JumpToFrame().EntryPoint();
   uword size = StubCode::JumpToFrameSize();
   return (pc >= entry) && (pc < (entry + size));
-#else
-  // This stub does not exist on DBC.
-  return false;
-#endif
 }
 
 RawCode* StubCode::GetAllocationStubForClass(const Class& cls) {
-// These stubs are not used by DBC.
-#if !defined(TARGET_ARCH_DBC)
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   const Error& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
@@ -231,12 +213,9 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   return stub.raw();
-#endif  // !DBC
-  UNIMPLEMENTED();
-  return Code::null();
 }
 
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
 RawCode* StubCode::GetBuildMethodExtractorStub(
     compiler::ObjectPoolBuilder* pool) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -283,11 +262,9 @@
   return nullptr;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
-#endif  // !defined(TARGET_ARCH_DBC)
+#endif  // !defined(TARGET_ARCH_IA32)
 
 const Code& StubCode::UnoptimizedStaticCallEntry(intptr_t num_args_tested) {
-// These stubs are not used by DBC.
-#if !defined(TARGET_ARCH_DBC)
   switch (num_args_tested) {
     case 0:
       return ZeroArgsUnoptimizedStaticCall();
@@ -299,9 +276,6 @@
       UNIMPLEMENTED();
       return Code::Handle();
   }
-#else
-  return Code::Handle();
-#endif
 }
 
 const char* StubCode::NameOfStub(uword entry_point) {
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 6de3ae4..cf832cb 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -59,7 +59,7 @@
 
   static RawCode* GetAllocationStubForClass(const Class& cls);
 
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
   static RawCode* GetBuildMethodExtractorStub(
       compiler::ObjectPoolBuilder* pool);
 #endif
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 0ca76d2..ba767d0 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -9,7 +9,6 @@
 
 // List of stubs created in the VM isolate, these stubs are shared by different
 // isolates running in this dart process.
-#if !defined(TARGET_ARCH_DBC)
 #define VM_STUB_CODE_LIST(V)                                                   \
   V(GetCStackPointer)                                                          \
   V(JumpToFrame)                                                               \
@@ -80,30 +79,6 @@
   V(ExitSafepoint)                                                             \
   V(CallNativeThroughSafepoint)
 
-#else
-#define VM_STUB_CODE_LIST(V)                                                   \
-  V(LazyCompile)                                                               \
-  V(OptimizeFunction)                                                          \
-  V(CallClosureNoSuchMethod)                                                   \
-  V(RunExceptionHandler)                                                       \
-  V(DeoptForRewind)                                                            \
-  V(FixCallersTarget)                                                          \
-  V(Deoptimize)                                                                \
-  V(DeoptimizeLazyFromReturn)                                                  \
-  V(DeoptimizeLazyFromThrow)                                                   \
-  V(DefaultTypeTest)                                                           \
-  V(TopTypeTypeTest)                                                           \
-  V(TypeRefTypeTest)                                                           \
-  V(UnreachableTypeTest)                                                       \
-  V(SlowTypeTest)                                                              \
-  V(LazySpecializeTypeTest)                                                    \
-  V(FrameAwaitingMaterialization)                                              \
-  V(AsynchronousGapMarker)                                                     \
-  V(InvokeDartCodeFromBytecode)                                                \
-  V(InterpretCall)
-
-#endif  // !defined(TARGET_ARCH_DBC)
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STUB_CODE_LIST_H_
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index cdbd809..10c22d1 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -207,6 +207,7 @@
   V(MoveNext, "moveNext")                                                      \
   V(Namespace, "Namespace")                                                    \
   V(Native, "native")                                                          \
+  V(Never, "Never")                                                            \
   V(NoSuchMethod, "noSuchMethod")                                              \
   V(NoSuchMethodError, "NoSuchMethodError")                                    \
   V(NotInitialized, "<not initialized>")                                       \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 688e886..c79be7b 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -60,6 +60,7 @@
 Thread::Thread(bool is_vm_isolate)
     : ThreadState(false),
       stack_limit_(0),
+      saved_stack_limit_(0),
       stack_overflow_flags_(0),
       write_barrier_mask_(RawObject::kGenerationalBarrierMask),
       isolate_(NULL),
@@ -89,7 +90,6 @@
       no_safepoint_scope_depth_(0),
 #endif
       reusable_handles_(),
-      saved_stack_limit_(0),
       defer_oob_messages_count_(0),
       deferred_interrupts_mask_(0),
       deferred_interrupts_(0),
@@ -951,7 +951,7 @@
   const int32_t id = array.Length() - 1;
 
   // Allocate a native callback trampoline if necessary.
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+#if !defined(DART_PRECOMPILED_RUNTIME)
   if (NativeCallbackTrampolines::Enabled()) {
     auto* const tramps = isolate()->native_callback_trampolines();
     ASSERT(tramps->next_callback_id() == id);
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index a982438..2469d30 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -95,9 +95,6 @@
   V(TypeArguments)                                                             \
   V(TypeParameter)
 
-#if defined(TARGET_ARCH_DBC)
-#define CACHED_VM_STUBS_LIST(V)
-#else
 #define CACHED_VM_STUBS_LIST(V)                                                \
   V(RawCode*, write_barrier_code_, StubCode::WriteBarrier().raw(), NULL)       \
   V(RawCode*, array_write_barrier_code_, StubCode::ArrayWriteBarrier().raw(),  \
@@ -133,8 +130,6 @@
   V(RawCode*, call_native_through_safepoint_stub_,                             \
     StubCode::CallNativeThroughSafepoint().raw(), NULL)
 
-#endif
-
 #define CACHED_NON_VM_STUB_LIST(V)                                             \
   V(RawObject*, object_null_, Object::null(), NULL)                            \
   V(RawBool*, bool_true_, Object::bool_true().raw(), NULL)                     \
@@ -152,9 +147,6 @@
   ASSERT((Thread::bool_true_offset() + kWordSize) ==                           \
          Thread::bool_false_offset());
 
-#if defined(TARGET_ARCH_DBC)
-#define CACHED_VM_STUBS_ADDRESSES_LIST(V)
-#else
 #define CACHED_VM_STUBS_ADDRESSES_LIST(V)                                      \
   V(uword, write_barrier_entry_point_, StubCode::WriteBarrier().EntryPoint(),  \
     0)                                                                         \
@@ -178,7 +170,6 @@
   V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)          \
   V(uword, call_native_through_safepoint_entry_point_,                         \
     StubCode::CallNativeThroughSafepoint().EntryPoint(), 0)
-#endif
 
 #define CACHED_ADDRESSES_LIST(V)                                               \
   CACHED_VM_STUBS_ADDRESSES_LIST(V)                                            \
@@ -269,8 +260,9 @@
   void SetStackLimit(uword value);
   void ClearStackLimit();
 
-  // Access to the current stack limit for generated code.  This may be
-  // overwritten with a special value to trigger interrupts.
+  // Access to the current stack limit for generated code. Either the true OS
+  // thread's stack limit minus some headroom, or a special value to trigger
+  // interrupts.
   uword stack_limit_address() const {
     return reinterpret_cast<uword>(&stack_limit_);
   }
@@ -278,7 +270,10 @@
     return OFFSET_OF(Thread, stack_limit_);
   }
 
-  // The true stack limit for this isolate.
+  // The true stack limit for this OS thread.
+  static intptr_t saved_stack_limit_offset() {
+    return OFFSET_OF(Thread, saved_stack_limit_);
+  }
   uword saved_stack_limit() const { return saved_stack_limit_; }
 
 #if defined(USING_SAFE_STACK)
@@ -291,11 +286,6 @@
     return OFFSET_OF(Thread, saved_shadow_call_stack_);
   }
 
-#if defined(TARGET_ARCH_DBC)
-  // Access to the current stack limit for DBC interpreter.
-  uword stack_limit() const { return stack_limit_; }
-#endif
-
   // Stack overflow flags
   enum {
     kOsrRequest = 0x1,  // Current stack overflow caused by OSR request.
@@ -314,13 +304,11 @@
     return ++stack_overflow_count_;
   }
 
-#if !defined(TARGET_ARCH_DBC)
   static uword stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
     return fpu_regs
                ? stack_overflow_shared_with_fpu_regs_entry_point_offset()
                : stack_overflow_shared_without_fpu_regs_entry_point_offset();
   }
-#endif
 
   static intptr_t safepoint_state_offset() {
     return OFFSET_OF(Thread, safepoint_state_);
@@ -670,13 +658,13 @@
    *   kThreadInNative - The thread is running native code.
    *   kThreadInBlockedState - The thread is blocked waiting for a resource.
    */
-  static bool IsAtSafepoint(uint32_t state) {
+  static bool IsAtSafepoint(uword state) {
     return AtSafepointField::decode(state);
   }
   bool IsAtSafepoint() const {
     return AtSafepointField::decode(safepoint_state_);
   }
-  static uint32_t SetAtSafepoint(bool value, uint32_t state) {
+  static uword SetAtSafepoint(bool value, uword state) {
     return AtSafepointField::update(value, state);
   }
   void SetAtSafepoint(bool value) {
@@ -686,21 +674,20 @@
   bool IsSafepointRequested() const {
     return SafepointRequestedField::decode(safepoint_state_);
   }
-  static uint32_t SetSafepointRequested(bool value, uint32_t state) {
+  static uword SetSafepointRequested(bool value, uword state) {
     return SafepointRequestedField::update(value, state);
   }
-  uint32_t SetSafepointRequested(bool value) {
+  uword SetSafepointRequested(bool value) {
     ASSERT(thread_lock()->IsOwnedByCurrentThread());
-    uint32_t old_state;
-    uint32_t new_state;
-    do {
-      old_state = safepoint_state_;
-      new_state = SafepointRequestedField::update(value, old_state);
-    } while (AtomicOperations::CompareAndSwapWord(&safepoint_state_, old_state,
-                                                  new_state) != old_state);
-    return old_state;
+    if (value) {
+      return safepoint_state_.fetch_or(SafepointRequestedField::encode(true),
+                                       std::memory_order_relaxed);
+    } else {
+      return safepoint_state_.fetch_and(~SafepointRequestedField::encode(true),
+                                        std::memory_order_relaxed);
+    }
   }
-  static bool IsBlockedForSafepoint(uint32_t state) {
+  static bool IsBlockedForSafepoint(uword state) {
     return BlockedForSafepointField::decode(state);
   }
   bool IsBlockedForSafepoint() const {
@@ -714,7 +701,7 @@
   bool BypassSafepoints() const {
     return BypassSafepointsField::decode(safepoint_state_);
   }
-  static uint32_t SetBypassSafepoints(bool value, uint32_t state) {
+  static uword SetBypassSafepoints(bool value, uword state) {
     return BypassSafepointsField::update(value, state);
   }
 
@@ -744,12 +731,10 @@
   static uword safepoint_state_acquired() { return SetAtSafepoint(true, 0); }
 
   bool TryEnterSafepoint() {
-    uint32_t new_state = SetAtSafepoint(true, 0);
-    if (AtomicOperations::CompareAndSwapWord(&safepoint_state_, 0, new_state) !=
-        0) {
-      return false;
-    }
-    return true;
+    uword old_state = 0;
+    uword new_state = SetAtSafepoint(true, 0);
+    return safepoint_state_.compare_exchange_strong(old_state, new_state,
+                                                    std::memory_order_acq_rel);
   }
 
   void EnterSafepoint() {
@@ -764,12 +749,10 @@
   }
 
   bool TryExitSafepoint() {
-    uint32_t old_state = SetAtSafepoint(true, 0);
-    if (AtomicOperations::CompareAndSwapWord(&safepoint_state_, old_state, 0) !=
-        old_state) {
-      return false;
-    }
-    return true;
+    uword old_state = SetAtSafepoint(true, 0);
+    uword new_state = 0;
+    return safepoint_state_.compare_exchange_strong(old_state, new_state,
+                                                    std::memory_order_acq_rel);
   }
 
   void ExitSafepoint() {
@@ -853,6 +836,7 @@
   // We use only word-sized fields to avoid differences in struct packing on the
   // different architectures. See also CheckOffsets in dart.cc.
   uword stack_limit_;
+  uword saved_stack_limit_;
   uword stack_overflow_flags_;
   uword write_barrier_mask_;
   Isolate* isolate_;
@@ -897,7 +881,7 @@
   uword resume_pc_;
   uword saved_shadow_call_stack_ = 0;
   uword execution_state_;
-  uword safepoint_state_;
+  std::atomic<uword> safepoint_state_;
   RawGrowableObjectArray* ffi_callback_code_;
 
   // ---- End accessed from generated code. ----
@@ -918,7 +902,6 @@
   int32_t no_safepoint_scope_depth_;
 #endif
   VMHandles reusable_handles_;
-  uword saved_stack_limit_;
   intptr_t defer_oob_messages_count_;
   uint16_t deferred_interrupts_mask_;
   uint16_t deferred_interrupts_;
@@ -951,10 +934,10 @@
 #endif  // defined(DEBUG)
 
   // Generated code assumes that AtSafepointField is the LSB.
-  class AtSafepointField : public BitField<uint32_t, bool, 0, 1> {};
-  class SafepointRequestedField : public BitField<uint32_t, bool, 1, 1> {};
-  class BlockedForSafepointField : public BitField<uint32_t, bool, 2, 1> {};
-  class BypassSafepointsField : public BitField<uint32_t, bool, 3, 1> {};
+  class AtSafepointField : public BitField<uword, bool, 0, 1> {};
+  class SafepointRequestedField : public BitField<uword, bool, 1, 1> {};
+  class BlockedForSafepointField : public BitField<uword, bool, 2, 1> {};
+  class BypassSafepointsField : public BitField<uword, bool, 3, 1> {};
 
 #if defined(USING_SAFE_STACK)
   uword saved_safestack_limit_;
diff --git a/runtime/vm/thread_pool.cc b/runtime/vm/thread_pool.cc
index 6f43097..8353648 100644
--- a/runtime/vm/thread_pool.cc
+++ b/runtime/vm/thread_pool.cc
@@ -343,6 +343,7 @@
 }
 
 void ThreadPool::Worker::SetTask(std::unique_ptr<Task> task) {
+  std::atomic_thread_fence(std::memory_order_release);
   MonitorLocker ml(&monitor_);
   ASSERT(task_ == nullptr);
   task_ = std::move(task);
@@ -377,6 +378,7 @@
 
     // Release monitor while handling the task.
     ml.Exit();
+    std::atomic_thread_fence(std::memory_order_acquire);
     task->Run();
     ASSERT(Isolate::Current() == NULL);
     task.reset();
@@ -422,9 +424,6 @@
   ThreadId id = os_thread->id();
   ThreadPool* pool;
 
-  // Set the thread's stack_base based on the current stack pointer.
-  os_thread->RefineStackBoundsFromSP(OSThread::GetCurrentStackPointer());
-
   {
     MonitorLocker ml(&worker->monitor_);
     ASSERT(worker->task_);
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index edbc632..b11f669 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -398,7 +398,7 @@
                  const Array& ic_datas,
                  Monitor* monitor,
                  intptr_t* exited,
-                 bool* done)
+                 std::atomic<bool>* done)
       : isolate_(isolate),
         ic_datas_(ic_datas),
         len_(ic_datas.Length()),
@@ -430,7 +430,7 @@
           }
         }
 
-        if (AtomicOperations::LoadAcquire(done_)) {
+        if (done_->load(std::memory_order_acquire)) {
           break;
         }
 
@@ -452,7 +452,7 @@
   const intptr_t len_;
   Monitor* monitor_;
   intptr_t* exited_;  // # tasks that are no longer running.
-  bool* done_;        // Signal that helper threads can stop working.
+  std::atomic<bool>* done_;  // Signal that helper threads can stop working.
 };
 
 static Function* CreateFunction(const char* name) {
@@ -479,7 +479,7 @@
   USE(isolate);
   Monitor monitor;
   intptr_t exited = 0;
-  bool done = false;
+  std::atomic<bool> done = {false};
 
   const intptr_t kNumICData = 0x10;
 
@@ -517,7 +517,7 @@
   }
   // Ensure we looped long enough to allow all helpers to succeed and exit.
   {
-    AtomicOperations::StoreRelease(&done, true);
+    done.store(true, std::memory_order_release);
     MonitorLocker ml(&monitor);
     while (exited != ICDataTestTask::kTaskCount) {
       ml.Wait();
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 775d1ae..c11f219 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -116,7 +116,7 @@
 
 #if defined(HOST_OS_LINUX) || defined(HOST_OS_ANDROID)
       return new TimelineEventSystraceRecorder();
-#elif defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#elif defined(HOST_OS_FUCHSIA)
       return new TimelineEventFuchsiaRecorder();
 #else
       OS::PrintErr(
@@ -1110,7 +1110,7 @@
 
 int64_t TimelineEventRecorder::GetNextAsyncId() {
   // TODO(johnmccutchan): Gracefully handle wrap around.
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(HOST_OS_FUCHSIA)
   return trace_generate_nonce();
 #else
   uint32_t next = static_cast<uint32_t>(async_id_.fetch_add(1u));
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 2239982..5cb05a5 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -15,7 +15,10 @@
 #include "vm/os.h"
 #include "vm/os_thread.h"
 
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(FUCHSIA_SDK)
+#include <lib/trace-engine/context.h>
+#include <lib/trace-engine/instrumentation.h>
+#elif defined(HOST_OS_FUCHSIA)
 #include <trace-engine/context.h>
 #include <trace-engine/instrumentation.h>
 #endif
@@ -66,7 +69,7 @@
   const char* fuchsia_name() const { return fuchsia_name_; }
 
   bool enabled() {
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(HOST_OS_FUCHSIA)
 #ifdef PRODUCT
     return trace_is_category_enabled(fuchsia_name_);
 #else
@@ -74,7 +77,7 @@
 #endif  // PRODUCT
 #else
     return enabled_ != 0;
-#endif  // defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#endif  // defined(HOST_OS_FUCHSIA)
   }
 
   void set_enabled(bool enabled) { enabled_ = enabled ? 1 : 0; }
@@ -89,7 +92,7 @@
     return OFFSET_OF(TimelineStream, enabled_);
   }
 
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(HOST_OS_FUCHSIA)
   trace_site_t* trace_site() { return &trace_site_; }
 #endif
 
@@ -101,7 +104,7 @@
   // 0 or 1. If this becomes a BitField, the generated code must be updated.
   uintptr_t enabled_;
 
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(HOST_OS_FUCHSIA)
   trace_site_t trace_site_ = {};
 #endif
 };
@@ -918,7 +921,7 @@
   void CompleteEvent(TimelineEvent* event);
 };
 
-#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
+#if defined(HOST_OS_FUCHSIA)
 // A recorder that sends events to Fuchsia's tracing app.
 class TimelineEventFuchsiaRecorder : public TimelineEventPlatformRecorder {
  public:
diff --git a/runtime/vm/timeline_fuchsia.cc b/runtime/vm/timeline_fuchsia.cc
index fde26e5..3274603 100644
--- a/runtime/vm/timeline_fuchsia.cc
+++ b/runtime/vm/timeline_fuchsia.cc
@@ -3,11 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include "vm/globals.h"
-#if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE) &&                   \
-    !defined(FUCHSIA_SDK)
-
+#if defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE)
+#if defined(FUCHSIA_SDK)
+#include <lib/trace-engine/context.h>
+#include <lib/trace-engine/instrumentation.h>
+#else
 #include <trace-engine/context.h>
 #include <trace-engine/instrumentation.h>
+#endif  // defined(FUCHSIA_SDK)
 #include <zircon/syscalls.h>
 
 #include "platform/utils.h"
@@ -123,4 +126,4 @@
 
 }  // namespace dart
 
-#endif  // defined(HOST_OS_FUCHSIA) && !defined(PRODUCT)
+#endif  // defined(HOST_OS_FUCHSIA) && defined(SUPPORT_TIMELINE)
diff --git a/runtime/vm/type_table.h b/runtime/vm/type_table.h
index 518491b..e9c21a2 100644
--- a/runtime/vm/type_table.h
+++ b/runtime/vm/type_table.h
@@ -22,7 +22,7 @@
   DISALLOW_ALLOCATION();
 };
 
-// Traits for looking up Canonical Type based on it's hash.
+// Traits for looking up Canonical Type based on its hash.
 class CanonicalTypeTraits {
  public:
   static const char* Name() { return "CanonicalTypeTraits"; }
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index d4195bd..eff9fd1 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -96,19 +96,25 @@
     const AbstractType& type,
     bool lazy_specialize /* = true */) {
   // During bootstrapping we have no access to stubs yet, so we'll just return
-  // `null` and patch these later in `Object::FinishInitOnce()`.
+  // `null` and patch these later in `Object::FinishInit()`.
   if (!StubCode::HasBeenInitialized()) {
     ASSERT(type.IsType());
     const intptr_t cid = Type::Cast(type).type_class_id();
-    ASSERT(cid == kDynamicCid || cid == kVoidCid);
+    ASSERT(cid == kDynamicCid || cid == kVoidCid | cid == kNeverCid);
     return Code::null();
   }
 
+  // TODO(regis): Revisit when type checking mode is not kUnaware anymore.
   if (type.raw() == Type::ObjectType() || type.raw() == Type::DynamicType() ||
       type.raw() == Type::VoidType()) {
     return StubCode::TopTypeTypeTest().raw();
   }
 
+  if (type.raw() == Type::NeverType()) {
+    // TODO(regis): Revisit.
+    return StubCode::StubCode::DefaultTypeTest().raw();
+  }
+
   if (type.IsTypeRef()) {
     return StubCode::TypeRefTypeTest().raw();
   }
@@ -138,7 +144,7 @@
 
 RawCode* TypeTestingStubGenerator::OptimizedCodeForType(
     const AbstractType& type) {
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
   ASSERT(StubCode::HasBeenInitialized());
 
   if (type.IsTypeRef()) {
@@ -168,11 +174,11 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
     }
   }
-#endif  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#endif  // !defined(TARGET_ARCH_IA32)
   return TypeTestingStubGenerator::DefaultCodeForType(type, false);
 }
 
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
 RawCode* TypeTestingStubGenerator::BuildCodeForType(const Type& type) {
@@ -546,7 +552,7 @@
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-#else  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#else  // !defined(TARGET_ARCH_IA32)
 
 void RegisterTypeArgumentsUse(const Function& function,
                               TypeUsageInfo* type_usage_info,
@@ -556,7 +562,7 @@
   UNREACHABLE();
 }
 
-#endif  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#endif  // !defined(TARGET_ARCH_IA32)
 
 #undef __
 
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index b0a772d..65c9bd2 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -51,7 +51,7 @@
   RawCode* OptimizedCodeForType(const AbstractType& type);
 
  private:
-#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#if !defined(TARGET_ARCH_IA32)
 #if !defined(DART_PRECOMPILED_RUNTIME)
   RawCode* BuildCodeForType(const Type& type);
   static void BuildOptimizedTypeTestStub(compiler::Assembler* assembler,
@@ -116,7 +116,7 @@
       compiler::Label* check_failed);
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-#endif  // !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+#endif  // !defined(TARGET_ARCH_IA32)
 
   TypeTestingStubNamer namer_;
   ObjectStore* object_store_;
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index c8e96b9..66addfe 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -114,9 +114,9 @@
   Isolate::FlagsInitialize(&api_flags);
   Dart_Isolate isolate = NULL;
   if (len == 0) {
-    isolate = Dart_CreateIsolateGroup(name, NULL, data_buffer, instr_buffer,
-                                      NULL, NULL, &api_flags, group_data,
-                                      isolate_data, &err);
+    isolate =
+        Dart_CreateIsolateGroup(name, NULL, data_buffer, instr_buffer,
+                                &api_flags, group_data, isolate_data, &err);
   } else {
     isolate = Dart_CreateIsolateGroupFromKernel(name, NULL, data_buffer, len,
                                                 &api_flags, group_data,
@@ -359,11 +359,6 @@
     }
     return Dart_DefaultCanonicalizeUrl(library_url, url);
   }
-  if (tag == Dart_kScriptTag) {
-    // Reload request.
-    UNREACHABLE();
-    return Dart_Null();
-  }
   if (!Dart_IsLibrary(library)) {
     return Dart_NewApiError("not a library");
   }
@@ -428,14 +423,8 @@
   // Do sync loading since unit_test doesn't support async.
   Dart_Handle source = DartUtils::ReadStringFromFile(resolved_url_chars);
   EXPECT_VALID(source);
-  if (tag == Dart_kImportTag) {
-    UNREACHABLE();
-    return Dart_Null();
-  } else {
-    ASSERT(tag == Dart_kSourceTag);
-    UNREACHABLE();
-    return Dart_Null();
-  }
+  UNREACHABLE();
+  return Dart_Null();
 }
 
 static intptr_t BuildSourceFilesArray(
@@ -707,11 +696,10 @@
       String::ZoneHandle(Symbols::New(Thread::Current(), name_));
 
   // We make a dummy script so that exception objects can be composed for
-  // assembler instructions that do runtime calls, in particular on DBC.
+  // assembler instructions that do runtime calls.
   const char* kDummyScript = "assembler_test_dummy_function() {}";
   const Script& script = Script::Handle(
-      Script::New(function_name, String::Handle(String::New(kDummyScript)),
-                  RawScript::kSourceTag));
+      Script::New(function_name, String::Handle(String::New(kDummyScript))));
   const Library& lib = Library::Handle(Library::CoreLibrary());
   const Class& cls = Class::ZoneHandle(
       Class::New(lib, function_name, script, TokenPosition::kMinSource));
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index af1e38e..947cd15 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -481,7 +481,7 @@
 // using the ABI calling convention.
 // ResultType is the return type of the assembler test function.
 // ArgNType is the type of the Nth argument.
-#if defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
+#if defined(USING_SIMULATOR)
 
 #if defined(ARCH_IS_64_BIT)
   // TODO(fschneider): Make InvokeWithCodeAndThread<> more general and work on
@@ -532,29 +532,6 @@
         reinterpret_cast<intptr_t>(arg2), reinterpret_cast<intptr_t>(arg3), 0,
         fp_return, fp_args);
   }
-#elif defined(USING_SIMULATOR) && defined(TARGET_ARCH_DBC)
-  template <typename ResultType,
-            typename Arg1Type,
-            typename Arg2Type,
-            typename Arg3Type>
-  ResultType Invoke(Arg1Type arg1, Arg2Type arg2, Arg3Type arg3) {
-    // TODO(fschneider): Support double arguments for simulator calls.
-    COMPILE_ASSERT(is_void<ResultType>::value);
-    COMPILE_ASSERT(!is_double<Arg1Type>::value);
-    COMPILE_ASSERT(!is_double<Arg2Type>::value);
-    COMPILE_ASSERT(!is_double<Arg3Type>::value);
-    const Object& arg1obj = Object::Handle(reinterpret_cast<RawObject*>(arg1));
-    const Object& arg2obj = Object::Handle(reinterpret_cast<RawObject*>(arg2));
-    const intptr_t kTypeArgsLen = 0;
-    const intptr_t kNumArgs = 2;
-    const Array& argdesc =
-        Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArgs));
-    const Array& arguments = Array::Handle(Array::New(2));
-    arguments.SetAt(0, arg1obj);
-    arguments.SetAt(1, arg2obj);
-    Simulator::Current()->Call(code(), argdesc, arguments,
-                               reinterpret_cast<Thread*>(arg3));
-  }
 #else
   template <typename ResultType>
   ResultType InvokeWithCodeAndThread() {
@@ -580,7 +557,7 @@
     typedef ResultType (*FunctionType)(Arg1Type, Arg2Type, Arg3Type);
     return reinterpret_cast<FunctionType>(entry())(arg1, arg2, arg3);
   }
-#endif  // defined(USING_SIMULATOR) && !defined(TARGET_ARCH_DBC)
+#endif  // defined(USING_SIMULATOR)
 
   // Assemble test and set code_.
   void Assemble();
diff --git a/runtime/vm/utils_test.cc b/runtime/vm/utils_test.cc
index a115a4f..85ff6d4 100644
--- a/runtime/vm/utils_test.cc
+++ b/runtime/vm/utils_test.cc
@@ -323,4 +323,31 @@
   EXPECT(Utils::DoublesBitEqual(NAN, NAN));
 }
 
+VM_UNIT_TEST_CASE(NBitMask) {
+#if defined(ARCH_IS_64_BIT)
+  EXPECT_EQ(0ull, Utils::NBitMask(0));
+  EXPECT_EQ(0x1ull, Utils::NBitMask(1));
+  EXPECT_EQ(0x3ull, Utils::NBitMask(2));
+  EXPECT_EQ(0xfull, Utils::NBitMask(4));
+  EXPECT_EQ(0xffull, Utils::NBitMask(8));
+  EXPECT_EQ(0xffffull, Utils::NBitMask(16));
+  EXPECT_EQ(0x1ffffull, Utils::NBitMask(17));
+  EXPECT_EQ(0x7fffffffull, Utils::NBitMask(31));
+  EXPECT_EQ(0xffffffffull, Utils::NBitMask(32));
+  EXPECT_EQ(0x1ffffffffull, Utils::NBitMask(33));
+  EXPECT_EQ(0x7fffffffffffffffull, Utils::NBitMask(kBitsPerWord - 1));
+  EXPECT_EQ(0xffffffffffffffffull, Utils::NBitMask(kBitsPerWord));
+#else
+  EXPECT_EQ(0u, Utils::NBitMask(0));
+  EXPECT_EQ(0x1u, Utils::NBitMask(1));
+  EXPECT_EQ(0x3u, Utils::NBitMask(2));
+  EXPECT_EQ(0xfu, Utils::NBitMask(4));
+  EXPECT_EQ(0xffu, Utils::NBitMask(8));
+  EXPECT_EQ(0xffffu, Utils::NBitMask(16));
+  EXPECT_EQ(0x1ffffu, Utils::NBitMask(17));
+  EXPECT_EQ(0x7fffffffu, Utils::NBitMask(kBitsPerWord - 1));
+  EXPECT_EQ(0xffffffffu, Utils::NBitMask(kBitsPerWord));
+#endif
+}
+
 }  // namespace dart
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index bf4fed7..22a6b4d 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -169,10 +169,6 @@
                                               intptr_t alignment,
                                               bool is_executable,
                                               const char* name) {
-#if defined(TARGET_ARCH_DBC)
-  RELEASE_ASSERT(!is_executable);
-#endif
-
   // When FLAG_write_protect_code is active, code memory (indicated by
   // is_executable = true) is allocated as non-executable and later
   // changed to executable via VirtualMemory::Protect.
@@ -265,9 +261,6 @@
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
-#if defined(TARGET_ARCH_DBC)
-  RELEASE_ASSERT((mode != kReadExecute) && (mode != kReadWriteExecute));
-#endif
 #if defined(DEBUG)
   Thread* thread = Thread::Current();
   ASSERT((thread == nullptr) || thread->IsMutatorThread() ||
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index b692ab4..1a6c0de 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -39,7 +39,6 @@
   "code_patcher.h",
   "code_patcher_arm.cc",
   "code_patcher_arm64.cc",
-  "code_patcher_dbc.cc",
   "code_patcher_ia32.cc",
   "code_patcher_kbc.cc",
   "code_patcher_x64.cc",
@@ -49,8 +48,6 @@
   "constants_arm.h",
   "constants_arm64.cc",
   "constants_arm64.h",
-  "constants_dbc.cc",
-  "constants_dbc.h",
   "constants_ia32.cc",
   "constants_ia32.h",
   "constants_kbc.cc",
@@ -60,7 +57,6 @@
   "cpu.h",
   "cpu_arm.cc",
   "cpu_arm64.cc",
-  "cpu_dbc.cc",
   "cpu_ia32.cc",
   "cpu_x64.cc",
   "cpuid.cc",
@@ -86,7 +82,6 @@
   "debugger.h",
   "debugger_arm.cc",
   "debugger_arm64.cc",
-  "debugger_dbc.cc",
   "debugger_ia32.cc",
   "debugger_kbc.cc",
   "debugger_x64.cc",
@@ -127,8 +122,6 @@
   "instructions_arm.h",
   "instructions_arm64.cc",
   "instructions_arm64.h",
-  "instructions_dbc.cc",
-  "instructions_dbc.h",
   "instructions_ia32.cc",
   "instructions_ia32.h",
   "instructions_kbc.cc",
@@ -265,7 +258,6 @@
   "runtime_entry.h",
   "runtime_entry_arm.cc",
   "runtime_entry_arm64.cc",
-  "runtime_entry_dbc.cc",
   "runtime_entry_ia32.cc",
   "runtime_entry_list.h",
   "runtime_entry_x64.cc",
@@ -289,8 +281,6 @@
   "simulator_arm.h",
   "simulator_arm64.cc",
   "simulator_arm64.h",
-  "simulator_dbc.cc",
-  "simulator_dbc.h",
   "snapshot.cc",
   "snapshot.h",
   "snapshot_ids.h",
@@ -300,7 +290,6 @@
   "stack_frame.h",
   "stack_frame_arm.h",
   "stack_frame_arm64.h",
-  "stack_frame_dbc.h",
   "stack_frame_ia32.h",
   "stack_frame_kbc.h",
   "stack_frame_x64.h",
@@ -425,7 +414,6 @@
   "native_entry_test.h",
   "object_arm64_test.cc",
   "object_arm_test.cc",
-  "object_dbc_test.cc",
   "object_graph_test.cc",
   "object_ia32_test.cc",
   "object_id_ring_test.cc",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index bcd37eb..b6d3727 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -92,7 +92,7 @@
   Segment* result = reinterpret_cast<Segment*>(memory->start());
 #ifdef DEBUG
   // Zap the entire allocated segment (including the header).
-  memset(result, kZapUninitializedByte, size);
+  memset(reinterpret_cast<void*>(result), kZapUninitializedByte, size);
 #endif
   result->next_ = next;
   result->size_ = size;
@@ -114,7 +114,7 @@
     VirtualMemory* memory = current->memory();
 #ifdef DEBUG
     // Zap the entire current segment (including the header).
-    memset(current, kZapDeletedByte, current->size());
+    memset(reinterpret_cast<void*>(current), kZapDeletedByte, current->size());
 #endif
     LSAN_UNREGISTER_ROOT_REGION(current, sizeof(*current));
 
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index edb0cb8..7115cc71 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -123,7 +123,8 @@
 #ifdef DEBUG
     if (len > 0) {
       ASSERT(old_array != nullptr);
-      memset(old_array, kZapUninitializedByte, len * sizeof(ElementType));
+      memset(static_cast<void*>(old_array), kZapUninitializedByte,
+             len * sizeof(ElementType));
     }
 #endif
   }
diff --git a/samples/ffi/coordinate.dart b/samples/ffi/coordinate.dart
index 2246f03..c5d96a2 100644
--- a/samples/ffi/coordinate.dart
+++ b/samples/ffi/coordinate.dart
@@ -2,11 +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.
 
-library FfiTest;
-
 import 'dart:ffi';
 
-import 'package:ffi/ffi.dart' as ffi;
+import "package:ffi/ffi.dart";
 
 /// Sample struct for dart:ffi library.
 class Coordinate extends Struct {
@@ -18,20 +16,10 @@
 
   Pointer<Coordinate> next;
 
-  // Implementation generated by @ffi.struct annotation.
-  external static int sizeOf();
-
-  Coordinate elementAt(int index) => addressOf.elementAt(index).ref;
-
-  static Coordinate allocate({int count: 1}) =>
-      ffi.allocate<Coordinate>(count: count).ref;
-
-  /// Allocate a new [Coordinate] in C memory and populate its fields.
-  factory Coordinate(double x, double y, Coordinate next) {
-    Coordinate result = Coordinate.allocate()
+  factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
+    return allocate<Coordinate>().ref
       ..x = x
       ..y = y
-      ..next = next.addressOf;
-    return result;
+      ..next = next;
   }
 }
diff --git a/samples/ffi/dylib_utils.dart b/samples/ffi/dylib_utils.dart
index 1c924d4..7304a7e 100644
--- a/samples/ffi/dylib_utils.dart
+++ b/samples/ffi/dylib_utils.dart
@@ -2,18 +2,19 @@
 // for 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' as ffi;
+import 'dart:ffi';
 import 'dart:io' show Platform;
 
 String _platformPath(String name, {String path}) {
   if (path == null) path = "";
-  if (Platform.isLinux) return path + "lib" + name + ".so";
+  if (Platform.isLinux || Platform.isAndroid)
+    return path + "lib" + name + ".so";
   if (Platform.isMacOS) return path + "lib" + name + ".dylib";
   if (Platform.isWindows) return path + name + ".dll";
   throw Exception("Platform not implemented");
 }
 
-ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
+DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
   String fullPath = _platformPath(name, path: path);
-  return ffi.DynamicLibrary.open(fullPath);
+  return DynamicLibrary.open(fullPath);
 }
diff --git a/samples/ffi/sample_ffi_bitfield.dart b/samples/ffi/sample_ffi_bitfield.dart
new file mode 100644
index 0000000..0d91d47
--- /dev/null
+++ b/samples/ffi/sample_ffi_bitfield.dart
@@ -0,0 +1,123 @@
+// 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:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:expect/expect.dart';
+
+/// typedef struct {
+///     unsigned int bold      : 1;
+///     unsigned int underline : 2;
+///     unsigned int italic    : 1;
+///     unsigned int blink     : 1;
+///     unsigned int reverse   : 1;
+///     unsigned int strike    : 1;
+///     unsigned int font      : 4;
+/// } ScreenCellAttrs;
+class ScreenCellAttrs extends Struct {
+  @Int16()
+  int bits;
+
+  int get bold => getBits(kBoldFieldOffset, kBoldFieldLength);
+  void set bold(int value) =>
+      setBits(kBoldFieldOffset, kBoldFieldLength, value);
+
+  int get underline => getBits(kUnderlineFieldOffset, kUnderlineFieldLength);
+  void set underline(int value) =>
+      setBits(kUnderlineFieldOffset, kUnderlineFieldLength, value);
+
+  int get italic => getBits(kItalicFieldOffset, kItalicFieldLength);
+  void set italic(int value) =>
+      setBits(kItalicFieldOffset, kItalicFieldLength, value);
+
+  int get blink => getBits(kBlinkFieldOffset, kBlinkFieldLength);
+  void set blink(int value) =>
+      setBits(kBlinkFieldOffset, kBlinkFieldLength, value);
+
+  int get reverse => getBits(kReverseFieldOffset, kReverseFieldLength);
+  void set reverse(int value) =>
+      setBits(kReverseFieldOffset, kReverseFieldLength, value);
+
+  int get strike => getBits(kStrikeFieldOffset, kStrikeFieldLength);
+  void set strike(int value) =>
+      setBits(kStrikeFieldOffset, kStrikeFieldLength, value);
+
+  int get font => getBits(kFontFieldOffset, kFontFieldLength);
+  void set font(int value) =>
+      setBits(kFontFieldOffset, kFontFieldLength, value);
+
+  int getBits(int offset, int length) => bits.getBits(offset, length);
+
+  void setBits(int offset, int length, int value) {
+    bits = bits.setBits(offset, length, value);
+  }
+}
+
+const int kBoldFieldOffset = 0;
+const int kBoldFieldLength = 1;
+const int kUnderlineFieldOffset = kBoldFieldOffset + kBoldFieldLength;
+const int kUnderlineFieldLength = 2;
+const int kItalicFieldOffset = kUnderlineFieldOffset + kUnderlineFieldLength;
+const int kItalicFieldLength = 1;
+const int kBlinkFieldOffset = kItalicFieldOffset + kItalicFieldLength;
+const int kBlinkFieldLength = 1;
+const int kReverseFieldOffset = kBlinkFieldOffset + kBlinkFieldLength;
+const int kReverseFieldLength = 1;
+const int kStrikeFieldOffset = kReverseFieldOffset + kReverseFieldLength;
+const int kStrikeFieldLength = 1;
+const int kFontFieldOffset = kStrikeFieldOffset + kStrikeFieldLength;
+const int kFontFieldLength = 4;
+
+/// Extension to use a 64-bit integer as bit field.
+extension IntBitField on int {
+  static int _bitMask(int offset, int lenght) => ((1 << lenght) - 1) << offset;
+
+  /// Read `length` bits at `offset`.
+  ///
+  /// Truncates everything.
+  int getBits(int offset, int length) {
+    final mask = _bitMask(offset, length);
+    return (this & mask) >> offset;
+  }
+
+  /// Returns a new integer value in which `length` bits are overwritten at
+  /// `offset`.
+  ///
+  /// Truncates everything.
+  int setBits(int offset, int length, int value) {
+    final mask = _bitMask(offset, length);
+    return (this & ~mask) | ((value << offset) & mask);
+  }
+}
+
+main() {
+  final p = allocate<ScreenCellAttrs>(count: 3);
+
+  // Zeroes out all fields.
+  p.ref.bits = 0;
+
+  // Set individual fields.
+  p.ref.blink = 0;
+  p.ref.bold = 1;
+  p.ref.font = 15;
+  p.ref.italic = 1;
+  p.ref.reverse = 0;
+  p.ref.strike = 0;
+  p.ref.underline = 2;
+
+  // Read individual fields.
+  print(p.ref.blink);
+  print(p.ref.bold);
+  print(p.ref.font);
+  print(p.ref.italic);
+  print(p.ref.reverse);
+  print(p.ref.strike);
+  print(p.ref.underline);
+
+  // A check for automated testing.
+  Expect.equals(1933, p.ref.bits);
+
+  free(p);
+}
diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart
index 7b34917..8e713d0 100644
--- a/samples/ffi/sample_ffi_data.dart
+++ b/samples/ffi/sample_ffi_data.dart
@@ -5,11 +5,11 @@
 import 'dart:ffi';
 import 'package:ffi/ffi.dart';
 
-main(List<String> arguments) {
+main() {
   print('start main');
 
   {
-    // basic operation: allocate, get, set, and free
+    // Basic operation: allocate, get, set, and free.
     Pointer<Int64> p = allocate();
     p.value = 42;
     int pValue = p.value;
@@ -18,7 +18,7 @@
   }
 
   {
-    // undefined behavior before set
+    // Undefined behavior before set.
     Pointer<Int64> p = allocate();
     int pValue = p.value;
     print('If not set, returns garbage: ${pValue}');
@@ -26,7 +26,7 @@
   }
 
   {
-    // pointers can be created from an address
+    // Pointers can be created from an address.
     Pointer<Int64> pHelper = allocate();
     pHelper.value = 1337;
 
@@ -40,31 +40,31 @@
   }
 
   {
-    // address is zeroed out after free
+    // Address is zeroed out after free.
     Pointer<Int64> p = allocate();
     free(p);
     print('After free, address is zero: ${p.address}');
   }
 
   {
-    // allocating too much throws an exception
+    // Allocating too much throws an exception.
     try {
       int maxMint = 9223372036854775807; // 2^63 - 1
       allocate<Int64>(count: maxMint);
-    } on RangeError {
+    } on Error {
       print('Expected exception on allocating too much');
     }
     try {
       int maxInt1_8 = 1152921504606846975; // 2^60 -1
       allocate<Int64>(count: maxInt1_8);
-    } on ArgumentError {
+    } on Error {
       print('Expected exception on allocating too much');
     }
   }
 
   {
-    // pointers can be cast into another type
-    // resulting in the corresponding bits read
+    // Pointers can be cast into another type,
+    // resulting in the corresponding bits read.
     Pointer<Int64> p1 = allocate();
     p1.value = 9223372036854775807; // 2^63 - 1
 
@@ -78,7 +78,7 @@
   }
 
   {
-    // data can be tightly packed in memory
+    // Data can be tightly packed in memory.
     Pointer<Int8> p = allocate(count: 8);
     for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
       p.elementAt(i).value = i * 3;
@@ -90,20 +90,18 @@
   }
 
   {
-    // exception on storing a value that does not fit
+    // Values that don't fit are truncated.
     Pointer<Int32> p11 = allocate();
 
-    try {
-      p11.value = 9223372036854775807;
-    } on ArgumentError {
-      print('Expected exception on calling set with a value that does not fit');
-    }
+    p11.value = 9223372036854775807;
+
+    print(p11);
 
     free(p11);
   }
 
   {
-    // doubles
+    // Doubles.
     Pointer<Double> p = allocate();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
@@ -113,7 +111,7 @@
   }
 
   {
-    // floats
+    // Floats.
     Pointer<Float> p = allocate();
     p.value = 3.14159265359;
     print('${p.runtimeType} value: ${p.value}');
@@ -123,8 +121,8 @@
   }
 
   {
-    // IntPtr varies in size based on whether the platform is 32 or 64 bit
-    // addresses of pointers fit in this size
+    // 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();
     int p14addr = p.address;
     p.value = p14addr;
@@ -134,36 +132,28 @@
   }
 
   {
-    // void pointers are unsized
-    // the size of the element it is pointing to is undefined
-    // this means they cannot be allocated, read, or written
-    // this would would fail to compile:
-    // allocate<Void>();
+    // Void pointers are unsized.
+    // The size of the element it is pointing to is undefined,
+    // they cannot be allocated, read, or written.
 
     Pointer<IntPtr> p1 = allocate();
     Pointer<Void> p2 = p1.cast();
     print('${p2.runtimeType} address: ${p2.address}');
 
-    // this fails to compile, we cannot read something unsized
-    // p2.load<int>();
-
-    // this fails to compile, we cannot write something unsized
-    // p2.store(1234);
-
     free(p1);
   }
 
   {
-    // pointer to a pointer to something
+    // Pointer to a pointer to something.
     Pointer<Int16> pHelper = allocate();
     pHelper.value = 17;
 
     Pointer<Pointer<Int16>> p = allocate();
 
-    // storing into a pointer pointer automatically unboxes
+    // Storing into a pointer pointer automatically unboxes.
     p.value = pHelper;
 
-    // reading from a pointer pointer automatically boxes
+    // Reading from a pointer pointer automatically boxes.
     Pointer<Int16> pHelper2 = p.value;
     print('${pHelper2.runtimeType} value: ${pHelper2.value}');
 
@@ -175,23 +165,22 @@
   }
 
   {
-    // the pointer to pointer types must match up
+    // The pointer to pointer types must match up.
     Pointer<Int8> pHelper = allocate();
     pHelper.value = 123;
 
     Pointer<Pointer<Int16>> p = allocate();
 
-    // this fails to compile due to type mismatch
-    // p.store(pHelper);
+    // Trying to store `pHelper` into `p.val` would result in a type mismatch.
 
     free(pHelper);
     free(p);
   }
 
   {
-    // null pointer in Dart points to address 0 in c++
+    // `nullptr` points to address 0 in c++.
     Pointer<Pointer<Int8>> pointerToPointer = allocate();
-    Pointer<Int8> value = null;
+    Pointer<Int8> value = nullptr;
     pointerToPointer.value = value;
     value = pointerToPointer.value;
     print("Loading a pointer to the 0 address is null: ${value}");
@@ -199,27 +188,17 @@
   }
 
   {
-    // sizeof returns element size in bytes
+    // The toplevel function sizeOf returns element size in bytes.
     print('sizeOf<Double>(): ${sizeOf<Double>()}');
     print('sizeOf<Int16>(): ${sizeOf<Int16>()}');
     print('sizeOf<IntPtr>(): ${sizeOf<IntPtr>()}');
   }
 
   {
-    // only concrete sub types of NativeType can be allocated
-    // this would fail to compile:
-    // allocate();
-  }
-
-  {
-    // only concrete sub types of NativeType can be asked for size
-    // this would fail to compile:
-    // sizeOf();
-  }
-
-  {
-    // with IntPtr pointers, one can manually setup aribtrary data
+    // With IntPtr pointers, one could manually setup aribtrary data
     // structres in C memory.
+    //
+    // However, it is advised to use Pointer<Pointer<...>> for that.
 
     void createChain(Pointer<IntPtr> head, int length, int value) {
       if (length == 0) {
diff --git a/samples/ffi/sample_ffi_dynamic_library.dart b/samples/ffi/sample_ffi_dynamic_library.dart
index 234e3d0..28772ff 100644
--- a/samples/ffi/sample_ffi_dynamic_library.dart
+++ b/samples/ffi/sample_ffi_dynamic_library.dart
@@ -2,16 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:ffi' as ffi;
+import 'dart:ffi';
 
 import 'dylib_utils.dart';
 
-typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
+typedef NativeDoubleUnOp = Double Function(Double);
 
 typedef DoubleUnOp = double Function(double);
 
-main(List<String> arguments) {
-  ffi.DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
+main() {
+  DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
   print(l);
   print(l.runtimeType);
 
diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart
index 4275b3d..72db3eb 100644
--- a/samples/ffi/sample_ffi_functions.dart
+++ b/samples/ffi/sample_ffi_functions.dart
@@ -2,69 +2,48 @@
 // for 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' as ffi;
+import 'dart:ffi';
 
 import 'package:ffi/ffi.dart';
 
 import 'dylib_utils.dart';
 
-typedef NativeUnaryOp = ffi.Int32 Function(ffi.Int32);
-typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
+typedef NativeUnaryOp = Int32 Function(Int32);
+typedef NativeBinaryOp = Int32 Function(Int32, Int32);
 typedef UnaryOp = int Function(int);
 typedef BinaryOp = int Function(int, int);
 typedef GenericBinaryOp<T> = int Function(int, T);
-typedef NativeQuadOpSigned = ffi.Int64 Function(
-    ffi.Int64, ffi.Int32, ffi.Int16, ffi.Int8);
-typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
-    ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8);
-typedef NativeFunc4 = ffi.IntPtr Function(ffi.IntPtr);
-typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
-typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
-typedef NativeDecenaryOp = ffi.IntPtr Function(
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr,
-    ffi.IntPtr);
-typedef NativeDoubleDecenaryOp = ffi.Double Function(
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double,
-    ffi.Double);
-typedef NativeVigesimalOp = ffi.Double Function(
-    ffi.IntPtr,
-    ffi.Float,
-    ffi.IntPtr,
-    ffi.Double,
-    ffi.IntPtr,
-    ffi.Float,
-    ffi.IntPtr,
-    ffi.Double,
-    ffi.IntPtr,
-    ffi.Float,
-    ffi.IntPtr,
-    ffi.Double,
-    ffi.IntPtr,
-    ffi.Float,
-    ffi.IntPtr,
-    ffi.Double,
-    ffi.IntPtr,
-    ffi.Float,
-    ffi.IntPtr,
-    ffi.Double);
-typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
-    ffi.Pointer<ffi.Int64>);
+typedef NativeQuadOpSigned = Int64 Function(Int64, Int32, Int16, Int8);
+typedef NativeQuadOpUnsigned = Uint64 Function(Uint64, Uint32, Uint16, Uint8);
+typedef NativeFunc4 = IntPtr Function(IntPtr);
+typedef NativeDoubleUnaryOp = Double Function(Double);
+typedef NativeFloatUnaryOp = Float Function(Float);
+typedef NativeDecenaryOp = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr,
+    IntPtr, IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+typedef NativeDoubleDecenaryOp = Double Function(Double, Double, Double, Double,
+    Double, Double, Double, Double, Double, Double);
+typedef NativeVigesimalOp = Double Function(
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double,
+    IntPtr,
+    Float,
+    IntPtr,
+    Double);
+typedef Int64PointerUnOp = Pointer<Int64> Function(Pointer<Int64>);
 typedef QuadOp = int Function(int, int, int, int);
 typedef DoubleUnaryOp = double Function(double);
 typedef DecenaryOp = int Function(
@@ -93,14 +72,14 @@
     int,
     double);
 
-main(List<String> arguments) {
+main() {
   print('start main');
 
-  ffi.DynamicLibrary ffiTestFunctions =
+  DynamicLibrary ffiTestFunctions =
       dlopenPlatformSpecific("ffi_test_functions");
 
   {
-    // int32 bin op
+    // A int32 bin op.
     BinaryOp sumPlus42 =
         ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
 
@@ -110,7 +89,7 @@
   }
 
   {
-    // various size arguments
+    // Various size arguments.
     QuadOp intComputation = ffiTestFunctions
         .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
     var result = intComputation(125, 250, 500, 1000);
@@ -124,7 +103,7 @@
   }
 
   {
-    // unsigned int parameters
+    // Unsigned int parameters.
     QuadOp uintComputation = ffiTestFunctions
         .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
     var result = uintComputation(0xFF, 0xFFFF, 0xFFFFFFFF, -1);
@@ -135,9 +114,8 @@
   }
 
   {
-    // architecture size argument
-    ffi.Pointer<ffi.NativeFunction<NativeFunc4>> p =
-        ffiTestFunctions.lookup("Times3");
+    // Architecture size argument.
+    Pointer<NativeFunction<NativeFunc4>> p = ffiTestFunctions.lookup("Times3");
     UnaryOp f6 = p.asFunction();
     var result = f6(1337);
     print(result);
@@ -145,7 +123,7 @@
   }
 
   {
-    // function with double
+    // Function with double.
     DoubleUnaryOp times1_337Double = ffiTestFunctions
         .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
     var result = times1_337Double(2.0);
@@ -154,7 +132,7 @@
   }
 
   {
-    // function with float
+    // Function with float.
     DoubleUnaryOp times1_337Float = ffiTestFunctions
         .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
     var result = times1_337Float(1000.0);
@@ -163,7 +141,7 @@
   }
 
   {
-    // function with many arguments: arguments get passed in registers and stack
+    // Function with many arguments: arguments get passed in registers and stack.
     DecenaryOp sumManyInts = ffiTestFunctions
         .lookupFunction<NativeDecenaryOp, DecenaryOp>("SumManyInts");
     var result = sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
@@ -172,7 +150,7 @@
   }
 
   {
-    // function with many double arguments
+    // Function with many double arguments.
     DoubleDecenaryOp sumManyDoubles = ffiTestFunctions.lookupFunction<
         NativeDoubleDecenaryOp, DoubleDecenaryOp>("SumManyDoubles");
     var result =
@@ -182,7 +160,7 @@
   }
 
   {
-    // function with many arguments, ints and doubles mixed
+    // Function with many arguments, ints and doubles mixed.
     VigesimalOp sumManyNumbers = ffiTestFunctions
         .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
     var result = sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11,
@@ -195,49 +173,49 @@
     // pass an array / pointer as argument
     Int64PointerUnOp assign1337Index1 = ffiTestFunctions
         .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
-    ffi.Pointer<ffi.Int64> p2 = allocate(count: 2);
-    p2.store(42);
-    p2.elementAt(1).store(1000);
+    Pointer<Int64> p2 = allocate(count: 2);
+    p2.value = 42;
+    p2[1] = 1000;
     print(p2.elementAt(1).address.toRadixString(16));
-    print(p2.elementAt(1).load<int>());
-    ffi.Pointer<ffi.Int64> result = assign1337Index1(p2);
-    print(p2.elementAt(1).load<int>());
+    print(p2[1]);
+    Pointer<Int64> result = assign1337Index1(p2);
+    print(p2[1]);
     print(assign1337Index1);
     print(assign1337Index1.runtimeType);
     print(result);
     print(result.runtimeType);
     print(result.address.toRadixString(16));
-    print(result.load<int>());
+    print(result.value);
   }
 
   {
-    // passing in null for an int argument throws a null pointer exception
+    // Passing in null for an int argument throws a null pointer exception.
     BinaryOp sumPlus42 =
         ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
 
     int x = null;
     try {
       sumPlus42(43, x);
-    } on ArgumentError {
+    } on Error {
       print('Expected exception on passing null for int');
     }
   }
 
   {
-    // passing in null for a double argument throws a null pointer exception
+    // Passing in null for a double argument throws a null pointer exception.
     DoubleUnaryOp times1_337Double = ffiTestFunctions
         .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
 
     double x = null;
     try {
       times1_337Double(x);
-    } on ArgumentError {
+    } on Error {
       print('Expected exception on passing null for double');
     }
   }
 
   {
-    // passing in null for an int argument throws a null pointer exception
+    // Passing in null for an int argument throws a null pointer exception.
     VigesimalOp sumManyNumbers = ffiTestFunctions
         .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
 
@@ -245,22 +223,22 @@
     try {
       sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
           14.0, 15, 16.0, 17, 18.0, x, 20.0);
-    } on ArgumentError {
+    } on Error {
       print('Expected exception on passing null for int');
     }
   }
 
   {
-    // passing in null for a pointer argument results in a nullptr in c
+    // Passing in nullptr for a pointer argument results in a nullptr in c.
     Int64PointerUnOp nullableInt64ElemAt1 =
         ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
             "NullableInt64ElemAt1");
 
-    ffi.Pointer<ffi.Int64> result = nullableInt64ElemAt1(null);
+    Pointer<Int64> result = nullableInt64ElemAt1(nullptr);
     print(result);
     print(result.runtimeType);
 
-    ffi.Pointer<ffi.Int64> p2 = allocate(count: 2);
+    Pointer<Int64> p2 = allocate(count: 2);
     result = nullableInt64ElemAt1(p2);
     print(result);
     print(result.runtimeType);
diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart
index 62ed355..affdcef 100644
--- a/samples/ffi/sample_ffi_functions_callbacks.dart
+++ b/samples/ffi/sample_ffi_functions_callbacks.dart
@@ -2,27 +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.
 
-import 'dart:ffi' as ffi;
-
-import 'dylib_utils.dart';
+import 'dart:ffi';
 
 import 'coordinate.dart';
+import 'dylib_utils.dart';
 
-typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>);
 
-typedef CoordinateTrice = Coordinate Function(
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+typedef CoordinateTrice = Pointer<Coordinate> Function(
+    Pointer<NativeFunction<NativeCoordinateOp>>, Pointer<Coordinate>);
 
 typedef BinaryOp = int Function(int, int);
-typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
-typedef NativeIntptrBinOpLookup
-    = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
+typedef NativeIntptrBinOp = IntPtr Function(IntPtr, IntPtr);
+typedef NativeIntptrBinOpLookup = Pointer<NativeFunction<NativeIntptrBinOp>>
+    Function();
 
-typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef NativeApplyTo42And74Type = IntPtr Function(
+    Pointer<NativeFunction<NativeIntptrBinOp>>);
 
 typedef ApplyTo42And74Type = int Function(
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+    Pointer<NativeFunction<NativeIntptrBinOp>>);
 
 int myPlus(int a, int b) {
   print("myPlus");
@@ -31,51 +30,51 @@
   return a + b;
 }
 
-main(List<String> arguments) {
+main() {
   print('start main');
 
-  ffi.DynamicLibrary ffiTestFunctions =
+  DynamicLibrary ffiTestFunctions =
       dlopenPlatformSpecific("ffi_test_functions");
 
   {
-    // pass a c pointer to a c function as an argument to a c function
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
-        transposeCoordinatePointer =
+    // Pass a c pointer to a c function as an argument to a c function.
+    Pointer<NativeFunction<NativeCoordinateOp>> transposeCoordinatePointer =
         ffiTestFunctions.lookup("TransposeCoordinate");
-    ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
+    Pointer<NativeFunction<CoordinateTrice>> p2 =
         ffiTestFunctions.lookup("CoordinateUnOpTrice");
     CoordinateTrice coordinateUnOpTrice = p2.asFunction();
-    Coordinate c1 = Coordinate(10.0, 20.0, null);
+    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
     c1.next = c1.addressOf;
-    Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+    Coordinate result =
+        coordinateUnOpTrice(transposeCoordinatePointer, c1.addressOf).ref;
     print(result.runtimeType);
     print(result.x);
     print(result.y);
   }
 
   {
-    // return a c pointer to a c function from a c function
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p14 =
+    // Return a c pointer to a c function from a c function.
+    Pointer<NativeFunction<NativeIntptrBinOpLookup>> p14 =
         ffiTestFunctions.lookup("IntptrAdditionClosure");
     NativeIntptrBinOpLookup intptrAdditionClosure = p14.asFunction();
 
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
+    Pointer<NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
         intptrAdditionClosure();
     BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
     print(intptrAddition(10, 27));
   }
 
   {
-    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> pointer =
-        ffi.Pointer.fromFunction(myPlus);
+    Pointer<NativeFunction<NativeIntptrBinOp>> pointer =
+        Pointer.fromFunction(myPlus, 0);
     print(pointer);
 
-    ffi.Pointer<ffi.NativeFunction<NativeApplyTo42And74Type>> p17 =
+    Pointer<NativeFunction<NativeApplyTo42And74Type>> p17 =
         ffiTestFunctions.lookup("ApplyTo42And74");
     ApplyTo42And74Type applyTo42And74 = p17.asFunction();
 
-    // int result = applyTo42And74(pointer);
-    // print(result);
+    int result = applyTo42And74(pointer);
+    print(result);
   }
 
   print("end main");
diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart
index c166b8b..9aefb57 100644
--- a/samples/ffi/sample_ffi_functions_structs.dart
+++ b/samples/ffi/sample_ffi_functions_structs.dart
@@ -2,31 +2,32 @@
 // for 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' as ffi;
-
-import 'dylib_utils.dart';
+import 'dart:ffi';
 
 import 'coordinate.dart';
+import 'dylib_utils.dart';
 
-typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+import 'package:ffi/ffi.dart';
 
-main(List<String> arguments) {
+typedef NativeCoordinateOp = Pointer<Coordinate> Function(Pointer<Coordinate>);
+
+main() {
   print('start main');
 
-  ffi.DynamicLibrary ffiTestFunctions =
+  DynamicLibrary ffiTestFunctions =
       dlopenPlatformSpecific("ffi_test_functions");
 
   {
-    // pass a struct to a c function and get a struct as return value
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+    // Pass a struct to a c function and get a struct as return value.
+    Pointer<NativeFunction<NativeCoordinateOp>> p1 =
         ffiTestFunctions.lookup("TransposeCoordinate");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Coordinate c1 = Coordinate(10.0, 20.0, null);
-    Coordinate c2 = Coordinate(42.0, 84.0, c1);
+    Coordinate c1 = Coordinate.allocate(10.0, 20.0, nullptr);
+    Coordinate c2 = Coordinate.allocate(42.0, 84.0, c1.addressOf);
     c1.next = c2.addressOf;
 
-    Coordinate result = f1(c1);
+    Coordinate result = f1(c1.addressOf).ref;
 
     print(c1.x);
     print(c1.y);
@@ -38,25 +39,25 @@
   }
 
   {
-    // pass an array of structs to a c funtion
-    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+    // Pass an array of structs to a c funtion.
+    Pointer<NativeFunction<NativeCoordinateOp>> p1 =
         ffiTestFunctions.lookup("CoordinateElemAt1");
     NativeCoordinateOp f1 = p1.asFunction();
 
-    Coordinate c1 = Coordinate.allocate(count: 3);
-    Coordinate c2 = c1.elementAt(1);
-    Coordinate c3 = c1.elementAt(2);
-    c1.x = 10.0;
-    c1.y = 10.0;
-    c1.next = c3.addressOf;
-    c2.x = 20.0;
-    c2.y = 20.0;
-    c2.next = c1.addressOf;
-    c3.x = 30.0;
-    c3.y = 30.0;
-    c3.next = c2.addressOf;
+    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c2 = c1.elementAt(1);
+    Pointer<Coordinate> c3 = c1.elementAt(2);
+    c1.ref.x = 10.0;
+    c1.ref.y = 10.0;
+    c1.ref.next = c3;
+    c2.ref.x = 20.0;
+    c2.ref.y = 20.0;
+    c2.ref.next = c1;
+    c3.ref.x = 30.0;
+    c3.ref.y = 30.0;
+    c3.ref.next = c2;
 
-    Coordinate result = f1(c1);
+    Coordinate result = f1(c1).ref;
 
     print(result.x);
     print(result.y);
diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart
index 471f23f..bd6d7c7 100644
--- a/samples/ffi/sample_ffi_structs.dart
+++ b/samples/ffi/sample_ffi_structs.dart
@@ -8,14 +8,14 @@
 
 import 'coordinate.dart';
 
-main(List<String> arguments) {
+main() {
   print('start main');
 
   {
-    // allocates each coordinate separately in c memory
-    Coordinate c1 = Coordinate(10.0, 10.0, null);
-    Coordinate c2 = Coordinate(20.0, 20.0, c1);
-    Coordinate c3 = Coordinate(30.0, 30.0, c2);
+    // 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);
     c1.next = c3.addressOf;
 
     Coordinate currentCoordinate = c1;
@@ -30,31 +30,31 @@
   }
 
   {
-    // allocates coordinates consecutively in c memory
-    Coordinate c1 = Coordinate.allocate(count: 3);
-    Coordinate c2 = c1.elementAt(1);
-    Coordinate c3 = c1.elementAt(2);
-    c1.x = 10.0;
-    c1.y = 10.0;
-    c1.next = c3.addressOf;
-    c2.x = 20.0;
-    c2.y = 20.0;
-    c2.next = c1.addressOf;
-    c3.x = 30.0;
-    c3.y = 30.0;
-    c3.next = c2.addressOf;
+    // Allocates coordinates consecutively in c memory.
+    Pointer<Coordinate> c1 = allocate<Coordinate>(count: 3);
+    Pointer<Coordinate> c2 = c1.elementAt(1);
+    Pointer<Coordinate> c3 = c1.elementAt(2);
+    c1.ref.x = 10.0;
+    c1.ref.y = 10.0;
+    c1.ref.next = c3;
+    c2.ref.x = 20.0;
+    c2.ref.y = 20.0;
+    c2.ref.next = c1;
+    c3.ref.x = 30.0;
+    c3.ref.y = 30.0;
+    c3.ref.next = c2;
 
-    Coordinate currentCoordinate = c1;
+    Coordinate currentCoordinate = c1.ref;
     for (var i in [0, 1, 2, 3, 4]) {
       currentCoordinate = currentCoordinate.next.ref;
       print("${currentCoordinate.x}; ${currentCoordinate.y}");
     }
 
-    free(c1.addressOf);
+    free(c1);
   }
 
   {
-    Coordinate c = Coordinate(10, 10, null);
+    Coordinate c = Coordinate.allocate(10, 10, nullptr);
     print(c is Coordinate);
     print(c is Pointer<Void>);
     print(c is Pointer);
diff --git a/samples/ffi/samples_test.dart b/samples/ffi/samples_test.dart
new file mode 100644
index 0000000..9814463
--- /dev/null
+++ b/samples/ffi/samples_test.dart
@@ -0,0 +1,25 @@
+// 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 exercises the sample files so that they are tested.
+//
+// SharedObjects=ffi_test_dynamic_library ffi_test_functions
+
+import 'sample_ffi_bitfield.dart' as sample0;
+import 'sample_ffi_data.dart' as sample1;
+import 'sample_ffi_dynamic_library.dart' as sample2;
+import 'sample_ffi_functions_callbacks.dart' as sample3;
+import 'sample_ffi_functions_structs.dart' as sample4;
+import 'sample_ffi_functions.dart' as sample5;
+import 'sample_ffi_structs.dart' as sample6;
+
+main() {
+  sample0.main();
+  sample1.main();
+  sample2.main();
+  sample3.main();
+  sample4.main();
+  sample5.main();
+  sample6.main();
+}
diff --git a/samples/ffi/sqlite/docs/android.md b/samples/ffi/sqlite/docs/android.md
index 7b20002..7478c17 100644
--- a/samples/ffi/sqlite/docs/android.md
+++ b/samples/ffi/sqlite/docs/android.md
@@ -49,5 +49,5 @@
 
 Within the `native-libraries` folder, the libraries are organized by ABI.
 Therefore, we must copy the compiled `libsqlite3.so` into `native-libraries/arm64-v8a/libsqlite3.so`.
-If multiple sub-directories are present, the libraries from the sub-directory corresponding to the target ABI will be available in the application's linking path, so the library can be loaded with `ffi.DynamicLibrary.open("libsqlite3.so")` in Dart.
+If multiple sub-directories are present, the libraries from the sub-directory corresponding to the target ABI will be available in the application's linking path, so the library can be loaded with `DynamicLibrary.open("libsqlite3.so")` in Dart.
 Finally, pass `--target-platform=android-arm64` to the `flutter` command when running or building the app since `libsqlite3.so` was compiled for the `arm64-v8a` ABI.
diff --git a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
index fb8153a..7304a7e 100644
--- a/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
+++ b/samples/ffi/sqlite/lib/src/ffi/dylib_utils.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:ffi' as ffi;
+import 'dart:ffi';
 import 'dart:io' show Platform;
 
 String _platformPath(String name, {String path}) {
@@ -14,7 +14,7 @@
   throw Exception("Platform not implemented");
 }
 
-ffi.DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
+DynamicLibrary dlopenPlatformSpecific(String name, {String path}) {
   String fullPath = _platformPath(name, path: path);
-  return ffi.DynamicLibrary.open(fullPath);
+  return DynamicLibrary.open(fullPath);
 }
diff --git a/samples/ffi/sqlite/test/sqlite_test.dart b/samples/ffi/sqlite/test/sqlite_test.dart
index 78fa39e..7bef552 100644
--- a/samples/ffi/sqlite/test/sqlite_test.dart
+++ b/samples/ffi/sqlite/test/sqlite_test.dart
@@ -5,16 +5,17 @@
 // VMOptions=--optimization-counter-threshold=5
 
 import "dart:ffi";
+import "dart:io";
+
 import "package:ffi/ffi.dart";
 import "package:test/test.dart";
 
 import '../lib/sqlite.dart';
 
 void main() {
+  final dbPath = Platform.script.resolve("test.db").path;
   test("sqlite integration test", () {
-    // TODO(dacoharkes): Put the database relative to this file,
-    // instead of where the script was invoked from.
-    Database d = Database("test.db");
+    Database d = Database(dbPath);
     d.execute("drop table if exists Cookies;");
     d.execute("""
       create table Cookies (
@@ -107,8 +108,8 @@
   });
 
   test("concurrent db open and queries", () {
-    Database d = Database("test.db");
-    Database d2 = Database("test.db");
+    Database d = Database(dbPath);
+    Database d2 = Database(dbPath);
     d.execute("drop table if exists Cookies;");
     d.execute("""
       create table Cookies (
@@ -141,7 +142,7 @@
   });
 
   test("stress test", () {
-    Database d = Database("test.db");
+    Database d = Database(dbPath);
     d.execute("drop table if exists Cookies;");
     d.execute("""
       create table Cookies (
diff --git a/samples/sample_extension/README.md b/samples/sample_extension/README.md
new file mode 100644
index 0000000..2e13091
--- /dev/null
+++ b/samples/sample_extension/README.md
@@ -0,0 +1,13 @@
+This directory contains samples of native extensions.
+
+To run the samples, first build both the Dart SDK and the runtime. For example:
+
+```
+$ ./tools/build.py create_sdk runtime
+```
+
+Then execute the sample programs. For example:
+
+```
+$ xcodebuild/ReleaseX64/dart samples/sample_extension/test/sample_extension_test.dart
+```
diff --git a/samples/samples.status b/samples/samples.status
index 257e3a5..21a603b9 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -17,16 +17,19 @@
 [ $compiler == none && $runtime == vm && $system == fuchsia ]
 *: Skip # Not yet triaged.
 
+[ $arch == simarm || $arch == simarm64 || $builder_tag == asan ]
+ffi/samples_test: SkipByDesign # FFI skips, see ffi.status
+
 [ $arch != x64 || $compiler != dartk || $system != linux || $hot_reload || $hot_reload_rollback ]
-ffi/sqlite/test/sqlite_test: Skip # FFI not supported or libsqlite3.so not available.
+ffi/sqlite/test/sqlite_test: SkipByDesign # FFI not supported or libsqlite3.so not available.
 
 [ $compiler == app_jitk || $compiler == dartkp ]
 sample_extension/test/sample_extension_app_snapshot_test: SkipByDesign
 sample_extension/test/sample_extension_test: SkipByDesign
 
-# Skip tests that use dart:io
 [ $runtime == d8 || $browser ]
-sample_extension/*: Skip
+ffi/*: SkipByDesign # Skip tests that use dart:ffi.
+sample_extension/*: SkipByDesign # Skip tests that use dart:io.
 
 [ $hot_reload || $hot_reload_rollback ]
 sample_extension/test/sample_extension_app_snapshot_test: SkipByDesign # Cannot reload with URI pointing to app snapshot.
diff --git a/sdk/bin/dart b/sdk/bin/dart
index f50184b..34cb80b 100755
--- a/sdk/bin/dart
+++ b/sdk/bin/dart
@@ -30,8 +30,7 @@
   DIRS=$( ls "$OUT_DIR" )
   # list of possible configurations in decreasing desirability
   CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
+    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64" )
   DART_CONFIGURATION="None"
   for CONFIG in ${CONFIGS[*]}
   do
diff --git a/sdk/bin/pub b/sdk/bin/pub
index 5dda611..85ad5d6 100755
--- a/sdk/bin/pub
+++ b/sdk/bin/pub
@@ -47,8 +47,7 @@
   DIRS=$( ls "$OUT_DIR" )
   # list of possible configurations in decreasing desirability
   CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
+    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64" )
   DART_CONFIGURATION="None"
   for CONFIG in ${CONFIGS[*]}
   do
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
index 61d031a..fcdaa65 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
@@ -448,7 +448,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog = 0, bool v6Only = false, bool shared = false}) {
     throw UnsupportedError("ServerSocket.bind");
   }
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 8fe2fa6..1fe79ab 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
@@ -116,6 +116,8 @@
 /// The Symbol for storing type arguments on a specialized generic type.
 final _typeArguments = JS('', 'Symbol("typeArguments")');
 
+final _variances = JS('', 'Symbol("variances")');
+
 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
 
 final mixinNew = JS('', 'Symbol("dart.mixinNew")');
@@ -177,6 +179,12 @@
 List getGenericArgs(type) =>
     JS('List', '#', safeGetOwnProperty(type, _typeArguments));
 
+List getGenericArgVariances(type) =>
+    JS('List', '#', safeGetOwnProperty(type, _variances));
+
+void setGenericArgVariances(f, variances) =>
+    JS('', '#[#] = #', f, _variances, variances);
+
 List<TypeVariable> getGenericTypeFormals(genericClass) {
   return _typeFormalsFromFunction(getGenericTypeCtor(genericClass));
 }
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index 11ea1ae..34c66e2 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -152,6 +152,9 @@
   JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
   JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
   JS('', '#.set(#, #)', _loadedPartMaps, moduleName, parts);
+  _libraries = null;
+  _libraryObjects = null;
+  _parts = null;
 }
 
 List<String> _libraries;
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 99e1ab9..1c6ce56 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
@@ -181,12 +181,20 @@
 @notNull
 final List<void Function()> _resetFields = JS('', '[]');
 
+/// A counter to track each time [hotRestart] is invoked. This is used to ensure
+/// that pending callbacks that were created on a previous iteration (e.g. a
+/// timer callback or a DOM callback) will not execute when they get invoked.
+// TODO(sigmund): consider whether we should track and cancel callbacks to
+// reduce memory leaks.
+int hotRestartIteration = 0;
+
 /// Clears out runtime state in `dartdevc` so we can hot-restart.
 ///
 /// This should be called when the user requests a hot-restart, when the UI is
 /// handling that user action.
 void hotRestart() {
-  // TODO(jmesserly): we need to prevent all pending callbacks from firing.
+  // TODO(sigmund): prevent DOM callbacks from firing.
+  hotRestartIteration++;
   for (var f in _resetFields) f();
   _resetFields.clear();
   for (var m in _cacheMaps) JS('', '#.clear()', m);
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 6f07c07..4456041 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
@@ -516,6 +516,13 @@
   toString() => name;
 }
 
+class Variance {
+  static const int unrelated = 0;
+  static const int covariant = 1;
+  static const int contravariant = 2;
+  static const int invariant = 3;
+}
+
 class GenericFunctionType extends AbstractFunctionType {
   final _instantiateTypeParts;
   final int formalCount;
@@ -1030,9 +1037,23 @@
     if (typeArguments1.length != typeArguments2.length) {
       $assertFailed();
     }
+    let variances = $getGenericArgVariances($t1);
     for (let i = 0; i < typeArguments1.length; ++i) {
-      if (!$_isSubtype(typeArguments1[i], typeArguments2[i])) {
-        return false;
+      // When using implicit variance, variances will be undefined and
+      // considered covariant.
+      if (variances === void 0 || variances[i] == ${Variance.covariant}) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i])) {
+          return false;
+        }
+      } else if (variances[i] == ${Variance.contravariant}) {
+        if (!$_isSubtype(typeArguments2[i], typeArguments1[i])) {
+          return false;
+        }
+      } else if (variances[i] == ${Variance.invariant}) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i]) ||
+            !$_isSubtype(typeArguments2[i], typeArguments1[i])) {
+          return false;
+        }
       }
     }
     return true;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
index 490c4b9..9132848 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
@@ -39,11 +39,14 @@
 
   TimerImpl(int milliseconds, void callback()) : _once = true {
     if (hasTimer()) {
+      int currentHotRestartIteration = dart.hotRestartIteration;
       void internalCallback() {
         _handle = null;
         dart.removeAsyncCallback();
         _tick = 1;
-        callback();
+        if (currentHotRestartIteration == dart.hotRestartIteration) {
+          callback();
+        }
       }
 
       dart.addAsyncCallback();
@@ -60,7 +63,12 @@
     if (hasTimer()) {
       dart.addAsyncCallback();
       int start = JS<int>('!', 'Date.now()');
+      int currentHotRestartIteration = dart.hotRestartIteration;
       _handle = JS<int>('!', '#.setInterval(#, #)', global, () {
+        if (currentHotRestartIteration != dart.hotRestartIteration) {
+          cancel();
+          return;
+        }
         int tick = this._tick + 1;
         if (milliseconds > 0) {
           int duration = JS<int>('!', 'Date.now()') - start;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index fadcda0..6eeee38 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -79,7 +79,9 @@
   bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
   bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);
   bool get _isUnicode => JS("bool", "#.unicode", _nativeRegExp);
-  bool get _isDotAll => JS("bool", "#.dotAll", _nativeRegExp);
+  // The "dotAll" property is not available on all browsers, but our internals
+  // currently assume this is non-null.  Coerce to false if not present.
+  bool get _isDotAll => JS("bool", "#.dotAll == true", _nativeRegExp);
 
   static makeNative(@nullCheck String source, bool multiLine,
       bool caseSensitive, bool unicode, bool dotAll, bool global) {
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 4f3894d..ee1eb4d 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -448,7 +448,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog: 0, bool v6Only: false, bool shared: false}) {
     throw new UnsupportedError("ServerSocket.bind");
   }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 5b7b6aa..a9fd83b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2560,17 +2560,11 @@
 
   String toString() {
     String name;
-    if (JS_GET_FLAG('USE_NEW_RTI')) {
-      var constructor = JS('', '#.constructor', this);
-      name =
-          constructor == null ? null : JS('String|Null', '#.name', constructor);
-      if (name == null) name = 'unknown';
-    } else {
-      name = Primitives.objectTypeName(this);
-      // Mirrors puts a space in front of some names, so remove it.
-      name = JS('String', '#.trim()', name);
-    }
-    return "Closure '$name'";
+    var constructor = JS('', '#.constructor', this);
+    name =
+        constructor == null ? null : JS('String|Null', '#.name', constructor);
+    if (name == null) name = 'unknown';
+    return "Closure '${unminifyOrTag(name)}'";
   }
 }
 
@@ -3080,9 +3074,9 @@
 futureOrCast(o, futureOrRti) => subtypeOfRuntimeTypeCast(o, futureOrRti);
 
 @pragma('dart2js:noInline')
-void checkDeferredIsLoaded(String loadId, String uri) {
+void checkDeferredIsLoaded(String loadId) {
   if (!_loadedLibraries.contains(loadId)) {
-    throw new DeferredNotLoadedError(uri);
+    throw new DeferredNotLoadedError(loadId);
   }
 }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index b3890bd..b0300d5 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -129,17 +129,18 @@
   static const kindDynamic = 2;
   static const kindVoid = 3; // TODO(sra): Use `dynamic` instead?
   static const kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
+  static const kindErased = 5;
   // Unary terms.
-  static const kindStar = 5;
-  static const kindQuestion = 6;
-  static const kindFutureOr = 7;
+  static const kindStar = 6;
+  static const kindQuestion = 7;
+  static const kindFutureOr = 8;
   // More complex terms.
-  static const kindInterface = 8;
+  static const kindInterface = 9;
   // A vector of type parameters from enclosing functions and closures.
-  static const kindBinding = 9;
-  static const kindFunction = 10;
-  static const kindGenericFunction = 11;
-  static const kindGenericFunctionParameter = 12;
+  static const kindBinding = 10;
+  static const kindFunction = 11;
+  static const kindGenericFunction = 12;
+  static const kindGenericFunctionParameter = 13;
 
   static bool _isUnionOfFunctionType(Rti rti) {
     int kind = Rti._getKind(rti);
@@ -402,6 +403,7 @@
 Rti _instantiate(universe, Rti rti, Object typeArguments, int depth) {
   int kind = Rti._getKind(rti);
   switch (kind) {
+    case Rti.kindErased:
     case Rti.kindNever:
     case Rti.kindDynamic:
     case Rti.kindVoid:
@@ -646,7 +648,8 @@
 
 Rti _instanceTypeFromConstructor(constructor) {
   // TODO(sra): Cache Rti on constructor.
-  return findType(JS('String', '#.name', constructor));
+  return _Universe.findErasedType(
+      _theUniverse(), JS('String', '#.name', constructor));
 }
 
 /// Returns the structural function type of [object], or `null` if the object is
@@ -709,6 +712,52 @@
 }
 
 /// Called from generated code.
+///
+/// The first time the default `_is` method is called, it replaces itself with a
+/// specialized version.
+// TODO(sra): Emit code to force-replace the `_is` method, generated dependent
+// on the types used in the program. e.g.
+//
+//     findType("bool")._is = H._isBool;
+//
+// This could be omitted if (1) the `bool` rti is not used directly for a test
+// (e.g. we lower a check to a direct helper), and (2) `bool` does not flow to a
+// tested type parameter. The trick will be to ensure that `H._isBool` is
+// generated.
+bool _installSpecializedIsTest(object) {
+  // This static method is installed on an Rti object as a JavaScript instance
+  // method. The Rti object is 'this'.
+  Rti testRti = _castToRti(JS('', 'this'));
+  int kind = Rti._getKind(testRti);
+
+  var isFn = RAW_DART_FUNCTION_REF(_generalIsTestImplementation);
+
+  if (isTopType(testRti)) {
+    isFn = RAW_DART_FUNCTION_REF(_isTop);
+    var asFn = RAW_DART_FUNCTION_REF(_asTop);
+    Rti._setAsCheckFunction(testRti, asFn);
+    Rti._setTypeCheckFunction(testRti, asFn);
+  } else if (kind == Rti.kindInterface) {
+    String key = Rti._getCanonicalRecipe(testRti);
+
+    if (JS_GET_NAME(JsGetName.INT_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isInt);
+    } else if (JS_GET_NAME(JsGetName.DOUBLE_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isNum);
+    } else if (JS_GET_NAME(JsGetName.NUM_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isNum);
+    } else if (JS_GET_NAME(JsGetName.STRING_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isString);
+    } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isBool);
+    }
+  }
+
+  Rti._setIsTestFunction(testRti, isFn);
+  return Rti._isCheck(testRti, object);
+}
+
+/// Called from generated code.
 bool _generalIsTestImplementation(object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
@@ -796,6 +845,18 @@
 // Specializations can be placed on Rti objects as the _as, _check and _is
 // 'methods'. They can also be called directly called from generated code.
 
+/// Specialization for 'is dynamic' and other top types.
+/// Called from generated code via Rti `_is` method.
+bool _isTop(object) {
+  return true;
+}
+
+/// Specialization for 'as dynamic' and other top types.
+/// Called from generated code via Rti `_as` and `_check` methods.
+dynamic _asTop(object) {
+  return object;
+}
+
 /// Specialization for 'is bool'.
 /// Called from generated code.
 bool _isBool(object) {
@@ -1008,6 +1069,7 @@
 String _rtiToString(Rti rti, List<String> genericContext) {
   int kind = Rti._getKind(rti);
 
+  if (kind == Rti.kindErased) return 'erased';
   if (kind == Rti.kindDynamic) return 'dynamic';
   if (kind == Rti.kindVoid) return 'void';
   if (kind == Rti.kindNever) return 'Never';
@@ -1121,6 +1183,7 @@
 String _rtiToDebugString(Rti rti) {
   int kind = Rti._getKind(rti);
 
+  if (kind == Rti.kindErased) return 'erased';
   if (kind == Rti.kindDynamic) return 'dynamic';
   if (kind == Rti.kindVoid) return 'void';
   if (kind == Rti.kindNever) return 'Never';
@@ -1197,10 +1260,12 @@
         '{'
             '#: new Map(),'
             '#: {},'
+            '#: {},'
             '#: [],' // shared empty array.
             '}',
         RtiUniverseFieldNames.evalCache,
         RtiUniverseFieldNames.typeRules,
+        RtiUniverseFieldNames.erasedTypes,
         RtiUniverseFieldNames.sharedEmptyArray);
   }
 
@@ -1212,6 +1277,9 @@
   static Object typeRules(universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.typeRules);
 
+  static Object erasedTypes(universe) =>
+      JS('', '#.#', universe, RtiUniverseFieldNames.erasedTypes);
+
   static Object _findRule(universe, String targetType) =>
       JS('', '#.#', typeRules(universe), targetType);
 
@@ -1223,17 +1291,32 @@
     return rule;
   }
 
-  static void addRules(universe, rules) {
-    // TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
-    var keys = JS('JSArray', 'Object.keys(#)', rules);
-    int length = _Utils.arrayLength(keys);
-    Object ruleset = typeRules(universe);
-    for (int i = 0; i < length; i++) {
-      String targetType = _Utils.asString(_Utils.arrayAt(keys, i));
-      JS('', '#[#] = #[#]', ruleset, targetType, rules, targetType);
+  static Rti findErasedType(universe, String cls) {
+    Object metadata = erasedTypes(universe);
+    var probe = JS('', '#.#', metadata, cls);
+    if (probe == null) {
+      return eval(universe, cls);
+    } else if (_Utils.isNum(probe)) {
+      int length = _Utils.asInt(probe);
+      Rti erased = _lookupErasedRti(universe);
+      Object arguments = JS('', '[]');
+      for (int i = 0; i < length; i++) {
+        _Utils.arrayPush(arguments, erased);
+      }
+      Rti interface = _lookupInterfaceRti(universe, cls, arguments);
+      JS('', '#.# = #', metadata, cls, interface);
+      return interface;
+    } else {
+      return _castToRti(probe);
     }
   }
 
+  static void addRules(universe, rules) =>
+      _Utils.objectAssign(typeRules(universe), rules);
+
+  static void addErasedTypes(universe, types) =>
+      _Utils.objectAssign(erasedTypes(universe), types);
+
   static Object sharedEmptyArray(universe) =>
       JS('JSArray', '#.#', universe, RtiUniverseFieldNames.sharedEmptyArray);
 
@@ -1315,26 +1398,13 @@
     String key = Rti._getCanonicalRecipe(rti);
     _cacheSet(evalCache(universe), key, rti);
 
-    // Set up methods to perform type tests.
-
-    // TODO(sra): Find better way to install specializations. Perhaps the
-    // installed version should replace itself with the specialization.
+    // Set up methods to perform type tests. The general as-check / type-check
+    // methods use the is-test method. The is-test method on first use
+    // overwrites itself, and possibly the as-check / type-check methods, with a
+    // specialized version.
     var checkFn = RAW_DART_FUNCTION_REF(_generalTypeCheckImplementation);
     var asFn = RAW_DART_FUNCTION_REF(_generalAsCheckImplementation);
-    var isFn = RAW_DART_FUNCTION_REF(_generalIsTestImplementation);
-
-    if (JS_GET_NAME(JsGetName.INT_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isInt);
-    } else if (JS_GET_NAME(JsGetName.DOUBLE_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isNum);
-    } else if (JS_GET_NAME(JsGetName.NUM_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isNum);
-    } else if (JS_GET_NAME(JsGetName.STRING_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isString);
-    } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isBool);
-    }
-
+    var isFn = RAW_DART_FUNCTION_REF(_installSpecializedIsTest);
     Rti._setAsCheckFunction(rti, asFn);
     Rti._setTypeCheckFunction(rti, checkFn);
     Rti._setIsTestFunction(rti, isFn);
@@ -1349,6 +1419,7 @@
   //   for the proposed type.
   // * `createXXX` to create the type if it does not exist.
 
+  static String _canonicalRecipeOfErased() => Recipe.pushErasedString;
   static String _canonicalRecipeOfDynamic() => Recipe.pushDynamicString;
   static String _canonicalRecipeOfVoid() => Recipe.pushVoidString;
   static String _canonicalRecipeOfNever() =>
@@ -1366,6 +1437,11 @@
   static String _canonicalRecipeOfGenericFunctionParameter(int index) =>
       '$index' + Recipe.genericFunctionTypeParameterIndexString;
 
+  static Rti _lookupErasedRti(universe) {
+    return _lookupTerminalRti(
+        universe, Rti.kindErased, _canonicalRecipeOfErased());
+  }
+
   static Rti _lookupDynamicRti(universe) {
     return _lookupTerminalRti(
         universe, Rti.kindDynamic, _canonicalRecipeOfDynamic());
@@ -1653,6 +1729,8 @@
 ///
 ///   Used to separate elements.
 ///
+/// '#': --- erasedType
+///
 /// '@': --- dynamicType
 ///
 /// '~': --- voidType
@@ -1813,6 +1891,10 @@
                 toGenericFunctionParameter(universe(parser), pop(stack)));
             break;
 
+          case Recipe.pushErased:
+            push(stack, _Universe._lookupErasedRti(universe(parser)));
+            break;
+
           case Recipe.pushDynamic:
             push(stack, _Universe._lookupDynamicRti(universe(parser)));
             break;
@@ -2035,10 +2117,6 @@
   static Rti toType(Object universe, Rti environment, Object item) {
     if (_Utils.isString(item)) {
       String name = _Utils.asString(item);
-      // TODO(sra): Compile this out for minified code.
-      if ('dynamic' == name) {
-        return _Universe._lookupDynamicRti(universe);
-      }
       return _Universe._lookupInterfaceRti(
           universe, name, _Universe.sharedEmptyArray(universe));
     } else if (_Utils.isNum(item)) {
@@ -2129,6 +2207,8 @@
   // Subtyping is reflexive.
   if (_Utils.isIdentical(s, t)) return true;
 
+  // Erased types are treated like `dynamic` and handled by the top type case.
+
   if (isTopType(t)) return true;
 
   if (isJsInteropType(s)) return true;
@@ -2404,8 +2484,13 @@
         _FunctionParameters._getOptionalNamed(tParameters));
 
 bool isTopType(Rti t) =>
-    isDynamicType(t) || isVoidType(t) || isObjectType(t) || isJsInteropType(t);
+    isErasedType(t) ||
+    isDynamicType(t) ||
+    isVoidType(t) ||
+    isObjectType(t) ||
+    isJsInteropType(t);
 
+bool isErasedType(Rti t) => Rti._getKind(t) == Rti.kindErased;
 bool isDynamicType(Rti t) => Rti._getKind(t) == Rti.kindDynamic;
 bool isVoidType(Rti t) => Rti._getKind(t) == Rti.kindVoid;
 bool isJsInteropType(Rti t) => Rti._getKind(t) == Rti.kindAny;
@@ -2456,6 +2541,19 @@
 
   static bool isIdentical(s, t) => JS('bool', '# === #', s, t);
 
+  static JSArray objectKeys(Object o) =>
+      JS('returns:JSArray;new:true;', 'Object.keys(#)', o);
+
+  static void objectAssign(Object o, Object other) {
+    // TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
+    var keys = objectKeys(other);
+    int length = arrayLength(keys);
+    for (int i = 0; i < length; i++) {
+      String key = asString(arrayAt(keys, i));
+      JS('', '#[#] = #[#]', o, key, other, key);
+    }
+  }
+
   static bool isArray(Object o) => JS('bool', 'Array.isArray(#)', o);
 
   static int arrayLength(Object array) => JS('int', '#.length', array);
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index 6800e37..66cba17 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -265,6 +265,9 @@
   /// 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,
 
@@ -451,5 +454,6 @@
 class RtiUniverseFieldNames {
   static String evalCache = 'eC';
   static String typeRules = 'tR';
+  static String erasedTypes = 'eT';
   static String sharedEmptyArray = 'sEA';
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart b/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
index 7666379..ef7fbff 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
@@ -18,6 +18,8 @@
   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;
@@ -170,6 +172,7 @@
 
     test("separator", separator, separatorString);
     test("toType", toType, toTypeString);
+    test("pushErased", pushErased, pushErasedString);
     test("pushDynamic", pushDynamic, pushDynamicString);
     test("pushVoid", pushVoid, pushVoidString);
     test("wrapStar", wrapStar, wrapStarString);
diff --git a/sdk/lib/_internal/vm/bin/builtin.dart b/sdk/lib/_internal/vm/bin/builtin.dart
index 363469b..23c5dc7 100644
--- a/sdk/lib/_internal/vm/bin/builtin.dart
+++ b/sdk/lib/_internal/vm/bin/builtin.dart
@@ -45,7 +45,6 @@
 // Requests made to the service isolate over the load port.
 
 // Extra requests. Keep these in sync between loader.dart and builtin.dart.
-const _Dart_kInitLoader = 4; // Initialize the loader.
 const _Dart_kResourceLoad = 5; // Resource class support.
 const _Dart_kGetPackageRootUri = 6; // Uri of the packages/ directory.
 const _Dart_kGetPackageConfigUri = 7; // Uri of the .packages file.
diff --git a/sdk/lib/_internal/vm/bin/file_patch.dart b/sdk/lib/_internal/vm/bin/file_patch.dart
index 57cf8fd..a404aa0 100644
--- a/sdk/lib/_internal/vm/bin/file_patch.dart
+++ b/sdk/lib/_internal/vm/bin/file_patch.dart
@@ -217,7 +217,9 @@
         bool getIsDir(event) {
           if (Platform.isWindows) {
             // Windows does not get 'isDir' as part of the event.
-            return FileSystemEntity.isDirectorySync(getPath(event));
+            // Links should also be skipped.
+            return FileSystemEntity.isDirectorySync(getPath(event)) &&
+                !FileSystemEntity.isLinkSync(getPath(event));
           }
           return (event[0] & FileSystemEvent._isDir) != 0;
         }
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index c1336e3..b0ce8e6 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -1506,7 +1506,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog: 0, bool v6Only: false, bool shared: false}) {
     return _ServerSocket.bind(address, port, backlog, v6Only, shared);
   }
diff --git a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
index d07645d..81fac07 100644
--- a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
@@ -6,6 +6,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 DynamicLibrary _open(String name) native "Ffi_dl_open";
 DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
diff --git a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
index dcd76ed..473ba7a 100644
--- a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
@@ -6,6 +6,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 // NativeType is not private, because it is used in type arguments.
 // NativeType is abstract because it not used with const constructors in
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 69e6b20..71706ef 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -6,6 +6,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 const Map<Type, int> _knownSizes = {
   Int8: 1,
@@ -442,3 +443,8 @@
   @patch
   T operator [](int index) => _loadStruct(this, index);
 }
+
+extension NativePort on SendPort {
+  @patch
+  int get nativePort native "SendPortImpl_get_id";
+}
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index b9d22c1..19c9dbe 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -13,8 +13,6 @@
 /// It is a compile-time error for any class to extend, mix in or implement
 /// `FutureOr`.
 ///
-/// Note: the `FutureOr<T>` type is interpreted as `dynamic` in non strong-mode.
-///
 /// # Examples
 /// ``` dart
 /// // The `Future<T>.then` function takes a callback [f] that returns either
@@ -637,8 +635,6 @@
   // - (dynamic, StackTrace) -> FutureOr<T>
   // Given that there is a `test` function that is usually used to do an
   // `isCheck` we should also expect functions that take a specific argument.
-  // Note: making `catchError` return a `Future<T>` in non-strong mode could be
-  // a breaking change.
   Future<T> catchError(Function onError, {bool test(Object error)});
 
   /**
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 66df3dc..bfa1741 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -250,6 +250,8 @@
    * every event.
    *
    * If [computation] is omitted the event values will all be `null`.
+   *
+   * [period] must a non-negative [Duration].
    */
   factory Stream.periodic(Duration period,
       [T computation(int computationCount)]) {
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index aa2f088..97560a9 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.dart
@@ -67,6 +67,8 @@
    * 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) {
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 1d83aa4..56661e3 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -21,7 +21,11 @@
 /// to the growable list, or, preferably, use `DelegatingList` from
 /// "package:collection/wrappers.dart" instead.
 abstract class ListBase<E> extends Object with ListMixin<E> {
-  /// Convert a `List` to a string as `[each, element, as, string]`.
+  /// Converts a [List] to a [String].
+  ///
+  /// Converts [list] to a string by converting each element to a string (by
+  /// calling [Object.toString]), joining them with ", ", and wrapping the
+  /// result in "[" and "]".
   ///
   /// Handles circular references where converting one of the elements
   /// to a string ends up converting [list] to a string again.
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 62994b9..8a95cf4 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(superSet.whereType<SubType>());
+  ///     new Queue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
   factory Queue.from(Iterable elements) = ListQueue<E>.from;
 
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 7508b23..c911faf 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -299,7 +299,11 @@
 /// `clear` in constant time. The default implementation works by removing every
 /// element.
 abstract class SetBase<E> extends Object with SetMixin<E> {
-  /// Convert a `Set` to a string as `{each, element, as, string}`.
+  /// Converts a [Set] to a [String].
+  ///
+  /// Converts [set] to a string by converting each element to a string (by
+  /// calling [Object.toString]), joining them with ", ", and wrapping the
+  /// result in "{" and "}".
   ///
   /// Handles circular references where converting one of the elements
   /// to a string ends up converting [set] to a string again.
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index b5c6072..bfdb07b 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -190,6 +190,10 @@
 
   /// Create a task with an explicit [taskId]. This is useful if you are
   /// passing a task from one isolate to another.
+  ///
+  /// Important note: only provide task IDs which have been obtained as a
+  /// result of invoking [TimelineTask.pass]. Specifying a custom ID can lead
+  /// to ID collisions, resulting in incorrect rendering of timeline events.
   TimelineTask.withTaskId(int taskId)
       : _parent = null,
         _taskId = taskId {
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 422788f..a47ebdf 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -15,6 +15,7 @@
 library dart.ffi;
 
 import 'dart:typed_data';
+import 'dart:isolate';
 
 part "native_type.dart";
 part "annotations.dart";
@@ -609,3 +610,13 @@
   /// the platform.
   external T operator [](int index);
 }
+
+/// Extension to retrieve the native `Dart_Port` from a [SendPort].
+extension NativePort on SendPort {
+  /// The native port of this [SendPort].
+  ///
+  /// The returned native port can for example be used by C code to post
+  /// messages to the connected [ReceivePort] via `Dart_PostCObject()` - see
+  /// `dart_native_api.h`.
+  external int get nativePort;
+}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 69474c6..090115d 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -10842,13 +10842,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, width.hashCode, height.hashCode);
@@ -32939,13 +32938,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, width.hashCode, height.hashCode);
@@ -34970,8 +34968,8 @@
   }
 
   // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
-  // Ideally we would provide a RectangleMixin class that provides this implementation.
-  // In an ideal world we would exp
+  // Ideally we would provide a RectangleMixin class that provides this
+  // implementation. In an ideal world we would exp
   /** The x-coordinate of the right edge. */
   num get right => left + width;
   /** The y-coordinate of the bottom edge. */
@@ -34981,13 +34979,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        right == other.right &&
-        bottom == other.bottom;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      right == other.right &&
+      bottom == other.bottom;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 861ce47..cae672b 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -704,11 +704,13 @@
   Future<int> readInto(List<int> buffer, [int start = 0, int end]);
 
   /**
-   * Synchronously 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.
+   * 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.
    */
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index c640c5b..d30e97e 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -213,6 +213,7 @@
 part 'io_service.dart';
 part 'link.dart';
 part 'namespace_impl.dart';
+part 'network_profiling.dart';
 part 'overrides.dart';
 part 'platform.dart';
 part 'platform_impl.dart';
diff --git a/sdk/lib/io/io_sources.gni b/sdk/lib/io/io_sources.gni
index 51e283a..308dd94 100644
--- a/sdk/lib/io/io_sources.gni
+++ b/sdk/lib/io/io_sources.gni
@@ -21,6 +21,7 @@
   "io_service.dart",
   "link.dart",
   "namespace_impl.dart",
+  "network_profiling.dart",
   "overrides.dart",
   "platform.dart",
   "platform_impl.dart",
diff --git a/sdk/lib/io/network_profiling.dart b/sdk/lib/io/network_profiling.dart
new file mode 100644
index 0000000..e562b0d
--- /dev/null
+++ b/sdk/lib/io/network_profiling.dart
@@ -0,0 +1,57 @@
+// 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.
+
+part of dart.io;
+
+@pragma('vm:entry-point')
+abstract class _NetworkProfiling {
+  static const _kGetHttpProfileRPC = 'ext.dart.io.getHttpProfile';
+  static const _kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
+
+  @pragma('vm:entry-point')
+  static void _registerServiceExtension() {
+    registerExtension(_kGetHttpProfileRPC, _serviceExtensionHandler);
+    registerExtension(_kGetSocketProfileRPC, _serviceExtensionHandler);
+  }
+
+  static Future<ServiceExtensionResponse> _serviceExtensionHandler(
+      String method, Map<String, String> parameters) {
+    String responseJson;
+    switch (method) {
+      case _kGetHttpProfileRPC:
+        responseJson = _HttpProfile.toJSON();
+        break;
+      case _kGetSocketProfileRPC:
+        responseJson = _SocketProfile.toJSON();
+        break;
+      default:
+        return Future.value(ServiceExtensionResponse.error(
+            ServiceExtensionResponse.extensionError,
+            'Method $method does not exist'));
+    }
+    return Future.value(ServiceExtensionResponse.result(responseJson));
+  }
+}
+
+abstract class _HttpProfile {
+  static const _kType = 'HttpProfile';
+  // TODO(bkonyi): implement.
+  static String toJSON() {
+    final response = <String, dynamic>{
+      'type': _kType,
+    };
+    return json.encode(response);
+  }
+}
+
+abstract class _SocketProfile {
+  static const _kType = 'SocketProfile';
+  // TODO(bkonyi): implement.
+  static String toJSON() {
+    final response = <String, dynamic>{
+      'type': _kType,
+    };
+    return json.encode(response);
+  }
+}
diff --git a/sdk/lib/io/overrides.dart b/sdk/lib/io/overrides.dart
index 1a71881..aa1c8a4 100644
--- a/sdk/lib/io/overrides.dart
+++ b/sdk/lib/io/overrides.dart
@@ -87,6 +87,11 @@
               {dynamic sourceAddress})
           socketStartConnect,
 
+      // ServerSocket
+      Future<ServerSocket> Function(dynamic, int,
+              {int backlog, bool v6Only, bool shared})
+          serverSocketBind,
+
       // Optional Zone parameters
       ZoneSpecification zoneSpecification,
       Function onError}) {
@@ -120,6 +125,9 @@
       // Socket
       socketConnect,
       socketStartConnect,
+
+      // ServerSocket
+      serverSocketBind,
     );
     return _asyncRunZoned<R>(body,
         zoneValues: {_ioOverridesToken: overrides},
@@ -274,6 +282,19 @@
       {sourceAddress}) {
     return Socket._startConnect(host, port, sourceAddress: sourceAddress);
   }
+
+  // ServerSocket
+
+  /// Asynchronously returns a [ServerSocket] that connects to the given address
+  /// and port when successful.
+  ///
+  /// 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}) {
+    return ServerSocket._bind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
 }
 
 class _IOOverridesScope extends IOOverrides {
@@ -311,6 +332,10 @@
   Future<ConnectionTask<Socket>> Function(dynamic, int, {dynamic sourceAddress})
       _socketStartConnect;
 
+  // ServerSocket
+  Future<ServerSocket> Function(dynamic, int,
+      {int backlog, bool v6Only, bool shared}) _serverSocketBind;
+
   _IOOverridesScope(
     // Directory
     this._createDirectory,
@@ -341,6 +366,9 @@
     // Socket
     this._socketConnect,
     this._socketStartConnect,
+
+    // ServerSocket
+    this._serverSocketBind,
   );
 
   // Directory
@@ -478,4 +506,20 @@
     }
     return super.socketStartConnect(host, port, sourceAddress: sourceAddress);
   }
+
+  // ServerSocket
+  @override
+  Future<ServerSocket> serverSocketBind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    if (_serverSocketBind != null) {
+      return _serverSocketBind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    if (_previous != null) {
+      return _previous.serverSocketBind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    return super.serverSocketBind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
 }
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index d51c616..5d9c239 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -149,7 +149,7 @@
 
   /**
    * Lookup a host, returning a Future of a list of
-   * [InternetAddress]s. If [type] is [InternetAddressType.ANY], it
+   * [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
@@ -327,7 +327,18 @@
    * distributed among all the bound `ServerSocket`s. Connections can be
    * distributed over multiple isolates this way.
    */
-  external static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> bind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    final IOOverrides overrides = IOOverrides.current;
+    if (overrides == null) {
+      return ServerSocket._bind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    return overrides.serverSocketBind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
+
+  external static Future<ServerSocket> _bind(address, int port,
       {int backlog: 0, bool v6Only: false, bool shared: false});
 
   /**
diff --git a/sdk_nnbd/bin/dart b/sdk_nnbd/bin/dart
index f50184b..34cb80b 100755
--- a/sdk_nnbd/bin/dart
+++ b/sdk_nnbd/bin/dart
@@ -30,8 +30,7 @@
   DIRS=$( ls "$OUT_DIR" )
   # list of possible configurations in decreasing desirability
   CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
+    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64" )
   DART_CONFIGURATION="None"
   for CONFIG in ${CONFIGS[*]}
   do
diff --git a/sdk_nnbd/bin/pub b/sdk_nnbd/bin/pub
index 5dda611..85ad5d6 100755
--- a/sdk_nnbd/bin/pub
+++ b/sdk_nnbd/bin/pub
@@ -47,8 +47,7 @@
   DIRS=$( ls "$OUT_DIR" )
   # list of possible configurations in decreasing desirability
   CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
-    "ReleaseARM"    "ReleaseARM64"    "ReleaseARMV5TE"
-    "DebugARM"      "DebugARM64"      "DebugARMV5TE")
+    "ReleaseARM" "ReleaseARM64" "DebugARM" "DebugARM64" )
   DART_CONFIGURATION="None"
   for CONFIG in ${CONFIGS[*]}
   do
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/collection_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/collection_patch.dart
index d37655d..daa3bf8 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/collection_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/collection_patch.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.5
-
 // Patch file for dart:collection classes.
 import 'dart:_foreign_helper' show JS, JSExportName;
 import 'dart:_runtime' as dart;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart
index 637febd..486473b 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.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.5
-
 // Patch file for dart:convert library.
 
 import 'dart:_js_helper' show argumentErrorValue, patch;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 3665c70..4829140 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.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.5
-
 // Patch file for dart:core classes.
 import "dart:_internal" as _symbol_dev;
 import 'dart:_interceptors';
@@ -33,11 +31,11 @@
     : _symbol_dev.Symbol.getName(symbol);
 
 @patch
-int identityHashCode(Object object) {
+int identityHashCode(Object? object) {
   if (object == null) return 0;
   // Note: this works for primitives because we define the `identityHashCode`
   // for them to be equivalent to their computed hashCode function.
-  int hash = JS('int|Null', r'#[#]', object, dart.identityHashCode_);
+  int? hash = JS<int?>('int|Null', r'#[#]', object, dart.identityHashCode_);
   if (hash == null) {
     hash = JS<int>('!', '(Math.random() * 0x3fffffff) | 0');
     JS('void', r'#[#] = #', object, dart.identityHashCode_, hash);
@@ -49,7 +47,7 @@
 @patch
 class Object {
   @patch
-  bool operator ==(other) => identical(this, other);
+  bool operator ==(Object other) => identical(this, other);
 
   @patch
   int get hashCode => identityHashCode(this);
@@ -59,7 +57,7 @@
       "Instance of '${dart.typeName(dart.getReifiedType(this))}'";
 
   @patch
-  noSuchMethod(Invocation invocation) {
+  dynamic noSuchMethod(Invocation invocation) {
     return dart.defaultNoSuchMethod(this, invocation);
   }
 
@@ -77,8 +75,8 @@
 @patch
 class Function {
   @patch
-  static apply(Function f, List positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]) {
+  static apply(Function f, List<Object>? positionalArguments,
+      [Map<Symbol, dynamic>? namedArguments]) {
     positionalArguments ??= [];
     // dcall expects the namedArguments as a JS map in the last slot.
     if (namedArguments != null && namedArguments.isNotEmpty) {
@@ -104,18 +102,18 @@
 // TODO(jmesserly): switch to WeakMap
 // Patch for Expando implementation.
 @patch
-class Expando<T> {
+class Expando<T extends Object> {
   @patch
-  Expando([String name]) : this.name = name;
+  Expando([String? name]) : this.name = name;
 
   @patch
-  T operator [](Object object) {
+  T? operator [](Object object) {
     var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
     return (values == null) ? null : Primitives.getProperty(values, _getKey());
   }
 
   @patch
-  void operator []=(Object object, T value) {
+  void operator []=(Object object, T? value) {
     var values = Primitives.getProperty(object, _EXPANDO_PROPERTY_NAME);
     if (values == null) {
       values = Object();
@@ -144,17 +142,17 @@
 class int {
   @patch
   static int parse(String source,
-      {int radix, @deprecated int onError(String source)}) {
-    return Primitives.parseInt(source, radix, onError);
+      {int? radix, @deprecated int onError(String source)?}) {
+    return Primitives.parseInt(source, radix, onError)!;
   }
 
   @patch
-  static int tryParse(String source, {int radix}) {
+  static int? tryParse(String source, {int? radix}) {
     return Primitives.parseInt(source, radix, _kNull);
   }
 
   @patch
-  factory int.fromEnvironment(String name, {int defaultValue}) {
+  factory int.fromEnvironment(String name, {int defaultValue = 0}) {
     // ignore: const_constructor_throws_exception
     throw UnsupportedError(
         'int.fromEnvironment can only be used as a const constructor');
@@ -166,11 +164,11 @@
   @patch
   static double parse(String source,
       [@deprecated double onError(String source)]) {
-    return Primitives.parseDouble(source, onError);
+    return Primitives.parseDouble(source, onError)!;
   }
 
   @patch
-  static double tryParse(String source) {
+  static double? tryParse(String source) {
     return Primitives.parseDouble(source, _kNull);
   }
 }
@@ -185,11 +183,11 @@
   static BigInt get two => _BigIntImpl.two;
 
   @patch
-  static BigInt parse(String source, {int radix}) =>
+  static BigInt parse(String source, {int? radix}) =>
       _BigIntImpl.parse(source, radix: radix);
 
   @patch
-  static BigInt tryParse(String source, {int radix}) =>
+  static BigInt? tryParse(String source, {int? radix}) =>
       _BigIntImpl._tryParse(source, radix: radix);
 
   @patch
@@ -199,7 +197,7 @@
 @patch
 class Error {
   @patch
-  static String _objectToString(Object object) {
+  static String _objectToString(Object? object) {
     return "Instance of '${dart.typeName(dart.getReifiedType(object))}'";
   }
 
@@ -245,10 +243,7 @@
   @patch
   DateTime._internal(int year, int month, int day, int hour, int minute,
       int second, int millisecond, int microsecond, bool isUtc)
-      // checkBool is manually inlined here because dart2js doesn't inline it
-      // and [isUtc] is usually a constant.
-      : this.isUtc =
-            isUtc is bool ? isUtc : throw ArgumentError.value(isUtc, 'isUtc'),
+      : isUtc = isUtc,
         _value = checkInt(Primitives.valueFromDecomposedDate(
             year,
             month,
@@ -272,7 +267,7 @@
   }
 
   @patch
-  static int _brokenDownDateToValue(int year, int month, int day, int hour,
+  static int? _brokenDownDateToValue(int year, int month, int day, int hour,
       int minute, int second, int millisecond, int microsecond, bool isUtc) {
     return Primitives.valueFromDecomposedDate(
         year,
@@ -293,7 +288,7 @@
 
   @patch
   Duration get timeZoneOffset {
-    if (isUtc) return Duration();
+    if (isUtc) return Duration.zero;
     return Duration(minutes: Primitives.getTimeZoneOffsetInMinutes(this));
   }
 
@@ -370,9 +365,9 @@
 @patch
 class Stopwatch {
   @patch
-  static void _initTicker() {
+  static int _initTicker() {
     Primitives.initTicker();
-    _frequency = Primitives.timerFrequency;
+    return Primitives.timerFrequency;
   }
 
   @patch
@@ -416,6 +411,13 @@
   }
 
   @patch
+  factory List.empty({bool growable = false}) {
+    var list = JSArray<E>.of(JS('', 'new Array()'));
+    if (!growable) JSArray.markFixedList(list);
+    return list;
+  }
+
+  @patch
   factory List.filled(@nullCheck int length, E fill, {bool growable = false}) {
     var list = JSArray<E>.of(JS('', 'new Array(#)', length));
     JS('', '#.fill(#)', list, fill);
@@ -464,7 +466,7 @@
 class String {
   @patch
   factory String.fromCharCodes(Iterable<int> charCodes,
-      [int start = 0, int end]) {
+      [int start = 0, int? end]) {
     if (charCodes is JSArray) {
       return _stringFromJSArray(charCodes, start, end);
     }
@@ -480,7 +482,7 @@
   }
 
   @patch
-  factory String.fromEnvironment(String name, {String defaultValue}) {
+  factory String.fromEnvironment(String name, {String defaultValue = ""}) {
     // ignore: const_constructor_throws_exception
     throw UnsupportedError(
         'String.fromEnvironment can only be used as a const constructor');
@@ -489,7 +491,7 @@
   static String _stringFromJSArray(
       /*=JSArray<int>*/ list,
       int start,
-      int endOrNull) {
+      int? endOrNull) {
     int len = list.length;
     int end = RangeError.checkValidRange(start, endOrNull, len);
     if (start > 0 || end < len) {
@@ -499,14 +501,14 @@
   }
 
   static String _stringFromUint8List(
-      NativeUint8List charCodes, int start, int endOrNull) {
+      NativeUint8List charCodes, int start, int? endOrNull) {
     int len = charCodes.length;
     int end = RangeError.checkValidRange(start, endOrNull, len);
     return Primitives.stringFromNativeUint8List(charCodes, start, end);
   }
 
   static String _stringFromIterable(
-      Iterable<int> charCodes, int start, int end) {
+      Iterable<int> charCodes, int start, int? end) {
     if (start < 0) throw RangeError.range(start, 0, charCodes.length);
     if (end != null && end < start) {
       throw RangeError.range(end, start, charCodes.length);
@@ -565,7 +567,7 @@
 
 // Patch for 'identical' function.
 @patch
-bool identical(Object a, Object b) {
+bool identical(Object? a, Object? b) {
   return JS<bool>('!', '(# == null ? # == null : # === #)', a, b, a, b);
 }
 
@@ -580,7 +582,7 @@
   int get length => _contents.length;
 
   @patch
-  void write(Object obj) {
+  void write(Object? obj) {
     _writeString('$obj');
   }
 
@@ -595,7 +597,7 @@
   }
 
   @patch
-  void writeln([Object obj = ""]) {
+  void writeln([Object? obj = ""]) {
     _writeString('$obj\n');
   }
 
@@ -607,7 +609,7 @@
   @patch
   String toString() => Primitives.flattenString(_contents);
 
-  void _writeString(str) {
+  void _writeString(String str) {
     _contents = Primitives.stringConcatUnchecked(_contents, str);
   }
 
@@ -642,17 +644,17 @@
 
 @patch
 class NoSuchMethodError {
-  final Object _receiver;
+  final Object? _receiver;
   final Symbol _memberName;
-  final List _arguments;
-  final Map<Symbol, dynamic> _namedArguments;
-  final List _existingArgumentNames;
-  final Invocation _invocation;
+  final List? _arguments;
+  final Map<Symbol, dynamic>? _namedArguments;
+  final List? _existingArgumentNames;
+  final Invocation? _invocation;
 
   @patch
-  NoSuchMethodError(Object receiver, Symbol memberName,
-      List positionalArguments, Map<Symbol, dynamic> namedArguments,
-      [List existingArgumentNames = null])
+  NoSuchMethodError(Object? receiver, Symbol memberName,
+      List? positionalArguments, Map<Symbol, dynamic>? namedArguments,
+      [List? existingArgumentNames = null])
       : _receiver = receiver,
         _memberName = memberName,
         _arguments = positionalArguments,
@@ -661,7 +663,7 @@
         _invocation = null;
 
   @patch
-  NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
+  NoSuchMethodError.withInvocation(Object? receiver, Invocation invocation)
       : _receiver = receiver,
         _memberName = invocation.memberName,
         _arguments = invocation.positionalArguments,
@@ -673,15 +675,17 @@
   String toString() {
     StringBuffer sb = StringBuffer('');
     String comma = '';
-    if (_arguments != null) {
-      for (var argument in _arguments) {
+    var arguments = _arguments;
+    if (arguments != null) {
+      for (var argument in arguments) {
         sb.write(comma);
         sb.write(Error.safeToString(argument));
         comma = ', ';
       }
     }
-    if (_namedArguments != null) {
-      _namedArguments.forEach((Symbol key, var value) {
+    var namedArguments = _namedArguments;
+    if (namedArguments != null) {
+      namedArguments.forEach((Symbol key, var value) {
         sb.write(comma);
         sb.write(_symbolToString(key));
         sb.write(": ");
@@ -692,16 +696,18 @@
     String memberName = _symbolToString(_memberName);
     String receiverText = Error.safeToString(_receiver);
     String actualParameters = '$sb';
-    var failureMessage = (_invocation is dart.InvocationImpl)
-        ? (_invocation as dart.InvocationImpl).failureMessage
+    var invocation = _invocation;
+    var failureMessage = (invocation is dart.InvocationImpl)
+        ? invocation.failureMessage
         : 'method not found';
-    if (_existingArgumentNames == null) {
+    List? existingArgumentNames = _existingArgumentNames;
+    if (existingArgumentNames == null) {
       return "NoSuchMethodError: '$memberName'\n"
           "$failureMessage\n"
           "Receiver: ${receiverText}\n"
           "Arguments: [$actualParameters]";
     } else {
-      String formalParameters = _existingArgumentNames.join(', ');
+      String formalParameters = existingArgumentNames.join(', ');
       return "NoSuchMethodError: incorrect number of arguments passed to "
           "method named '$memberName'\n"
           "Receiver: ${receiverText}\n"
@@ -908,7 +914,7 @@
    * Throws a [FormatException] if the [source] is not a valid integer literal,
    * optionally prefixed by a sign.
    */
-  static _BigIntImpl parse(String source, {int radix}) {
+  static _BigIntImpl parse(String source, {int? radix}) {
     var result = _tryParse(source, radix: radix);
     if (result == null) {
       throw FormatException("Could not parse BigInt", source);
@@ -1020,7 +1026,7 @@
   /// Returns the parsed big integer, or `null` if it failed.
   ///
   /// If the [radix] is `null` accepts decimal literals or `0x` hex literals.
-  static _BigIntImpl _tryParse(String source, {int radix}) {
+  static _BigIntImpl? _tryParse(String source, {int? radix}) {
     if (source == "") return null;
 
     var match = _parseRE.firstMatch(source);
@@ -1032,9 +1038,9 @@
 
     bool isNegative = match[signIndex] == "-";
 
-    String decimalMatch = match[decimalIndex];
-    String hexMatch = match[hexIndex];
-    String nonDecimalMatch = match[nonDecimalHexIndex];
+    String? decimalMatch = match[decimalIndex];
+    String? hexMatch = match[hexIndex];
+    String? nonDecimalMatch = match[nonDecimalHexIndex];
 
     if (radix == null) {
       if (decimalMatch != null) {
@@ -1048,9 +1054,6 @@
       return null;
     }
 
-    if (radix is! int) {
-      throw ArgumentError.value(radix, 'radix', 'is not an integer');
-    }
     if (radix < 2 || radix > 36) {
       throw RangeError.range(radix, 2, 36, 'radix');
     }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart
index 4f2befc..7f5e4fe 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/developer_patch.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.5
-
 // Patch file for dart:developer library.
 
 import 'dart:_js_helper' show patch, ForceInline, ReifyFunctionTypes;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/io_patch.dart
index 595f4c2..8c28b56 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/io_patch.dart
@@ -450,7 +450,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog = 0, bool v6Only = false, bool shared = false}) {
     throw UnsupportedError("ServerSocket.bind");
   }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart
index eb5c568..fbd054c 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/math_patch.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.5
-
 // Patch file for dart:math library.
 import 'dart:_foreign_helper' show JS;
 import 'dart:_js_helper' show patch, nullCheck, notNull;
@@ -12,53 +10,52 @@
 @patch
 @notNull
 T min<T extends num>(@nullCheck T a, @nullCheck T b) =>
-    JS('-dynamic', r'Math.min(#, #)', a, b);
+    JS<T>('-dynamic', r'Math.min(#, #)', a, b);
 
 @patch
 @notNull
 T max<T extends num>(@nullCheck T a, @nullCheck T b) =>
-    JS('-dynamic', r'Math.max(#, #)', a, b);
+    JS<T>('-dynamic', r'Math.max(#, #)', a, b);
 
 @patch
 @notNull
-double sqrt(@nullCheck num x) => JS<num>('!', r'Math.sqrt(#)', x);
+double sqrt(@nullCheck num x) => JS<double>('!', r'Math.sqrt(#)', x);
 
 @patch
 @notNull
-double sin(@nullCheck num radians) => JS<num>('!', r'Math.sin(#)', radians);
+double sin(@nullCheck num radians) => JS<double>('!', r'Math.sin(#)', radians);
 
 @patch
 @notNull
-double cos(@nullCheck num radians) => JS<num>('!', r'Math.cos(#)', radians);
+double cos(@nullCheck num radians) => JS<double>('!', r'Math.cos(#)', radians);
 
 @patch
 @notNull
-double tan(@nullCheck num radians) => JS<num>('!', r'Math.tan(#)', radians);
+double tan(@nullCheck num radians) => JS<double>('!', r'Math.tan(#)', radians);
 
 @patch
 @notNull
-double acos(@nullCheck num x) => JS<num>('!', r'Math.acos(#)', x);
+double acos(@nullCheck num x) => JS<double>('!', r'Math.acos(#)', x);
 
 @patch
 @notNull
-double asin(@nullCheck num x) => JS<num>('!', r'Math.asin(#)', x);
+double asin(@nullCheck num x) => JS<double>('!', r'Math.asin(#)', x);
 
 @patch
 @notNull
-double atan(@nullCheck num x) => JS<num>('!', r'Math.atan(#)', x);
+double atan(@nullCheck num x) => JS<double>('!', r'Math.atan(#)', x);
 
 @patch
 @notNull
 double atan2(@nullCheck num a, @nullCheck num b) =>
-    JS<num>('!', r'Math.atan2(#, #)', a, b);
+    JS<double>('!', r'Math.atan2(#, #)', a, b);
+
+@patch
+double exp(num x) => JS<double>('!', r'Math.exp(#)', x);
 
 @patch
 @notNull
-double exp(@nullCheck num x) => JS<num>('!', r'Math.exp(#)', x);
-
-@patch
-@notNull
-double log(@nullCheck num x) => JS<num>('!', r'Math.log(#)', x);
+double log(@nullCheck num x) => JS<double>('!', r'Math.log(#)', x);
 
 @patch
 @notNull
@@ -69,10 +66,10 @@
 
 @patch
 class Random {
-  static Random _secureRandom;
+  static Random? _secureRandom;
 
   @patch
-  factory Random([int seed]) =>
+  factory Random([int? seed]) =>
       (seed == null) ? const _JSRandom() : _Random(seed);
 
   @patch
@@ -88,7 +85,7 @@
     if (max <= 0 || max > _POW2_32) {
       throw RangeError("max must be in range 0 < max ≤ 2^32, was $max");
     }
-    return JS("int", "(Math.random() * #) >>> 0", max);
+    return JS<int>("int", "(Math.random() * #) >>> 0", max);
   }
 
   /**
@@ -96,13 +93,13 @@
    * the range from 0.0, inclusive, to 1.0, exclusive.
    */
   @notNull
-  double nextDouble() => JS("double", "Math.random()");
+  double nextDouble() => JS<double>("double", "Math.random()");
 
   /**
    * Generates a random boolean value.
    */
   @notNull
-  bool nextBool() => JS("bool", "Math.random() < 0.5");
+  bool nextBool() => JS<bool>("bool", "Math.random() < 0.5");
 }
 
 class _Random implements Random {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
index a06bd14..f1e2dc1 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/typed_data_patch.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.5
-
 import 'dart:collection';
 import 'dart:_js_helper' show patch;
 import 'dart:_native_typed_data';
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index fb2b5b0..178ef43 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -118,6 +118,8 @@
 /// The Symbol for storing type arguments on a specialized generic type.
 final _typeArguments = JS('', 'Symbol("typeArguments")');
 
+final _variances = JS('', 'Symbol("variances")');
+
 final _originalDeclaration = JS('', 'Symbol("originalDeclaration")');
 
 final mixinNew = JS('', 'Symbol("dart.mixinNew")');
@@ -179,6 +181,12 @@
 List getGenericArgs(type) =>
     JS('List', '#', safeGetOwnProperty(type, _typeArguments));
 
+List getGenericArgVariances(type) =>
+    JS('List', '#', safeGetOwnProperty(type, _variances));
+
+void setGenericArgVariances(f, variances) =>
+    JS('', '#[#] = #', f, _variances, variances);
+
 List<TypeVariable> getGenericTypeFormals(genericClass) {
   return _typeFormalsFromFunction(getGenericTypeCtor(genericClass));
 }
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 224ba1c..b9e353d 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -185,14 +185,23 @@
   // Check if we have invalid named arguments.
   Iterable names;
   var named = type.named;
+  var requiredNamed = type.requiredNamed;
   if (namedActuals != null) {
     names = getOwnPropertyNames(namedActuals);
     for (var name in names) {
-      if (!JS('!', '#.hasOwnProperty(#)', named, name)) {
+      if (!JS('!', '(#.hasOwnProperty(#) || #.hasOwnProperty(#))', named, name,
+          requiredNamed, name)) {
         return "Dynamic call with unexpected named argument '$name'.";
       }
     }
   }
+  // Verify that all required named parameters are provided an argument.
+  Iterable requiredNames = getOwnPropertyNames(requiredNamed);
+  for (var name in requiredNames) {
+    if (!JS('!', '#.hasOwnProperty(#)', namedActuals, name)) {
+      return "Dynamic call with missing required named argument '$name'.";
+    }
+  }
   // Now that we know the signature matches, we can perform type checks.
   for (var i = 0; i < requiredCount; ++i) {
     JS('', '#[#]._check(#[#])', required, i, actuals, i);
@@ -202,7 +211,8 @@
   }
   if (names != null) {
     for (var name in names) {
-      JS('', '#[#]._check(#[#])', named, name, namedActuals, name);
+      JS('', '(#[#] || #[#])._check(#[#])', named, name, requiredNamed, name,
+          namedActuals, name);
     }
   }
   return null;
@@ -331,8 +341,8 @@
 dcall(f, args, [@undefined named]) => _checkAndCall(
     f, null, JS('', 'void 0'), null, args, named, JS('', 'f.name'));
 
-dgcall(f, typeArgs, args, [@undefined named]) =>
-    _checkAndCall(f, null, JS('', 'void 0'), typeArgs, args, named, 'call');
+dgcall(f, typeArgs, args, [@undefined named]) => _checkAndCall(f, null,
+    JS('', 'void 0'), typeArgs, args, named, JS('', "f.name || 'call'"));
 
 /// Helper for REPL dynamic invocation variants that make a best effort to
 /// enable accessing private members across library boundaries.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index 6ac07ee..965d5b5 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
@@ -154,6 +154,9 @@
   JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
   JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
   JS('', '#.set(#, #)', _loadedPartMaps, moduleName, parts);
+  _libraries = null;
+  _libraryObjects = null;
+  _parts = null;
 }
 
 List<String> _libraries;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 198ba6e..e74aa01 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -183,12 +183,20 @@
 @notNull
 final List<void Function()> _resetFields = JS('', '[]');
 
+/// A counter to track each time [hotRestart] is invoked. This is used to ensure
+/// that pending callbacks that were created on a previous iteration (e.g. a
+/// timer callback or a DOM callback) will not execute when they get invoked.
+// TODO(sigmund): consider whether we should track and cancel callbacks to
+// reduce memory leaks.
+int hotRestartIteration = 0;
+
 /// Clears out runtime state in `dartdevc` so we can hot-restart.
 ///
 /// This should be called when the user requests a hot-restart, when the UI is
 /// handling that user action.
 void hotRestart() {
-  // TODO(jmesserly): we need to prevent all pending callbacks from firing.
+  // TODO(sigmund): prevent DOM callbacks from firing.
+  hotRestartIteration++;
   for (var f in _resetFields) f();
   _resetFields.clear();
   for (var m in _cacheMaps) JS('', '#.clear()', m);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 4aa1238..b12494b 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -7,6 +7,13 @@
 /// This library defines the representation of runtime types.
 part of dart._runtime;
 
+/// Sets the mode of the runtime subtype checks.
+///
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) {
+  JS('', 'dart.__strictSubtypeChecks = #', flag);
+}
+
 final metadata = JS('', 'Symbol("metadata")');
 
 /// Types in dart are represented internally at runtime as follows.
@@ -202,43 +209,60 @@
   return ret;
 }
 
-/// Returns a nullable version of [type].
-///
-/// The resulting type will be normalized to avoid nesting the use of nullable
-/// (question) and legacy (star).
-@notNull
-DartType nullable(type) {
-  // Normalize and / or wrap the type.
-  // Given: T? -> T | Null
-  // Then: T?? -> T? | Null -> T | Null | Null -> T?
-  if (type is NullableType) return type;
-  // Then T*? -> (T? | T)? -> T?? | T? -> T?
-  if (type is LegacyType) return nullable(type.type);
+/// A javascript Symbol used to store a canonical version of T? on T.
+final _cachedNullable = JS('', 'Symbol("cachedNullable")');
 
-  return NullableType(type);
+/// A javascript Symbol used to store a canonical version of T* on T.
+final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
+
+/// Returns a nullable (question, ?) version of [type].
+///
+/// The resulting type returned in a normalized form based on the rules from the
+/// normalization doc: https://github.com/dart-lang/language/pull/456
+// TODO(nshahan): Update after the normalization doc PR lands.
+@notNull
+Object nullable(type) {
+  if (_isNullable(type) || _isTop(type) || _isNullType(type)) return type;
+  if (type == never_) return unwrapType(Null);
+  if (_isLegacy(type)) type = type.type;
+
+  // Check if a nullable version of this type has already been created.
+  if (JS<bool>('!', '#.hasOwnProperty(#)', type, _cachedNullable)) {
+    return JS<NullableType>('!', '#[#]', type, _cachedNullable);
+  }
+  // Cache a canonical nullable version of this type on this type.
+  var cachedType = NullableType(type);
+  JS('', '#[#] = #', type, _cachedNullable, cachedType);
+  return cachedType;
 }
 
-/// Returns a legacy version of [type].
+/// Returns a legacy (star, *) version of [type].
 ///
-/// The resulting type will be normalized to avoid nesting the use of nullable
-/// (question) and legacy (star).
+/// The resulting type returned in a normalized form based on the rules from the
+/// normalization doc: https://github.com/dart-lang/language/pull/456
+// TODO(nshahan): Update after the normalization doc PR lands.
 @notNull
 DartType legacy(type) {
-  // Normalize and / or wrap the type.
-  // Given: T* -> T? | T
-  // Then: T** -> T*? | T* ->  (T? | T)? | T? | T -> T? | T -> T*
-  // Then: T?* -> T?? | T? -> T?
-  if (type is LegacyType || type is NullableType) return type;
+  // TODO(nshahan) Maybe normailize never*,  Null*.
+  if (_isLegacy(type) || _isNullable(type) || _isTop(type)) return type;
 
-  return LegacyType(type);
+  // Check if a legacy version of this type has already been created.
+  if (JS<bool>('!', '#.hasOwnProperty(#)', type, _cachedLegacy)) {
+    return JS<NullableType>('!', '#[#]', type, _cachedLegacy);
+  }
+  // Cache a canonical legacy version of this type on this type.
+  var cachedType = LegacyType(type);
+  JS('', '#[#] = #', type, _cachedLegacy, cachedType);
+  return cachedType;
 }
 
-// TODO(nshahan) Revisit this representation to support caching of the subtype
-// check results.
+/// A wrapper to identify a nullable (question, ?) type of the form [type]?.
 class NullableType extends DartType {
   final Type type;
 
-  NullableType(this.type);
+  NullableType(this.type)
+      : assert(type is! NullableType),
+        assert(type is! LegacyType);
 
   @override
   String get name => '$type?';
@@ -247,12 +271,13 @@
   String toString() => name;
 }
 
-// TODO(nshahan) Revisit this representation to support caching of the subtype
-// check results.
+/// A wrapper to identify a legacy (star, *) type of the form [type]*.
 class LegacyType extends DartType {
   final Type type;
 
-  LegacyType(this.type);
+  LegacyType(this.type)
+      : assert(type is! LegacyType),
+        assert(type is! NullableType);
 
   @override
   String get name => '$type*';
@@ -401,7 +426,7 @@
  }
  let result = map.get($returnType);
  if (result !== void 0) return result;
- result = ${new FunctionType(returnType, required, [], JS('', '{}'))};
+ result = ${new FunctionType(returnType, required, [], JS('', '{}'), JS('', '{}'))};
  map.set($returnType, result);
  return result;
 })()''');
@@ -412,6 +437,7 @@
   List optionals;
   // Named arguments native JS Object of the form { namedArgName: namedArgType }
   final named;
+  final requiredNamed;
   // TODO(vsm): This is just parameter metadata for now.
   // Suspected but not confirmed: Only used by mirrors for pageloader2 support.
   // The metadata is represented as a list of JS arrays, one for each argument
@@ -430,30 +456,34 @@
   ///
   /// Note: Generic function subtype checks assume types have been canonicalized
   /// when testing if type bounds are equal.
-  static FunctionType create(returnType, List args, extra) {
-    // Note that if extra is ever passed as an empty array
-    // or an empty map, we can end up with semantically
-    // identical function types that don't canonicalize
-    // to the same object since we won't fall into this
-    // fast path.
-    if (extra == null && JS<bool>('!', '#.length < 3', args)) {
+  static FunctionType create(
+      returnType, List args, optionalArgs, requiredNamedArgs) {
+    // Note that if optionalArgs is ever passed as an empty array or an empty
+    // map, we can end up with semantically identical function types that don't
+    // canonicalize to the same object since we won't fall into this fast path.
+    var noOptionalArgs = optionalArgs == null && requiredNamedArgs == null;
+    if (noOptionalArgs && JS<bool>('!', '#.length < 3', args)) {
       return _createSmall(returnType, args);
     }
     args = _canonicalizeArray(args, _fnTypeArrayArgMap);
     var keys;
     FunctionType Function() create;
-    if (extra == null) {
+    if (noOptionalArgs) {
       keys = [returnType, args];
-      create = () => FunctionType(returnType, args, [], JS('', '{}'));
-    } else if (JS('!', '# instanceof Array', extra)) {
+      create =
+          () => FunctionType(returnType, args, [], JS('', '{}'), JS('', '{}'));
+    } else if (JS('!', '# instanceof Array', optionalArgs)) {
       var optionals =
-          _canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
+          _canonicalizeArray(JS('', '#', optionalArgs), _fnTypeArrayArgMap);
       keys = [returnType, args, optionals];
-      create = () => FunctionType(returnType, args, optionals, JS('', '{}'));
+      create = () =>
+          FunctionType(returnType, args, optionals, JS('', '{}'), JS('', '{}'));
     } else {
-      var named = _canonicalizeNamed(extra, _fnTypeNamedArgMap);
-      keys = [returnType, args, named];
-      create = () => FunctionType(returnType, args, [], named);
+      var named = _canonicalizeNamed(optionalArgs, _fnTypeNamedArgMap);
+      var requiredNamed =
+          _canonicalizeNamed(requiredNamedArgs, _fnTypeNamedArgMap);
+      keys = [returnType, args, named, requiredNamed];
+      create = () => FunctionType(returnType, args, [], named, requiredNamed);
     }
     return _memoizeArray(_fnTypeTypeMap, keys, create);
   }
@@ -478,7 +508,8 @@
     return result;
   }
 
-  FunctionType(this.returnType, this.args, this.optionals, this.named) {
+  FunctionType(this.returnType, this.args, this.optionals, this.named,
+      this.requiredNamed) {
     this.args = _process(this.args);
     this.optionals = _process(this.optionals);
     // TODO(vsm): Named arguments were never used by pageloader2 so they were
@@ -495,9 +526,10 @@
     return i < n ? args[i] : optionals[i + n];
   }
 
-  Map<String, Object> getNamedParameters() {
+  /// Maps argument names to their canonicalized type.
+  Map<String, Object> _createNameMap(List<String> names) {
     var result = <String, Object>{};
-    var names = getOwnPropertyNames(named);
+    // TODO: Remove this sort if ordering can be conserved.
     JS('', '#.sort()', names);
     for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
       String name = JS('!', '#[#]', names, i);
@@ -506,9 +538,16 @@
     return result;
   }
 
+  /// Maps optional named parameter names to their canonicalized type.
+  Map<String, Object> getNamedParameters() =>
+      _createNameMap(getOwnPropertyNames(named));
+
+  /// Maps required named parameter names to their canonicalized type.
+  Map<String, Object> getRequiredNamedParameters() =>
+      _createNameMap(getOwnPropertyNames(requiredNamed));
+
   get name {
     if (_stringValue != null) return _stringValue;
-
     var buffer = '(';
     for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
       if (i > 0) {
@@ -526,21 +565,32 @@
         buffer += typeName(JS('', '#[#]', optionals, i));
       }
       buffer += ']';
-    } else if (JS('!', 'Object.keys(#).length > 0', named)) {
+    } else if (JS('!', 'Object.keys(#).length > 0 || Object.keys(#).length > 0',
+        named, requiredNamed)) {
       if (JS('!', '#.length > 0', args)) buffer += ', ';
       buffer += '{';
       var names = getOwnPropertyNames(named);
       JS('', '#.sort()', names);
-      for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
+      for (var i = 0; JS<bool>('!', '# < #.length', i, names); i++) {
         if (i > 0) {
           buffer += ', ';
         }
         var typeNameString = typeName(JS('', '#[#[#]]', named, names, i));
         buffer += '$typeNameString ${JS('', '#[#]', names, i)}';
       }
+      if (JS('!', '#.length > 0', names)) buffer += ', ';
+      names = getOwnPropertyNames(requiredNamed);
+      JS('', '#.sort()', names);
+      for (var i = 0; JS<bool>('!', '# < #.length', i, names); i++) {
+        if (i > 0) {
+          buffer += ', ';
+        }
+        var typeNameString =
+            typeName(JS('', '#[#[#]]', requiredNamed, names, i));
+        buffer += 'required $typeNameString ${JS('', '#[#]', names, i)}';
+      }
       buffer += '}';
     }
-
     var returnTypeName = typeName(returnType);
     buffer += ') => $returnTypeName';
     _stringValue = buffer;
@@ -585,6 +635,13 @@
   toString() => name;
 }
 
+class Variance {
+  static const int unrelated = 0;
+  static const int covariant = 1;
+  static const int contravariant = 2;
+  static const int invariant = 3;
+}
+
 class GenericFunctionType extends AbstractFunctionType {
   final _instantiateTypeParts;
   final int formalCount;
@@ -619,8 +676,8 @@
 
   FunctionType instantiate(typeArgs) {
     var parts = JS('', '#.apply(null, #)', _instantiateTypeParts, typeArgs);
-    return FunctionType.create(
-        JS('', '#[0]', parts), JS('', '#[1]', parts), JS('', '#[2]', parts));
+    return FunctionType.create(JS('', '#[0]', parts), JS('', '#[1]', parts),
+        JS('', '#[2]', parts), JS('', '#[3]', parts));
   }
 
   List instantiateTypeBounds(List typeArgs) {
@@ -778,8 +835,9 @@
 }
 
 /// Create a function type.
-FunctionType fnType(returnType, List args, [@undefined extra]) =>
-    FunctionType.create(returnType, args, extra);
+FunctionType fnType(returnType, List args,
+        [@undefined optional, @undefined requiredNamed]) =>
+    FunctionType.create(returnType, args, optional, requiredNamed);
 
 /// Creates a generic function type from [instantiateFn] and [typeBounds].
 ///
@@ -853,7 +911,7 @@
 })()''');
 
 /// Returns true if [ft1] <: [ft2].
-_isFunctionSubtype(ft1, ft2) => JS('', '''(() => {
+_isFunctionSubtype(ft1, ft2, bool strictMode) => JS('', '''(() => {
   let ret1 = $ft1.returnType;
   let ret2 = $ft2.returnType;
 
@@ -865,7 +923,7 @@
   }
 
   for (let i = 0; i < args1.length; ++i) {
-    if (!$_isSubtype(args2[i], args1[i])) {
+    if (!$_isSubtype(args2[i], args1[i], strictMode)) {
       return false;
     }
   }
@@ -879,21 +937,35 @@
 
   let j = 0;
   for (let i = args1.length; i < args2.length; ++i, ++j) {
-    if (!$_isSubtype(args2[i], optionals1[j])) {
+    if (!$_isSubtype(args2[i], optionals1[j], strictMode)) {
       return false;
     }
   }
 
   for (let i = 0; i < optionals2.length; ++i, ++j) {
-    if (!$_isSubtype(optionals2[i], optionals1[j])) {
+    if (!$_isSubtype(optionals2[i], optionals1[j], strictMode)) {
       return false;
     }
   }
 
+  // Named parameter invariants:
+  // 1) All named params in the superclass are named params in the subclass.
+  // 2) All required named params in the subclass are required named params
+  //    in the superclass.
   let named1 = $ft1.named;
+  let requiredNamed1 = $ft1.requiredNamed;
   let named2 = $ft2.named;
+  let requiredNamed2 = $ft2.requiredNamed;
 
-  let names = $getOwnPropertyNames(named2);
+  let names = $getOwnPropertyNames(requiredNamed1);
+  for (let i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let n2 = requiredNamed2[name];
+    if (n2 === void 0) {
+      return false;
+    }
+  }
+  names = $getOwnPropertyNames(named2);
   for (let i = 0; i < names.length; ++i) {
     let name = names[i];
     let n1 = named1[name];
@@ -901,12 +973,24 @@
     if (n1 === void 0) {
       return false;
     }
+    if (!$_isSubtype(n2, n1, strictMode)) {
+      return false;
+    }
+  }
+  names = $getOwnPropertyNames(requiredNamed2);
+  for (let i = 0; i < names.length; ++i) {
+    let name = names[i];
+    let n1 = named1[name] || requiredNamed1[name];
+    let n2 = requiredNamed2[name];
+    if (n1 === void 0) {
+      return false;
+    }
     if (!$_isSubtype(n2, n1)) {
       return false;
     }
   }
 
-  return $_isSubtype(ret1, ret2);
+  return $_isSubtype(ret1, ret2, strictMode);
 })()''');
 
 /// Returns true if [t1] <: [t2].
@@ -914,73 +998,87 @@
 bool isSubtypeOf(Object t1, Object t2) {
   // TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, so they're
   // dispatched on the type. Can we optimize the subtype relation too?
-  // Object map;
-  // if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
-  //   JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
-  //   _cacheMaps.add(map);
-  // } else {
-  //   map = JS('', '#[#]', t1, _subtypeCache);
-  //   bool result = JS('', '#.get(#)', map, t2);
-  //   if (JS('!', '# !== void 0', result)) return result;
-  // }
-  // TODO(nshahan) Read and write cache when it's stored on nnbd-wrapper type.
-  // TODO(nshahan): Add support for strict/weak mode.
-  var result = _isSubtype(t1, t2);
-  // JS('', '#.set(#, #)', map, t2, result);
-  return result;
+  Object map;
+  if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
+    JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
+    _cacheMaps.add(map);
+  } else {
+    map = JS('', '#[#]', t1, _subtypeCache);
+    bool result = JS('', '#.get(#)', map, t2);
+    if (JS('!', '# !== void 0', result)) return result;
+  }
+  var validSubtype = _isSubtype(t1, t2, true);
+
+  if (!validSubtype && !JS<bool>('!', 'dart.__strictSubtypeChecks')) {
+    validSubtype = _isSubtype(t1, t2, false);
+    if (validSubtype) {
+      // TODO(nshahan) Need more information to be helpful here.
+      // File and line number that caused the subtype check?
+      // Possibly break into debuger?
+      _warn("$t1 is not a subtype of $t2.\n"
+          "This will be a runtime failure when strict mode is enabled.");
+    }
+  }
+  JS('', '#.set(#, #)', map, t2, validSubtype);
+  return validSubtype;
 }
 
 final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
 
-// TODO(nshahan): Add support for strict/weak mode.
 @notNull
-bool _isBottom(type) => JS('!', '# == #', type, bottom);
+bool _isBottom(type, strictMode) =>
+    JS('!', '# == # || (!# && #)', type, bottom, strictMode, _isNullType(type));
 
 // TODO(nshahan): Add support for strict/weak mode.
 @notNull
 bool _isTop(type) {
-  if (_isFutureOr(type)) {
-    return _isTop(JS('', '#[0]', getGenericArgs(type)));
-  }
-
-  if (_isNullable(type)) {
-    if (JS('!', '# == #', type.type, Object)) {
-      return true;
-    }
-    // TODO(nshahan): Revisit after deciding on normalization of NNBD top types.
-    // TODO(nshahan): Handle Object* in a way that ensures
-    // instanceOf(null, Object*) returns true.
-    return _isTop(type.type);
-  }
-
-  if (_isLegacy(type)) {
-    // TODO(nshahan): Revisit after deciding on normalization of NNBD top types.
-    return _isTop(type.type);
-  }
+  // TODO(nshahan): Handle Object* in a way that ensures
+  // instanceOf(null, Object*) returns true.
+  if (_isFutureOr(type)) return _isTop(JS('', '#[0]', getGenericArgs(type)));
+  if (_isNullable(type)) return (JS('!', '# == #', type.type, Object));
 
   return JS('!', '# == # || # == #', type, dynamic, type, void_);
 }
 
-_isNullable(Type type) => JS<bool>('!', '$type instanceof $NullableType');
-_isLegacy(Type type) => JS<bool>('!', '$type instanceof $LegacyType');
+/// Returns `true` if [type] represents a nullable (question, ?) type.
+@notNull
+bool _isNullable(Type type) => JS<bool>('!', '$type instanceof $NullableType');
+
+/// Returns `true` if [type] represents a legacy (star, *) type.
+@notNull
+bool _isLegacy(Type type) => JS<bool>('!', '$type instanceof $LegacyType');
+
+/// Returns `true` if [type] is the [Null] type.
+@notNull
+bool _isNullType(Object type) => identical(type, unwrapType(Null));
 
 @notNull
 bool _isFutureOr(type) =>
     identical(getGenericClass(type), getGenericClass(FutureOr));
 
-bool _isSubtype(t1, t2) => JS('bool', '''(() => {
+bool _isSubtype(t1, t2, bool strictMode) => JS('bool', '''(() => {
+  if (!$strictMode) {
+    // Strip nullable types when performing check in weak mode.
+    // TODO(nshahan) Investigate stripping off legacy types as well.
+    if (${_isNullable(t1)}) {
+      t1 = t1.type;
+    }
+    if (${_isNullable(t2)}) {
+      t2 = t2.type;
+    }
+  }
   if ($t1 === $t2) {
     return true;
   }
 
   // Trivially true, "Right Top" or "Left Bottom".
-  if (${_isTop(t2)} || ${_isBottom(t1)}) {
+  if (${_isTop(t2)} || ${_isBottom(t1, strictMode)}) {
     return true;
   }
 
   // "Left Top".
   if ($t1 == $dynamic || $t1 == $void_) {
-    return $_isSubtype($nullable($Object), $t2);
+    return $_isSubtype($nullable($Object), $t2, $strictMode);
   }
 
   // "Right Object".
@@ -989,15 +1087,15 @@
     // https://github.com/dart-lang/sdk/issues/38816
     if (${_isFutureOr(t1)}) {
       let t1TypeArg = ${getGenericArgs(t1)}[0];
-      return $_isSubtype(t1TypeArg, $Object);
+      return $_isSubtype(t1TypeArg, $Object, $strictMode);
     }
 
     if (${_isLegacy(t1)}) {
-      return $_isSubtype(t1.type, t2);
+      return $_isSubtype(t1.type, t2, $strictMode);
     }
 
-    if ($t1 == $dynamic || $t1 == $void_ || $t1 == $Null
-        || ${_isNullable(t1)}) {
+    if (${_isNullType(t1)} || ${_isNullable(t1)}) {
+      // Checks for t1 is dynamic or void already performed in "Left Top" test.
       return false;
     }
     return true;
@@ -1009,7 +1107,7 @@
     // https://github.com/dart-lang/sdk/issues/38816
     if (${_isFutureOr(t2)}) {
       let t2TypeArg = ${getGenericArgs(t2)}[0];
-      return $_isSubtype($Null, t2TypeArg);
+      return $_isSubtype($Null, t2TypeArg, $strictMode);
     }
 
     return $t2 == $Null || ${_isLegacy(t2)} || ${_isNullable(t2)};
@@ -1017,12 +1115,12 @@
 
   // "Left Legacy".
   if (${_isLegacy(t1)}) {
-    return $_isSubtype(t1.type, t2);
+    return $_isSubtype(t1.type, t2, $strictMode);
   }
 
   // "Right Legacy".
   if (${_isLegacy(t2)}) {
-    return $_isSubtype(t1, $nullable(t2.type));
+    return $_isSubtype(t1, $nullable(t2.type), $strictMode);
   }
 
   // Handle FutureOr<T> union type.
@@ -1033,21 +1131,21 @@
       // FutureOr<A> <: FutureOr<B> iff A <: B
       // TODO(nshahan): Proven to not actually be true and needs cleanup.
       // https://github.com/dart-lang/sdk/issues/38818
-      return $_isSubtype(t1TypeArg, t2TypeArg);
+      return $_isSubtype(t1TypeArg, t2TypeArg, $strictMode);
     }
 
     // given t1 is Future<A> | A, then:
     // (Future<A> | A) <: t2 iff Future<A> <: t2 and A <: t2.
     let t1Future = ${getGenericClass(Future)}(t1TypeArg);
     // Known to handle the case FutureOr<Null> <: Future<Null>.
-    return $_isSubtype(t1Future, $t2) && $_isSubtype(t1TypeArg, $t2);
+    return $_isSubtype(t1Future, $t2, $strictMode) && $_isSubtype(t1TypeArg, $t2, $strictMode);
   }
 
   // "Left Nullable".
   if (${_isNullable(t1)}) {
     // TODO(nshahan) Need to handle type variables.
     // https://github.com/dart-lang/sdk/issues/38816
-    return $_isSubtype(t1.type, t2) && $_isSubtype($Null, t2);
+    return $_isSubtype(t1.type, t2, $strictMode) && $_isSubtype($Null, t2, $strictMode);
   }
 
   if ($_isFutureOr($t2)) {
@@ -1057,14 +1155,14 @@
     let t2Future = ${getGenericClass(Future)}(t2TypeArg);
     // TODO(nshahan) Need to handle type variables on the left.
     // https://github.com/dart-lang/sdk/issues/38816
-    return $_isSubtype($t1, t2Future) || $_isSubtype($t1, t2TypeArg);
+    return $_isSubtype($t1, t2Future, $strictMode) || $_isSubtype($t1, t2TypeArg, $strictMode);
   }
 
   // "Right Nullable".
   if (${_isNullable(t2)}) {
     // TODO(nshahan) Need to handle type variables.
     // https://github.com/dart-lang/sdk/issues/38816
-    return $_isSubtype(t1, t2.type) || $_isSubtype(t1, $Null);
+    return $_isSubtype(t1, t2.type, $strictMode) || $_isSubtype(t1, $Null, $strictMode);
   }
 
   // "Traditional" name-based subtype check.  Avoid passing
@@ -1085,7 +1183,7 @@
     }
 
     // Compare two interface types.
-    return ${_isInterfaceSubtype(t1, t2)};
+    return ${_isInterfaceSubtype(t1, t2, strictMode)};
   }
 
   // Function subtyping.
@@ -1143,10 +1241,10 @@
   }
 
   // Handle non-generic functions.
-  return ${_isFunctionSubtype(t1, t2)};
+  return ${_isFunctionSubtype(t1, t2, strictMode)};
 })()''');
 
-bool _isInterfaceSubtype(t1, t2) => JS('', '''(() => {
+bool _isInterfaceSubtype(t1, t2, strictMode) => JS('', '''(() => {
   // If we have lazy JS types, unwrap them.  This will effectively
   // reduce to a prototype check below.
   if ($t1 instanceof $LazyJSType) $t1 = $t1.rawJSTypeForCheck();
@@ -1179,21 +1277,35 @@
     if (typeArguments1.length != typeArguments2.length) {
       $assertFailed();
     }
+    let variances = $getGenericArgVariances($t1);
     for (let i = 0; i < typeArguments1.length; ++i) {
-      if (!$_isSubtype(typeArguments1[i], typeArguments2[i])) {
-        return false;
+      // When using implicit variance, variances will be undefined and
+      // considered covariant.
+      if (variances === void 0 || variances[i] == ${Variance.covariant}) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode)) {
+          return false;
+        }
+      } else if (variances[i] == ${Variance.contravariant}) {
+        if (!$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
+          return false;
+        }
+      } else if (variances[i] == ${Variance.invariant}) {
+        if (!$_isSubtype(typeArguments1[i], typeArguments2[i], $strictMode) ||
+            !$_isSubtype(typeArguments2[i], typeArguments1[i], $strictMode)) {
+          return false;
+        }
       }
     }
     return true;
   }
 
-  if ($_isInterfaceSubtype(t1.__proto__, $t2)) {
+  if ($_isInterfaceSubtype(t1.__proto__, $t2, $strictMode)) {
     return true;
   }
 
   // Check mixin.
   let m1 = $getMixin($t1);
-  if (m1 != null && $_isInterfaceSubtype(m1, $t2)) {
+  if (m1 != null && $_isInterfaceSubtype(m1, $t2, $strictMode)) {
     return true;
   }
 
@@ -1201,7 +1313,7 @@
   let getInterfaces = $getImplements($t1);
   if (getInterfaces) {
     for (let i1 of getInterfaces()) {
-      if ($_isInterfaceSubtype(i1, $t2)) {
+      if ($_isInterfaceSubtype(i1, $t2, $strictMode)) {
         return true;
       }
     }
@@ -1311,8 +1423,19 @@
         return false;
       }
     }
+
+    // Named parameter invariants:
+    // 1) All named params in the superclass are named params in the subclass.
+    // 2) All required named params in the subclass are required named params
+    //    in the superclass.
     var supertypeNamed = supertype.getNamedParameters();
+    var supertypeRequiredNamed = supertype.getRequiredNamedParameters();
     var subtypeNamed = supertype.getNamedParameters();
+    var subtypeRequiredNamed = supertype.getRequiredNamedParameters();
+    for (var name in subtypeRequiredNamed.keys) {
+      var supertypeParamType = supertypeRequiredNamed[name];
+      if (supertypeParamType == null) return false;
+    }
     for (var name in supertypeNamed.keys) {
       var subtypeParamType = subtypeNamed[name];
       if (subtypeParamType == null) return false;
@@ -1320,6 +1443,12 @@
         return false;
       }
     }
+    for (var name in supertypeRequiredNamed.keys) {
+      var subtypeParamType = subtypeRequiredNamed[name] ?? subtypeNamed[name];
+      if (!_isSubtypeMatch(supertypeRequiredNamed[name], subtypeParamType)) {
+        return false;
+      }
+    }
     return true;
   }
 
@@ -1357,8 +1486,6 @@
     return true;
   }
 
-  bool _isNull(Object type) => identical(type, unwrapType(Null));
-
   /// Attempts to match [subtype] as a subtype of [supertype], gathering any
   /// constraints discovered in the process.
   ///
@@ -1391,7 +1518,7 @@
     if (_isTop(supertype)) return true;
     // `Null` is a subtype match for any type `Q` under no constraints.
     // Note that nullable types will change this.
-    if (_isNull(subtype)) return true;
+    if (_isNullType(subtype)) return true;
 
     // Handle FutureOr<T> union type.
     if (_isFutureOr(subtype)) {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
index ad4ec46..44824c7 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
@@ -41,11 +41,14 @@
 
   TimerImpl(int milliseconds, void callback()) : _once = true {
     if (hasTimer()) {
+      int currentHotRestartIteration = dart.hotRestartIteration;
       void internalCallback() {
         _handle = null;
         dart.removeAsyncCallback();
         _tick = 1;
-        callback();
+        if (currentHotRestartIteration == dart.hotRestartIteration) {
+          callback();
+        }
       }
 
       dart.addAsyncCallback();
@@ -62,7 +65,12 @@
     if (hasTimer()) {
       dart.addAsyncCallback();
       int start = JS<int>('!', 'Date.now()');
+      int currentHotRestartIteration = dart.hotRestartIteration;
       _handle = JS<int>('!', '#.setInterval(#, #)', global, () {
+        if (currentHotRestartIteration != dart.hotRestartIteration) {
+          cancel();
+          return;
+        }
         int tick = this._tick + 1;
         if (milliseconds > 0) {
           int duration = JS<int>('!', 'Date.now()') - start;
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart
index 13fc0b5..2a7a621 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.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.5
-
 /**
  * Specialized integers and floating point numbers,
  * with SIMD support and efficient lists.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index fb0ee04..ecd69c65 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -81,7 +81,9 @@
   bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp);
   bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp);
   bool get _isUnicode => JS("bool", "#.unicode", _nativeRegExp);
-  bool get _isDotAll => JS("bool", "#.dotAll", _nativeRegExp);
+  // The "dotAll" property is not available on all browsers, but our internals
+  // currently assume this is non-null.  Coerce to false if not present.
+  bool get _isDotAll => JS("bool", "#.dotAll == true", _nativeRegExp);
 
   static makeNative(@nullCheck String source, bool multiLine,
       bool caseSensitive, bool unicode, bool dotAll, bool global) {
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
index 64c10cd..e31c549 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
@@ -386,9 +386,9 @@
 @patch
 class Stopwatch {
   @patch
-  static void _initTicker() {
+  static int _initTicker() {
     Primitives.initTicker();
-    _frequency = Primitives.timerFrequency;
+    return Primitives.timerFrequency;
   }
 
   @patch
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart
index 8460b21..48946c3 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/io_patch.dart
@@ -450,7 +450,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog: 0, bool v6Only: false, bool shared: false}) {
     throw new UnsupportedError("ServerSocket.bind");
   }
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
index eda4d66..3cefb05 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2562,17 +2562,11 @@
 
   String toString() {
     String name;
-    if (JS_GET_FLAG('USE_NEW_RTI')) {
-      var constructor = JS('', '#.constructor', this);
-      name =
-          constructor == null ? null : JS('String|Null', '#.name', constructor);
-      if (name == null) name = 'unknown';
-    } else {
-      name = Primitives.objectTypeName(this);
-      // Mirrors puts a space in front of some names, so remove it.
-      name = JS('String', '#.trim()', name);
-    }
-    return "Closure '$name'";
+    var constructor = JS('', '#.constructor', this);
+    name =
+        constructor == null ? null : JS('String|Null', '#.name', constructor);
+    if (name == null) name = 'unknown';
+    return "Closure '${unminifyOrTag(name)}'";
   }
 }
 
@@ -3082,9 +3076,9 @@
 futureOrCast(o, futureOrRti) => subtypeOfRuntimeTypeCast(o, futureOrRti);
 
 @pragma('dart2js:noInline')
-void checkDeferredIsLoaded(String loadId, String uri) {
+void checkDeferredIsLoaded(String loadId) {
   if (!_loadedLibraries.contains(loadId)) {
-    throw new DeferredNotLoadedError(uri);
+    throw new DeferredNotLoadedError(loadId);
   }
 }
 
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 0f35ac9..1bda4e3 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -131,17 +131,18 @@
   static const kindDynamic = 2;
   static const kindVoid = 3; // TODO(sra): Use `dynamic` instead?
   static const kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
+  static const kindErased = 5;
   // Unary terms.
-  static const kindStar = 5;
-  static const kindQuestion = 6;
-  static const kindFutureOr = 7;
+  static const kindStar = 6;
+  static const kindQuestion = 7;
+  static const kindFutureOr = 8;
   // More complex terms.
-  static const kindInterface = 8;
+  static const kindInterface = 9;
   // A vector of type parameters from enclosing functions and closures.
-  static const kindBinding = 9;
-  static const kindFunction = 10;
-  static const kindGenericFunction = 11;
-  static const kindGenericFunctionParameter = 12;
+  static const kindBinding = 10;
+  static const kindFunction = 11;
+  static const kindGenericFunction = 12;
+  static const kindGenericFunctionParameter = 13;
 
   static bool _isUnionOfFunctionType(Rti rti) {
     int kind = Rti._getKind(rti);
@@ -404,6 +405,7 @@
 Rti _instantiate(universe, Rti rti, Object typeArguments, int depth) {
   int kind = Rti._getKind(rti);
   switch (kind) {
+    case Rti.kindErased:
     case Rti.kindNever:
     case Rti.kindDynamic:
     case Rti.kindVoid:
@@ -648,7 +650,8 @@
 
 Rti _instanceTypeFromConstructor(constructor) {
   // TODO(sra): Cache Rti on constructor.
-  return findType(JS('String', '#.name', constructor));
+  return _Universe.findErasedType(
+      _theUniverse(), JS('String', '#.name', constructor));
 }
 
 /// Returns the structural function type of [object], or `null` if the object is
@@ -711,6 +714,52 @@
 }
 
 /// Called from generated code.
+///
+/// The first time the default `_is` method is called, it replaces itself with a
+/// specialized version.
+// TODO(sra): Emit code to force-replace the `_is` method, generated dependent
+// on the types used in the program. e.g.
+//
+//     findType("bool")._is = H._isBool;
+//
+// This could be omitted if (1) the `bool` rti is not used directly for a test
+// (e.g. we lower a check to a direct helper), and (2) `bool` does not flow to a
+// tested type parameter. The trick will be to ensure that `H._isBool` is
+// generated.
+bool _installSpecializedIsTest(object) {
+  // This static method is installed on an Rti object as a JavaScript instance
+  // method. The Rti object is 'this'.
+  Rti testRti = _castToRti(JS('', 'this'));
+  int kind = Rti._getKind(testRti);
+
+  var isFn = RAW_DART_FUNCTION_REF(_generalIsTestImplementation);
+
+  if (isTopType(testRti)) {
+    isFn = RAW_DART_FUNCTION_REF(_isTop);
+    var asFn = RAW_DART_FUNCTION_REF(_asTop);
+    Rti._setAsCheckFunction(testRti, asFn);
+    Rti._setTypeCheckFunction(testRti, asFn);
+  } else if (kind == Rti.kindInterface) {
+    String key = Rti._getCanonicalRecipe(testRti);
+
+    if (JS_GET_NAME(JsGetName.INT_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isInt);
+    } else if (JS_GET_NAME(JsGetName.DOUBLE_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isNum);
+    } else if (JS_GET_NAME(JsGetName.NUM_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isNum);
+    } else if (JS_GET_NAME(JsGetName.STRING_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isString);
+    } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
+      isFn = RAW_DART_FUNCTION_REF(_isBool);
+    }
+  }
+
+  Rti._setIsTestFunction(testRti, isFn);
+  return Rti._isCheck(testRti, object);
+}
+
+/// Called from generated code.
 bool _generalIsTestImplementation(object) {
   // This static method is installed on an Rti object as a JavaScript instance
   // method. The Rti object is 'this'.
@@ -798,6 +847,18 @@
 // Specializations can be placed on Rti objects as the _as, _check and _is
 // 'methods'. They can also be called directly called from generated code.
 
+/// Specialization for 'is dynamic' and other top types.
+/// Called from generated code via Rti `_is` method.
+bool _isTop(object) {
+  return true;
+}
+
+/// Specialization for 'as dynamic' and other top types.
+/// Called from generated code via Rti `_as` and `_check` methods.
+dynamic _asTop(object) {
+  return object;
+}
+
 /// Specialization for 'is bool'.
 /// Called from generated code.
 bool _isBool(object) {
@@ -1010,6 +1071,7 @@
 String _rtiToString(Rti rti, List<String> genericContext) {
   int kind = Rti._getKind(rti);
 
+  if (kind == Rti.kindErased) return 'erased';
   if (kind == Rti.kindDynamic) return 'dynamic';
   if (kind == Rti.kindVoid) return 'void';
   if (kind == Rti.kindNever) return 'Never';
@@ -1123,6 +1185,7 @@
 String _rtiToDebugString(Rti rti) {
   int kind = Rti._getKind(rti);
 
+  if (kind == Rti.kindErased) return 'erased';
   if (kind == Rti.kindDynamic) return 'dynamic';
   if (kind == Rti.kindVoid) return 'void';
   if (kind == Rti.kindNever) return 'Never';
@@ -1199,10 +1262,12 @@
         '{'
             '#: new Map(),'
             '#: {},'
+            '#: {},'
             '#: [],' // shared empty array.
             '}',
         RtiUniverseFieldNames.evalCache,
         RtiUniverseFieldNames.typeRules,
+        RtiUniverseFieldNames.erasedTypes,
         RtiUniverseFieldNames.sharedEmptyArray);
   }
 
@@ -1214,6 +1279,9 @@
   static Object typeRules(universe) =>
       JS('', '#.#', universe, RtiUniverseFieldNames.typeRules);
 
+  static Object erasedTypes(universe) =>
+      JS('', '#.#', universe, RtiUniverseFieldNames.erasedTypes);
+
   static Object _findRule(universe, String targetType) =>
       JS('', '#.#', typeRules(universe), targetType);
 
@@ -1225,17 +1293,32 @@
     return rule;
   }
 
-  static void addRules(universe, rules) {
-    // TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
-    var keys = JS('JSArray', 'Object.keys(#)', rules);
-    int length = _Utils.arrayLength(keys);
-    Object ruleset = typeRules(universe);
-    for (int i = 0; i < length; i++) {
-      String targetType = _Utils.asString(_Utils.arrayAt(keys, i));
-      JS('', '#[#] = #[#]', ruleset, targetType, rules, targetType);
+  static Rti findErasedType(universe, String cls) {
+    Object metadata = erasedTypes(universe);
+    var probe = JS('', '#.#', metadata, cls);
+    if (probe == null) {
+      return eval(universe, cls);
+    } else if (_Utils.isNum(probe)) {
+      int length = _Utils.asInt(probe);
+      Rti erased = _lookupErasedRti(universe);
+      Object arguments = JS('', '[]');
+      for (int i = 0; i < length; i++) {
+        _Utils.arrayPush(arguments, erased);
+      }
+      Rti interface = _lookupInterfaceRti(universe, cls, arguments);
+      JS('', '#.# = #', metadata, cls, interface);
+      return interface;
+    } else {
+      return _castToRti(probe);
     }
   }
 
+  static void addRules(universe, rules) =>
+      _Utils.objectAssign(typeRules(universe), rules);
+
+  static void addErasedTypes(universe, types) =>
+      _Utils.objectAssign(erasedTypes(universe), types);
+
   static Object sharedEmptyArray(universe) =>
       JS('JSArray', '#.#', universe, RtiUniverseFieldNames.sharedEmptyArray);
 
@@ -1317,26 +1400,13 @@
     String key = Rti._getCanonicalRecipe(rti);
     _cacheSet(evalCache(universe), key, rti);
 
-    // Set up methods to perform type tests.
-
-    // TODO(sra): Find better way to install specializations. Perhaps the
-    // installed version should replace itself with the specialization.
+    // Set up methods to perform type tests. The general as-check / type-check
+    // methods use the is-test method. The is-test method on first use
+    // overwrites itself, and possibly the as-check / type-check methods, with a
+    // specialized version.
     var checkFn = RAW_DART_FUNCTION_REF(_generalTypeCheckImplementation);
     var asFn = RAW_DART_FUNCTION_REF(_generalAsCheckImplementation);
-    var isFn = RAW_DART_FUNCTION_REF(_generalIsTestImplementation);
-
-    if (JS_GET_NAME(JsGetName.INT_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isInt);
-    } else if (JS_GET_NAME(JsGetName.DOUBLE_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isNum);
-    } else if (JS_GET_NAME(JsGetName.NUM_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isNum);
-    } else if (JS_GET_NAME(JsGetName.STRING_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isString);
-    } else if (JS_GET_NAME(JsGetName.BOOL_RECIPE) == key) {
-      isFn = RAW_DART_FUNCTION_REF(_isBool);
-    }
-
+    var isFn = RAW_DART_FUNCTION_REF(_installSpecializedIsTest);
     Rti._setAsCheckFunction(rti, asFn);
     Rti._setTypeCheckFunction(rti, checkFn);
     Rti._setIsTestFunction(rti, isFn);
@@ -1351,6 +1421,7 @@
   //   for the proposed type.
   // * `createXXX` to create the type if it does not exist.
 
+  static String _canonicalRecipeOfErased() => Recipe.pushErasedString;
   static String _canonicalRecipeOfDynamic() => Recipe.pushDynamicString;
   static String _canonicalRecipeOfVoid() => Recipe.pushVoidString;
   static String _canonicalRecipeOfNever() =>
@@ -1368,6 +1439,11 @@
   static String _canonicalRecipeOfGenericFunctionParameter(int index) =>
       '$index' + Recipe.genericFunctionTypeParameterIndexString;
 
+  static Rti _lookupErasedRti(universe) {
+    return _lookupTerminalRti(
+        universe, Rti.kindErased, _canonicalRecipeOfErased());
+  }
+
   static Rti _lookupDynamicRti(universe) {
     return _lookupTerminalRti(
         universe, Rti.kindDynamic, _canonicalRecipeOfDynamic());
@@ -1655,6 +1731,8 @@
 ///
 ///   Used to separate elements.
 ///
+/// '#': --- erasedType
+///
 /// '@': --- dynamicType
 ///
 /// '~': --- voidType
@@ -1815,6 +1893,10 @@
                 toGenericFunctionParameter(universe(parser), pop(stack)));
             break;
 
+          case Recipe.pushErased:
+            push(stack, _Universe._lookupErasedRti(universe(parser)));
+            break;
+
           case Recipe.pushDynamic:
             push(stack, _Universe._lookupDynamicRti(universe(parser)));
             break;
@@ -2037,10 +2119,6 @@
   static Rti toType(Object universe, Rti environment, Object item) {
     if (_Utils.isString(item)) {
       String name = _Utils.asString(item);
-      // TODO(sra): Compile this out for minified code.
-      if ('dynamic' == name) {
-        return _Universe._lookupDynamicRti(universe);
-      }
       return _Universe._lookupInterfaceRti(
           universe, name, _Universe.sharedEmptyArray(universe));
     } else if (_Utils.isNum(item)) {
@@ -2131,6 +2209,8 @@
   // Subtyping is reflexive.
   if (_Utils.isIdentical(s, t)) return true;
 
+  // Erased types are treated like `dynamic` and handled by the top type case.
+
   if (isTopType(t)) return true;
 
   if (isJsInteropType(s)) return true;
@@ -2406,8 +2486,13 @@
         _FunctionParameters._getOptionalNamed(tParameters));
 
 bool isTopType(Rti t) =>
-    isDynamicType(t) || isVoidType(t) || isObjectType(t) || isJsInteropType(t);
+    isErasedType(t) ||
+    isDynamicType(t) ||
+    isVoidType(t) ||
+    isObjectType(t) ||
+    isJsInteropType(t);
 
+bool isErasedType(Rti t) => Rti._getKind(t) == Rti.kindErased;
 bool isDynamicType(Rti t) => Rti._getKind(t) == Rti.kindDynamic;
 bool isVoidType(Rti t) => Rti._getKind(t) == Rti.kindVoid;
 bool isJsInteropType(Rti t) => Rti._getKind(t) == Rti.kindAny;
@@ -2458,6 +2543,19 @@
 
   static bool isIdentical(s, t) => JS('bool', '# === #', s, t);
 
+  static JSArray objectKeys(Object o) =>
+      JS('returns:JSArray;new:true;', 'Object.keys(#)', o);
+
+  static void objectAssign(Object o, Object other) {
+    // TODO(fishythefish): Use `Object.assign()` when IE11 is deprecated.
+    var keys = objectKeys(other);
+    int length = arrayLength(keys);
+    for (int i = 0; i < length; i++) {
+      String key = asString(arrayAt(keys, i));
+      JS('', '#[#] = #[#]', o, key, other, key);
+    }
+  }
+
   static bool isArray(Object o) => JS('bool', 'Array.isArray(#)', o);
 
   static int arrayLength(Object array) => JS('int', '#.length', array);
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index 389c6db..4628ac9 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -267,6 +267,9 @@
   /// 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,
 
@@ -453,5 +456,6 @@
 class RtiUniverseFieldNames {
   static String evalCache = 'eC';
   static String typeRules = 'tR';
+  static String erasedTypes = 'eT';
   static String sharedEmptyArray = 'sEA';
 }
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
index cab107f..5320597 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
@@ -20,6 +20,8 @@
   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;
@@ -172,6 +174,7 @@
 
     test("separator", separator, separatorString);
     test("toType", toType, toTypeString);
+    test("pushErased", pushErased, pushErasedString);
     test("pushDynamic", pushDynamic, pushDynamicString);
     test("pushVoid", pushVoid, pushVoidString);
     test("wrapStar", wrapStar, wrapStarString);
diff --git a/sdk_nnbd/lib/_internal/vm/bin/builtin.dart b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart
index 69ebae3..84a91cb 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/builtin.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/builtin.dart
@@ -47,7 +47,6 @@
 // Requests made to the service isolate over the load port.
 
 // Extra requests. Keep these in sync between loader.dart and builtin.dart.
-const _Dart_kInitLoader = 4; // Initialize the loader.
 const _Dart_kResourceLoad = 5; // Resource class support.
 const _Dart_kGetPackageRootUri = 6; // Uri of the packages/ directory.
 const _Dart_kGetPackageConfigUri = 7; // Uri of the .packages file.
diff --git a/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart
index 03ebb71..fa5e9ab 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/file_patch.dart
@@ -219,7 +219,9 @@
         bool getIsDir(event) {
           if (Platform.isWindows) {
             // Windows does not get 'isDir' as part of the event.
-            return FileSystemEntity.isDirectorySync(getPath(event));
+            // Links should also be skipped.
+            return FileSystemEntity.isDirectorySync(getPath(event)) &&
+                !FileSystemEntity.isLinkSync(getPath(event));
           }
           return (event[0] & FileSystemEvent._isDir) != 0;
         }
diff --git a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
index f4136a0..750aca8 100644
--- a/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/bin/socket_patch.dart
@@ -1508,7 +1508,7 @@
 @patch
 class ServerSocket {
   @patch
-  static Future<ServerSocket> bind(address, int port,
+  static Future<ServerSocket> _bind(address, int port,
       {int backlog: 0, bool v6Only: false, bool shared: false}) {
     return _ServerSocket.bind(address, port, backlog, v6Only, shared);
   }
diff --git a/sdk_nnbd/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
index dc2be0d..a8bfc23 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
@@ -8,6 +8,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 DynamicLibrary _open(String name) native "Ffi_dl_open";
 DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
diff --git a/sdk_nnbd/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/ffi_native_type_patch.dart
index 6824c19..f2972c8 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/ffi_native_type_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_native_type_patch.dart
@@ -8,6 +8,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 // NativeType is not private, because it is used in type arguments.
 // NativeType is abstract because it not used with const constructors in
diff --git a/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
index 55ba588..3cbdafc 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/ffi_patch.dart
@@ -8,6 +8,7 @@
 // the patches are applied.
 import "dart:_internal" show patch;
 import 'dart:typed_data';
+import 'dart:isolate';
 
 const Map<Type, int> _knownSizes = {
   Int8: 1,
@@ -444,3 +445,8 @@
   @patch
   T operator [](int index) => _loadStruct(this, index);
 }
+
+extension NativePort on SendPort {
+  @patch
+  int get nativePort native "SendPortImpl_get_id";
+}
diff --git a/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart
index 1aad490..63a8fbd 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/stopwatch_patch.dart
@@ -11,11 +11,7 @@
   static const _maxInt = 0x7FFFFFFFFFFFFFFF;
 
   @patch
-  static void _initTicker() {
-    if (_frequency == null) {
-      _frequency = _computeFrequency();
-    }
-  }
+  static int _initTicker() => _computeFrequency();
 
   // Returns the current clock tick.
   @patch
diff --git a/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
index 8443c16..0e00cbb 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/typed_data_patch.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.5
-
 /// Note: the VM concatenates all patch files into a single patch file. This
 /// file is the first patch in "dart:typed_data" which contains all the imports
 /// used by patches of that library. We plan to change this when we have a
@@ -142,9 +140,10 @@
     return -1;
   }
 
-  int lastIndexWhere(bool test(int element), [int start]) {
-    if (start == null || start >= this.length) start = this.length - 1;
-    for (int i = start; i >= 0; i--) {
+  int lastIndexWhere(bool test(int element), [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (test(this[i])) return i;
     }
     return -1;
@@ -166,7 +165,7 @@
     return false;
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= new Random();
     var i = this.length;
     while (i > 1) {
@@ -194,9 +193,9 @@
 
   Map<int, int> asMap() => new ListMapView<int>(this);
 
-  Iterable<int> getRange(int start, [int end]) {
-    RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<int>(this, start, end);
+  Iterable<int> getRange(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    return new SubListIterable<int>(this, start, endIndex);
   }
 
   Iterator<int> get iterator => new _TypedListIterator<int>(this);
@@ -316,7 +315,7 @@
     throw new UnsupportedError("Cannot insert into a fixed-length list");
   }
 
-  void sort([int compare(int a, int b)]) {
+  void sort([int compare(int a, int b)?]) {
     Sort.sort(this, compare ?? Comparable.compare);
   }
 
@@ -332,13 +331,10 @@
     return -1;
   }
 
-  int lastIndexOf(int element, [int start = null]) {
-    if (start == null || start >= this.length) {
-      start = this.length - 1;
-    } else if (start < 0) {
-      return -1;
-    }
-    for (int i = start; i >= 0; i--) {
+  int lastIndexOf(int element, [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
@@ -381,7 +377,8 @@
     setRange(index, end, iterable);
   }
 
-  void fillRange(int start, int end, [int fillValue]) {
+  void fillRange(int start, int end, [int? fillValue]) {
+    if (fillValue == null) throw ArgumentError.notNull("fillValue");
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -458,9 +455,9 @@
     Lists.copy(otherList, otherStart, this, start, count);
   }
 
-  SpawnedType sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, this.length);
-    var length = end - start;
+  SpawnedType sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    var length = endIndex - start;
     SpawnedType result = _createList(length);
     result.setRange(0, length, this, start);
     return result;
@@ -496,9 +493,10 @@
     return -1;
   }
 
-  int lastIndexWhere(bool test(double element), [int start]) {
-    if (start == null || start >= this.length) start = this.length - 1;
-    for (int i = start; i >= 0; i--) {
+  int lastIndexWhere(bool test(double element), [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (test(this[i])) return i;
     }
     return -1;
@@ -520,7 +518,7 @@
     return false;
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= new Random();
     var i = this.length;
     while (i > 1) {
@@ -549,9 +547,9 @@
 
   Map<int, double> asMap() => new ListMapView<double>(this);
 
-  Iterable<double> getRange(int start, [int end]) {
-    RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<double>(this, start, end);
+  Iterable<double> getRange(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    return new SubListIterable<double>(this, start, endIndex);
   }
 
   Iterator<double> get iterator => new _TypedListIterator<double>(this);
@@ -672,7 +670,7 @@
     throw new UnsupportedError("Cannot insert into a fixed-length list");
   }
 
-  void sort([int compare(double a, double b)]) {
+  void sort([int compare(double a, double b)?]) {
     Sort.sort(this, compare ?? Comparable.compare);
   }
 
@@ -688,13 +686,10 @@
     return -1;
   }
 
-  int lastIndexOf(double element, [int start = null]) {
-    if (start == null || start >= this.length) {
-      start = this.length - 1;
-    } else if (start < 0) {
-      return -1;
-    }
-    for (int i = start; i >= 0; i--) {
+  int lastIndexOf(double element, [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
@@ -737,7 +732,9 @@
     setRange(index, end, iterable);
   }
 
-  void fillRange(int start, int end, [double fillValue]) {
+  void fillRange(int start, int end, [double? fillValue]) {
+    // TODO(eernst): Could use zero as default and not throw; issue .
+    if (fillValue == null) throw ArgumentError.notNull("fillValue");
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -815,9 +812,9 @@
     Lists.copy(otherList, otherStart, this, start, count);
   }
 
-  SpawnedType sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, this.length);
-    var length = end - start;
+  SpawnedType sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    var length = endIndex - start;
     SpawnedType result = _createList(length);
     result.setRange(0, length, this, start);
     return result;
@@ -855,9 +852,10 @@
     return -1;
   }
 
-  int lastIndexWhere(bool test(Float32x4 element), [int start]) {
-    if (start == null || start >= this.length) start = this.length - 1;
-    for (int i = start; i >= 0; i--) {
+  int lastIndexWhere(bool test(Float32x4 element), [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (test(this[i])) return i;
     }
     return -1;
@@ -879,7 +877,7 @@
     return false;
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= new Random();
     var i = this.length;
     while (i > 1) {
@@ -975,9 +973,9 @@
 
   Map<int, Float32x4> asMap() => new ListMapView<Float32x4>(this);
 
-  Iterable<Float32x4> getRange(int start, [int end]) {
-    RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<Float32x4>(this, start, end);
+  Iterable<Float32x4> getRange(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    return new SubListIterable<Float32x4>(this, start, endIndex);
   }
 
   Iterator<Float32x4> get iterator => new _TypedListIterator<Float32x4>(this);
@@ -1098,7 +1096,7 @@
     throw new UnsupportedError("Cannot insert into a fixed-length list");
   }
 
-  void sort([int compare(Float32x4 a, Float32x4 b)]) {
+  void sort([int compare(Float32x4 a, Float32x4 b)?]) {
     if (compare == null) {
       throw "SIMD don't have default compare.";
     }
@@ -1117,13 +1115,10 @@
     return -1;
   }
 
-  int lastIndexOf(Float32x4 element, [int start = null]) {
-    if (start == null || start >= this.length) {
-      start = this.length - 1;
-    } else if (start < 0) {
-      return -1;
-    }
-    for (int i = start; i >= 0; i--) {
+  int lastIndexOf(Float32x4 element, [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
@@ -1161,9 +1156,9 @@
     throw IterableElementError.tooMany();
   }
 
-  Float32x4List sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, this.length);
-    var length = end - start;
+  Float32x4List sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    var length = endIndex - start;
     Float32x4List result = _createList(length);
     result.setRange(0, length, this, start);
     return result;
@@ -1174,7 +1169,8 @@
     setRange(index, end, iterable);
   }
 
-  void fillRange(int start, int end, [Float32x4 fillValue]) {
+  void fillRange(int start, int end, [Float32x4? fillValue]) {
+    if (fillValue == null) throw ArgumentError.notNull("fillValue");
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1213,9 +1209,10 @@
     return -1;
   }
 
-  int lastIndexWhere(bool test(Int32x4 element), [int start]) {
-    if (start == null || start >= this.length) start = this.length - 1;
-    for (int i = start; i >= 0; i--) {
+  int lastIndexWhere(bool test(Int32x4 element), [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (test(this[i])) return i;
     }
     return -1;
@@ -1237,7 +1234,7 @@
     return false;
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= new Random();
     var i = this.length;
     while (i > 1) {
@@ -1332,9 +1329,9 @@
 
   Map<int, Int32x4> asMap() => new ListMapView<Int32x4>(this);
 
-  Iterable<Int32x4> getRange(int start, [int end]) {
-    RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<Int32x4>(this, start, end);
+  Iterable<Int32x4> getRange(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    return new SubListIterable<Int32x4>(this, start, endIndex);
   }
 
   Iterator<Int32x4> get iterator => new _TypedListIterator<Int32x4>(this);
@@ -1455,7 +1452,7 @@
     throw new UnsupportedError("Cannot insert into a fixed-length list");
   }
 
-  void sort([int compare(Int32x4 a, Int32x4 b)]) {
+  void sort([int compare(Int32x4 a, Int32x4 b)?]) {
     if (compare == null) {
       throw "SIMD don't have default compare.";
     }
@@ -1474,13 +1471,10 @@
     return -1;
   }
 
-  int lastIndexOf(Int32x4 element, [int start = null]) {
-    if (start == null || start >= this.length) {
-      start = this.length - 1;
-    } else if (start < 0) {
-      return -1;
-    }
-    for (int i = start; i >= 0; i--) {
+  int lastIndexOf(Int32x4 element, [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
@@ -1518,9 +1512,9 @@
     throw IterableElementError.tooMany();
   }
 
-  Int32x4List sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, this.length);
-    var length = end - start;
+  Int32x4List sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    var length = endIndex - start;
     Int32x4List result = _createList(length);
     result.setRange(0, length, this, start);
     return result;
@@ -1531,7 +1525,8 @@
     setRange(index, end, iterable);
   }
 
-  void fillRange(int start, int end, [Int32x4 fillValue]) {
+  void fillRange(int start, int end, [Int32x4? fillValue]) {
+    if (fillValue == null) throw ArgumentError.notNull("fillValue");
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1570,9 +1565,10 @@
     return -1;
   }
 
-  int lastIndexWhere(bool test(Float64x2 element), [int start]) {
-    if (start == null || start >= this.length) start = this.length - 1;
-    for (int i = start; i >= 0; i--) {
+  int lastIndexWhere(bool test(Float64x2 element), [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (test(this[i])) return i;
     }
     return -1;
@@ -1594,7 +1590,7 @@
     return false;
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= new Random();
     var i = this.length;
     while (i > 1) {
@@ -1690,9 +1686,9 @@
 
   Map<int, Float64x2> asMap() => new ListMapView<Float64x2>(this);
 
-  Iterable<Float64x2> getRange(int start, [int end]) {
-    RangeError.checkValidRange(start, end, this.length);
-    return new SubListIterable<Float64x2>(this, start, end);
+  Iterable<Float64x2> getRange(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    return new SubListIterable<Float64x2>(this, start, endIndex);
   }
 
   Iterator<Float64x2> get iterator => new _TypedListIterator<Float64x2>(this);
@@ -1813,7 +1809,7 @@
     throw new UnsupportedError("Cannot insert into a fixed-length list");
   }
 
-  void sort([int compare(Float64x2 a, Float64x2 b)]) {
+  void sort([int compare(Float64x2 a, Float64x2 b)?]) {
     if (compare == null) {
       throw "SIMD don't have default compare.";
     }
@@ -1832,13 +1828,10 @@
     return -1;
   }
 
-  int lastIndexOf(Float64x2 element, [int start = null]) {
-    if (start == null || start >= this.length) {
-      start = this.length - 1;
-    } else if (start < 0) {
-      return -1;
-    }
-    for (int i = start; i >= 0; i--) {
+  int lastIndexOf(Float64x2 element, [int? start]) {
+    int startIndex =
+        (start == null || start >= this.length) ? this.length - 1 : start;
+    for (int i = startIndex; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
@@ -1876,9 +1869,9 @@
     throw IterableElementError.tooMany();
   }
 
-  Float64x2List sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, this.length);
-    var length = end - start;
+  Float64x2List sublist(int start, [int? end]) {
+    int endIndex = RangeError.checkValidRange(start, end, this.length);
+    var length = endIndex - start;
     Float64x2List result = _createList(length);
     result.setRange(0, length, this, start);
     return result;
@@ -1889,7 +1882,8 @@
     setRange(index, end, iterable);
   }
 
-  void fillRange(int start, int end, [Float64x2 fillValue]) {
+  void fillRange(int start, int end, [Float64x2? fillValue]) {
+    if (fillValue == null) throw ArgumentError.notNull("fillValue");
     RangeError.checkValidRange(start, end, this.length);
     for (var i = start; i < end; ++i) {
       this[i] = fillValue;
@@ -1912,20 +1906,20 @@
   bool operator ==(Object other) =>
       (other is _ByteBuffer) && identical(_data, other._data);
 
-  ByteData asByteData([int offsetInBytes = 0, int length]) {
+  ByteData asByteData([int offsetInBytes = 0, int? length]) {
     length ??= this.lengthInBytes - offsetInBytes;
     _rangeCheck(this._data.lengthInBytes, offsetInBytes, length);
     return new _ByteDataView._(this._data, offsetInBytes, length);
   }
 
-  Int8List asInt8List([int offsetInBytes = 0, int length]) {
+  Int8List asInt8List([int offsetInBytes = 0, int? length]) {
     length ??= (this.lengthInBytes - offsetInBytes) ~/ Int8List.bytesPerElement;
     _rangeCheck(
         this.lengthInBytes, offsetInBytes, length * Int8List.bytesPerElement);
     return new _Int8ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Uint8List asUint8List([int offsetInBytes = 0, int length]) {
+  Uint8List asUint8List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint8List.bytesPerElement;
     _rangeCheck(
@@ -1933,7 +1927,7 @@
     return new _Uint8ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
+  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]) {
     length ??= (this.lengthInBytes - offsetInBytes) ~/
         Uint8ClampedList.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
@@ -1941,7 +1935,7 @@
     return new _Uint8ClampedArrayView._(this._data, offsetInBytes, length);
   }
 
-  Int16List asInt16List([int offsetInBytes = 0, int length]) {
+  Int16List asInt16List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int16List.bytesPerElement;
     _rangeCheck(
@@ -1950,7 +1944,7 @@
     return new _Int16ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Uint16List asUint16List([int offsetInBytes = 0, int length]) {
+  Uint16List asUint16List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint16List.bytesPerElement;
     _rangeCheck(
@@ -1959,7 +1953,7 @@
     return new _Uint16ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Int32List asInt32List([int offsetInBytes = 0, int length]) {
+  Int32List asInt32List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int32List.bytesPerElement;
     _rangeCheck(
@@ -1968,7 +1962,7 @@
     return new _Int32ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Uint32List asUint32List([int offsetInBytes = 0, int length]) {
+  Uint32List asUint32List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint32List.bytesPerElement;
     _rangeCheck(
@@ -1977,7 +1971,7 @@
     return new _Uint32ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Int64List asInt64List([int offsetInBytes = 0, int length]) {
+  Int64List asInt64List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int64List.bytesPerElement;
     _rangeCheck(
@@ -1986,7 +1980,7 @@
     return new _Int64ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Uint64List asUint64List([int offsetInBytes = 0, int length]) {
+  Uint64List asUint64List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Uint64List.bytesPerElement;
     _rangeCheck(
@@ -1995,7 +1989,7 @@
     return new _Uint64ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Float32List asFloat32List([int offsetInBytes = 0, int length]) {
+  Float32List asFloat32List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float32List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
@@ -2004,7 +1998,7 @@
     return new _Float32ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Float64List asFloat64List([int offsetInBytes = 0, int length]) {
+  Float64List asFloat64List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float64List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
@@ -2013,7 +2007,7 @@
     return new _Float64ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
+  Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float32x4List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
@@ -2022,7 +2016,7 @@
     return new _Float32x4ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
+  Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Int32x4List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
@@ -2031,7 +2025,7 @@
     return new _Int32x4ArrayView._(this._data, offsetInBytes, length);
   }
 
-  Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
+  Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]) {
     length ??=
         (this.lengthInBytes - offsetInBytes) ~/ Float64x2List.bytesPerElement;
     _rangeCheck(this.lengthInBytes, offsetInBytes,
diff --git a/sdk_nnbd/lib/async/future.dart b/sdk_nnbd/lib/async/future.dart
index 2f9c24d..6e5a777 100644
--- a/sdk_nnbd/lib/async/future.dart
+++ b/sdk_nnbd/lib/async/future.dart
@@ -15,8 +15,6 @@
 /// It is a compile-time error for any class to extend, mix in or implement
 /// `FutureOr`.
 ///
-/// Note: the `FutureOr<T>` type is interpreted as `dynamic` in non strong-mode.
-///
 /// # Examples
 /// ``` dart
 /// // The `Future<T>.then` function takes a callback [f] that returns either
@@ -639,8 +637,6 @@
   // - (dynamic, StackTrace) -> FutureOr<T>
   // Given that there is a `test` function that is usually used to do an
   // `isCheck` we should also expect functions that take a specific argument.
-  // Note: making `catchError` return a `Future<T>` in non-strong mode could be
-  // a breaking change.
   Future<T> catchError(Function onError, {bool test(Object error)});
 
   /**
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index ba3dad6..26d4342 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -252,6 +252,8 @@
    * every event.
    *
    * If [computation] is omitted the event values will all be `null`.
+   *
+   * [period] must a non-negative [Duration].
    */
   factory Stream.periodic(Duration period,
       [T computation(int computationCount)]) {
diff --git a/sdk_nnbd/lib/async/timer.dart b/sdk_nnbd/lib/async/timer.dart
index e3f7edb..c1089bc 100644
--- a/sdk_nnbd/lib/async/timer.dart
+++ b/sdk_nnbd/lib/async/timer.dart
@@ -69,6 +69,8 @@
    * 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) {
diff --git a/sdk_nnbd/lib/collection/collection.dart b/sdk_nnbd/lib/collection/collection.dart
index 644bcff..b050a48 100644
--- a/sdk_nnbd/lib/collection/collection.dart
+++ b/sdk_nnbd/lib/collection/collection.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.5
-
 /// Classes and utilities that supplement the collection support in dart:core.
 ///
 /// To use this library in your code:
diff --git a/sdk_nnbd/lib/collection/collections.dart b/sdk_nnbd/lib/collection/collections.dart
index f836d8e..9b43996 100644
--- a/sdk_nnbd/lib/collection/collections.dart
+++ b/sdk_nnbd/lib/collection/collections.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.5
-
 part of dart.collection;
 
 /// An unmodifiable [List] view of another List.
diff --git a/sdk_nnbd/lib/collection/hash_map.dart b/sdk_nnbd/lib/collection/hash_map.dart
index 18ea1b6..7339deb 100644
--- a/sdk_nnbd/lib/collection/hash_map.dart
+++ b/sdk_nnbd/lib/collection/hash_map.dart
@@ -2,17 +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.
 
-// @dart = 2.5
-
 part of dart.collection;
 
-/// Default function for equality comparison in customized HashMaps
-bool _defaultEquals(a, b) => a == b;
+/// Default function for equality comparison in customized HashMaps.
+bool _defaultEquals(Object? a, Object? b) => a == b;
 
-/// Default function for hash-code computation in customized HashMaps
-int _defaultHashCode(a) => a.hashCode;
+/// Default function for hash-code computation in customized HashMaps.
+int _defaultHashCode(Object? a) => a.hashCode;
 
-/// Type of custom equality function
+/// Type of custom equality function.
 typedef _Equality<K> = bool Function(K a, K b);
 
 /// Type of custom hash code function.
@@ -85,9 +83,9 @@
   /// If you supply one of [equals] and [hashCode],
   /// you should generally also to supply the other.
   external factory HashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(potentialKey)});
+      {bool Function(K key1, K key2)? equals,
+      int Function(K key)? hashCode,
+      bool Function(dynamic potentialKey)? isValidKey});
 
   /// Creates an unordered identity-based map.
   ///
@@ -101,10 +99,10 @@
   ///
   /// The keys must all be instances of [K] and the values of [V].
   /// The [other] map itself can have any type.
-  factory HashMap.from(Map other) {
-    Map<K, V> result = HashMap<K, V>();
-    other.forEach((k, v) {
-      result[k] = v;
+  factory HashMap.from(Map<dynamic, dynamic> other) {
+    HashMap<K, V> result = HashMap<K, V>();
+    other.forEach((dynamic k, dynamic v) {
+      result[k as K] = v as V;
     });
     return result;
   }
@@ -124,8 +122,8 @@
   /// If no values are specified for [key] and [value] the default is the
   /// identity function.
   factory HashMap.fromIterable(Iterable iterable,
-      {K key(element), V value(element)}) {
-    Map<K, V> map = HashMap<K, V>();
+      {K Function(dynamic element)? key, V Function(dynamic element)? value}) {
+    HashMap<K, V> map = HashMap<K, V>();
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
   }
@@ -140,7 +138,7 @@
   ///
   /// It is an error if the two [Iterable]s don't have the same length.
   factory HashMap.fromIterables(Iterable<K> keys, Iterable<V> values) {
-    Map<K, V> map = HashMap<K, V>();
+    HashMap<K, V> map = HashMap<K, V>();
     MapBase._fillMapWithIterables(map, keys, values);
     return map;
   }
diff --git a/sdk_nnbd/lib/collection/hash_set.dart b/sdk_nnbd/lib/collection/hash_set.dart
index 61f1f6c..6007fa8 100644
--- a/sdk_nnbd/lib/collection/hash_set.dart
+++ b/sdk_nnbd/lib/collection/hash_set.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.5
-
 part of dart.collection;
 
 /// An unordered hash-table based [Set] implementation.
@@ -66,9 +64,9 @@
   /// and the `isValidKey` defaults to accepting all keys.
   /// Such a map can be created directly using [HashSet.identity].
   external factory HashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(potentialKey)});
+      {bool Function(E e1, E e2)? equals,
+      int Function(E e)? hashCode,
+      bool Function(dynamic potentialKey)? isValidKey});
 
   /// Creates an unordered identity-based set.
   ///
@@ -80,7 +78,7 @@
 
   /// Create a hash set containing all [elements].
   ///
-  /// Creates a hash set as by `new HashSet<E>()` and adds all given [elements]
+  /// Creates a hash set as by `HashSet<E>()` and adds all given [elements]
   /// to the set. The elements are added in order. If [elements] contains
   /// two entries that are equal, but not identical, then the first one is
   /// the one in the resulting set.
@@ -91,12 +89,12 @@
   /// ```dart
   /// Set<SuperType> superSet = ...;
   /// Set<SubType> subSet =
-  ///     new HashSet<SubType>.from(superSet.whereType<SubType>());
+  ///     HashSet<SubType>.from(superSet.whereType<SubType>());
   /// ```
-  factory HashSet.from(Iterable elements) {
+  factory HashSet.from(Iterable<dynamic> elements) {
     HashSet<E> result = HashSet<E>();
     for (final e in elements) {
-      result.add(e);
+      result.add(e as E);
     }
     return result;
   }
diff --git a/sdk_nnbd/lib/collection/iterable.dart b/sdk_nnbd/lib/collection/iterable.dart
index 8ac38b2..9a03fac 100644
--- a/sdk_nnbd/lib/collection/iterable.dart
+++ b/sdk_nnbd/lib/collection/iterable.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.5
-
 part of dart.collection;
 
 /// This [Iterable] mixin implements all [Iterable] members except `iterator`.
@@ -159,7 +157,7 @@
     return result;
   }
 
-  E firstWhere(bool test(E value), {E orElse()}) {
+  E firstWhere(bool test(E value), {E Function()? orElse}) {
     for (E element in this) {
       if (test(element)) return element;
     }
@@ -167,8 +165,8 @@
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E value), {E orElse()}) {
-    E result;
+  E lastWhere(bool test(E value), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -181,8 +179,8 @@
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E element), {E orElse()}) {
-    E result;
+  E singleWhere(bool test(E element), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -277,7 +275,7 @@
 }
 
 /// A collection used to identify cyclic lists during toString() calls.
-final List _toStringVisiting = [];
+final List<Object> _toStringVisiting = [];
 
 /// Check if we are currently visiting `o` in a toString call.
 bool _isToStringVisiting(Object o) {
@@ -288,7 +286,7 @@
 }
 
 /// Convert elements of [iterable] to strings and store them in [parts].
-void _iterablePartsToStrings(Iterable iterable, List<String> parts) {
+void _iterablePartsToStrings(Iterable<Object?> iterable, List<String> parts) {
   /*
    * This is the complicated part of [iterableToShortString].
    * It is extracted as a separate function to avoid having too much code
@@ -313,7 +311,7 @@
 
   int length = 0;
   int count = 0;
-  Iterator it = iterable.iterator;
+  Iterator<Object?> it = iterable.iterator;
   // Initial run of elements, at least headCount, and then continue until
   // passing at most lengthLimit characters.
   while (length < lengthLimit || count < headCount) {
@@ -329,14 +327,12 @@
 
   // Find last two elements. One or more of them may already be in the
   // parts array. Include their length in `length`.
-  Object penultimate;
-  Object ultimate;
   if (!it.moveNext()) {
     if (count <= headCount + tailCount) return;
     ultimateString = parts.removeLast();
     penultimateString = parts.removeLast();
   } else {
-    penultimate = it.current;
+    Object? penultimate = it.current;
     count++;
     if (!it.moveNext()) {
       if (count <= headCount + 1) {
@@ -347,7 +343,7 @@
       penultimateString = parts.removeLast();
       length += ultimateString.length + overhead;
     } else {
-      ultimate = it.current;
+      Object? ultimate = it.current;
       count++;
       // Then keep looping, keeping the last two elements in variables.
       assert(count < maxCount);
@@ -380,7 +376,7 @@
 
   // If there is a gap between the initial run and the last two,
   // prepare to add an ellipsis.
-  String elision;
+  String? elision;
   if (count > parts.length + tailCount) {
     elision = "...";
     length += ellipsisSize + overhead;
diff --git a/sdk_nnbd/lib/collection/iterator.dart b/sdk_nnbd/lib/collection/iterator.dart
index e7e0c3b..671f0ee 100644
--- a/sdk_nnbd/lib/collection/iterator.dart
+++ b/sdk_nnbd/lib/collection/iterator.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.5
-
 part of dart.collection;
 
 /// The [HasNextIterator] class wraps an [Iterator] and provides methods to
diff --git a/sdk_nnbd/lib/collection/linked_hash_map.dart b/sdk_nnbd/lib/collection/linked_hash_map.dart
index de94009..195480e 100644
--- a/sdk_nnbd/lib/collection/linked_hash_map.dart
+++ b/sdk_nnbd/lib/collection/linked_hash_map.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.5
-
 part of dart.collection;
 
 /// A hash-table based implementation of [Map].
@@ -69,9 +67,9 @@
   /// If you supply one of [equals] and [hashCode],
   /// you should generally also to supply the other.
   external factory LinkedHashMap(
-      {bool equals(K key1, K key2),
-      int hashCode(K key),
-      bool isValidKey(potentialKey)});
+      {bool Function(K key1, K key2)? equals,
+      int Function(K key)? hashCode,
+      bool Function(dynamic potentialKey)? isValidKey});
 
   /// Creates an insertion-ordered identity-based map.
   ///
@@ -85,10 +83,10 @@
   ///
   /// The keys must all be instances of [K] and the values to [V].
   /// The [other] map itself can have any type.
-  factory LinkedHashMap.from(Map other) {
+  factory LinkedHashMap.from(Map<dynamic, dynamic> other) {
     LinkedHashMap<K, V> result = LinkedHashMap<K, V>();
-    other.forEach((k, v) {
-      result[k] = v;
+    other.forEach((dynamic k, dynamic v) {
+      result[k as K] = v as V;
     });
     return result;
   }
@@ -109,7 +107,7 @@
   /// If no values are specified for [key] and [value] the default is the
   /// identity function.
   factory LinkedHashMap.fromIterable(Iterable iterable,
-      {K key(element), V value(element)}) {
+      {K Function(dynamic element)? key, V Function(dynamic element)? value}) {
     LinkedHashMap<K, V> map = LinkedHashMap<K, V>();
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
@@ -139,5 +137,5 @@
   /// later occurrences overwrite the earlier ones.
   @Since("2.1")
   factory LinkedHashMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
-      <K, V>{}..addEntries(entries);
+      LinkedHashMap<K, V>()..addEntries(entries);
 }
diff --git a/sdk_nnbd/lib/collection/linked_hash_set.dart b/sdk_nnbd/lib/collection/linked_hash_set.dart
index 195b5fb..19e374f 100644
--- a/sdk_nnbd/lib/collection/linked_hash_set.dart
+++ b/sdk_nnbd/lib/collection/linked_hash_set.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.5
-
 part of dart.collection;
 
 /// A [LinkedHashSet] is a hash-table based [Set] implementation.
@@ -73,9 +71,9 @@
   /// and the `isValidKey` defaults to accepting all keys.
   /// Such a map can be created directly using [LinkedHashSet.identity].
   external factory LinkedHashSet(
-      {bool equals(E e1, E e2),
-      int hashCode(E e),
-      bool isValidKey(potentialKey)});
+      {bool Function(E e1, E e2)? equals,
+      int Function(E e)? hashCode,
+      bool Function(dynamic potentialKey)? isValidKey});
 
   /// Creates an insertion-ordered identity-based set.
   ///
@@ -97,10 +95,10 @@
   ///     Set<SuperType> superSet = ...;
   ///     Iterable<SuperType> tmp = superSet.where((e) => e is SubType);
   ///     Set<SubType> subSet = new LinkedHashSet<SubType>.from(tmp);
-  factory LinkedHashSet.from(Iterable elements) {
+  factory LinkedHashSet.from(Iterable<dynamic> elements) {
     LinkedHashSet<E> result = LinkedHashSet<E>();
     for (final element in elements) {
-      result.add(element);
+      result.add(element as E);
     }
     return result;
   }
diff --git a/sdk_nnbd/lib/collection/linked_list.dart b/sdk_nnbd/lib/collection/linked_list.dart
index 9ef7a56..a273edb 100644
--- a/sdk_nnbd/lib/collection/linked_list.dart
+++ b/sdk_nnbd/lib/collection/linked_list.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.5
-
 part of dart.collection;
 
 /// A specialized double-linked list of elements that extends [LinkedListEntry].
@@ -30,7 +28,7 @@
 class LinkedList<E extends LinkedListEntry<E>> extends Iterable<E> {
   int _modificationCount = 0;
   int _length = 0;
-  E _first;
+  E? _first;
 
   /// Construct a new empty linked list.
   LinkedList();
@@ -72,10 +70,10 @@
     _modificationCount++;
     if (isEmpty) return;
 
-    E next = _first;
+    E next = _first!;
     do {
       E entry = next;
-      next = entry._next;
+      next = entry._next!;
       entry._next = entry._previous = entry._list = null;
     } while (!identical(next, _first));
 
@@ -87,14 +85,14 @@
     if (isEmpty) {
       throw StateError('No such element');
     }
-    return _first;
+    return _first!;
   }
 
   E get last {
     if (isEmpty) {
       throw StateError('No such element');
     }
-    return _first._previous;
+    return _first!._previous!;
   }
 
   E get single {
@@ -104,23 +102,23 @@
     if (_length > 1) {
       throw StateError('Too many elements');
     }
-    return _first;
+    return _first!;
   }
 
   /// Call [action] with each entry in this linked list.
   ///
-  /// It's an error if [action] modify the linked list.
+  /// It's an error if [action] modifies the linked list.
   void forEach(void action(E entry)) {
     int modificationCount = _modificationCount;
     if (isEmpty) return;
 
-    E current = _first;
+    E current = _first!;
     do {
       action(current);
       if (modificationCount != _modificationCount) {
         throw ConcurrentModificationError(this);
       }
-      current = current._next;
+      current = current._next!;
     } while (!identical(current, _first));
   }
 
@@ -130,7 +128,7 @@
   ///
   /// If [updateFirst] is true and [entry] is the first entry in the list,
   /// updates the [_first] field to point to the [newEntry] as first entry.
-  void _insertBefore(E entry, E newEntry, {bool updateFirst}) {
+  void _insertBefore(E? entry, E newEntry, {required bool updateFirst}) {
     if (newEntry.list != null) {
       throw StateError('LinkedListEntry is already in a LinkedList');
     }
@@ -144,8 +142,8 @@
       _length++;
       return;
     }
-    E predecessor = entry._previous;
-    E successor = entry;
+    E predecessor = entry!._previous!;
+    E successor = entry!;
     newEntry._previous = predecessor;
     newEntry._next = successor;
     predecessor._next = newEntry;
@@ -158,8 +156,8 @@
 
   void _unlink(E entry) {
     _modificationCount++;
-    entry._next._previous = entry._previous;
-    E next = entry._previous._next = entry._next;
+    entry._next!._previous = entry._previous;
+    E? next = entry._previous!._next = entry._next;
     _length--;
     entry._list = entry._next = entry._previous = null;
     if (isEmpty) {
@@ -173,8 +171,8 @@
 class _LinkedListIterator<E extends LinkedListEntry<E>> implements Iterator<E> {
   final LinkedList<E> _list;
   final int _modificationCount;
-  E _current;
-  LinkedListEntry<E> _next;
+  E? _current;
+  E? _next;
   bool _visitedFirst;
 
   _LinkedListIterator(LinkedList<E> list)
@@ -183,7 +181,7 @@
         _next = list._first,
         _visitedFirst = false;
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
     if (_modificationCount != _list._modificationCount) {
@@ -195,7 +193,7 @@
     }
     _visitedFirst = true;
     _current = _next;
-    _next = _next._next;
+    _next = _next!._next;
     return true;
   }
 }
@@ -213,28 +211,28 @@
 ///
 /// When created, an entry is not in any linked list.
 abstract class LinkedListEntry<E extends LinkedListEntry<E>> {
-  LinkedList<E> _list;
-  E _next;
-  E _previous;
+  LinkedList<E>? _list;
+  E? _next;
+  E? _previous;
 
   /// Get the linked list containing this element.
   ///
   /// Returns `null` if this entry is not currently in any list.
-  LinkedList<E> get list => _list;
+  LinkedList<E>? get list => _list;
 
   /// Unlink the element from its linked list.
   ///
   /// The entry must currently be in a linked list when this method is called.
   void unlink() {
-    _list._unlink(this);
+    _list!._unlink(this as E);
   }
 
   /// Return 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.
-  E get next {
-    if (_list == null || identical(_list.first, _next)) return null;
+  E? get next {
+    if (_list == null || identical(_list!.first, _next)) return null;
     return _next;
   }
 
@@ -242,8 +240,8 @@
   ///
   /// Returns `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;
+  E? get previous {
+    if (_list == null || identical(this, _list!.first)) return null;
     return _previous;
   }
 
@@ -252,7 +250,7 @@
   /// This entry must be in a linked list when this method is called.
   /// The [entry] must not be in a linked list.
   void insertAfter(E entry) {
-    _list._insertBefore(_next, entry, updateFirst: false);
+    _list!._insertBefore(_next, entry, updateFirst: false);
   }
 
   /// Insert an element before this element in this element's linked list.
@@ -260,6 +258,6 @@
   /// This entry must be in a linked list when this method is called.
   /// The [entry] must not be in a linked list.
   void insertBefore(E entry) {
-    _list._insertBefore(this, entry, updateFirst: true);
+    _list!._insertBefore(this as E, entry, updateFirst: true);
   }
 }
diff --git a/sdk_nnbd/lib/collection/list.dart b/sdk_nnbd/lib/collection/list.dart
index 911820b..262490f 100644
--- a/sdk_nnbd/lib/collection/list.dart
+++ b/sdk_nnbd/lib/collection/list.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.5
-
 part of dart.collection;
 
 /// Abstract implementation of a list.
@@ -23,7 +21,11 @@
 /// to the growable list, or, preferably, use `DelegatingList` from
 /// "package:collection/wrappers.dart" instead.
 abstract class ListBase<E> extends Object with ListMixin<E> {
-  /// Convert a `List` to a string as `[each, element, as, string]`.
+  /// Converts a [List] to a [String].
+  ///
+  /// Converts [list] to a string by converting each element to a string (by
+  /// calling [Object.toString]), joining them with ", ", and wrapping the
+  /// result in "[" and "]".
   ///
   /// Handles circular references where converting one of the elements
   /// to a string ends up converting [list] to a string again.
@@ -133,7 +135,7 @@
     return false;
   }
 
-  E firstWhere(bool test(E element), {E orElse()}) {
+  E firstWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
     for (int i = 0; i < length; i++) {
       E element = this[i];
@@ -146,7 +148,7 @@
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E element), {E orElse()}) {
+  E lastWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
     for (int i = length - 1; i >= 0; i--) {
       E element = this[i];
@@ -159,9 +161,9 @@
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E element), {E orElse()}) {
+  E singleWhere(bool test(E element), {E Function()? orElse}) {
     int length = this.length;
-    E match;
+    late E match;
     bool matchFound = false;
     for (int i = 0; i < length; i++) {
       E element = this[i];
@@ -234,13 +236,11 @@
   }
 
   List<E> toList({bool growable = true}) {
-    List<E> result;
-    if (growable) {
-      result = <E>[]..length = length;
-    } else {
-      result = List<E>(length);
-    }
-    for (int i = 0; i < length; i++) {
+    // TODO(rnystrom): Use List.empty() instead once that lands.
+    if (this.isEmpty) return List<E>.of([], growable: growable);
+    var first = this[0];
+    var result = List<E>.filled(this.length, first, growable: growable);
+    for (int i = 1; i < this.length; i++) {
       result[i] = this[i];
     }
     return result;
@@ -333,18 +333,18 @@
     return result;
   }
 
-  void sort([int compare(E a, E b)]) {
+  void sort([int Function(E a, E b)? compare]) {
     Sort.sort(this, compare ?? _compareAny);
   }
 
-  static int _compareAny(a, b) {
-    // In strong mode Comparable.compare requires an implicit cast to ensure
-    // `a` and `b` are Comparable.
-    return Comparable.compare(a, b);
+  static int _compareAny(dynamic a, dynamic b) {
+    return Comparable.compare(a as Comparable, b as Comparable);
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     random ??= Random();
+    if (random == null) throw "!"; // TODO(38493): The `??=` should promote.
+
     int length = this.length;
     while (length > 1) {
       int pos = random.nextInt(length);
@@ -366,9 +366,11 @@
     return result;
   }
 
-  List<E> sublist(int start, [int end]) {
+  List<E> sublist(int start, [int? end]) {
     int listLength = this.length;
     end ??= listLength;
+    if (end == null) throw "!"; // TODO(38493): The `??=` should promote.
+
     RangeError.checkValidRange(start, end, listLength);
     int length = end - start;
     List<E> result = <E>[]..length = length;
@@ -390,10 +392,13 @@
     }
   }
 
-  void fillRange(int start, int end, [E fill]) {
+  void fillRange(int start, int end, [E? fill]) {
+    // Hoist the case to fail eagerly if the user provides an invalid `null`
+    // value (or omits it) when E is a non-nullable type.
+    E value = fill as E;
     RangeError.checkValidRange(start, end, this.length);
     for (int i = start; i < end; i++) {
-      this[i] = fill;
+      this[i] = value;
     }
   }
 
@@ -467,16 +472,24 @@
     return -1;
   }
 
-  int lastIndexOf(Object element, [int start]) {
+  int lastIndexOf(Object element, [int? start]) {
     if (start == null || start >= this.length) start = this.length - 1;
+
+    // TODO(38493): The previous line should promote.
+    if (start == null) throw "!";
+
     for (int i = start; i >= 0; i--) {
       if (this[i] == element) return i;
     }
     return -1;
   }
 
-  int lastIndexWhere(bool test(E element), [int start]) {
+  int lastIndexWhere(bool test(E element), [int? start]) {
     if (start == null || start >= this.length) start = this.length - 1;
+
+    // TODO(38493): The previous line should promote.
+    if (start == null) throw "!";
+
     for (int i = start; i >= 0; i--) {
       if (test(this[i])) return i;
     }
diff --git a/sdk_nnbd/lib/collection/maps.dart b/sdk_nnbd/lib/collection/maps.dart
index 7fb2551..7ca8eeb 100644
--- a/sdk_nnbd/lib/collection/maps.dart
+++ b/sdk_nnbd/lib/collection/maps.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.5
-
 part of dart.collection;
 
 /// Base class for implementing a [Map].
@@ -21,7 +19,7 @@
 /// A more efficient implementation is usually possible by overriding
 /// some of the other members as well.
 abstract class MapBase<K, V> extends MapMixin<K, V> {
-  static String mapToString(Map m) {
+  static String mapToString(Map<Object?, Object?> m) {
     // Reuses the list in IterableBase for detecting toString cycles.
     if (_isToStringVisiting(m)) {
       return '{...}';
@@ -32,7 +30,7 @@
       _toStringVisiting.add(m);
       result.write('{');
       bool first = true;
-      m.forEach((k, v) {
+      m.forEach((Object? k, Object? v) {
         if (!first) {
           result.write(', ');
         }
@@ -50,17 +48,23 @@
     return result.toString();
   }
 
-  static _id(x) => x;
+  static Object? _id(Object? x) => x;
 
   /// Fills a [Map] with key/value pairs computed from [iterable].
   ///
   /// This method is used by [Map] classes in the named constructor
   /// `fromIterable`.
   static void _fillMapWithMappedIterable(
-      Map map, Iterable iterable, key(element), value(element)) {
+      Map<Object?, Object?> map,
+      Iterable<Object?> iterable,
+      Object? Function(Object? element)? key,
+      Object? Function(Object? element)? value) {
     key ??= _id;
     value ??= _id;
 
+    if (key == null) throw "!"; // TODO(38493): The `??=` should promote.
+    if (value == null) throw "!"; // TODO(38493): The `??=` should promote.
+
     for (var element in iterable) {
       map[key(element)] = value(element);
     }
@@ -70,9 +74,10 @@
   ///
   /// This method is used by [Map] classes in the named constructor
   /// `fromIterables`.
-  static void _fillMapWithIterables(Map map, Iterable keys, Iterable values) {
-    Iterator keyIterator = keys.iterator;
-    Iterator valueIterator = values.iterator;
+  static void _fillMapWithIterables(Map<Object?, Object?> map,
+      Iterable<Object?> keys, Iterable<Object?> values) {
+    Iterator<Object?> keyIterator = keys.iterator;
+    Iterator<Object?> valueIterator = values.iterator;
 
     bool hasNextKey = keyIterator.moveNext();
     bool hasNextValue = valueIterator.moveNext();
@@ -105,9 +110,9 @@
 /// some of the other members as well.
 abstract class MapMixin<K, V> implements Map<K, V> {
   Iterable<K> get keys;
-  V operator [](Object key);
+  V? operator [](Object? key);
   operator []=(K key, V value);
-  V remove(Object key);
+  V? remove(Object? key);
   // The `clear` operation should not be based on `remove`.
   // It should clear the map even if some keys are not equal to themselves.
   void clear();
@@ -115,7 +120,7 @@
   Map<RK, RV> cast<RK, RV>() => Map.castFrom<K, V, RK, RV>(this);
   void forEach(void action(K key, V value)) {
     for (K key in keys) {
-      action(key, this[key]);
+      action(key, this[key] as V);
     }
   }
 
@@ -125,7 +130,7 @@
     }
   }
 
-  bool containsValue(Object value) {
+  bool containsValue(Object? value) {
     for (K key in keys) {
       if (this[key] == value) return true;
     }
@@ -134,14 +139,14 @@
 
   V putIfAbsent(K key, V ifAbsent()) {
     if (containsKey(key)) {
-      return this[key];
+      return this[key] as V;
     }
     return this[key] = ifAbsent();
   }
 
-  V update(K key, V update(V value), {V ifAbsent()}) {
+  V update(K key, V update(V value), {V Function()? ifAbsent}) {
     if (this.containsKey(key)) {
-      return this[key] = update(this[key]);
+      return this[key] = update(this[key] as V);
     }
     if (ifAbsent != null) {
       return this[key] = ifAbsent();
@@ -151,18 +156,18 @@
 
   void updateAll(V update(K key, V value)) {
     for (var key in this.keys) {
-      this[key] = update(key, this[key]);
+      this[key] = update(key, this[key] as V);
     }
   }
 
   Iterable<MapEntry<K, V>> get entries {
-    return keys.map((K key) => MapEntry<K, V>(key, this[key]));
+    return keys.map((K key) => MapEntry<K, V>(key, this[key] as V));
   }
 
   Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) {
     var result = <K2, V2>{};
     for (var key in this.keys) {
-      var entry = transform(key, this[key]);
+      var entry = transform(key, this[key] as V);
       result[entry.key] = entry.value;
     }
     return result;
@@ -177,14 +182,14 @@
   void removeWhere(bool test(K key, V value)) {
     var keysToRemove = <K>[];
     for (var key in keys) {
-      if (test(key, this[key])) keysToRemove.add(key);
+      if (test(key, this[key] as V)) keysToRemove.add(key);
     }
     for (var key in keysToRemove) {
       this.remove(key);
     }
   }
 
-  bool containsKey(Object key) => keys.contains(key);
+  bool containsKey(Object? key) => keys.contains(key);
   int get length => keys.length;
   bool get isEmpty => keys.isEmpty;
   bool get isNotEmpty => keys.isNotEmpty;
@@ -238,7 +243,7 @@
 class _MapBaseValueIterator<K, V> implements Iterator<V> {
   final Iterator<K> _keys;
   final Map<K, V> _map;
-  V _current;
+  V? _current;
 
   _MapBaseValueIterator(Map<K, V> map)
       : _map = map,
@@ -253,7 +258,7 @@
     return false;
   }
 
-  V get current => _current;
+  V get current => _current as V;
 }
 
 /// Mixin that overrides mutating map operations with implementations that
@@ -280,7 +285,7 @@
   }
 
   /// This operation is not supported by an unmodifiable map.
-  V remove(Object key) {
+  V remove(Object? key) {
     throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
@@ -295,7 +300,7 @@
   }
 
   /// This operation is not supported by an unmodifiable map.
-  V update(K key, V update(V value), {V ifAbsent()}) {
+  V update(K key, V update(V value), {V Function()? ifAbsent}) {
     throw UnsupportedError("Cannot modify unmodifiable map");
   }
 
@@ -354,7 +359,7 @@
   Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> transform(K key, V value)) =>
       _map.map<K2, V2>(transform);
 
-  V update(K key, V update(V value), {V ifAbsent()}) =>
+  V update(K key, V update(V value), {V Function()? ifAbsent}) =>
       _map.update(key, update, ifAbsent: ifAbsent);
 
   void updateAll(V update(K key, V value)) {
diff --git a/sdk_nnbd/lib/collection/queue.dart b/sdk_nnbd/lib/collection/queue.dart
index 77b27b1..685f5dc 100644
--- a/sdk_nnbd/lib/collection/queue.dart
+++ b/sdk_nnbd/lib/collection/queue.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.5
-
 part of dart.collection;
 
 /// A [Queue] is a collection that can be manipulated at both ends. One
@@ -32,7 +30,7 @@
   /// ```dart
   /// Queue<SuperType> superQueue = ...;
   /// Queue<SubType> subQueue =
-  ///     new Queue<SubType>.from(superSet.whereType<SubType>());
+  ///     new Queue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
   factory Queue.from(Iterable elements) = ListQueue<E>.from;
 
@@ -112,19 +110,19 @@
 }
 
 class _DoubleLink<Link extends _DoubleLink<Link>> {
-  Link _previousLink;
-  Link _nextLink;
+  Link? _previousLink;
+  Link? _nextLink;
 
-  void _link(Link previous, Link next) {
+  void _link(Link? previous, Link? next) {
     _nextLink = next;
     _previousLink = previous;
-    if (previous != null) previous._nextLink = this;
-    if (next != null) next._previousLink = this;
+    if (previous != null) previous!._nextLink = this as Link;
+    if (next != null) next!._previousLink = this as Link;
   }
 
   void _unlink() {
-    if (_previousLink != null) _previousLink._nextLink = _nextLink;
-    if (_nextLink != null) _nextLink._previousLink = _previousLink;
+    if (_previousLink != null) _previousLink!._nextLink = _nextLink as Link;
+    if (_nextLink != null) _nextLink!._previousLink = _previousLink as Link;
     _nextLink = null;
     _previousLink = null;
   }
@@ -133,10 +131,19 @@
 /// An entry in a doubly linked list. It contains a pointer to the next
 /// entry, the previous entry, and the boxed element.
 class DoubleLinkedQueueEntry<E> extends _DoubleLink<DoubleLinkedQueueEntry<E>> {
-  /// The element in the queue.
-  E element;
+  // TODO(rnystrom): This needs to be nullable because the subclass
+  // _DoubleLinkedQueueSentinel does not have an element. A cleaner solution is
+  // probably to refactor the class hierarchy so that _DoubleLinkedQueueSentinel
+  // does not inherit an element field.
+  E? _element;
 
-  DoubleLinkedQueueEntry(this.element);
+  /// The element in the queue.
+  E get element => _element as E;
+  set element(E element) {
+    _element = element;
+  }
+
+  DoubleLinkedQueueEntry(this._element);
 
   /// Appends the given [e] as entry just after this entry.
   void append(E e) {
@@ -154,10 +161,10 @@
   }
 
   /// Returns the previous entry or `null` if there is none.
-  DoubleLinkedQueueEntry<E> previousEntry() => _previousLink;
+  DoubleLinkedQueueEntry<E>? previousEntry() => _previousLink;
 
   /// Returns the next entry or `null` if there is none.
-  DoubleLinkedQueueEntry<E> nextEntry() => _nextLink;
+  DoubleLinkedQueueEntry<E>? nextEntry() => _nextLink;
 }
 
 /// Interface for the link classes used by [DoubleLinkedQueue].
@@ -167,10 +174,10 @@
 /// The entry contains a link back to the queue, so calling `append`
 /// or `prepend` can correctly update the element count.
 abstract class _DoubleLinkedQueueEntry<E> extends DoubleLinkedQueueEntry<E> {
-  DoubleLinkedQueue<E> _queue;
-  _DoubleLinkedQueueEntry(E element, this._queue) : super(element);
+  DoubleLinkedQueue<E>? _queue;
+  _DoubleLinkedQueueEntry(E? element, this._queue) : super(element);
 
-  DoubleLinkedQueueEntry<E> _asNonSentinelEntry();
+  DoubleLinkedQueueEntry<E>? _asNonSentinelEntry();
 
   void _append(E e) {
     _DoubleLinkedQueueElement<E>(e, _queue)._link(this, _nextLink);
@@ -185,13 +192,14 @@
   E get _element => element;
 
   DoubleLinkedQueueEntry<E> nextEntry() {
-    _DoubleLinkedQueueEntry<E> entry = _nextLink;
-    return entry._asNonSentinelEntry();
+    _DoubleLinkedQueueEntry<E> entry = _nextLink as _DoubleLinkedQueueEntry<E>;
+    return entry._asNonSentinelEntry()!;
   }
 
   DoubleLinkedQueueEntry<E> previousEntry() {
-    _DoubleLinkedQueueEntry<E> entry = _previousLink;
-    return entry._asNonSentinelEntry();
+    _DoubleLinkedQueueEntry<E> entry =
+        _previousLink as _DoubleLinkedQueueEntry<E>;
+    return entry._asNonSentinelEntry()!;
   }
 }
 
@@ -200,17 +208,17 @@
 /// The entry contains a reference to the queue, allowing
 /// [append]/[prepend] to update the list length.
 class _DoubleLinkedQueueElement<E> extends _DoubleLinkedQueueEntry<E> {
-  _DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E> queue)
+  _DoubleLinkedQueueElement(E element, DoubleLinkedQueue<E>? queue)
       : super(element, queue);
 
   void append(E e) {
     _append(e);
-    if (_queue != null) _queue._elementCount++;
+    if (_queue != null) _queue!._elementCount++;
   }
 
   void prepend(E e) {
     _prepend(e);
-    if (_queue != null) _queue._elementCount++;
+    if (_queue != null) _queue!._elementCount++;
   }
 
   E _remove() {
@@ -220,11 +228,11 @@
   }
 
   E remove() {
-    if (_queue != null) _queue._elementCount--;
+    if (_queue != null) _queue!._elementCount--;
     return _remove();
   }
 
-  _DoubleLinkedQueueElement<E> _asNonSentinelEntry() {
+  _DoubleLinkedQueueElement<E>? _asNonSentinelEntry() {
     return this;
   }
 }
@@ -241,7 +249,7 @@
     _nextLink = this;
   }
 
-  DoubleLinkedQueueEntry<E> _asNonSentinelEntry() {
+  DoubleLinkedQueueEntry<E>? _asNonSentinelEntry() {
     return null;
   }
 
@@ -260,12 +268,12 @@
 ///
 /// Allows constant time add, remove-at-ends and peek operations.
 class DoubleLinkedQueue<E> extends Iterable<E> implements Queue<E> {
-  _DoubleLinkedQueueSentinel<E> _sentinel;
+  late _DoubleLinkedQueueSentinel<E> _sentinel =
+      _DoubleLinkedQueueSentinel<E>(this);
+
   int _elementCount = 0;
 
-  DoubleLinkedQueue() {
-    _sentinel = _DoubleLinkedQueueSentinel<E>(this);
-  }
+  DoubleLinkedQueue();
 
   /// Creates a double-linked queue containing all [elements].
   ///
@@ -280,10 +288,10 @@
   /// Queue<SubType> subQueue =
   ///     new DoubleLinkedQueue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
-  factory DoubleLinkedQueue.from(Iterable elements) {
-    Queue<E> list = DoubleLinkedQueue<E>();
+  factory DoubleLinkedQueue.from(Iterable<dynamic> elements) {
+    DoubleLinkedQueue<E> list = DoubleLinkedQueue<E>();
     for (final e in elements) {
-      list.addLast(e);
+      list.addLast(e as E);
     }
     return list;
   }
@@ -321,21 +329,24 @@
   }
 
   E removeLast() {
-    _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink;
+    _DoubleLinkedQueueEntry<E> lastEntry =
+        _sentinel._previousLink as _DoubleLinkedQueueEntry<E>;
     E result = lastEntry._remove();
     _elementCount--;
     return result;
   }
 
   E removeFirst() {
-    _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink;
+    _DoubleLinkedQueueEntry<E> firstEntry =
+        _sentinel._nextLink as _DoubleLinkedQueueEntry<E>;
     E result = firstEntry._remove();
     _elementCount--;
     return result;
   }
 
   bool remove(Object o) {
-    _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
+    _DoubleLinkedQueueEntry<E> entry =
+        _sentinel._nextLink as _DoubleLinkedQueueEntry<E>;
     while (!identical(entry, _sentinel)) {
       bool equals = (entry._element == o);
       if (!identical(this, entry._queue)) {
@@ -347,25 +358,26 @@
         _elementCount--;
         return true;
       }
-      entry = entry._nextLink;
+      entry = entry._nextLink as _DoubleLinkedQueueEntry<E>;
     }
     return false;
   }
 
   void _filter(bool test(E element), bool removeMatching) {
-    _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
+    _DoubleLinkedQueueEntry<E> entry =
+        _sentinel._nextLink as _DoubleLinkedQueueEntry<E>;
     while (!identical(entry, _sentinel)) {
       bool matches = test(entry._element);
       if (!identical(this, entry._queue)) {
         // Entry must still be in the queue.
         throw ConcurrentModificationError(this);
       }
-      _DoubleLinkedQueueEntry<E> next = entry._nextLink; // Cannot be null.
+      DoubleLinkedQueueEntry<E> next = entry._nextLink!; // Cannot be null.
       if (identical(removeMatching, matches)) {
         entry._remove();
         _elementCount--;
       }
-      entry = next;
+      entry = next as _DoubleLinkedQueueEntry<E>;
     }
   }
 
@@ -378,21 +390,21 @@
   }
 
   E get first {
-    _DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink;
-    return firstEntry._element;
+    DoubleLinkedQueueEntry<E> firstEntry = _sentinel._nextLink!;
+    return firstEntry._element as E;
   }
 
   E get last {
-    _DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink;
-    return lastEntry._element;
+    DoubleLinkedQueueEntry<E> lastEntry = _sentinel._previousLink!;
+    return lastEntry._element as E;
   }
 
   E get single {
     // Note that this throws correctly if the queue is empty
     // because reading the element of the sentinel throws.
     if (identical(_sentinel._nextLink, _sentinel._previousLink)) {
-      _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
-      return entry._element;
+      DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink!;
+      return entry._element as E;
     }
     throw IterableElementError.tooMany();
   }
@@ -448,17 +460,20 @@
   /// inserted after the current element before it is removed will not be
   /// visited by the iteration.
   void forEachEntry(void action(DoubleLinkedQueueEntry<E> element)) {
-    _DoubleLinkedQueueEntry<E> entry = _sentinel._nextLink;
+    _DoubleLinkedQueueEntry<E> entry =
+        _sentinel._nextLink as _DoubleLinkedQueueEntry<E>;
     while (!identical(entry, _sentinel)) {
-      _DoubleLinkedQueueElement<E> element = entry;
-      _DoubleLinkedQueueEntry<E> next = element._nextLink;
+      _DoubleLinkedQueueElement<E> element =
+          entry as _DoubleLinkedQueueElement<E>;
+      _DoubleLinkedQueueEntry<E> next =
+          element._nextLink as _DoubleLinkedQueueEntry<E>;
       // Remember both entry and entry._nextLink.
       // If someone calls `element.remove()` we continue from `next`.
       // Otherwise we use the value of entry._nextLink which may have been
       // updated.
       action(element);
       if (identical(this, entry._queue)) {
-        next = entry._nextLink;
+        next = entry._nextLink as _DoubleLinkedQueueEntry<E>;
       } else if (!identical(this, next._queue)) {
         throw ConcurrentModificationError(this);
       }
@@ -474,9 +489,9 @@
 }
 
 class _DoubleLinkedQueueIterator<E> implements Iterator<E> {
-  _DoubleLinkedQueueSentinel<E> _sentinel;
-  _DoubleLinkedQueueEntry<E> _nextEntry;
-  E _current;
+  _DoubleLinkedQueueSentinel<E>? _sentinel;
+  DoubleLinkedQueueEntry<E>? _nextEntry;
+  E? _current;
 
   _DoubleLinkedQueueIterator(_DoubleLinkedQueueSentinel<E> sentinel)
       : _sentinel = sentinel,
@@ -489,16 +504,17 @@
       _sentinel = null;
       return false;
     }
-    _DoubleLinkedQueueElement<E> elementEntry = _nextEntry;
-    if (!identical(_sentinel._queue, elementEntry._queue)) {
-      throw ConcurrentModificationError(_sentinel._queue);
+    _DoubleLinkedQueueEntry<E> elementEntry =
+        _nextEntry as _DoubleLinkedQueueEntry<E>;
+    if (!identical(_sentinel!._queue, elementEntry._queue)) {
+      throw ConcurrentModificationError(_sentinel!._queue);
     }
     _current = elementEntry._element;
     _nextEntry = elementEntry._nextLink;
     return true;
   }
 
-  E get current => _current;
+  E get current => _current as E;
 }
 
 /// List based [Queue].
@@ -510,7 +526,7 @@
 /// The structure is efficient for any queue or stack usage.
 class ListQueue<E> extends ListIterable<E> implements Queue<E> {
   static const int _INITIAL_CAPACITY = 8;
-  List<E> _table;
+  List<E?> _table;
   int _head;
   int _tail;
   int _modificationCount = 0;
@@ -519,16 +535,19 @@
   ///
   /// If [initialCapacity] is given, prepare the queue for at least that many
   /// elements.
-  ListQueue([int initialCapacity])
+  ListQueue([int? initialCapacity])
       : _head = 0,
-        _tail = 0 {
+        _tail = 0,
+        _table = List<E?>(_calculateCapacity(initialCapacity));
+
+  static int _calculateCapacity(int? initialCapacity) {
     if (initialCapacity == null || initialCapacity < _INITIAL_CAPACITY) {
-      initialCapacity = _INITIAL_CAPACITY;
+      return _INITIAL_CAPACITY;
     } else if (!_isPowerOf2(initialCapacity)) {
-      initialCapacity = _nextPowerOf2(initialCapacity);
+      return _nextPowerOf2(initialCapacity);
     }
     assert(_isPowerOf2(initialCapacity));
-    _table = List<E>(initialCapacity);
+    return initialCapacity;
   }
 
   /// Create a `ListQueue` containing all [elements].
@@ -544,13 +563,13 @@
   /// Queue<SubType> subQueue =
   ///     new ListQueue<SubType>.from(superQueue.whereType<SubType>());
   /// ```
-  factory ListQueue.from(Iterable elements) {
-    if (elements is List) {
+  factory ListQueue.from(Iterable<dynamic> elements) {
+    if (elements is List<dynamic>) {
       int length = elements.length;
       ListQueue<E> queue = ListQueue<E>(length + 1);
       assert(queue._table.length > length);
       for (int i = 0; i < length; i++) {
-        queue._table[i] = elements[i];
+        queue._table[i] = elements[i] as E;
       }
       queue._tail = length;
       return queue;
@@ -561,7 +580,7 @@
       }
       ListQueue<E> result = ListQueue<E>(capacity);
       for (final element in elements) {
-        result.addLast(element);
+        result.addLast(element as E);
       }
       return result;
     }
@@ -582,7 +601,7 @@
   void forEach(void f(E element)) {
     int modificationCount = _modificationCount;
     for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) {
-      f(_table[i]);
+      f(_table[i] as E);
       _checkModification(modificationCount);
     }
   }
@@ -593,32 +612,30 @@
 
   E get first {
     if (_head == _tail) throw IterableElementError.noElement();
-    return _table[_head];
+    return _table[_head] as E;
   }
 
   E get last {
     if (_head == _tail) throw IterableElementError.noElement();
-    return _table[(_tail - 1) & (_table.length - 1)];
+    return _table[(_tail - 1) & (_table.length - 1)] as E;
   }
 
   E get single {
     if (_head == _tail) throw IterableElementError.noElement();
     if (length > 1) throw IterableElementError.tooMany();
-    return _table[_head];
+    return _table[_head] as E;
   }
 
   E elementAt(int index) {
     RangeError.checkValidIndex(index, this);
-    return _table[(_head + index) & (_table.length - 1)];
+    return _table[(_head + index) & (_table.length - 1)] as E;
   }
 
   List<E> toList({bool growable = true}) {
-    List<E> list;
-    if (growable) {
-      list = <E>[]..length = length;
-    } else {
-      list = List<E>(length);
-    }
+    // TODO(rnystrom): Use List.empty() when that's available.
+    if (length == 0) return List<E>.of([], growable: growable);
+
+    List<E> list = List<E>.filled(length, first, growable: growable);
     _writeToList(list);
     return list;
   }
@@ -658,9 +675,9 @@
     }
   }
 
-  bool remove(Object value) {
+  bool remove(Object? value) {
     for (int i = _head; i != _tail; i = (i + 1) & (_table.length - 1)) {
-      E element = _table[i];
+      E? element = _table[i];
       if (element == value) {
         _remove(i);
         _modificationCount++;
@@ -674,7 +691,7 @@
     int modificationCount = _modificationCount;
     int i = _head;
     while (i != _tail) {
-      E element = _table[i];
+      E element = _table[i] as E;
       bool remove = identical(removeMatching, test(element));
       _checkModification(modificationCount);
       if (remove) {
@@ -730,7 +747,7 @@
   E removeFirst() {
     if (_head == _tail) throw IterableElementError.noElement();
     _modificationCount++;
-    E result = _table[_head];
+    E result = _table[_head] as E;
     _table[_head] = null;
     _head = (_head + 1) & (_table.length - 1);
     return result;
@@ -740,7 +757,7 @@
     if (_head == _tail) throw IterableElementError.noElement();
     _modificationCount++;
     _tail = (_tail - 1) & (_table.length - 1);
-    E result = _table[_tail];
+    E result = _table[_tail] as E;
     _table[_tail] = null;
     return result;
   }
@@ -820,7 +837,7 @@
 
   /// Grow the table when full.
   void _grow() {
-    List<E> newTable = List<E>(_table.length * 2);
+    List<E?> newTable = List<E?>(_table.length * 2);
     int split = _table.length - _head;
     newTable.setRange(0, split, _table, _head);
     newTable.setRange(split, split + _head, _table, 0);
@@ -829,7 +846,7 @@
     _table = newTable;
   }
 
-  int _writeToList(List<E> target) {
+  int _writeToList(List<E?> target) {
     assert(target.length >= length);
     if (_head <= _tail) {
       int length = _tail - _head;
@@ -851,7 +868,7 @@
     // expansion.
     newElementCount += newElementCount >> 1;
     int newCapacity = _nextPowerOf2(newElementCount);
-    List<E> newTable = List<E>(newCapacity);
+    List<E?> newTable = List<E?>(newCapacity);
     _tail = _writeToList(newTable);
     _table = newTable;
     _head = 0;
@@ -866,7 +883,7 @@
   final int _end;
   final int _modificationCount;
   int _position;
-  E _current;
+  E? _current;
 
   _ListQueueIterator(ListQueue<E> queue)
       : _queue = queue,
@@ -874,7 +891,7 @@
         _modificationCount = queue._modificationCount,
         _position = queue._head;
 
-  E get current => _current;
+  E get current => _current as E;
 
   bool moveNext() {
     _queue._checkModification(_modificationCount);
diff --git a/sdk_nnbd/lib/collection/set.dart b/sdk_nnbd/lib/collection/set.dart
index b6b9efc..7ac5bd7 100644
--- a/sdk_nnbd/lib/collection/set.dart
+++ b/sdk_nnbd/lib/collection/set.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.5
-
 /// Base implementations of [Set].
 part of dart.collection;
 
@@ -29,11 +27,11 @@
 
   bool add(E value);
 
-  bool contains(Object element);
+  bool contains(Object? element);
 
-  E lookup(Object element);
+  E? lookup(Object? element);
 
-  bool remove(Object value);
+  bool remove(Object? value);
 
   Iterator<E> get iterator;
 
@@ -59,22 +57,22 @@
     for (E element in elements) add(element);
   }
 
-  void removeAll(Iterable<Object> elements) {
-    for (Object element in elements) remove(element);
+  void removeAll(Iterable<Object?> elements) {
+    for (Object? element in elements) remove(element);
   }
 
-  void retainAll(Iterable<Object> elements) {
+  void retainAll(Iterable<Object?> elements) {
     // Create a copy of the set, remove all of elements from the copy,
     // then remove all remaining elements in copy from this.
     Set<E> toRemove = toSet();
-    for (Object o in elements) {
+    for (Object? o in elements) {
       toRemove.remove(o);
     }
     removeAll(toRemove);
   }
 
   void removeWhere(bool test(E element)) {
-    List toRemove = [];
+    List<Object?> toRemove = [];
     for (E element in this) {
       if (test(element)) toRemove.add(element);
     }
@@ -82,7 +80,7 @@
   }
 
   void retainWhere(bool test(E element)) {
-    List toRemove = [];
+    List<Object?> toRemove = [];
     for (E element in this) {
       if (!test(element)) toRemove.add(element);
     }
@@ -116,12 +114,8 @@
     return result;
   }
 
-  List<E> toList({bool growable = true}) {
-    List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
-    int i = 0;
-    for (E element in this) result[i++] = element;
-    return result;
-  }
+  List<E> toList({bool growable = true}) =>
+      List<E>.of(this, growable: growable);
 
   Iterable<T> map<T>(T f(E element)) =>
       EfficientLengthMappedIterable<E, T>(this, f);
@@ -234,7 +228,7 @@
     return result;
   }
 
-  E firstWhere(bool test(E value), {E orElse()}) {
+  E firstWhere(bool test(E value), {E Function()? orElse}) {
     for (E element in this) {
       if (test(element)) return element;
     }
@@ -242,8 +236,8 @@
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E value), {E orElse()}) {
-    E result;
+  E lastWhere(bool test(E value), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -256,8 +250,8 @@
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E value), {E orElse()}) {
-    E result;
+  E singleWhere(bool test(E value), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -301,7 +295,11 @@
 /// `clear` in constant time. The default implementation works by removing every
 /// element.
 abstract class SetBase<E> extends Object with SetMixin<E> {
-  /// Convert a `Set` to a string as `{each, element, as, string}`.
+  /// Converts a [Set] to a [String].
+  ///
+  /// Converts [set] to a string by converting each element to a string (by
+  /// calling [Object.toString]), joining them with ", ", and wrapping the
+  /// result in "{" and "}".
   ///
   /// Handles circular references where converting one of the elements
   /// to a string ends up converting [set] to a string again.
@@ -364,22 +362,22 @@
     for (E element in elements) add(element);
   }
 
-  void removeAll(Iterable<Object> elements) {
-    for (Object element in elements) remove(element);
+  void removeAll(Iterable<Object?> elements) {
+    for (Object? element in elements) remove(element);
   }
 
-  void retainAll(Iterable<Object> elements) {
+  void retainAll(Iterable<Object?> elements) {
     // Create a copy of the set, remove all of elements from the copy,
     // then remove all remaining elements in copy from this.
     Set<E> toRemove = toSet();
-    for (Object o in elements) {
+    for (Object? o in elements) {
       toRemove.remove(o);
     }
     removeAll(toRemove);
   }
 
   void removeWhere(bool test(E element)) {
-    List toRemove = [];
+    List<Object?> toRemove = [];
     for (E element in this) {
       if (test(element)) toRemove.add(element);
     }
@@ -387,15 +385,15 @@
   }
 
   void retainWhere(bool test(E element)) {
-    List toRemove = [];
+    List<Object?> toRemove = [];
     for (E element in this) {
       if (!test(element)) toRemove.add(element);
     }
     removeAll(toRemove);
   }
 
-  bool containsAll(Iterable<Object> other) {
-    for (Object o in other) {
+  bool containsAll(Iterable<Object?> other) {
+    for (Object? o in other) {
       if (!contains(o)) return false;
     }
     return true;
@@ -405,12 +403,8 @@
     return toSet()..addAll(other);
   }
 
-  List<E> toList({bool growable = true}) {
-    List<E> result = growable ? (<E>[]..length = length) : List<E>(length);
-    int i = 0;
-    for (E element in this) result[i++] = element;
-    return result;
-  }
+  List<E> toList({bool growable = true}) =>
+      List<E>.of(this, growable: growable);
 
   Iterable<T> map<T>(T f(E element)) =>
       EfficientLengthMappedIterable<E, T>(this, f);
@@ -520,7 +514,7 @@
     return result;
   }
 
-  E firstWhere(bool test(E value), {E orElse()}) {
+  E firstWhere(bool test(E value), {E Function()? orElse}) {
     for (E element in this) {
       if (test(element)) return element;
     }
@@ -528,8 +522,8 @@
     throw IterableElementError.noElement();
   }
 
-  E lastWhere(bool test(E value), {E orElse()}) {
-    E result;
+  E lastWhere(bool test(E value), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -542,8 +536,8 @@
     throw IterableElementError.noElement();
   }
 
-  E singleWhere(bool test(E value), {E orElse()}) {
-    E result;
+  E singleWhere(bool test(E value), {E Function()? orElse}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -583,13 +577,13 @@
 
   // Lookups use map methods.
 
-  bool contains(Object element) => _map.containsKey(element);
+  bool contains(Object? element) => _map.containsKey(element);
 
   Iterator<E> get iterator => _map.keys.iterator;
 
   int get length => _map.length;
 
-  E lookup(Object element) {
+  E? lookup(Object? element) {
     for (var key in _map.keys) {
       if (key == element) return key;
     }
@@ -610,11 +604,11 @@
     throw UnsupportedError("Cannot change unmodifiable set");
   }
 
-  void removeAll(Iterable<Object> elements) {
+  void removeAll(Iterable<Object?> elements) {
     throw UnsupportedError("Cannot change unmodifiable set");
   }
 
-  void retainAll(Iterable<Object> elements) {
+  void retainAll(Iterable<Object?> elements) {
     throw UnsupportedError("Cannot change unmodifiable set");
   }
 
@@ -626,7 +620,7 @@
     throw UnsupportedError("Cannot change unmodifiable set");
   }
 
-  bool remove(Object value) {
+  bool remove(Object? value) {
     throw UnsupportedError("Cannot change unmodifiable set");
   }
 }
diff --git a/sdk_nnbd/lib/collection/splay_tree.dart b/sdk_nnbd/lib/collection/splay_tree.dart
index ef3e51f..5d74080 100644
--- a/sdk_nnbd/lib/collection/splay_tree.dart
+++ b/sdk_nnbd/lib/collection/splay_tree.dart
@@ -2,22 +2,28 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.collection;
 
 typedef _Predicate<T> = bool Function(T value);
 
+class _SplayTreeNodeBase<K> {
+  _SplayTreeNode<K>? left;
+  _SplayTreeNode<K>? right;
+}
+
 /// A node in a splay tree. It holds the sorting key and the left
 /// and right children in the tree.
-class _SplayTreeNode<K> {
+class _SplayTreeNode<K> extends _SplayTreeNodeBase<K> {
   final K key;
-  _SplayTreeNode<K> left;
-  _SplayTreeNode<K> right;
 
   _SplayTreeNode(this.key);
 }
 
+class _DummySplayTreeNode<K> extends _SplayTreeNodeBase<K>
+    implements _SplayTreeNode<K> {
+  K get key => throw UnsupportedError("");
+}
+
 /// A node in a splay tree based map.
 ///
 /// A [_SplayTreeNode] that also contains a value
@@ -26,6 +32,12 @@
   _SplayTreeMapNode(K key, this.value) : super(key);
 }
 
+class _DummySplayTreeMapNode<K, V> extends _DummySplayTreeNode<K>
+    implements _SplayTreeMapNode<K, V> {
+  V get value => throw UnsupportedError("");
+  set value(V v) => throw UnsupportedError("");
+}
+
 /// A splay tree is a self-balancing binary search tree.
 ///
 /// It has the additional property that recently accessed elements
@@ -35,8 +47,8 @@
 abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
   // The root node of the splay tree. It will contain either the last
   // element inserted or the last element looked up.
-  Node get _root;
-  set _root(Node newValue);
+  Node? get _root;
+  set _root(Node? newValue);
 
   // The dummy node used when performing a splay on the tree. Reusing it
   // avoids allocating a node each time a splay is performed.
@@ -82,16 +94,16 @@
     // and right will always be nodes and we avoid special cases.
     Node left = _dummy;
     Node right = _dummy;
-    Node current = _root;
+    Node current = _root!;
     int comp;
     while (true) {
       comp = _compare(current.key, key);
       if (comp > 0) {
         if (current.left == null) break;
-        comp = _compare(current.left.key, key);
+        comp = _compare(current.left!.key, key);
         if (comp > 0) {
           // Rotate right.
-          _SplayTreeNode<K> tmp = current.left;
+          Node tmp = current.left as Node;
           current.left = tmp.right;
           tmp.right = current;
           current = tmp;
@@ -100,13 +112,13 @@
         // Link right.
         right.left = current;
         right = current;
-        current = current.left;
+        current = current.left as Node;
       } else if (comp < 0) {
         if (current.right == null) break;
-        comp = _compare(current.right.key, key);
+        comp = _compare(current.right!.key, key);
         if (comp < 0) {
           // Rotate left.
-          Node tmp = current.right;
+          Node tmp = current.right as Node;
           current.right = tmp.left;
           tmp.left = current;
           current = tmp;
@@ -115,7 +127,7 @@
         // Link left.
         left.right = current;
         left = current;
-        current = current.right;
+        current = current.right as Node;
       } else {
         break;
       }
@@ -146,22 +158,22 @@
   // in any parent tree or root pointer.
   external Node _splayMax(Node node);
 
-  Node _remove(K key) {
+  Node? _remove(K key) {
     if (_root == null) return null;
     int comp = _splay(key);
     if (comp != 0) return null;
-    Node result = _root;
+    Node result = _root!;
     _count--;
     // assert(_count >= 0);
-    if (_root.left == null) {
-      _root = _root.right;
+    if (_root!.left == null) {
+      _root = _root!.right as Node;
     } else {
-      Node right = _root.right;
+      Node right = _root!.right as Node;
       // Splay to make sure that the new root has an empty right child.
-      _root = _splayMax(_root.left);
+      _root = _splayMax(_root!.left as Node);
       // Insert the original right child as the right child of the new
       // root.
-      _root.right = right;
+      _root!.right = right;
     }
     _modificationCount++;
     return result;
@@ -181,25 +193,25 @@
     // assert(_count >= 0);
     if (comp < 0) {
       node.left = _root;
-      node.right = _root.right;
-      _root.right = null;
+      node.right = _root!.right;
+      _root!.right = null;
     } else {
       node.right = _root;
-      node.left = _root.left;
-      _root.left = null;
+      node.left = _root!.left;
+      _root!.left = null;
     }
     _root = node;
   }
 
-  Node get _first {
+  Node? get _first {
     if (_root == null) return null;
-    _root = _splayMin(_root);
+    _root = _splayMin(_root!);
     return _root;
   }
 
-  Node get _last {
+  Node? get _last {
     if (_root == null) return null;
-    _root = _splayMax(_root);
+    _root = _splayMax(_root!);
     return _root;
   }
 
@@ -210,18 +222,15 @@
   }
 }
 
-class _TypeTest<T> {
-  bool test(v) => v is T;
-}
-
-int _dynamicCompare(dynamic a, dynamic b) => Comparable.compare(a, b);
+int _dynamicCompare(dynamic a, dynamic b) =>
+    Comparable.compare(a as Comparable, b as Comparable);
 
 Comparator<K> _defaultCompare<K>() {
   // If K <: Comparable, then we can just use Comparable.compare
   // with no casts.
   Object compare = Comparable.compare;
   if (compare is Comparator<K>) {
-    return compare;
+    return compare as Comparator<K>;
   }
   // Otherwise wrap and cast the arguments on each call.
   return _dynamicCompare;
@@ -250,32 +259,36 @@
 /// value is a [K].
 class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
     with MapMixin<K, V> {
-  _SplayTreeMapNode<K, V> _root;
-  final _SplayTreeMapNode<K, V> _dummy = _SplayTreeMapNode<K, V>(null, null);
+  _SplayTreeMapNode<K, V>? _root;
+  final _SplayTreeMapNode<K, V> _dummy = _DummySplayTreeMapNode<K, V>();
 
   Comparator<K> _comparator;
   _Predicate _validKey;
 
-  SplayTreeMap([int compare(K key1, K key2), bool isValidKey(potentialKey)])
+  SplayTreeMap(
+      [int Function(K key1, K key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey])
       : _comparator = compare ?? _defaultCompare<K>(),
-        _validKey = isValidKey ?? ((v) => v is K);
+        _validKey = isValidKey ?? ((dynamic v) => v is K);
 
   /// Creates a [SplayTreeMap] 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.
-  factory SplayTreeMap.from(Map other,
-      [int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
+  factory SplayTreeMap.from(Map<dynamic, dynamic> other,
+      [int Function(K key1, K key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey]) {
     SplayTreeMap<K, V> result = SplayTreeMap<K, V>(compare, isValidKey);
-    other.forEach((k, v) {
-      result[k] = v;
+    other.forEach((dynamic k, dynamic v) {
+      result[k as K] = v as V;
     });
     return result;
   }
 
   /// Creates a [SplayTreeMap] that contains all key/value pairs of [other].
   factory SplayTreeMap.of(Map<K, V> other,
-          [int compare(K key1, K key2), bool isValidKey(potentialKey)]) =>
+          [int Function(K key1, K key2)? compare,
+          bool Function(dynamic potentialKey)? isValidKey]) =>
       SplayTreeMap<K, V>(compare, isValidKey)..addAll(other);
 
   /// Creates a [SplayTreeMap] where the keys and values are computed from the
@@ -290,10 +303,10 @@
   /// If no functions are specified for [key] and [value] the default is to
   /// use the iterable value itself.
   factory SplayTreeMap.fromIterable(Iterable iterable,
-      {K key(element),
-      V value(element),
-      int compare(K key1, K key2),
-      bool isValidKey(potentialKey)}) {
+      {K Function(dynamic element)? key,
+      V Function(dynamic element)? value,
+      int Function(K key1, K key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey}) {
     SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
     MapBase._fillMapWithMappedIterable(map, iterable, key, value);
     return map;
@@ -309,7 +322,8 @@
   ///
   /// It is an error if the two [Iterable]s don't have the same length.
   factory SplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
-      [int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
+      [int Function(K key1, K key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey]) {
     SplayTreeMap<K, V> map = SplayTreeMap<K, V>(compare, isValidKey);
     MapBase._fillMapWithIterables(map, keys, values);
     return map;
@@ -317,22 +331,20 @@
 
   int _compare(K key1, K key2) => _comparator(key1, key2);
 
-  SplayTreeMap._internal();
-
-  V operator [](Object key) {
+  V? operator [](Object? key) {
     if (!_validKey(key)) return null;
     if (_root != null) {
-      int comp = _splay(key);
+      int comp = _splay(key as K);
       if (comp == 0) {
-        return _root.value;
+        return _root!.value;
       }
     }
     return null;
   }
 
-  V remove(Object key) {
+  V? remove(Object? key) {
     if (!_validKey(key)) return null;
-    _SplayTreeMapNode<K, V> mapRoot = _remove(key);
+    _SplayTreeMapNode<K, V>? mapRoot = _remove(key as K);
     if (mapRoot != null) return mapRoot.value;
     return null;
   }
@@ -343,7 +355,7 @@
     // the key to the root of the tree.
     int comp = _splay(key);
     if (comp == 0) {
-      _root.value = value;
+      _root!.value = value;
       return;
     }
     _addNewRoot(_SplayTreeMapNode(key, value), comp);
@@ -353,7 +365,7 @@
     if (key == null) throw ArgumentError(key);
     int comp = _splay(key);
     if (comp == 0) {
-      return _root.value;
+      return _root!.value;
     }
     int modificationCount = _modificationCount;
     int splayCount = _splayCount;
@@ -385,7 +397,7 @@
   void forEach(void f(K key, V value)) {
     Iterator<_SplayTreeNode<K>> nodes = _SplayTreeNodeIterator<K>(this);
     while (nodes.moveNext()) {
-      _SplayTreeMapNode<K, V> node = nodes.current;
+      _SplayTreeMapNode<K, V> node = nodes.current as _SplayTreeMapNode<K, V>;
       f(node.key, node.value);
     }
   }
@@ -398,20 +410,22 @@
     _clear();
   }
 
-  bool containsKey(Object key) {
-    return _validKey(key) && _splay(key) == 0;
+  bool containsKey(Object? key) {
+    return _validKey(key) && _splay(key as K) == 0;
   }
 
-  bool containsValue(Object value) {
+  bool containsValue(Object? value) {
     int initialSplayCount = _splayCount;
-    bool visit(_SplayTreeMapNode node) {
+    bool visit(_SplayTreeMapNode? node) {
       while (node != null) {
         if (node.value == value) return true;
         if (initialSplayCount != _splayCount) {
           throw ConcurrentModificationError(this);
         }
-        if (node.right != null && visit(node.right)) return true;
-        node = node.left;
+        if (node.right != null && visit(node.right as _SplayTreeMapNode)) {
+          return true;
+        }
+        node = node.left as _SplayTreeMapNode;
       }
       return false;
     }
@@ -423,43 +437,43 @@
 
   Iterable<V> get values => _SplayTreeValueIterable<K, V>(this);
 
-  /// Get the first key in the map. Returns [:null:] if the map is empty.
-  K firstKey() {
+  /// Get the first key in the map. Returns `null` if the map is empty.
+  K? firstKey() {
     if (_root == null) return null;
-    return _first.key;
+    return _first!.key;
   }
 
-  /// Get the last key in the map. Returns [:null:] if the map is empty.
-  K lastKey() {
+  /// Get the last key in the map. Returns `null` if the map is empty.
+  K? lastKey() {
     if (_root == null) return null;
-    return _last.key;
+    return _last!.key;
   }
 
   /// Get the last key in the map that is strictly smaller than [key]. Returns
-  /// [:null:] if no key was not found.
-  K lastKeyBefore(K key) {
+  /// `null` if no key was not found.
+  K? lastKeyBefore(K key) {
     if (key == null) throw ArgumentError(key);
     if (_root == null) return null;
     int comp = _splay(key);
-    if (comp < 0) return _root.key;
-    _SplayTreeNode<K> node = _root.left;
+    if (comp < 0) return _root!.key;
+    _SplayTreeNode<K>? node = _root!.left;
     if (node == null) return null;
-    while (node.right != null) {
+    while (node!.right != null) {
       node = node.right;
     }
     return node.key;
   }
 
   /// Get the first key in the map that is strictly larger than [key]. Returns
-  /// [:null:] if no key was not found.
-  K firstKeyAfter(K key) {
+  /// `null` if no key was not found.
+  K? firstKeyAfter(K key) {
     if (key == null) throw ArgumentError(key);
     if (_root == null) return null;
     int comp = _splay(key);
-    if (comp > 0) return _root.key;
-    _SplayTreeNode<K> node = _root.right;
+    if (comp > 0) return _root!.key;
+    _SplayTreeNode<K>? node = _root!.right;
     if (node == null) return null;
-    while (node.left != null) {
+    while (node!.left != null) {
       node = node.left;
     }
     return node.key;
@@ -494,7 +508,7 @@
   int _splayCount;
 
   /// Current node.
-  _SplayTreeNode<K> _currentNode;
+  _SplayTreeNode<K>? _currentNode;
 
   _SplayTreeIterator(_SplayTree<K, _SplayTreeNode<K>> tree)
       : _tree = tree,
@@ -505,24 +519,25 @@
 
   _SplayTreeIterator.startAt(_SplayTree<K, _SplayTreeNode<K>> tree, K startKey)
       : _tree = tree,
-        _modificationCount = tree._modificationCount {
+        _modificationCount = tree._modificationCount,
+        _splayCount = -1 {
     if (tree._root == null) return;
     int compare = tree._splay(startKey);
     _splayCount = tree._splayCount;
     if (compare < 0) {
       // Don't include the root, start at the next element after the root.
-      _findLeftMostDescendent(tree._root.right);
+      _findLeftMostDescendent(tree._root!.right);
     } else {
       _workList.add(tree._root);
     }
   }
 
-  T get current {
+  T? get current {
     if (_currentNode == null) return null;
-    return _getValue(_currentNode);
+    return _getValue(_currentNode!);
   }
 
-  void _findLeftMostDescendent(_SplayTreeNode<K> node) {
+  void _findLeftMostDescendent(_SplayTreeNode<K>? node) {
     while (node != null) {
       _workList.add(node);
       node = node.left;
@@ -542,7 +557,7 @@
       _findLeftMostDescendent(_tree._root);
     } else {
       _tree._splay(currentNode.key);
-      _findLeftMostDescendent(_tree._root.right);
+      _findLeftMostDescendent(_tree._root!.right);
       assert(_workList.isNotEmpty);
     }
   }
@@ -561,10 +576,10 @@
       return false;
     }
     if (_tree._splayCount != _splayCount && _currentNode != null) {
-      _rebuildWorkList(_currentNode);
+      _rebuildWorkList(_currentNode!);
     }
     _currentNode = _workList.removeLast();
-    _findLeftMostDescendent(_currentNode.right);
+    _findLeftMostDescendent(_currentNode!.right);
     return true;
   }
 
@@ -602,7 +617,7 @@
 class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<K, V> {
   _SplayTreeValueIterator(SplayTreeMap<K, V> map) : super(map);
   V _getValue(_SplayTreeNode<K> node) {
-    _SplayTreeMapNode<K, V> mapNode = node;
+    _SplayTreeMapNode<K, V> mapNode = node as _SplayTreeMapNode<K, V>;
     return mapNode.value;
   }
 }
@@ -632,8 +647,8 @@
 /// in that case.
 class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
     with IterableMixin<E>, SetMixin<E> {
-  _SplayTreeNode<E> _root;
-  final _SplayTreeNode<E> _dummy = _SplayTreeNode<E>(null);
+  _SplayTreeNode<E>? _root;
+  final _SplayTreeNode<E> _dummy = _DummySplayTreeNode<E>();
 
   Comparator<E> _comparator;
   _Predicate _validKey;
@@ -660,9 +675,11 @@
   ///
   /// If omitted, the `isValidKey` function defaults to checking against the
   /// type parameter: `other is E`.
-  SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
+  SplayTreeSet(
+      [int Function(E key1, E key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey])
       : _comparator = compare ?? _defaultCompare<E>(),
-        _validKey = isValidKey ?? ((v) => v is E);
+        _validKey = isValidKey ?? ((dynamic v) => v is E);
 
   /// Creates a [SplayTreeSet] that contains all [elements].
   ///
@@ -678,10 +695,11 @@
   ///     new SplayTreeSet<SubType>.from(superSet.whereType<SubType>());
   /// ```
   factory SplayTreeSet.from(Iterable elements,
-      [int compare(E key1, E key2), bool isValidKey(potentialKey)]) {
+      [int Function(E key1, E key2)? compare,
+      bool Function(dynamic potentialKey)? isValidKey]) {
     SplayTreeSet<E> result = SplayTreeSet<E>(compare, isValidKey);
     for (final element in elements) {
-      E e = element;
+      E e = element as E;
       result.add(e);
     }
     return result;
@@ -693,7 +711,8 @@
   ///
   /// All the [elements] should be valid as arguments to the [compare] function.
   factory SplayTreeSet.of(Iterable<E> elements,
-          [int compare(E key1, E key2), bool isValidKey(potentialKey)]) =>
+          [int Function(E key1, E key2)? compare,
+          bool Function(dynamic potentialKey)? isValidKey]) =>
       SplayTreeSet(compare, isValidKey)..addAll(elements);
 
   Set<T> _newSet<T>() =>
@@ -712,23 +731,23 @@
 
   E get first {
     if (_count == 0) throw IterableElementError.noElement();
-    return _first.key;
+    return _first!.key;
   }
 
   E get last {
     if (_count == 0) throw IterableElementError.noElement();
-    return _last.key;
+    return _last!.key;
   }
 
   E get single {
     if (_count == 0) throw IterableElementError.noElement();
     if (_count > 1) throw IterableElementError.tooMany();
-    return _root.key;
+    return _root!.key;
   }
 
   // From Set.
-  bool contains(Object element) {
-    return _validKey(element) && _splay(element) == 0;
+  bool contains(Object? element) {
+    return _validKey(element) && _splay(element as E) == 0;
   }
 
   bool add(E element) {
@@ -738,9 +757,9 @@
     return true;
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     if (!_validKey(object)) return false;
-    return _remove(object) != null;
+    return _remove(object as E) != null;
   }
 
   void addAll(Iterable<E> elements) {
@@ -752,24 +771,24 @@
     }
   }
 
-  void removeAll(Iterable<Object> elements) {
-    for (Object element in elements) {
-      if (_validKey(element)) _remove(element);
+  void removeAll(Iterable<Object?> elements) {
+    for (Object? element in elements) {
+      if (_validKey(element)) _remove(element as E);
     }
   }
 
-  void retainAll(Iterable<Object> elements) {
+  void retainAll(Iterable<Object?> elements) {
     // Build a set with the same sense of equality as this set.
     SplayTreeSet<E> retainSet = SplayTreeSet<E>(_comparator, _validKey);
     int modificationCount = _modificationCount;
-    for (Object object in elements) {
+    for (Object? object in elements) {
       if (modificationCount != _modificationCount) {
         // The iterator should not have side effects.
         throw ConcurrentModificationError(this);
       }
       // Equivalent to this.contains(object).
-      if (_validKey(object) && _splay(object) == 0) {
-        retainSet.add(_root.key);
+      if (_validKey(object) && _splay(object as E) == 0) {
+        retainSet.add(_root!.key);
       }
     }
     // Take over the elements from the retained set, if it differs.
@@ -780,14 +799,14 @@
     }
   }
 
-  E lookup(Object object) {
+  E? lookup(Object? object) {
     if (!_validKey(object)) return null;
-    int comp = _splay(object);
+    int comp = _splay(object as E);
     if (comp != 0) return null;
-    return _root.key;
+    return _root!.key;
   }
 
-  Set<E> intersection(Set<Object> other) {
+  Set<E> intersection(Set<Object?> other) {
     Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
     for (E element in this) {
       if (other.contains(element)) result.add(element);
@@ -795,7 +814,7 @@
     return result;
   }
 
-  Set<E> difference(Set<Object> other) {
+  Set<E> difference(Set<Object?> other) {
     Set<E> result = SplayTreeSet<E>(_comparator, _validKey);
     for (E element in this) {
       if (!other.contains(element)) result.add(element);
@@ -816,7 +835,7 @@
 
   // Copies the structure of a SplayTree into a new similar structure.
   // Works on _SplayTreeMapNode as well, but only copies the keys,
-  _SplayTreeNode<E> _copyNode(_SplayTreeNode<E> node) {
+  _SplayTreeNode<E>? _copyNode(_SplayTreeNode<E>? node) {
     if (node == null) return null;
     return _SplayTreeNode<E>(node.key)
       ..left = _copyNode(node.left)
diff --git a/sdk_nnbd/lib/convert/ascii.dart b/sdk_nnbd/lib/convert/ascii.dart
index 307ac08..9d98016 100644
--- a/sdk_nnbd/lib/convert/ascii.dart
+++ b/sdk_nnbd/lib/convert/ascii.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.5
-
 part of dart.convert;
 
 /// An instance of the default implementation of the [AsciiCodec].
@@ -50,9 +48,8 @@
   ///
   /// If [allowInvalid] is not provided, it defaults to the value used to create
   /// this [AsciiCodec].
-  String decode(List<int> bytes, {bool allowInvalid}) {
-    allowInvalid ??= _allowInvalid;
-    if (allowInvalid) {
+  String decode(List<int> bytes, {bool? allowInvalid}) {
+    if (allowInvalid ?? _allowInvalid) {
       return const AsciiDecoder(allowInvalid: true).convert(bytes);
     } else {
       return const AsciiDecoder(allowInvalid: false).convert(bytes);
@@ -77,9 +74,13 @@
   ///
   /// If [start] and [end] are provided, only the substring
   /// `string.substring(start, end)` is used as input to the conversion.
-  Uint8List convert(String string, [int start = 0, int end]) {
+  Uint8List convert(String string, [int start = 0, int? end]) {
     var stringLength = string.length;
     end = RangeError.checkValidRange(start, end, stringLength);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     var length = end - start;
     var result = Uint8List(length);
     for (var i = 0; i < length; i++) {
@@ -164,11 +165,12 @@
   ///
   /// If [start] and [end] are provided, only the sub-list of bytes from
   /// `start` to `end` (`end` not inclusive) is used as input to the conversion.
-  String convert(List<int> bytes, [int start = 0, int end]) {
-    var byteCount = bytes.length;
-    RangeError.checkValidRange(start, end, byteCount);
-    end ??= byteCount;
-
+  String convert(List<int> bytes, [int start = 0, int? end]) {
+    end = RangeError.checkValidRange(start, end, bytes.length);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     for (var i = start; i < end; i++) {
       var byte = bytes[i];
       if ((byte & ~_subsetMask) != 0) {
diff --git a/sdk_nnbd/lib/convert/base64.dart b/sdk_nnbd/lib/convert/base64.dart
index 4187658..265ff69 100644
--- a/sdk_nnbd/lib/convert/base64.dart
+++ b/sdk_nnbd/lib/convert/base64.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.5
-
 part of dart.convert;
 
 /// A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
@@ -37,18 +35,18 @@
 
 /// Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
 ///
-/// Shorthand for [base64.encode]. Useful if a local variable shadows the global
+/// Shorthand for `base64.encode(bytes)`. Useful if a local variable shadows the global
 /// [base64] constant.
 String base64Encode(List<int> bytes) => base64.encode(bytes);
 
 /// Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding.
 ///
-/// Shorthand for [base64url.encode].
+/// Shorthand for `base64url.encode(bytes)`.
 String base64UrlEncode(List<int> bytes) => base64Url.encode(bytes);
 
 /// Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes.
 ///
-/// Shorthand for [base64.decode]. Useful if a local variable shadows the
+/// Shorthand for `base64.decode(bytes)`. Useful if a local variable shadows the
 /// global [base64] constant.
 Uint8List base64Decode(String source) => base64.decode(source);
 
@@ -95,11 +93,15 @@
   /// * Validate that existing padding (trailing `=` characters) is correct.
   /// * If no padding exists, add correct padding if necessary and possible.
   /// * Validate that the length is correct (a multiple of four).
-  String normalize(String source, [int start = 0, int end]) {
+  String normalize(String source, [int start = 0, int? end]) {
     end = RangeError.checkValidRange(start, end, source.length);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     const percent = 0x25;
     const equals = 0x3d;
-    StringBuffer buffer;
+    StringBuffer? buffer;
     var sliceStart = start;
     var alphabet = _Base64Encoder._base64Alphabet;
     var inverseAlphabet = _Base64Decoder._inverseAlphabet;
@@ -142,9 +144,9 @@
           if (originalChar == equals) continue;
         }
         if (value != _Base64Decoder._invalid) {
-          buffer ??= StringBuffer();
-          buffer.write(source.substring(sliceStart, sliceEnd));
-          buffer.writeCharCode(char);
+          (buffer ??= StringBuffer())
+            ..write(source.substring(sliceStart, sliceEnd))
+            ..writeCharCode(char);
           sliceStart = i;
           continue;
         }
@@ -233,7 +235,7 @@
   String convert(List<int> input) {
     if (input.isEmpty) return "";
     var encoder = _Base64Encoder(_urlSafe);
-    var buffer = encoder.encode(input, 0, input.length, true);
+    var buffer = encoder.encode(input, 0, input.length, true)!;
     return String.fromCharCodes(buffer);
   }
 
@@ -302,10 +304,10 @@
   /// with the necessary padding.
   ///
   /// Returns `null` if there is no output.
-  Uint8List encode(List<int> bytes, int start, int end, bool isLast) {
+  Uint8List? encode(List<int> bytes, int start, int end, bool isLast) {
     assert(0 <= start);
     assert(start <= end);
-    assert(bytes == null || end <= bytes.length);
+    assert(end <= bytes.length);
     var length = end - start;
 
     var count = _stateCount(_state);
@@ -395,16 +397,21 @@
   ///
   /// When the buffer isn't released to the sink, only used to create another
   /// value (a string), the buffer can be reused between chunks.
-  Uint8List bufferCache;
+  Uint8List? bufferCache;
 
   _BufferCachingBase64Encoder(bool urlSafe) : super(urlSafe);
 
   Uint8List createBuffer(int bufferLength) {
-    if (bufferCache == null || bufferCache.length < bufferLength) {
-      bufferCache = Uint8List(bufferLength);
+    Uint8List? buffer = bufferCache;
+    if (buffer == null || buffer.length < bufferLength) {
+      bufferCache = buffer = Uint8List(bufferLength);
+    }
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (buffer == null) {
+      throw "unreachable";
     }
     // Return a view of the buffer, so it has the requested length.
-    return Uint8List.view(bufferCache.buffer, 0, bufferLength);
+    return Uint8List.view(buffer.buffer, 0, bufferLength);
   }
 }
 
@@ -414,7 +421,7 @@
   }
 
   void close() {
-    _add(null, 0, 0, true);
+    _add(const [], 0, 0, true);
   }
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
@@ -480,11 +487,15 @@
   /// The returned [Uint8List] contains exactly the decoded bytes,
   /// so the [Uint8List.length] is precisely the number of decoded bytes.
   /// The [Uint8List.buffer] may be larger than the decoded bytes.
-  Uint8List convert(String input, [int start = 0, int end]) {
+  Uint8List convert(String input, [int start = 0, int? end]) {
     end = RangeError.checkValidRange(start, end, input.length);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     if (start == end) return Uint8List(0);
     var decoder = _Base64Decoder();
-    var buffer = decoder.decode(input, start, end);
+    var buffer = decoder.decode(input, start, end)!;
     decoder.close(input, end);
     return buffer;
   }
@@ -594,7 +605,7 @@
   /// Returns a [Uint8List] with the decoded bytes.
   /// If a previous call had an incomplete four-character block, the bits from
   /// those are included in decoding
-  Uint8List decode(String input, int start, int end) {
+  Uint8List? decode(String input, int start, int end) {
     assert(0 <= start);
     assert(start <= end);
     assert(end <= input.length);
@@ -604,12 +615,14 @@
     }
     if (start == end) return Uint8List(0);
     var buffer = _allocateBuffer(input, start, end, _state);
-    _state = decodeChunk(input, start, end, buffer, 0, _state);
+    if (buffer.length > 0) {
+      _state = decodeChunk(input, start, end, buffer, 0, _state);
+    }
     return buffer;
   }
 
   /// Checks that [_state] represents a valid decoding.
-  void close(String input, int end) {
+  void close(String? input, int? end) {
     if (_state < _encodePaddingState(0)) {
       throw FormatException("Missing padding character", input, end);
     }
@@ -693,6 +706,8 @@
     throw FormatException("Invalid character", input, i);
   }
 
+  static Uint8List _emptyBuffer = Uint8List(0);
+
   /// Allocates a buffer with room for the decoding of a substring of [input].
   ///
   /// Includes room for the characters in [state], and handles padding correctly.
@@ -712,7 +727,7 @@
     if (bufferLength > 0) return Uint8List(bufferLength);
     // If the input plus state is less than four characters, and it's not
     // at the end of input, no buffer is needed.
-    return null;
+    return _emptyBuffer;
   }
 
   /// Returns the position of the start of padding at the end of the input.
@@ -844,7 +859,7 @@
   }
 
   void addSlice(String string, int start, int end, bool isLast) {
-    end = RangeError.checkValidRange(start, end, string.length);
+    RangeError.checkValidRange(start, end, string.length);
     if (start == end) return;
     var buffer = _decoder.decode(string, start, end);
     if (buffer != null) _sink.add(buffer);
diff --git a/sdk_nnbd/lib/convert/byte_conversion.dart b/sdk_nnbd/lib/convert/byte_conversion.dart
index 9e66ecd..3d52d78 100644
--- a/sdk_nnbd/lib/convert/byte_conversion.dart
+++ b/sdk_nnbd/lib/convert/byte_conversion.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.5
-
 part of dart.convert;
 
 /// The [ByteConversionSink] provides an interface for converters to
diff --git a/sdk_nnbd/lib/convert/chunked_conversion.dart b/sdk_nnbd/lib/convert/chunked_conversion.dart
index d2f1a7c..654c9d2 100644
--- a/sdk_nnbd/lib/convert/chunked_conversion.dart
+++ b/sdk_nnbd/lib/convert/chunked_conversion.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.5
-
 part of dart.convert;
 
 /// A [ChunkedConversionSink] is used to transmit data more efficiently between
@@ -74,7 +72,7 @@
     _chunkedSink.add(o);
   }
 
-  void addError(Object error, [StackTrace stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     _eventSink.addError(error, stackTrace);
   }
 
diff --git a/sdk_nnbd/lib/convert/codec.dart b/sdk_nnbd/lib/convert/codec.dart
index 7c9fb07..38e4a3c 100644
--- a/sdk_nnbd/lib/convert/codec.dart
+++ b/sdk_nnbd/lib/convert/codec.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.5
-
 part of dart.convert;
 
 /// A [Codec] encodes and (if supported) decodes data.
diff --git a/sdk_nnbd/lib/convert/convert.dart b/sdk_nnbd/lib/convert/convert.dart
index 727a8c8..6173782 100644
--- a/sdk_nnbd/lib/convert/convert.dart
+++ b/sdk_nnbd/lib/convert/convert.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.5
-
 ///
 /// Encoders and decoders for converting between different data representations,
 /// including JSON and UTF-8.
diff --git a/sdk_nnbd/lib/convert/converter.dart b/sdk_nnbd/lib/convert/converter.dart
index 0205771..2167933 100644
--- a/sdk_nnbd/lib/convert/converter.dart
+++ b/sdk_nnbd/lib/convert/converter.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.5
-
 part of dart.convert;
 
 /// A [Converter] converts data from one representation into another.
diff --git a/sdk_nnbd/lib/convert/encoding.dart b/sdk_nnbd/lib/convert/encoding.dart
index d6d36ee..b9238a8 100644
--- a/sdk_nnbd/lib/convert/encoding.dart
+++ b/sdk_nnbd/lib/convert/encoding.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.5
-
 part of dart.convert;
 
 /// Open-ended Encoding enum.
@@ -74,10 +72,9 @@
   ///
   /// The [name] passed is case insensitive.
   ///
-  /// If character set is not supported [:null:] is returned.
-  static Encoding getByName(String name) {
+  /// If character set is not supported `null` is returned.
+  static Encoding? getByName(String? name) {
     if (name == null) return null;
-    name = name.toLowerCase();
-    return _nameToEncoding[name];
+    return _nameToEncoding[name.toLowerCase()];
   }
 }
diff --git a/sdk_nnbd/lib/convert/html_escape.dart b/sdk_nnbd/lib/convert/html_escape.dart
index 98f24df..317e6c1 100644
--- a/sdk_nnbd/lib/convert/html_escape.dart
+++ b/sdk_nnbd/lib/convert/html_escape.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.5
-
 part of dart.convert;
 
 /// A `String` converter that converts characters to HTML entities.
@@ -160,11 +158,11 @@
   ///
   /// Returns `null` if no changes were necessary, otherwise returns
   /// the converted string.
-  String _convert(String text, int start, int end) {
-    StringBuffer result;
+  String? _convert(String text, int start, int end) {
+    StringBuffer? result;
     for (var i = start; i < end; i++) {
       var ch = text[i];
-      String replacement;
+      String? replacement;
       switch (ch) {
         case '&':
           replacement = '&amp;';
@@ -187,6 +185,11 @@
       }
       if (replacement != null) {
         result ??= StringBuffer();
+        // TODO(38725): Remove workaround when assignment promotion is
+        // implemented
+        if (result == null) {
+          throw "unreachable";
+        }
         if (i > start) result.write(text.substring(start, i));
         result.write(replacement);
         start = i + 1;
diff --git a/sdk_nnbd/lib/convert/json.dart b/sdk_nnbd/lib/convert/json.dart
index 6ac392a..1fafde7 100644
--- a/sdk_nnbd/lib/convert/json.dart
+++ b/sdk_nnbd/lib/convert/json.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.5
-
 part of dart.convert;
 
 /// Error thrown by JSON serialization if an object cannot be serialized.
@@ -16,15 +14,15 @@
 /// serializable, the [cause] is null.
 class JsonUnsupportedObjectError extends Error {
   /// The object that could not be serialized.
-  final Object unsupportedObject;
+  final Object? unsupportedObject;
 
   /// The exception thrown when trying to convert the object.
-  final Object cause;
+  final Object? cause;
 
   /// The partial result of the conversion, up until the error happened.
   ///
   /// May be null.
-  final String partialResult;
+  final String? partialResult;
 
   JsonUnsupportedObjectError(this.unsupportedObject,
       {this.cause, this.partialResult});
@@ -48,7 +46,7 @@
 /// When the cycle is detected, a [JsonCyclicError] is thrown.
 class JsonCyclicError extends JsonUnsupportedObjectError {
   /// The first object that was detected as part of a cycle.
-  JsonCyclicError(Object object) : super(object);
+  JsonCyclicError(Object? object) : super(object);
   String toString() => "Cyclic error in JSON stringify";
 }
 
@@ -76,9 +74,10 @@
 /// If [toEncodable] is omitted, it defaults to a function that returns the
 /// result of calling `.toJson()` on the unencodable object.
 ///
-/// Shorthand for [json.encode]. Useful if a local variable shadows the global
+/// Shorthand for `json.encode`. Useful if a local variable shadows the global
 /// [json] constant.
-String jsonEncode(Object object, {Object toEncodable(Object nonEncodable)}) =>
+String jsonEncode(Object? object,
+        {Object? toEncodable(Object? nonEncodable)?}) =>
     json.encode(object, toEncodable: toEncodable);
 
 /// Parses the string and returns the resulting Json object.
@@ -90,9 +89,10 @@
 ///
 /// The default [reviver] (when not provided) is the identity function.
 ///
-/// Shorthand for [json.decode]. Useful if a local variable shadows the global
+/// Shorthand for `json.decode`. Useful if a local variable shadows the global
 /// [json] constant.
-dynamic jsonDecode(String source, {Object reviver(Object key, Object value)}) =>
+dynamic jsonDecode(String source,
+        {Object? reviver(Object? key, Object? value)?}) =>
     json.decode(source, reviver: reviver);
 
 /// A [JsonCodec] encodes JSON objects to strings and decodes strings to
@@ -102,9 +102,9 @@
 ///
 ///     var encoded = json.encode([1, 2, { "a": null }]);
 ///     var decoded = json.decode('["foo", { "bar": 499 }]');
-class JsonCodec extends Codec<Object, String> {
-  final Function(Object key, Object value) _reviver;
-  final Function(dynamic) _toEncodable;
+class JsonCodec extends Codec<Object?, String> {
+  final Object? Function(Object? key, Object? value)? _reviver;
+  final Object? Function(dynamic)? _toEncodable;
 
   /// Creates a `JsonCodec` with the given reviver and encoding function.
   ///
@@ -127,7 +127,9 @@
   ///
   /// If [toEncodable] is omitted, it defaults to a function that returns the
   /// result of calling `.toJson()` on the unencodable object.
-  const JsonCodec({reviver(Object key, Object value), toEncodable(var object)})
+  const JsonCodec(
+      {Object? reviver(Object? key, Object? value)?,
+      Object? toEncodable(dynamic object)?})
       : _reviver = reviver,
         _toEncodable = toEncodable;
 
@@ -137,7 +139,7 @@
   /// that has been parsed during decoding. The `key` argument is either the
   /// integer list index for a list property, the string map key for object
   /// properties, or `null` for the final result.
-  JsonCodec.withReviver(reviver(Object key, Object value))
+  JsonCodec.withReviver(dynamic reviver(Object? key, Object? value))
       : this(reviver: reviver);
 
   /// Parses the string and returns the resulting Json object.
@@ -148,7 +150,8 @@
   /// properties, or `null` for the final result.
   ///
   /// The default [reviver] (when not provided) is the identity function.
-  dynamic decode(String source, {reviver(Object key, Object value)}) {
+  dynamic decode(String source,
+      {Object? reviver(Object? key, Object? value)?}) {
     reviver ??= _reviver;
     if (reviver == null) return decoder.convert(source);
     return JsonDecoder(reviver).convert(source);
@@ -163,7 +166,7 @@
   ///
   /// If [toEncodable] is omitted, it defaults to a function that returns the
   /// result of calling `.toJson()` on the unencodable object.
-  String encode(Object value, {toEncodable(object)}) {
+  String encode(Object? value, {Object? toEncodable(dynamic object)?}) {
     toEncodable ??= _toEncodable;
     if (toEncodable == null) return encoder.convert(value);
     return JsonEncoder(toEncodable).convert(value);
@@ -181,18 +184,18 @@
 }
 
 /// This class converts JSON objects to strings.
-class JsonEncoder extends Converter<Object, String> {
+class JsonEncoder extends Converter<Object?, String> {
   /// The string used for indention.
   ///
   /// When generating multi-line output, this string is inserted once at the
   /// beginning of each indented line for each level of indentation.
   ///
   /// If `null`, the output is encoded as a single line.
-  final String indent;
+  final String? indent;
 
   /// Function called on non-encodable objects to return a replacement
   /// encodable object that will be encoded in the orignal's place.
-  final Function(dynamic) _toEncodable;
+  final Object? Function(dynamic)? _toEncodable;
 
   /// Creates a JSON encoder.
   ///
@@ -204,7 +207,7 @@
   ///
   /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on
   /// the object.
-  const JsonEncoder([toEncodable(object)])
+  const JsonEncoder([Object? toEncodable(dynamic object)?])
       : indent = null,
         _toEncodable = toEncodable;
 
@@ -224,7 +227,8 @@
   ///
   /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on
   /// the object.
-  const JsonEncoder.withIndent(this.indent, [toEncodable(object)])
+  const JsonEncoder.withIndent(this.indent,
+      [Object? toEncodable(dynamic object)?])
       : _toEncodable = toEncodable;
 
   /// Converts [object] to a JSON [String].
@@ -253,7 +257,7 @@
   /// If an object is serialized more than once, [convert] may cache the text
   /// for it. In other words, if the content of an object changes after it is
   /// first serialized, the new values may not be reflected in the result.
-  String convert(Object object) =>
+  String convert(Object? object) =>
       _JsonStringStringifier.stringify(object, _toEncodable, indent);
 
   /// Starts a chunked conversion.
@@ -263,7 +267,7 @@
   ///
   /// Returns a chunked-conversion sink that accepts at most one object. It is
   /// an error to invoke `add` more than once on the returned sink.
-  ChunkedConversionSink<Object> startChunkedConversion(Sink<String> sink) {
+  ChunkedConversionSink<Object?> startChunkedConversion(Sink<String> sink) {
     if (sink is _Utf8EncoderSink) {
       return _JsonUtf8EncoderSink(
           sink._sink,
@@ -278,15 +282,15 @@
   }
 
   // Override the base class's bind, to provide a better type.
-  Stream<String> bind(Stream<Object> stream) => super.bind(stream);
+  Stream<String> bind(Stream<Object?> stream) => super.bind(stream);
 
-  Converter<Object, T> fuse<T>(Converter<String, T> other) {
-    if (other is Utf8Encoder && T is List<int>) {
+  Converter<Object?, T> fuse<T>(Converter<String, T> other) {
+    if (other is Utf8Encoder) {
       // The instance check guarantees that `T` is (a subtype of) List<int>,
       // but the static type system doesn't know that, and so we cast.
       // Cast through dynamic to keep the cast implicit for builds using
       // unchecked implicit casts.
-      return JsonUtf8Encoder(indent, _toEncodable) as dynamic;
+      return JsonUtf8Encoder(indent, _toEncodable) as Converter<Object?, T>;
     }
     return super.fuse<T>(other);
   }
@@ -297,17 +301,17 @@
 /// This encoder works equivalently to first converting the object to
 /// a JSON string, and then UTF-8 encoding the string, but without
 /// creating an intermediate string.
-class JsonUtf8Encoder extends Converter<Object, List<int>> {
+class JsonUtf8Encoder extends Converter<Object?, List<int>> {
   /// Default buffer size used by the JSON-to-UTF-8 encoder.
   static const int _defaultBufferSize = 256;
   @deprecated
   static const int DEFAULT_BUFFER_SIZE = _defaultBufferSize;
 
   /// Indentation used in pretty-print mode, `null` if not pretty.
-  final List<int> _indent;
+  final List<int>? _indent;
 
   /// Function called with each un-encodable object encountered.
-  final Function(dynamic) _toEncodable;
+  final Object? Function(dynamic)? _toEncodable;
 
   /// UTF-8 buffer size.
   final int _bufferSize;
@@ -336,12 +340,12 @@
   /// If [toEncodable] is omitted, it defaults to calling `.toJson()` on the
   /// object.
   JsonUtf8Encoder(
-      [String indent, toEncodable(object), int bufferSize = _defaultBufferSize])
+      [String? indent, dynamic toEncodable(dynamic object)?, int? bufferSize])
       : _indent = _utf8Encode(indent),
         _toEncodable = toEncodable,
-        _bufferSize = bufferSize;
+        _bufferSize = bufferSize ?? _defaultBufferSize;
 
-  static List<int> _utf8Encode(String string) {
+  static List<int>? _utf8Encode(String? string) {
     if (string == null) return null;
     if (string.isEmpty) return Uint8List(0);
     checkAscii:
@@ -355,7 +359,7 @@
   }
 
   /// Convert [object] into UTF-8 encoded JSON.
-  List<int> convert(Object object) {
+  List<int> convert(Object? object) {
     var bytes = <List<int>>[];
     // The `stringify` function always converts into chunks.
     // Collect the chunks into the `bytes` list, then combine them afterwards.
@@ -391,7 +395,7 @@
   ///
   /// The argument [sink] will receive byte lists in sizes depending on the
   /// `bufferSize` passed to the constructor when creating this encoder.
-  ChunkedConversionSink<Object> startChunkedConversion(Sink<List<int>> sink) {
+  ChunkedConversionSink<Object?> startChunkedConversion(Sink<List<int>> sink) {
     ByteConversionSink byteSink;
     if (sink is ByteConversionSink) {
       byteSink = sink;
@@ -402,7 +406,7 @@
   }
 
   // Override the base class's bind, to provide a better type.
-  Stream<List<int>> bind(Stream<Object> stream) {
+  Stream<List<int>> bind(Stream<Object?> stream) {
     return super.bind(stream);
   }
 }
@@ -410,9 +414,9 @@
 /// Implements the chunked conversion from object to its JSON representation.
 ///
 /// The sink only accepts one value, but will produce output in a chunked way.
-class _JsonEncoderSink extends ChunkedConversionSink<Object> {
-  final String _indent;
-  final Function(dynamic) _toEncodable;
+class _JsonEncoderSink extends ChunkedConversionSink<Object?> {
+  final String? _indent;
+  final Object? Function(dynamic)? _toEncodable;
   final StringConversionSink _sink;
   bool _isDone = false;
 
@@ -423,7 +427,7 @@
   /// It is an error to invoke this method more than once on any instance. While
   /// this makes the input effectively non-chunked the output will be generated
   /// in a chunked way.
-  void add(Object o) {
+  void add(Object? o) {
     if (_isDone) {
       throw StateError("Only one call to add allowed");
     }
@@ -437,11 +441,11 @@
 }
 
 /// Sink returned when starting a chunked conversion from object to bytes.
-class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object> {
+class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object?> {
   /// The byte sink receiveing the encoded chunks.
   final ByteConversionSink _sink;
-  final List<int> _indent;
-  final Function(dynamic) _toEncodable;
+  final List<int>? _indent;
+  final Object? Function(dynamic)? _toEncodable;
   final int _bufferSize;
   bool _isDone = false;
   _JsonUtf8EncoderSink(
@@ -452,7 +456,7 @@
     _sink.addSlice(chunk, start, end, false);
   }
 
-  void add(Object object) {
+  void add(Object? object) {
     if (_isDone) {
       throw StateError("Only one call to add allowed");
     }
@@ -471,13 +475,14 @@
 }
 
 /// This class parses JSON strings and builds the corresponding objects.
-class JsonDecoder extends Converter<String, Object> {
-  final Function(Object key, Object value) _reviver;
+class JsonDecoder extends Converter<String, Object?> {
+  final Object? Function(Object? key, Object? value)? _reviver;
 
   /// Constructs a new JsonDecoder.
   ///
   /// The [reviver] may be `null`.
-  const JsonDecoder([reviver(Object key, Object value)]) : _reviver = reviver;
+  const JsonDecoder([Object? reviver(Object? key, Object? value)?])
+      : _reviver = reviver;
 
   /// Converts the given JSON-string [input] to its corresponding object.
   ///
@@ -497,14 +502,14 @@
   /// Starts a conversion from a chunked JSON string to its corresponding object.
   ///
   /// The output [sink] receives exactly one decoded element through `add`.
-  external StringConversionSink startChunkedConversion(Sink<Object> sink);
+  external StringConversionSink startChunkedConversion(Sink<Object?> sink);
 
   // Override the base class's bind, to provide a better type.
-  Stream<Object> bind(Stream<String> stream) => super.bind(stream);
+  Stream<Object?> bind(Stream<String> stream) => super.bind(stream);
 }
 
 // Internal optimized JSON parsing implementation.
-external _parseJson(String source, reviver(key, value));
+external _parseJson(String source, reviver(key, value)?);
 
 // Implementation of encoder/stringifier.
 
@@ -537,10 +542,10 @@
   /// Function called for each un-encodable object encountered.
   final Function(dynamic) _toEncodable;
 
-  _JsonStringifier(toEncodable(o))
+  _JsonStringifier(dynamic toEncodable(dynamic o)?)
       : _toEncodable = toEncodable ?? _defaultToEncodable;
 
-  String get _partialResult;
+  String? get _partialResult;
 
   /// Append a string to the JSON output.
   void writeString(String characters);
@@ -610,7 +615,7 @@
   ///
   /// Records the object if it isn't already seen. Should have a matching call to
   /// [_removeSeen] when the object is no longer being traversed.
-  void _checkCycle(object) {
+  void _checkCycle(Object? object) {
     for (var i = 0; i < _seen.length; i++) {
       if (identical(object, _seen[i])) {
         throw JsonCyclicError(object);
@@ -623,7 +628,7 @@
   ///
   /// Should be called in the opposite order of the matching [_checkCycle]
   /// calls.
-  void _removeSeen(object) {
+  void _removeSeen(Object? object) {
     assert(_seen.isNotEmpty);
     assert(identical(_seen.last, object));
     _seen.removeLast();
@@ -633,7 +638,7 @@
   ///
   /// If [object] isn't directly encodable, the [_toEncodable] function gets one
   /// chance to return a replacement which is encodable.
-  void writeObject(object) {
+  void writeObject(Object? object) {
     // Tries stringifying object directly. If it's not a simple value, List or
     // Map, call toJson() to get a custom representation and try serializing
     // that.
@@ -655,7 +660,7 @@
   ///
   /// Returns true if the value is one of these types, and false if not.
   /// If a value is both a [List] and a [Map], it's serialized as a [List].
-  bool writeJsonValue(object) {
+  bool writeJsonValue(Object? object) {
     if (object is num) {
       if (!object.isFinite) return false;
       writeNumber(object);
@@ -691,7 +696,7 @@
   }
 
   /// Serialize a [List].
-  void writeList(List list) {
+  void writeList(List<Object?> list) {
     writeString('[');
     if (list.isNotEmpty) {
       writeObject(list[0]);
@@ -704,12 +709,12 @@
   }
 
   /// Serialize a [Map].
-  bool writeMap(Map map) {
+  bool writeMap(Map<Object?, Object?> map) {
     if (map.isEmpty) {
       writeString("{}");
       return true;
     }
-    var keyValueList = List(map.length * 2);
+    var keyValueList = List<Object?>(map.length * 2);
     var i = 0;
     var allStringKeys = true;
     map.forEach((key, value) {
@@ -725,7 +730,7 @@
     for (var i = 0; i < keyValueList.length; i += 2) {
       writeString(separator);
       separator = ',"';
-      writeStringContent(keyValueList[i]);
+      writeStringContent(keyValueList[i] as String);
       writeString('":');
       writeObject(keyValueList[i + 1]);
     }
@@ -744,7 +749,7 @@
   /// Add [indentLevel] indentations to the JSON output.
   void writeIndentation(int indentLevel);
 
-  void writeList(List list) {
+  void writeList(List<Object?> list) {
     if (list.isEmpty) {
       writeString('[]');
     } else {
@@ -764,12 +769,12 @@
     }
   }
 
-  bool writeMap(Map map) {
+  bool writeMap(Map<Object?, Object?> map) {
     if (map.isEmpty) {
       writeString("{}");
       return true;
     }
-    var keyValueList = List(map.length * 2);
+    var keyValueList = List<Object?>(map.length * 2);
     var i = 0;
     var allStringKeys = true;
     map.forEach((key, value) {
@@ -788,7 +793,7 @@
       separator = ",\n";
       writeIndentation(_indentLevel);
       writeString('"');
-      writeStringContent(keyValueList[i]);
+      writeStringContent(keyValueList[i] as String);
       writeString('": ');
       writeObject(keyValueList[i + 1]);
     }
@@ -804,7 +809,8 @@
 class _JsonStringStringifier extends _JsonStringifier {
   final StringSink _sink;
 
-  _JsonStringStringifier(this._sink, dynamic Function(dynamic) _toEncodable)
+  _JsonStringStringifier(
+      this._sink, dynamic Function(dynamic object)? _toEncodable)
       : super(_toEncodable);
 
   /// Convert object to a string.
@@ -816,7 +822,8 @@
   /// with newlines and indentation. The `indent` string is added as indentation
   /// for each indentation level. It should only contain valid JSON whitespace
   /// characters (space, tab, carriage return or line feed).
-  static String stringify(object, toEncodable(o), String indent) {
+  static String stringify(
+      Object? object, dynamic toEncodable(dynamic object)?, String? indent) {
     var output = StringBuffer();
     printOn(object, output, toEncodable, indent);
     return output.toString();
@@ -825,8 +832,8 @@
   /// Convert object to a string, and write the result to the [output] sink.
   ///
   /// The result is written piecemally to the sink.
-  static void printOn(
-      object, StringSink output, toEncodable(o), String indent) {
+  static void printOn(Object? object, StringSink output,
+      dynamic toEncodable(dynamic o)?, String? indent) {
     _JsonStringifier stringifier;
     if (indent == null) {
       stringifier = _JsonStringStringifier(output, toEncodable);
@@ -836,7 +843,7 @@
     stringifier.writeObject(object);
   }
 
-  String get _partialResult => _sink is StringBuffer ? _sink.toString() : null;
+  String? get _partialResult => _sink is StringBuffer ? _sink.toString() : null;
 
   void writeNumber(num number) {
     _sink.write(number.toString());
@@ -859,7 +866,8 @@
     with _JsonPrettyPrintMixin {
   final String _indent;
 
-  _JsonStringStringifierPretty(StringSink sink, toEncodable(o), this._indent)
+  _JsonStringStringifierPretty(
+      StringSink sink, dynamic toEncodable(dynamic o)?, this._indent)
       : super(sink, toEncodable);
 
   void writeIndentation(int count) {
@@ -877,7 +885,8 @@
   Uint8List buffer;
   int index = 0;
 
-  _JsonUtf8Stringifier(toEncodable(o), this.bufferSize, this.addChunk)
+  _JsonUtf8Stringifier(
+      dynamic toEncodable(dynamic o)?, this.bufferSize, this.addChunk)
       : buffer = Uint8List(bufferSize),
         super(toEncodable);
 
@@ -890,8 +899,12 @@
   ///
   /// If [indent] is non-`null`, the result will be "pretty-printed" with extra
   /// newlines and indentation, using [indent] as the indentation.
-  static void stringify(Object object, List<int> indent, toEncodable(o),
-      int bufferSize, void addChunk(Uint8List chunk, int start, int end)) {
+  static void stringify(
+      Object? object,
+      List<int>? indent,
+      dynamic toEncodable(dynamic o)?,
+      int bufferSize,
+      void addChunk(Uint8List chunk, int start, int end)) {
     _JsonUtf8Stringifier stringifier;
     if (indent != null) {
       stringifier =
@@ -909,11 +922,11 @@
     if (index > 0) {
       addChunk(buffer, 0, index);
     }
-    buffer = null;
+    buffer = Uint8List(0);
     index = 0;
   }
 
-  String get _partialResult => null;
+  String? get _partialResult => null;
 
   void writeNumber(num number) {
     writeAsciiString(number.toString());
@@ -937,7 +950,7 @@
   void writeStringSlice(String string, int start, int end) {
     // TODO(lrn): Optimize by copying directly into buffer instead of going
     // through writeCharCode/writeByte. Assumption is the most characters
-    // in starings are plain ASCII.
+    // in strings are plain ASCII.
     for (var i = start; i < end; i++) {
       var char = string.codeUnitAt(i);
       if (char <= 0x7f) {
@@ -1005,8 +1018,8 @@
 class _JsonUtf8StringifierPretty extends _JsonUtf8Stringifier
     with _JsonPrettyPrintMixin {
   final List<int> indent;
-  _JsonUtf8StringifierPretty(toEncodable(o), this.indent, int bufferSize,
-      void addChunk(Uint8List buffer, int start, int end))
+  _JsonUtf8StringifierPretty(dynamic toEncodable(dynamic o)?, this.indent,
+      int bufferSize, void addChunk(Uint8List buffer, int start, int end))
       : super(toEncodable, bufferSize, addChunk);
 
   void writeIndentation(int count) {
diff --git a/sdk_nnbd/lib/convert/latin1.dart b/sdk_nnbd/lib/convert/latin1.dart
index 305017f..f396682 100644
--- a/sdk_nnbd/lib/convert/latin1.dart
+++ b/sdk_nnbd/lib/convert/latin1.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.5
-
 part of dart.convert;
 
 /// An instance of the default implementation of the [Latin1Codec].
@@ -49,9 +47,8 @@
   ///
   /// If [allowInvalid] is not provided, it defaults to the value used to create
   /// this [Latin1Codec].
-  String decode(List<int> bytes, {bool allowInvalid}) {
-    allowInvalid ??= _allowInvalid;
-    if (allowInvalid) {
+  String decode(List<int> bytes, {bool? allowInvalid}) {
+    if (allowInvalid ?? _allowInvalid) {
       return const Latin1Decoder(allowInvalid: true).convert(bytes);
     } else {
       return const Latin1Decoder(allowInvalid: false).convert(bytes);
@@ -102,11 +99,11 @@
 }
 
 class _Latin1DecoderSink extends ByteConversionSinkBase {
-  StringConversionSink _sink;
+  StringConversionSink? _sink;
   _Latin1DecoderSink(this._sink);
 
   void close() {
-    _sink.close();
+    _sink!.close();
     _sink = null;
   }
 
@@ -119,12 +116,12 @@
     // _sink.addSlice(source, start, end, isLast).
     // The code below is an moderately stupid workaround until a real
     // solution can be made.
-    _sink.add(String.fromCharCodes(source, start, end));
+    _sink!.add(String.fromCharCodes(source, start, end));
     if (isLast) close();
   }
 
   void addSlice(List<int> source, int start, int end, bool isLast) {
-    end = RangeError.checkValidRange(start, end, source.length);
+    RangeError.checkValidRange(start, end, source.length);
     if (start == end) return;
     if (source is! Uint8List) {
       // List may contain value outside of the 0..255 range. If so, throw.
diff --git a/sdk_nnbd/lib/convert/line_splitter.dart b/sdk_nnbd/lib/convert/line_splitter.dart
index 6980e88..fa0be3f 100644
--- a/sdk_nnbd/lib/convert/line_splitter.dart
+++ b/sdk_nnbd/lib/convert/line_splitter.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.5
-
 part of dart.convert;
 
 // Character constants.
@@ -27,8 +25,12 @@
   /// `lines.substring(start, end)`. The [start] and [end] values must
   /// specify a valid sub-range of [lines]
   /// (`0 <= start <= end <= lines.length`).
-  static Iterable<String> split(String lines, [int start = 0, int end]) sync* {
+  static Iterable<String> split(String lines, [int start = 0, int? end]) sync* {
     end = RangeError.checkValidRange(start, end, lines.length);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     var sliceStart = start;
     var char = 0;
     for (var i = start; i < end; i++) {
@@ -92,7 +94,7 @@
   ///
   /// If the previous slice ended in a line without a line terminator,
   /// then the next slice may continue the line.
-  String _carry;
+  String? _carry;
 
   /// Whether to skip a leading LF character from the next slice.
   ///
@@ -112,9 +114,10 @@
       if (isLast) close();
       return;
     }
-    if (_carry != null) {
+    String? carry = _carry;
+    if (carry != null) {
       assert(!_skipLeadingLF);
-      chunk = _carry + chunk.substring(start, end);
+      chunk = carry + chunk.substring(start, end);
       start = 0;
       end = chunk.length;
       _carry = null;
@@ -130,7 +133,7 @@
 
   void close() {
     if (_carry != null) {
-      _sink.add(_carry);
+      _sink.add(_carry!);
       _carry = null;
     }
     _sink.close();
@@ -168,7 +171,7 @@
       : _eventSink = eventSink,
         super(StringConversionSink.from(eventSink));
 
-  void addError(Object o, [StackTrace stackTrace]) {
+  void addError(Object o, [StackTrace? stackTrace]) {
     _eventSink.addError(o, stackTrace);
   }
 }
diff --git a/sdk_nnbd/lib/convert/string_conversion.dart b/sdk_nnbd/lib/convert/string_conversion.dart
index 94d129c..ea33dc5 100644
--- a/sdk_nnbd/lib/convert/string_conversion.dart
+++ b/sdk_nnbd/lib/convert/string_conversion.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.5
-
 part of dart.convert;
 
 /// This class provides an interface for converters to
@@ -101,8 +99,8 @@
 class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink {
   static const _MIN_STRING_SIZE = 16;
 
-  StringBuffer _buffer;
-  StringConversionSink _chunkedSink;
+  final StringBuffer _buffer;
+  final StringConversionSink _chunkedSink;
 
   _StringConversionSinkAsStringSinkAdapter(this._chunkedSink)
       : _buffer = StringBuffer();
@@ -117,12 +115,12 @@
     if (_buffer.length > _MIN_STRING_SIZE) _flush();
   }
 
-  void write(Object o) {
+  void write(Object? o) {
     if (_buffer.isNotEmpty) _flush();
     _chunkedSink.add(o.toString());
   }
 
-  void writeln([Object o = ""]) {
+  void writeln([Object? o = ""]) {
     _buffer.writeln(o);
     if (_buffer.length > _MIN_STRING_SIZE) _flush();
   }
@@ -177,10 +175,11 @@
 /// This class is a [StringConversionSink] that wraps a [StringSink].
 class _StringSinkConversionSink<TStringSink extends StringSink>
     extends StringConversionSinkBase {
-  TStringSink _stringSink;
+  final TStringSink _stringSink;
   _StringSinkConversionSink(this._stringSink);
 
   void close() {}
+
   void addSlice(String str, int start, int end, bool isLast) {
     if (start != 0 || end != str.length) {
       for (var i = start; i < end; i++) {
@@ -211,6 +210,7 @@
 /// This class can be used to terminate a chunked conversion.
 class _StringCallbackSink extends _StringSinkConversionSink<StringBuffer> {
   final void Function(String) _callback;
+
   _StringCallbackSink(this._callback) : super(StringBuffer());
 
   void close() {
@@ -253,16 +253,18 @@
 }
 
 /// Decodes UTF-8 code units and stores them in a [StringSink].
+///
+/// The `Sink` provided is closed when this sink is closed.
 class _Utf8StringSinkAdapter extends ByteConversionSink {
   final _Utf8Decoder _decoder;
-  final Sink _sink;
+  final Sink<Object?> _sink;
 
   _Utf8StringSinkAdapter(this._sink, StringSink stringSink, bool allowMalformed)
       : _decoder = _Utf8Decoder(stringSink, allowMalformed);
 
   void close() {
     _decoder.close();
-    if (_sink != null) _sink.close();
+    _sink.close();
   }
 
   void add(List<int> chunk) {
diff --git a/sdk_nnbd/lib/convert/utf.dart b/sdk_nnbd/lib/convert/utf.dart
index 692a01c..d9324f6 100644
--- a/sdk_nnbd/lib/convert/utf.dart
+++ b/sdk_nnbd/lib/convert/utf.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.5
-
 part of dart.convert;
 
 /// The Unicode Replacement character `U+FFFD` (�).
@@ -56,9 +54,9 @@
   ///
   /// If [allowMalformed] is not given, it defaults to the `allowMalformed` that
   /// was used to instantiate `this`.
-  String decode(List<int> codeUnits, {bool allowMalformed}) {
-    allowMalformed ??= _allowMalformed;
-    return Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
+  String decode(List<int> codeUnits, {bool? allowMalformed}) {
+    return Utf8Decoder(allowMalformed: allowMalformed ?? _allowMalformed)
+        .convert(codeUnits);
   }
 
   Utf8Encoder get encoder => const Utf8Encoder();
@@ -77,9 +75,13 @@
   ///
   /// If [start] and [end] are provided, only the substring
   /// `string.substring(start, end)` is converted.
-  Uint8List convert(String string, [int start = 0, int end]) {
+  Uint8List convert(String string, [int start = 0, int? end]) {
     var stringLength = string.length;
     end = RangeError.checkValidRange(start, end, stringLength);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
     var length = end - start;
     if (length == 0) return Uint8List(0);
     // Create a new encoder with a length that is guaranteed to be big enough.
@@ -298,7 +300,7 @@
   ///
   /// If the [codeUnits] start with the encoding of a
   /// [unicodeBomCharacterRune], that character is discarded.
-  String convert(List<int> codeUnits, [int start = 0, int end]) {
+  String convert(List<int> codeUnits, [int start = 0, int? end]) {
     // Allow the implementation to intercept and specialize based on the type
     // of codeUnits.
     var result = _convertIntercepted(_allowMalformed, codeUnits, start, end);
@@ -308,6 +310,10 @@
 
     var length = codeUnits.length;
     end = RangeError.checkValidRange(start, end, length);
+    // TODO(38725): Remove workaround when assignment promotion is implemented
+    if (end == null) {
+      throw RangeError("Invalid range");
+    }
 
     // Fast case for ASCII strings avoids StringBuffer/_Utf8Decoder.
     int oneBytes = _scanOneByteCharacters(codeUnits, start, end);
@@ -321,9 +327,9 @@
       }
       buffer = StringBuffer(firstPart);
       isFirstCharacter = false;
+    } else {
+      buffer = StringBuffer();
     }
-
-    buffer ??= StringBuffer();
     var decoder = _Utf8Decoder(buffer, _allowMalformed);
     decoder._isFirstCharacter = isFirstCharacter;
     decoder.convert(codeUnits, start, end);
@@ -350,8 +356,8 @@
 
   external Converter<List<int>, T> fuse<T>(Converter<String, T> next);
 
-  external static String _convertIntercepted(
-      bool allowMalformed, List<int> codeUnits, int start, int end);
+  external static String? _convertIntercepted(
+      bool allowMalformed, List<int> codeUnits, int start, int? end);
 }
 
 // UTF-8 constants.
@@ -409,7 +415,7 @@
   ///
   /// The [source] and [offset] of the current position may be provided,
   /// and are included in the exception if one is thrown.
-  void flush([List<int> source, int offset]) {
+  void flush([List<int>? source, int? offset]) {
     if (hasPartialInput) {
       if (!_allowMalformed) {
         throw FormatException(
diff --git a/sdk_nnbd/lib/core/annotations.dart b/sdk_nnbd/lib/core/annotations.dart
index 4592eb0..f407683 100644
--- a/sdk_nnbd/lib/core/annotations.dart
+++ b/sdk_nnbd/lib/core/annotations.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.5
-
 part of dart.core;
 
 /**
@@ -122,8 +120,8 @@
  */
 @deprecated
 class Provisional {
-  String get message => null;
-  const Provisional({String message});
+  String? get message => null;
+  const Provisional({String? message});
 }
 
 /**
@@ -233,10 +231,10 @@
   final String name;
 
   /** Optional extra data parameterizing the hint. */
-  final Object options;
+  final Object? options;
 
   /** Creates a hint named [name] with optional [options]. */
-  const factory pragma(String name, [Object options]) = pragma._;
+  const factory pragma(String name, [Object? options]) = pragma._;
 
   const pragma._(this.name, [this.options]);
 }
diff --git a/sdk_nnbd/lib/core/bigint.dart b/sdk_nnbd/lib/core/bigint.dart
index e6f3ba0..94a9445 100644
--- a/sdk_nnbd/lib/core/bigint.dart
+++ b/sdk_nnbd/lib/core/bigint.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.5
-
 part of dart.core;
 
 /**
@@ -37,7 +35,7 @@
    * 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});
+  external static BigInt parse(String source, {int? radix});
 
   /**
    * Parses [source] as a, possibly signed, integer literal and returns its
@@ -46,7 +44,7 @@
    * As [parse] except that this method returns `null` if the input is not
    * valid
    */
-  external static BigInt tryParse(String source, {int radix});
+  external static BigInt? tryParse(String source, {int? radix});
 
   /// Allocates a big integer from the provided [value] number.
   external factory BigInt.from(num value);
diff --git a/sdk_nnbd/lib/core/bool.dart b/sdk_nnbd/lib/core/bool.dart
index 692186f..8d420fc 100644
--- a/sdk_nnbd/lib/core/bool.dart
+++ b/sdk_nnbd/lib/core/bool.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.5
-
 part of dart.core;
 
 /**
@@ -56,21 +54,20 @@
   /// The logical conjunction ("and") of this and [other].
   ///
   /// Returns `true` if both this and [other] are `true`, and `false` otherwise.
-  //TODO(lrn): Remove "as bool" in Dart 2.
   @Since("2.1")
-  bool operator &(bool other) => (other as bool) && this;
+  bool operator &(bool other) => other && this;
 
   /// The logical disjunction ("inclusive or") of this and [other].
   ///
   /// Returns `true` if either this or [other] is `true`, and `false` otherwise.
   @Since("2.1")
-  bool operator |(bool other) => (other as bool) || this;
+  bool operator |(bool other) => other || this;
 
   /// The logical exclusive disjunction ("exclusive or") of this and [other].
   ///
   /// Returns whether this and [other] are neither both `true` nor both `false`.
   @Since("2.1")
-  bool operator ^(bool other) => !(other as bool) == this;
+  bool operator ^(bool other) => !other == this;
 
   /**
    * Returns either `"true"` for `true` and `"false"` for `false`.
diff --git a/sdk_nnbd/lib/core/comparable.dart b/sdk_nnbd/lib/core/comparable.dart
index 4416dc0..835aa34 100644
--- a/sdk_nnbd/lib/core/comparable.dart
+++ b/sdk_nnbd/lib/core/comparable.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.5
-
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/core.dart b/sdk_nnbd/lib/core/core.dart
index d9137cd..dc037a3 100644
--- a/sdk_nnbd/lib/core/core.dart
+++ b/sdk_nnbd/lib/core/core.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.5
-
 /**
  *
  * Built-in types, collections,
@@ -169,7 +167,7 @@
         StringConversionSink,
         utf8;
 import "dart:math" show Random; // Used by List.shuffle.
-import "dart:typed_data" show Uint8List, Uint16List, Endian;
+import "dart:typed_data" show Uint8List;
 
 @Since("2.1")
 export "dart:async" show Future, Stream;
diff --git a/sdk_nnbd/lib/core/date_time.dart b/sdk_nnbd/lib/core/date_time.dart
index 1dd01bb..4f5f299 100644
--- a/sdk_nnbd/lib/core/date_time.dart
+++ b/sdk_nnbd/lib/core/date_time.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.5
-
 part of dart.core;
 
 /**
@@ -278,16 +276,16 @@
   // Or not, that may be a breaking change.
   static DateTime parse(String formattedString) {
     var re = _parseFormat;
-    Match match = re.firstMatch(formattedString);
+    Match? match = re.firstMatch(formattedString);
     if (match != null) {
-      int parseIntOrZero(String matched) {
+      int parseIntOrZero(String? matched) {
         if (matched == null) return 0;
         return int.parse(matched);
       }
 
       // Parses fractional second digits of '.(\d{1,6})' into the combined
       // microseconds.
-      int parseMilliAndMicroseconds(String matched) {
+      int parseMilliAndMicroseconds(String? matched) {
         if (matched == null) return 0;
         int length = matched.length;
         assert(length >= 1);
@@ -303,32 +301,32 @@
         return result;
       }
 
-      int years = int.parse(match[1]);
-      int month = int.parse(match[2]);
-      int day = int.parse(match[3]);
+      int years = int.parse(match[1]!);
+      int month = int.parse(match[2]!);
+      int day = int.parse(match[3]!);
       int hour = parseIntOrZero(match[4]);
       int minute = parseIntOrZero(match[5]);
       int second = parseIntOrZero(match[6]);
-      bool addOneMillisecond = false;
       int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
       int millisecond =
           milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
-      int microsecond =
-          milliAndMicroseconds.remainder(Duration.microsecondsPerMillisecond);
+      int microsecond = milliAndMicroseconds
+          .remainder(Duration.microsecondsPerMillisecond) as int;
       bool isUtc = false;
       if (match[8] != null) {
         // timezone part
         isUtc = true;
-        if (match[9] != null) {
+        String? tzSign = match[9];
+        if (tzSign != null) {
           // timezone other than 'Z' and 'z'.
-          int sign = (match[9] == '-') ? -1 : 1;
-          int hourDifference = int.parse(match[10]);
+          int sign = (tzSign == '-') ? -1 : 1;
+          int hourDifference = int.parse(match[10]!);
           int minuteDifference = parseIntOrZero(match[11]);
           minuteDifference += 60 * hourDifference;
           minute -= sign * minuteDifference;
         }
       }
-      int value = _brokenDownDateToValue(years, month, day, hour, minute,
+      int? value = _brokenDownDateToValue(years, month, day, hour, minute,
           second, millisecond, microsecond, isUtc);
       if (value == null) {
         throw FormatException("Time out of range", formattedString);
@@ -345,7 +343,7 @@
    * Works like [parse] except that this function returns `null`
    * where [parse] would throw a [FormatException].
    */
-  static DateTime tryParse(String formattedString) {
+  static DateTime? tryParse(String formattedString) {
     // TODO: Optimize to avoid throwing.
     try {
       return parse(formattedString);
@@ -387,16 +385,13 @@
    *
    * If [isUtc] is false then the date is in the local time zone.
    */
-  DateTime._withValue(this._value, {this.isUtc}) {
+  DateTime._withValue(this._value, {required this.isUtc}) {
     if (millisecondsSinceEpoch.abs() > _maxMillisecondsSinceEpoch ||
         (millisecondsSinceEpoch.abs() == _maxMillisecondsSinceEpoch &&
             microsecond != 0)) {
       throw ArgumentError(
           "DateTime is outside valid range: $millisecondsSinceEpoch");
     }
-    if (isUtc == null) {
-      throw ArgumentError("'isUtc' flag may not be 'null'");
-    }
   }
 
   /**
@@ -414,7 +409,7 @@
    * See [isAtSameMomentAs] for a comparison that compares moments in time
    * independently of their zones.
    */
-  external bool operator ==(dynamic other);
+  external bool operator ==(Object other);
 
   /**
    * Returns true if [this] occurs before [other].
@@ -693,7 +688,7 @@
 
   /// Returns the time as value (millisecond or microsecond since epoch), or
   /// null if the values are out of range.
-  external static int _brokenDownDateToValue(
+  external static int? _brokenDownDateToValue(
       int year,
       int month,
       int day,
diff --git a/sdk_nnbd/lib/core/double.dart b/sdk_nnbd/lib/core/double.dart
index f8d109c..42ff566 100644
--- a/sdk_nnbd/lib/core/double.dart
+++ b/sdk_nnbd/lib/core/double.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.5
-
 part of dart.core;
 
 // TODO: Convert this abstract class into a concrete class double
@@ -208,7 +206,7 @@
    * you should use `double.tryParse(string) ?? (...)`.
    */
   external static double parse(String source,
-      [@deprecated double onError(String source)]);
+      [@deprecated double onError(String source)?]);
 
   /**
    * Parse [source] as an double literal and return its value.
@@ -216,5 +214,5 @@
    * Like [parse] except that this function returns `null` for invalid inputs
    * instead of throwing, and the [source] must still not be `null`.
    */
-  external static double tryParse(String source);
+  external static double? tryParse(String source);
 }
diff --git a/sdk_nnbd/lib/core/duration.dart b/sdk_nnbd/lib/core/duration.dart
index f68609f..2a1f406 100644
--- a/sdk_nnbd/lib/core/duration.dart
+++ b/sdk_nnbd/lib/core/duration.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.5
-
 part of dart.core;
 
 /**
@@ -215,7 +213,7 @@
   /**
    * Returns `true` if this [Duration] has the same value as [other].
    */
-  bool operator ==(dynamic other) =>
+  bool operator ==(Object other) =>
       other is Duration && _duration == other.inMicroseconds;
 
   int get hashCode => _duration.hashCode;
@@ -260,10 +258,12 @@
     if (inMicroseconds < 0) {
       return "-${-this}";
     }
-    String twoDigitMinutes = twoDigits(inMinutes.remainder(minutesPerHour));
-    String twoDigitSeconds = twoDigits(inSeconds.remainder(secondsPerMinute));
+    String twoDigitMinutes =
+        twoDigits(inMinutes.remainder(minutesPerHour) as int);
+    String twoDigitSeconds =
+        twoDigits(inSeconds.remainder(secondsPerMinute) as int);
     String sixDigitUs =
-        sixDigits(inMicroseconds.remainder(microsecondsPerSecond));
+        sixDigits(inMicroseconds.remainder(microsecondsPerSecond) as int);
     return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
   }
 
diff --git a/sdk_nnbd/lib/core/errors.dart b/sdk_nnbd/lib/core/errors.dart
index b2454f8..044e2aa 100644
--- a/sdk_nnbd/lib/core/errors.dart
+++ b/sdk_nnbd/lib/core/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.
 
-// @dart = 2.5
-
 part of dart.core;
 
 /**
@@ -76,7 +74,7 @@
    * The conversion is guaranteed to not throw, so it won't use the object's
    * toString method.
    */
-  static String safeToString(Object object) {
+  static String safeToString(Object? object) {
     if (object is num || object is bool || null == object) {
       return object.toString();
     }
@@ -91,7 +89,7 @@
 
   external static String _objectToString(Object object);
 
-  external StackTrace get stackTrace;
+  external StackTrace? get stackTrace;
 }
 
 /**
@@ -99,7 +97,7 @@
  */
 class AssertionError extends Error {
   /** Message describing the assertion error. */
-  final Object message;
+  final Object? message;
   AssertionError([this.message]);
   String toString() => "Assertion failed";
 }
@@ -115,7 +113,7 @@
 class CastError extends Error {}
 
 /**
- * Error thrown when attempting to throw [:null:].
+ * Error thrown when attempting to throw `null`.
  */
 class NullThrownError extends Error {
   @pragma("vm:entry-point")
@@ -130,11 +128,11 @@
   /** Whether value was provided. */
   final bool _hasValue;
   /** The invalid value. */
-  final invalidValue;
+  final dynamic invalidValue;
   /** Name of the invalid argument, if available. */
-  final String name;
+  final String? name;
   /** Message describing the problem. */
-  final message;
+  final dynamic message;
 
   /**
    * The [message] describes the erroneous argument.
@@ -179,7 +177,7 @@
    * Throws if [argument] is `null`.
    */
   @Since("2.1")
-  static void checkNotNull(Object argument, [String name]) {
+  static void checkNotNull(Object? argument, [String? name]) {
     if (argument == null) throw ArgumentError.notNull(name);
   }
 
@@ -188,12 +186,11 @@
   String get _errorExplanation => "";
 
   String toString() {
-    String nameString = "";
-    if (name != null) {
-      nameString = " ($name)";
-    }
-    var message = (this.message == null) ? "" : ": ${this.message}";
-    String prefix = "$_errorName$nameString$message";
+    String? name = this.name;
+    String nameString = (name == null) ? "" : " ($name)";
+    Object? message = this.message;
+    var messageString = (message == null) ? "" : ": ${message}";
+    String prefix = "$_errorName$nameString$messageString";
     if (!_hasValue) return prefix;
     // If we know the invalid value, we can try to describe the problem.
     String explanation = _errorExplanation;
@@ -207,9 +204,9 @@
  */
 class RangeError extends ArgumentError {
   /** The minimum value that [value] is allowed to assume. */
-  final num start;
+  final num? start;
   /** The maximum value that [value] is allowed to assume. */
-  final num end;
+  final num? end;
 
   // TODO(lrn): This constructor should be called only with string values.
   // It currently isn't in all cases.
@@ -229,11 +226,10 @@
    * invalid value, and the [message] can override the default error
    * description.
    */
-  RangeError.value(num value, [String name, String message])
+  RangeError.value(num value, [String? name, String? message])
       : start = null,
         end = null,
-        super.value(
-            value, name, (message != null) ? message : "Value not in range");
+        super.value(value, name, message ?? "Value not in range");
 
   /**
    * Create a new [RangeError] for a value being outside the valid range.
@@ -250,12 +246,11 @@
    * description.
    */
   @pragma("vm:entry-point")
-  RangeError.range(num invalidValue, int minValue, int maxValue,
-      [String name, String message])
+  RangeError.range(num invalidValue, int? minValue, int? maxValue,
+      [String? name, String? message])
       : start = minValue,
         end = maxValue,
-        super.value(
-            invalidValue, name, (message != null) ? message : "Invalid value");
+        super.value(invalidValue, name, message ?? "Invalid value");
 
   /**
    * Creates a new [RangeError] stating that [index] is not a valid index
@@ -269,7 +264,7 @@
    * If `length` is omitted, it defaults to `indexable.length`.
    */
   factory RangeError.index(int index, dynamic indexable,
-      [String name, String message, int length]) = IndexError;
+      [String? name, String? message, int? length]) = IndexError;
 
   /**
    * Check that a [value] lies in a specific interval.
@@ -278,7 +273,7 @@
    * The interval is from [minValue] to [maxValue], both inclusive.
    */
   static void checkValueInInterval(int value, int minValue, int maxValue,
-      [String name, String message]) {
+      [String? name, String? message]) {
     if (value < minValue || value > maxValue) {
       throw RangeError.range(value, minValue, maxValue, name, message);
     }
@@ -296,8 +291,8 @@
    * otherwise the length is found as `indexable.length`.
    */
   static void checkValidIndex(int index, dynamic indexable,
-      [String name, int length, String message]) {
-    length ??= indexable.length;
+      [String? name, int? length, String? message]) {
+    length ??= (indexable.length as int);
     // Comparing with `0` as receiver produces better dart2js type inference.
     if (0 > index || index >= length) {
       name ??= "index";
@@ -321,8 +316,8 @@
    * 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]) {
+  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.
     // Ditto `start > end` below.
     if (0 > start || start > length) {
@@ -344,7 +339,7 @@
    *
    * Throws if the value is negative.
    */
-  static void checkNotNegative(int value, [String name, String message]) {
+  static void checkNotNegative(int value, [String? name, String? message]) {
     if (value < 0) throw RangeError.range(value, 0, null, name, message);
   }
 
@@ -352,6 +347,8 @@
   String get _errorExplanation {
     assert(_hasValue);
     String explanation = "";
+    num? start = this.start;
+    num? end = this.end;
     if (start == null) {
       if (end != null) {
         explanation = ": Not less than or equal to $end";
@@ -394,11 +391,10 @@
    * The message is used as part of the string representation of the error.
    */
   IndexError(int invalidValue, dynamic indexable,
-      [String name, String message, int length])
+      [String? name, String? message, int? length])
       : this.indexable = indexable,
         this.length = length ?? indexable.length,
-        super.value(invalidValue, name,
-            (message != null) ? message : "Index out of range");
+        super.value(invalidValue, name, message ?? "Index out of range");
 
   // Getters inherited from RangeError.
   int get start => 0;
@@ -458,7 +454,7 @@
    * should not be `null`.
    */
   external NoSuchMethodError.withInvocation(
-      Object receiver, Invocation invocation);
+      Object? receiver, Invocation invocation);
 
   // Deprecated constructor to be removed after dart2js updates to the above.
   /**
@@ -477,16 +473,16 @@
    * empty list.
    *
    * The [namedArguments] is a map from [Symbol]s to the values of named
-   * arguments that the method was called with.
+   * 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,
-      [@deprecated List existingArgumentNames]);
+  external NoSuchMethodError(Object? receiver, Symbol memberName,
+      List? positionalArguments, Map<Symbol, dynamic>? namedArguments);
 
   external String toString();
 }
@@ -499,9 +495,9 @@
  */
 @pragma("vm:entry-point")
 class UnsupportedError extends Error {
-  final String message;
+  final String? message;
   @pragma("vm:entry-point")
-  UnsupportedError(this.message);
+  UnsupportedError(String this.message);
   String toString() => "Unsupported operation: $message";
 }
 
@@ -516,11 +512,14 @@
  * use during development.
  */
 class UnimplementedError extends Error implements UnsupportedError {
-  final String message;
+  final String? message;
   UnimplementedError([this.message]);
-  String toString() => (this.message != null
-      ? "UnimplementedError: $message"
-      : "UnimplementedError");
+  String toString() {
+    var message = this.message;
+    return (message != null)
+        ? "UnimplementedError: $message"
+        : "UnimplementedError";
+  }
 }
 
 /**
@@ -544,7 +543,7 @@
  */
 class ConcurrentModificationError extends Error {
   /** The object that was modified in an incompatible way. */
-  final Object modifiedObject;
+  final Object? modifiedObject;
 
   ConcurrentModificationError([this.modifiedObject]);
 
@@ -562,7 +561,7 @@
   const OutOfMemoryError();
   String toString() => "Out of Memory";
 
-  StackTrace get stackTrace => null;
+  StackTrace? get stackTrace => null;
 }
 
 class StackOverflowError implements Error {
@@ -570,7 +569,7 @@
   const StackOverflowError();
   String toString() => "Stack Overflow";
 
-  StackTrace get stackTrace => null;
+  StackTrace? get stackTrace => null;
 }
 
 /**
@@ -581,10 +580,13 @@
  * another read of the variable, this error is thrown.
  */
 class CyclicInitializationError extends Error {
-  final String variableName;
+  final String? variableName;
   @pragma("vm:entry-point")
   CyclicInitializationError([this.variableName]);
-  String toString() => variableName == null
-      ? "Reading static variable during its initialization"
-      : "Reading static variable '$variableName' during its initialization";
+  String toString() {
+    var variableName = this.variableName;
+    return variableName == null
+        ? "Reading static variable during its initialization"
+        : "Reading static variable '$variableName' during its initialization";
+  }
 }
diff --git a/sdk_nnbd/lib/core/exceptions.dart b/sdk_nnbd/lib/core/exceptions.dart
index 38a5575..7d76a66 100644
--- a/sdk_nnbd/lib/core/exceptions.dart
+++ b/sdk_nnbd/lib/core/exceptions.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.5
-
 part of dart.core;
 
 // Exceptions are thrown either by the VM or from Dart code.
@@ -26,11 +24,12 @@
 
 /** Default implementation of [Exception] which carries a message. */
 class _Exception implements Exception {
-  final message;
+  final dynamic message;
 
   _Exception([this.message]);
 
   String toString() {
+    Object? message = this.message;
     if (message == null) return "Exception";
     return "Exception: $message";
   }
@@ -54,7 +53,7 @@
    *
    * The source is `null` if omitted or unknown.
    */
-  final source;
+  final dynamic source;
 
   /**
    * The offset in [source] where the error was detected.
@@ -69,7 +68,7 @@
    *
    * May be omitted. If present, [source] should also be present if possible.
    */
-  final int offset;
+  final int? offset;
 
   /**
    * Creates a new FormatException with an optional error [message].
@@ -97,13 +96,13 @@
    */
   String toString() {
     String report = "FormatException";
+    Object? message = this.message;
     if (message != null && "" != message) {
       report = "$report: $message";
     }
-    int offset = this.offset;
-    Object objectSource = this.source;
-    if (objectSource is String) {
-      String source = objectSource;
+    int? offset = this.offset;
+    Object? source = this.source;
+    if (source is String) {
       if (offset != null && (offset < 0 || offset > source.length)) {
         offset = null;
       }
diff --git a/sdk_nnbd/lib/core/expando.dart b/sdk_nnbd/lib/core/expando.dart
index 132d38a..ac36b9b 100644
--- a/sdk_nnbd/lib/core/expando.dart
+++ b/sdk_nnbd/lib/core/expando.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.
 
-// @dart = 2.5
-
 part of dart.core;
 
 /**
  * An [Expando] allows adding new properties to objects.
  *
- * Does not work on numbers, strings, booleans or null.
+ * 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.
@@ -17,19 +15,19 @@
  * 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
+ * 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> {
+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:].
+   * no name was passed to the constructor, the name is `null`.
    */
-  final String name;
+  final String? name;
 
   /**
    * Creates a new [Expando]. The optional name is only used for
@@ -37,21 +35,21 @@
    * same name yields two [Expando]s that work on different properties
    * of the objects they are used on.
    */
-  external Expando([String name]);
+  external Expando([String? name]);
 
   /**
    * Expando toString method override.
    */
-  String toString() => "Expando:$name";
+  String toString() => "Expando:${name.toString()}";
 
   /**
    * Gets the value of this [Expando]'s property on the given
    * object. If the object hasn't been expanded, the method returns
-   * [:null:].
+   * `null`.
    *
    * The object must not be a number, a string, a boolean or null.
    */
-  external T operator [](Object object);
+  external T? operator [](Object object);
 
   /**
    * Sets the value of this [Expando]'s property on the given
@@ -60,5 +58,5 @@
    *
    * The object must not be a number, a string, a boolean or null.
    */
-  external void operator []=(Object object, T value);
+  external void operator []=(Object object, T? value);
 }
diff --git a/sdk_nnbd/lib/core/function.dart b/sdk_nnbd/lib/core/function.dart
index 7c34bf5..b21f6759 100644
--- a/sdk_nnbd/lib/core/function.dart
+++ b/sdk_nnbd/lib/core/function.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.5
-
 part of dart.core;
 
 /**
@@ -36,8 +34,8 @@
    * 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 positionalArguments,
-      [Map<Symbol, dynamic> namedArguments]);
+  external static apply(Function function, List<dynamic>? positionalArguments,
+      [Map<Symbol, dynamic>? namedArguments]);
 
   /**
    * Returns a hash code value that is compatible with `operator==`.
diff --git a/sdk_nnbd/lib/core/identical.dart b/sdk_nnbd/lib/core/identical.dart
index 8789642..20d331e 100644
--- a/sdk_nnbd/lib/core/identical.dart
+++ b/sdk_nnbd/lib/core/identical.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.
 
-// @dart = 2.5
-
 part of dart.core;
 
 /**
  * Check whether two references are to the same object.
  */
-external bool identical(Object a, Object b);
+external bool identical(Object? a, Object? b);
 
 /**
  * Returns the identity hash code of `object`.
@@ -21,4 +19,4 @@
  * This hash code is compatible with [identical].
  */
 @pragma("vm:entry-point")
-external int identityHashCode(Object object);
+external int identityHashCode(Object? object);
diff --git a/sdk_nnbd/lib/core/int.dart b/sdk_nnbd/lib/core/int.dart
index a55641c..42af709 100644
--- a/sdk_nnbd/lib/core/int.dart
+++ b/sdk_nnbd/lib/core/int.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.5
-
 part of dart.core;
 
 /**
@@ -44,7 +42,8 @@
   // Disable those static errors.
   //ignore: const_constructor_with_body
   //ignore: const_factory
-  external const factory int.fromEnvironment(String name, {int defaultValue});
+  external const factory int.fromEnvironment(String name,
+      {int defaultValue = 0});
 
   /**
    * Bit-wise and operator.
@@ -344,7 +343,7 @@
    * and the result of that call is returned by [parse].
    */
   external static int parse(String source,
-      {int radix, @deprecated int onError(String source)});
+      {int? radix, @deprecated int onError(String source)?});
 
   /**
    * Parse [source] as a, possibly signed, integer literal and return its value.
@@ -353,5 +352,5 @@
    * similar call to [parse] would throw a [FormatException],
    * and the [source] must still not be `null`.
    */
-  external static int tryParse(String source, {int radix});
+  external static int? tryParse(String source, {int? radix});
 }
diff --git a/sdk_nnbd/lib/core/invocation.dart b/sdk_nnbd/lib/core/invocation.dart
index 6644a84..5959201 100644
--- a/sdk_nnbd/lib/core/invocation.dart
+++ b/sdk_nnbd/lib/core/invocation.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.5
-
 part of dart.core;
 
 /**
@@ -23,8 +21,8 @@
    * If the named arguments are omitted, they default to no named arguments.
    */
   factory Invocation.method(
-          Symbol memberName, Iterable<Object> positionalArguments,
-          [Map<Symbol, Object> namedArguments]) =>
+          Symbol memberName, Iterable<Object?> positionalArguments,
+          [Map<Symbol, Object?>? namedArguments]) =>
       _Invocation.method(memberName, null, positionalArguments, namedArguments);
 
   /**
@@ -37,8 +35,8 @@
    * 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]) =>
+          Iterable<Type> typeArguments, Iterable<Object?> positionalArguments,
+          [Map<Symbol, Object?>? namedArguments]) =>
       _Invocation.method(
           memberName, typeArguments, positionalArguments, namedArguments);
 
@@ -57,7 +55,7 @@
    * Invocation.setter(const Symbol("member="), value)
    * ```
    */
-  factory Invocation.setter(Symbol memberName, Object argument) =
+  factory Invocation.setter(Symbol memberName, Object? argument) =
       _Invocation.setter;
 
   /** The name of the invoked member. */
@@ -114,26 +112,29 @@
   final Symbol memberName;
   final List<Type> typeArguments;
   // Positional arguments is `null` for getters only.
-  final List<Object> _positional;
+  final List<Object?>? _positional;
   // Named arguments is `null` for accessors only.
-  final Map<Symbol, Object> _named;
+  final Map<Symbol, Object?>? _named;
 
-  _Invocation.method(this.memberName, Iterable<Type> types,
-      Iterable<Object> positional, Map<Symbol, Object> named)
-      : typeArguments = _ensureNonNullTypes(_makeUnmodifiable<Type>(types)),
-        _positional = _makeUnmodifiable<Object>(positional) ?? const <Object>[],
+  _Invocation.method(this.memberName, Iterable<Type>? types,
+      Iterable<Object?>? positional, Map<Symbol, Object?>? named)
+      : typeArguments =
+            types == null ? const <Type>[] : List<Type>.unmodifiable(types),
+        _positional = positional == null
+            ? const <Object?>[]
+            : List<Object?>.unmodifiable(positional),
         _named = (named == null || named.isEmpty)
-            ? const <Symbol, Object>{}
-            : Map<Symbol, Object>.unmodifiable(named);
+            ? const <Symbol, Object?>{}
+            : Map<Symbol, Object?>.unmodifiable(named);
 
   _Invocation.getter(this.memberName)
       : typeArguments = const <Type>[],
         _positional = null,
         _named = null;
 
-  _Invocation.setter(this.memberName, Object argument)
+  _Invocation.setter(this.memberName, Object? argument)
       : typeArguments = const <Type>[],
-        _positional = List<Object>.unmodifiable([argument]),
+        _positional = List<Object?>.unmodifiable([argument]),
         _named = null;
 
   List<dynamic> get positionalArguments => _positional ?? const <Object>[];
@@ -144,21 +145,4 @@
   bool get isGetter => _positional == null;
   bool get isSetter => _positional != null && _named == null;
   bool get isAccessor => _named == null;
-
-  /// Checks that the elements of [types] are not null.
-  static List<Type> _ensureNonNullTypes(List<Type> types) {
-    if (types == null) return const <Type>[];
-    for (int i = 0; i < types.length; i++) {
-      if (types[i] == null) {
-        throw ArgumentError(
-            "Type arguments must be non-null, was null at index $i.");
-      }
-    }
-    return types;
-  }
-
-  static List<T> _makeUnmodifiable<T>(Iterable<T> elements) {
-    if (elements == null) return null;
-    return List<T>.unmodifiable(elements);
-  }
 }
diff --git a/sdk_nnbd/lib/core/iterable.dart b/sdk_nnbd/lib/core/iterable.dart
index 32225b0..b00549c 100644
--- a/sdk_nnbd/lib/core/iterable.dart
+++ b/sdk_nnbd/lib/core/iterable.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.5
-
 part of dart.core;
 
 /**
@@ -101,7 +99,7 @@
    * As an `Iterable`, `new Iterable.generate(n, generator))` is equivalent to
    * `const [0, ..., n - 1].map(generator)`.
    */
-  factory Iterable.generate(int count, [E generator(int index)]) {
+  factory Iterable.generate(int count, [E generator(int index)?]) {
     if (count <= 0) return EmptyIterable<E>();
     return _GeneratorIterable<E>(count, generator);
   }
@@ -166,6 +164,7 @@
    * 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 concatentation of this iterable and [other].
    *
@@ -174,8 +173,9 @@
    * original iterables.
    */
   Iterable<E> followedBy(Iterable<E> other) {
-    if (this is EfficientLengthIterable<E>) {
-      return FollowedByIterable<E>.firstEfficient(this, other);
+    var self = this; // TODO(lrn): Remove when we can promote `this`.
+    if (self is EfficientLengthIterable<E>) {
+      return FollowedByIterable<E>.firstEfficient(self, other);
     }
     return FollowedByIterable<E>(this, other);
   }
@@ -264,7 +264,7 @@
    * Likewise the `Iterable` returned by a [Map.keys] call
    * should use the same equality that the `Map` uses for keys.
    */
-  bool contains(Object element) {
+  bool contains(Object? element) {
     for (E e in this) {
       if (e == element) return true;
     }
@@ -365,13 +365,13 @@
     StringBuffer buffer = StringBuffer();
     if (separator == null || separator == "") {
       do {
-        buffer.write("${iterator.current}");
+        buffer.write(iterator.current.toString());
       } while (iterator.moveNext());
     } else {
-      buffer.write("${iterator.current}");
+      buffer.write(iterator.current.toString());
       while (iterator.moveNext()) {
         buffer.write(separator);
-        buffer.write("${iterator.current}");
+        buffer.write(iterator.current.toString());
       }
     }
     return buffer.toString();
@@ -397,7 +397,7 @@
    * The list is fixed-length if [growable] is false.
    */
   List<E> toList({bool growable = true}) {
-    return List<E>.from(this, growable: growable);
+    return List<E>.of(this, growable: growable);
   }
 
   /**
@@ -409,7 +409,7 @@
    * The order of the elements in the set is not guaranteed to be the same
    * as for the iterable.
    */
-  Set<E> toSet() => Set<E>.from(this);
+  Set<E> toSet() => Set<E>.of(this);
 
   /**
    * Returns the number of elements in [this].
@@ -566,7 +566,7 @@
    * function is returned.
    * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
-  E firstWhere(bool test(E element), {E orElse()}) {
+  E firstWhere(bool test(E element), {E orElse()?}) {
     for (E element in this) {
       if (test(element)) return element;
     }
@@ -588,8 +588,8 @@
    * function is returned.
    * If [orElse] is omitted, it defaults to throwing a [StateError].
    */
-  E lastWhere(bool test(E element), {E orElse()}) {
-    E result;
+  E lastWhere(bool test(E element), {E orElse()?}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -611,8 +611,8 @@
    * 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()}) {
-    E result;
+  E singleWhere(bool test(E element), {E orElse()?}) {
+    late E result;
     bool foundMatching = false;
     for (E element in this) {
       if (test(element)) {
@@ -640,7 +640,6 @@
    * Some iterables may have more a efficient way to find the element.
    */
   E elementAt(int index) {
-    ArgumentError.checkNotNull(index, "index");
     RangeError.checkNotNegative(index, "index");
     int elementIndex = 0;
     for (E element in this) {
@@ -669,22 +668,20 @@
   String toString() => IterableBase.iterableToShortString(this, '(', ')');
 }
 
-typedef _Generator<E> = E Function(int index);
-
 class _GeneratorIterable<E> extends ListIterable<E> {
   /// The length of the generated iterable.
   final int length;
 
   /// The function mapping indices to values.
-  final _Generator<E> _generator;
+  final E Function(int) _generator;
 
   /// Creates the generated iterable.
   ///
   /// If [generator] is `null`, it is checked that `int` is assignable to [E].
-  _GeneratorIterable(this.length, E generator(int index))
+  _GeneratorIterable(this.length, E generator(int index)?)
       : // The `as` below is used as check to make sure that `int` is assignable
         // to [E].
-        _generator = (generator != null) ? generator : _id as _Generator<E>;
+        _generator = generator ?? (_id as E Function(int));
 
   E elementAt(int index) {
     RangeError.checkValidIndex(index, this);
@@ -696,14 +693,15 @@
 }
 
 /**
- * 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 sets [current] to null if there is no previous element.
+   * and updates [current] to an implementation defined state if there is no
+   * previous element
    */
   bool movePrevious();
 }
diff --git a/sdk_nnbd/lib/core/iterator.dart b/sdk_nnbd/lib/core/iterator.dart
index d69e937..799388d 100644
--- a/sdk_nnbd/lib/core/iterator.dart
+++ b/sdk_nnbd/lib/core/iterator.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.5
-
 part of dart.core;
 
 /**
@@ -18,8 +16,11 @@
  * 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, [current]
- * returns `null`, and all further calls to [moveNext] will also return false.
+ * 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:
  *
@@ -36,24 +37,32 @@
   /**
    * Moves to the next element.
    *
-   * Returns true if [current] contains the next element.
+   * Returns true when [current] can be used to access the next element.
    * Returns false if no elements are left.
    *
    * It is safe to invoke [moveNext] even when the iterator is already
    * positioned after the last element.
    * In this case [moveNext] returns false again and has no effect.
    *
-   * A call to `moveNext` may throw if iteration has been broken by
-   * changing the underlying collection.
+   * A call to [moveNext] may throw if iteration has been broken by
+   * changing the underlying collection, or for other reasons specific to
+   * a particular iterator.
+   * The iterator should not be used after [moveNext] throws.
+   * If it is used, the value of [current] and the behavior of
+   * calling [moveNext] again are unspecified.
    */
   bool moveNext();
 
   /**
    * Returns the current element.
    *
-   * Returns `null` if the iterator has not yet been moved to the first
-   * element, or if the iterator has been moved past the last element of the
-   * [Iterable].
+   * 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.
diff --git a/sdk_nnbd/lib/core/list.dart b/sdk_nnbd/lib/core/list.dart
index b096bfa..2ef1601 100644
--- a/sdk_nnbd/lib/core/list.dart
+++ b/sdk_nnbd/lib/core/list.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.5
-
 part of dart.core;
 
 /**
@@ -57,6 +55,10 @@
   /**
    * Creates a list of the given length.
    *
+   * This constructor will throw an exception if [E] is not a nullable type.
+   * In this case, another constructor such as [List.filled] must be used
+   * instead.
+   *
    * The created list is fixed-length if [length] is provided.
    *
    *     List fixedLengthList = new List(3);
@@ -65,18 +67,25 @@
    *
    * The list has length 0 and is growable if [length] is omitted.
    *
-   *     List growableList = new List();
+   *     List growableList = [];
    *     growableList.length; // 0;
    *     growableList.length = 3;
    *
-   * To create a growable list with a given length, just assign the length
-   * right after creation:
+   * To create a growable list with a given length, for a nullable element type,
+   * just assign the length right after creation:
    *
-   *     List growableList = new List()..length = 500;
+   *     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.
    */
-  external factory List([int length]);
+  external factory List([int? length]);
 
   /**
    * Creates a list of the given length with [fill] at each position.
@@ -113,6 +122,15 @@
   external factory List.filled(int length, E fill, {bool growable = false});
 
   /**
+   * Creates a new empty list.
+   *
+   * If [growable] is `true`, which is the default,
+   * the list is growable and equivalent to `<E>[]`.
+   * If [growable] is `false`, the list is a fixed-length list of length zero.
+   */
+  external factory List.empty({bool growable = true});
+
+  /**
    * Creates a list containing all [elements].
    *
    * The [Iterator] of [elements] provides the order of the elements.
@@ -155,13 +173,12 @@
    */
   factory List.generate(int length, E generator(int index),
       {bool growable = true}) {
-    List<E> result;
-    if (growable) {
-      result = <E>[]..length = length;
-    } else {
-      result = List<E>(length);
+    if (length <= 0) {
+      if (growable) return <E>[];
+      return List<E>.empty();
     }
-    for (int i = 0; i < length; i++) {
+    List<E> result = List<E>.filled(length, generator(0), growable: growable);
+    for (int i = 1; i < length; i++) {
       result[i] = generator(i);
     }
     return result;
@@ -211,9 +228,13 @@
    * 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]) {
+      [int? start, int? end]) {
     start ??= 0;
     end = RangeError.checkValidRange(start, end, source.length);
+    if (end == null) {
+      // TODO(dart-lang/language#440): Remove when promotion works.
+      throw "unreachable";
+    }
     int length = end - start;
     if (target.length < at + length) {
       throw ArgumentError.value(target, "target",
@@ -271,6 +292,7 @@
    * 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.
@@ -302,7 +324,7 @@
   void set last(E value);
 
   /**
-   * Returns the number of objects in this list.
+   * The number of objects in this list.
    *
    * The valid indices for a list are `0` through `length - 1`.
    */
@@ -312,9 +334,11 @@
    * Changes the length of this list.
    *
    * If [newLength] is greater than
-   * the current length, entries are initialized to [:null:].
+   * 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.
+   * Throws an [UnsupportedError] if the list is fixed-length or
+   * if attempting tp enlarge the list when `null` is not a valid element.
    */
   set length(int newLength);
 
@@ -365,12 +389,12 @@
    *     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)]);
+  void sort([int compare(E a, E b)?]);
 
   /**
    * Shuffles the elements of this list randomly.
    */
-  void shuffle([Random random]);
+  void shuffle([Random? random]);
 
   /**
    * Returns the first index of [element] in this list.
@@ -415,6 +439,7 @@
    * 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'];
@@ -427,7 +452,7 @@
    * notes.lastIndexWhere((note) => note.startsWith('k'));    // -1
    * ```
    */
-  int lastIndexWhere(bool test(E element), [int start]);
+  int lastIndexWhere(bool test(E element), [int? start]);
 
   /**
    * Returns the last index of [element] in this list.
@@ -441,7 +466,7 @@
    *     notes.lastIndexOf('re', 2); // 1
    *
    * If [start] is not provided, this method searches from the end of the
-   * list./Returns
+   * list.
    *
    *     notes.lastIndexOf('re');  // 3
    *
@@ -449,7 +474,7 @@
    *
    *     notes.lastIndexOf('fa');  // -1
    */
-  int lastIndexOf(E element, [int start]);
+  int lastIndexOf(E element, [int? start]);
 
   /**
    * Removes all objects from this list;
@@ -605,7 +630,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  List<E> sublist(int start, [int end]);
+  List<E> sublist(int start, [int? end]);
 
   /**
    * Returns an [Iterable] that iterates over the objects in the range
@@ -686,8 +711,10 @@
    *     print(list); //  [1, 1, null]
    * ```
    *
+   * If the element type is not nullable, omitting [fillValue] or passing `null`
+   * as [fillValue] will make the `fillRange` fail.
    */
-  void fillRange(int start, int end, [E fillValue]);
+  void fillRange(int start, int end, [E? fillValue]);
 
   /**
    * Removes the objects in the range [start] inclusive to [end] exclusive
@@ -729,5 +756,5 @@
   * Even if [other] is also a list, the equality comparison
   * does not compare the elements of the two lists.
   */
- bool operator ==(Object other);
+  bool operator ==(Object other);
 }
diff --git a/sdk_nnbd/lib/core/map.dart b/sdk_nnbd/lib/core/map.dart
index fa1573a..a92d08d 100644
--- a/sdk_nnbd/lib/core/map.dart
+++ b/sdk_nnbd/lib/core/map.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.5
-
 part of dart.core;
 
 /**
@@ -79,7 +77,7 @@
    * 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 other);
+  external factory Map.unmodifiable(Map<dynamic, dynamic> other);
 
   /**
    * Creates an identity map with the default implementation, [LinkedHashMap].
@@ -131,7 +129,7 @@
    * last occurrence of a key will simply overwrite any previous value.
    */
   factory Map.fromIterable(Iterable iterable,
-      {K key(element), V value(element)}) = LinkedHashMap<K, V>.fromIterable;
+      {K key(element)?, V value(element)?}) = LinkedHashMap<K, V>.fromIterable;
 
   /**
    * Creates a Map instance associating the given [keys] to [values].
@@ -201,13 +199,14 @@
    * `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.
    */
-  bool containsValue(Object value);
+  bool containsValue(Object? value);
 
   /**
    * Returns true if this map contains the given [key].
@@ -215,7 +214,7 @@
    * 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);
+  bool containsKey(Object? key);
 
   /**
    * Returns the value for the given [key] or null if [key] is not in the map.
@@ -226,7 +225,7 @@
    * Methods like [containsKey] or [putIfAbsent] can be used if the distinction
    * is important.
    */
-  V operator [](Object key);
+  V? operator [](Object? key);
 
   /**
    * Associates the [key] with the given [value].
@@ -271,7 +270,7 @@
    *
    * It's an error if the key is not present and [ifAbsent] is not provided.
    */
-  V update(K key, V update(V value), {V ifAbsent()});
+  V update(K key, V update(V value), {V ifAbsent()?});
 
   /**
    * Updates all values.
@@ -325,7 +324,7 @@
    * Note that values can be `null` and a returned `null` value doesn't
    * always mean that the key was absent.
    */
-  V remove(Object key);
+  V? remove(Object? key);
 
   /**
    * Removes all pairs from the map.
@@ -402,5 +401,5 @@
 
   const MapEntry._(this.key, this.value);
 
-  String toString() => "MapEntry($key: $value)";
+  String toString() => "MapEntry(${key.toString()}: ${value.toString()})";
 }
diff --git a/sdk_nnbd/lib/core/null.dart b/sdk_nnbd/lib/core/null.dart
index 0e8dec5..f8588a1 100644
--- a/sdk_nnbd/lib/core/null.dart
+++ b/sdk_nnbd/lib/core/null.dart
@@ -2,16 +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.5
-
 part of dart.core;
 
 /**
- * The reserved word [:null:] denotes an object that is the sole instance of 
+ * 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.
+ * [Null].
  */
 @pragma("vm:entry-point")
 class Null {
diff --git a/sdk_nnbd/lib/core/num.dart b/sdk_nnbd/lib/core/num.dart
index e7afd77..7b45da6 100644
--- a/sdk_nnbd/lib/core/num.dart
+++ b/sdk_nnbd/lib/core/num.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.5
-
 part of dart.core;
 
 /**
@@ -44,7 +42,7 @@
    * Use [compareTo] for a comparison that distinguishes zero and minus zero,
    * and that considers NaN values as equal.
    */
-  bool operator ==(Object other);
+  bool operator ==(Object? other);
 
   /**
    * Returns a hash code for a numerical value.
@@ -387,7 +385,7 @@
    *     123456.toStringAsExponential(3); // 1.235e+5
    *     123.toStringAsExponential(0);    // 1e+2
    */
-  String toStringAsExponential([int fractionDigits]);
+  String toStringAsExponential([int? fractionDigits]);
 
   /**
    * Converts `this` to a double and returns a string representation with
@@ -470,8 +468,8 @@
    * 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);
+  static num parse(String input, [@deprecated num onError(String input)?]) {
+    num? result = tryParse(input);
     if (result != null) return result;
     if (onError == null) throw FormatException(input);
     return onError(input);
@@ -483,13 +481,9 @@
    * Like [parse] except that this function returns `null` for invalid inputs
    * instead of throwing.
    */
-  static num tryParse(String input) {
+  static num? tryParse(String input) {
     String source = input.trim();
     // TODO(lrn): Optimize to detect format and result type in one check.
     return int.tryParse(source) ?? double.tryParse(source);
   }
-
-  /** Helper functions for [parse]. */
-  static int _returnIntNull(String _) => null;
-  static double _returnDoubleNull(String _) => null;
 }
diff --git a/sdk_nnbd/lib/core/object.dart b/sdk_nnbd/lib/core/object.dart
index 6490430..31602df 100644
--- a/sdk_nnbd/lib/core/object.dart
+++ b/sdk_nnbd/lib/core/object.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.5
-
 part of dart.core;
 
 /**
@@ -59,7 +57,7 @@
    * If a subclass overrides the equality operator it should override
    * the [hashCode] method as well to maintain consistency.
    */
-  external bool operator ==(other);
+  external bool operator ==(Object other);
 
   /**
    * The hash code for this object.
diff --git a/sdk_nnbd/lib/core/pattern.dart b/sdk_nnbd/lib/core/pattern.dart
index 42607e1..7a3d933 100644
--- a/sdk_nnbd/lib/core/pattern.dart
+++ b/sdk_nnbd/lib/core/pattern.dart
@@ -2,18 +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.5
-
 part of dart.core;
 
 /**
  * An interface for basic searches within strings.
  */
 abstract class Pattern {
-  // NOTE: When using "start" index from the language library, call
-  // without an argument if start is zero. This allows backwards compatibility
-  // with implementations of the older interface that didn't have the start
-  // index argument.
   /**
    * Match this pattern against the string repeatedly.
    *
@@ -42,7 +36,7 @@
    * pattern can match a part of the string starting from position [start].
    * Returns `null` if the pattern doesn't match.
    */
-  Match matchAsPrefix(String string, [int start = 0]);
+  Match? matchAsPrefix(String string, [int start = 0]);
 }
 
 /**
@@ -93,7 +87,7 @@
    * The result may be `null` if the pattern didn't assign a value to it
    * as part of this match.
    */
-  String group(int group);
+  String? group(int group);
 
   /**
    * Returns the string matched by the given [group].
@@ -102,7 +96,7 @@
    *
    * Short alias for [Match.group].
    */
-  String operator [](int group);
+  String? operator [](int group);
 
   /**
    * Returns a list of the groups with the given indices.
@@ -110,7 +104,7 @@
    * The list contains the strings returned by [group] for each index in
    * [groupIndices].
    */
-  List<String> groups(List<int> groupIndices);
+  List<String?> groups(List<int> groupIndices);
 
   /**
    * Returns the number of captured groups in the match.
diff --git a/sdk_nnbd/lib/core/print.dart b/sdk_nnbd/lib/core/print.dart
index 6b33db5..c45336c 100644
--- a/sdk_nnbd/lib/core/print.dart
+++ b/sdk_nnbd/lib/core/print.dart
@@ -2,13 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.5
-
 part of dart.core;
 
 /// Prints a string representation of the object to the console.
-void print(Object object) {
-  String line = "$object";
+void print(Object? object) {
+  String line = object.toString();
   if (printToZone == null) {
     printToConsole(line);
   } else {
diff --git a/sdk_nnbd/lib/core/regexp.dart b/sdk_nnbd/lib/core/regexp.dart
index 4d1228c..b75882d 100644
--- a/sdk_nnbd/lib/core/regexp.dart
+++ b/sdk_nnbd/lib/core/regexp.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.5
-
 part of dart.core;
 
 /**
@@ -90,7 +88,7 @@
    * Searches for the first match of the regular expression
    * in the string [input]. Returns `null` if there is no match.
    */
-  RegExpMatch firstMatch(String input);
+  RegExpMatch? firstMatch(String input);
 
   /**
    * Returns an iterable of the matches of the regular expression on [input].
@@ -107,7 +105,7 @@
   /**
    * Returns the first substring match of this regular expression in [input].
    */
-  String stringMatch(String input);
+  String? stringMatch(String input);
 
   /**
    * The source regular expression string used to create this `RegExp`.
@@ -182,7 +180,7 @@
    * expression creating this match (that is, the name must be in
    * [groupNames]).
    */
-  String namedGroup(String name);
+  String? namedGroup(String name);
 
   /**
    * The names of the captured groups in the match.
diff --git a/sdk_nnbd/lib/core/set.dart b/sdk_nnbd/lib/core/set.dart
index d0be04c..ae1e381 100644
--- a/sdk_nnbd/lib/core/set.dart
+++ b/sdk_nnbd/lib/core/set.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.5
-
 part of dart.core;
 
 /**
@@ -112,7 +110,7 @@
    * 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}) =>
+  static Set<T> castFrom<S, T>(Set<S> source, {Set<R> Function<R>()? newSet}) =>
       CastSet<S, T>(source, newSet);
 
   /**
@@ -128,6 +126,7 @@
    * this set as well.
    */
   Set<R> cast<R>();
+
   /**
    * Provides an iterator that iterates over the elements of this set.
    *
@@ -139,7 +138,7 @@
   /**
    * Returns true if [value] is in the set.
    */
-  bool contains(Object value);
+  bool contains(Object? value);
 
   /**
    * Adds [value] to the set.
@@ -177,7 +176,7 @@
    * in the set. Returns false otherwise. The method has no effect
    * if [value] value was not in the set.
    */
-  bool remove(Object value);
+  bool remove(Object? value);
 
   /**
    * If an object equal to [object] is in the set, return it.
@@ -193,12 +192,12 @@
    * then there may not be a specific object instance representing the
    * set element.
    */
-  E lookup(Object object);
+  E? lookup(Object? object);
 
   /**
    * Removes each element of [elements] from this set.
    */
-  void removeAll(Iterable<Object> elements);
+  void removeAll(Iterable<Object?> elements);
 
   /**
    * Removes all elements of this set that are not elements in [elements].
@@ -208,7 +207,7 @@
    * 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);
+  void retainAll(Iterable<Object?> elements);
 
   /**
    * Removes all elements of this set that satisfy [test].
@@ -223,7 +222,7 @@
   /**
    * Returns whether this Set contains all the elements of [other].
    */
-  bool containsAll(Iterable<Object> other);
+  bool containsAll(Iterable<Object?> other);
 
   /**
    * Returns a new set which is the intersection between this set and [other].
@@ -231,7 +230,7 @@
    * 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);
+  Set<E> intersection(Set<Object?> other);
 
   /**
    * Returns a new set which contains all the elements of this set and [other].
@@ -247,7 +246,7 @@
    * 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);
+  Set<E> difference(Set<Object?> other);
 
   /**
    * Removes all elements in the set.
diff --git a/sdk_nnbd/lib/core/sink.dart b/sdk_nnbd/lib/core/sink.dart
index ed921b1..c79214b 100644
--- a/sdk_nnbd/lib/core/sink.dart
+++ b/sdk_nnbd/lib/core/sink.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.5
-
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/stacktrace.dart b/sdk_nnbd/lib/core/stacktrace.dart
index 434be96..2eb1493 100644
--- a/sdk_nnbd/lib/core/stacktrace.dart
+++ b/sdk_nnbd/lib/core/stacktrace.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.5
-
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/stopwatch.dart b/sdk_nnbd/lib/core/stopwatch.dart
index 0db02c9..311db3d 100644
--- a/sdk_nnbd/lib/core/stopwatch.dart
+++ b/sdk_nnbd/lib/core/stopwatch.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.5
-
 part of dart.core;
 
 /**
@@ -13,15 +11,15 @@
   /**
    * Cached frequency of the system in Hz (ticks per second).
    *
-   * Must be initialized in [_initTicker];
+   * Value must be returned by [_initTicker], which is called only once.
    */
-  static int _frequency;
+  static final int _frequency = _initTicker();
 
   // The _start and _stop fields capture the time when [start] and [stop]
   // are called respectively.
   // If _stop is null, the stopwatch is running.
   int _start = 0;
-  int _stop = 0;
+  int? _stop = 0;
 
   /**
    * Creates a [Stopwatch] in stopped state with a zero elapsed count.
@@ -33,7 +31,7 @@
    * ```
    */
   Stopwatch() {
-    if (_frequency == null) _initTicker();
+    _frequency; // Ensures initialization before using any method.
   }
 
   /**
@@ -51,10 +49,11 @@
    * If the [Stopwatch] is currently running, then calling start does nothing.
    */
   void start() {
-    if (_stop != null) {
+    int? stop = _stop;
+    if (stop != null) {
       // (Re)start this stopwatch.
       // Don't count the time while the stopwatch has been stopped.
-      _start += _now() - _stop;
+      _start += _now() - stop;
       _stop = null;
     }
   }
@@ -117,9 +116,9 @@
   bool get isRunning => _stop == null;
 
   /**
-   * Initializes the time-measuring system. *Must* initialize the [_frequency]
-   * variable.
+   * Initializes the time-measuring system. *Must* return the [_frequency]
+   * variable. May do other necessary initialization.
    */
-  external static void _initTicker();
+  external static int _initTicker();
   external static int _now();
 }
diff --git a/sdk_nnbd/lib/core/string.dart b/sdk_nnbd/lib/core/string.dart
index 7559f9c..1a838aa 100644
--- a/sdk_nnbd/lib/core/string.dart
+++ b/sdk_nnbd/lib/core/string.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.5
-
 part of dart.core;
 
 /**
@@ -121,7 +119,7 @@
    * `0 <= start <= end <= charCodes.length`.
    */
   external factory String.fromCharCodes(Iterable<int> charCodes,
-      [int start = 0, int end]);
+      [int start = 0, int? end]);
 
   /**
    * Allocates a new String for the specified [charCode].
@@ -131,7 +129,7 @@
    * the code units form a surrogate pair. See documentation for
    * [fromCharCodes].
    *
-   * Creating a String with half of a surrogate pair is allowed.
+   * Creating a [String] with one half of a surrogate pair is allowed.
    */
   external factory String.fromCharCode(int charCode);
 
@@ -160,7 +158,7 @@
   //ignore: const_constructor_with_body
   //ignore: const_factory
   external const factory String.fromEnvironment(String name,
-      {String defaultValue});
+      {String defaultValue = ""});
 
   /**
    * Gets the character (as a single-code-unit [String]) at the given [index].
@@ -287,7 +285,7 @@
    *
    * [start] must be non-negative and not greater than [length].
    */
-  int indexOf(Pattern pattern, [int start]);
+  int indexOf(Pattern pattern, [int start = 0]);
 
   /**
    * Returns the position of the last match [pattern] in this string, searching
@@ -303,7 +301,7 @@
    *
    * The [start] must be non-negative and not greater than [length].
    */
-  int lastIndexOf(Pattern pattern, [int start]);
+  int lastIndexOf(Pattern pattern, [int? start]);
 
   /**
    * Returns true if this string is empty.
@@ -330,7 +328,7 @@
    *     string.substring(1);    // 'artlang'
    *     string.substring(1, 4); // 'art'
    */
-  String substring(int startIndex, [int endIndex]);
+  String substring(int startIndex, [int? endIndex]);
 
   /**
    * Returns the string without any leading and trailing whitespace.
@@ -522,7 +520,7 @@
    * That is `0 <= start <= end <= this.length`.
    * If [end] is `null`, it defaults to [length].
    */
-  String replaceRange(int start, int end, String replacement);
+  String replaceRange(int start, int? end, String replacement);
 
   /**
    * Splits the string at matches of [pattern] and returns a list of substrings.
@@ -591,7 +589,7 @@
    *         onNonMatch: (n) => '*'); // *shoots*
    */
   String splitMapJoin(Pattern pattern,
-      {String onMatch(Match match), String onNonMatch(String nonMatch)});
+      {String onMatch(Match match)?, String onNonMatch(String nonMatch)?});
 
   /**
    * Returns an unmodifiable list of the UTF-16 code units of this string.
@@ -670,9 +668,9 @@
   return 0x10000 + ((start & 0x3FF) << 10) + (end & 0x3FF);
 }
 
-/** [Iterator] for reading runes (integer Unicode code points) out of a Dart
-  * string.
-  */
+/**
+ * [Iterator] for reading runes (integer Unicode code points) of a Dart string.
+ */
 class RuneIterator implements BidirectionalIterator<int> {
   /** String being iterated. */
   final String string;
@@ -683,10 +681,10 @@
   /**
    * Current code point.
    *
-   * If the iterator has hit either end, the [_currentCodePoint] is null
+   * If the iterator has hit either end, the [_currentCodePoint] is -1
    * and [: _position == _nextPosition :].
    */
-  int _currentCodePoint;
+  int _currentCodePoint = -1;
 
   /** Create an iterator positioned at the beginning of the string. */
   RuneIterator(String string)
@@ -758,11 +756,14 @@
     RangeError.checkValueInInterval(rawIndex, 0, string.length, "rawIndex");
     _checkSplitSurrogate(rawIndex);
     _position = _nextPosition = rawIndex;
-    _currentCodePoint = null;
+    _currentCodePoint = -1;
   }
 
-  /** The rune (integer Unicode code point) starting at the current position in
-   *  the string.
+  /**
+   * 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;
 
@@ -779,10 +780,10 @@
    * For runes outside the basic multilingual plane, this will be
    * a String of length 2, containing two code units.
    *
-   * Returns null if [current] is null.
+   * Returns an empty string if there is no [current] value.
    */
   String get currentAsString {
-    if (_position == _nextPosition) return null;
+    if (_position == _nextPosition) return "";
     if (_position + 1 == _nextPosition) return string[_position];
     return string.substring(_position, _nextPosition);
   }
@@ -790,7 +791,7 @@
   bool moveNext() {
     _position = _nextPosition;
     if (_position == string.length) {
-      _currentCodePoint = null;
+      _currentCodePoint = -1;
       return false;
     }
     int codeUnit = string.codeUnitAt(_position);
@@ -811,7 +812,7 @@
   bool movePrevious() {
     _nextPosition = _position;
     if (_position == 0) {
-      _currentCodePoint = null;
+      _currentCodePoint = -1;
       return false;
     }
     int position = _position - 1;
diff --git a/sdk_nnbd/lib/core/string_buffer.dart b/sdk_nnbd/lib/core/string_buffer.dart
index 417676a..d664101 100644
--- a/sdk_nnbd/lib/core/string_buffer.dart
+++ b/sdk_nnbd/lib/core/string_buffer.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.5
-
 part of dart.core;
 
 /**
@@ -33,14 +31,14 @@
   bool get isNotEmpty => !isEmpty;
 
   /// Adds the contents of [obj], converted to a string, to the buffer.
-  external void write(Object obj);
+  external void write(Object? obj);
 
   /// Adds the string representation of [charCode] to the buffer.
   external void writeCharCode(int charCode);
 
-  external void writeAll(Iterable objects, [String separator = ""]);
+  external void writeAll(Iterable<dynamic> objects, [String separator = ""]);
 
-  external void writeln([Object obj = ""]);
+  external void writeln([Object? obj = ""]);
 
   /**
    * Clears the string buffer.
diff --git a/sdk_nnbd/lib/core/string_sink.dart b/sdk_nnbd/lib/core/string_sink.dart
index 8c19b9b..c507424 100644
--- a/sdk_nnbd/lib/core/string_sink.dart
+++ b/sdk_nnbd/lib/core/string_sink.dart
@@ -2,27 +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.
 
-// @dart = 2.5
-
 part of dart.core;
 
 abstract class StringSink {
   /**
-   * Converts [obj] to a String by invoking [Object.toString] and 
+   * Converts [obj] to a String by invoking [Object.toString] and
    * adds the result to `this`.
    */
-  void write(Object obj);
+  void write(Object? obj);
 
   /**
    * Iterates over the given [objects] and [write]s them in sequence.
    */
-  void writeAll(Iterable objects, [String separator = ""]);
+  void writeAll(Iterable<dynamic> objects, [String separator = ""]);
 
   /**
-   * Converts [obj] to a String by invoking [Object.toString] and 
+   * Converts [obj] to a String by invoking [Object.toString] and
    * adds the result to `this`, followed by a newline.
    */
-  void writeln([Object obj = ""]);
+  void writeln([Object? obj = ""]);
 
   /**
    * Writes the [charCode] to `this`.
diff --git a/sdk_nnbd/lib/core/symbol.dart b/sdk_nnbd/lib/core/symbol.dart
index 2904b9f..65e83ff 100644
--- a/sdk_nnbd/lib/core/symbol.dart
+++ b/sdk_nnbd/lib/core/symbol.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.5
-
 part of dart.core;
 
 /// Opaque name used by mirrors, invocations and [Function.apply].
@@ -95,5 +93,5 @@
    * Qualified member names, like `#foo.bar` are equal only if they have the
    * same identifiers before the same final member name.
    */
-  bool operator ==(other);
+  bool operator ==(Object other);
 }
diff --git a/sdk_nnbd/lib/core/type.dart b/sdk_nnbd/lib/core/type.dart
index 8657cd4..d2e107b 100644
--- a/sdk_nnbd/lib/core/type.dart
+++ b/sdk_nnbd/lib/core/type.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.5
-
 part of dart.core;
 
 /**
diff --git a/sdk_nnbd/lib/core/uri.dart b/sdk_nnbd/lib/core/uri.dart
index 478e9d7..8e3100f 100644
--- a/sdk_nnbd/lib/core/uri.dart
+++ b/sdk_nnbd/lib/core/uri.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.5
-
 part of dart.core;
 
 // Frequently used character codes.
@@ -121,15 +119,15 @@
    * If `fragment` is omitted or `null`, the URI has no fragment part.
    */
   factory Uri(
-      {String scheme,
-      String userInfo,
-      String host,
-      int port,
-      String path,
-      Iterable<String> pathSegments,
-      String query,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
-      String fragment}) = _Uri;
+      {String? scheme,
+      String? userInfo,
+      String? host,
+      int? port,
+      String? path,
+      Iterable<String>? pathSegments,
+      String? query,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
+      String? fragment}) = _Uri;
 
   /**
    * Creates a new `http` URI from authority, path and query.
@@ -165,7 +163,7 @@
    * argument.
    */
   factory Uri.http(String authority, String unencodedPath,
-      [Map<String, String> queryParameters]) = _Uri.http;
+      [Map<String, String>? queryParameters]) = _Uri.http;
 
   /**
    * Creates a new `https` URI from authority, path and query.
@@ -174,7 +172,7 @@
    * which is set to `https`.
    */
   factory Uri.https(String authority, String unencodedPath,
-      [Map<String, String> queryParameters]) = _Uri.https;
+      [Map<String, String>? queryParameters]) = _Uri.https;
 
   /**
    * Creates a new file URI from an absolute or relative file path.
@@ -259,7 +257,7 @@
    *
    * If the path passed is not a valid file path, an error is thrown.
    */
-  factory Uri.file(String path, {bool windows}) = _Uri.file;
+  factory Uri.file(String path, {bool? windows}) = _Uri.file;
 
   /**
    * Like [Uri.file] except that a non-empty URI path ends in a slash.
@@ -268,7 +266,7 @@
    * 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;
+  factory Uri.directory(String path, {bool? windows}) = _Uri.directory;
 
   /**
    * Creates a `data:` URI containing the [content] string.
@@ -299,9 +297,9 @@
    * To read the content back, use [UriData.contentAsString].
    */
   factory Uri.dataFromString(String content,
-      {String mimeType,
-      Encoding encoding,
-      Map<String, String> parameters,
+      {String? mimeType,
+      Encoding? encoding,
+      Map<String, String>? parameters,
       bool base64 = false}) {
     UriData data = UriData.fromString(content,
         mimeType: mimeType,
@@ -328,9 +326,9 @@
    * encoded.
    */
   factory Uri.dataFromBytes(List<int> bytes,
-      {mimeType = "application/octet-stream",
-      Map<String, String> parameters,
-      percentEncoded = false}) {
+      {String mimeType = "application/octet-stream",
+      Map<String, String>? parameters,
+      bool percentEncoded = false}) {
     UriData data = UriData.fromBytes(bytes,
         mimeType: mimeType,
         parameters: parameters,
@@ -597,7 +595,7 @@
    */
   // TODO(lrn): Deprecate and move functionality to File class or similar.
   // The core libraries should not worry about the platform.
-  String toFilePath({bool windows});
+  String toFilePath({bool? windows});
 
   /**
    * Access the structure of a `data:` URI.
@@ -607,7 +605,7 @@
    * The [UriData] object can be used to access the media type and data
    * of a `data:` URI.
    */
-  UriData get data;
+  UriData? get data;
 
   /// Returns a hash code computed as `toString().hashCode`.
   ///
@@ -661,15 +659,15 @@
    * from this `Uri` need not be checked for validity again.
    */
   Uri replace(
-      {String scheme,
-      String userInfo,
-      String host,
-      int port,
-      String path,
-      Iterable<String> pathSegments,
-      String query,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
-      String fragment});
+      {String? scheme,
+      String? userInfo,
+      String? host,
+      int? port,
+      String? path,
+      Iterable<String>? pathSegments,
+      String? query,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
+      String? fragment});
 
   /**
    * Returns a `Uri` that differs from this only in not having a fragment.
@@ -734,7 +732,7 @@
    * 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]) {
+  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]
     // to do the final parsing.
@@ -809,7 +807,7 @@
     // The following index-normalization belongs with the scanning, but is
     // easier to do here because we already have extracted variables from the
     // indices list.
-    var indices = List<int>(8);
+    var indices = List<int>.filled(8, 0, growable: false);
 
     // Set default values for each position.
     // The value will either be correct in some cases where it isn't set
@@ -851,8 +849,8 @@
     int queryStart = indices[_queryStartIndex];
     int fragmentStart = indices[_fragmentStartIndex];
 
-    // We may discover scheme while handling special cases.
-    String scheme;
+    // We may discover the scheme while handling special cases.
+    String? scheme;
 
     // Derive some positions that weren't set to normalize the indices.
     if (fragmentStart < queryStart) queryStart = fragmentStart;
@@ -1034,7 +1032,7 @@
    *
    * 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]) {
+  static Uri? tryParse(String uri, [int start = 0, int? end]) {
     // TODO: Optimize to avoid throwing-and-recatching.
     try {
       return parse(uri, start, end);
@@ -1262,7 +1260,7 @@
    *  * `::FFFF:129.144.52.38`
    *  * `2010:836B:4179::836B:4179`
    */
-  static List<int> parseIPv6Address(String host, [int start = 0, int end]) {
+  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
     // by `:`'s, with the following exceptions:
@@ -1385,7 +1383,7 @@
    * 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;
+  final String? _host;
 
   /**
    * The port number part of the authority.
@@ -1393,7 +1391,7 @@
    * 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;
+  int? _port;
 
   /**
    * The path of the URI.
@@ -1402,44 +1400,38 @@
    */
   final String path;
 
-  // The query content, or null if there is no query.
-  final String _query;
+  /// The query content, or null if there is no query.
+  final String? _query;
 
   // The fragment content, or null if there is no fragment.
-  final String _fragment;
+  final String? _fragment;
 
-  /**
-   * Cache the computed return value of [pathSegments].
-   */
-  List<String> _pathSegments;
+  /// Cache of the full normalized text representation of the URI.
+  late final String _text = this._initializeText();
 
-  /**
-   * Cache of the full normalized text representation of the URI.
-   */
-  String _text;
+  /// Cache of the list of path segments.
+  late final List<String> pathSegments = _computePathSegments(this.path);
 
-  /**
-   * Cache of the hashCode of [_text].
-   *
-   * Is null until computed.
-   */
-  int _hashCodeCache;
+  /// Lazily computed and cached hashCode of [_text].
+  late final int hashCode = this._text.hashCode;
 
-  /**
-   * Cache the computed return value of [queryParameters].
-   */
-  Map<String, String> _queryParameters;
-  Map<String, List<String>> _queryParameterLists;
+  /// Cache the computed return value of [queryParameters].
+  late final Map<String, String> queryParameters =
+      UnmodifiableMapView<String, String>(Uri.splitQueryString(this.query));
+
+  /// Cache the computed return value of [queryParametersAll].
+  late final Map<String, List<String>> queryParametersAll =
+      _computeQueryParametersAll(this.query);
 
   /// Internal non-verifying constructor. Only call with validated arguments.
   ///
   /// The components must be properly normalized.
   ///
   /// Use `null` for [_host] if there is no authority. In that case, always
-  /// pass `null` for [_port] and [_userInfo] as well.
+  /// pass `null` for [_port] and an empty string for [_userInfo] as well.
   ///
-  /// Use `null` for [_port], [_userInfo], [_query] and [_fragment] if there is
-  /// component of that type.
+  /// Use `null` for [_port], [_query] and [_fragment] if there is
+  /// component of that type, and empty string for [_userInfo].
   ///
   /// The [path] and [scheme] are never empty.
   _Uri._internal(this.scheme, this._userInfo, this._host, this._port, this.path,
@@ -1460,7 +1452,7 @@
       int pathStart,
       int queryStart,
       int fragmentStart,
-      String scheme) {
+      String? scheme) {
     if (scheme == null) {
       scheme = "";
       if (schemeEnd > start) {
@@ -1470,8 +1462,8 @@
       }
     }
     String userInfo = "";
-    String host;
-    int port;
+    String? host;
+    int? port;
     if (hostStart > start) {
       int userInfoStart = schemeEnd + 3;
       if (userInfoStart < hostStart) {
@@ -1479,20 +1471,19 @@
       }
       host = _makeHost(uri, hostStart, portStart, false);
       if (portStart + 1 < pathStart) {
-        // Should throw because invalid.
-        port = int.parse(uri.substring(portStart + 1, pathStart), onError: (_) {
-          throw FormatException("Invalid port", uri, portStart + 1);
-        });
-        port = _makePort(port, scheme);
+        int portNumber =
+            int.tryParse(uri.substring(portStart + 1, pathStart)) ??
+                (throw FormatException("Invalid port", uri, portStart + 1));
+        port = _makePort(portNumber, scheme);
       }
     }
     String path =
         _makePath(uri, pathStart, queryStart, null, scheme, host != null);
-    String query;
+    String? query;
     if (queryStart < fragmentStart) {
       query = _makeQuery(uri, queryStart + 1, fragmentStart, null);
     }
-    String fragment;
+    String? fragment;
     if (fragmentStart < end) {
       fragment = _makeFragment(uri, fragmentStart + 1, end);
     }
@@ -1501,17 +1492,25 @@
 
   /// Implementation of [Uri.Uri].
   factory _Uri(
-      {String scheme,
-      String userInfo,
-      String host,
-      int port,
-      String path,
-      Iterable<String> pathSegments,
-      String query,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
-      String fragment}) {
-    scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
+      {String? scheme,
+      String? userInfo,
+      String? host,
+      int? port,
+      String? path,
+      Iterable<String>? pathSegments,
+      String? query,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
+      String? fragment}) {
+    if (scheme == null) {
+      scheme = "";
+    } else {
+      scheme = _makeScheme(scheme, 0, scheme.length);
+    }
     userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
+    if (userInfo == null) {
+      // TODO(dart-lang/language#440): Remove when promotion works.
+      throw "unreachable";
+    }
     host = _makeHost(host, 0, _stringOrNullLength(host), false);
     // Special case this constructor for backwards compatibility.
     if (query == "") query = null;
@@ -1525,6 +1524,10 @@
     bool hasAuthority = (host != null);
     path = _makePath(
         path, 0, _stringOrNullLength(path), pathSegments, scheme, hasAuthority);
+    if (path == null) {
+      // TODO(dart-lang/language#440): Remove when promotion works.
+      throw "unreachable";
+    }
     if (scheme.isEmpty && host == null && !path.startsWith('/')) {
       bool allowScheme = scheme.isNotEmpty || host != null;
       path = _normalizeRelativePath(path, allowScheme);
@@ -1539,13 +1542,13 @@
 
   /// Implementation of [Uri.http].
   factory _Uri.http(String authority, String unencodedPath,
-      [Map<String, String> queryParameters]) {
+      [Map<String, String>? queryParameters]) {
     return _makeHttpUri("http", authority, unencodedPath, queryParameters);
   }
 
   /// Implementation of [Uri.https].
   factory _Uri.https(String authority, String unencodedPath,
-      [Map<String, String> queryParameters]) {
+      [Map<String, String>? queryParameters]) {
     return _makeHttpUri("https", authority, unencodedPath, queryParameters);
   }
 
@@ -1559,19 +1562,19 @@
   String get userInfo => _userInfo;
 
   String get host {
-    if (_host == null) return "";
-    if (_host.startsWith('[')) {
-      return _host.substring(1, _host.length - 1);
+    String? host = _host;
+    if (host == null) return "";
+    if (host.startsWith('[')) {
+      return host.substring(1, host.length - 1);
     }
-    return _host;
+    return host;
   }
 
   int get port {
-    if (_port == null) return _defaultPort(scheme);
-    return _port;
+    return _port ?? _defaultPort(scheme);
   }
 
-  // The default port for the scheme of this Uri.
+  /// The default port for the scheme of this Uri.
   static int _defaultPort(String scheme) {
     if (scheme == "http") return 80;
     if (scheme == "https") return 443;
@@ -1620,25 +1623,23 @@
     return true;
   }
 
-  // Report a parse failure.
-  static void _fail(String uri, int index, String message) {
+  /// Report a parse failure.
+  static Never _fail(String uri, int index, String message) {
     throw FormatException(message, uri, index);
   }
 
-  static Uri _makeHttpUri(String scheme, String authority, String unencodedPath,
-      Map<String, String> queryParameters) {
+  static _Uri _makeHttpUri(String scheme, String? authority,
+      String unencodedPath, Map<String, String>? queryParameters) {
     var userInfo = "";
-    String host;
-    int port;
+    String? host;
+    int? port;
 
     if (authority != null && authority.isNotEmpty) {
       var hostStart = 0;
       // Split off the user info.
-      bool hasUserInfo = false;
       for (int i = 0; i < authority.length; i++) {
         const int atSign = 0x40;
         if (authority.codeUnitAt(i) == atSign) {
-          hasUserInfo = true;
           userInfo = authority.substring(0, i);
           hostStart = i + 1;
           break;
@@ -1673,7 +1674,6 @@
         }
       }
       // Split host and port.
-      bool hasPort = false;
       for (; hostEnd < authority.length; hostEnd++) {
         if (authority.codeUnitAt(hostEnd) == _COLON) {
           var portString = authority.substring(hostEnd + 1);
@@ -1684,7 +1684,7 @@
       }
       host = authority.substring(hostStart, hostEnd);
     }
-    return Uri(
+    return _Uri(
         scheme: scheme,
         userInfo: userInfo,
         host: host,
@@ -1694,25 +1694,25 @@
   }
 
   /// Implementation of [Uri.file].
-  factory _Uri.file(String path, {bool windows}) {
-    windows = (windows == null) ? _Uri._isWindows : windows;
-    return windows
+  factory _Uri.file(String path, {bool? windows}) {
+    return (windows ?? _Uri._isWindows)
         ? _makeWindowsFileUrl(path, false)
         : _makeFileUri(path, false);
   }
 
   /// Implementation of [Uri.directory].
-  factory _Uri.directory(String path, {bool windows}) {
-    windows = (windows == null) ? _Uri._isWindows : windows;
-    return windows ? _makeWindowsFileUrl(path, true) : _makeFileUri(path, true);
+  factory _Uri.directory(String path, {bool? windows}) {
+    return (windows ?? _Uri._isWindows)
+        ? _makeWindowsFileUrl(path, true)
+        : _makeFileUri(path, true);
   }
 
   /// Used internally in path-related constructors.
   external static bool get _isWindows;
 
-  static _checkNonWindowsPathReservedCharacters(
+  static void _checkNonWindowsPathReservedCharacters(
       List<String> segments, bool argumentError) {
-    segments.forEach((segment) {
+    for (var segment in segments) {
       if (segment.contains("/")) {
         if (argumentError) {
           throw ArgumentError("Illegal path character $segment");
@@ -1720,10 +1720,10 @@
           throw UnsupportedError("Illegal path character $segment");
         }
       }
-    });
+    }
   }
 
-  static _checkWindowsPathReservedCharacters(
+  static void _checkWindowsPathReservedCharacters(
       List<String> segments, bool argumentError,
       [int firstSegment = 0]) {
     for (var segment in segments.skip(firstSegment)) {
@@ -1737,7 +1737,7 @@
     }
   }
 
-  static _checkWindowsDriveLetter(int charCode, bool argumentError) {
+  static void _checkWindowsDriveLetter(int charCode, bool argumentError) {
     if ((_UPPER_CASE_A <= charCode && charCode <= _UPPER_CASE_Z) ||
         (_LOWER_CASE_A <= charCode && charCode <= _LOWER_CASE_Z)) {
       return;
@@ -1751,7 +1751,7 @@
     }
   }
 
-  static _makeFileUri(String path, bool slashTerminated) {
+  static Uri _makeFileUri(String path, bool slashTerminated) {
     const String sep = "/";
     var segments = path.split(sep);
     if (slashTerminated && segments.isNotEmpty && segments.last.isNotEmpty) {
@@ -1833,15 +1833,15 @@
   }
 
   Uri replace(
-      {String scheme,
-      String userInfo,
-      String host,
-      int port,
-      String path,
-      Iterable<String> pathSegments,
-      String query,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
-      String fragment}) {
+      {String? scheme,
+      String? userInfo,
+      String? host,
+      int? port,
+      String? path,
+      Iterable<String>? pathSegments,
+      String? query,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
+      String? fragment}) {
     // Set to true if the scheme has (potentially) changed.
     // In that case, the default port may also have changed and we need
     // to check even the existing port.
@@ -1852,12 +1852,14 @@
     } else {
       scheme = this.scheme;
     }
+
     bool isFile = (scheme == "file");
     if (userInfo != null) {
       userInfo = _makeUserInfo(userInfo, 0, userInfo.length);
     } else {
       userInfo = this._userInfo;
     }
+
     if (port != null) {
       port = _makePort(port, scheme);
     } else {
@@ -1880,11 +1882,12 @@
       path = _makePath(path, 0, _stringOrNullLength(path), pathSegments, scheme,
           hasAuthority);
     } else {
-      path = this.path;
-      if ((isFile || (hasAuthority && !path.isEmpty)) &&
-          !path.startsWith('/')) {
-        path = "/" + path;
+      var currentPath = this.path;
+      if ((isFile || (hasAuthority && !currentPath.isEmpty)) &&
+          !currentPath.startsWith('/')) {
+        currentPath = "/" + currentPath;
       }
+      path = currentPath;
     }
 
     if (query != null || queryParameters != null) {
@@ -1907,39 +1910,21 @@
     return _Uri._internal(scheme, _userInfo, _host, _port, path, _query, null);
   }
 
-  List<String> get pathSegments {
-    var result = _pathSegments;
-    if (result != null) return result;
-
-    var pathToSplit = path;
+  static List<String> _computePathSegments(String pathToSplit) {
     if (pathToSplit.isNotEmpty && pathToSplit.codeUnitAt(0) == _SLASH) {
       pathToSplit = pathToSplit.substring(1);
     }
-    result = (pathToSplit == "")
+    return (pathToSplit.isEmpty)
         ? const <String>[]
         : List<String>.unmodifiable(
             pathToSplit.split("/").map(Uri.decodeComponent));
-    _pathSegments = result;
-    return result;
   }
 
-  Map<String, String> get queryParameters {
-    _queryParameters ??=
-        UnmodifiableMapView<String, String>(Uri.splitQueryString(query));
-    return _queryParameters;
-  }
-
-  Map<String, List<String>> get queryParametersAll {
-    if (_queryParameterLists == null) {
-      Map queryParameterLists = _splitQueryStringAll(query);
-      for (var key in queryParameterLists.keys) {
-        queryParameterLists[key] =
-            List<String>.unmodifiable(queryParameterLists[key]);
-      }
-      _queryParameterLists =
-          Map<String, List<String>>.unmodifiable(queryParameterLists);
-    }
-    return _queryParameterLists;
+  static Map<String, List<String>> _computeQueryParametersAll(String? query) {
+    if (query == null || query.isEmpty) return const <String, List<String>>{};
+    Map<String, List<String>> queryParameterLists = _splitQueryStringAll(query);
+    queryParameterLists.updateAll(_toUnmodifiableStringList);
+    return Map<String, List<String>>.unmodifiable(queryParameterLists);
   }
 
   Uri normalizePath() {
@@ -1948,7 +1933,7 @@
     return this.replace(path: path);
   }
 
-  static int _makePort(int port, String scheme) {
+  static int? _makePort(int? port, String scheme) {
     // Perform scheme specific normalization.
     if (port != null && port == _defaultPort(scheme)) return null;
     return port;
@@ -1965,7 +1950,7 @@
    * 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) {
+  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;
     if (start == end) return "";
@@ -2004,8 +1989,8 @@
     return _normalizeRegName(host, start, end);
   }
 
-  // RFC 6874 check for ZoneID
-  // Return the index of first appeared `%`.
+  /// RFC 6874 check for ZoneID
+  /// Return the index of first appeared `%`.
   static int _checkZoneID(String host, int start, int end) {
     int index = host.indexOf('%', start);
     index = (index >= start && index < end) ? index : end;
@@ -2026,7 +2011,7 @@
    */
   static String _normalizeZoneID(String host, int start, int end,
       [String prefix = '']) {
-    StringBuffer buffer;
+    StringBuffer? buffer;
     if (prefix != '') {
       buffer = StringBuffer(prefix);
     }
@@ -2038,7 +2023,7 @@
     while (index < end) {
       int char = host.codeUnitAt(index);
       if (char == _PERCENT) {
-        String replacement = _normalizeEscape(host, index, true);
+        String? replacement = _normalizeEscape(host, index, true);
         if (replacement == null && isNormalized) {
           index += 3;
           continue;
@@ -2076,10 +2061,8 @@
             sourceLength = 2;
           }
         }
-        buffer ??= StringBuffer();
         String slice = host.substring(sectionStart, index);
-        buffer.write(slice);
-        buffer.write(_escapeChar(char));
+        (buffer ??= StringBuffer())..write(slice)..write(_escapeChar(char));
         index += sourceLength;
         sectionStart = index;
       }
@@ -2104,7 +2087,7 @@
    * lower case unreserved characters or upper case escapes.
    */
   static String _normalizeRegName(String host, int start, int end) {
-    StringBuffer buffer;
+    StringBuffer? buffer;
     int sectionStart = start;
     int index = start;
     // Whether all characters between sectionStart and index are normalized,
@@ -2114,7 +2097,7 @@
       int char = host.codeUnitAt(index);
       if (char == _PERCENT) {
         // The _regNameTable contains "%", so we check that first.
-        String replacement = _normalizeEscape(host, index, true);
+        String? replacement = _normalizeEscape(host, index, true);
         if (replacement == null && isNormalized) {
           index += 3;
           continue;
@@ -2156,11 +2139,9 @@
             sourceLength = 2;
           }
         }
-        buffer ??= StringBuffer();
         String slice = host.substring(sectionStart, index);
         if (!isNormalized) slice = slice.toLowerCase();
-        buffer.write(slice);
-        buffer.write(_escapeChar(char));
+        (buffer ??= StringBuffer())..write(slice)..write(_escapeChar(char));
         index += sourceLength;
         sectionStart = index;
       }
@@ -2200,9 +2181,9 @@
     return _canonicalizeScheme(scheme);
   }
 
-  // Canonicalize a few often-used scheme strings.
-  //
-  // This improves memory usage and makes comparison faster.
+  /// Canonicalize a few often-used scheme strings.
+  ///
+  /// This improves memory usage and makes comparison faster.
   static String _canonicalizeScheme(String scheme) {
     if (scheme == "http") return "http";
     if (scheme == "file") return "file";
@@ -2211,27 +2192,26 @@
     return scheme;
   }
 
-  static String _makeUserInfo(String userInfo, int start, int end) {
+  static String _makeUserInfo(String? userInfo, int start, int end) {
     if (userInfo == null) return "";
     return _normalizeOrSubstring(userInfo, start, end, _userinfoTable);
   }
 
-  static String _makePath(String path, int start, int end,
-      Iterable<String> pathSegments, String scheme, bool hasAuthority) {
+  static String _makePath(String? path, int start, int end,
+      Iterable<String>? pathSegments, String scheme, bool hasAuthority) {
     bool isFile = (scheme == "file");
     bool ensureLeadingSlash = isFile || hasAuthority;
-    if (path == null && pathSegments == null) return isFile ? "/" : "";
-    if (path != null && pathSegments != null) {
-      throw ArgumentError('Both path and pathSegments specified');
-    }
     String result;
-    if (path != null) {
-      result = _normalizeOrSubstring(path, start, end, _pathCharOrSlashTable,
-          escapeDelimiters: true);
-    } else {
+    if (path == null) {
+      if (pathSegments == null) return isFile ? "/" : "";
       result = pathSegments
           .map((s) => _uriEncode(_pathCharTable, s, utf8, false))
           .join("/");
+    } else if (pathSegments != null) {
+      throw ArgumentError('Both path and pathSegments specified');
+    } else {
+      result = _normalizeOrSubstring(path, start, end, _pathCharOrSlashTable,
+          escapeDelimiters: true);
     }
     if (result.isEmpty) {
       if (isFile) return "/";
@@ -2254,8 +2234,8 @@
     return _removeDotSegments(path);
   }
 
-  static String _makeQuery(String query, int start, int end,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters) {
+  static String? _makeQuery(String? query, int start, int end,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters) {
     if (query != null) {
       if (queryParameters != null) {
         throw ArgumentError('Both query and queryParameters specified');
@@ -2291,7 +2271,7 @@
     return result.toString();
   }
 
-  static String _makeFragment(String fragment, int start, int end) {
+  static String? _makeFragment(String? fragment, int start, int end) {
     if (fragment == null) return null;
     return _normalizeOrSubstring(fragment, start, end, _queryCharTable,
         escapeDelimiters: true);
@@ -2310,7 +2290,7 @@
    *
    * If [lowerCase] is true, a single character returned is always lower case,
    */
-  static String _normalizeEscape(String source, int index, bool lowerCase) {
+  static String? _normalizeEscape(String source, int index, bool lowerCase) {
     assert(source.codeUnitAt(index) == _PERCENT);
     if (index + 2 >= source.length) {
       return "%"; // Marks the escape as invalid.
@@ -2343,7 +2323,7 @@
     List<int> codeUnits;
     if (char < 0x80) {
       // ASCII, a single percent encoded sequence.
-      codeUnits = List(3);
+      codeUnits = Uint8List(3);
       codeUnits[0] = _PERCENT;
       codeUnits[1] = _hexDigits.codeUnitAt(char >> 4);
       codeUnits[2] = _hexDigits.codeUnitAt(char & 0xf);
@@ -2359,7 +2339,7 @@
           flag = 0xf0;
         }
       }
-      codeUnits = List(3 * encodedBytes);
+      codeUnits = Uint8List(3 * encodedBytes);
       int index = 0;
       while (--encodedBytes >= 0) {
         int byte = ((char >> (6 * encodedBytes)) & 0x3f) | flag;
@@ -2398,10 +2378,10 @@
    *
    * Returns `null` if the original content was already normalized.
    */
-  static String _normalize(
+  static String? _normalize(
       String component, int start, int end, List<int> charTable,
       {bool escapeDelimiters = false}) {
-    StringBuffer buffer;
+    StringBuffer? buffer;
     int sectionStart = start;
     int index = start;
     // Loop while characters are valid and escapes correct and upper-case.
@@ -2410,7 +2390,7 @@
       if (char < 127 && (charTable[char >> 4] & (1 << (char & 0x0f))) != 0) {
         index++;
       } else {
-        String replacement;
+        String? replacement;
         int sourceLength;
         if (char == _PERCENT) {
           replacement = _normalizeEscape(component, index, false);
@@ -2428,6 +2408,7 @@
           }
         } else if (!escapeDelimiters && _isGeneralDelimiter(char)) {
           _fail(component, index, "Invalid character");
+          throw "unreachable"; // TODO(lrn): Remove when Never-returning functions are recognized as throwing.
         } else {
           sourceLength = 1;
           if ((char & 0xFC00) == 0xD800) {
@@ -2443,9 +2424,9 @@
           }
           replacement = _escapeChar(char);
         }
-        buffer ??= StringBuffer();
-        buffer.write(component.substring(sectionStart, index));
-        buffer.write(replacement);
+        (buffer ??= StringBuffer())
+          ..write(component.substring(sectionStart, index))
+          ..write(replacement);
         index += sourceLength;
         sectionStart = index;
       }
@@ -2615,10 +2596,10 @@
     // From RFC 3986.
     String targetScheme;
     String targetUserInfo = "";
-    String targetHost;
-    int targetPort;
+    String? targetHost;
+    int? targetPort;
     String targetPath;
-    String targetQuery;
+    String? targetQuery;
     if (reference.scheme.isNotEmpty) {
       targetScheme = reference.scheme;
       if (reference.hasAuthority) {
@@ -2714,15 +2695,17 @@
       throw StateError(
           "Origin is only applicable schemes http and https: $this");
     }
-    if (_host == null || _host == "") {
+    String? host = _host;
+    if (host == null || host == "") {
       throw StateError(
           "A $scheme: URI should have a non-empty host name: $this");
     }
-    if (_port == null) return "$scheme://$_host";
-    return "$scheme://$_host:$_port";
+    int? port = _port;
+    if (port == null) return "$scheme://$host";
+    return "$scheme://$host:$port";
   }
 
-  String toFilePath({bool windows}) {
+  String toFilePath({bool? windows}) {
     if (scheme != "" && scheme != "file") {
       throw UnsupportedError("Cannot extract a file path from a $scheme URI");
     }
@@ -2734,8 +2717,7 @@
       throw UnsupportedError(
           "Cannot extract a file path from a URI with a fragment component");
     }
-    windows ??= _isWindows;
-    return windows ? _toWindowsFilePath(this) : _toFilePath();
+    return (windows ?? _isWindows) ? _toWindowsFilePath(this) : _toFilePath();
   }
 
   String _toFilePath() {
@@ -2780,10 +2762,6 @@
     return result.toString();
   }
 
-  bool get _isPathAbsolute {
-    return path != null && path.startsWith('/');
-  }
-
   void _writeAuthority(StringSink ss) {
     if (_userInfo.isNotEmpty) {
       ss.write(_userInfo);
@@ -2804,14 +2782,11 @@
    * 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;
+  UriData? get data => (scheme == "data") ? UriData.fromUri(this) : null;
 
-  String toString() {
-    return _text ??= _initializeText();
-  }
+  String toString() => _text;
 
   String _initializeText() {
-    assert(_text == null);
     StringBuffer sb = StringBuffer();
     if (scheme.isNotEmpty) sb..write(scheme)..write(":");
     if (hasAuthority || (scheme == "file")) {
@@ -2841,10 +2816,6 @@
         fragment == other.fragment;
   }
 
-  int get hashCode {
-    return _hashCodeCache ??= toString().hashCode;
-  }
-
   static List<String> _createList() => <String>[];
 
   static Map<String, List<String>> _splitQueryStringAll(String query,
@@ -2926,7 +2897,6 @@
     assert(0 <= start);
     assert(start <= end);
     assert(end <= text.length);
-    assert(encoding != null);
     // First check whether there is any characters which need special handling.
     bool simple = true;
     for (int i = start; i < end; i++) {
@@ -2946,7 +2916,7 @@
         bytes = text.substring(start, end).codeUnits;
       }
     } else {
-      bytes = List();
+      bytes = <int>[];
       for (int i = start; i < end; i++) {
         var codeUnit = text.codeUnitAt(i);
         if (codeUnit > 127) {
@@ -3062,50 +3032,6 @@
     0x07ff, // 0x70 - 0x7f  1111111111100010
   ];
 
-  // Characters allowed in scheme except for upper case letters.
-  static const _schemeLowerTable = <int>[
-    //                     LSB            MSB
-    //                      |              |
-    0x0000, // 0x00 - 0x0f  0000000000000000
-    0x0000, // 0x10 - 0x1f  0000000000000000
-    //                                 + -.
-    0x6800, // 0x20 - 0x2f  0000000000010110
-    //                      0123456789
-    0x03ff, // 0x30 - 0x3f  1111111111000000
-    //
-    0x0000, // 0x40 - 0x4f  0111111111111111
-    //
-    0x0000, // 0x50 - 0x5f  1111111111100001
-    //                       abcdefghijklmno
-    0xfffe, // 0x60 - 0x6f  0111111111111111
-    //                      pqrstuvwxyz
-    0x07ff, // 0x70 - 0x7f  1111111111100010
-  ];
-
-  // Sub delimiter characters combined with unreserved as of 3986.
-  // sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
-  //         / "*" / "+" / "," / ";" / "="
-  // RFC 3986 section 2.3.
-  // unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
-  static const _subDelimitersTable = <int>[
-    //                     LSB            MSB
-    //                      |              |
-    0x0000, // 0x00 - 0x0f  0000000000000000
-    0x0000, // 0x10 - 0x1f  0000000000000000
-    //                       !  $ &'()*+,-.
-    0x7fd2, // 0x20 - 0x2f  0100101111111110
-    //                      0123456789 ; =
-    0x2bff, // 0x30 - 0x3f  1111111111010100
-    //                       ABCDEFGHIJKLMNO
-    0xfffe, // 0x40 - 0x4f  0111111111111111
-    //                      PQRSTUVWXYZ    _
-    0x87ff, // 0x50 - 0x5f  1111111111100001
-    //                       abcdefghijklmno
-    0xfffe, // 0x60 - 0x6f  0111111111111111
-    //                      pqrstuvwxyz   ~
-    0x47ff, // 0x70 - 0x7f  1111111111100010
-  ];
-
   // General delimiter characters, RFC 3986 section 2.2.
   // gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
   //
@@ -3310,7 +3236,7 @@
   /**
    * Cache of the result returned by [uri].
    */
-  Uri _uriCache;
+  Uri? _uriCache;
 
   UriData._(this._text, this._separatorIndices, this._uriCache);
 
@@ -3324,15 +3250,15 @@
    * be more efficient if the [uri] itself isn't used.
    */
   factory UriData.fromString(String content,
-      {String mimeType,
-      Encoding encoding,
-      Map<String, String> parameters,
+      {String? mimeType,
+      Encoding? encoding,
+      Map<String, String>? parameters,
       bool base64 = false}) {
     StringBuffer buffer = StringBuffer();
     List<int> indices = [_noScheme];
-    String charsetName;
-    String encodingName;
-    if (parameters != null) charsetName = parameters["charset"];
+    String? charsetName;
+    String? charSetName = parameters?.["charset"];
+    String? encodingName;
     if (encoding == null) {
       if (charsetName != null) {
         encoding = Encoding.getByName(charsetName);
@@ -3362,9 +3288,9 @@
    * be more efficient if the [uri] itself isn't used.
    */
   factory UriData.fromBytes(List<int> bytes,
-      {mimeType = "application/octet-stream",
-      Map<String, String> parameters,
-      percentEncoded = false}) {
+      {String mimeType = "application/octet-stream",
+      Map<String, String>? parameters,
+      bool percentEncoded = false}) {
     StringBuffer buffer = StringBuffer();
     List<int> indices = [_noScheme];
     _writeUri(mimeType, null, parameters, buffer, indices);
@@ -3405,7 +3331,7 @@
       return _parse(uri.path, 0, uri);
     }
     // Includes path and query (and leading "data:").
-    return _parse("$uri", 5, uri);
+    return _parse(uri.toString(), 5, uri);
   }
 
   /**
@@ -3416,11 +3342,16 @@
    * Of an [indices] list is passed, separator indices are stored in that
    * list.
    */
-  static void _writeUri(String mimeType, String charsetName,
-      Map<String, String> parameters, StringBuffer buffer, List indices) {
+  static void _writeUri(
+      String? mimeType,
+      String? charsetName,
+      Map<String, String>? parameters,
+      StringBuffer buffer,
+      List<int>? indices) {
     if (mimeType == null || mimeType == "text/plain") {
       mimeType = "";
     }
+
     if (mimeType.isEmpty || identical(mimeType, "application/octet-stream")) {
       buffer.write(mimeType); // Common cases need no escaping.
     } else {
@@ -3435,9 +3366,8 @@
           _tokenCharTable, mimeType.substring(slashIndex + 1), utf8, false));
     }
     if (charsetName != null) {
-      if (indices != null) {
-        indices..add(buffer.length)..add(buffer.length + 8);
-      }
+      // TODO(39209): Use ?.. when sequences are properly supported.
+      if (indices != null) indices..add(buffer.length)..add(buffer.length + 8);
       buffer.write(";charset=");
       buffer.write(_Uri._uriEncode(_tokenCharTable, charsetName, utf8, false));
     }
@@ -3449,11 +3379,11 @@
         throw ArgumentError.value(
             "", "Parameter values must not be empty", 'parameters["$key"]');
       }
-      if (indices != null) indices.add(buffer.length);
+      indices?.add(buffer.length);
       buffer.write(';');
       // Encode any non-RFC2045-token character and both '%' and '#'.
       buffer.write(_Uri._uriEncode(_tokenCharTable, key, utf8, false));
-      if (indices != null) indices.add(buffer.length);
+      indices?.add(buffer.length);
       buffer.write('=');
       buffer.write(_Uri._uriEncode(_tokenCharTable, value, utf8, false));
     });
@@ -3533,9 +3463,12 @@
    * as path.
    */
   Uri get uri {
-    if (_uriCache != null) return _uriCache;
+    return _uriCache ??= _computeUri();
+  }
+
+  Uri _computeUri() {
     String path = _text;
-    String query;
+    String? query;
     int colonIndex = _separatorIndices[0];
     int queryIndex = _text.indexOf('?', colonIndex + 1);
     int end = _text.length;
@@ -3546,8 +3479,7 @@
     }
     path = _Uri._normalizeOrSubstring(
         _text, colonIndex + 1, end, _Uri._pathCharOrSlashTable);
-    _uriCache = _DataUri(this, path, query);
-    return _uriCache;
+    return _DataUri(this, path, query);
   }
 
   /**
@@ -3686,7 +3618,7 @@
    * converted to bytes and then the character codes and byte values are
    * decoded using [encoding].
    */
-  String contentAsString({Encoding encoding}) {
+  String contentAsString({Encoding? encoding}) {
     if (encoding == null) {
       var charset = this.charset; // Returns "US-ASCII" if not present.
       encoding = Encoding.getByName(charset);
@@ -3730,7 +3662,7 @@
     return result;
   }
 
-  static UriData _parse(String text, int start, Uri sourceUri) {
+  static UriData _parse(String text, int start, Uri? sourceUri) {
     assert(start == 0 || start == 5);
     assert((start == 5) == text.startsWith("data:"));
 
@@ -3872,26 +3804,6 @@
   //
   // This is the same characters as in a URI query (which is URI pchar plus '?')
   static const _uricTable = _Uri._queryCharTable;
-
-  // Characters allowed in base-64 encoding (alphanumeric, '/', '+' and '=').
-  static const _base64Table = [
-    //                     LSB             MSB
-    //                      |               |
-    0x0000, // 0x00 - 0x0f  00000000 00000000
-    0x0000, // 0x10 - 0x1f  00000000 00000000
-    //                                  +   /
-    0x8800, // 0x20 - 0x2f  00000000 00010001
-    //                      01234567 89
-    0x03ff, // 0x30 - 0x3f  11111111 11000000
-    //                       ABCDEFG HIJKLMNO
-    0xfffe, // 0x40 - 0x4f  01111111 11111111
-    //                      PQRSTUVW XYZ
-    0x07ff, // 0x50 - 0x5f  11111111 11100000
-    //                       abcdefg hijklmno
-    0xfffe, // 0x60 - 0x6f  01111111 11111111
-    //                      pqrstuvw xyz
-    0x07ff, // 0x70 - 0x7f  11111111 11100000
-  ];
 }
 
 // --------------------------------------------------------------------
@@ -4295,8 +4207,8 @@
   /// The scheme is often used to distinguish URIs.
   /// To make comparisons more efficient, we cache the value, and
   /// canonicalize a few known types.
-  String _schemeCache;
-  int _hashCodeCache;
+  String? _schemeCache;
+  int? _hashCodeCache;
 
   _SimpleUri(
       this._uri,
@@ -4336,20 +4248,16 @@
   }
 
   String get scheme {
+    return _schemeCache ??= _computeScheme();
+  }
+
+  String _computeScheme() {
     if (_schemeEnd <= 0) return "";
-    if (_schemeCache != null) return _schemeCache;
-    if (_isHttp) {
-      _schemeCache = "http";
-    } else if (_isHttps) {
-      _schemeCache = "https";
-    } else if (_isFile) {
-      _schemeCache = "file";
-    } else if (_isPackage) {
-      _schemeCache = "package";
-    } else {
-      _schemeCache = _uri.substring(0, _schemeEnd);
-    }
-    return _schemeCache;
+    if (_isHttp) return "http";
+    if (_isHttps) return "https";
+    if (_isFile) return "file";
+    if (_isPackage) return "package";
+    return _uri.substring(0, _schemeEnd);
   }
 
   String get authority =>
@@ -4419,11 +4327,9 @@
 
   Map<String, List<String>> get queryParametersAll {
     if (!hasQuery) return const <String, List<String>>{};
-    Map queryParameterLists = _Uri._splitQueryStringAll(query);
-    for (var key in queryParameterLists.keys) {
-      queryParameterLists[key] =
-          List<String>.unmodifiable(queryParameterLists[key]);
-    }
+    Map<String, List<String>> queryParameterLists =
+        _Uri._splitQueryStringAll(query);
+    queryParameterLists.updateAll(_toUnmodifiableStringList);
     return Map<String, List<String>>.unmodifiable(queryParameterLists);
   }
 
@@ -4442,15 +4348,15 @@
   }
 
   Uri replace(
-      {String scheme,
-      String userInfo,
-      String host,
-      int port,
-      String path,
-      Iterable<String> pathSegments,
-      String query,
-      Map<String, dynamic /*String|Iterable<String>*/ > queryParameters,
-      String fragment}) {
+      {String? scheme,
+      String? userInfo,
+      String? host,
+      int? port,
+      String? path,
+      Iterable<String>? pathSegments,
+      String? query,
+      Map<String, dynamic /*String|Iterable<String>*/ >? queryParameters,
+      String? fragment}) {
     bool schemeChanged = false;
     if (scheme != null) {
       scheme = _Uri._makeScheme(scheme, 0, scheme.length);
@@ -4702,7 +4608,7 @@
         base._schemeCache);
   }
 
-  String toFilePath({bool windows}) {
+  String toFilePath({bool? windows}) {
     if (_schemeEnd >= 0 && !_isFile) {
       throw UnsupportedError("Cannot extract a file path from a $scheme URI");
     }
@@ -4714,8 +4620,9 @@
       throw UnsupportedError(
           "Cannot extract a file path from a URI with a fragment component");
     }
-    windows ??= _Uri._isWindows;
-    return windows ? _Uri._toWindowsFilePath(this) : _toFilePath();
+    return (windows ?? _Uri._isWindows)
+        ? _Uri._toWindowsFilePath(this)
+        : _toFilePath();
   }
 
   String _toFilePath() {
@@ -4728,7 +4635,7 @@
     return this.path;
   }
 
-  UriData get data {
+  UriData? get data {
     assert(scheme != "data");
     return null;
   }
@@ -4758,10 +4665,10 @@
 class _DataUri extends _Uri {
   final UriData _data;
 
-  _DataUri(this._data, String path, String query)
-      : super._internal("data", null, null, null, path, query, null);
+  _DataUri(this._data, String path, String? query)
+      : super._internal("data", "", null, null, path, query, null);
 
-  UriData get data => _data;
+  UriData? get data => _data;
 }
 
 /// Checks whether [text] starts with "data:" at position [start].
@@ -4783,4 +4690,7 @@
 }
 
 /// Helper function returning the length of a string, or `0` for `null`.
-int _stringOrNullLength(String s) => (s == null) ? 0 : s.length;
+int _stringOrNullLength(String? s) => (s == null) ? 0 : s.length;
+
+List<String> _toUnmodifiableStringList(String key, List<String> list) =>
+    List<String>.unmodifiable(list);
diff --git a/sdk_nnbd/lib/developer/developer.dart b/sdk_nnbd/lib/developer/developer.dart
index 732e1d9..5e0df5a 100644
--- a/sdk_nnbd/lib/developer/developer.dart
+++ b/sdk_nnbd/lib/developer/developer.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.5
-
 /// Interact with developer tools such as the debugger and inspector.
 ///
 /// This library is platform dependent and has separate implementations for
@@ -36,12 +34,12 @@
 /// regardless of whether or not a debugger is connected. When compiled to
 /// JavaScript, this uses the "debugger" statement, and behaves exactly as
 /// that does.
-external bool debugger({bool when: true, String message});
+external bool debugger({bool when = true, String? message});
 
 /// Send a reference to [object] to any attached debuggers.
 ///
 /// Debuggers may open an inspector on the object. Returns the argument.
-external Object inspect(Object object);
+external Object inspect(Object? object);
 
 /// Emit a log event.
 ///
@@ -59,11 +57,11 @@
 /// - [stackTrace] (optional) a stack trace associated with this log event
 external void log(
   String message, {
-  DateTime time,
-  int sequenceNumber,
-  int level: 0,
-  String name: '',
-  Zone zone,
-  Object error,
-  StackTrace stackTrace,
+  DateTime? time,
+  int? sequenceNumber,
+  int level = 0,
+  String name = '',
+  Zone? zone,
+  Object? error,
+  StackTrace? stackTrace,
 });
diff --git a/sdk_nnbd/lib/developer/extension.dart b/sdk_nnbd/lib/developer/extension.dart
index d292857..bf03cd9 100644
--- a/sdk_nnbd/lib/developer/extension.dart
+++ b/sdk_nnbd/lib/developer/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.5
-
 part of dart.developer;
 
 /// A response to a service protocol extension RPC.
@@ -12,13 +10,13 @@
 /// use [ServiceExtensionResponse.error].
 class ServiceExtensionResponse {
   /// The result of a successful service protocol extension RPC.
-  final String result;
+  final String? result;
 
   /// The error code associated with a failed service protocol extension RPC.
-  final int errorCode;
+  final int? errorCode;
 
   /// The details of a failed service protocol extension RPC.
-  final String errorDetail;
+  final String? errorDetail;
 
   /// Creates a successful response to a service protocol extension RPC.
   ///
@@ -28,6 +26,7 @@
       : result = result,
         errorCode = null,
         errorDetail = null {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(result, "result");
   }
 
@@ -42,6 +41,7 @@
         errorCode = errorCode,
         errorDetail = errorDetail {
     _validateErrorCode(errorCode);
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(errorDetail, "errorDetail");
   }
 
@@ -82,6 +82,7 @@
   }
 
   static _validateErrorCode(int errorCode) {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(errorCode, "errorCode");
     if (errorCode == invalidParams) return;
     if ((errorCode >= extensionErrorMin) && (errorCode <= extensionErrorMax)) {
@@ -95,17 +96,12 @@
 
   // ignore: unused_element, called from runtime/lib/developer.dart
   String _toString() {
-    if (result != null) {
-      return result;
-    } else {
-      assert(errorCode != null);
-      assert(errorDetail != null);
-      return json.encode({
-        'code': errorCode,
-        'message': _errorCodeMessage(errorCode),
-        'data': {'details': errorDetail}
-      });
-    }
+    return result ??
+        json.encode({
+          'code': errorCode!,
+          'message': _errorCodeMessage(errorCode!),
+          'data': {'details': errorDetail!}
+        });
   }
 }
 
@@ -132,6 +128,7 @@
 /// Because service extensions are isolate specific, clients using extensions
 /// must always include an 'isolateId' parameter with each RPC.
 void registerExtension(String method, ServiceExtensionHandler handler) {
+  // TODO: When NNBD is complete, delete the following line.
   ArgumentError.checkNotNull(method, 'method');
   if (!method.startsWith('ext.')) {
     throw new ArgumentError.value(method, 'method', 'Must begin with ext.');
@@ -139,6 +136,7 @@
   if (_lookupExtension(method) != null) {
     throw new ArgumentError('Extension already registered: $method');
   }
+  // TODO: When NNBD is complete, delete the following line.
   ArgumentError.checkNotNull(handler, 'handler');
   _registerExtension(method, handler);
 }
@@ -146,6 +144,7 @@
 /// Post an event of [eventKind] with payload of [eventData] to the `Extension`
 /// event stream.
 void postEvent(String eventKind, Map eventData) {
+  // TODO: When NNBD is complete, delete the following two lines.
   ArgumentError.checkNotNull(eventKind, 'eventKind');
   ArgumentError.checkNotNull(eventData, 'eventData');
   String eventDataAsString = json.encode(eventData);
diff --git a/sdk_nnbd/lib/developer/profiler.dart b/sdk_nnbd/lib/developer/profiler.dart
index f08df89..b7472f1 100644
--- a/sdk_nnbd/lib/developer/profiler.dart
+++ b/sdk_nnbd/lib/developer/profiler.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.5
-
 part of dart.developer;
 
 /// A UserTag can be used to group samples in the Observatory profiler.
@@ -65,11 +63,12 @@
   }
 
   Gauge(String name, String description, this.min, this.max)
-      : super(name, description) {
+      : _value = min ?? double.negativeInfinity,
+        super(name, description) {
+    // TODO: When NNBD is complete, delete the following two lines.
     ArgumentError.checkNotNull(min, 'min');
     ArgumentError.checkNotNull(max, 'max');
     if (!(min < max)) throw new ArgumentError('min must be less than max');
-    _value = min;
   }
 
   Map _toJSON() {
@@ -113,6 +112,7 @@
 
   /// Register [Metric]s to make them visible to Observatory.
   static void register(Metric metric) {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(metric, 'metric');
     if (_metrics[metric.name] != null) {
       throw new ArgumentError('Registered metrics have unique names');
@@ -122,12 +122,13 @@
 
   /// Deregister [Metric]s to make them not visible to Observatory.
   static void deregister(Metric metric) {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(metric, 'metric');
     _metrics.remove(metric.name);
   }
 
   // ignore: unused_element, called from native code
-  static String _printMetric(String id) {
+  static String? _printMetric(String id) {
     var metric = _metrics[id];
     if (metric == null) {
       return null;
diff --git a/sdk_nnbd/lib/developer/service.dart b/sdk_nnbd/lib/developer/service.dart
index 2678da7..a9757e4 100644
--- a/sdk_nnbd/lib/developer/service.dart
+++ b/sdk_nnbd/lib/developer/service.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.5
-
 part of dart.developer;
 
 /// Service protocol is the protocol that a client like the Observatory
@@ -60,6 +58,7 @@
   /// enable (true) or disable (false) the web server servicing requests.
   static Future<ServiceProtocolInfo> controlWebServer(
       {bool enable: false}) async {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(enable, 'enable');
     // Port to receive response from service isolate.
     final RawReceivePort receivePort = new RawReceivePort();
@@ -79,6 +78,7 @@
   /// Returns null if the running Dart environment does not support the service
   /// protocol.
   static String getIsolateID(Isolate isolate) {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(isolate, 'isolate');
     return _getIsolateIDFromSendPort(isolate.controlPort);
   }
diff --git a/sdk_nnbd/lib/developer/timeline.dart b/sdk_nnbd/lib/developer/timeline.dart
index 56f4f16..7ec4fd5 100644
--- a/sdk_nnbd/lib/developer/timeline.dart
+++ b/sdk_nnbd/lib/developer/timeline.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.5
-
 part of dart.developer;
 
 const bool _hasTimeline =
@@ -58,7 +56,7 @@
   /// When passed to a [Timeline] method, generates a "begin" Flow event.
   /// If [id] is not provided, an id that conflicts with no other Dart-generated
   /// flow id's will be generated.
-  static Flow begin({int id}) {
+  static Flow begin({int? id}) {
     return new Flow._(_begin, id ?? _getNextAsyncId());
   }
 
@@ -102,8 +100,9 @@
   /// a [Map] of [arguments]. This slice may also optionally be associated with
   /// a [Flow] event. This operation must be finished before
   /// returning to the event queue.
-  static void startSync(String name, {Map arguments, Flow flow}) {
+  static void startSync(String name, {Map? arguments, Flow? flow}) {
     if (!_hasTimeline) return;
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(name, 'name');
     if (!_isDartStreamEnabled()) {
       // Push a null onto the stack and return.
@@ -139,14 +138,15 @@
   }
 
   /// Emit an instant event.
-  static void instantSync(String name, {Map arguments}) {
+  static void instantSync(String name, {Map? arguments}) {
     if (!_hasTimeline) return;
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(name, 'name');
     if (!_isDartStreamEnabled()) {
       // Stream is disabled.
       return;
     }
-    Map instantArguments;
+    Map? instantArguments;
     if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
@@ -157,7 +157,7 @@
   /// A utility method to time a synchronous [function]. Internally calls
   /// [function] bracketed by calls to [startSync] and [finishSync].
   static T timeSync<T>(String name, TimelineSyncFunction<T> function,
-      {Map arguments, Flow flow}) {
+      {Map? arguments, Flow? flow}) {
     startSync(name, arguments: arguments, flow: flow);
     try {
       return function();
@@ -172,7 +172,7 @@
   /// When run on the Dart VM, uses the same monotonic clock as the embedding
   /// API's `Dart_TimelineGetMicros`.
   static int get now => _getTraceClock();
-  static final List<_SyncBlock> _stack = new List<_SyncBlock>();
+  static final List<_SyncBlock?> _stack = [];
 }
 
 /// An asynchronous task on the timeline. An asynchronous task can have many
@@ -186,37 +186,52 @@
   /// If [parent] is provided, the parent's task ID is provided as argument
   /// 'parentId' when [start] is called. In DevTools, this argument will result
   /// in this [TimelineTask] being linked to the [parent] [TimelineTask].
-  TimelineTask({TimelineTask parent})
+  TimelineTask({TimelineTask? parent})
       : _parent = parent,
         _taskId = _getNextAsyncId() {}
 
   /// Create a task with an explicit [taskId]. This is useful if you are
   /// passing a task from one isolate to another.
+  ///
+  /// Important note: only provide task IDs which have been obtained as a
+  /// result of invoking [TimelineTask.pass]. Specifying a custom ID can lead
+  /// to ID collisions, resulting in incorrect rendering of timeline events.
   TimelineTask.withTaskId(int taskId)
       : _parent = null,
         _taskId = taskId {
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(taskId, 'taskId');
   }
 
   /// Start a synchronous operation within this task named [name].
   /// Optionally takes a [Map] of [arguments].
-  void start(String name, {Map arguments}) {
+  void start(String name, {Map? arguments}) {
     if (!_hasTimeline) return;
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(name, 'name');
     var block = new _AsyncBlock._(name, _taskId);
     _stack.add(block);
-    block._start({
-      if (arguments != null) ...arguments,
-      if (_parent != null) 'parentId': _parent._taskId.toRadixString(16),
-    });
+    // TODO(39115): Spurious error about collection literal ambiguity.
+    // TODO(39117): Spurious error about typing of `...?arguments`.
+    // TODO(39120): Spurious error even about `...arguments`.
+    // When these TODOs are done, we can use spread and if elements.
+    var map = <Object?, Object?>{};
+    if (arguments != null) {
+      for (var key in arguments.keys) {
+        map[key] = arguments[key];
+      }
+    }
+    if (_parent != null) map['parentId'] = _parent!._taskId.toRadixString(16);
+    block._start(map);
   }
 
   /// Emit an instant event for this task.
   /// Optionally takes a [Map] of [arguments].
-  void instant(String name, {Map arguments}) {
+  void instant(String name, {Map? arguments}) {
     if (!_hasTimeline) return;
+    // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(name, 'name');
-    Map instantArguments;
+    Map? instantArguments;
     if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
@@ -226,7 +241,7 @@
 
   /// Finish the last synchronous operation that was started.
   /// Optionally takes a [Map] of [arguments].
-  void finish({Map arguments}) {
+  void finish({Map? arguments}) {
     if (!_hasTimeline) {
       return;
     }
@@ -250,7 +265,7 @@
     return r;
   }
 
-  final TimelineTask _parent;
+  final TimelineTask? _parent;
   final int _taskId;
   final List<_AsyncBlock> _stack = [];
 }
@@ -276,7 +291,7 @@
   }
 
   // Emit the finish event.
-  void _finish(Map arguments) {
+  void _finish(Map? arguments) {
     _reportTaskEvent(_getTraceClock(), _taskId, 'e', category, name,
         _argumentsAsJson(arguments));
   }
@@ -293,14 +308,14 @@
 
   /// An (optional) set of arguments which will be serialized to JSON and
   /// associated with this block.
-  Map _arguments;
+  Map? _arguments;
   // The start time stamp.
   final int _start;
   // The start time stamp of the thread cpu clock.
   final int _startCpu;
 
   /// An (optional) flow event associated with this block.
-  Flow _flow;
+  Flow? _flow;
 
   _SyncBlock._(this.name, this._start, this._startCpu);
 
@@ -311,8 +326,8 @@
     _reportCompleteEvent(
         _start, _startCpu, category, name, _argumentsAsJson(_arguments));
     if (_flow != null) {
-      _reportFlowEvent(_start, _startCpu, category, "${_flow.id}", _flow._type,
-          _flow.id, _argumentsAsJson(null));
+      _reportFlowEvent(_start, _startCpu, category, "${_flow!.id}",
+          _flow!._type, _flow!.id, _argumentsAsJson(null));
     }
   }
 
@@ -321,7 +336,7 @@
   }
 }
 
-String _argumentsAsJson(Map arguments) {
+String _argumentsAsJson(Map? arguments) {
   if ((arguments == null) || (arguments.length == 0)) {
     // Fast path no arguments. Avoid calling jsonEncode.
     return '{}';
diff --git a/sdk_nnbd/lib/ffi/ffi.dart b/sdk_nnbd/lib/ffi/ffi.dart
index c00226f..a8428bc 100644
--- a/sdk_nnbd/lib/ffi/ffi.dart
+++ b/sdk_nnbd/lib/ffi/ffi.dart
@@ -611,3 +611,13 @@
   /// the platform.
   external T operator [](int index);
 }
+
+/// Extension to retrieve the native `Dart_Port` from a [SendPort].
+extension NativePort on SendPort {
+  /// The native port of this [SendPort].
+  ///
+  /// The returned native port can for example be used by C code to post
+  /// messages to the connected [ReceivePort] via `Dart_PostCObject()` - see
+  /// `dart_native_api.h`.
+  external int get nativePort;
+}
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index 29f0c70..bcad33f 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -10844,13 +10844,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, width.hashCode, height.hashCode);
@@ -32941,13 +32940,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, width.hashCode, height.hashCode);
@@ -34972,8 +34970,8 @@
   }
 
   // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
-  // Ideally we would provide a RectangleMixin class that provides this implementation.
-  // In an ideal world we would exp
+  // Ideally we would provide a RectangleMixin class that provides this
+  // implementation. In an ideal world we would exp
   /** The x-coordinate of the right edge. */
   num get right => left + width;
   /** The y-coordinate of the bottom edge. */
@@ -34983,13 +34981,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        right == other.right &&
-        bottom == other.bottom;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      right == other.right &&
+      bottom == other.bottom;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
diff --git a/sdk_nnbd/lib/io/file.dart b/sdk_nnbd/lib/io/file.dart
index 6e515ea..a291c71 100644
--- a/sdk_nnbd/lib/io/file.dart
+++ b/sdk_nnbd/lib/io/file.dart
@@ -706,11 +706,13 @@
   Future<int> readInto(List<int> buffer, [int start = 0, int end]);
 
   /**
-   * Synchronously 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.
+   * 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.
    */
diff --git a/sdk_nnbd/lib/io/io.dart b/sdk_nnbd/lib/io/io.dart
index 05df370..64a1f78 100644
--- a/sdk_nnbd/lib/io/io.dart
+++ b/sdk_nnbd/lib/io/io.dart
@@ -215,6 +215,7 @@
 part 'io_service.dart';
 part 'link.dart';
 part 'namespace_impl.dart';
+part 'network_profiling.dart';
 part 'overrides.dart';
 part 'platform.dart';
 part 'platform_impl.dart';
diff --git a/sdk_nnbd/lib/io/io_sources.gni b/sdk_nnbd/lib/io/io_sources.gni
index 51e283a..308dd94 100644
--- a/sdk_nnbd/lib/io/io_sources.gni
+++ b/sdk_nnbd/lib/io/io_sources.gni
@@ -21,6 +21,7 @@
   "io_service.dart",
   "link.dart",
   "namespace_impl.dart",
+  "network_profiling.dart",
   "overrides.dart",
   "platform.dart",
   "platform_impl.dart",
diff --git a/sdk_nnbd/lib/io/network_profiling.dart b/sdk_nnbd/lib/io/network_profiling.dart
new file mode 100644
index 0000000..c32f2b6
--- /dev/null
+++ b/sdk_nnbd/lib/io/network_profiling.dart
@@ -0,0 +1,59 @@
+// 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.5
+
+part of dart.io;
+
+@pragma('vm:entry-point')
+abstract class _NetworkProfiling {
+  static const _kGetHttpProfileRPC = 'ext.dart.io.getHttpProfile';
+  static const _kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
+
+  @pragma('vm:entry-point')
+  static void _registerServiceExtension() {
+    registerExtension(_kGetHttpProfileRPC, _serviceExtensionHandler);
+    registerExtension(_kGetSocketProfileRPC, _serviceExtensionHandler);
+  }
+
+  static Future<ServiceExtensionResponse> _serviceExtensionHandler(
+      String method, Map<String, String> parameters) {
+    String responseJson;
+    switch (method) {
+      case _kGetHttpProfileRPC:
+        responseJson = _HttpProfile.toJSON();
+        break;
+      case _kGetSocketProfileRPC:
+        responseJson = _SocketProfile.toJSON();
+        break;
+      default:
+        return Future.value(ServiceExtensionResponse.error(
+            ServiceExtensionResponse.extensionError,
+            'Method $method does not exist'));
+    }
+    return Future.value(ServiceExtensionResponse.result(responseJson));
+  }
+}
+
+abstract class _HttpProfile {
+  static const _kType = 'HttpProfile';
+  // TODO(bkonyi): implement.
+  static String toJSON() {
+    final response = <String, dynamic>{
+      'type': _kType,
+    };
+    return json.encode(response);
+  }
+}
+
+abstract class _SocketProfile {
+  static const _kType = 'SocketProfile';
+  // TODO(bkonyi): implement.
+  static String toJSON() {
+    final response = <String, dynamic>{
+      'type': _kType,
+    };
+    return json.encode(response);
+  }
+}
diff --git a/sdk_nnbd/lib/io/overrides.dart b/sdk_nnbd/lib/io/overrides.dart
index 6786ae4..b46af8a 100644
--- a/sdk_nnbd/lib/io/overrides.dart
+++ b/sdk_nnbd/lib/io/overrides.dart
@@ -89,6 +89,11 @@
               {dynamic sourceAddress})
           socketStartConnect,
 
+      // ServerSocket
+      Future<ServerSocket> Function(dynamic, int,
+              {int backlog, bool v6Only, bool shared})
+          serverSocketBind,
+
       // Optional Zone parameters
       ZoneSpecification zoneSpecification,
       Function onError}) {
@@ -122,6 +127,9 @@
       // Socket
       socketConnect,
       socketStartConnect,
+
+      // ServerSocket
+      serverSocketBind,
     );
     return _asyncRunZoned<R>(body,
         zoneValues: {_ioOverridesToken: overrides},
@@ -276,6 +284,19 @@
       {sourceAddress}) {
     return Socket._startConnect(host, port, sourceAddress: sourceAddress);
   }
+
+  // ServerSocket
+
+  /// Asynchronously returns a [ServerSocket] that connects to the given address
+  /// and port when successful.
+  ///
+  /// 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}) {
+    return ServerSocket._bind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
 }
 
 class _IOOverridesScope extends IOOverrides {
@@ -313,6 +334,10 @@
   Future<ConnectionTask<Socket>> Function(dynamic, int, {dynamic sourceAddress})
       _socketStartConnect;
 
+  // ServerSocket
+  Future<ServerSocket> Function(dynamic, int,
+      {int backlog, bool v6Only, bool shared}) _serverSocketBind;
+
   _IOOverridesScope(
     // Directory
     this._createDirectory,
@@ -343,6 +368,9 @@
     // Socket
     this._socketConnect,
     this._socketStartConnect,
+
+    // ServerSocket
+    this._serverSocketBind,
   );
 
   // Directory
@@ -480,4 +508,20 @@
     }
     return super.socketStartConnect(host, port, sourceAddress: sourceAddress);
   }
+
+  // ServerSocket
+  @override
+  Future<ServerSocket> serverSocketBind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    if (_serverSocketBind != null) {
+      return _serverSocketBind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    if (_previous != null) {
+      return _previous.serverSocketBind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    return super.serverSocketBind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
 }
diff --git a/sdk_nnbd/lib/io/socket.dart b/sdk_nnbd/lib/io/socket.dart
index c3583de..6f45741 100644
--- a/sdk_nnbd/lib/io/socket.dart
+++ b/sdk_nnbd/lib/io/socket.dart
@@ -329,9 +329,19 @@
    * distributed among all the bound `ServerSocket`s. Connections can be
    * distributed over multiple isolates this way.
    */
-  external static Future<ServerSocket> bind(address, int port,
-      {int backlog: 0, bool v6Only: false, bool shared: false});
+  static Future<ServerSocket> bind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false}) {
+    final IOOverrides overrides = IOOverrides.current;
+    if (overrides == null) {
+      return ServerSocket._bind(address, port,
+          backlog: backlog, v6Only: v6Only, shared: shared);
+    }
+    return overrides.serverSocketBind(address, port,
+        backlog: backlog, v6Only: v6Only, shared: shared);
+  }
 
+  external static Future<ServerSocket> _bind(address, int port,
+      {int backlog: 0, bool v6Only: false, bool shared: false});
   /**
    * Returns the port used by this socket.
    */
diff --git a/sdk_nnbd/lib/libraries_nnbd_mix_hack.json b/sdk_nnbd/lib/libraries_nnbd_mix_hack.json
new file mode 100644
index 0000000..5d71fb6
--- /dev/null
+++ b/sdk_nnbd/lib/libraries_nnbd_mix_hack.json
@@ -0,0 +1,485 @@
+{
+  "comment:0": "NOTE: THIS FILE IS COPIED FROM A GENERATED VERSION.",
+  "comment:1": "It contains edits to build the current SDK for DDC with the NNBD dart:_runtime library.",
+  "comment:2": "This is only a temporary hack to unblock DDC development while the NNBD SDK is migrating and does not compile.",
+  "vm": {
+    "libraries": {
+      "_builtin": {
+        "uri": "_internal/vm/bin/builtin.dart"
+      },
+      "cli": {
+        "patches": [
+          "_internal/vm/bin/cli_patch.dart"
+        ],
+        "uri": "cli/cli.dart"
+      },
+      "core": {
+        "patches": [
+          "_internal/vm/lib/core_patch.dart",
+          "_internal/vm/lib/array.dart",
+          "_internal/vm/lib/array_patch.dart",
+          "_internal/vm/lib/bigint_patch.dart",
+          "_internal/vm/lib/bool_patch.dart",
+          "_internal/vm/lib/date_patch.dart",
+          "_internal/vm/lib/double.dart",
+          "_internal/vm/lib/double_patch.dart",
+          "_internal/vm/lib/errors_patch.dart",
+          "_internal/vm/lib/expando_patch.dart",
+          "_internal/vm/lib/function.dart",
+          "_internal/vm/lib/function_patch.dart",
+          "_internal/vm/lib/growable_array.dart",
+          "_internal/vm/lib/identical_patch.dart",
+          "_internal/vm/lib/immutable_map.dart",
+          "_internal/vm/lib/integers.dart",
+          "_internal/vm/lib/integers_patch.dart",
+          "_internal/vm/lib/invocation_mirror_patch.dart",
+          "_internal/vm/lib/lib_prefix.dart",
+          "_internal/vm/lib/map_patch.dart",
+          "_internal/vm/lib/null_patch.dart",
+          "_internal/vm/lib/object_patch.dart",
+          "_internal/vm/lib/regexp_patch.dart",
+          "_internal/vm/lib/stacktrace.dart",
+          "_internal/vm/lib/stopwatch_patch.dart",
+          "_internal/vm/lib/string_buffer_patch.dart",
+          "_internal/vm/lib/string_patch.dart",
+          "_internal/vm/lib/type_patch.dart",
+          "_internal/vm/lib/uri_patch.dart",
+          "_internal/vm/lib/weak_property.dart"
+        ],
+        "uri": "core/core.dart"
+      },
+      "async": {
+        "patches": [
+          "_internal/vm/lib/async_patch.dart",
+          "_internal/vm/lib/deferred_load_patch.dart",
+          "_internal/vm/lib/schedule_microtask_patch.dart",
+          "_internal/vm/lib/timer_patch.dart"
+        ],
+        "uri": "async/async.dart"
+      },
+      "collection": {
+        "patches": [
+          "_internal/vm/lib/collection_patch.dart",
+          "_internal/vm/lib/compact_hash.dart"
+        ],
+        "uri": "collection/collection.dart"
+      },
+      "ffi": {
+        "patches": [
+          "_internal/vm/lib/ffi_patch.dart",
+          "_internal/vm/lib/ffi_dynamic_library_patch.dart",
+          "_internal/vm/lib/ffi_native_type_patch.dart"
+        ],
+        "uri": "ffi/ffi.dart"
+      },
+      "typed_data": {
+        "patches": "_internal/vm/lib/typed_data_patch.dart",
+        "uri": "typed_data/typed_data.dart"
+      },
+      "nativewrappers": {
+        "uri": "html/dartium/nativewrappers.dart"
+      },
+      "mirrors": {
+        "patches": [
+          "_internal/vm/lib/mirrors_patch.dart",
+          "_internal/vm/lib/mirrors_impl.dart",
+          "_internal/vm/lib/mirror_reference.dart"
+        ],
+        "uri": "mirrors/mirrors.dart"
+      },
+      "developer": {
+        "patches": [
+          "_internal/vm/lib/developer.dart",
+          "_internal/vm/lib/profiler.dart",
+          "_internal/vm/lib/timeline.dart"
+        ],
+        "uri": "developer/developer.dart"
+      },
+      "isolate": {
+        "patches": [
+          "_internal/vm/lib/isolate_patch.dart",
+          "_internal/vm/lib/timer_impl.dart"
+        ],
+        "uri": "isolate/isolate.dart"
+      },
+      "_vmservice": {
+        "uri": "vmservice/vmservice.dart"
+      },
+      "wasm": {
+        "patches": [
+          "_internal/vm/lib/wasm_patch.dart"
+        ],
+        "uri": "wasm/wasm.dart"
+      },
+      "io": {
+        "patches": [
+          "_internal/vm/bin/common_patch.dart",
+          "_internal/vm/bin/directory_patch.dart",
+          "_internal/vm/bin/eventhandler_patch.dart",
+          "_internal/vm/bin/file_patch.dart",
+          "_internal/vm/bin/file_system_entity_patch.dart",
+          "_internal/vm/bin/filter_patch.dart",
+          "_internal/vm/bin/io_service_patch.dart",
+          "_internal/vm/bin/namespace_patch.dart",
+          "_internal/vm/bin/platform_patch.dart",
+          "_internal/vm/bin/process_patch.dart",
+          "_internal/vm/bin/socket_patch.dart",
+          "_internal/vm/bin/stdio_patch.dart",
+          "_internal/vm/bin/secure_socket_patch.dart",
+          "_internal/vm/bin/sync_socket_patch.dart"
+        ],
+        "uri": "io/io.dart"
+      },
+      "_internal": {
+        "patches": [
+          "_internal/vm/lib/internal_patch.dart",
+          "_internal/vm/lib/class_id_fasta.dart",
+          "_internal/vm/lib/print_patch.dart",
+          "_internal/vm/lib/symbol_patch.dart",
+          "internal/patch.dart"
+        ],
+        "uri": "internal/internal.dart"
+      },
+      "convert": {
+        "patches": "_internal/vm/lib/convert_patch.dart",
+        "uri": "convert/convert.dart"
+      },
+      "math": {
+        "patches": "_internal/vm/lib/math_patch.dart",
+        "uri": "math/math.dart"
+      },
+      "_http": {
+        "uri": "_http/http.dart"
+      },
+      "vmservice_io": {
+        "uri": "../../runtime/bin/vmservice/vmservice_io.dart"
+      }
+    }
+  },
+  "none": {
+    "libraries": {}
+  },
+  "dart2js": {
+    "libraries": {
+      "async": {
+        "patches": "_internal/js_runtime/lib/async_patch.dart",
+        "uri": "async/async.dart"
+      },
+      "_interceptors": {
+        "uri": "_internal/js_runtime/lib/interceptors.dart"
+      },
+      "mirrors": {
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false,
+        "uri": "mirrors/mirrors.dart"
+      },
+      "_js_embedded_names": {
+        "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+      },
+      "io": {
+        "patches": "_internal/js_runtime/lib/io_patch.dart",
+        "supported": false,
+        "uri": "io/io.dart"
+      },
+      "_internal": {
+        "patches": "_internal/js_runtime/lib/internal_patch.dart",
+        "uri": "internal/internal.dart"
+      },
+      "_metadata": {
+        "uri": "html/html_common/metadata.dart"
+      },
+      "_async_await_error_codes": {
+        "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+      },
+      "_http": {
+        "uri": "_http/http.dart"
+      },
+      "_js_primitives": {
+        "uri": "_internal/js_runtime/lib/js_primitives.dart"
+      },
+      "_js_helper": {
+        "uri": "_internal/js_runtime/lib/js_helper.dart"
+      },
+      "js": {
+        "uri": "js/dart2js/js_dart2js.dart"
+      },
+      "html_common": {
+        "uri": "html/html_common/html_common_dart2js.dart"
+      },
+      "_recipe_syntax": {
+        "uri": "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+      },
+      "_native_typed_data": {
+        "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+      },
+      "_js_names": {
+        "uri": "_internal/js_runtime/lib/js_names.dart"
+      },
+      "core": {
+        "patches": "_internal/js_runtime/lib/core_patch.dart",
+        "uri": "core/core.dart"
+      },
+      "collection": {
+        "patches": "_internal/js_runtime/lib/collection_patch.dart",
+        "uri": "collection/collection.dart"
+      },
+      "js_util": {
+        "uri": "js_util/dart2js/js_util_dart2js.dart"
+      },
+      "typed_data": {
+        "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
+        "uri": "typed_data/typed_data.dart"
+      },
+      "web_audio": {
+        "uri": "web_audio/dart2js/web_audio_dart2js.dart"
+      },
+      "html": {
+        "uri": "html/dart2js/html_dart2js.dart"
+      },
+      "isolate": {
+        "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+        "supported": false,
+        "uri": "isolate/isolate.dart"
+      },
+      "developer": {
+        "patches": "_internal/js_runtime/lib/developer_patch.dart",
+        "uri": "developer/developer.dart"
+      },
+      "web_gl": {
+        "uri": "web_gl/dart2js/web_gl_dart2js.dart"
+      },
+      "indexed_db": {
+        "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
+      },
+      "_js": {
+        "patches": "js/_js_client.dart",
+        "uri": "js/_js.dart"
+      },
+      "convert": {
+        "patches": "_internal/js_runtime/lib/convert_patch.dart",
+        "uri": "convert/convert.dart"
+      },
+      "math": {
+        "patches": "_internal/js_runtime/lib/math_patch.dart",
+        "uri": "math/math.dart"
+      },
+      "_foreign_helper": {
+        "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+      },
+      "web_sql": {
+        "uri": "web_sql/dart2js/web_sql_dart2js.dart"
+      },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      },
+      "svg": {
+        "uri": "svg/dart2js/svg_dart2js.dart"
+      }
+    }
+  },
+  "dartdevc": {
+    "libraries": {
+      "async": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart",
+        "uri": "../../sdk/lib/async/async.dart"
+      },
+      "_runtime": {
+        "uri": "../../sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
+      },
+      "_interceptors": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/interceptors.dart"
+      },
+      "mirrors": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart",
+        "supported": false,
+        "uri": "../../sdk/lib/mirrors/mirrors.dart"
+      },
+      "_debugger": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/debugger.dart"
+      },
+      "io": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart",
+        "supported": false,
+        "uri": "../../sdk/lib/io/io.dart"
+      },
+      "_internal": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart",
+        "uri": "../../sdk/lib/internal/internal.dart"
+      },
+      "_metadata": {
+        "uri": "../../sdk/lib/html/html_common/metadata.dart"
+      },
+      "_http": {
+        "uri": "../../sdk/lib/_http/http.dart"
+      },
+      "_js_primitives": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart"
+      },
+      "_js_helper": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_helper.dart"
+      },
+      "js": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
+      },
+      "_js_mirrors": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart"
+      },
+      "html_common": {
+        "uri": "../../sdk/lib/html/html_common/html_common_dart2js.dart"
+      },
+      "_native_typed_data": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart"
+      },
+      "core": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart",
+        "uri": "../../sdk/lib/core/core.dart"
+      },
+      "js_util": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+      },
+      "collection": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart",
+        "uri": "../../sdk/lib/collection/collection.dart"
+      },
+      "typed_data": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart",
+        "uri": "../../sdk/lib/typed_data/typed_data.dart"
+      },
+      "web_audio": {
+        "uri": "../../sdk/lib/web_audio/dart2js/web_audio_dart2js.dart"
+      },
+      "html": {
+        "uri": "../../sdk/lib/html/dart2js/html_dart2js.dart"
+      },
+      "developer": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart",
+        "uri": "../../sdk/lib/developer/developer.dart"
+      },
+      "isolate": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart",
+        "supported": false,
+        "uri": "../../sdk/lib/isolate/isolate.dart"
+      },
+      "web_gl": {
+        "uri": "../../sdk/lib/web_gl/dart2js/web_gl_dart2js.dart"
+      },
+      "indexed_db": {
+        "uri": "../../sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart"
+      },
+      "convert": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart",
+        "uri": "../../sdk/lib/convert/convert.dart"
+      },
+      "_isolate_helper": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart"
+      },
+      "math": {
+        "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart",
+        "uri": "../../sdk/lib/math/math.dart"
+      },
+      "_foreign_helper": {
+        "uri": "../../sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart"
+      },
+      "web_sql": {
+        "uri": "../../sdk/lib/web_sql/dart2js/web_sql_dart2js.dart"
+      },
+      "svg": {
+        "uri": "../../sdk/lib/svg/dart2js/svg_dart2js.dart"
+      }
+    }
+  },
+  "dart2js_server": {
+    "libraries": {
+      "async": {
+        "patches": "_internal/js_runtime/lib/async_patch.dart",
+        "uri": "async/async.dart"
+      },
+      "mirrors": {
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false,
+        "uri": "mirrors/mirrors.dart"
+      },
+      "_interceptors": {
+        "uri": "_internal/js_runtime/lib/interceptors.dart"
+      },
+      "_js_embedded_names": {
+        "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+      },
+      "io": {
+        "patches": "_internal/js_runtime/lib/io_patch.dart",
+        "supported": false,
+        "uri": "io/io.dart"
+      },
+      "_internal": {
+        "patches": "_internal/js_runtime/lib/internal_patch.dart",
+        "uri": "internal/internal.dart"
+      },
+      "_async_await_error_codes": {
+        "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+      },
+      "_http": {
+        "uri": "_http/http.dart"
+      },
+      "_js_helper": {
+        "uri": "_internal/js_runtime/lib/js_helper.dart"
+      },
+      "_js_primitives": {
+        "uri": "_internal/js_runtime/lib/js_primitives.dart"
+      },
+      "js": {
+        "uri": "js/dart2js/js_dart2js.dart"
+      },
+      "_recipe_syntax": {
+        "uri": "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+      },
+      "_native_typed_data": {
+        "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+      },
+      "core": {
+        "patches": "_internal/js_runtime/lib/core_patch.dart",
+        "uri": "core/core.dart"
+      },
+      "_js_names": {
+        "uri": "_internal/js_runtime/lib/js_names.dart"
+      },
+      "js_util": {
+        "uri": "js_util/dart2js/js_util_dart2js.dart"
+      },
+      "collection": {
+        "patches": "_internal/js_runtime/lib/collection_patch.dart",
+        "uri": "collection/collection.dart"
+      },
+      "typed_data": {
+        "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
+        "uri": "typed_data/typed_data.dart"
+      },
+      "isolate": {
+        "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+        "supported": false,
+        "uri": "isolate/isolate.dart"
+      },
+      "developer": {
+        "patches": "_internal/js_runtime/lib/developer_patch.dart",
+        "uri": "developer/developer.dart"
+      },
+      "_js": {
+        "patches": "js/_js_server.dart",
+        "uri": "js/_js.dart"
+      },
+      "convert": {
+        "patches": "_internal/js_runtime/lib/convert_patch.dart",
+        "uri": "convert/convert.dart"
+      },
+      "math": {
+        "patches": "_internal/js_runtime/lib/math_patch.dart",
+        "uri": "math/math.dart"
+      },
+      "_foreign_helper": {
+        "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+      },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/sdk_nnbd/lib/math/jenkins_smi_hash.dart b/sdk_nnbd/lib/math/jenkins_smi_hash.dart
index 0cc69b0..deca56c 100644
--- a/sdk_nnbd/lib/math/jenkins_smi_hash.dart
+++ b/sdk_nnbd/lib/math/jenkins_smi_hash.dart
@@ -1,7 +1,6 @@
 // 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.5
 
 part of dart.math;
 
@@ -34,8 +33,8 @@
     return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
   }
 
-  static int hash2(a, b) => finish(combine(combine(0, a), b));
+  static int hash2(int a, int b) => finish(combine(combine(0, a), b));
 
-  static int hash4(a, b, c, d) =>
+  static int hash4(int a, int b, int c, int d) =>
       finish(combine(combine(combine(combine(0, a), b), c), d));
 }
diff --git a/sdk_nnbd/lib/math/math.dart b/sdk_nnbd/lib/math/math.dart
index 16583df..548fb59 100644
--- a/sdk_nnbd/lib/math/math.dart
+++ b/sdk_nnbd/lib/math/math.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.5
-
 /// Mathematical constants and functions, plus a random number generator.
 ///
 /// To use this library in your code:
diff --git a/sdk_nnbd/lib/math/point.dart b/sdk_nnbd/lib/math/point.dart
index a7c91f6..4b0fed5 100644
--- a/sdk_nnbd/lib/math/point.dart
+++ b/sdk_nnbd/lib/math/point.dart
@@ -1,7 +1,6 @@
 // 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.5
 
 part of dart.math;
 
@@ -16,14 +15,12 @@
 
   String toString() => 'Point($x, $y)';
 
-  /// A `Point` is only equal to another `Point` with the same coordinates.
+  /// Whether [other] is a point with the same coordinates as this point.
   ///
-  /// This point is equal to `other` if, and only if,
-  /// `other` is a `Point` with
-  /// [x] equal to `other.x` and [y] equal to `other.y`.
-  bool operator ==(dynamic other) =>
-      // Cannot change parameter type to `Object` in case some class
-      // inherits the type and uses their argument dynamically.
+  /// Returns `true` if [other] is a [Point] with [x] and [y]
+  /// coordinates equal to the corresponding coordiantes of this point,
+  /// and `false` otherwise.
+  bool operator ==(Object other) =>
       other is Point && x == other.x && y == other.y;
 
   int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode);
@@ -32,25 +29,25 @@
   ///
   /// Returns the resulting "vector" as a Point.
   Point<T> operator +(Point<T> other) {
-    return Point<T>(x + other.x, y + other.y);
+    return Point<T>((x + other.x) as T, (y + other.y) as T);
   }
 
   /// Subtract [other] from `this`, as if both points were vectors.
   ///
   /// Returns the resulting "vector" as a Point.
   Point<T> operator -(Point<T> other) {
-    return Point<T>(x - other.x, y - other.y);
+    return Point<T>((x - other.x) as T, (y - other.y) as T);
   }
 
   /// Scale this point by [factor] as if it were a vector.
   ///
   /// *Important* *Note*: This function accepts a `num` as its argument only so
-  /// that you can scale Point<double> objects by an `int` factor. Because the
-  /// star operator always returns the same type of Point that originally called
-  /// it, passing in a double [factor] on a `Point<int>` _causes_ _a_
-  /// _runtime_ _error_ in checked mode.
+  /// that you can scale `Point<double>` objects by an `int` factor. Because the
+  /// `*` operator always returns the same type of `Point` as it is called on,
+  /// passing in a double [factor] on a `Point<int>` _causes_ _a_
+  /// _runtime_ _error_.
   Point<T> operator *(num /*T|int*/ factor) {
-    return Point<T>((x * factor), (y * factor));
+    return Point<T>((x * factor) as T, (y * factor) as T);
   }
 
   /// Get the straight line (Euclidean) distance between the origin (0, 0) and
@@ -71,6 +68,6 @@
   T squaredDistanceTo(Point<T> other) {
     var dx = x - other.x;
     var dy = y - other.y;
-    return dx * dx + dy * dy;
+    return (dx * dx + dy * dy) as T;
   }
 }
diff --git a/sdk_nnbd/lib/math/random.dart b/sdk_nnbd/lib/math/random.dart
index de7d36c..fd75e12 100644
--- a/sdk_nnbd/lib/math/random.dart
+++ b/sdk_nnbd/lib/math/random.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.5
-
 part of dart.math;
 
 /// A generator of random bool, int, or double values.
@@ -18,7 +16,7 @@
   /// The optional parameter [seed] is used to initialize the
   /// internal state of the generator. The implementation of the
   /// random stream can change between releases of the library.
-  external factory Random([int seed]);
+  external factory Random([int? seed]);
 
   /// Creates a cryptographically secure random number generator.
   ///
diff --git a/sdk_nnbd/lib/math/rectangle.dart b/sdk_nnbd/lib/math/rectangle.dart
index 0c14d42..09f27df 100644
--- a/sdk_nnbd/lib/math/rectangle.dart
+++ b/sdk_nnbd/lib/math/rectangle.dart
@@ -1,7 +1,6 @@
 // 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.5
 
 part of dart.math;
 
@@ -33,18 +32,16 @@
   T get height;
 
   /// The x-coordinate of the right edge.
-  T get right => left + width;
+  T get right => (left + width) as T;
 
   /// The y-coordinate of the bottom edge.
-  T get bottom => top + height;
+  T get bottom => (top + height) as T;
 
   String toString() {
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(dynamic other) =>
-      // Can't change argument type to `Object` since subclasses inherit it
-      // and uses their argument dynamically.
+  bool operator ==(Object other) =>
       other is Rectangle &&
       left == other.left &&
       top == other.top &&
@@ -61,7 +58,7 @@
   ///
   /// Returns the intersection of this and `other`, or `null` if they don't
   /// intersect.
-  Rectangle<T> intersection(Rectangle<T> other) {
+  Rectangle<T>? intersection(Rectangle<T> other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
@@ -70,7 +67,7 @@
       var y1 = min(top + height, other.top + other.height);
 
       if (y0 <= y1) {
-        return Rectangle<T>(x0, y0, x1 - x0, y1 - y0);
+        return Rectangle<T>(x0, y0, (x1 - x0) as T, (y1 - y0) as T);
       }
     }
     return null;
@@ -92,7 +89,7 @@
     var left = min(this.left, other.left);
     var top = min(this.top, other.top);
 
-    return Rectangle<T>(left, top, right - left, bottom - top);
+    return Rectangle<T>(left, top, (right - left) as T, (bottom - top) as T);
   }
 
   /// Tests whether `this` entirely contains [another].
@@ -112,10 +109,10 @@
   }
 
   Point<T> get topLeft => Point<T>(this.left, this.top);
-  Point<T> get topRight => Point<T>(this.left + this.width, this.top);
+  Point<T> get topRight => Point<T>((this.left + this.width) as T, this.top);
   Point<T> get bottomRight =>
-      Point<T>(this.left + this.width, this.top + this.height);
-  Point<T> get bottomLeft => Point<T>(this.left, this.top + this.height);
+      Point<T>((this.left + this.width) as T, (this.top + this.height) as T);
+  Point<T> get bottomLeft => Point<T>(this.left, (this.top + this.height) as T);
 }
 
 /// A class for representing two-dimensional rectangles whose properties are
@@ -139,8 +136,8 @@
   /// If `width` and `height` are zero, the "rectangle" comprises only the
   /// single point `(left, top)`.
   const Rectangle(this.left, this.top, T width, T height)
-      : this.width = (width < 0) ? -width * 0 : width, // Inline _clampToZero.
-        this.height = (height < 0) ? -height * 0 : height;
+      : width = (width < 0) ? (-width * 0) as dynamic : width, // Inline _clampToZero<num>.
+        height = (height < 0) ? (-height * 0) as dynamic : height;
 
   /// Create a rectangle spanned by the points [a] and [b];
   ///
@@ -154,9 +151,9 @@
   /// Similar for the y-coordinates and the bottom edge.
   factory Rectangle.fromPoints(Point<T> a, Point<T> b) {
     T left = min(a.x, b.x);
-    T width = max(a.x, b.x) - left;
+    T width = (max(a.x, b.x) - left) as T;
     T top = min(a.y, b.y);
-    T height = max(a.y, b.y) - top;
+    T height = (max(a.y, b.y) - top) as T;
     return Rectangle<T>(left, top, width, height);
   }
 }
@@ -205,9 +202,9 @@
   /// Similar for the y-coordinates and the bottom edge.
   factory MutableRectangle.fromPoints(Point<T> a, Point<T> b) {
     T left = min(a.x, b.x);
-    T width = max(a.x, b.x) - left;
+    T width = (max(a.x, b.x) - left) as T;
     T top = min(a.y, b.y);
-    T height = max(a.y, b.y) - top;
+    T height = (max(a.y, b.y) - top) as T;
     return MutableRectangle<T>(left, top, width, height);
   }
 
@@ -245,5 +242,5 @@
 /// Returns `0` if value is int, `0.0` if value is double.
 T _clampToZero<T extends num>(T value) {
   assert(value < 0);
-  return -value * 0;
+  return (-value * 0) as T;
 }
diff --git a/sdk_nnbd/lib/typed_data/typed_data.dart b/sdk_nnbd/lib/typed_data/typed_data.dart
index a5e37bd..66410cb 100644
--- a/sdk_nnbd/lib/typed_data/typed_data.dart
+++ b/sdk_nnbd/lib/typed_data/typed_data.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.5
-
 /// Lists that efficiently handle fixed sized data
 /// (for example, unsigned 8 byte integers) and SIMD numeric types.
 ///
@@ -46,7 +44,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length` must not be greater than [lengthInBytes].
    */
-  Uint8List asUint8List([int offsetInBytes = 0, int length]);
+  Uint8List asUint8List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Int8List] _view_ of a region of this byte buffer.
@@ -64,7 +62,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length` must not be greater than [lengthInBytes].
    */
-  Int8List asInt8List([int offsetInBytes = 0, int length]);
+  Int8List asInt8List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Uint8ClampedList] _view_ of a region of this byte buffer.
@@ -82,7 +80,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length` must not be greater than [lengthInBytes].
    */
-  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]);
+  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Uint16List] _view_ of a region of this byte buffer.
@@ -105,7 +103,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
    */
-  Uint16List asUint16List([int offsetInBytes = 0, int length]);
+  Uint16List asUint16List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Int16List] _view_ of a region of this byte buffer.
@@ -128,7 +126,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 2` must not be greater than [lengthInBytes].
    */
-  Int16List asInt16List([int offsetInBytes = 0, int length]);
+  Int16List asInt16List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Uint32List] _view_ of a region of this byte buffer.
@@ -152,7 +150,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
    */
-  Uint32List asUint32List([int offsetInBytes = 0, int length]);
+  Uint32List asUint32List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Int32List] _view_ of a region of this byte buffer.
@@ -176,7 +174,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
    */
-  Int32List asInt32List([int offsetInBytes = 0, int length]);
+  Int32List asInt32List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Uint64List] _view_ of a region of this byte buffer.
@@ -200,7 +198,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
    */
-  Uint64List asUint64List([int offsetInBytes = 0, int length]);
+  Uint64List asUint64List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Int64List] _view_ of a region of this byte buffer.
@@ -224,7 +222,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
    */
-  Int64List asInt64List([int offsetInBytes = 0, int length]);
+  Int64List asInt64List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Int32x4List] _view_ of a region of this byte buffer.
@@ -248,7 +246,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
    */
-  Int32x4List asInt32x4List([int offsetInBytes = 0, int length]);
+  Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Float32List] _view_ of a region of this byte buffer.
@@ -272,7 +270,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 4` must not be greater than [lengthInBytes].
    */
-  Float32List asFloat32List([int offsetInBytes = 0, int length]);
+  Float32List asFloat32List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Float64List] _view_ of a region of this byte buffer.
@@ -296,7 +294,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 8` must not be greater than [lengthInBytes].
    */
-  Float64List asFloat64List([int offsetInBytes = 0, int length]);
+  Float64List asFloat64List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Float32x4List] _view_ of a region of this byte buffer.
@@ -320,7 +318,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
    */
-  Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]);
+  Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [Float64x2List] _view_ of a region of this byte buffer.
@@ -344,7 +342,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length * 16` must not be greater than [lengthInBytes].
    */
-  Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]);
+  Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]);
 
   /**
    * Creates a [ByteData] _view_ of a region of this byte buffer.
@@ -362,7 +360,7 @@
    * * `length` must not be negative, and
    * * `offsetInBytes + length` must not be greater than [lengthInBytes].
    */
-  ByteData asByteData([int offsetInBytes = 0, int length]);
+  ByteData asByteData([int offsetInBytes = 0, int? length]);
 }
 
 /**
@@ -475,7 +473,7 @@
    * the length of [buffer].
    */
   factory ByteData.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asByteData(offsetInBytes, length);
   }
 
@@ -770,7 +768,7 @@
    * the length of [buffer].
    */
   factory Int8List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asInt8List(offsetInBytes, length);
   }
 
@@ -797,7 +795,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Int8List sublist(int start, [int end]);
+  Int8List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
@@ -843,7 +841,7 @@
    * the length of [buffer].
    */
   factory Uint8List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asUint8List(offsetInBytes, length);
   }
 
@@ -879,7 +877,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Uint8List sublist(int start, [int end]);
+  Uint8List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
@@ -926,7 +924,7 @@
    * the length of [buffer].
    */
   factory Uint8ClampedList.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asUint8ClampedList(offsetInBytes, length);
   }
 
@@ -953,7 +951,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Uint8ClampedList sublist(int start, [int end]);
+  Uint8ClampedList sublist(int start, [int? end]);
 
   static const int bytesPerElement = 1;
 }
@@ -1003,7 +1001,7 @@
    * [bytesPerElement].
    */
   factory Int16List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asInt16List(offsetInBytes, length);
   }
 
@@ -1030,7 +1028,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Int16List sublist(int start, [int end]);
+  Int16List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 2;
 }
@@ -1081,7 +1079,7 @@
    * [bytesPerElement].
    */
   factory Uint16List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asUint16List(offsetInBytes, length);
   }
 
@@ -1108,7 +1106,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Uint16List sublist(int start, [int end]);
+  Uint16List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 2;
 }
@@ -1158,7 +1156,7 @@
    * [bytesPerElement].
    */
   factory Int32List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asInt32List(offsetInBytes, length);
   }
 
@@ -1185,7 +1183,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Int32List sublist(int start, [int end]);
+  Int32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
@@ -1236,7 +1234,7 @@
    * [bytesPerElement].
    */
   factory Uint32List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asUint32List(offsetInBytes, length);
   }
 
@@ -1263,7 +1261,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Uint32List sublist(int start, [int end]);
+  Uint32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
@@ -1313,7 +1311,7 @@
    * [bytesPerElement].
    */
   factory Int64List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asInt64List(offsetInBytes, length);
   }
 
@@ -1340,7 +1338,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Int64List sublist(int start, [int end]);
+  Int64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
@@ -1391,7 +1389,7 @@
    * [bytesPerElement].
    */
   factory Uint64List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asUint64List(offsetInBytes, length);
   }
 
@@ -1418,7 +1416,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Uint64List sublist(int start, [int end]);
+  Uint64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
@@ -1469,7 +1467,7 @@
    * [bytesPerElement].
    */
   factory Float32List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat32List(offsetInBytes, length);
   }
 
@@ -1496,7 +1494,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Float32List sublist(int start, [int end]);
+  Float32List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 4;
 }
@@ -1540,7 +1538,7 @@
    * [bytesPerElement].
    */
   factory Float64List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat64List(offsetInBytes, length);
   }
 
@@ -1567,7 +1565,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Float64List sublist(int start, [int end]);
+  Float64List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 8;
 }
@@ -1610,7 +1608,7 @@
    * [bytesPerElement].
    */
   factory Float32x4List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat32x4List(offsetInBytes, length);
   }
 
@@ -1645,7 +1643,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Float32x4List sublist(int start, [int end]);
+  Float32x4List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
@@ -1688,7 +1686,7 @@
    * [bytesPerElement].
    */
   factory Int32x4List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asInt32x4List(offsetInBytes, length);
   }
 
@@ -1723,7 +1721,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Int32x4List sublist(int start, [int end]);
+  Int32x4List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
@@ -1774,7 +1772,7 @@
    * [bytesPerElement].
    */
   factory Float64x2List.view(ByteBuffer buffer,
-      [int offsetInBytes = 0, int length]) {
+      [int offsetInBytes = 0, int? length]) {
     return buffer.asFloat64x2List(offsetInBytes, length);
   }
 
@@ -1801,7 +1799,7 @@
    * 0 ≤ `start` ≤ `end` ≤ `this.length`
    * If `end` is equal to `start`, then the returned list is empty.
    */
-  Float64x2List sublist(int start, [int end]);
+  Float64x2List sublist(int start, [int? end]);
 
   static const int bytesPerElement = 16;
 }
diff --git a/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart b/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart
index f3def8f..30bdf51 100644
--- a/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.dart
+++ b/sdk_nnbd/lib/typed_data/unmodifiable_typed_data.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.5
-
 part of dart.typed_data;
 
 /**
@@ -16,55 +14,55 @@
 
   int get lengthInBytes => _data.lengthInBytes;
 
-  Uint8List asUint8List([int offsetInBytes = 0, int length]) =>
+  Uint8List asUint8List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableUint8ListView(_data.asUint8List(offsetInBytes, length));
 
-  Int8List asInt8List([int offsetInBytes = 0, int length]) =>
+  Int8List asInt8List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableInt8ListView(_data.asInt8List(offsetInBytes, length));
 
-  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) =>
+  Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableUint8ClampedListView(
           _data.asUint8ClampedList(offsetInBytes, length));
 
-  Uint16List asUint16List([int offsetInBytes = 0, int length]) =>
+  Uint16List asUint16List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableUint16ListView(_data.asUint16List(offsetInBytes, length));
 
-  Int16List asInt16List([int offsetInBytes = 0, int length]) =>
+  Int16List asInt16List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableInt16ListView(_data.asInt16List(offsetInBytes, length));
 
-  Uint32List asUint32List([int offsetInBytes = 0, int length]) =>
+  Uint32List asUint32List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableUint32ListView(_data.asUint32List(offsetInBytes, length));
 
-  Int32List asInt32List([int offsetInBytes = 0, int length]) =>
+  Int32List asInt32List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableInt32ListView(_data.asInt32List(offsetInBytes, length));
 
-  Uint64List asUint64List([int offsetInBytes = 0, int length]) =>
+  Uint64List asUint64List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableUint64ListView(_data.asUint64List(offsetInBytes, length));
 
-  Int64List asInt64List([int offsetInBytes = 0, int length]) =>
+  Int64List asInt64List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableInt64ListView(_data.asInt64List(offsetInBytes, length));
 
-  Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) =>
+  Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableInt32x4ListView(
           _data.asInt32x4List(offsetInBytes, length));
 
-  Float32List asFloat32List([int offsetInBytes = 0, int length]) =>
+  Float32List asFloat32List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableFloat32ListView(
           _data.asFloat32List(offsetInBytes, length));
 
-  Float64List asFloat64List([int offsetInBytes = 0, int length]) =>
+  Float64List asFloat64List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableFloat64ListView(
           _data.asFloat64List(offsetInBytes, length));
 
-  Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) =>
+  Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableFloat32x4ListView(
           _data.asFloat32x4List(offsetInBytes, length));
 
-  Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) =>
+  Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableFloat64x2ListView(
           _data.asFloat64x2List(offsetInBytes, length));
 
-  ByteData asByteData([int offsetInBytes = 0, int length]) =>
+  ByteData asByteData([int offsetInBytes = 0, int? length]) =>
       new UnmodifiableByteDataView(_data.asByteData(offsetInBytes, length));
 }
 
@@ -165,9 +163,10 @@
 
   L _createList(int length);
 
-  L sublist(int start, [int end]) {
-    end = RangeError.checkValidRange(start, end, length);
-    int sublistLength = end - start;
+  L sublist(int start, [int? end]) {
+    // NNBD: Spurious error at `end`, `checkValidRange` is legacy.
+    int endIndex = RangeError.checkValidRange(start, end!, length);
+    int sublistLength = endIndex - start;
     L result = _createList(sublistLength);
     result.setRange(0, sublistLength, _list, start);
     return result;
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index e6024bc..2511212 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -178,17 +178,6 @@
 LanguageFeatures/regression/34803_t01: Crash
 LanguageFeatures/regression/34803_t02: Crash
 
-[ $arch == simdbc64 && $compiler == dartk ]
-LibTest/collection/ListBase/ListBase_class_A01_t02: Crash # Issue http://dartbug.com/35242
-LibTest/collection/ListMixin/ListMixin_class_A01_t02: Crash # Issue http://dartbug.com/35242
-LibTest/core/List/List_class_A01_t02: Crash # Issue http://dartbug.com/35242
-
-[ $arch == simdbc64 && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
-LanguageFeatures/Subtyping/static/generated/function_type_function_arguments_binding_A04_t02: Crash
-
-[ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
-LibTest/isolate/Isolate/removeErrorListener_A02_t01: Crash
-
 [ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
 LibTest/isolate/Isolate/spawn_A06_t03: Crash
 
@@ -212,5 +201,5 @@
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
 # These Isolate tests that use spawnURI are hence skipped on purpose.
-[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
+[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ]
 LibTest/isolate/Isolate/spawnUri*: Skip
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index 91e687c..041f245 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io' hide Link;
+import 'package:_fe_analyzer_shared/src/util/link.dart' show Link;
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/common.dart';
@@ -14,7 +15,6 @@
 import 'package:compiler/src/js_model/locals.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
-import 'package:front_end/src/fasta/util/link.dart' show Link;
 import 'package:front_end/src/testing/features.dart';
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
diff --git a/tests/compiler/dart2js/equivalence/check_helpers.dart b/tests/compiler/dart2js/equivalence/check_helpers.dart
index dd61237..ee1aa14 100644
--- a/tests/compiler/dart2js/equivalence/check_helpers.dart
+++ b/tests/compiler/dart2js/equivalence/check_helpers.dart
@@ -446,6 +446,11 @@
   }
 
   @override
+  visitErasedType(ErasedType type, _) {
+    sb.write('erased');
+  }
+
+  @override
   visitAnyType(AnyType type, _) {
     sb.write('any');
   }
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index c815fb2..a78c587 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.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 'package:_fe_analyzer_shared/src/testing/id.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/ir/util.dart';
 import 'package:compiler/src/js_model/locals.dart';
 import 'package:expect/expect.dart';
 import 'package:kernel/ast.dart' as ir;
-import 'package:front_end/src/testing/id.dart';
 import 'package:front_end/src/testing/id_extractor.dart';
 
-export 'package:front_end/src/testing/id.dart';
+export 'package:_fe_analyzer_shared/src/testing/id.dart';
 export 'package:front_end/src/testing/id_extractor.dart';
 
 SourceSpan computeSourceSpanFromUriOffset(Uri uri, int offset) {
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 4455bf5..1da2f67 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/common_elements.dart';
@@ -14,13 +15,12 @@
 import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
 import 'package:expect/expect.dart';
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:kernel/ast.dart' as ir;
 
 import '../helpers/memory_compiler.dart';
 import '../equivalence/id_equivalence.dart';
 
-export 'package:front_end/src/testing/id_testing.dart'
+export 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
     show DataInterpreter, StringDataInterpreter;
 export '../helpers/memory_compiler.dart' show CollectedMessage;
 
diff --git a/tests/compiler/dart2js/equivalence/id_testing_test.dart b/tests/compiler/dart2js/equivalence/id_testing_test.dart
index c40ff6f..0773b2c 100644
--- a/tests/compiler/dart2js/equivalence/id_testing_test.dart
+++ b/tests/compiler/dart2js/equivalence/id_testing_test.dart
@@ -3,13 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:front_end/src/testing/id_testing_utils.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
diff --git a/tests/compiler/dart2js/equivalence/show_helper.dart b/tests/compiler/dart2js/equivalence/show_helper.dart
index c89194b..0942501 100644
--- a/tests/compiler/dart2js/equivalence/show_helper.dart
+++ b/tests/compiler/dart2js/equivalence/show_helper.dart
@@ -5,12 +5,12 @@
 /// Helper program that shows the equivalence-based data on a dart program.
 
 import 'dart:io';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:args/args.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/filenames.dart';
 import 'package:compiler/src/io/source_file.dart';
 import 'package:compiler/src/source_file_provider.dart';
-import 'package:front_end/src/testing/id_testing.dart';
 import 'id_equivalence_helper.dart';
 
 ArgParser createArgParser() {
diff --git a/tests/compiler/dart2js/helpers/compiler_helper.dart b/tests/compiler/dart2js/helpers/compiler_helper.dart
index 215609c..2180d4c 100644
--- a/tests/compiler/dart2js/helpers/compiler_helper.dart
+++ b/tests/compiler/dart2js/helpers/compiler_helper.dart
@@ -13,7 +13,7 @@
 import 'package:compiler/src/js_model/js_strategy.dart';
 import 'package:compiler/src/world.dart';
 import 'package:expect/expect.dart';
-import 'package:front_end/src/fasta/util/link.dart' show Link;
+import 'package:_fe_analyzer_shared/src/util/link.dart' show Link;
 import 'memory_compiler.dart';
 import 'output_collector.dart';
 
diff --git a/tests/compiler/dart2js/helpers/ir_types.dart b/tests/compiler/dart2js/helpers/ir_types.dart
index cd18f77..64f44a4 100644
--- a/tests/compiler/dart2js/helpers/ir_types.dart
+++ b/tests/compiler/dart2js/helpers/ir_types.dart
@@ -105,6 +105,11 @@
   }
 
   @override
+  void visitNeverType(ir.NeverType node, StringBuffer sb) {
+    sb.write('Never');
+  }
+
+  @override
   void visitVoidType(ir.VoidType node, StringBuffer sb) {
     sb.write('void');
   }
diff --git a/tests/compiler/dart2js/helpers/link_helper.dart b/tests/compiler/dart2js/helpers/link_helper.dart
index 00e82ae..53d20d4 100644
--- a/tests/compiler/dart2js/helpers/link_helper.dart
+++ b/tests/compiler/dart2js/helpers/link_helper.dart
@@ -4,8 +4,8 @@
 
 library link_helper;
 
-import 'package:front_end/src/fasta/util/link.dart';
-import 'package:front_end/src/fasta/util/link_implementation.dart';
+import 'package:_fe_analyzer_shared/src/util/link.dart';
+import 'package:_fe_analyzer_shared/src/util/link_implementation.dart';
 
 Link LinkFromList(List list) {
   switch (list.length) {
diff --git a/tests/compiler/dart2js/helpers/type_test_helper.dart b/tests/compiler/dart2js/helpers/type_test_helper.dart
index 3e38e24..77656fc 100644
--- a/tests/compiler/dart2js/helpers/type_test_helper.dart
+++ b/tests/compiler/dart2js/helpers/type_test_helper.dart
@@ -112,10 +112,10 @@
 
   DartType operator [](String name) {
     if (name == 'dynamic') {
-      return const DynamicType();
+      return DynamicType();
     }
     if (name == 'void') {
-      return const VoidType();
+      return VoidType();
     }
     return getElementType(name);
   }
diff --git a/tests/compiler/dart2js/model/cfe_constant_test.dart b/tests/compiler/dart2js/model/cfe_constant_test.dart
index d62662b..a6ff5a0 100644
--- a/tests/compiler/dart2js/model/cfe_constant_test.dart
+++ b/tests/compiler/dart2js/model/cfe_constant_test.dart
@@ -3,13 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
+import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
-import 'package:front_end/src/testing/id_testing.dart';
 import 'package:kernel/ast.dart' as ir;
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
@@ -22,7 +22,7 @@
 main(List<String> args) {
   asyncTest(() async {
     Directory dataDir = new Directory.fromUri(Platform.script
-        .resolve('../../../../pkg/front_end/test/constants/data'));
+        .resolve('../../../../pkg/_fe_analyzer_shared/test/constants/data'));
     await checkTests(dataDir, new ConstantDataComputer(),
         args: args,
         testedConfigs: [sharedConfig],
diff --git a/tests/compiler/dart2js/model/link_test.dart b/tests/compiler/dart2js/model/link_test.dart
index 85ea006..9b2b00e 100644
--- a/tests/compiler/dart2js/model/link_test.dart
+++ b/tests/compiler/dart2js/model/link_test.dart
@@ -2,8 +2,8 @@
 // for 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/util/link.dart' show Link;
 import "package:expect/expect.dart";
-import 'package:front_end/src/fasta/util/link.dart' show Link;
 import '../helpers/link_helper.dart';
 
 main() {
diff --git a/tests/compiler/dart2js/model/type_substitution_test.dart b/tests/compiler/dart2js/model/type_substitution_test.dart
index 50cc055..35730ab 100644
--- a/tests/compiler/dart2js/model/type_substitution_test.dart
+++ b/tests/compiler/dart2js/model/type_substitution_test.dart
@@ -146,10 +146,10 @@
   List<DartType> parameters = <DartType>[T, S];
   List<DartType> arguments = <DartType>[intType, StringType];
 
-  testSubstitution(env.elementEnvironment, arguments, parameters,
-      const VoidType(), const VoidType());
-  testSubstitution(env.elementEnvironment, arguments, parameters,
-      const DynamicType(), const DynamicType());
+  testSubstitution(
+      env.elementEnvironment, arguments, parameters, VoidType(), VoidType());
+  testSubstitution(env.elementEnvironment, arguments, parameters, DynamicType(),
+      DynamicType());
   testSubstitution(
       env.elementEnvironment, arguments, parameters, intType, intType);
   testSubstitution(
@@ -174,8 +174,8 @@
       env.elementEnvironment,
       arguments,
       parameters,
-      instantiate(ListClass, [const DynamicType()]),
-      instantiate(ListClass, [const DynamicType()]));
+      instantiate(ListClass, [DynamicType()]),
+      instantiate(ListClass, [DynamicType()]));
   testSubstitution(
       env.elementEnvironment,
       arguments,
@@ -192,8 +192,8 @@
       env.elementEnvironment,
       arguments,
       parameters,
-      instantiate(MapClass, [const DynamicType(), StringType]),
-      instantiate(MapClass, [const DynamicType(), StringType]));
+      instantiate(MapClass, [DynamicType(), StringType]),
+      instantiate(MapClass, [DynamicType(), StringType]));
   testSubstitution(env.elementEnvironment, arguments, parameters, T, intType);
   testSubstitution(
       env.elementEnvironment, arguments, parameters, S, StringType);
@@ -207,14 +207,12 @@
       env.elementEnvironment,
       arguments,
       parameters,
-      new FunctionType(const VoidType(), [T, S], [], [], [], []),
-      new FunctionType(
-          const VoidType(), [intType, StringType], [], [], [], []));
+      new FunctionType(VoidType(), [T, S], [], [], [], []),
+      new FunctionType(VoidType(), [intType, StringType], [], [], [], []));
   testSubstitution(
       env.elementEnvironment,
       arguments,
       parameters,
-      new FunctionType(const VoidType(), [const DynamicType()], [], [], [], []),
-      new FunctionType(
-          const VoidType(), [const DynamicType()], [], [], [], []));
+      new FunctionType(VoidType(), [DynamicType()], [], [], [], []),
+      new FunctionType(VoidType(), [DynamicType()], [], [], [], []));
 }
diff --git a/tests/compiler/dart2js/sourcemaps/mapping_test.dart b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
index a534142..25920a7 100644
--- a/tests/compiler/dart2js/sourcemaps/mapping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/mapping_test.dart
@@ -5,11 +5,11 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
 import 'package:expect/expect.dart';
 import 'package:source_maps/source_maps.dart';
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 
 import '../helpers/memory_compiler.dart';
 
diff --git a/tests/compiler/dart2js/sourcemaps/stepping_test.dart b/tests/compiler/dart2js/sourcemaps/stepping_test.dart
index e37bf06..e1688e1 100644
--- a/tests/compiler/dart2js/sourcemaps/stepping_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stepping_test.dart
@@ -5,13 +5,13 @@
 import 'dart:async';
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
 import 'package:args/args.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/dart2js.dart' as entry;
 import 'package:expect/expect.dart';
-import 'package:front_end/src/testing/annotated_code_helper.dart';
 import 'package:sourcemap_testing/src/stepping_helper.dart';
 
 void main(List<String> args) {
diff --git a/tests/compiler/dart2js/static_type/type_promotion_data/sequence.dart b/tests/compiler/dart2js/static_type/type_promotion_data/sequence.dart
new file mode 100644
index 0000000..71cc004
--- /dev/null
+++ b/tests/compiler/dart2js/static_type/type_promotion_data/sequence.dart
@@ -0,0 +1,29 @@
+// 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.
+
+class A {}
+
+class B {}
+
+class C {}
+
+class D {}
+
+main() {
+  ifThenElseSequence(null);
+}
+
+ifThenElseSequence(dynamic o) {
+  if (/*{}*/ o is A) {
+    /*{o:[{true:A}|A]}*/ o;
+  } else if (/*{o:[{false:A}|A]}*/ o is B) {
+    /*{o:[{true:B,false:A}|A,B]}*/ o;
+  } else if (/*{o:[{false:A,B}|A,B]}*/ o is C) {
+    /*{o:[{true:C,false:A,B}|A,B,C]}*/ o;
+  } else if (/*{o:[{false:A,B,C}|A,B,C]}*/ o is D) {
+    /*{o:[{true:D,false:A,B,C}|A,B,C,D]}*/ o;
+  } else {
+    /*{o:[{false:A,B,C,D}|A,B,C,D]}*/ o;
+  }
+}
diff --git a/tests/compiler/dart2js_extra/38949_test.dart b/tests/compiler/dart2js_extra/38949_test.dart
new file mode 100644
index 0000000..4b0ceba
--- /dev/null
+++ b/tests/compiler/dart2js_extra/38949_test.dart
@@ -0,0 +1,34 @@
+// 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:expect/expect.dart';
+
+abstract class Foo<A, B> {
+  bool pip(o);
+}
+
+class Bar<X, Y> implements Foo<X, Y> {
+  bool pip(o) => o is Y;
+}
+
+class Baz<U, V> implements Foo<U, V> {
+  bool pip(o) => true;
+}
+
+void main() {
+  Expect.listEquals([], test(1));
+  Expect.listEquals([true, false], test(Bar<String, int>()));
+  Expect.listEquals([true, true], test(Baz<String, int>()));
+}
+
+@pragma('dart2js:noInline')
+List<bool> test(dynamic p) {
+  List<bool> result = [];
+  if (p is Foo) {
+    for (var o in [1, 'x']) {
+      result.add(p.pip(o));
+    }
+  }
+  return result;
+}
diff --git a/tests/compiler/dart2js_extra/generic_type_error_message_test.dart b/tests/compiler/dart2js_extra/generic_type_error_message_test.dart
index 038fecf..e9ff104 100644
--- a/tests/compiler/dart2js_extra/generic_type_error_message_test.dart
+++ b/tests/compiler/dart2js_extra/generic_type_error_message_test.dart
@@ -31,7 +31,7 @@
     if (!expectTypeArguments) {
       expected = expected.substring(0, expected.indexOf('<'));
     }
-    expected = "'$expected'";
+    expected = '$expected';
     Expect.isTrue(e.toString().contains(expected),
         'Expected "$expected" in the message: $e');
     caught = true;
diff --git a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string3_test.dart b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string3_test.dart
index 1cf0e0e..1d244c0 100644
--- a/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string3_test.dart
+++ b/tests/compiler/dart2js_extra/lax_runtime_type_closure_to_string3_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 --omit-implicit-checks --lax-runtime-type-to-string
+// dart2jsOptions=--strong --omit-implicit-checks --lax-runtime-type-to-string --experiment-new-rti
 
 import 'package:expect/expect.dart';
 
@@ -18,6 +18,6 @@
 
 main() {
   Class1<int> cls1 = new Class1<int>();
-  Expect.equals("() => dynamic", cls1.method.runtimeType.toString());
+  Expect.equals("() => erased", cls1.method.runtimeType.toString());
   new Class2<int>();
 }
diff --git a/tests/compiler/dart2js_extra/non_trivial_substitution_test.dart b/tests/compiler/dart2js_extra/non_trivial_substitution_test.dart
new file mode 100644
index 0000000..2a4ebf00
--- /dev/null
+++ b/tests/compiler/dart2js_extra/non_trivial_substitution_test.dart
@@ -0,0 +1,20 @@
+// 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:expect/expect.dart";
+
+class A {}
+
+class B {}
+
+class C extends A implements B {}
+
+class Base<T> {}
+
+class Sub implements Base<C> {}
+
+void main() {
+  Expect.subtype<Sub, Base<A>>();
+  Expect.subtype<Sub, Base<B>>();
+}
diff --git a/tests/compiler/dart2js_extra/rti/simple_2_test.dart b/tests/compiler/dart2js_extra/rti/simple_2_test.dart
index ac77e3c..e195451 100644
--- a/tests/compiler/dart2js_extra/rti/simple_2_test.dart
+++ b/tests/compiler/dart2js_extra/rti/simple_2_test.dart
@@ -11,21 +11,10 @@
   Expect.equals(expected, result.replaceAll('minified:', ''));
 }
 
-testDynamic1() {
+testDynamic() {
   var universe = rti.testingCreateUniverse();
 
-  var rti1 = rti.testingUniverseEval(universe, 'dynamic');
-  var rti2 = rti.testingUniverseEval(universe, ',,dynamic,,');
-
-  Expect.isTrue(identical(rti1, rti2), 'dynamic should be identical');
-  Expect.isFalse(rti1 is String);
-  checkToString('dynamic', rti1);
-}
-
-testDynamic2() {
-  var universe = rti.testingCreateUniverse();
-
-  var rti1 = rti.testingUniverseEval(universe, 'dynamic');
+  var rti1 = rti.testingUniverseEval(universe, '@');
   var rti2 = rti.testingUniverseEval(universe, ',,@,,');
 
   Expect.isTrue(identical(rti1, rti2), 'dynamic should be identical');
@@ -127,8 +116,7 @@
 }
 
 main() {
-  testDynamic1();
-  testDynamic2();
+  testDynamic();
   testVoid();
   testNever();
   testAny();
diff --git a/tests/compiler/dart2js_extra/rti/simple_test.dart b/tests/compiler/dart2js_extra/rti/simple_test.dart
index 88ccf9f..13a893e 100644
--- a/tests/compiler/dart2js_extra/rti/simple_test.dart
+++ b/tests/compiler/dart2js_extra/rti/simple_test.dart
@@ -10,8 +10,8 @@
 
   // TODO(sra): Add call: rti.testingAddRules(universe, ???);
 
-  var dynamicRti1 = rti.testingUniverseEval(universe, 'dynamic');
-  var dynamicRti2 = rti.testingUniverseEval(universe, 'dynamic');
+  var dynamicRti1 = rti.testingUniverseEval(universe, '@');
+  var dynamicRti2 = rti.testingUniverseEval(universe, '@');
 
   Expect.isTrue(identical(dynamicRti1, dynamicRti2));
   Expect.isFalse(dynamicRti1 is String);
diff --git a/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart b/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart
index 80fa25c..d61335f 100644
--- a/tests/compiler/dart2js_extra/runtime_type_to_string1_test.dart
+++ b/tests/compiler/dart2js_extra/runtime_type_to_string1_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 --omit-implicit-checks --lax-runtime-type-to-string
+// dart2jsOptions=--strong --omit-implicit-checks --lax-runtime-type-to-string --experiment-new-rti
 
 import 'package:expect/expect.dart';
 
@@ -13,9 +13,10 @@
 main() {
   // Since the type argument of `Class` is only needed for
   // `.runtimeType.toString()`, it is not reified, and the toString is therefore
-  // only 'Class'.
+  // 'Class<erased>'.
   String className = (Class).toString();
   className = className.substring(0, className.indexOf('<'));
-  Expect.equals(className, new Class().runtimeType.toString());
-  Expect.equals(className, new Class<int>().runtimeType.toString());
+  String erasedName = '$className<erased>';
+  Expect.equals(erasedName, new Class().runtimeType.toString());
+  Expect.equals(erasedName, new Class<int>().runtimeType.toString());
 }
diff --git a/tests/compiler/dartdevc/modular/nnbd_strong_subtype/main.dart b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/main.dart
new file mode 100644
index 0000000..86a3ddd
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/main.dart
@@ -0,0 +1,300 @@
+// 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.
+
+// Copied from tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart.
+
+// Requirements=nnbd-strong
+
+import 'dart:async';
+
+import 'runtime_utils.dart';
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class D<T extends B> {}
+
+class E<T, S> {}
+
+class F extends E<B, B> {}
+
+void main() {
+  // Run tests with strict subtype checks.
+  strictSubtypeChecks(true);
+
+  // Top type symmetry.
+  // Object? <: dynamic
+  checkSubtype(nullable(Object), dynamic);
+  // dynamic <: Object?
+  checkSubtype(dynamic, nullable(Object));
+  // Object? <: void
+  checkSubtype(nullable(Object), voidType);
+  // void <: Object?
+  checkSubtype(voidType, nullable(Object));
+  // void <: dynamic
+  checkSubtype(voidType, dynamic);
+  // dynamic <: void
+  checkSubtype(dynamic, voidType);
+
+  // Bottom is subtype of top.
+  // never <: dynamic
+  checkProperSubtype(neverType, dynamic);
+  // never <: void
+  checkProperSubtype(neverType, voidType);
+  // never <: Object?
+  checkProperSubtype(neverType, nullable(Object));
+
+  // Object is between top and bottom.
+  // Object <: Object?
+  checkProperSubtype(Object, nullable(Object));
+  // never <: Object
+  checkProperSubtype(neverType, Object);
+
+  // Null is between top and bottom.
+  // Null <: Object?
+  checkProperSubtype(Null, nullable(Object));
+  // never <: Null
+  checkProperSubtype(neverType, Null);
+
+  // Class is between Object and bottom.
+  // A <: Object
+  checkProperSubtype(A, dynamic);
+  // never <: A
+  checkProperSubtype(neverType, A);
+
+  // Nullable types are a union of T and Null.
+  // A <: A?
+  checkProperSubtype(A, nullable(A));
+  // Null <: A?
+  checkProperSubtype(Null, nullable(A));
+  // A? <: Object?
+  checkProperSubtype(nullable(A), nullable(Object));
+
+  // Legacy types will eventually be migrated to T or T? but until then are
+  // symmetric with both.
+  // Object* <: Object
+  checkSubtype(legacy(Object), Object);
+  // Object <: Object*
+  checkSubtype(Object, legacy(Object));
+  // Object* <: Object?
+  checkSubtype(legacy(Object), nullable(Object));
+  // Object? <: Object*
+  checkSubtype(nullable(Object), legacy(Object));
+  // Null <: Object*
+  checkSubtype(Null, legacy(Object));
+  // never <: Object*
+  checkSubtype(neverType, legacy(Object));
+  // A* <: A
+  checkSubtype(legacy(A), A);
+  // A <: A*
+  checkSubtype(A, legacy(A));
+  // A* <: A?
+  checkSubtype(legacy(A), nullable(A));
+  // A? <: A*
+  checkSubtype(nullable(A), legacy(A));
+  // A* <: Object
+  checkProperSubtype(legacy(A), Object);
+  // A* <: Object?
+  checkProperSubtype(legacy(A), nullable(Object));
+  // Null <: A*
+  checkProperSubtype(Null, legacy(A));
+  // never <: A*
+  checkProperSubtype(neverType, legacy(A));
+
+  // Futures.
+  // Null <: FutureOr<Object?>
+  checkProperSubtype(Null, generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object?>
+  checkProperSubtype(Object, generic1(FutureOr, nullable(Object)));
+  // Object? <: FutureOr<Object?>
+  checkSubtype(nullable(Object), generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object>
+  checkSubtype(Object, generic1(FutureOr, Object));
+  // FutureOr<Object> <: Object
+  checkSubtype(generic1(FutureOr, Object), Object);
+  // Object <: FutureOr<dynamic>
+  checkProperSubtype(Object, generic1(FutureOr, dynamic));
+  // Object <: FutureOr<void>
+  checkProperSubtype(Object, generic1(FutureOr, voidType));
+  // Future<Object> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, Object), generic1(FutureOr, nullable(Object)));
+  // Future<Object?> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, nullable(Object)), generic1(FutureOr, nullable(Object)));
+  // FutureOr<Never> <: Future<Never>
+  checkSubtype(generic1(FutureOr, neverType), generic1(Future, neverType));
+  // Future<B> <: FutureOr<A>
+  checkProperSubtype(generic1(Future, B), generic1(FutureOr, A));
+  // B <: <: FutureOr<A>
+  checkProperSubtype(B, generic1(FutureOr, A));
+  // Future<B> <: Future<A>
+  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+
+  // Interface subtypes.
+  // A <: A
+  checkSubtype(A, A);
+  // B <: A
+  checkProperSubtype(B, A);
+  // C <: B
+  checkProperSubtype(C, B);
+  // C <: A
+  checkProperSubtype(C, A);
+
+  // Functions.
+  // A -> B <: Function
+  checkProperSubtype(function1(B, A), Function);
+
+  // A -> B <: A -> B
+  checkSubtype(function1(B, A), function1(B, A));
+
+  // A -> B <: B -> B
+  checkProperSubtype(function1(B, A), function1(B, B));
+  // TODO(nshahan) Subtype check with covariant keyword?
+
+  // A -> B <: A -> A
+  checkSubtype(function1(B, A), function1(A, A));
+
+  // Generic Function Subtypes.
+  // Bound is a built in type.
+  // <T extends int> void -> void <: <T extends int> void -> void
+  checkSubtype(genericFunction(int), genericFunction(int));
+
+  // <T extends String> A -> T <: <T extends String> B -> T
+  checkProperSubtype(
+      functionGenericReturn(String, A), functionGenericReturn(String, B));
+
+  // <T extends double> T -> B <: <T extends double> T -> A
+  checkProperSubtype(
+      functionGenericArg(double, B), functionGenericArg(double, A));
+
+  // Bound is a function type.
+  // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
+  checkSubtype(
+      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+
+  // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
+  checkProperSubtype(functionGenericReturn(function1(B, A), A),
+      functionGenericReturn(function1(B, A), B));
+
+  // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
+  checkProperSubtype(functionGenericArg(function1(B, A), B),
+      functionGenericArg(function1(B, A), A));
+
+  // Bound is a user defined class.
+  // <T extends B> void -> void <: <T extends B> void -> void
+  checkSubtype(genericFunction(B), genericFunction(B));
+
+  // <T extends B> A -> T <: <T extends B> B -> T
+  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+
+  // <T extends B> T -> B <: <T extends B> T -> A
+  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+
+  // Bound is a Future.
+  // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
+  checkSubtype(genericFunction(generic1(Future, B)),
+      genericFunction(generic1(Future, B)));
+
+  // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
+      functionGenericReturn(generic1(Future, B), B));
+
+  // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
+      functionGenericArg(generic1(Future, B), A));
+
+  // Bound is a FutureOr.
+  // <T extends FutureOr<B>> void -> void <:
+  //    <T extends FutureOr<B>> void -> void
+  checkSubtype(genericFunction(generic1(FutureOr, B)),
+      genericFunction(generic1(FutureOr, B)));
+
+  // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(FutureOr, B), A),
+      functionGenericReturn(generic1(FutureOr, B), B));
+
+  // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(FutureOr, B), B),
+      functionGenericArg(generic1(FutureOr, B), A));
+
+  // Generics.
+  // D <: D<B>
+  checkSubtype(D, generic1(D, B));
+  // D<B> <: D
+  checkSubtype(generic1(D, B), D);
+  // D<C> <: D<B>
+  checkProperSubtype(generic1(D, C), generic1(D, B));
+
+  // F <: E
+  checkProperSubtype(F, E);
+  // F <: E<A, A>
+  checkProperSubtype(F, generic2(E, A, A));
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), E);
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+
+  // Nullable interface subtypes.
+  // B <: A?
+  checkProperSubtype(B, nullable(A));
+  // C <: A?
+  checkProperSubtype(C, nullable(A));
+  // B? <: A?
+  checkProperSubtype(nullable(B), nullable(A));
+  // C? <: A?
+  checkProperSubtype(nullable(C), nullable(A));
+
+  // Mixed mode.
+  // B* <: A
+  checkProperSubtype(legacy(B), A);
+  // B* <: A?
+  checkProperSubtype(legacy(B), nullable(A));
+  // A* <\: B
+  checkSubtypeFailure(legacy(A), B);
+  // B? <: A*
+  checkProperSubtype(nullable(B), legacy(A));
+  // B <: A*
+  checkProperSubtype(B, legacy(A));
+  // A <: B*
+  checkSubtypeFailure(A, legacy(B));
+  // A? <: B*
+  checkSubtypeFailure(nullable(A), legacy(B));
+
+  // Allowed in weak mode.
+  // dynamic <\: Object
+  checkSubtypeFailure(dynamic, Object);
+  // void <\: Object
+  checkSubtypeFailure(voidType, Object);
+  // Object? <\: Object
+  checkSubtypeFailure(nullable(Object), Object);
+  // A? <\: Object
+  checkSubtypeFailure(nullable(A), Object);
+  // A? <\: A
+  checkSubtypeFailure(nullable(A), A);
+  // Null <\: never
+  checkSubtypeFailure(Null, neverType);
+  // Null <\: Object
+  checkSubtypeFailure(Null, Object);
+  // Null <\: A
+  checkSubtypeFailure(Null, A);
+  // Null <\: FutureOr<A>
+  checkSubtypeFailure(Null, generic1(FutureOr, A));
+  // Null <\: Future<A>
+  checkSubtypeFailure(Null, generic1(Future, A));
+  // FutureOr<Null> <\: Future<Null>
+  checkSubtypeFailure(generic1(FutureOr, Null), generic1(Future, Null));
+  // Null <\: Future<A?>
+  checkSubtypeFailure(Null, generic1(Future, nullable(A)));
+  // FutureOr<Object?> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, nullable(Object)), Object);
+  // FutureOr<dynamic> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, dynamic), Object);
+  // FutureOr<void> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, voidType), Object);
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_strong_subtype/modules.yaml b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/modules.yaml
new file mode 100644
index 0000000..5c3492e
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/modules.yaml
@@ -0,0 +1,12 @@
+# 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.
+#
+# NNBD Strong runtime subtype tests.
+# Copied from test/compiler/dartdevc_native suite. This is temporary until the
+# forked NNBD SDK can build again.
+dependencies:
+  main: [runtime_utils, runtime_utils_nnbd]
+  runtime_utils: expect
+flags:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils.dart b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils.dart
new file mode 100644
index 0000000..8c6bbdc
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils.dart
@@ -0,0 +1,82 @@
+// 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.
+
+// Copied from tests/compiler/dartdevc_native/runtime_utils.dart.
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+// The runtime representation of the void type.
+final voidType = dart.wrapType(dart.void_);
+
+// Returns sWrapped<tWrapped> as a wrapped type.
+Type generic1(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#)', sGeneric, t));
+}
+
+// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
+Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var r = dart.unwrapType(rWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
+}
+
+// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
+Type function1(Type returnWrapped, Type argWrapped) {
+  var returnType = dart.unwrapType(returnWrapped);
+  var argType = dart.unwrapType(argWrapped);
+  var fun = dart.fnType(returnType, [argType]);
+  return dart.wrapType(fun);
+}
+
+// Returns a function type with a bounded type argument that takes no argument
+// and returns void as a wrapped type.
+Type genericFunction(Type boundWrapped) => dart.wrapType(dart.gFnType(
+    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function type with a bounded generic return type of
+// <T extends boundWrapped> argWrapped -> T as a wrapped type.
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              T,
+              [dart.unwrapType(argWrapped)]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function with a bounded generic argument type of
+// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              dart.unwrapType(returnWrapped),
+              [T]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+void checkSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+}
+
+void checkProperSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+  checkSubtypeFailure(tWrapped, sWrapped);
+}
+
+void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils_nnbd.dart b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils_nnbd.dart
new file mode 100644
index 0000000..c4cc4b8
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_strong_subtype/runtime_utils_nnbd.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.
+
+// Copied from tests/compiler/dartdevc_native/runtime_utils_nnbd.dart.
+
+import 'dart:_runtime' as dart;
+
+/// The runtime representation of the never type.
+final neverType = dart.wrapType(dart.never_);
+
+/// Sets the mode of the runtime subtype checks.
+///
+/// In tests the mode should be set only once at the very beginning of the test.
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) => dart.strictSubtypeChecks(flag);
+
+/// Returns tWrapped? as a wrapped type.
+Type nullable(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tNullable = dart.nullable(t);
+  return dart.wrapType(tNullable);
+}
+
+/// Returns tWrapped* as a wrapped type.
+Type legacy(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tLegacy = dart.legacy(t);
+  return dart.wrapType(tLegacy);
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_subtype/main.dart b/tests/compiler/dartdevc/modular/nnbd_subtype/main.dart
deleted file mode 100644
index d03c305..0000000
--- a/tests/compiler/dartdevc/modular/nnbd_subtype/main.dart
+++ /dev/null
@@ -1,274 +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:_foreign_helper' show JS;
-import 'dart:_runtime' as dart;
-import 'dart:async';
-
-import 'package:expect/expect.dart';
-
-class A {}
-
-class B extends A {}
-
-class C extends B {}
-
-class D<T extends B> {}
-
-class E<T, S> {}
-
-class F extends E<B, B> {}
-
-// Returns sWrapped<tWrapped> as a wrapped type.
-Type generic1(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#)', sGeneric, t));
-}
-
-// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
-Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  var r = dart.unwrapType(rWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
-}
-
-// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
-Type function1(Type returnWrapped, Type argWrapped) {
-  var returnType = dart.unwrapType(returnWrapped);
-  var argType = dart.unwrapType(argWrapped);
-  var fun = dart.fnType(returnType, [argType]);
-  return dart.wrapType(fun);
-}
-
-// Returns a function type with a bounded type argument that takes no argument
-// and returns void as a wrapped type.
-Type genericFunction(Type boundWrapped) => dart.wrapType(dart.gFnType(
-    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
-
-// Returns a function type with a bounded generic return type of
-// <T extends typeBoud> argWrapped -> T as a wrapped type.
-Type functionGenericReturn(Type boundWrapped, Type argWrapped) =>
-    dart.wrapType(dart.gFnType(
-        (T) => [
-              T,
-              [dart.unwrapType(argWrapped)]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
-
-// Returns a function with a bounded generic argument type of
-// <T extends typeBoud> T -> returnWrapped as a wrapped type.
-Type functionGenericArg(Type boundWrapped, Type returnWrapped) =>
-    dart.wrapType(dart.gFnType(
-        (T) => [
-              dart.unwrapType(returnWrapped),
-              [T]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
-
-void checkSubtype(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-}
-
-void checkProperSubtype(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-  checkSubtypeFailure(tWrapped, sWrapped);
-}
-
-void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
-}
-
-// NNBD tests
-// Returns tWrapped? as a wrapped type.
-Type nullable(Type tWrapped) {
-  var t = dart.unwrapType(tWrapped);
-  var tNullable = dart.nullable(t);
-  return dart.wrapType(tNullable);
-}
-
-// Returns tWrapped* as a wrapped type.
-Type legacy(Type tWrapped) {
-  var t = dart.unwrapType(tWrapped);
-  var tLegacy = dart.legacy(t);
-  return dart.wrapType(tLegacy);
-}
-
-void main() {
-  // dynamic <\: A
-  checkSubtypeFailure(dynamic, A);
-  // A <: dynamic
-  checkProperSubtype(A, dynamic);
-  // A <: void
-  checkProperSubtype(A, dart.wrapType(dart.void_));
-  // Null <\: A
-  checkSubtypeFailure(Null, A);
-
-  // FutureOr<Never> <: Future<Never>
-  checkSubtype(generic1(FutureOr, dart.wrapType(dart.never_)),
-      generic1(Future, dart.wrapType(dart.never_)));
-  // Future<B> <: FutureOr<A>
-  checkProperSubtype(generic1(Future, B), generic1(FutureOr, A));
-  // B <: <: FutureOr<A>
-  checkProperSubtype(B, generic1(FutureOr, A));
-  // Future<B> <: Future<A>
-  checkProperSubtype(generic1(Future, B), generic1(Future, A));
-
-  // B <: A
-  checkProperSubtype(B, A);
-  // A <: A
-  checkSubtype(A, A);
-  // C <: B
-  checkProperSubtype(C, B);
-  // C <: A
-  checkProperSubtype(C, A);
-
-  // A -> B <: Function
-  checkProperSubtype(function1(B, A), Function);
-
-  // A -> B <: A -> B
-  checkSubtype(function1(B, A), function1(B, A));
-
-  // A -> B <: B -> B
-  checkProperSubtype(function1(B, A), function1(B, B));
-  // TODO(nshahan) Subtype check with covariant keyword?
-
-  // A -> B <: A -> A
-  checkSubtype(function1(B, A), function1(A, A));
-
-  // Generic Function Subtypes.
-  // Bound is a built in type.
-  // <T extends int> void -> void <: <T extends int> void -> void
-  checkSubtype(genericFunction(int), genericFunction(int));
-
-  // <T extends String> A -> T <: <T extends String> B -> T
-  checkProperSubtype(
-      functionGenericReturn(String, A), functionGenericReturn(String, B));
-
-  // <T extends double> T -> B <: <T extends double> T -> A
-  checkProperSubtype(
-      functionGenericArg(double, B), functionGenericArg(double, A));
-
-  // Bound is a function type.
-  // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
-  checkSubtype(
-      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
-
-  // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
-  checkProperSubtype(functionGenericReturn(function1(B, A), A),
-      functionGenericReturn(function1(B, A), B));
-
-  // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
-  checkProperSubtype(functionGenericArg(function1(B, A), B),
-      functionGenericArg(function1(B, A), A));
-
-  // Bound is a user defined class.
-  // <T extends B> void -> void <: <T extends B> void -> void
-  checkSubtype(genericFunction(B), genericFunction(B));
-
-  // <T extends B> A -> T <: <T extends B> B -> T
-  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
-
-  // <T extends B> T -> B <: <T extends B> T -> A
-  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
-
-  // Bound is a Future.
-  // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
-  checkSubtype(genericFunction(generic1(Future, B)),
-      genericFunction(generic1(Future, B)));
-
-  // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
-  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
-      functionGenericReturn(generic1(Future, B), B));
-
-  // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
-  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
-      functionGenericArg(generic1(Future, B), A));
-
-  // Bound is a FutureOr.
-  // <T extends FutureOr<B>> void -> void <:
-  //    <T extends FutureOr<B>> void -> void
-  checkSubtype(genericFunction(generic1(FutureOr, B)),
-      genericFunction(generic1(FutureOr, B)));
-
-  // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
-  checkProperSubtype(functionGenericReturn(generic1(FutureOr, B), A),
-      functionGenericReturn(generic1(FutureOr, B), B));
-
-  // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
-  checkProperSubtype(functionGenericArg(generic1(FutureOr, B), B),
-      functionGenericArg(generic1(FutureOr, B), A));
-
-  // D <: D<B>
-  checkSubtype(D, generic1(D, B));
-  // D<B> <: D
-  checkSubtype(generic1(D, B), D);
-  // D<C> <: D<B>
-  checkProperSubtype(generic1(D, C), generic1(D, B));
-
-  // F <: E
-  checkProperSubtype(F, E);
-  // F <: E<A, A>
-  checkProperSubtype(F, generic2(E, A, A));
-  // // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), E);
-  // // E<B, B> <: E<A, A>
-  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
-
-  // A <: A?
-  checkProperSubtype(A, nullable(A));
-  // B <: A?
-  checkProperSubtype(B, nullable(A));
-  // C <: A?
-  checkProperSubtype(C, nullable(A));
-  // B? <: A?
-  checkProperSubtype(nullable(B), nullable(A));
-  // C? <: A?
-  checkProperSubtype(nullable(C), nullable(A));
-
-  // A <: Object
-  checkProperSubtype(A, Object);
-  // A* <: Object
-  checkProperSubtype(legacy(A), Object);
-  // dynamic <\: Object
-  checkSubtypeFailure(dynamic, Object);
-  // void <\: Object
-  checkSubtypeFailure(dart.wrapType(dart.void_), Object);
-  // Null <\: Object
-  checkSubtypeFailure(Null, Object);
-  // A? <\: Object
-  checkSubtypeFailure(nullable(A), Object);
-
-  // Null <: FutureOr<A?>
-  checkProperSubtype(Null, generic1(FutureOr, nullable(A)));
-  // Null <: Null
-  checkSubtype(Null, Null);
-  // Null <: A?
-  checkProperSubtype(Null, nullable(A));
-  // Null <: A*
-  checkProperSubtype(Null, legacy(A));
-
-  // B* <: A
-  checkProperSubtype(legacy(B), A);
-  // A* <\: B
-  checkSubtypeFailure(legacy(A), B);
-
-  // B? <: A*
-  checkProperSubtype(nullable(B), legacy(A));
-  // B <: A*
-  checkProperSubtype(B, legacy(A));
-  // A <: B*
-  checkSubtypeFailure(A, legacy(B));
-  // A? <: B*
-  checkSubtypeFailure(nullable(A), legacy(B));
-}
diff --git a/tests/compiler/dartdevc/modular/nnbd_subtype/modules.yaml b/tests/compiler/dartdevc/modular/nnbd_subtype/modules.yaml
deleted file mode 100644
index 0d34072..0000000
--- a/tests/compiler/dartdevc/modular/nnbd_subtype/modules.yaml
+++ /dev/null
@@ -1,11 +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.
-#
-# NNBD runtime subtype tests.
-# Temporarily here until the test/compiler/dartdevc_native suite is migrated for
-# nnbd.
-dependencies:
-  main: expect
-flags:
-  - non-nullable
\ No newline at end of file
diff --git a/tests/compiler/dartdevc/modular/nnbd_type_normalization/main.dart b/tests/compiler/dartdevc/modular/nnbd_type_normalization/main.dart
new file mode 100644
index 0000000..24a3ff0
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_type_normalization/main.dart
@@ -0,0 +1,40 @@
+// 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.
+
+// Copied from tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart.
+
+// Requirements=nnbd
+
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+void main() {
+  // A?? == A?
+  Expect.identical(nullable(nullable(A)), nullable(A));
+  // A?* == A?
+  Expect.identical(legacy(nullable(A)), nullable(A));
+  // A*? == A?
+  Expect.identical(nullable(legacy(A)), nullable(A));
+  // A** == A*
+  Expect.identical(legacy(legacy(A)), legacy(A));
+  // Null? == Null
+  Expect.identical(nullable(Null), Null);
+  // Never? == Null
+  Expect.identical(nullable(dart.wrapType(dart.never_)), Null);
+  // dynamic? == dynamic
+  Expect.identical(nullable(dynamic), dynamic);
+  // void? == void
+  Expect.identical(
+      nullable(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+  // dynamic* == dynamic
+  Expect.identical(legacy(dynamic), dynamic);
+  // void* == void
+  Expect.identical(
+      legacy(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_type_normalization/modules.yaml b/tests/compiler/dartdevc/modular/nnbd_type_normalization/modules.yaml
new file mode 100644
index 0000000..73a8131
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_type_normalization/modules.yaml
@@ -0,0 +1,11 @@
+# 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.
+#
+# NNBD type normalization tests.
+# Copied from test/compiler/dartdevc_native suite. This is temporary until the
+# forked NNBD SDK can build again.
+dependencies:
+  main: [expect, runtime_utils_nnbd]
+flags:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/compiler/dartdevc/modular/nnbd_type_normalization/runtime_utils_nnbd.dart b/tests/compiler/dartdevc/modular/nnbd_type_normalization/runtime_utils_nnbd.dart
new file mode 100644
index 0000000..c4cc4b8
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_type_normalization/runtime_utils_nnbd.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.
+
+// Copied from tests/compiler/dartdevc_native/runtime_utils_nnbd.dart.
+
+import 'dart:_runtime' as dart;
+
+/// The runtime representation of the never type.
+final neverType = dart.wrapType(dart.never_);
+
+/// Sets the mode of the runtime subtype checks.
+///
+/// In tests the mode should be set only once at the very beginning of the test.
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) => dart.strictSubtypeChecks(flag);
+
+/// Returns tWrapped? as a wrapped type.
+Type nullable(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tNullable = dart.nullable(t);
+  return dart.wrapType(tNullable);
+}
+
+/// Returns tWrapped* as a wrapped type.
+Type legacy(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tLegacy = dart.legacy(t);
+  return dart.wrapType(tLegacy);
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_weak_subtype/main.dart b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/main.dart
new file mode 100644
index 0000000..21c8bb11
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/main.dart
@@ -0,0 +1,300 @@
+// 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.
+
+// Copied from tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart.
+
+// Requirements=nnbd-weak
+
+import 'dart:async';
+
+import 'runtime_utils.dart';
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class D<T extends B> {}
+
+class E<T, S> {}
+
+class F extends E<B, B> {}
+
+void main() {
+  // Run tests with weak subtype checks.
+  strictSubtypeChecks(false);
+
+  // Top type symmetry.
+  // Object? <: dynamic
+  checkSubtype(nullable(Object), dynamic);
+  // dynamic <: Object?
+  checkSubtype(dynamic, nullable(Object));
+  // Object? <: void
+  checkSubtype(nullable(Object), voidType);
+  // void <: Object?
+  checkSubtype(voidType, nullable(Object));
+  // void <: dynamic
+  checkSubtype(voidType, dynamic);
+  // dynamic <: void
+  checkSubtype(dynamic, voidType);
+
+  // Bottom is subtype of top.
+  // never <: dynamic
+  checkProperSubtype(neverType, dynamic);
+  // never <: void
+  checkProperSubtype(neverType, voidType);
+  // never <: Object?
+  checkProperSubtype(neverType, nullable(Object));
+
+  // Object is between top and bottom.
+  // Object <: Object?
+  checkSubtype(Object, nullable(Object));
+  // never <: Object
+  checkProperSubtype(neverType, Object);
+
+  // Null is between top and bottom.
+  // Null <: Object?
+  checkProperSubtype(Null, nullable(Object));
+  // never <: Null
+  checkSubtype(neverType, Null);
+
+  // Class is between Object and bottom.
+  // A <: Object
+  checkProperSubtype(A, dynamic);
+  // never <: A
+  checkProperSubtype(neverType, A);
+
+  // Nullable types are a union of T and Null.
+  // A <: A?
+  checkSubtype(A, nullable(A));
+  // Null <: A?
+  checkProperSubtype(Null, nullable(A));
+  // A? <: Object?
+  checkProperSubtype(nullable(A), nullable(Object));
+
+  // Legacy types will eventually be migrated to T or T? but until then are
+  // symmetric with both.
+  // Object* <: Object
+  checkSubtype(legacy(Object), Object);
+  // Object <: Object*
+  checkSubtype(Object, legacy(Object));
+  // Object* <: Object?
+  checkSubtype(legacy(Object), nullable(Object));
+  // Object? <: Object*
+  checkSubtype(nullable(Object), legacy(Object));
+  // Null <: Object*
+  checkSubtype(Null, legacy(Object));
+  // never <: Object*
+  checkSubtype(neverType, legacy(Object));
+  // A* <: A
+  checkSubtype(legacy(A), A);
+  // A <: A*
+  checkSubtype(A, legacy(A));
+  // A* <: A?
+  checkSubtype(legacy(A), nullable(A));
+  // A? <: A*
+  checkSubtype(nullable(A), legacy(A));
+  // A* <: Object
+  checkProperSubtype(legacy(A), Object);
+  // A* <: Object?
+  checkProperSubtype(legacy(A), nullable(Object));
+  // Null <: A*
+  checkProperSubtype(Null, legacy(A));
+  // never <: A*
+  checkProperSubtype(neverType, legacy(A));
+
+  // Futures.
+  // Null <: FutureOr<Object?>
+  checkProperSubtype(Null, generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object?>
+  checkSubtype(Object, generic1(FutureOr, nullable(Object)));
+  // Object? <: FutureOr<Object?>
+  checkSubtype(nullable(Object), generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object>
+  checkSubtype(Object, generic1(FutureOr, Object));
+  // FutureOr<Object> <: Object
+  checkSubtype(generic1(FutureOr, Object), Object);
+  // Object <: FutureOr<dynamic>
+  checkSubtype(Object, generic1(FutureOr, dynamic));
+  // Object <: FutureOr<void>
+  checkSubtype(Object, generic1(FutureOr, voidType));
+  // Future<Object> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, Object), generic1(FutureOr, nullable(Object)));
+  // Future<Object?> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, nullable(Object)), generic1(FutureOr, nullable(Object)));
+  // FutureOr<Never> <: Future<Never>
+  checkSubtype(generic1(FutureOr, neverType), generic1(Future, neverType));
+  // Future<B> <: FutureOr<A>
+  checkProperSubtype(generic1(Future, B), generic1(FutureOr, A));
+  // B <: <: FutureOr<A>
+  checkProperSubtype(B, generic1(FutureOr, A));
+  // Future<B> <: Future<A>
+  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+
+  // Interface subtypes.
+  // A <: A
+  checkSubtype(A, A);
+  // B <: A
+  checkProperSubtype(B, A);
+  // C <: B
+  checkProperSubtype(C, B);
+  // C <: A
+  checkProperSubtype(C, A);
+
+  // Functions.
+  // A -> B <: Function
+  checkProperSubtype(function1(B, A), Function);
+
+  // A -> B <: A -> B
+  checkSubtype(function1(B, A), function1(B, A));
+
+  // A -> B <: B -> B
+  checkProperSubtype(function1(B, A), function1(B, B));
+  // TODO(nshahan) Subtype check with covariant keyword?
+
+  // A -> B <: A -> A
+  checkSubtype(function1(B, A), function1(A, A));
+
+  // Generic Function Subtypes.
+  // Bound is a built in type.
+  // <T extends int> void -> void <: <T extends int> void -> void
+  checkSubtype(genericFunction(int), genericFunction(int));
+
+  // <T extends String> A -> T <: <T extends String> B -> T
+  checkProperSubtype(
+      functionGenericReturn(String, A), functionGenericReturn(String, B));
+
+  // <T extends double> T -> B <: <T extends double> T -> A
+  checkProperSubtype(
+      functionGenericArg(double, B), functionGenericArg(double, A));
+
+  // Bound is a function type.
+  // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
+  checkSubtype(
+      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+
+  // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
+  checkProperSubtype(functionGenericReturn(function1(B, A), A),
+      functionGenericReturn(function1(B, A), B));
+
+  // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
+  checkProperSubtype(functionGenericArg(function1(B, A), B),
+      functionGenericArg(function1(B, A), A));
+
+  // Bound is a user defined class.
+  // <T extends B> void -> void <: <T extends B> void -> void
+  checkSubtype(genericFunction(B), genericFunction(B));
+
+  // <T extends B> A -> T <: <T extends B> B -> T
+  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+
+  // <T extends B> T -> B <: <T extends B> T -> A
+  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+
+  // Bound is a Future.
+  // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
+  checkSubtype(genericFunction(generic1(Future, B)),
+      genericFunction(generic1(Future, B)));
+
+  // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
+      functionGenericReturn(generic1(Future, B), B));
+
+  // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
+      functionGenericArg(generic1(Future, B), A));
+
+  // Bound is a FutureOr.
+  // <T extends FutureOr<B>> void -> void <:
+  //    <T extends FutureOr<B>> void -> void
+  checkSubtype(genericFunction(generic1(FutureOr, B)),
+      genericFunction(generic1(FutureOr, B)));
+
+  // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(FutureOr, B), A),
+      functionGenericReturn(generic1(FutureOr, B), B));
+
+  // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(FutureOr, B), B),
+      functionGenericArg(generic1(FutureOr, B), A));
+
+  // Generics.
+  // D <: D<B>
+  checkSubtype(D, generic1(D, B));
+  // D<B> <: D
+  checkSubtype(generic1(D, B), D);
+  // D<C> <: D<B>
+  checkProperSubtype(generic1(D, C), generic1(D, B));
+
+  // F <: E
+  checkProperSubtype(F, E);
+  // F <: E<A, A>
+  checkProperSubtype(F, generic2(E, A, A));
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), E);
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+
+  // Nullable interface subtypes.
+  // B <: A?
+  checkProperSubtype(B, nullable(A));
+  // C <: A?
+  checkProperSubtype(C, nullable(A));
+  // B? <: A?
+  checkProperSubtype(nullable(B), nullable(A));
+  // C? <: A?
+  checkProperSubtype(nullable(C), nullable(A));
+
+  // Mixed mode.
+  // B* <: A
+  checkProperSubtype(legacy(B), A);
+  // B* <: A?
+  checkProperSubtype(legacy(B), nullable(A));
+  // A* <\: B
+  checkSubtypeFailure(legacy(A), B);
+  // B? <: A*
+  checkProperSubtype(nullable(B), legacy(A));
+  // B <: A*
+  checkProperSubtype(B, legacy(A));
+  // A <: B*
+  checkSubtypeFailure(A, legacy(B));
+  // A? <: B*
+  checkSubtypeFailure(nullable(A), legacy(B));
+
+  // Allowed in weak mode.
+  // dynamic <: Object
+  checkSubtype(dynamic, Object);
+  // void <: Object
+  checkSubtype(voidType, Object);
+  // Object? <: Object
+  checkSubtype(nullable(Object), Object);
+  // A? <: Object
+  checkProperSubtype(nullable(A), Object);
+  // A? <: A
+  checkSubtype(nullable(A), A);
+  // Null <: never
+  checkSubtype(Null, neverType);
+  // Null <: Object
+  checkProperSubtype(Null, Object);
+  // Null <: A
+  checkProperSubtype(Null, A);
+  // Null <: FutureOr<A>
+  checkProperSubtype(Null, generic1(FutureOr, A));
+  // Null <: Future<A>
+  checkProperSubtype(Null, generic1(Future, A));
+  // FutureOr<Null> <: Future<Null>
+  checkSubtype(generic1(FutureOr, Null), generic1(Future, Null));
+  // Null <: Future<A?>
+  checkProperSubtype(Null, generic1(Future, nullable(A)));
+  // FutureOr<Object?> <: Object
+  checkSubtype(generic1(FutureOr, nullable(Object)), Object);
+  // FutureOr<dynamic> <: Object
+  checkSubtype(generic1(FutureOr, dynamic), Object);
+  // FutureOr<void> <: Object
+  checkSubtype(generic1(FutureOr, voidType), Object);
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_weak_subtype/modules.yaml b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/modules.yaml
new file mode 100644
index 0000000..5c3492e
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/modules.yaml
@@ -0,0 +1,12 @@
+# 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.
+#
+# NNBD Strong runtime subtype tests.
+# Copied from test/compiler/dartdevc_native suite. This is temporary until the
+# forked NNBD SDK can build again.
+dependencies:
+  main: [runtime_utils, runtime_utils_nnbd]
+  runtime_utils: expect
+flags:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils.dart b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils.dart
new file mode 100644
index 0000000..8c6bbdc
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils.dart
@@ -0,0 +1,82 @@
+// 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.
+
+// Copied from tests/compiler/dartdevc_native/runtime_utils.dart.
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+// The runtime representation of the void type.
+final voidType = dart.wrapType(dart.void_);
+
+// Returns sWrapped<tWrapped> as a wrapped type.
+Type generic1(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#)', sGeneric, t));
+}
+
+// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
+Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var r = dart.unwrapType(rWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
+}
+
+// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
+Type function1(Type returnWrapped, Type argWrapped) {
+  var returnType = dart.unwrapType(returnWrapped);
+  var argType = dart.unwrapType(argWrapped);
+  var fun = dart.fnType(returnType, [argType]);
+  return dart.wrapType(fun);
+}
+
+// Returns a function type with a bounded type argument that takes no argument
+// and returns void as a wrapped type.
+Type genericFunction(Type boundWrapped) => dart.wrapType(dart.gFnType(
+    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function type with a bounded generic return type of
+// <T extends boundWrapped> argWrapped -> T as a wrapped type.
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              T,
+              [dart.unwrapType(argWrapped)]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function with a bounded generic argument type of
+// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              dart.unwrapType(returnWrapped),
+              [T]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+void checkSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+}
+
+void checkProperSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+  checkSubtypeFailure(tWrapped, sWrapped);
+}
+
+void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
+}
diff --git a/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils_nnbd.dart b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils_nnbd.dart
new file mode 100644
index 0000000..c4cc4b8
--- /dev/null
+++ b/tests/compiler/dartdevc/modular/nnbd_weak_subtype/runtime_utils_nnbd.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.
+
+// Copied from tests/compiler/dartdevc_native/runtime_utils_nnbd.dart.
+
+import 'dart:_runtime' as dart;
+
+/// The runtime representation of the never type.
+final neverType = dart.wrapType(dart.never_);
+
+/// Sets the mode of the runtime subtype checks.
+///
+/// In tests the mode should be set only once at the very beginning of the test.
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) => dart.strictSubtypeChecks(flag);
+
+/// Returns tWrapped? as a wrapped type.
+Type nullable(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tNullable = dart.nullable(t);
+  return dart.wrapType(tNullable);
+}
+
+/// Returns tWrapped* as a wrapped type.
+Type legacy(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tLegacy = dart.legacy(t);
+  return dart.wrapType(tLegacy);
+}
diff --git a/tests/compiler/dartdevc_native/dartdevc_native_dartdevc.status b/tests/compiler/dartdevc_native/dartdevc_native_dartdevc.status
new file mode 100644
index 0000000..0cfabdd
--- /dev/null
+++ b/tests/compiler/dartdevc_native/dartdevc_native_dartdevc.status
@@ -0,0 +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.
+
+# Sections in this file should contain "$compiler == dartdevc" or dartdevk.
+
+[ $compiler == dartdevc ]
+variance_subtype_test: SkipByDesign # Not supported by analyzer based DDC.
+variance_test: SkipByDesign # Not supported by analyzer based DDC.
diff --git a/tests/compiler/dartdevc_native/hot_restart_timer_test.dart b/tests/compiler/dartdevc_native/hot_restart_timer_test.dart
new file mode 100644
index 0000000..9685f51
--- /dev/null
+++ b/tests/compiler/dartdevc_native/hot_restart_timer_test.dart
@@ -0,0 +1,53 @@
+// 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:expect/expect.dart';
+import 'dart:async';
+import 'dart:_runtime' as dart;
+
+void main() async {
+  await timeoutTest();
+  await periodicTest();
+}
+
+void timeoutTest() async {
+  bool beforeRestart = true;
+  bool calledBeforeRestart = false;
+  bool calledAfterRestart = false;
+  void callback() {
+    if (beforeRestart) {
+      calledBeforeRestart = true;
+    } else {
+      calledAfterRestart = true;
+    }
+  }
+
+  Timer(Duration(milliseconds: 500), callback);
+  dart.hotRestart();
+  beforeRestart = false;
+  await new Future.delayed(Duration(milliseconds: 600));
+  Expect.isFalse(calledBeforeRestart);
+  Expect.isFalse(calledAfterRestart);
+}
+
+void periodicTest() async {
+  bool beforeRestart = true;
+  bool calledBeforeRestart = false;
+  bool calledAfterRestart = false;
+  void callback(_) {
+    if (beforeRestart) {
+      calledBeforeRestart = true;
+    } else {
+      calledAfterRestart = true;
+    }
+  }
+
+  Timer.periodic(Duration(milliseconds: 10), callback);
+  await new Future.delayed(Duration(milliseconds: 100));
+  dart.hotRestart();
+  beforeRestart = false;
+  await new Future.delayed(Duration(milliseconds: 100));
+  Expect.isTrue(calledBeforeRestart);
+  Expect.isFalse(calledAfterRestart);
+}
diff --git a/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
new file mode 100644
index 0000000..7c5a2c9d
--- /dev/null
+++ b/tests/compiler/dartdevc_native/nnbd_strong_subtype_test.dart
@@ -0,0 +1,298 @@
+// 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.
+
+// Requirements=nnbd-strong
+
+import 'dart:async';
+
+import 'runtime_utils.dart';
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class D<T extends B> {}
+
+class E<T, S> {}
+
+class F extends E<B, B> {}
+
+void main() {
+  // Run tests with strict subtype checks.
+  strictSubtypeChecks(true);
+
+  // Top type symmetry.
+  // Object? <: dynamic
+  checkSubtype(nullable(Object), dynamic);
+  // dynamic <: Object?
+  checkSubtype(dynamic, nullable(Object));
+  // Object? <: void
+  checkSubtype(nullable(Object), voidType);
+  // void <: Object?
+  checkSubtype(voidType, nullable(Object));
+  // void <: dynamic
+  checkSubtype(voidType, dynamic);
+  // dynamic <: void
+  checkSubtype(dynamic, voidType);
+
+  // Bottom is subtype of top.
+  // never <: dynamic
+  checkProperSubtype(neverType, dynamic);
+  // never <: void
+  checkProperSubtype(neverType, voidType);
+  // never <: Object?
+  checkProperSubtype(neverType, nullable(Object));
+
+  // Object is between top and bottom.
+  // Object <: Object?
+  checkProperSubtype(Object, nullable(Object));
+  // never <: Object
+  checkProperSubtype(neverType, Object);
+
+  // Null is between top and bottom.
+  // Null <: Object?
+  checkProperSubtype(Null, nullable(Object));
+  // never <: Null
+  checkProperSubtype(neverType, Null);
+
+  // Class is between Object and bottom.
+  // A <: Object
+  checkProperSubtype(A, dynamic);
+  // never <: A
+  checkProperSubtype(neverType, A);
+
+  // Nullable types are a union of T and Null.
+  // A <: A?
+  checkProperSubtype(A, nullable(A));
+  // Null <: A?
+  checkProperSubtype(Null, nullable(A));
+  // A? <: Object?
+  checkProperSubtype(nullable(A), nullable(Object));
+
+  // Legacy types will eventually be migrated to T or T? but until then are
+  // symmetric with both.
+  // Object* <: Object
+  checkSubtype(legacy(Object), Object);
+  // Object <: Object*
+  checkSubtype(Object, legacy(Object));
+  // Object* <: Object?
+  checkSubtype(legacy(Object), nullable(Object));
+  // Object? <: Object*
+  checkSubtype(nullable(Object), legacy(Object));
+  // Null <: Object*
+  checkSubtype(Null, legacy(Object));
+  // never <: Object*
+  checkSubtype(neverType, legacy(Object));
+  // A* <: A
+  checkSubtype(legacy(A), A);
+  // A <: A*
+  checkSubtype(A, legacy(A));
+  // A* <: A?
+  checkSubtype(legacy(A), nullable(A));
+  // A? <: A*
+  checkSubtype(nullable(A), legacy(A));
+  // A* <: Object
+  checkProperSubtype(legacy(A), Object);
+  // A* <: Object?
+  checkProperSubtype(legacy(A), nullable(Object));
+  // Null <: A*
+  checkProperSubtype(Null, legacy(A));
+  // never <: A*
+  checkProperSubtype(neverType, legacy(A));
+
+  // Futures.
+  // Null <: FutureOr<Object?>
+  checkProperSubtype(Null, generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object?>
+  checkProperSubtype(Object, generic1(FutureOr, nullable(Object)));
+  // Object? <: FutureOr<Object?>
+  checkSubtype(nullable(Object), generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object>
+  checkSubtype(Object, generic1(FutureOr, Object));
+  // FutureOr<Object> <: Object
+  checkSubtype(generic1(FutureOr, Object), Object);
+  // Object <: FutureOr<dynamic>
+  checkProperSubtype(Object, generic1(FutureOr, dynamic));
+  // Object <: FutureOr<void>
+  checkProperSubtype(Object, generic1(FutureOr, voidType));
+  // Future<Object> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, Object), generic1(FutureOr, nullable(Object)));
+  // Future<Object?> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, nullable(Object)), generic1(FutureOr, nullable(Object)));
+  // FutureOr<Never> <: Future<Never>
+  checkSubtype(generic1(FutureOr, neverType), generic1(Future, neverType));
+  // Future<B> <: FutureOr<A>
+  checkProperSubtype(generic1(Future, B), generic1(FutureOr, A));
+  // B <: <: FutureOr<A>
+  checkProperSubtype(B, generic1(FutureOr, A));
+  // Future<B> <: Future<A>
+  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+
+  // Interface subtypes.
+  // A <: A
+  checkSubtype(A, A);
+  // B <: A
+  checkProperSubtype(B, A);
+  // C <: B
+  checkProperSubtype(C, B);
+  // C <: A
+  checkProperSubtype(C, A);
+
+  // Functions.
+  // A -> B <: Function
+  checkProperSubtype(function1(B, A), Function);
+
+  // A -> B <: A -> B
+  checkSubtype(function1(B, A), function1(B, A));
+
+  // A -> B <: B -> B
+  checkProperSubtype(function1(B, A), function1(B, B));
+  // TODO(nshahan) Subtype check with covariant keyword?
+
+  // A -> B <: A -> A
+  checkSubtype(function1(B, A), function1(A, A));
+
+  // Generic Function Subtypes.
+  // Bound is a built in type.
+  // <T extends int> void -> void <: <T extends int> void -> void
+  checkSubtype(genericFunction(int), genericFunction(int));
+
+  // <T extends String> A -> T <: <T extends String> B -> T
+  checkProperSubtype(
+      functionGenericReturn(String, A), functionGenericReturn(String, B));
+
+  // <T extends double> T -> B <: <T extends double> T -> A
+  checkProperSubtype(
+      functionGenericArg(double, B), functionGenericArg(double, A));
+
+  // Bound is a function type.
+  // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
+  checkSubtype(
+      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+
+  // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
+  checkProperSubtype(functionGenericReturn(function1(B, A), A),
+      functionGenericReturn(function1(B, A), B));
+
+  // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
+  checkProperSubtype(functionGenericArg(function1(B, A), B),
+      functionGenericArg(function1(B, A), A));
+
+  // Bound is a user defined class.
+  // <T extends B> void -> void <: <T extends B> void -> void
+  checkSubtype(genericFunction(B), genericFunction(B));
+
+  // <T extends B> A -> T <: <T extends B> B -> T
+  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+
+  // <T extends B> T -> B <: <T extends B> T -> A
+  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+
+  // Bound is a Future.
+  // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
+  checkSubtype(genericFunction(generic1(Future, B)),
+      genericFunction(generic1(Future, B)));
+
+  // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
+      functionGenericReturn(generic1(Future, B), B));
+
+  // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
+      functionGenericArg(generic1(Future, B), A));
+
+  // Bound is a FutureOr.
+  // <T extends FutureOr<B>> void -> void <:
+  //    <T extends FutureOr<B>> void -> void
+  checkSubtype(genericFunction(generic1(FutureOr, B)),
+      genericFunction(generic1(FutureOr, B)));
+
+  // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(FutureOr, B), A),
+      functionGenericReturn(generic1(FutureOr, B), B));
+
+  // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(FutureOr, B), B),
+      functionGenericArg(generic1(FutureOr, B), A));
+
+  // Generics.
+  // D <: D<B>
+  checkSubtype(D, generic1(D, B));
+  // D<B> <: D
+  checkSubtype(generic1(D, B), D);
+  // D<C> <: D<B>
+  checkProperSubtype(generic1(D, C), generic1(D, B));
+
+  // F <: E
+  checkProperSubtype(F, E);
+  // F <: E<A, A>
+  checkProperSubtype(F, generic2(E, A, A));
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), E);
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+
+  // Nullable interface subtypes.
+  // B <: A?
+  checkProperSubtype(B, nullable(A));
+  // C <: A?
+  checkProperSubtype(C, nullable(A));
+  // B? <: A?
+  checkProperSubtype(nullable(B), nullable(A));
+  // C? <: A?
+  checkProperSubtype(nullable(C), nullable(A));
+
+  // Mixed mode.
+  // B* <: A
+  checkProperSubtype(legacy(B), A);
+  // B* <: A?
+  checkProperSubtype(legacy(B), nullable(A));
+  // A* <\: B
+  checkSubtypeFailure(legacy(A), B);
+  // B? <: A*
+  checkProperSubtype(nullable(B), legacy(A));
+  // B <: A*
+  checkProperSubtype(B, legacy(A));
+  // A <: B*
+  checkSubtypeFailure(A, legacy(B));
+  // A? <: B*
+  checkSubtypeFailure(nullable(A), legacy(B));
+
+  // Allowed in weak mode.
+  // dynamic <\: Object
+  checkSubtypeFailure(dynamic, Object);
+  // void <\: Object
+  checkSubtypeFailure(voidType, Object);
+  // Object? <\: Object
+  checkSubtypeFailure(nullable(Object), Object);
+  // A? <\: Object
+  checkSubtypeFailure(nullable(A), Object);
+  // A? <\: A
+  checkSubtypeFailure(nullable(A), A);
+  // Null <\: never
+  checkSubtypeFailure(Null, neverType);
+  // Null <\: Object
+  checkSubtypeFailure(Null, Object);
+  // Null <\: A
+  checkSubtypeFailure(Null, A);
+  // Null <\: FutureOr<A>
+  checkSubtypeFailure(Null, generic1(FutureOr, A));
+  // Null <\: Future<A>
+  checkSubtypeFailure(Null, generic1(Future, A));
+  // FutureOr<Null> <\: Future<Null>
+  checkSubtypeFailure(generic1(FutureOr, Null), generic1(Future, Null));
+  // Null <\: Future<A?>
+  checkSubtypeFailure(Null, generic1(Future, nullable(A)));
+  // FutureOr<Object?> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, nullable(Object)), Object);
+  // FutureOr<dynamic> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, dynamic), Object);
+  // FutureOr<void> <\: Object
+  checkSubtypeFailure(generic1(FutureOr, voidType), Object);
+}
diff --git a/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart b/tests/compiler/dartdevc_native/nnbd_type_normalization_test.dart
new file mode 100644
index 0000000..825caaf
--- /dev/null
+++ b/tests/compiler/dartdevc_native/nnbd_type_normalization_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.
+
+// Requirements=nnbd
+
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+void main() {
+  // A?? == A?
+  Expect.identical(nullable(nullable(A)), nullable(A));
+  // A?* == A?
+  Expect.identical(legacy(nullable(A)), nullable(A));
+  // A*? == A?
+  Expect.identical(nullable(legacy(A)), nullable(A));
+  // A** == A*
+  Expect.identical(legacy(legacy(A)), legacy(A));
+  // Null? == Null
+  Expect.identical(nullable(Null), Null);
+  // Never? == Null
+  Expect.identical(nullable(dart.wrapType(dart.never_)), Null);
+  // dynamic? == dynamic
+  Expect.identical(nullable(dynamic), dynamic);
+  // void? == void
+  Expect.identical(
+      nullable(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+  // dynamic* == dynamic
+  Expect.identical(legacy(dynamic), dynamic);
+  // void* == void
+  Expect.identical(
+      legacy(dart.wrapType(dart.void_)), dart.wrapType(dart.void_));
+}
diff --git a/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
new file mode 100644
index 0000000..f8fe125
--- /dev/null
+++ b/tests/compiler/dartdevc_native/nnbd_weak_subtype_test.dart
@@ -0,0 +1,298 @@
+// 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.
+
+// Requirements=nnbd-weak
+
+import 'dart:async';
+
+import 'runtime_utils.dart';
+import 'runtime_utils_nnbd.dart';
+
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class D<T extends B> {}
+
+class E<T, S> {}
+
+class F extends E<B, B> {}
+
+void main() {
+  // Run tests with weak subtype checks.
+  strictSubtypeChecks(false);
+
+  // Top type symmetry.
+  // Object? <: dynamic
+  checkSubtype(nullable(Object), dynamic);
+  // dynamic <: Object?
+  checkSubtype(dynamic, nullable(Object));
+  // Object? <: void
+  checkSubtype(nullable(Object), voidType);
+  // void <: Object?
+  checkSubtype(voidType, nullable(Object));
+  // void <: dynamic
+  checkSubtype(voidType, dynamic);
+  // dynamic <: void
+  checkSubtype(dynamic, voidType);
+
+  // Bottom is subtype of top.
+  // never <: dynamic
+  checkProperSubtype(neverType, dynamic);
+  // never <: void
+  checkProperSubtype(neverType, voidType);
+  // never <: Object?
+  checkProperSubtype(neverType, nullable(Object));
+
+  // Object is between top and bottom.
+  // Object <: Object?
+  checkSubtype(Object, nullable(Object));
+  // never <: Object
+  checkProperSubtype(neverType, Object);
+
+  // Null is between top and bottom.
+  // Null <: Object?
+  checkProperSubtype(Null, nullable(Object));
+  // never <: Null
+  checkSubtype(neverType, Null);
+
+  // Class is between Object and bottom.
+  // A <: Object
+  checkProperSubtype(A, dynamic);
+  // never <: A
+  checkProperSubtype(neverType, A);
+
+  // Nullable types are a union of T and Null.
+  // A <: A?
+  checkSubtype(A, nullable(A));
+  // Null <: A?
+  checkProperSubtype(Null, nullable(A));
+  // A? <: Object?
+  checkProperSubtype(nullable(A), nullable(Object));
+
+  // Legacy types will eventually be migrated to T or T? but until then are
+  // symmetric with both.
+  // Object* <: Object
+  checkSubtype(legacy(Object), Object);
+  // Object <: Object*
+  checkSubtype(Object, legacy(Object));
+  // Object* <: Object?
+  checkSubtype(legacy(Object), nullable(Object));
+  // Object? <: Object*
+  checkSubtype(nullable(Object), legacy(Object));
+  // Null <: Object*
+  checkSubtype(Null, legacy(Object));
+  // never <: Object*
+  checkSubtype(neverType, legacy(Object));
+  // A* <: A
+  checkSubtype(legacy(A), A);
+  // A <: A*
+  checkSubtype(A, legacy(A));
+  // A* <: A?
+  checkSubtype(legacy(A), nullable(A));
+  // A? <: A*
+  checkSubtype(nullable(A), legacy(A));
+  // A* <: Object
+  checkProperSubtype(legacy(A), Object);
+  // A* <: Object?
+  checkProperSubtype(legacy(A), nullable(Object));
+  // Null <: A*
+  checkProperSubtype(Null, legacy(A));
+  // never <: A*
+  checkProperSubtype(neverType, legacy(A));
+
+  // Futures.
+  // Null <: FutureOr<Object?>
+  checkProperSubtype(Null, generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object?>
+  checkSubtype(Object, generic1(FutureOr, nullable(Object)));
+  // Object? <: FutureOr<Object?>
+  checkSubtype(nullable(Object), generic1(FutureOr, nullable(Object)));
+  // Object <: FutureOr<Object>
+  checkSubtype(Object, generic1(FutureOr, Object));
+  // FutureOr<Object> <: Object
+  checkSubtype(generic1(FutureOr, Object), Object);
+  // Object <: FutureOr<dynamic>
+  checkSubtype(Object, generic1(FutureOr, dynamic));
+  // Object <: FutureOr<void>
+  checkSubtype(Object, generic1(FutureOr, voidType));
+  // Future<Object> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, Object), generic1(FutureOr, nullable(Object)));
+  // Future<Object?> <: FutureOr<Object?>
+  checkProperSubtype(
+      generic1(Future, nullable(Object)), generic1(FutureOr, nullable(Object)));
+  // FutureOr<Never> <: Future<Never>
+  checkSubtype(generic1(FutureOr, neverType), generic1(Future, neverType));
+  // Future<B> <: FutureOr<A>
+  checkProperSubtype(generic1(Future, B), generic1(FutureOr, A));
+  // B <: <: FutureOr<A>
+  checkProperSubtype(B, generic1(FutureOr, A));
+  // Future<B> <: Future<A>
+  checkProperSubtype(generic1(Future, B), generic1(Future, A));
+
+  // Interface subtypes.
+  // A <: A
+  checkSubtype(A, A);
+  // B <: A
+  checkProperSubtype(B, A);
+  // C <: B
+  checkProperSubtype(C, B);
+  // C <: A
+  checkProperSubtype(C, A);
+
+  // Functions.
+  // A -> B <: Function
+  checkProperSubtype(function1(B, A), Function);
+
+  // A -> B <: A -> B
+  checkSubtype(function1(B, A), function1(B, A));
+
+  // A -> B <: B -> B
+  checkProperSubtype(function1(B, A), function1(B, B));
+  // TODO(nshahan) Subtype check with covariant keyword?
+
+  // A -> B <: A -> A
+  checkSubtype(function1(B, A), function1(A, A));
+
+  // Generic Function Subtypes.
+  // Bound is a built in type.
+  // <T extends int> void -> void <: <T extends int> void -> void
+  checkSubtype(genericFunction(int), genericFunction(int));
+
+  // <T extends String> A -> T <: <T extends String> B -> T
+  checkProperSubtype(
+      functionGenericReturn(String, A), functionGenericReturn(String, B));
+
+  // <T extends double> T -> B <: <T extends double> T -> A
+  checkProperSubtype(
+      functionGenericArg(double, B), functionGenericArg(double, A));
+
+  // Bound is a function type.
+  // <T extends A -> B> void -> void <: <T extends A -> B> void -> void
+  checkSubtype(
+      genericFunction(function1(B, A)), genericFunction(function1(B, A)));
+
+  // <T extends A -> B> A -> T <: <T extends A -> B> B -> T
+  checkProperSubtype(functionGenericReturn(function1(B, A), A),
+      functionGenericReturn(function1(B, A), B));
+
+  // <T extends A -> B> T -> B <: <T extends A -> B> T -> A
+  checkProperSubtype(functionGenericArg(function1(B, A), B),
+      functionGenericArg(function1(B, A), A));
+
+  // Bound is a user defined class.
+  // <T extends B> void -> void <: <T extends B> void -> void
+  checkSubtype(genericFunction(B), genericFunction(B));
+
+  // <T extends B> A -> T <: <T extends B> B -> T
+  checkProperSubtype(functionGenericReturn(B, A), functionGenericReturn(B, B));
+
+  // <T extends B> T -> B <: <T extends B> T -> A
+  checkProperSubtype(functionGenericArg(B, B), functionGenericArg(B, A));
+
+  // Bound is a Future.
+  // <T extends Future<B>> void -> void <: <T extends Future<B>> void -> void
+  checkSubtype(genericFunction(generic1(Future, B)),
+      genericFunction(generic1(Future, B)));
+
+  // <T extends Future<B>> A -> T <: <T extends Future<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(Future, B), A),
+      functionGenericReturn(generic1(Future, B), B));
+
+  // <T extends Future<B>> T -> B <: <T extends Future<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(Future, B), B),
+      functionGenericArg(generic1(Future, B), A));
+
+  // Bound is a FutureOr.
+  // <T extends FutureOr<B>> void -> void <:
+  //    <T extends FutureOr<B>> void -> void
+  checkSubtype(genericFunction(generic1(FutureOr, B)),
+      genericFunction(generic1(FutureOr, B)));
+
+  // <T extends FutureOr<B>> A -> T <: <T extends FutureOr<B>> B -> T
+  checkProperSubtype(functionGenericReturn(generic1(FutureOr, B), A),
+      functionGenericReturn(generic1(FutureOr, B), B));
+
+  // <T extends FutureOr<B>> T -> B <: <T extends FutureOr<B>> T -> A
+  checkProperSubtype(functionGenericArg(generic1(FutureOr, B), B),
+      functionGenericArg(generic1(FutureOr, B), A));
+
+  // Generics.
+  // D <: D<B>
+  checkSubtype(D, generic1(D, B));
+  // D<B> <: D
+  checkSubtype(generic1(D, B), D);
+  // D<C> <: D<B>
+  checkProperSubtype(generic1(D, C), generic1(D, B));
+
+  // F <: E
+  checkProperSubtype(F, E);
+  // F <: E<A, A>
+  checkProperSubtype(F, generic2(E, A, A));
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), E);
+  // E<B, B> <: E<A, A>
+  checkProperSubtype(generic2(E, B, B), generic2(E, A, A));
+
+  // Nullable interface subtypes.
+  // B <: A?
+  checkProperSubtype(B, nullable(A));
+  // C <: A?
+  checkProperSubtype(C, nullable(A));
+  // B? <: A?
+  checkProperSubtype(nullable(B), nullable(A));
+  // C? <: A?
+  checkProperSubtype(nullable(C), nullable(A));
+
+  // Mixed mode.
+  // B* <: A
+  checkProperSubtype(legacy(B), A);
+  // B* <: A?
+  checkProperSubtype(legacy(B), nullable(A));
+  // A* <\: B
+  checkSubtypeFailure(legacy(A), B);
+  // B? <: A*
+  checkProperSubtype(nullable(B), legacy(A));
+  // B <: A*
+  checkProperSubtype(B, legacy(A));
+  // A <: B*
+  checkSubtypeFailure(A, legacy(B));
+  // A? <: B*
+  checkSubtypeFailure(nullable(A), legacy(B));
+
+  // Allowed in weak mode.
+  // dynamic <: Object
+  checkSubtype(dynamic, Object);
+  // void <: Object
+  checkSubtype(voidType, Object);
+  // Object? <: Object
+  checkSubtype(nullable(Object), Object);
+  // A? <: Object
+  checkProperSubtype(nullable(A), Object);
+  // A? <: A
+  checkSubtype(nullable(A), A);
+  // Null <: never
+  checkSubtype(Null, neverType);
+  // Null <: Object
+  checkProperSubtype(Null, Object);
+  // Null <: A
+  checkProperSubtype(Null, A);
+  // Null <: FutureOr<A>
+  checkProperSubtype(Null, generic1(FutureOr, A));
+  // Null <: Future<A>
+  checkProperSubtype(Null, generic1(Future, A));
+  // FutureOr<Null> <: Future<Null>
+  checkSubtype(generic1(FutureOr, Null), generic1(Future, Null));
+  // Null <: Future<A?>
+  checkProperSubtype(Null, generic1(Future, nullable(A)));
+  // FutureOr<Object?> <: Object
+  checkSubtype(generic1(FutureOr, nullable(Object)), Object);
+  // FutureOr<dynamic> <: Object
+  checkSubtype(generic1(FutureOr, dynamic), Object);
+  // FutureOr<void> <: Object
+  checkSubtype(generic1(FutureOr, voidType), Object);
+}
diff --git a/tests/compiler/dartdevc_native/runtime_utils.dart b/tests/compiler/dartdevc_native/runtime_utils.dart
new file mode 100644
index 0000000..4bb6829
--- /dev/null
+++ b/tests/compiler/dartdevc_native/runtime_utils.dart
@@ -0,0 +1,80 @@
+// 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:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+// The runtime representation of the void type.
+final voidType = dart.wrapType(dart.void_);
+
+// Returns sWrapped<tWrapped> as a wrapped type.
+Type generic1(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#)', sGeneric, t));
+}
+
+// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
+Type generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  var r = dart.unwrapType(rWrapped);
+  var sGeneric = dart.getGenericClass(s);
+  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
+}
+
+// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
+Type function1(Type returnWrapped, Type argWrapped) {
+  var returnType = dart.unwrapType(returnWrapped);
+  var argType = dart.unwrapType(argWrapped);
+  var fun = dart.fnType(returnType, [argType]);
+  return dart.wrapType(fun);
+}
+
+// Returns a function type with a bounded type argument that takes no argument
+// and returns void as a wrapped type.
+Type genericFunction(Type boundWrapped) => dart.wrapType(dart.gFnType(
+    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function type with a bounded generic return type of
+// <T extends boundWrapped> argWrapped -> T as a wrapped type.
+Type functionGenericReturn(Type boundWrapped, Type argWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              T,
+              [dart.unwrapType(argWrapped)]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+// Returns a function with a bounded generic argument type of
+// <T extends boundWrapped> T -> returnWrapped as a wrapped type.
+Type functionGenericArg(Type boundWrapped, Type returnWrapped) =>
+    dart.wrapType(dart.gFnType(
+        (T) => [
+              dart.unwrapType(returnWrapped),
+              [T]
+            ],
+        (T) => [dart.unwrapType(boundWrapped)]));
+
+void checkSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+}
+
+void checkProperSubtype(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
+  checkSubtypeFailure(tWrapped, sWrapped);
+}
+
+void checkSubtypeFailure(Type sWrapped, Type tWrapped) {
+  var s = dart.unwrapType(sWrapped);
+  var t = dart.unwrapType(tWrapped);
+  Expect.isFalse(dart.isSubtypeOf(s, t), '$s should not be subtype of $t.');
+}
diff --git a/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
new file mode 100644
index 0000000..1da6b7f
--- /dev/null
+++ b/tests/compiler/dartdevc_native/runtime_utils_nnbd.dart
@@ -0,0 +1,28 @@
+// 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:_runtime' as dart;
+
+/// The runtime representation of the never type.
+final neverType = dart.wrapType(dart.never_);
+
+/// Sets the mode of the runtime subtype checks.
+///
+/// In tests the mode should be set only once at the very beginning of the test.
+/// Changing the mode after any calls to dart.isSubtype() is not supported.
+void strictSubtypeChecks(bool flag) => dart.strictSubtypeChecks(flag);
+
+/// Returns tWrapped? as a wrapped type.
+Type nullable(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tNullable = dart.nullable(t);
+  return dart.wrapType(tNullable);
+}
+
+/// Returns tWrapped* as a wrapped type.
+Type legacy(Type tWrapped) {
+  var t = dart.unwrapType(tWrapped);
+  var tLegacy = dart.legacy(t);
+  return dart.wrapType(tLegacy);
+}
diff --git a/tests/compiler/dartdevc_native/subtype_test.dart b/tests/compiler/dartdevc_native/subtype_test.dart
index fd89ae0..066500f 100644
--- a/tests/compiler/dartdevc_native/subtype_test.dart
+++ b/tests/compiler/dartdevc_native/subtype_test.dart
@@ -2,11 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:_foreign_helper' show JS;
-import 'dart:_runtime' as dart;
 import 'dart:async';
 
-import 'package:expect/expect.dart';
+import 'runtime_utils.dart';
 
 class A {}
 
@@ -20,69 +18,6 @@
 
 class F extends E<B, B> {}
 
-// Returns sWrapped<tWrapped> as a wrapped type.
-Object generic1(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#)', sGeneric, t));
-}
-
-// Returns sWrapped<tWrapped, rWrapped> as a wrapped type.
-Object generic2(Type sWrapped, Type tWrapped, Type rWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  var r = dart.unwrapType(rWrapped);
-  var sGeneric = dart.getGenericClass(s);
-  return dart.wrapType(JS('', '#(#, #)', sGeneric, t, r));
-}
-
-// Returns a function type of argWrapped -> returnWrapped as a wrapped type.
-Object function1(Type returnWrapped, Type argWrapped) {
-  var returnType = dart.unwrapType(returnWrapped);
-  var argType = dart.unwrapType(argWrapped);
-  var fun = dart.fnType(returnType, [argType]);
-  return dart.wrapType(fun);
-}
-
-// Returns a function type with a bounded type argument that takes no argument
-// and returns void as a wrapped type.
-Object genericFunction(Type boundWrapped) => dart.wrapType(dart.gFnType(
-    (T) => [dart.VoidType, []], (T) => [dart.unwrapType(boundWrapped)]));
-
-// Returns a function type with a bounded generic return type of
-// <T extends typeBoud> argWrapped -> T as a wrapped type.
-Object functionGenericReturn(Type boundWrapped, Type argWrapped) =>
-    dart.wrapType(dart.gFnType(
-        (T) => [
-              T,
-              [dart.unwrapType(argWrapped)]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
-
-// Returns a function with a bounded generic argument type of
-// <T extends typeBoud> T -> returnWrapped as a wrapped type.
-Object functionGenericArg(Type boundWrapped, Type returnWrapped) =>
-    dart.wrapType(dart.gFnType(
-        (T) => [
-              dart.unwrapType(returnWrapped),
-              [T]
-            ],
-        (T) => [dart.unwrapType(boundWrapped)]));
-
-void checkSubtype(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-}
-
-void checkProperSubtype(Type sWrapped, Type tWrapped) {
-  var s = dart.unwrapType(sWrapped);
-  var t = dart.unwrapType(tWrapped);
-  Expect.isTrue(dart.isSubtypeOf(s, t), '$s should be subtype of $t.');
-  Expect.isFalse(dart.isSubtypeOf(t, s), '$t should not be subtype of $s.');
-}
-
 void main() {
   // A <: dynamic
   checkProperSubtype(A, dynamic);
diff --git a/tests/compiler/dartdevc_native/variance_subtype_test.dart b/tests/compiler/dartdevc_native/variance_subtype_test.dart
new file mode 100644
index 0000000..46b94c2
--- /dev/null
+++ b/tests/compiler/dartdevc_native/variance_subtype_test.dart
@@ -0,0 +1,148 @@
+// 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 runtime subtyping with explicit variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+import 'dart:async';
+
+import 'runtime_utils.dart';
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+class LegacyCovariant<T> {}
+
+void main() {
+  // Covariant<Lower> <: Covariant<Middle>
+  checkProperSubtype(generic1(Covariant, Lower), generic1(Covariant, Middle));
+
+  // Covariant<Middle> <: Covariant<Middle>
+  checkSubtype(generic1(Covariant, Middle), generic1(Covariant, Middle));
+
+  // Contravariant<Upper> <: Contravariant<Middle>
+  checkProperSubtype(generic1(Contravariant, Upper), generic1(Contravariant, Middle));
+
+  // Contravariant<Middle> <: Contravariant<Middle>
+  checkSubtype(generic1(Contravariant, Middle), generic1(Contravariant, Middle));
+
+  // Invariant<Middle> <: Invariant<Middle>
+  checkSubtype(generic1(Invariant, Middle), generic1(Invariant, Middle));
+
+  // Invariant<dynamic> <:> Invariant<Object>
+  checkSubtype(generic1(Invariant, dynamic), generic1(Invariant, Object));
+  checkSubtype(generic1(Invariant, Object), generic1(Invariant, dynamic));
+
+  // Invariant<FutureOr<dynamic>> <:> Invariant<dynamic>
+  checkSubtype(generic1(Invariant, generic1(FutureOr, dynamic)), generic1(Invariant, dynamic));
+  checkSubtype(generic1(Invariant, dynamic), generic1(Invariant, generic1(FutureOr, dynamic)));
+
+  // Invariant<FutureOr<Null>> <:> Invariant<Future<Null>>
+  checkSubtype(generic1(Invariant, generic1(FutureOr, Null)), generic1(Invariant, generic1(Future, Null)));
+  checkSubtype(generic1(Invariant, generic1(Future, Null)), generic1(Invariant, generic1(FutureOr, Null)));
+
+  // LegacyCovariant<Lower> <: LegacyCovariant<Middle>
+  checkProperSubtype(generic1(LegacyCovariant, Lower), generic1(LegacyCovariant, Middle));
+
+  // List<Covariant<Lower>> <: Iterable<Covariant<Middle>>
+  checkProperSubtype(generic1(List, generic1(Covariant, Lower)), generic1(Iterable, generic1(Covariant, Middle)));
+
+  // List<Contravariant<Upper>> <: Iterable<Contravariant<Middle>>
+  checkProperSubtype(generic1(List, generic1(Contravariant, Upper)), generic1(Iterable, generic1(Contravariant, Middle)));
+
+  // List<Invariant<Middle>> <: Iterable<Invariant<Middle>>
+  checkProperSubtype(generic1(List, generic1(Invariant, Middle)), generic1(Iterable, generic1(Invariant, Middle)));
+
+  // List<LegacyCovariant<Lower>> <: Iterable<LegacyCovariant<Middle>>
+  checkProperSubtype(generic1(List, generic1(LegacyCovariant, Lower)), generic1(Iterable, generic1(LegacyCovariant, Middle)));
+
+  // String -> Covariant<Lower> <: String -> Covariant<Middle>
+  checkProperSubtype(function1(generic1(Covariant, Lower), String), function1(generic1(Covariant, Middle), String));
+
+  // Covariant<Upper> -> String <: Covariant<Middle> -> String
+  checkProperSubtype(function1(String, generic1(Covariant, Upper)), function1(String, generic1(Covariant, Middle)));
+
+  // String -> Contravariant<Upper> <: String -> Contravariant<Middle>
+  checkProperSubtype(function1(generic1(Contravariant, Upper), String), function1(generic1(Contravariant, Middle), String));
+
+  // Contravariant<Lower> -> String <: Contravariant<Middle> -> String
+  checkProperSubtype(function1(String, generic1(Contravariant, Lower)), function1(String, generic1(Contravariant, Middle)));
+
+  // String -> Invariant<Middle> <: String -> Invariant<Middle>
+  checkSubtype(function1(generic1(Invariant, Middle), String), function1(generic1(Invariant, Middle), String));
+
+  // Invariant<Middle> -> String <: Invariant<Middle> -> String
+  checkSubtype(function1(String, generic1(Invariant, Middle)), function1(String, generic1(Invariant, Middle)));
+
+  // String -> LegacyCovariant<Lower> <: String -> LegacyCovariant<Middle>
+  checkProperSubtype(function1(generic1(LegacyCovariant, Lower), String), function1(generic1(LegacyCovariant, Middle), String));
+
+  // LegacyCovariant<Upper> -> String <: LegacyCovariant<Middle> -> String
+  checkProperSubtype(function1(String, generic1(LegacyCovariant, Upper)), function1(String, generic1(LegacyCovariant, Middle)));
+
+  // Covariant<Upper> </: Covariant<Middle>
+  checkSubtypeFailure(generic1(Covariant, Upper), generic1(Covariant, Middle));
+
+  // Contravariant<Lower> </: Contravariant<Middle>
+  checkSubtypeFailure(generic1(Contravariant, Lower), generic1(Contravariant, Middle));
+
+  // Invariant<Upper> </: Invariant<Middle>
+  checkSubtypeFailure(generic1(Invariant, Upper), generic1(Invariant, Middle));
+
+  // Invariant<Lower> </: Invariant<Middle>
+  checkSubtypeFailure(generic1(Invariant, Lower), generic1(Invariant, Middle));
+
+  // LegacyCovariant<Upper> </: LegacyCovariant<Middle>
+  checkSubtypeFailure(generic1(LegacyCovariant, Upper), generic1(LegacyCovariant, Middle));
+
+  // List<Covariant<Upper>> </: Iterable<Covariant<Middle>>
+  checkSubtypeFailure(generic1(List, generic1(Covariant, Upper)), generic1(Iterable, generic1(Covariant, Middle)));
+
+  // List<Contravariant<Lower>> </: Iterable<Contravariant<Middle>>
+  checkSubtypeFailure(generic1(List, generic1(Contravariant, Lower)), generic1(Iterable, generic1(Contravariant, Middle)));
+
+  // List<Invariant<Upper>> </: Iterable<Invariant<Middle>>
+  checkSubtypeFailure(generic1(List, generic1(Invariant, Upper)), generic1(Iterable, generic1(Invariant, Middle)));
+
+  // List<Invariant<Lower>> </: Iterable<Invariant<Middle>>
+  checkSubtypeFailure(generic1(List, generic1(Invariant, Lower)), generic1(Iterable, generic1(Invariant, Middle)));
+
+  // List<LegacyCovariant<Upper>> </: Iterable<LegacyCovariant<Middle>>
+  checkSubtypeFailure(generic1(List, generic1(LegacyCovariant, Upper)), generic1(Iterable, generic1(LegacyCovariant, Middle)));
+
+  // String -> Covariant<Upper> </: String -> Covariant<Middle>
+  checkSubtypeFailure(function1(generic1(Covariant, Upper), String), function1(generic1(Covariant, Middle), String));
+
+  // Covariant<Lower> -> String </: Covariant<Middle> -> String
+  checkSubtypeFailure(function1(String, generic1(Covariant, Lower)), function1(String, generic1(Covariant, Middle)));
+
+  // String -> Contravariant<Lower> </: String -> Contravariant<Middle>
+  checkSubtypeFailure(function1(generic1(Contravariant, Lower), String), function1(generic1(Contravariant, Middle), String));
+
+  // Contravariant<Upper> -> String </: Contravariant<Middle> -> String
+  checkSubtypeFailure(function1(String, generic1(Contravariant, Upper)), function1(String, generic1(Contravariant, Middle)));
+
+  // String -> Invariant<Upper> </: String -> Invariant<Middle>
+  checkSubtypeFailure(function1(generic1(Invariant, Upper), String), function1(generic1(Invariant, Middle), String));
+
+  // Invariant<Upper> -> String </: Invariant<Middle> -> String
+  checkSubtypeFailure(function1(String, generic1(Invariant, Upper)), function1(String, generic1(Invariant, Middle)));
+
+  // String -> Invariant<Lower> </: String -> Invariant<Middle>
+  checkSubtypeFailure(function1(generic1(Invariant, Lower), String), function1(generic1(Invariant, Middle), String));
+
+  // Invariant<Lower> -> String <: Invariant<Middle> -> String
+  checkSubtypeFailure(function1(String, generic1(Invariant, Lower)), function1(String, generic1(Invariant, Middle)));
+
+  // String -> LegacyCovariant<Upper> </: String -> LegacyCovariant<Middle>
+  checkSubtypeFailure(function1(generic1(LegacyCovariant, Upper), String), function1(generic1(LegacyCovariant, Middle), String));
+
+  // LegacyCovariant<Lower> -> String </: LegacyCovariant<Middle> -> String
+  checkSubtypeFailure(function1(String, generic1(LegacyCovariant, Lower)), function1(String, generic1(LegacyCovariant, Middle)));
+}
diff --git a/tests/compiler/dartdevc_native/variance_test.dart b/tests/compiler/dartdevc_native/variance_test.dart
new file mode 100644
index 0000000..ec4fca2
--- /dev/null
+++ b/tests/compiler/dartdevc_native/variance_test.dart
@@ -0,0 +1,54 @@
+// 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 the emission of explicit variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+
+class A<in T> {}
+
+class B<out T> {}
+
+class C<inout T> {}
+
+class D<T> {}
+
+class E<inout X, out Y, in Z> {}
+
+mixin F<in T> {}
+
+class G<inout T> = Object with F<T>;
+
+List getVariances(Type typeWrapped) {
+  var type = dart.unwrapType(typeWrapped);
+  return dart.getGenericArgVariances(type);
+}
+
+void checkVariances(List v1, List v2) {
+  Expect.equals(v1.length, v2.length);
+  for (int i = 0; i < v1.length; i++) {
+    Expect.equals(v1[i], v2[i]);
+  }
+}
+
+main() {
+  checkVariances(getVariances(A), [dart.Variance.contravariant]);
+
+  checkVariances(getVariances(B), [dart.Variance.covariant]);
+
+  checkVariances(getVariances(C), [dart.Variance.invariant]);
+
+  // Implicit variance is not emitted into the generated code.
+  Expect.isNull(getVariances(D));
+
+  checkVariances(getVariances(E), [dart.Variance.invariant, dart.Variance.covariant, dart.Variance.contravariant]);
+
+  checkVariances(getVariances(F), [dart.Variance.contravariant]);
+
+  checkVariances(getVariances(G), [dart.Variance.invariant]);
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 2d8824e..834728b 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -8,10 +8,6 @@
 [ $mode == debug ]
 regexp/pcre_test: Slow # Issue 22008
 
-[ $arch == simarmv5te && ($runtime == dart_precompiled || $runtime == vm) ]
-int_parse_radix_test/*: Slow
-integer_parsed_mul_div_vm_test: Slow
-
 [ $arch == x64 && $system == windows ]
 stopwatch_test: Skip # Flaky test due to expected performance behaviour.
 
@@ -38,10 +34,7 @@
 int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
 
-[ ($arch == simdbc || $arch == simdbc64) && ($hot_reload || $hot_reload_rollback) ]
-uri_parse_test: SkipSlow
-
-[ $arch == simarm || $arch == simarm64 || $arch == simdbc64 ]
+[ $arch == simarm || $arch == simarm64 ]
 bigint_parse_radix_test: Skip # Issue 31659
 bigint_test: Skip # Issue 31659
 
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 9f28066..4e5b3d1 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -2,9 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $arch == simdbc || $arch == simdbc64 ]
-*: Skip # SIMDBC will be deleted soon.
-
 [ $builder_tag == asan ]
 data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose.
 
diff --git a/tests/ffi/send_port_id_test.dart b/tests/ffi/send_port_id_test.dart
new file mode 100644
index 0000000..abe7ccc
--- /dev/null
+++ b/tests/ffi/send_port_id_test.dart
@@ -0,0 +1,37 @@
+// 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:async';
+import 'dart:ffi';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+typedef Dart_PostIntegerNFT = IntPtr Function(Int64 port, Int64 message);
+typedef Dart_PostIntegerFT = int Function(int port, int message);
+
+main() async {
+  const int message = 112344556677888;
+
+  final completer = Completer();
+
+  final receivePort = ReceivePort()
+    ..listen((receivedMessage) => completer.complete(receivedMessage));
+
+  final executableSymbols = DynamicLibrary.executable();
+
+  final postInteger =
+      executableSymbols.lookupFunction<Dart_PostIntegerNFT, Dart_PostIntegerFT>(
+          "Dart_PostInteger");
+
+  // Issue(dartbug.com/38545): The dart:ffi doesn't have a bool type yet.
+  final bool success =
+      postInteger(receivePort.sendPort.nativePort, message) != 0;
+  Expect.isTrue(success);
+
+  final postedMessage = await completer.future;
+  Expect.equals(message, postedMessage);
+
+  receivePort.close();
+}
diff --git a/tests/language_2/extension_methods/extension_operation_in_const_test.dart b/tests/language_2/extension_methods/extension_operation_in_const_test.dart
new file mode 100644
index 0000000..4dc4b6a
--- /dev/null
+++ b/tests/language_2/extension_methods/extension_operation_in_const_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.
+
+import "package:expect/expect.dart";
+
+extension on Object {
+  int operator -() => 42;
+  int get length => 5;
+}
+
+class Tester {
+  final value;
+  const Tester.neg(Object o) : value = -o;
+  const Tester.length(Object o) : value = o.length;
+}
+
+main() {
+  const //
+      Object //# neg: compile-time error
+      i = 2;
+  const int x = -i;
+  print(x);
+
+  const //
+      Object //# length: compile-time error
+      s = "fisk";
+  const int y = s.length;
+  print(y);
+
+  Expect.equals(42, new Tester.neg(3).value);
+  const tx = Tester.neg(42); //# tneg: compile-time error
+  print(tx); //# tneg: continued
+
+  Expect.equals(5, new Tester.length("abc").value);
+  const ty = Tester.length("abc"); //# tlength: compile-time error
+  print(ty); //# tlength: continued
+}
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 4abcf1c..1aed49b 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -11,6 +11,7 @@
 extension_methods/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing extension methods.
 large_class_declaration_test: Slow
 nnbd/*: Skip
+variance/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing variance.
 
 [ $compiler == dartdevk && !$checked ]
 assertion_initializer_const_error2_test/*: SkipByDesign # DDC does not support non-checked mode.
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index 171c316..7cd6359 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -5,13 +5,10 @@
 [ $compiler == spec_parser ]
 built_in_identifier_prefix_test: Skip # A built-in identifier can _not_ be a prefix.
 closure_type_test: Pass # Marked as RuntimeError for all in language_2.status.
-conditional_import_string_test: Fail # Uses conditional import.
-conditional_import_test: Fail # Uses conditional import.
 const_native_factory_test: Skip # Uses `native`.
 deep_nesting_expression_test: Skip # JVM stack overflow.
 deep_nesting_statement_test: Skip # JVM stack overflow.
 double_invalid_test: Skip # Contains illegaly formatted double.
-extension_methods: Skip # Not yet supported.
 getter_declaration_negative_test: Fail # Negative, uses getter with parameter.
 inst_field_initializer1_negative_test: Skip # Negative, not syntax.
 instance_call_wrong_argument_count_negative_test: Skip # Negative, not syntax.
@@ -62,5 +59,6 @@
 switch1_negative_test: Fail # Negative, `default` clause not last.
 test_negative_test: Fail # Negative, uses non-terminated string literal.
 unary_plus_negative_test: Fail # Negative, uses non-existing unary plus.
+variance: Skip # Not yet supported.
 vm/debug_break_enabled_vm_test/01: Fail # Uses debug break.
 vm/debug_break_enabled_vm_test/none: Fail # Uses debug break.
diff --git a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_cascaded_test.dart b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_cascaded_test.dart
new file mode 100644
index 0000000..9678ea9
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_cascaded_test.dart
@@ -0,0 +1,33 @@
+// 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error to use nullable types in unsound ways.
+void main() {
+  List? list;
+  list..add(0); //# 00: compile-time error
+  list?..add(0); //# 01: ok
+  list..toString(); //# 02: ok
+  list?..toString(); //# 03: ok
+  list..last = 0; //# 04: compile-time error
+  list?..last = 0; //# 05: ok
+  list..[0] = 0; //# 06: compile-time error
+  list?..[0] = 0; //# 07: ok
+
+  // Note: the following look weird because they call a getter (or
+  // getter-like operator) and discard the result, but they are
+  // permitted by both the analyzer and the front end, so we should
+  // test them.
+  list..add; //# 08: compile-time error
+  list?..add; //# 09: ok
+  list..toString; //# 10: ok
+  list?..toString; //# 11: ok
+  list..last; //# 12: compile-time error
+  list?..last; //# 13: ok
+  list..runtimeType; //# 14: ok
+  list?..runtimeType; //# 15: ok
+  list..[0]; //# 16: compile-time error
+  list?..[0]; //# 17: ok
+}
diff --git a/tests/language_2/spread_collections/bind_test.dart b/tests/language_2/spread_collections/bind_test.dart
new file mode 100644
index 0000000..8619008c
--- /dev/null
+++ b/tests/language_2/spread_collections/bind_test.dart
@@ -0,0 +1,87 @@
+// 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.
+
+/// Check that spread collections can be used in combination with async/await features.
+/// This is a regression test for http://dartbug.com/38896
+
+import "package:async_helper/async_helper.dart";
+import 'package:expect/expect.dart';
+
+Future<void> asyncTest1(Future<void> f()) {
+  asyncStart();
+  return f().then(asyncSuccess);
+}
+
+void main() {
+  asyncTest1(() async {
+    await awaitSpreadMemberCallBindTest(); // A
+    await yieldSpreadMemberCallBindTest(); // C
+    await spreadAwaitMemberCallBindTest(); // G
+    await spreadAwaitMemberAccessBindTest(); // I
+  });
+}
+
+class A {
+  List<int> m1() => [1, 2];
+  Future<List<int>> run() async {
+    return [await null, ...m1()];
+  }
+}
+
+Future<void> awaitSpreadMemberCallBindTest() async {
+  // spread on member call in await
+  Expect.listEquals([null, 1, 2], await A().run());
+}
+
+class C {
+  List<int> m2() => [1, 2];
+
+  Future<List<int>> run() async {
+    return await run3().toList();
+  }
+
+  Stream<int> run3() async* {
+    for (var k in [...await m2()]) yield k;
+  }
+}
+
+Future<void> yieldSpreadMemberCallBindTest() async {
+  var expected = [1, 2];
+
+  // spread on await of member call with yield
+  Expect.listEquals(expected, await C().run());
+}
+
+class G {
+  List<int> m2() => [1, 2];
+
+  Future<List<int>> run() async {
+    return [...await m2()];
+  }
+}
+
+Future<void> spreadAwaitMemberCallBindTest() async {
+  var expected = [1, 2];
+
+  // spread on await of member call
+  Expect.listEquals(expected, await G().run());
+}
+
+class I1 {
+  List<int> foo() => [1, 2];
+}
+
+class I {
+  I1 b = I1();
+  Future<List<int>> run() async {
+    return [...await b.foo()];
+  }
+}
+
+Future<void> spreadAwaitMemberAccessBindTest() async {
+  var expected = [1, 2];
+
+  // spread on await of member access
+  Expect.listEquals(expected, await I().run());
+}
diff --git a/tests/language_2/variance/variance_in_field_error_test.dart b/tests/language_2/variance/variance_in_field_error_test.dart
new file mode 100644
index 0000000..2250cda
--- /dev/null
+++ b/tests/language_2/variance/variance_in_field_error_test.dart
@@ -0,0 +1,61 @@
+// 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 erroneous field usage for the `in` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class A<in T> {
+  final T a = null;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  final T Function() b = () => null;
+  //                 ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  T get c => null;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  T d;
+  //^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  covariant T e;
+  //          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+}
+
+mixin BMixin<in T> {
+  final T a = null;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  final T Function() b = () => null;
+  //                 ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  T get c => null;
+  //      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  T d;
+  //^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  covariant T e;
+  //          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+}
diff --git a/tests/language_2/variance/variance_in_method_error_test.dart b/tests/language_2/variance/variance_in_method_error_test.dart
new file mode 100644
index 0000000..af5ef41
--- /dev/null
+++ b/tests/language_2/variance/variance_in_method_error_test.dart
@@ -0,0 +1,296 @@
+// 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 erroneous method signatures and return types for the `in` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+typedef Inv<T> = void Function<X extends T>();
+typedef Cov<T> = T Function();
+typedef Contra<T> = void Function(T);
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
+class A<in T> {
+  // TODO (kallentu): Come NNBD, change `T` to `T?`
+  T method1() => null;
+  //       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method2(Contra<T> x) {}
+  //                     ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Cov<T> method3() {
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+    return () => null;
+  }
+
+  void method4(Contra<Cov<T>> x) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method5(Cov<Contra<T>> x) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Contra<Contra<T>> method6() => (Contra<T> x) {};
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  Cov<Cov<T>> method7() {
+  //                 ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+    return () {
+      return () => null;
+    };
+  }
+
+  Inv<T> method8() => null;
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
+
+  void method9(Inv<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  Covariant<T> method10() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method11(Contravariant<T> x) {}
+  //                             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Invariant<T> method12() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
+
+  void method13(Invariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method14(Contravariant<Covariant<T>> x) {}
+  //                                        ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method15(Covariant<Contravariant<T>> x) {}
+  //                                        ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Contravariant<Contravariant<T>> method16() => Contravariant<Contravariant<T>>();
+  //                                      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  Covariant<Covariant<T>> method17() => Covariant<Covariant<T>>();
+  //                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method18<X extends T>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method19<X extends Cov<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method20<X extends Covariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method21({Contra<T> x}) {}
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method22({Contravariant<T> x}) {}
+  //                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method23({Covariant<T> x, Contravariant<T> y}) {}
+  //                                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method24<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method25<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+}
+
+mixin BMixin<in T> {
+  // TODO (kallentu): Come NNBD, change `T` to `T?`
+  T method1() => null;
+  //       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method2(Contra<T> x) {}
+  //                     ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Cov<T> method3() {
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+    return () => null;
+  }
+
+  void method4(Contra<Cov<T>> x) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method5(Cov<Contra<T>> x) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Contra<Contra<T>> method6() => (Contra<T> x) {};
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  Cov<Cov<T>> method7() {
+  //                 ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+    return () {
+      return () => null;
+    };
+  }
+
+  Inv<T> method8() => null;
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
+
+  void method9(Inv<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  Covariant<T> method10() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method11(Contravariant<T> x) {}
+  //                             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Invariant<T> method12() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
+
+  void method13(Invariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method14(Contravariant<Covariant<T>> x) {}
+  //                                        ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method15(Covariant<Contravariant<T>> x) {}
+  //                                        ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  Contravariant<Contravariant<T>> method16() => Contravariant<Contravariant<T>>();
+  //                                      ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  Covariant<Covariant<T>> method17() => Covariant<Covariant<T>>();
+  //                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+
+  void method18<X extends T>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method19<X extends Cov<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method20<X extends Covariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method21({Contra<T> x}) {}
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method22({Contravariant<T> x}) {}
+  //                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method23({Covariant<T> x, Contravariant<T> y}) {}
+  //                                              ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+
+  void method24<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+
+  void method25<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
+}
+
+class B<in T> {
+  void method1(A<T> x) {}
+  //                ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+  Contra<A<T>> method2() {
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+    return null;
+  }
+}
diff --git a/tests/language_2/variance/variance_in_method_test.dart b/tests/language_2/variance/variance_in_method_test.dart
index 36a6d98..f209a16 100644
--- a/tests/language_2/variance/variance_in_method_test.dart
+++ b/tests/language_2/variance/variance_in_method_test.dart
@@ -11,6 +11,12 @@
 typedef Cov<T> = T Function();
 typedef Contra<T> = void Function(T);
 
+Cov<int> covFunction = () => 2;
+Contra<int> contraFunction = (int val) {};
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+
 class A<in T> {
   void method1(T x) {}
   void method2(Cov<T> x) {}
@@ -34,6 +40,23 @@
     };
   }
   void method7(Contra<Contra<T>> x) {}
+
+  void method8(Covariant<T> x) {}
+  Contravariant<T> method9() => null;
+  void method10(Covariant<Covariant<T>> x) {}
+  Contravariant<Covariant<T>> method11() => null;
+  void method12(Contravariant<Contravariant<T>> x) {}
+  Covariant<Contravariant<T>> method13() => null;
+
+  void method14(covariant T x) {}
+  void method15(covariant Contra<T> x) {}
+  void method16(covariant Cov<T> x) {}
+  void method17(covariant Contravariant<T> x) {}
+  void method18(covariant Covariant<T> x) {}
+
+  void method19({T x}) {}
+  void method20({Covariant<T> x}) {}
+  void method21({Cov<T> x}) {}
 }
 
 mixin BMixin<in T> {
@@ -59,6 +82,23 @@
     };
   }
   void method7(Contra<Contra<T>> x) {}
+
+  void method8(Covariant<T> x) {}
+  Contravariant<T> method9() => null;
+  void method10(Covariant<Covariant<T>> x) {}
+  Contravariant<Covariant<T>> method11() => null;
+  void method12(Contravariant<Contravariant<T>> x) {}
+  Covariant<Contravariant<T>> method13() => null;
+
+  void method14(covariant T x) {}
+  void method15(covariant Contra<T> x) {}
+  void method16(covariant Cov<T> x) {}
+  void method17(covariant Contravariant<T> x) {}
+  void method18(covariant Covariant<T> x) {}
+
+  void method19({T x}) {}
+  void method20({Covariant<T> x}) {}
+  void method21({Cov<T> x}) {}
 }
 
 class B with BMixin<int> {}
@@ -75,19 +115,19 @@
 
   a.method1(2);
 
-  a.method2(() => 2);
+  a.method2(covFunction);
 
   Expect.type<Contra<int>>(a.method3());
   Contra<int> method3Function = a.method3();
   method3Function(2);
 
   a.method4(() {
-    return () => 2;
+    return covFunction;
   });
 
   Expect.type<Contra<Cov<int>>>(a.method5());
   Contra<Cov<int>> method5Function = a.method5();
-  method5Function(() => 2);
+  method5Function(covFunction);
 
   Expect.type<Cov<Contra<int>>>(a.method6());
   Cov<Contra<int>> method6Function = a.method6();
@@ -96,6 +136,23 @@
   method6NestedFunction(2);
 
   a.method7((Contra<int> x) {});
+
+  a.method8(Covariant<int>());
+  Expect.isNull(a.method9());
+  a.method10(Covariant<Covariant<int>>());
+  Expect.isNull(a.method11());
+  a.method12(Contravariant<Contravariant<int>>());
+  Expect.isNull(a.method13());
+
+  a.method14(3);
+  a.method15(contraFunction);
+  a.method16(covFunction);
+  a.method17(Contravariant<int>());
+  a.method18(Covariant<int>());
+
+  a.method19();
+  a.method20();
+  a.method21();
 }
 
 void testMixin() {
@@ -103,19 +160,19 @@
 
   b.method1(2);
 
-  b.method2(() => 2);
+  b.method2(covFunction);
 
   Expect.type<Contra<int>>(b.method3());
   Contra<int> method3Return = b.method3();
   method3Return(2);
 
   b.method4(() {
-    return () => 2;
+    return covFunction;
   });
 
   Expect.type<Contra<Cov<int>>>(b.method5());
   Contra<Cov<int>> method5Return = b.method5();
-  method5Return(() => 2);
+  method5Return(covFunction);
 
   Expect.type<Cov<Contra<int>>>(b.method6());
   Cov<Contra<int>> method6Function = b.method6();
@@ -124,6 +181,23 @@
   method6NestedFunction(2);
 
   b.method7((Contra<int> x) {});
+
+  b.method8(Covariant<int>());
+  Expect.isNull(b.method9());
+  b.method10(Covariant<Covariant<int>>());
+  Expect.isNull(b.method11());
+  b.method12(Contravariant<Contravariant<int>>());
+  Expect.isNull(b.method13());
+
+  b.method14(3);
+  b.method15(contraFunction);
+  b.method16(covFunction);
+  b.method17(Contravariant<int>());
+  b.method18(Covariant<int>());
+
+  b.method19();
+  b.method20();
+  b.method21();
 }
 
 void testClassInMethods() {
diff --git a/tests/language_2/variance/variance_in_subclass_error_test.dart b/tests/language_2/variance/variance_in_subclass_error_test.dart
index 7b0db8e..6899685 100644
--- a/tests/language_2/variance/variance_in_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_in_subclass_error_test.dart
@@ -22,102 +22,102 @@
 class A<in T> extends LegacyCovariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'LegacyCovariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'LegacyCovariant'.
 
 class B<in T> implements LegacyCovariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'LegacyCovariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'LegacyCovariant'.
 
 class C<in T> with MLegacyCovariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MLegacyCovariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MLegacyCovariant'.
 
 class D<in T> extends Covariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class E<in T> implements Covariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class F<in T> with MCovariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MCovariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MCovariant'.
 
 class G<in T> extends Invariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
 
 class H<in T> implements Invariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
 
 class I<in T> with MInvariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MInvariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MInvariant'.
 
 class J<in T> extends Covariant<Covariant<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class K<in T> extends Contravariant<Contravariant<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Contravariant'.
 
 class L<in T> extends Covariant<CovFunction<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class M<in T> extends Covariant<ContraFunction<ContraFunction<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class N<in T> extends Contravariant<CovFunction<Contravariant<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Contravariant'.
 
 class O<in T> extends Covariant<CovFunction<Covariant<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class P<in T> extends Covariant<Covariant<Covariant<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class Q<in T> extends Invariant<InvFunction<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
 
 class R<in T> = Covariant<T> with MContravariant<T>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class S<in T> = Contravariant<T> with MCovariant<T>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MCovariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MCovariant'.
 
 class T<in X> = Invariant<X> with MInvariant<X>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'X' in supertype 'Invariant'.
+// [cfe] Can't use 'in' type variable 'X' in an 'inout' position in supertype 'Invariant'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'X' in supertype 'MInvariant'.
+// [cfe] Can't use 'in' type variable 'X' in an 'inout' position in supertype 'MInvariant'.
diff --git a/tests/language_2/variance/variance_in_subtyping_test.dart b/tests/language_2/variance/variance_in_subtyping_test.dart
index c44d77e..df89b2b 100644
--- a/tests/language_2/variance/variance_in_subtyping_test.dart
+++ b/tests/language_2/variance/variance_in_subtyping_test.dart
@@ -6,6 +6,8 @@
 
 // SharedOptions=--enable-experiment=variance
 
+import "package:expect/expect.dart";
+
 class Contravariant<in T> {}
 
 class Upper {}
@@ -58,14 +60,23 @@
 
 main() {
   A a = new A();
+  Expect.type<Contravariant<Middle>>(a.method1());
+  Expect.type<Contravariant<Lower>>(a.method1());
+  Expect.notType<Contravariant<Upper>>(a.method1());
   a.method2(new Contravariant<Middle>());
   a.method2(new Contravariant<Upper>());
 
   B b = new B();
+  Expect.type<Contravariant<Upper>>(b.method1());
+  Expect.type<Contravariant<Middle>>(b.method1());
+  Expect.type<Contravariant<Lower>>(b.method1());
   b.method2(new Contravariant<Lower>());
   b.method2(new Contravariant<Middle>());
 
   C c = new C();
+  Expect.type<Contravariant<Middle>>(c.method1());
+  Expect.type<Contravariant<Lower>>(c.method1());
+  Expect.notType<Contravariant<Upper>>(c.method1());
   c.method2(new Contravariant<Middle>());
   c.method2(new Contravariant<Upper>());
 
@@ -73,12 +84,19 @@
   D<Contravariant<Middle>> dMiddle = new D<Contravariant<Middle>>();
 
   E e = new E();
+  Expect.type<D<Contravariant<Upper>>>(e.method1());
+  Expect.type<D<Contravariant<Middle>>>(e.method1());
 
   F f = new F();
+  Expect.type<D<Contravariant<Middle>>>(e.method1());
 
   Iterable<Contravariant<Lower>> iterableLower = [new Contravariant<Lower>()];
   List<Contravariant<Middle>> listMiddle = [new Contravariant<Middle>()];
   iterableLower = listMiddle;
 
   testCall(listMiddle);
+
+  Expect.subtype<Contravariant<Upper>, Contravariant<Middle>>();
+  Expect.subtype<Contravariant<Middle>, Contravariant<Middle>>();
+  Expect.notSubtype<Contravariant<Lower>, Contravariant<Middle>>();
 }
diff --git a/tests/language_2/variance/variance_inout_field_test.dart b/tests/language_2/variance/variance_inout_field_test.dart
index 58fe155..49e2349 100644
--- a/tests/language_2/variance/variance_inout_field_test.dart
+++ b/tests/language_2/variance/variance_inout_field_test.dart
@@ -19,6 +19,10 @@
     Expect.equals(2, val);
   };
   A<T> get e => this;
+  covariant T f;
+  T get g => null;
+  void set h(T value) => value;
+  void set i(covariant T value) => value;
 }
 
 mixin BMixin<inout T> {
@@ -29,6 +33,10 @@
     Expect.equals(2, val);
   };
   BMixin<T> get e => this;
+  covariant T f;
+  T get g => null;
+  void set h(T value) => value;
+  void set i(covariant T value) => value;
 }
 
 class B with BMixin<int> {}
@@ -48,6 +56,15 @@
   a.d(2);
 
   a.e.a = 3;
+
+  a.f = 2;
+  Expect.equals(2, a.f);
+
+  Expect.isNull(a.g);
+
+  a.h = 2;
+
+  a.i = 2;
 }
 
 void testMixin() {
@@ -65,6 +82,15 @@
   b.d(2);
 
   b.e.a = 3;
+
+  b.f = 2;
+  Expect.equals(2, b.f);
+
+  Expect.isNull(b.g);
+
+  b.h = 2;
+
+  b.i = 2;
 }
 
 main() {
diff --git a/tests/language_2/variance/variance_inout_method_test.dart b/tests/language_2/variance/variance_inout_method_test.dart
index e167928..f533b71 100644
--- a/tests/language_2/variance/variance_inout_method_test.dart
+++ b/tests/language_2/variance/variance_inout_method_test.dart
@@ -10,13 +10,17 @@
 
 typedef Cov<T> = T Function();
 typedef Contra<T> = void Function(T);
+
 Cov<int> covFunction = () => 2;
 Contra<int> contraFunction = (int val) {};
 Cov<num> covFunctionNum = () => 2;
 Contra<num> contraFunctionNum = (num val) {};
 
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
 class A<inout T> {
-  // Contravariant positions
   void method1(T x) {}
   void method2(Cov<T> x) {}
   Contra<T> method3() {
@@ -25,23 +29,41 @@
     };
   }
 
-  // Covariant positions
   T method4() => null;
   void method5(Contra<T> x) {}
   Cov<T> method6() {
     return () => null;
   }
 
-  // Invariant member signatures
   T method7(T x) => x;
   Contra<T> method8(Contra<T> x) => x;
   Cov<T> method9(Cov<T> x) => x;
 
   T method10<S extends T>(S x) => x;
+
+  void method11(Covariant<T> x) {}
+  Covariant<T> method12() => null;
+  void method13(Contravariant<T> x) {}
+  Contravariant<T> method14() => null;
+  void method15(Invariant<T> x) {}
+  Invariant<T> method16() => null;
+
+  void method17(covariant T x) {}
+  void method18(covariant Contra<T> x) {}
+  void method19(covariant Cov<T> x) {}
+  void method20(covariant Contravariant<T> x) {}
+  void method21(covariant Covariant<T> x) {}
+
+  void method22<S extends Contravariant<T>>() {}
+  void method23<S extends Covariant<T>>() {}
+  void method24<S extends Contra<T>>() {}
+  void method25<S extends Cov<T>>() {}
+
+  void method26({Contra<T> a, Cov<T> b, T c}) {}
+  void method27({Contravariant<T> a, Covariant<T> b}) {}
 }
 
 mixin BMixin<inout T> {
-  // Contravariant positions
   void method1(T x) {}
   void method2(Cov<T> x) {}
   Contra<T> method3() {
@@ -50,19 +72,38 @@
     };
   }
 
-  // Covariant positions
   T method4() => null;
   void method5(Contra<T> x) {}
   Cov<T> method6() {
     return () => null;
   }
 
-  // Invariant member signatures
   T method7(T x) => x;
   Contra<T> method8(Contra<T> x) => x;
   Cov<T> method9(Cov<T> x) => x;
 
   T method10<S extends T>(S x) => x;
+
+  void method11(Covariant<T> x) {}
+  Covariant<T> method12() => null;
+  void method13(Contravariant<T> x) {}
+  Contravariant<T> method14() => null;
+  void method15(Invariant<T> x) {}
+  Invariant<T> method16() => null;
+
+  void method17(covariant T x) {}
+  void method18(covariant Contra<T> x) {}
+  void method19(covariant Cov<T> x) {}
+  void method20(covariant Contravariant<T> x) {}
+  void method21(covariant Covariant<T> x) {}
+
+  void method22<S extends Contravariant<T>>() {}
+  void method23<S extends Covariant<T>>() {}
+  void method24<S extends Contra<T>>() {}
+  void method25<S extends Cov<T>>() {}
+
+  void method26({Contra<T> a, Cov<T> b, T c}) {}
+  void method27({Contravariant<T> a, Covariant<T> b}) {}
 }
 
 class B with BMixin<num> {}
@@ -104,6 +145,27 @@
 
   A<num> aa = new A();
   Expect.type<num>(aa.method10(3));
+
+  a.method11(Covariant<int>());
+  Expect.isNull(a.method12());
+  a.method13(Contravariant<int>());
+  Expect.isNull(a.method14());
+  a.method15(Invariant<int>());
+  Expect.isNull(a.method16());
+
+  a.method17(3);
+  a.method18(contraFunction);
+  a.method19(covFunction);
+  a.method20(Contravariant<int>());
+  a.method21(Covariant<int>());
+
+  a.method22<Contravariant<int>>();
+  a.method23<Covariant<int>>();
+  a.method24<Contra<int>>();
+  a.method25<Cov<int>>();
+
+  a.method26();
+  a.method27();
 }
 
 void testMixin() {
@@ -134,6 +196,27 @@
   Expect.equals(covFunctionNum, b.method9(covFunctionNum));
 
   Expect.type<num>(b.method10(3));
+
+  b.method11(Covariant<num>());
+  Expect.isNull(b.method12());
+  b.method13(Contravariant<num>());
+  Expect.isNull(b.method14());
+  b.method15(Invariant<num>());
+  Expect.isNull(b.method16());
+
+  b.method17(3);
+  b.method18(contraFunctionNum);
+  b.method19(covFunctionNum);
+  b.method20(Contravariant<num>());
+  b.method21(Covariant<num>());
+
+  b.method22<Contravariant<num>>();
+  b.method23<Covariant<num>>();
+  b.method24<Contra<num>>();
+  b.method25<Cov<num>>();
+
+  b.method26();
+  b.method27();
 }
 
 void testClassInMethods() {
diff --git a/tests/language_2/variance/variance_inout_subtyping_test.dart b/tests/language_2/variance/variance_inout_subtyping_test.dart
index 9ebdea5..d245002 100644
--- a/tests/language_2/variance/variance_inout_subtyping_test.dart
+++ b/tests/language_2/variance/variance_inout_subtyping_test.dart
@@ -6,6 +6,10 @@
 
 // SharedOptions=--enable-experiment=variance
 
+import 'dart:async';
+
+import "package:expect/expect.dart";
+
 class Invariant<inout T> {}
 
 class Upper {}
@@ -38,22 +42,129 @@
   }
 }
 
+class E {
+  Invariant<dynamic> method1() {
+    return new Invariant<dynamic>();
+  }
+
+  void method2(Invariant<Object> x) {}
+}
+
+class F extends E {
+  @override
+  Invariant<Object> method1() {
+    return new Invariant<Object>();
+  }
+
+  @override
+  void method2(Invariant<dynamic> x) {}
+}
+
+class G {
+  Invariant<dynamic> method1() {
+    return new Invariant<dynamic>();
+  }
+
+  void method2(Invariant<FutureOr<dynamic>> x) {}
+}
+
+class H extends G {
+  @override
+  Invariant<FutureOr<dynamic>> method1() {
+    return new Invariant<FutureOr<dynamic>>();
+  }
+
+  @override
+  void method2(Invariant<dynamic> x) {}
+}
+
+class I {
+  Invariant<FutureOr<Null>> method1() {
+    return new Invariant<FutureOr<Null>>();
+  }
+
+  void method2(Invariant<Future<Null>> x) {}
+}
+
+class J extends I {
+  @override
+  Invariant<Future<Null>> method1() {
+    return new Invariant<Future<Null>>();
+  }
+
+  @override
+  void method2(Invariant<FutureOr<Null>> x) {}
+}
+
 void testCall(Iterable<Invariant<Middle>> x) {}
 
 main() {
   A a = new A();
+  Expect.type<Invariant<Middle>>(a.method1());
+  Expect.notType<Invariant<Upper>>(a.method1());
+  Expect.notType<Invariant<Lower>>(a.method1());
   a.method2(new Invariant<Middle>());
 
   B b = new B();
+  Expect.type<Invariant<Middle>>(b.method1());
+  Expect.notType<Invariant<Upper>>(b.method1());
+  Expect.notType<Invariant<Lower>>(b.method1());
   b.method2(new Invariant<Middle>());
 
   C<Invariant<Middle>> c = new C<Invariant<Middle>>();
 
   D d = new D();
+  Expect.type<C<Invariant<Middle>>>(d.method1());
+
+  E e = new E();
+  Expect.type<Invariant<dynamic>>(e.method1());
+  e.method2(new Invariant<Object>());
+
+  // Invariant<dynamic> <:> Invariant<Object>
+  F f = new F();
+  Expect.type<Invariant<Object>>(f.method1());
+  Expect.type<Invariant<dynamic>>(f.method1());
+  f.method2(new Invariant<Object>());
+  f.method2(new Invariant<dynamic>());
+
+  G g = new G();
+  Expect.type<Invariant<dynamic>>(g.method1());
+  g.method2(new Invariant<FutureOr<dynamic>>());
+
+  // Invariant<FutureOr<dynamic>> <:> Invariant<dynamic>
+  H h = new H();
+  Expect.type<Invariant<FutureOr<dynamic>>>(h.method1());
+  Expect.type<Invariant<dynamic>>(h.method1());
+  h.method2(new Invariant<FutureOr<dynamic>>());
+  h.method2(new Invariant<dynamic>());
+
+  I i = new I();
+  Expect.type<Invariant<FutureOr<Null>>>(i.method1());
+  i.method2(new Invariant<Future<Null>>());
+
+  // Invariant<FutureOr<Null>> <:> Invariant<Future<Null>>
+  J j = new J();
+  Expect.type<Invariant<FutureOr<Null>>>(j.method1());
+  Expect.type<Invariant<Future<Null>>>(j.method1());
+  j.method2(new Invariant<FutureOr<Null>>());
+  j.method2(new Invariant<Future<Null>>());
 
   Iterable<Invariant<Middle>> iterableMiddle = [new Invariant<Middle>()];
   List<Invariant<Middle>> listMiddle = [new Invariant<Middle>()];
   iterableMiddle = listMiddle;
 
   testCall(listMiddle);
+
+  Expect.subtype<Invariant<Middle>, Invariant<Middle>>();
+  Expect.notSubtype<Invariant<Lower>, Invariant<Middle>>();
+  Expect.notSubtype<Invariant<Upper>, Invariant<Middle>>();
+
+  Expect.subtype<Invariant<dynamic>, Invariant<Object>>();
+  Expect.subtype<Invariant<Object>, Invariant<dynamic>>();
+
+  Expect.subtype<Invariant<FutureOr<dynamic>>, Invariant<dynamic>>();
+  Expect.subtype<Invariant<dynamic>, Invariant<FutureOr<dynamic>>>();
+
+  Expect.subtype<Invariant<FutureOr<Null>>, Invariant<Future<Null>>>();
+  Expect.subtype<Invariant<Future<Null>>, Invariant<FutureOr<Null>>>();
 }
diff --git a/tests/language_2/variance/variance_multi_subclass_error_test.dart b/tests/language_2/variance/variance_multi_subclass_error_test.dart
index 358c81f..18e2db2 100644
--- a/tests/language_2/variance/variance_multi_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_multi_subclass_error_test.dart
@@ -18,54 +18,54 @@
 class A<in T, out U, inout V> extends Covariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
 
 class B<in T> extends MultiThree<T, T, T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiThree'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MultiThree'.
 
 class C<in T, out U, inout V> extends MultiTwo<U, T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiTwo'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'U' in supertype 'MultiTwo'.
+// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
 
 class D<in T, out U, inout V> extends MultiThree<V, U, T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiThree'.
+// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MultiThree'.
 
 class E<in T, out U, inout V> extends MultiThree<Covariant<U>, Covariant<T>, Covariant<U>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiThree'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiThree'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'U' in supertype 'MultiThree'.
+// [cfe] Can't use 'out' type variable 'U' in an 'inout' position in supertype 'MultiThree'.
 
 class F<in T, out U, inout V> extends MultiTwo<Contravariant<T>, Contravariant<U>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiTwo'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'U' in supertype 'MultiTwo'.
+// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
 
 class G<in T, out U, inout V> extends MultiThree<CovFunction<U>, CovFunction<T>, CovFunction<U>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiThree'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiThree'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'U' in supertype 'MultiThree'.
+// [cfe] Can't use 'out' type variable 'U' in an 'inout' position in supertype 'MultiThree'.
 
 class H<in T, out U, inout V> extends MultiTwo<ContraFunction<T>, ContraFunction<U>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MultiTwo'.
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'U' in supertype 'MultiTwo'.
+// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
diff --git a/tests/language_2/variance/variance_out_field_error_test.dart b/tests/language_2/variance/variance_out_field_error_test.dart
new file mode 100644
index 0000000..629cf96
--- /dev/null
+++ b/tests/language_2/variance/variance_out_field_error_test.dart
@@ -0,0 +1,37 @@
+// 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 erroneous field usage for the `out` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+class A<out T> {
+  void set a(T value) => value;
+  //           ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+  final void Function(T) b = (T val) {};
+  //                     ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+  T c;
+  //^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+}
+
+mixin BMixin<out T> {
+  void set a(T value) => value;
+  //           ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+  final void Function(T) b = (T val) {};
+  //                     ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+  T c;
+  //^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+}
diff --git a/tests/language_2/variance/variance_out_field_test.dart b/tests/language_2/variance/variance_out_field_test.dart
index f39945f..775d2a6 100644
--- a/tests/language_2/variance/variance_out_field_test.dart
+++ b/tests/language_2/variance/variance_out_field_test.dart
@@ -15,6 +15,8 @@
   final T Function() b = () => null;
   T get c => null;
   A<T> get d => this;
+  covariant T e;
+  void set f(covariant T value) => value;
 }
 
 mixin BMixin<out T> {
@@ -22,6 +24,8 @@
   final T Function() b = () => null;
   T get c => null;
   BMixin<T> get d => this;
+  covariant T e;
+  void set f(covariant T value) => value;
 }
 
 class B with BMixin<int> {}
@@ -37,6 +41,11 @@
   Expect.isNull(a.c);
 
   Expect.isNull(a.d.a);
+
+  a.e = 2;
+  Expect.equals(2, a.e);
+
+  a.f = 2;
 }
 
 void testMixin() {
@@ -50,6 +59,11 @@
   Expect.isNull(b.c);
 
   Expect.isNull(b.d.a);
+
+  b.e = 2;
+  Expect.equals(2, b.e);
+
+  b.f = 2;
 }
 
 main() {
diff --git a/tests/language_2/variance/variance_out_method_error_test.dart b/tests/language_2/variance/variance_out_method_error_test.dart
new file mode 100644
index 0000000..fc4264b
--- /dev/null
+++ b/tests/language_2/variance/variance_out_method_error_test.dart
@@ -0,0 +1,300 @@
+// 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 erroneous method signatures and return types for the `out` variance modifier.
+
+// SharedOptions=--enable-experiment=variance
+
+typedef Inv<T> = void Function<X extends T>();
+typedef Cov<T> = T Function();
+typedef Contra<T> = void Function(T);
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+
+class A<out T> {
+  void method1(T x) {}
+  //             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method2(Cov<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contra<T> method3() => (T val) {};
+  //               ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method4(Cov<Cov<T>> x) {}
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contra<Cov<T>> method5() => (Cov<T> method) {};
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  Cov<Contra<T>> method6() {
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+    return () {
+      return (T x) {};
+    };
+  }
+
+  void method7(Contra<Contra<T>> x) {}
+  //                             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Inv<T> method8() => null;
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
+
+  void method9(Inv<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  Contravariant<T> method10() => null;
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method11(Covariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Invariant<T> method12() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
+
+  void method13(Invariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method14(Covariant<Covariant<T>> x) {}
+  //                                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method15(Contravariant<Contravariant<T>> x) {}
+  //                                            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contravariant<Covariant<T>> method16() => Contravariant<Covariant<T>>();
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  Covariant<Contravariant<T>> method17() => Covariant<Contravariant<T>>();
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method18<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method19<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method20({T x}) {}
+  //               ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method21({Cov<T> x}) {}
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method22({Covariant<T> x}) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method23({Covariant<T> x, Contravariant<T> y}) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method24<X extends T>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method25<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method26<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+}
+
+mixin BMixin<out T> {
+  void method1(T x) {}
+  //             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method2(Cov<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contra<T> method3() => (T val) {};
+  //               ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method4(Cov<Cov<T>> x) {}
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contra<Cov<T>> method5() => (Cov<T> method) {};
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  Cov<Contra<T>> method6() {
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+    return () {
+      return (T x) {};
+    };
+  }
+
+  void method7(Contra<Contra<T>> x) {}
+  //                             ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Inv<T> method8() => null;
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
+
+  void method9(Inv<T> x) {}
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  Contravariant<T> method10() => null;
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method11(Covariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Invariant<T> method12() => null;
+  //                   ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
+
+  void method13(Invariant<T> x) {}
+  //                         ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method14(Covariant<Covariant<T>> x) {}
+  //                                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method15(Contravariant<Contravariant<T>> x) {}
+  //                                            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  Contravariant<Covariant<T>> method16() => Contravariant<Covariant<T>>();
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  Covariant<Contravariant<T>> method17() => Covariant<Contravariant<T>>();
+  //                                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+
+  void method18<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method19<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method20({T x}) {}
+  //               ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method21({Cov<T> x}) {}
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method22({Covariant<T> x}) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method23({Covariant<T> x, Contravariant<T> y}) {}
+  //                          ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+
+  void method24<X extends T>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method25<X extends Contra<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+
+  void method26<X extends Contravariant<T>>() {}
+  //            ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
+}
+
+class B<out T> {
+  void method1(Cov<A<T>> x) {}
+  //                     ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+  Contra<A<T>> method2() {
+  //                  ^
+  // [analyzer] unspecified
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
+    return null;
+  }
+}
diff --git a/tests/language_2/variance/variance_out_method_test.dart b/tests/language_2/variance/variance_out_method_test.dart
index 0b0e0ff..64bde43 100644
--- a/tests/language_2/variance/variance_out_method_test.dart
+++ b/tests/language_2/variance/variance_out_method_test.dart
@@ -11,6 +11,12 @@
 typedef Cov<T> = T Function();
 typedef Contra<T> = void Function(T);
 
+Cov<int> covFunction = () => 2;
+Contra<int> contraFunction = (int val) {};
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+
 class A<out T> {
   // TODO (kallentu): Come NNBD, change `T` to `T?`
   T method1() => null;
@@ -32,6 +38,22 @@
       return () => null;
     };
   }
+
+  void method8(Contravariant<T> x) {}
+  Covariant<T> method9() => null;
+  void method10(Contravariant<Covariant<T>> x) {}
+  Covariant<Covariant<T>> method11() => null;
+  void method12(Covariant<Contravariant<T>> x) {}
+  Contravariant<Contravariant<T>> method13() => null;
+
+  void method14(covariant T x) {}
+  void method15(covariant Contra<T> x) {}
+  void method16(covariant Cov<T> x) {}
+  void method17(covariant Contravariant<T> x) {}
+  void method18(covariant Covariant<T> x) {}
+
+  void method19({Contravariant<T> x}) {}
+  void method20({Contra<T> x}) {}
 }
 
 mixin BMixin<out T> {
@@ -55,6 +77,22 @@
       return () => null;
     };
   }
+
+  void method8(Contravariant<T> x) {}
+  Covariant<T> method9() => null;
+  void method10(Contravariant<Covariant<T>> x) {}
+  Covariant<Covariant<T>> method11() => null;
+  void method12(Covariant<Contravariant<T>> x) {}
+  Contravariant<Contravariant<T>> method13() => null;
+
+  void method14(covariant T x) {}
+  void method15(covariant Contra<T> x) {}
+  void method16(covariant Cov<T> x) {}
+  void method17(covariant Contravariant<T> x) {}
+  void method18(covariant Covariant<T> x) {}
+
+  void method19({Contravariant<T> x}) {}
+  void method20({Contra<T> x}) {}
 }
 
 class B with BMixin<int> {}
@@ -71,9 +109,7 @@
 
   Expect.isNull(a.method1());
 
-  a.method2((int x) {
-    Expect.equals(2, x);
-  });
+  a.method2(contraFunction);
 
   Expect.type<Cov<int>>(a.method3());
   Cov<int> method3Function = a.method3();
@@ -82,18 +118,34 @@
   a.method4((Cov<int> x) {});
 
   a.method5(() {
-    return (int x) {};
+    return contraFunction;
   });
 
   Expect.type<Contra<Contra<int>>>(a.method6());
   Contra<Contra<int>> method6Function = a.method6();
-  method6Function((int x) {});
+  method6Function(contraFunction);
 
   Expect.type<Cov<Cov<int>>>(a.method7());
   Cov<Cov<int>> method7Function = a.method7();
   Expect.type<Cov<int>>(method7Function());
   Cov<int> method7NestedFunction = method7Function();
   Expect.isNull(method7NestedFunction());
+
+  a.method8(Contravariant<int>());
+  Expect.isNull(a.method9());
+  a.method10(Contravariant<Covariant<int>>());
+  Expect.isNull(a.method11());
+  a.method12(Covariant<Contravariant<int>>());
+  Expect.isNull(a.method13());
+
+  a.method14(3);
+  a.method15(contraFunction);
+  a.method16(covFunction);
+  a.method17(Contravariant<int>());
+  a.method18(Covariant<int>());
+
+  a.method19();
+  a.method20();
 }
 
 void testMixin() {
@@ -101,9 +153,7 @@
 
   Expect.isNull(b.method1());
 
-  b.method2((int x) {
-    Expect.equals(2, x);
-  });
+  b.method2(contraFunction);
 
   Expect.type<Cov<int>>(b.method3());
   Cov<int> method3Function = b.method3();
@@ -112,18 +162,34 @@
   b.method4((Cov<int> x) {});
 
   b.method5(() {
-    return (int x) {};
+    return contraFunction;
   });
 
   Expect.type<Contra<Contra<int>>>(b.method6());
   Contra<Contra<int>> method6Function = b.method6();
-  method6Function((int x) {});
+  method6Function(contraFunction);
 
   Expect.type<Cov<Cov<int>>>(b.method7());
   Cov<Cov<int>> method7Function = b.method7();
   Expect.type<Cov<int>>(method7Function());
   Cov<int> method7NestedFunction = method7Function();
   Expect.isNull(method7NestedFunction());
+
+  b.method8(Contravariant<int>());
+  Expect.isNull(b.method9());
+  b.method10(Contravariant<Covariant<int>>());
+  Expect.isNull(b.method11());
+  b.method12(Covariant<Contravariant<int>>());
+  Expect.isNull(b.method13());
+
+  b.method14(3);
+  b.method15(contraFunction);
+  b.method16(covFunction);
+  b.method17(Contravariant<int>());
+  b.method18(Covariant<int>());
+
+  b.method19();
+  b.method20();
 }
 
 void testClassInMethods() {
diff --git a/tests/language_2/variance/variance_out_subclass_error_test.dart b/tests/language_2/variance/variance_out_subclass_error_test.dart
index 24eb2b8..a6d783a 100644
--- a/tests/language_2/variance/variance_out_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_out_subclass_error_test.dart
@@ -20,87 +20,87 @@
 class A<out T> extends Contravariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
 
 class B<out T> implements Contravariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
 
 class C<out T> with MContravariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MContravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MContravariant'.
 
 class D<out T> extends Invariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
 
 class E<out T> implements Invariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
 
 class F<out T> with MInvariant<T> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MInvariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MInvariant'.
 
 class G<out T> extends Covariant<Contravariant<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
 
 class H<out T> extends Contravariant<Covariant<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
 
 class I<out T> extends Covariant<ContraFunction<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
 
 class J<out T> extends Covariant<ContraFunction<CovFunction<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
 
 class K<out T> extends Covariant<CovFunction<ContraFunction<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
 
 class L<out T> extends Covariant<ContraFunction<Covariant<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
 
 class M<out T> extends Contravariant<Contravariant<Contravariant<T>>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
 
 class N<out T> extends Covariant<InvFunction<T>> {}
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Covariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Covariant'.
 
 class O<out T> = Covariant<T> with MContravariant<T>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MContravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MContravariant'.
 
 class P<out T> = Contravariant<T> with MCovariant<T>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Contravariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
 
 class Q<out T> = Invariant<T> with MInvariant<T>;
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'Invariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MInvariant'.
 //    ^
 // [analyzer] unspecified
-// [cfe] Found unsupported uses of 'T' in supertype 'MInvariant'.
+// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
diff --git a/tests/language_2/variance/variance_out_subtyping_test.dart b/tests/language_2/variance/variance_out_subtyping_test.dart
index a057a05..00f5ed3 100644
--- a/tests/language_2/variance/variance_out_subtyping_test.dart
+++ b/tests/language_2/variance/variance_out_subtyping_test.dart
@@ -6,6 +6,8 @@
 
 // SharedOptions=--enable-experiment=variance
 
+import "package:expect/expect.dart";
+
 class Covariant<out T> {}
 
 class Upper {}
@@ -58,14 +60,23 @@
 
 main() {
   A a = new A();
+  Expect.type<Covariant<Middle>>(a.method1());
+  Expect.type<Covariant<Upper>>(a.method1());
+  Expect.notType<Covariant<Lower>>(a.method1());
   a.method2(new Covariant<Middle>());
   a.method2(new Covariant<Lower>());
 
   B b = new B();
+  Expect.type<Covariant<Upper>>(b.method1());
+  Expect.type<Covariant<Middle>>(b.method1());
+  Expect.type<Covariant<Lower>>(b.method1());
   b.method2(new Covariant<Upper>());
   b.method2(new Covariant<Middle>());
 
   C c = new C();
+  Expect.type<Covariant<Middle>>(c.method1());
+  Expect.type<Covariant<Upper>>(c.method1());
+  Expect.notType<Covariant<Lower>>(c.method1());
   c.method2(new Covariant<Middle>());
   c.method2(new Covariant<Lower>());
 
@@ -73,12 +84,19 @@
   D<Covariant<Middle>> dMiddle = new D<Covariant<Middle>>();
 
   E e = new E();
+  Expect.type<D<Covariant<Lower>>>(e.method1());
+  Expect.type<D<Covariant<Middle>>>(e.method1());
 
   F f = new F();
+  Expect.type<D<Covariant<Middle>>>(f.method1());
 
   Iterable<Covariant<Middle>> iterableMiddle = [new Covariant<Middle>()];
   List<Covariant<Lower>> listLower = [new Covariant<Lower>()];
   iterableMiddle = listLower;
 
   testCall(listLower);
+
+  Expect.subtype<Covariant<Lower>, Covariant<Middle>>();
+  Expect.subtype<Covariant<Middle>, Covariant<Middle>>();
+  Expect.notSubtype<Covariant<Upper>, Covariant<Middle>>();
 }
diff --git a/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart b/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart
new file mode 100644
index 0000000..cd6e13b
--- /dev/null
+++ b/tests/language_2/variance/variance_upper_lower_bounds_error_test.dart
@@ -0,0 +1,102 @@
+// 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 erroneous upper and lower bounds computation with respect to
+// variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+class LegacyCovariant<T> {}
+
+class Multi<out T, inout U, in V> {}
+
+class Exactly<inout T> {}
+Exactly<T> exactly<T>(T x) => new Exactly<T>();
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+main() {
+  bool condition = true;
+
+  var contraLowerActual =
+      exactly(condition ? Contravariant<Upper>() : Contravariant<Lower>());
+  Exactly<Contravariant<Upper>> contraUpperExpected = contraLowerActual;
+  //                                                  ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Contravariant<Lower>>' can't be assigned to a variable of type 'Exactly<Contravariant<Upper>>'.
+
+  var contraMiddleActual =
+      exactly(condition ? Contravariant<Upper>() : Contravariant<Middle>());
+  contraUpperExpected = contraMiddleActual;
+  //                    ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Contravariant<Middle>>' can't be assigned to a variable of type 'Exactly<Contravariant<Upper>>'.
+
+  var covMiddleActual =
+      exactly(condition ? Covariant<Middle>() : Covariant<Lower>());
+  Exactly<Covariant<Lower>> covLowerExpected = covMiddleActual;
+  //                                           ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Covariant<Middle>>' can't be assigned to a variable of type 'Exactly<Covariant<Lower>>'.
+
+  var covUpperActual =
+      exactly(condition ? Covariant<Upper>() : Covariant<Lower>());
+  covLowerExpected = covUpperActual;
+  //                 ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Covariant<Upper>>' can't be assigned to a variable of type 'Exactly<Covariant<Lower>>'.
+
+  var invObjectActual =
+      exactly(condition ? Invariant<Upper>() : Invariant<Middle>());
+  Exactly<Invariant<Middle>> invMiddleExpected = invObjectActual;
+  //                                             ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Invariant<Middle>>'.
+  Exactly<Invariant<Upper>> invUpperExpected = invObjectActual;
+  //                                           ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Invariant<Upper>>'.
+
+  var legacyCovMiddleActual =
+      exactly(condition ? LegacyCovariant<Middle>() : LegacyCovariant<Lower>());
+  Exactly<LegacyCovariant<Lower>> legacyCovLowerExpected =
+      legacyCovMiddleActual;
+  //  ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<LegacyCovariant<Middle>>' can't be assigned to a variable of type 'Exactly<LegacyCovariant<Lower>>'.
+
+  var legacyCovUpperActual =
+      exactly(condition ? LegacyCovariant<Upper>() : LegacyCovariant<Lower>());
+  legacyCovLowerExpected = legacyCovUpperActual;
+  //                       ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<LegacyCovariant<Upper>>' can't be assigned to a variable of type 'Exactly<LegacyCovariant<Lower>>'.
+
+  var multiActual = exactly(condition
+      ? Multi<Middle, Middle, Middle>()
+      : Multi<Lower, Middle, Lower>());
+  Exactly<Multi<Lower, Middle, Lower>> multiExpected = multiActual;
+  //                                                   ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Multi<Middle, Middle, Lower>>' can't be assigned to a variable of type 'Exactly<Multi<Lower, Middle, Lower>>'.
+
+  var multiActual2 = exactly(
+      condition ? Multi<Middle, int, Middle>() : Multi<Lower, Middle, Lower>());
+  Exactly<Multi<Middle, Object, Lower>> multiObjectExpected = multiActual2;
+  //                                                          ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Object>' can't be assigned to a variable of type 'Exactly<Multi<Middle, Object, Lower>>'.
+
+  var multiActual3 = exactly(
+      condition ? Multi<int, Middle, Middle>() : Multi<Lower, Middle, Lower>());
+  Exactly<Object> multiObjectExpected2 = multiActual3;
+  //                                     ^
+  // [analyzer] unspecified
+  // [cfe] A value of type 'Exactly<Multi<Object, Middle, Lower>>' can't be assigned to a variable of type 'Exactly<Object>'.
+}
diff --git a/tests/language_2/variance/variance_upper_lower_bounds_test.dart b/tests/language_2/variance/variance_upper_lower_bounds_test.dart
new file mode 100644
index 0000000..ceb9ac8
--- /dev/null
+++ b/tests/language_2/variance/variance_upper_lower_bounds_test.dart
@@ -0,0 +1,71 @@
+// 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 upper and lower bounds computation with respect to variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+class Covariant<out T> {}
+class Contravariant<in T> {}
+class Invariant<inout T> {}
+class LegacyCovariant<T> {}
+
+class Multi<out T, inout U, in V> {}
+
+class Exactly<inout T> {}
+Exactly<T> exactly<T>(T x) => new Exactly<T>();
+
+class Upper {}
+class Middle extends Upper {}
+class Lower extends Middle {}
+
+main() {
+  bool condition = true;
+
+  var contraLowerActual =
+      exactly(condition ? Contravariant<Upper>() : Contravariant<Lower>());
+  Exactly<Contravariant<Lower>> contraLowerExpected = contraLowerActual;
+
+  var contraMiddleActual =
+      exactly(condition ? Contravariant<Upper>() : Contravariant<Middle>());
+  Exactly<Contravariant<Middle>> contraMiddleExpected = contraMiddleActual;
+
+  var covMiddleActual =
+      exactly(condition ? Covariant<Middle>() : Covariant<Lower>());
+  Exactly<Covariant<Middle>> covMiddleExpected = covMiddleActual;
+
+  var covUpperActual =
+      exactly(condition ? Covariant<Upper>() : Covariant<Lower>());
+  Exactly<Covariant<Upper>> covUpperExpected = covUpperActual;
+
+  var invMiddleActual =
+      exactly(condition ? Invariant<Middle>() : Invariant<Middle>());
+  Exactly<Invariant<Middle>> invMiddleExpected = invMiddleActual;
+
+  var invObjectActual =
+      exactly(condition ? Invariant<Upper>() : Invariant<Middle>());
+  Exactly<Object> invObjectExpected = invObjectActual;
+
+  var legacyCovMiddleActual =
+      exactly(condition ? LegacyCovariant<Middle>() : LegacyCovariant<Lower>());
+  Exactly<LegacyCovariant<Middle>> legacyCovMiddleExpected =
+      legacyCovMiddleActual;
+
+  var legacyCovUpperActual =
+      exactly(condition ? LegacyCovariant<Upper>() : LegacyCovariant<Lower>());
+  Exactly<LegacyCovariant<Upper>> legacyCovUpperExpected = legacyCovUpperActual;
+
+  var multiActual = exactly(condition
+      ? Multi<Middle, Middle, Middle>()
+      : Multi<Lower, Middle, Lower>());
+  Exactly<Multi<Middle, Middle, Lower>> multiExpected = multiActual;
+
+  var multiActual2 = exactly(
+      condition ? Multi<Middle, int, Middle>() : Multi<Lower, Middle, Lower>());
+  Exactly<Object> multiObjectExpected = multiActual2;
+
+  var multiActual3 = exactly(
+      condition ? Multi<int, Middle, Middle>() : Multi<Lower, Middle, Lower>());
+  Exactly<Multi<Object, Middle, Lower>> multiObjectExpected2 = multiActual3;
+}
diff --git a/tests/language_2/vm/regression_39071.dart b/tests/language_2/vm/regression_39071.dart
new file mode 100644
index 0000000..82049b4
--- /dev/null
+++ b/tests/language_2/vm/regression_39071.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// VMOptions=--optimization_counter_threshold=10
+
+// Found by DartFuzzing: would assert during OSR:
+// https://github.com/dart-lang/sdk/issues/39071
+
+main() {
+  var x = [
+    [for (int i = 0; i < 20; ++i) i]
+  ];
+}
diff --git a/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart b/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
index 951d43f..012ddde 100644
--- a/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
+++ b/tests/lib_2/convert/streamed_conversion_json_utf8_decode_test.dart
@@ -1,9 +1,11 @@
 // 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 write barrier verification mode.
-// VMOptions=--verify_before_gc --verify_after_gc --old_gen_growth_rate=1 --no-background-compilation
+
 // VMOptions=
+// VMOptions=--verify_before_gc
+// VMOptions=--verify_after_gc
+// VMOptions=--verify_before_gc --verify_after_gc
 
 import "package:expect/expect.dart";
 import 'dart:async';
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index cde9329..a592e6a 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -7,9 +7,6 @@
 [ $arch == simarm64 ]
 convert/utf85_test: Skip # Pass, Slow Issue 20111.
 
-[ $arch == simarmv5te ]
-mirrors/mirrors_reader_test: Slow
-
 [ $mode == product ]
 developer/timeline_test: Skip # Not supported
 isolate/issue_24243_parent_isolate_test: Skip # Requires checked mode
@@ -46,7 +43,7 @@
 [ $runtime != dart_precompiled && ($runtime != vm || $compiler != dartk && $compiler != none) ]
 isolate/vm_rehash_test: SkipByDesign
 
-[ $arch == simarm || $arch == simarmv5te || $arch == simarmv6 ]
+[ $arch == simarm || $arch == simarmv6 ]
 convert/utf85_test: Skip # Pass, Slow Issue 12644.
 
 [ $arch != x64 || $compiler == dartkb || $runtime != vm ]
@@ -73,7 +70,7 @@
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
 # These Isolate tests that use spawnURI are hence skipped on purpose.
-[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
+[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ]
 isolate/count_test: Skip # Isolate.spawnUri
 isolate/cross_isolate_message_test: Skip # Isolate.spawnUri
 isolate/deferred_in_isolate2_test: Skip # Isolate.spawnUri
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 2aeba0c..1c24f7b 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -4,7 +4,6 @@
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
 
-convert/streamed_conversion_json_utf8_decode_test: Slow # Uses --verify_before_gc --verify_after_gc --old_gen_growth_rate=1 flags
 isolate/ping_pause_test: Skip # Issue https://dartbug.com/37787
 
 [ $compiler == dartkb ]
@@ -14,9 +13,6 @@
 html/*: Skip # TODO(ahe): Make dart:html available.
 js/*: Skip # TODO(ahe): Make dart:js available.
 
-[ $arch == simdbc64 && $hot_reload_rollback ]
-convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Uses --verify_before_gc --verify_after_gc --old_gen_growth_rate=1 flags
-
 [ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
 
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 305c371..aba92ff 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -11,7 +11,7 @@
 [ $arch == ia32 && $mode == debug && $runtime == vm && $system == windows ]
 convert/streamed_conversion_json_utf8_decode_test: Skip # Verification OOM.
 
-[ $arch != ia32 && $arch != simarm && $arch != simarmv5te && $arch != simarmv6 && $arch != x64 && $mode == debug && $runtime == vm ]
+[ $arch != ia32 && $arch != simarm && $arch != simarmv6 && $arch != x64 && $mode == debug && $runtime == vm ]
 convert/streamed_conversion_json_utf8_decode_test: Skip # Verification not yet implemented.
 
 [ $arch == simarm64 && $runtime == vm ]
@@ -79,8 +79,8 @@
 mirrors/library_uri_io_test: RuntimeError
 mirrors/library_uri_package_test: RuntimeError
 
-[ $runtime == vm && ($arch == simarm || $arch == simarmv5te || $arch == simarmv6) ]
+[ $runtime == vm && ($arch == simarm || $arch == simarmv6) ]
 convert/utf85_test: Skip # Pass, Slow Issue 12644.
 
-[ $arch == simarmv5te || $arch == simarmv6 || $arch == simarm && $runtime == vm ]
+[ $arch == simarmv6 || $arch == simarm && $runtime == vm ]
 convert/chunked_conversion_utf88_test: Skip # Pass, Slow Issue 12644.
diff --git a/tests/standalone/app_snapshot_share_test.dart b/tests/standalone/app_snapshot_share_test.dart
deleted file mode 100644
index 65b95f5..0000000
--- a/tests/standalone/app_snapshot_share_test.dart
+++ /dev/null
@@ -1,97 +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 "dart:io";
-
-void main(List<String> args) {
-  if (args.contains("--child")) {
-    print("Hello, sharing world!");
-    return;
-  }
-
-  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
-    return; // Running in JIT or Windows: AOT binaries not available.
-  }
-
-  if (Platform.isAndroid) {
-    return; // SDK tree and dart_bootstrap not available on the test device.
-  }
-
-  var buildDir =
-      Platform.executable.substring(0, Platform.executable.lastIndexOf('/'));
-  var tempDir = Directory.systemTemp.createTempSync("app-shared");
-  var snapshot1Path = tempDir.uri.resolve("hello1.snapshot").toFilePath();
-  var snapshot2Path = tempDir.uri.resolve("hello2.snapshot").toFilePath();
-  var scriptPath = new Directory(buildDir)
-      .uri
-      .resolve("../../tests/standalone/app_snapshot_share_test.dart")
-      .toFilePath();
-
-  var exec = "$buildDir/dart_bootstrap";
-  args = new List<String>();
-  args.add("--no-preview-dart-2");
-  args.add("--deterministic");
-  args.add("--use-blobs");
-  args.add("--snapshot-kind=app-aot");
-  args.add("--snapshot=$snapshot1Path");
-  args.add(scriptPath);
-  print("+ $exec $args");
-  var result = Process.runSync(exec, args);
-  print("Exit code: ${result.exitCode}");
-  print("stdout:");
-  print(result.stdout);
-  print("stderr:");
-  print(result.stderr);
-  if (result.exitCode != 0) {
-    throw "Bad exit code";
-  }
-
-  exec = "$buildDir/dart_bootstrap";
-  args = new List<String>();
-  args.add("--no-preview-dart-2");
-  args.add("--deterministic");
-  args.add("--use-blobs");
-  args.add("--snapshot-kind=app-aot");
-  args.add("--snapshot=$snapshot2Path");
-  args.add("--shared-blobs=$snapshot1Path");
-  args.add(scriptPath);
-  print("+ $exec $args");
-  result = Process.runSync(exec, args);
-  print("Exit code: ${result.exitCode}");
-  print("stdout:");
-  print(result.stdout);
-  print("stderr:");
-  print(result.stderr);
-  if (result.exitCode != 0) {
-    throw "Bad exit code";
-  }
-
-  var sizeWithoutSharing = new File(snapshot1Path).statSync().size;
-  var deltaWhenSharing = new File(snapshot2Path).statSync().size;
-  print("sizeWithoutSharing: $sizeWithoutSharing");
-  print("deltaWhenSharing: $deltaWhenSharing");
-  if (deltaWhenSharing >= sizeWithoutSharing) {
-    throw "Sharing did not shrink size";
-  }
-
-  exec = "$buildDir/dart_precompiled_runtime";
-  args = new List<String>();
-  args.add("--no-preview-dart-2");
-  args.add("--shared-blobs=$snapshot1Path");
-  args.add(snapshot2Path);
-  args.add("--child");
-  print("+ $exec $args");
-  result = Process.runSync(exec, args);
-  print("Exit code: ${result.exitCode}");
-  print("stdout:");
-  print(result.stdout);
-  print("stderr:");
-  print(result.stderr);
-  if (result.exitCode != 0) {
-    throw "Bad exit code";
-  }
-  if (!result.stdout.contains("Hello, sharing world!")) {
-    throw "Missing output";
-  }
-}
diff --git a/tests/standalone/io/certificates/README b/tests/standalone/io/certificates/README
deleted file mode 100644
index 6ecd518..0000000
--- a/tests/standalone/io/certificates/README
+++ /dev/null
@@ -1,70 +0,0 @@
-    This directory, tests/standalone/io/certificates, contains the
-X509 TLS certificates and private keys needed to run tests of Dart's
-secure networking code.  The SecureSocket and SecureServer classes
-are tested by making TLS (formerly called SSL) connections, secured
-by certificates from a self-signed test root authority.
-
-The certificates are created by running ../create_sample_certificates.sh
-in a bash or sh shell, with the openssl tools installed.  Run the script
-twice to create the untrusted_* files.
-
-PEM files:
-
-server_chain.pem:
-  Contains the chain of certificates, from the self-signed
-test certificate authority, through the intermediate CA, to the server
-certificate, used on the server side of a test connection.
-
-server_key.pem:
-  Contains the private key for the server certificate
-
-trusted_certs.pem:
-  Contains the self-signed certificate of the test certificate authority.
-This certificate is set as "trusted" by the client side of the connection
-in its SecurityContext object, so that a verified TLS connection to the
-server can be made.
-
-untrusted_server_chain.pem:
-  Contains a chain of certificates, from a different self-signed
-test certificate authority, through an intermediate CA, to a server
-certificate, used on the server side of a test connection that is intended
-to fail because the client does not accept this certificate authority
-
-untrusted_server_key.pem:
-  Contains the private key for the untrusted server certificate
-in untrusted_server_chain.pem
-
-*_malformed.pem:
-  Truncated PEM formatted certificates used to test error handling.
-
-PKCS12 files:
-
-server_key.12:
-  Created with:
-  $ openssl pkcs12 -export -inkey server_key.pem -out server_key.p12 -nocerts
-  with password 'dartdart'
-
-server_chain.p12:
-  Created with:
-  $ openssl pkcs12 -export -in server_chain.pem -out server_chain.p12 -nokeys
-  with password 'dartdart'
-
-client1_key.p12:
-  Created with:
-  $ openssl pkcs12 -export -inkey client1_key.pem -out client1_key.p12 -nocerts
-  with password 'dartdart'
-
-client1.p12:
-  Created with:
-  $ openssl pkcs12 -export -in client1.pem -out client1.p12 -nokeys
-  with password 'dartdart'
-
-trusted_certs.p12:
-  Created with:
-  $ openssl pkcs12 -export -in trusted_certs.pem -out trusted_certs.p12 -nokeys
-  with password 'dartdart'
-
-client_authority.p12:
-  Created with:
-  $ openssl pkcs12 -export -in client_authority.pem -out client_authority.p12 -nokeys
-  with password 'dartdart'
diff --git a/tests/standalone/io/certificates/client1.p12 b/tests/standalone/io/certificates/client1.p12
deleted file mode 100644
index 8d19d04..0000000
--- a/tests/standalone/io/certificates/client1.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/client1.pem b/tests/standalone/io/certificates/client1.pem
deleted file mode 100644
index 429cd72..0000000
--- a/tests/standalone/io/certificates/client1.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDBzCCAe+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAQMQ4w
-DAYDVQQDDAV1c2VyMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALlg
-zRZlohMtAg44+kPk04G/gIkdeyh7toUA3nR/2sS11j8EutHewezvMV8YyxBxQn8f
-8x8FkDbrE/6GYg2Dsu6TxrXIFre9Lt5jLlJi/6qEaVtXNTdP3vKO87FJ7YVLCeYe
-MxuTCdHloeUICP5x3GJz3AVdcg/S9qRWrpm8LdRdFk66l8vD+aDf+Oqe+mLVtAr6
-kqkdq1nUJOkRBp+zFMmB3Zfm28aYew6BmFQSscxemZyJxiv4dB+EDr821kEjgGBY
-IQGpdADrfh3j9JAzEr30o6sjfr6QWKHG6ZD7xhSl7rIxmx1yoKoJh8vLpcQfdv79
-7VZZT5N7xjz0xkjqTA0CAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUMpcX
-0o3lu3BTmaKwCfIJMO5aMs4wHwYDVR0jBBgwFoAUtyLBueMoMi7TborRvM7CnwOi
-SQ4wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAAB1rNFg
-wdK79r7WO0OvE90uvtFf8sO2kqwW/7JIP/kcnIwIIkNiffUEfLfVr7aecK0rPer4
-DDZFAciuaOcts7dTxXRU+la1ZEPaEyx1mHaC6HJbgFYC9cG30L6GJGkZkIGOCTn+
-/yPxTM//dSc7YACc90GNTeUFVnAw6vskH91Ph4VYbdYxt7L1d1pzvBeun6Qi0eJq
-rkWQ2DOO9h9E6Rnt8Jea3w7WzX5P8pBjm74bv38YBKefawPeiiXck2Q/lUehLePV
-U1MRdy1QWC924+p6cXbR1GEhg0FZyvS/9WdpLMGIat/j/98juN6qyAbw7XXhlB1g
-fBHlfXbx+KMZAuY=
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client1_key.p12 b/tests/standalone/io/certificates/client1_key.p12
deleted file mode 100644
index 5d11e73..0000000
--- a/tests/standalone/io/certificates/client1_key.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/client1_key.pem b/tests/standalone/io/certificates/client1_key.pem
deleted file mode 100644
index 0e2ef5e..0000000
--- a/tests/standalone/io/certificates/client1_key.pem
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
-B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
-w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
-+qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
-HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
-/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
-xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
-g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
-38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
-q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
-XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
-O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
-gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
-M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
-I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
-nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
-HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
-qgXGcvZWgsgQFPXviKmDx+9KJ2oL35cLnDcMCRN7lLPdAhk8J/XrUq/iIYXNxud6
-f9mfVOsd0LT030je/N25IdEoPimTnps/INGGNug+FuJ3dCeIQGwB7uQB5ozoHL5h
-hzdQYq5+FWksuHPCOL1YLRJux9sH6OYxlXy2oigLtA05EHhq83Wwb2oTW6boo+rs
-gKqzc7OtFgYDsV8R1raoqlzAv3GNgkzyuHTSUakDdnJYmfcoOuK+Ch+MjVeZW5bS
-Ir7uqugUqqI/AiO/eHkvoGpQs0c67ao0qPR7ZQna/1FBj1O8J/dI4JBUtPvDa0tW
-7U+Ja/twJWri+Nn6/iEEWEuM/xx/xFmxrTb4WYza1ysrCls5l6POjQu2n6dT52+o
-cobwltkJmSNoIT2SYRuvEfgGlwyzY5p5B8U24HIAkNJIkO7hc9oD1mbq+K526HNl
-h6TG7RGUOffXIYuykrMmCTRRnv3bXmjTgsvWhVFujpCSQf9PqkQpv+KQPeFmy12h
-TA1QNtdVOZlh2GLEUgZuJVytyEz4m+3BfvBql5K9rlAUSQqsLJDKVxsmBDl132o3
-yy9JR7iC
------END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/client1_key_malformed.pem b/tests/standalone/io/certificates/client1_key_malformed.pem
deleted file mode 100644
index 8c1f7d8..0000000
--- a/tests/standalone/io/certificates/client1_key_malformed.pem
+++ /dev/null
@@ -1,17 +0,0 @@
-MIIE4jAcBgoqhkiG9w0BDAEBMA4ECF4ZB27y60SWAgIIAASCBMCEL3ZCzfC0q+m+
-B8gM9jQe1JFRD5reAuwK6+3speBS4KE+wjbcyQq09/5UoQu3Dci1WG1nKLB1u0Bk
-w9NuRahWCpvVLzz/GQ6Psesixq3V69zD3N6iMl/XQKymQBwGK51xIkeJO+6Skh2d
-+qoyBHINTlKY9+548Zgqu+Z3mI3pGmdhd7hCiamiffDwCLEqRxbXdZdLpC9GpAP5
-HOqXHzN2aZbAGHb1GkHVxskSNzAwlEEZhh4Ibe6o7U65hoL9borewT+gj6sQohI5
-/LHL0P2bVvtRZiwBVPUX8HZWuVYIFb6GEGTTqOofNhNHvHaKUlD8Uxi5/h/Xi8fq
-xpdkjIn7VXj9e+I3TkfiphDtk0+Q+f+UkuPyuzU1PafinPfRK1J6gk+ZqAQHW/sp
-g6GVr2r4PkOrBPsA6jmCnQhs2C4MlZyR2p65qjVutdkKU5NgftW+giK9shgglcza
-38RF8i01THOnD3j+2teM/t/Ziqb2PGWv/bmvhcYqt1aG186Pe3bBCxhh/L7bqNKD
-q7sxDmaDE2pTkfyvh07udarmBQc5gvfXYqwghbqP/n7wizqjeEJgAwwHyi8LLsFV
-XreBQ/8Z2gQwXurrh5WD+7KSgvgopW/oVC8a3++8Hmf5Nkj27lACzoDWTG2/Swah
-O1MmdtPyy/KCbf5ujt2BlXM9D206Rsr6hoO9UZ1s1ohRdJReVGc4NZ4XrVWc4TKT
-gUAFTaHIKgFe/DgLaQn8L8Pqb8B/JfoSgQ74r69S434Kc+EDKui8wnkgso5bqrr1
-M07H9Xo+OtG1D6rma2EUlpoU06CAIcyqNx5fHJ3xfk9GHScQi4U6vEDCAQTNTS65
-I5AOHthZ2kZzfXvP6TF39S5D37NrV7/WJu7ZFaJx3bUGwnS2HYTwjFPABHpVLMwJ
-nBylVJs+h7bCZdBNCWgTytcn1mYMCvXVmrW8VTwBRjUQsy4rgE2wjpZuIM9rx+gZ
-HtNvy5t2RlOSqVKapyvV0ll7qbT1lwGIePxjttiWmNbgbwRBQzjv6FZ1Yo331Fl4
diff --git a/tests/standalone/io/certificates/client2.pem b/tests/standalone/io/certificates/client2.pem
deleted file mode 100644
index f34bde4..0000000
--- a/tests/standalone/io/certificates/client2.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDBzCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAQMQ4w
-DAYDVQQDDAV1c2VyMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMay
-a0BYpNJHlwcNz6TyX+D6dKnqxUfdHQDgW9/5Hl4RiHDKAH+2iVYEsedksOmxNDlV
-HqZg4fBsyPVRzeGqia7nCsN3KlMbaqZgNI3ynvvMFIJkb3e/ZJtodg+cYzqnOu2F
-G3LijzRJG363aavTnjLdFumLnsOtSDdYnjRM43eeE3X2ajAiKkE9r6b6/wt8Ki5T
-GVIm9kG674iCloawK6dgCBA1dDPsKmzhcFoAl5UMpQSvd1OuW034qryE+RzQ0RCe
-G5u2leVgiuoq2rpmPL6fA0BHsyJ3wP1Gs74i+NhZdhiBhv+E89sfKaJOPpmDBW7b
-3jCpEmgRSm5h5SDm8KsCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUj0t8
-BdHrTqd7aKIV4+OLWvT6WX4wHwYDVR0jBBgwFoAUtyLBueMoMi7TborRvM7CnwOi
-SQ4wEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBABQ4PKRG
-VJYhWtktqpilP+C8CXsMArsqkEdMwHgQi8Xv3WVvXZpiLZHvO0To9J3+dgD2sOys
-MphZBXMJuOfX/+3IGerxsBxVj7Pnx37nn83g6PfCvGgVQQw7cGUjn5/Dw6apH2HH
-eO3yG+fgYeMNXyKt1KVWYeIToZfXUFvm+oMbWxxdpcctsKLRgCRvf1+r5EK9xE8+
-jYYk3S3pXvsk3qwWJz3pjg6zR3IbakkEuhE1Gl0Wrf4zZ9DOB8rd00/xirAuuYwm
-aIZ3KcFCTgVdGtB41q03D31xWNZPODCxAEADiICNE+3cuUMCi3wwBeCrybXSLhj/
-6St8K4NBvg+xL/w=
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client2_key.pem b/tests/standalone/io/certificates/client2_key.pem
deleted file mode 100644
index b4074f9..0000000
--- a/tests/standalone/io/certificates/client2_key.pem
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE5DAcBgoqhkiG9w0BDAEBMA4ECC/vc3ONj4KfAgIIAASCBMI1liT+B00kYYj+
-VRcEHQVrWsvD648OCd6BNQ9gKTYL5767lHUN0iG2JAdTHTKJy7XeEVVdPweU58jb
-HnS1yWbs0IuUFkCGy9wH3Lb6SkZtEScoAmzsNRdSY3WwmNhUG/yHrLITKM1SGkg3
-nf3ywIJYwO3YH22InVK0puVT/y943F1GXZSvklG/TGawR0uIyNuZOl0rg+5bsCaf
-1VSCWvt/Czgqm9Pc+Iz2PAKwyyjmvqRMBCtKvJTGNEPB63eDyHWQTtvQe0un06AF
-lvB7JYWaTXiwccSww2BuqTdJdBYKWxzPbdBfcqUT5Q9/LE0JhwvfZY/oDeJFP0HC
-HVBajuESZPJgb06xcsiX1qmk/iqAjZVZQ/CQ9K08qXem7YRFxJCy90wjLu3abjzQ
-Nvq0VsI8a8vlODQlr/Z5iXSYEKMYvUwh5Y9e8fc0BOOc1QzOYV2vxy28OVHmigOn
-tVHdj/FXK6N97QgtFzVUTjisO3YFygI2wybrz1BEys/vwqfCBiT+/hu+ur/lCrkn
-E2S6I967TyTvaxn+WCo9EW2Rb66XdI7tL09AkV2VZqJN4PTyis9YYgkr2uKjj4qX
-ySAQp/XHGEF1mmvjeptKTb2CMut0vcP+nl1bsUUXpSiKYGQ2BBcqgTcEFUEd75ms
-kcPMOuHdioaYh72nCRVzsRoDTDGF08NMTndW5PC8RpFsNS0vx8dq/A3VHAvJa2Rc
-9lP939FAU/Ck9b3NxH6hUgfDEFHQ61oW2Inpu4s3eRoClkgyf+aQEZZI7GTiNICm
-xqHosZ+hLe2mYoGk6xl1AruMk7kGeebRaPxzvS0UKfftOQDahFcDp8iEtLAcM1nx
-8Pdu4csyWFk+eBsTT6sPur2ZkD2LO0gLjR+N2nZNTqEJYy7n1jyV7M/JZBfh0fGi
-VX+sb+urTBAlDszX6b1LV7M78MDs6QwziDsrytjuClOWN47wzYbYYnSZZnDtTR+B
-CDHyK5wa8gNs4A+643HvD6sJz6zALOu2UI/9SrvuyYPltCwCUmWJ3A2XxoBmdJ/e
-yHEj/VdsNi6TtQ5qpBWqm43LpF0WAKNgksGnbFjOc/0QsUVk0txB9D6/oC9HyCd8
-u9nR8vLUC7l1dtYL0CwpocqU67qzVoRxrkkyCE4iblusKjr1ZlfstHDS0tPELodo
-8RroSs4vKXV9dzhzLQyqp6PzzdB7y/5Bpn0grxXrwln6/shoSR462h2CB4z9chGA
-Vdsp+KE8LDogIwZDT6iVVrpaBQDLoSxmX+E2IKRCUcj/l+gepEPyHbhOAn8/NxGX
-h16v89aDMtnyWqUcc/Gm2/Qep3o7goRfodyoyWvwy8nq9Lgf/wJIfEGn0lEeR0I/
-/Om/UAiId1o47C3LsGMm+qO+FcWesLA67eMQnp1WYoWpnanb3q4t8PWATzAlW05n
-cA59dYjutUmKJEjrh595AptMLXn6RM1GzA7x53+uAKvXaI+aR8wrtujiJLg9DwY2
-+f4ehwfwNptBxzZX97a7/3lGZ5U7BgDeJhNo9T02VQTvXxB29H6J/v6XYyPCKpuM
-upPhiHzrs9UyMvINfDnd/fJ58qr6TvEuBi0QxMMmOCfccYlj6Q5Bfqp+iuST0igg
-SLmBml+LkIM=
------END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/client_authority.p12 b/tests/standalone/io/certificates/client_authority.p12
deleted file mode 100644
index 545282e..0000000
--- a/tests/standalone/io/certificates/client_authority.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/client_authority.pem b/tests/standalone/io/certificates/client_authority.pem
deleted file mode 100644
index ae9ae5b..0000000
--- a/tests/standalone/io/certificates/client_authority.pem
+++ /dev/null
@@ -1,19 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
-FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
-TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
-DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
-SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
-3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
-4adgFQJagkTUoxWtDGL58+WcbcJa73XJAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
-Af8CAQAwHQYDVR0OBBYEFLciwbnjKDIu026K0bzOwp8DokkOMB8GA1UdIwQYMBaA
-FLciwbnjKDIu026K0bzOwp8DokkOMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh8rryWFoGjFdm0i4FLRktF8B
-aUqVCCpFVHIYlFcsQstznIb01X2Zq5nfSfrFxbr5STVGzGJ0HGDuFpicT8+qMnJX
-dou5AuaqubIDWeKL+oAgvI71Nt1gsesixqzFQAoCTRgUjrSGpY2fL7rElV0Ndy9b
-YepVouktP1/GULc8XbIG9ZLx70Id7YTyrITDgbH3hSnbjmmZSr9RKyKas4MXN0s8
-oKGHEgAx7KyNQRppjydz3bDeH/jVbM4W98vwL6rjKUJlOlo0Ru+3+oioFHqLMSvN
-w4f5rQEiuF260h7y8KKxRxQ8rw188gsBapZr4Rcp+y8gdQvlzJONtv3d1dap5A==
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/client_authority_malformed.pem b/tests/standalone/io/certificates/client_authority_malformed.pem
deleted file mode 100644
index d0aeff4..0000000
--- a/tests/standalone/io/certificates/client_authority_malformed.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
-FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
-TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
-DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
-SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
-3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
diff --git a/tests/standalone/io/certificates/server_chain.p12 b/tests/standalone/io/certificates/server_chain.p12
deleted file mode 100644
index 79e412d..0000000
--- a/tests/standalone/io/certificates/server_chain.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/server_chain.pem b/tests/standalone/io/certificates/server_chain.pem
deleted file mode 100644
index 341a86f..0000000
--- a/tests/standalone/io/certificates/server_chain.pem
+++ /dev/null
@@ -1,59 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
-WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
-/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
-KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
-oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
-1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
-PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
-bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
-ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
-BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
-B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
-phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
-YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
-UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
-2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
-PkLkXmoIod8=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
-A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
-ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
-VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
-V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
-Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
-kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
-GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
-eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
-NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
-MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
-rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
-9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
-RUE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
-A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_chain_malformed1.pem b/tests/standalone/io/certificates/server_chain_malformed1.pem
deleted file mode 100644
index cb623fd..0000000
--- a/tests/standalone/io/certificates/server_chain_malformed1.pem
+++ /dev/null
@@ -1,6 +0,0 @@
-MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
-WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
-/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
-KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
diff --git a/tests/standalone/io/certificates/server_chain_malformed2.pem b/tests/standalone/io/certificates/server_chain_malformed2.pem
deleted file mode 100644
index 978c523..0000000
--- a/tests/standalone/io/certificates/server_chain_malformed2.pem
+++ /dev/null
@@ -1,41 +0,0 @@
-MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1
-WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCkg/Qr8RQeLTOSgCkyiEX2ztgkgscX8hKGHEHdvlkmVK3JVEIIwkvu
-/Y9LtHZUia3nPAgqEEbexzTENZjSCcC0V6I2XW/e5tIE3rO0KLZyhtZhN/2SfJ6p
-KbOh0HLr1VtkKJGp1tzUmHW/aZI32pK60ZJ/N917NLPCJpCaL8+wHo3+w3oNqln6
-oJsfgxy9SUM8Bsc9WMYKMUdqLO1QKs1A5YwqZuO7Mwj+4LY2QDixC7Ua7V9YAPo2
-1SBeLvMCHbYxSPCuxcZ/kDkgax/DF9u7aZnGhMImkwBka0OQFvpfjKtTIuoobTpe
-PAG7MQYXk4RjnjdyEX/9XAQzvNo1CDObAgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
-bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
-ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBSvhJo6taTggJQBukEvMo/PDk8tKTAf
-BgNVHSMEGDAWgBS98L4T5RaIToE3DkBRsoeWPil0eDAOBgNVHQ8BAf8EBAMCA6gw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAHLOt0mL2S4A
-B7vN7KsfQeGlVgZUVlEjem6kqBh4fIzl4CsQuOO8oJ0FlO1z5JAIo98hZinymJx1
-phBVpyGIKakT/etMH0op5evLe9dD36VA3IM/FEv5ibk35iGnPokiJXIAcdHd1zam
-YaTHRAnZET5S03+7BgRTKoRuszhbvuFz/vKXaIAnVNOF4Gf2NUJ/Ax7ssJtRkN+5
-UVxe8TZVxzgiRv1uF6NTr+J8PDepkHCbJ6zEQNudcFKAuC56DN1vUe06gRDrNbVq
-2JHEh4pRfMpdsPCrS5YHBjVq/XHtFHgwDR6g0WTwSUJvDeM4OPQY5f61FB0JbFza
-PkLkXmoIod8=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
-A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
-ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
-VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
-V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
-Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
-kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
-GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
-eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
-NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
-MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
-rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
-9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
-RUE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/server_key.p12 b/tests/standalone/io/certificates/server_key.p12
deleted file mode 100644
index 204d42d..0000000
--- a/tests/standalone/io/certificates/server_key.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/server_key.pem b/tests/standalone/io/certificates/server_key.pem
deleted file mode 100644
index 895b7d2..0000000
--- a/tests/standalone/io/certificates/server_key.pem
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE4zAcBgoqhkiG9w0BDAEBMA4ECBMCjlg8JYZ4AgIIAASCBMFd9cBoZ5xcTock
-AVQcg/HzYJtMceKn1gtMDdC7mmXuyN0shoxhG4BpQInHkFARL+nenesXFxEm4X5e
-L603Pcgw72/ratxVpTW7hPMjiLTEBqza0GjQm7Sarbdy+Vzdp/6XFrAcPfFl1juY
-oyYzbozPsvFHz3Re44y1KmI4HAzU/qkjJUbNTTiPPVI2cDP6iYN2XXxBb1wwp8jR
-iqdZqFG7lU/wvPEbD7BVPpmJBHWNG681zb4ea5Zn4hW8UaxpiIBiaH0/IWc2SVZd
-RliAFo3NEsGxCcsnBo/n00oudGbOJxdOp7FbH5hJpeqX2WhCyJRxIeHOWmeuMAet
-03HFriiEmJ99m2nEJN1x0A3QUUM7ji6vZAb4qb1dyq7LlX4M2aaqixRnaTcQkapf
-DOxX35DEBXSKrDpyWp6Rx4wNpUyi1TKyhaVnYgD3Gn0VfC/2w86gSFlrf9PMYGM0
-PvFxTDzTyjOuPBRa728gZOGXgDOL7qvdInU/opVew7kFeRQHXxHzFCLK5dD+Vrig
-5fS3m0++f55ODkxqHXB8gbXbd3GMmsW6MrGpU7VsCNtbVPdSMW0FalovEB0M+2lj
-1VfuvL+0F5huTe+BgZAt6xgET/CIcZXdNMRPVhraqUjqWtI9Rdk4STPCpU1rDkjG
-YDl/fo4W2T6qQWFUpiC9IvVVGkVxaqfZZ4Qu+V5xPUi6vk95QiTNkN1t+m+sCCgS
-Llkea8Um0aHMy33Lj3NsfL0LMrnpniqcAks8BvcgIZwk1VRqcj7BQVCygJSYrmAR
-DBhMpjWlXuSggnyVPuduZDtnTN+8lCHLOKL3a3bDb6ySaKX49Km6GutDLfpDtEA0
-3mQvmEG4XVm7zy+AlN72qFbtSLDRi/D/uQh2q/ZrFQLOBQBQB56TvEbKouLimUDM
-ascQA3aUyhOE7e+d02NOFIFTozwc/C//CIFeA+ZEwxyfha/3Bor6Jez7PC/eHNxZ
-w7YMXzPW9NhcCcerhYGebuCJxLwzqJ+IGdukjKsGV2ytWDoB2xZiJNu096j4RKcq
-YSJoen0R7IH8N4eDujXR8m9kAl724Uqs1OoAs4VNICvzTutbsgVZ6Z+NMOcfnPw9
-jZkFhot16w8znD+OmhBR7/bzOLpaeUhk7EhNq5M6U0NNWx3WwkDlvU/jx+6/EQe3
-iLEHptH2HYBF1xscaKGbtKNtuQsfdzgWpOX0qK2YbK3yCKvL/xIm1DQmDZDKkWdW
-VNh8oGV1H96CivWlvxhAgXKz9F/83CjMw8YXRk7RJvWR4vtNvXFAvGkFIYCN9Jv9
-p+1ukaYoxSLGBik907I6gWSHqumJiCprUyAX/bVfZfNiYh4hzeA3lhwxZSax3JG4
-7QFPvyepOmF/3AAzS/Pusx6jOZnuCMCkfQi6Wpem1o3s4x+fP7kz00Xuj01ErucM
-S10ixfIh84kXBN3dTRDtDdeCyoMsBKO0W5jDBBlWL02YfdF6Opo1Q4cPh2DYgXMh
-XEszNZSK5LB0y+f3A6Kdx/hkZzHVvMONA70OyrkoZzGyWENhcB0c7ntTJyPPD2qM
-s0HRA2VwF/0ypU3OKERM1Ua5NSkTgvnnVTlV9GO90Tkn5v4fxdl8NzIuJLyGguTP
-Xc0tRM34Lg==
------END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/certificates/server_trusted.pem b/tests/standalone/io/certificates/server_trusted.pem
deleted file mode 100644
index b943cf9..0000000
--- a/tests/standalone/io/certificates/server_trusted.pem
+++ /dev/null
@@ -1,57 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBAjANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNVoXDTI1MTAyNDEwMjYzNVowIDEeMBwG
-A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6GndRFiXk+2q+Ig7ZOWKKGta+is8137qyXz+eVFs5sA0ajMN
-ZBAMWS0TIXw/Yks+y6fEcV/tfv91k1eUN4YXPcoxTdDF97d2hO9wxumeYOMnQeDy
-VZVDKQBZ+jFMeI+VkNpMEdmsLErpZDGob/1dC8tLEuR6RuRR8X6IDGMPOCMw1jLK
-V1bQjPtzqKadTscfjLuKxuLgspJdTrzsu6hdcl1mm8K6CjTY2HNXWxs1yYmwfuQ2
-Z4/8sOMNqFqLjN+ChD7pksTMq7IosqGiJzi2bpd5f44ek/k822Y0ATncJHk4h1Z+
-kZBnW6kgcLna1gDri9heRwSZ+M8T8nlHgIMZIQIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBS98L4T5RaIToE3DkBRsoeWPil0eDAfBgNVHSME
-GDAWgBRxD5DQHTmtpDFKDOiMf5FAi6vfbzAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAD+4KpUeV5mUPw5IG/7w
-eOXnUpeS96XFGuS1JuFo/TbgntPWSPyo+rD4GrPIkUXyoHaMCDd2UBEjyGbBIKlB
-NZA3RJOAEp7DTkLNK4RFn/OEcLwG0J5brL7kaLRO4vwvItVIdZ2XIqzypRQTc0MG
-MmF08zycnSlaN01ryM67AsMhwdHqVa+uXQPo8R8sdFGnZ33yywTYD73FeImXilQ2
-rDnFUVqmrW1fjl0Fi4rV5XI0EQiPrzKvRtmF8ZqjGATPOsRd64cwQX6V+P5hNeIR
-9pba6td7AbNGausHfacRYMyoGJWWWkFPd+7jWOCPqW7Fk1tmBgdB8GzXa3inWIRM
-RUE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
-A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDKjCCAhKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDEw9jbGll
-bnRhdXRob3JpdHkwHhcNMTUxMDI3MTAyNjM1WhcNMjUxMDI0MTAyNjM1WjAaMRgw
-FgYDVQQDEw9jbGllbnRhdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCi6wJAs6nppNmTZ3e/wE9l0pAmkMtDONwB9o115XXTG3rmSKfZOxa8
-TFjSn818Pr1OYb9fPdI1Y6x4WY9PELUtQyEBlNcKjwg96vhrP4p2DhqbWsI5nASH
-DSjJsM75bQ7D7qHYzriuAl0Fk1C4LcodRj+5wmErMtvGJG0x06qFbxCCMAJ2kC+h
-SneTN955/YHSXADgxjFlt3s1T0QPnqrr+G7Ro6PrVKLPBulglq7wAeTwrGkPRUt0
-3lDGOSi6i97NbpiXwrGp5XiLUtVCiID6Ro0xKWH4sjJ4JnVjIUG8CQWERc6sFDJM
-4adgFQJagkTUoxWtDGL58+WcbcJa73XJAgMBAAGjezB5MBIGA1UdEwEB/wQIMAYB
-Af8CAQAwHQYDVR0OBBYEFLciwbnjKDIu026K0bzOwp8DokkOMB8GA1UdIwQYMBaA
-FLciwbnjKDIu026K0bzOwp8DokkOMA4GA1UdDwEB/wQEAwICBDATBgNVHSUEDDAK
-BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAh8rryWFoGjFdm0i4FLRktF8B
-aUqVCCpFVHIYlFcsQstznIb01X2Zq5nfSfrFxbr5STVGzGJ0HGDuFpicT8+qMnJX
-dou5AuaqubIDWeKL+oAgvI71Nt1gsesixqzFQAoCTRgUjrSGpY2fL7rElV0Ndy9b
-YepVouktP1/GULc8XbIG9ZLx70Id7YTyrITDgbH3hSnbjmmZSr9RKyKas4MXN0s8
-oKGHEgAx7KyNQRppjydz3bDeH/jVbM4W98vwL6rjKUJlOlo0Ru+3+oioFHqLMSvN
-w4f5rQEiuF260h7y8KKxRxQ8rw188gsBapZr4Rcp+y8gdQvlzJONtv3d1dap5A==
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/trusted_certs.p12 b/tests/standalone/io/certificates/trusted_certs.p12
deleted file mode 100644
index 76c76ec..0000000
--- a/tests/standalone/io/certificates/trusted_certs.p12
+++ /dev/null
Binary files differ
diff --git a/tests/standalone/io/certificates/trusted_certs.pem b/tests/standalone/io/certificates/trusted_certs.pem
deleted file mode 100644
index 8b5bf3e..0000000
--- a/tests/standalone/io/certificates/trusted_certs.pem
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
-A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-9r9ihe4CqMjx+Q2kQ2S9Gz2V2ReO/n6vm2VQxsPRB/lV/9jh7cUcS0/9mggLYrDy
-cq1v7rLLQrWuxMz1E3gOhyCYJ38CAwEAAaNQME4wHQYDVR0OBBYEFHEPkNAdOa2k
-MUoM6Ix/kUCLq99vMB8GA1UdIwQYMBaAFHEPkNAdOa2kMUoM6Ix/kUCLq99vMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABrhjnWC6b+z9Kw73C/niOwo
-9sPdufjS6tb0sCwDjt3mjvE4NdNWt+/+ZOugW6dqtvqhtqZM1q0u9pJkNwIrqgFD
-ZHcfNaf31G6Z2YE+Io7woTVw6fFobg/EFo+a/qwbvWL26McmiRL5yiSBjVjpX4a5
-kdZ+aPQUCBaLrTWwlCDqzSVIULWUQvveRWbToMFKPNID58NtEpymAx3Pgir7YjV9
-UnlU2l5vZrh1PTCqZxvC/IdRESUfW80LdHaeyizRUP+6vKxGgSz2MRuYINjbd6GO
-hGiCpWlwziW2xLV1l2qSRLko2kIafLZP18N0ThM9zKbU5ps9NgFOf//wqSGtLaE=
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/trusted_certs_malformed.pem b/tests/standalone/io/certificates/trusted_certs_malformed.pem
deleted file mode 100644
index f96698e..0000000
--- a/tests/standalone/io/certificates/trusted_certs_malformed.pem
+++ /dev/null
@@ -1,8 +0,0 @@
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAyNzEwMjYzNFoXDTI1MTAyNDEwMjYzNFowGDEWMBQG
-A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMl+dcraUM/E7E6zl7+7hK9oUJYXJLnfiMtP/TRFVbH4+2aEN8vXzPbzKdR3
-FfaHczXQTwnTCaYA4u4uSDvSOsFFEfxEwYORsdKmQEM8nGpVX2NVvKsMcGIhh8kh
-ZwJfkMIOcAxmGIHGdMhF8VghonJ8uGiuqktxdfpARq0g3fqIjDHsF9/LpfshUfk9
-wsRyTF0yr90U/dsfnE+u8l7GvVl8j2Zegp0sagAGtLaNv7tP17AibqEGg2yDBrBN
-a
diff --git a/tests/standalone/io/certificates/untrusted_server_chain.pem b/tests/standalone/io/certificates/untrusted_server_chain.pem
deleted file mode 100644
index ff6e568..0000000
--- a/tests/standalone/io/certificates/untrusted_server_chain.pem
+++ /dev/null
@@ -1,59 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDZDCCAkygAwIBAgIBATANBgkqhkiG9w0BAQsFADAgMR4wHAYDVQQDDBVpbnRl
-cm1lZGlhdGVhdXRob3JpdHkwHhcNMTUxMDE5MTE1NTEyWhcNMjUxMDE2MTE1NTEy
-WjAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDca2l3VIWhnlTqazrA07hiHjgXACUYS/nVox+a2Jar383kBz2kzN6B
-u4K7IwD2msym2IOBp1YT9OKPh9/KkSGvpPelu7ToCoehala32W+0ozh53CR8IpzQ
-tmh7J9oHtN2PcbLgEzHfAWyrY3xp9RpWUONjxoG8xXPedNsZL0Rj65Z3fKAjOypl
-+XJsgrqrNNAi3x0OMdhextMmLrYl+YQjgdND8UpykTSc8Q0vwngDZuLH/Nhx0cAA
-Ade0ZfXS6snwWVxrWke+zGF6yANoiV00gsBhq+WZZ50SmE2mz5LT9uj4t5WpcOI/
-2TlbV9HSjdOEAFD8cJIrK5FkEmz383E1AgMBAAGjgbQwgbEwPAYDVR0RBDUwM4IJ
-bG9jYWxob3N0ggkxMjcuMC4wLjGCAzo6MYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAA
-ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQO+6Atr6tkTBmPasN4oTDUlbxQ1zAf
-BgNVHSMEGDAWgBRrkK4hOni2neySWQNmMfb9imn/+DAOBgNVHQ8BAf8EBAMCA6gw
-EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBACdVUzrhfXoW
-wG0zI9aT6CxD7T0i0WK4fC6Yrx0Pqz53xnuiwBfvuAJ/PRXKYsJMxa2LuHGJKU/A
-nImCXGJHoUwL6x4Eor6fg7L9nPNqtIrQ6tzubxNtVPpLj4tK6Ps3IM+FICYUSX0b
-FLSfnv74afUp/2+0OHsoUVsL1rCTO2WgEkEShLERdJvdcvUSTWHfC5IQORS9vfzG
-+cZGOOPebfm8TY2DJxMYj/t7CHs1Sk550x590sKb/prwtJAYtQxGe7v0m9rihiM3
-dFKZiNh99yXbQ1ELYyhkFP8WAdK8ZTnynGqgAYJmV89Dg8k2uU8z+dahlE3foORD
-Y/Gn0CZE1NY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAxOTExNTUxMloXDTI1MTAxNjExNTUxMlowIDEeMBwG
-A1UEAwwVaW50ZXJtZWRpYXRlYXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA1OV9iea75DPQ18NppXxEFW26J7IfjUvp4wVnj9m7pOhsByqd
-wwS6hpjlkpEwCyugKD/t7u/VGwp2BB+BeaX7FPj6rnYY82bOJQlyB/vvDmOZfAe2
-84ug9O7QcsQHSQ7YQFuvYKaeYCKdrGjzQPVYkoVdv2js2dYTDG3QSIxpbi305Vef
-ia6Zfs5CAW/SfL36+ETo2pXNlD1ZBGRL8H3z+mMnIEj1Tbaipf+1Npr2l3xqIs1k
-RWsM3X+9xMkWGyvsDdbLIGiTTVxM9kOF0aNLdQIKb2tZsg4jRrFIgiO+5TXwp0FW
-4ldc5/GhtaoPDcsIALyIQc7CJ/PpPm9hnxIy7QIDAQABo3sweTASBgNVHRMBAf8E
-CDAGAQH/AgEAMB0GA1UdDgQWBBRrkK4hOni2neySWQNmMfb9imn/+DAfBgNVHSME
-GDAWgBRpz+jRK9iGqijrL/4WCsGsIjxoETAOBgNVHQ8BAf8EBAMCAgQwEwYDVR0l
-BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBACcwiLJUPzYGIeGIYGlo
-XlP4++adiPlXvsyTxLdGVSFWJMBV5EhtiXQXaUsOs2PyC7SWxiiUdAgE8Y2tMsF3
-Bh5LY/kKxZQXZuFa+RN1kPlhlYJWdiPyqcBziSPFBtqwudWLDUVSaVAQDhYYVB3K
-5+pFaeQKfhYmPvJKR9U2nTvukOhN1fZM8GUBnm2uaiA3giQ0wxXyQIuqC9S52qbh
-x4D4ZdbshQAgThPkHBoZVmd/NF1TNzitZZy7uaU7GpGrS1dcevN7pEUwm3+KIkIT
-AOSLB2FbFOwPUg6a/lWkFPotT3gl0tdyCaqkfneGCHzVciT0JTS/AqpdYEtuxEMe
-PJk=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC+zCCAeOgAwIBAgIBATANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1yb290
-YXV0aG9yaXR5MB4XDTE1MTAxOTExNTUxMloXDTI1MTAxNjExNTUxMlowGDEWMBQG
-A1UEAwwNcm9vdGF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAMDzkcftGzdNJz5vXEAZSCAO2J6bCPz896pK3qtaViR/aF8I2vHZQm0IEoJc
-Y1NUMF3F50d6fMYCkEoORAkC0d7iAwTprhBdIg35+TxwGObcStrohDtEgwFmFRzg
-LtYeXiU0t0dBWOOQ9k2f9VGqbzKwZ2dbhOHSTXMTFoEcMStbeFc++oiOLY+QSq/J
-Xd/BXqvwVM3Mt+OwLvyUu45Kw18ENo77qubIPJUwoyaf+N2nFRqcc7bmNy0Wvk2Q
-StvQXy6DpN3KOoZx/sR7Ff8hYuHXcxbSsJ1hOO+tIJyOZyEJvU2BBOYVlKr4E4JU
-mkex0CM1IfIFqfcEkbvjwLjaojsCAwEAAaNQME4wHQYDVR0OBBYEFGnP6NEr2Iaq
-KOsv/hYKwawiPGgRMB8GA1UdIwQYMBaAFGnP6NEr2IaqKOsv/hYKwawiPGgRMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJKl4RCEaXwtosNeurZlS3b9
-owXdsXDRdnfEawcc//AbRkrS4bHCQyOJNp/3DibEKkeAXCJrJ5cvXRjE5gb3Q+rl
-0AqziLY15xuMAxUK3zv0e8Zir21PQzQ9x8zbmlucEoT/jn7KvMSSqfEoer77cXev
-BpmQDQzE3FNgKohmHIzIDoTPiU3ahv6x8IhJ1e47UmRsSPFgtqglHcdCYIEclXpY
-bHvctT6+pFZuJfIs9+BATMXPJWSX7NhlMcnyP+xdDxDKuF/nwVFy6xA+njuWnnZT
-TyiGCnx+u/VpKzOrwMfzv2DW8Db80UERoox5n6QNQLnXNWPMddUL92/p9lMzWJY=
------END CERTIFICATE-----
diff --git a/tests/standalone/io/certificates/untrusted_server_key.pem b/tests/standalone/io/certificates/untrusted_server_key.pem
deleted file mode 100644
index 29a9e32..0000000
--- a/tests/standalone/io/certificates/untrusted_server_key.pem
+++ /dev/null
@@ -1,29 +0,0 @@
------BEGIN ENCRYPTED PRIVATE KEY-----
-MIIE5TAcBgoqhkiG9w0BDAEBMA4ECKAry4fwmB/TAgIIAASCBMNsKbVVvIs/l6/N
-/1J9WXSiA1gnRTd2n58GJUV6mkiaRUMiWu3fK+V7iHpIi7KeLeD+JGsDeqxw0bB5
-lmS/RJy0wNBP0PL0oiI8VUe3wxTUU2b5wW9fomeOTGWOIUL5VZXHkTCf5KMcFWMY
-GMnDpIN/f/m9zvz/3FogxIZlIAxG7gKKrfEcKExIShAJ5wYDbDSFZWfNcjMODGPn
-xz3W04aRsJGf3KlOQvSuNtcBpsuwXuAXezzuFETM20xrWW3iJIsO5UmqJ1OJcdet
-A+k5k0K+1/WwLkceWJYSd19O+7LNULsZhKUJ515ZSO1TJGgfd5DznkgRXYUx5ucS
-tvJLYvShGbaYulsVKn8q2nkIxnQCov3my1hIRk/qCKb+uOvRD9dIkjSlNubqaRb6
-geEOfTh1g5PCeKPlSTkVueLQqWxKMye4eWYqUxExkUNuGJ0d2ndBGJRo6bulnc7I
-kt44DzEufV5OLvyTufimpohqRm3Yzq87DWSSThCKOGkhfGutn8B7cJR8ZPrG2euT
-J7Bv4EuFjhpKDieqDi8yoXgIkWSgyzFNMsewV4lxFNP/wbvoKPFrKsU4ny6jRfzy
-WTjMN1UOTBvsyZbVvjLII79cBKLqlowHAZQ7YwuxtbjeB9FRH+ZwkzYeyn4GNHdf
-QoVwOMKAiOMjzAK9qdW7isVXy/7v9EXaZplRmwMRhCZevC9zeY2Rueahq8qpHpH1
-GPjrew5elPkBRQhxX6IiL7kI7upE65UI5hnnTnrdrZkRmMYOFEZLyLbTU4wMCxui
-4BmEiGp6qCWe3UND1b8YhG+gsRYzHK5oEJV+Ck7m+e9iU3/axggUfAhZeBmdlgqd
-bUajlzcgbtfaSgZ08XXU1YPw0aLlmJGzb+oWMFwBJHAUYpOV2uqDHiXZZt4SoAF9
-gJQaXvqMGzY8JyP5ZQauljVtPGcopA+jbix3Rbwf97lLqJHSpWoHpcCa6FrfaMqG
-dx8oQsO67WN0gm5DIN3kB2jHOj9Nf7kr3HGjyC5tPq8s1+aT6baZcHWzVfyVr10c
-9X13Pz5XzEa1oiaO7JDPkzb9T7aPJZwskATNB8h6tWfqdGyUY5eURtsCnVrtG/1p
-pAXyY/0vAksfDPjMChKLKxZ7rBbscoNzr2f7Vw4CTnIpaxA4eLEx6UdpG4/5RzYJ
-0YuR+SzCkuNti7uZGi9DCGkZkYl6VndatW+Pk/+JVBexdKt6MsER6aVsS8ev9UbW
-JG+2C8bjMlfKy21644KwYOtZbVcE9jwlsz8w+e6YbOzBvbwiPmoCi0xcMxRJPa2y
-cKMrs2hSKmhUP6uIH0b0qNcHEPA32mVzGC0MToC5R+yb6OdyvoEsisqS7tEAMfTJ
-0yowcZr2lPehaMr4efSB8JY6DuofitfgI6X6bmiIPQ9v//djxhkxkRAbpTRGmFZx
-1YIKDa72S8jUxHWlVvmoqTWI8T+jltF2pYBctS6IMKEot/CcBCHb5l1zfMyo5a0x
-73ooh5tq+vRWJGaLRMj66VVSWGQoJmfAGwWpjBpTLa0UQoHO0/J1IbfjFOj5HV3J
-bscmoGWhVwuJM5ActB0MOvXGQe9mf2X4p/1Rp+yBuipH1SJzFEzbOZ3kE50Z6aXH
-CoJJOKkcuf43
------END ENCRYPTED PRIVATE KEY-----
diff --git a/tests/standalone/io/dart_std_io_pipe_test.sh b/tests/standalone/io/dart_std_io_pipe_test.sh
deleted file mode 100755
index 7caa1ed..0000000
--- a/tests/standalone/io/dart_std_io_pipe_test.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#! /bin/bash
-
-# This script expects the following arguments
-# $1: Path to dart executable
-# $2: Path to dart echoing script
-# $3: Argument to dart echoing script (0, 1 or 2)
-# $4: File for output from piping stdout and stderr
-# $5: File prefix for output from redirecting stdout and stderr to a file.
-# $6: Stdio type of stdin
-
-# Test piping and stdio file redirection.
-echo "Hello" | $1 $2 $3 pipe pipe pipe 2>&1 | cat - > $4
-$1 $2 $3 $6 file file < $4 > $5.stdout 2> $5.stderr
-$1 $2 $3 $6 file file < $4 >> $5.stdout 2>> $5.stderr
-$1 $2 $3 $6 terminal terminal < $4 > /dev/null 2> /dev/null
-$1 $2 $3 $6 terminal pipe < $4 2>&1 > /dev/null
-$1 $2 $3 $6 terminal terminal < $4 > /dev/null 2>&1
diff --git a/tests/standalone/io/directory_invalid_arguments_test.dart b/tests/standalone/io/directory_invalid_arguments_test.dart
deleted file mode 100644
index 7b67ae3..0000000
--- a/tests/standalone/io/directory_invalid_arguments_test.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "dart:io";
-
-import "package:async_helper/async_helper.dart";
-import "package:expect/expect.dart";
-
-void testFailingList(Directory d, var recursive) {
-  asyncStart();
-  int errors = 0;
-  d
-      .list(recursive: recursive)
-      .listen(() => Expect.fail("Unexpected listing result"), onError: (error) {
-    errors += 1;
-  }, onDone: () {
-    Expect.equals(1, errors);
-    asyncEnd();
-  });
-  Expect.equals(0, errors);
-}
-
-void testInvalidArguments() {
-  try {
-    Directory d = new Directory(12);
-    Expect.fail("No exception thrown");
-  } catch (e) {
-    Expect.isTrue(e is ArgumentError);
-  }
-  Directory d = new Directory(".");
-  testFailingList(d, 1);
-  Expect.throws(() => d.listSync(recursive: 1), (e) => e is ArgumentError);
-}
-
-main() {
-  testInvalidArguments();
-}
diff --git a/tests/standalone/io/empty_file b/tests/standalone/io/empty_file
deleted file mode 100644
index e69de29..0000000
--- a/tests/standalone/io/empty_file
+++ /dev/null
diff --git a/tests/standalone/io/file_test.txt b/tests/standalone/io/file_test.txt
deleted file mode 100644
index 4c2c0d1..0000000
--- a/tests/standalone/io/file_test.txt
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "bin/file.h"
-#include "platform/assert.h"
-#include "platform/globals.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-namespace bin {
-
-// Helper method to be able to run the test from the runtime
-// directory, or the top directory.
-static const char* GetFileName(const char* name) {
-  if (File::Exists(name)) {
-    return name;
-  } else {
-    static const int kRuntimeLength = strlen("runtime/");
-    return name + kRuntimeLength;
-  }
-}
-
-
-TEST_CASE(Read) {
-  const char* kFilename = GetFileName("runtime/bin/file_test.cc");
-  File* file = File::Open(kFilename, File::kRead);
-  EXPECT(file != NULL);
-  char buffer[16];
-  buffer[0] = '\0';
-  EXPECT(file->ReadFully(buffer, 13));  // ReadFully returns true.
-  buffer[13] = '\0';
-  EXPECT_STREQ("// Copyright ", buffer);
-  EXPECT(!file->WriteByte(1));  // Cannot write to a read-only file.
-  file->Release();
-}
-
-
-TEST_CASE(FileLength) {
-  const char* kFilename =
-      GetFileName("runtime/tests/vm/data/fixed_length_file");
-  File* file = File::Open(kFilename, File::kRead);
-  EXPECT(file != NULL);
-  EXPECT_EQ(42, file->Length());
-  file->Release();
-}
-
-
-TEST_CASE(FilePosition) {
-  char buf[42];
-  const char* kFilename =
-      GetFileName("runtime/tests/vm/data/fixed_length_file");
-  File* file = File::Open(kFilename, File::kRead);
-  EXPECT(file != NULL);
-  EXPECT(file->ReadFully(buf, 12));
-  EXPECT_EQ(12, file->Position());
-  EXPECT(file->ReadFully(buf, 6));
-  EXPECT_EQ(18, file->Position());
-  file->Release();
-}
-
-}  // namespace bin
-}  // namespace dart
diff --git a/tests/standalone/io/fixed_length_file b/tests/standalone/io/fixed_length_file
deleted file mode 100644
index 52ce32d..0000000
--- a/tests/standalone/io/fixed_length_file
+++ /dev/null
@@ -1 +0,0 @@
-This file should contain exactly 42 bytes.
\ No newline at end of file
diff --git a/tests/standalone/io/fixed_length_file_invalid_arguments b/tests/standalone/io/fixed_length_file_invalid_arguments
deleted file mode 100644
index 52ce32d..0000000
--- a/tests/standalone/io/fixed_length_file_invalid_arguments
+++ /dev/null
@@ -1 +0,0 @@
-This file should contain exactly 42 bytes.
\ No newline at end of file
diff --git a/tests/standalone/io/fixed_length_file_invalid_arguments_out b/tests/standalone/io/fixed_length_file_invalid_arguments_out
deleted file mode 100644
index e69de29..0000000
--- a/tests/standalone/io/fixed_length_file_invalid_arguments_out
+++ /dev/null
diff --git a/tests/standalone/io/internet_address_invalid_arguments_test.dart b/tests/standalone/io/internet_address_invalid_arguments_test.dart
deleted file mode 100644
index 85e18cb..0000000
--- a/tests/standalone/io/internet_address_invalid_arguments_test.dart
+++ /dev/null
@@ -1,29 +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.
-
-import 'dart:io';
-
-import "package:expect/expect.dart";
-
-void testIllegalArguments() {
-  var args = [
-    null,
-    1,
-    1.1,
-    new Object(),
-    [],
-    {'a': '127.0.0.1'},
-    "",
-    ".",
-    ":",
-    ":::"
-  ];
-  args.forEach((arg) {
-    Expect.throws(() => new InternetAddress(arg), (e) => e is ArgumentError);
-  });
-}
-
-void main() {
-  testIllegalArguments();
-}
diff --git a/tests/standalone/io/io_override_test.dart b/tests/standalone/io/io_override_test.dart
deleted file mode 100644
index 1e5983a..0000000
--- a/tests/standalone/io/io_override_test.dart
+++ /dev/null
@@ -1,243 +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 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import "package:expect/expect.dart";
-
-class DirectoryMock extends FileSystemEntity implements Directory {
-  final String path = "/mockdir";
-
-  DirectoryMock(String path);
-
-  static DirectoryMock createDirectory(String path) => new DirectoryMock(path);
-  static DirectoryMock getCurrent() => new DirectoryMock(null);
-  static void setCurrent(String path) {}
-  static DirectoryMock getSystemTemp() => new DirectoryMock(null);
-
-  Uri get uri => null;
-  Future<Directory> create({bool recursive: false}) => null;
-  void createSync({bool recursive: false}) {}
-  Future<Directory> createTemp([String prefix]) => null;
-  Directory createTempSync([String prefix]) => null;
-  Future<bool> exists() => null;
-  bool existsSync() => false;
-  Future<String> resolveSymbolicLinks() => null;
-  String resolveSymbolicLinksSync() => null;
-  Future<Directory> rename(String newPath) => null;
-  Directory renameSync(String newPath) => null;
-  Directory get absolute => null;
-  Stream<FileSystemEntity> list(
-          {bool recursive: false, bool followLinks: true}) =>
-      null;
-  List<FileSystemEntity> listSync(
-          {bool recursive: false, bool followLinks: true}) =>
-      null;
-}
-
-class FileMock extends FileSystemEntity implements File {
-  String get path => "/mockfile";
-
-  FileMock(String path);
-
-  static FileMock createFile(String path) => new FileMock(path);
-
-  Future<File> create({bool recursive: false}) => null;
-  void createSync({bool recursive: false}) {}
-  Future<File> rename(String newPath) => null;
-  File renameSync(String newPath) => null;
-  Future<File> copy(String newPath) => null;
-  File copySync(String newPath) => null;
-  Future<bool> exists() => null;
-  bool existsSync() => false;
-  Future<int> length() => null;
-  int lengthSync() => null;
-  File get absolute => null;
-  Future<DateTime> lastAccessed() => null;
-  DateTime lastAccessedSync() => null;
-  Future setLastAccessed(DateTime time) => null;
-  void setLastAccessedSync(DateTime time) {}
-  Future<DateTime> lastModified() => null;
-  DateTime lastModifiedSync() => null;
-  Future setLastModified(DateTime time) => null;
-  void setLastModifiedSync(DateTime time) {}
-  Future<RandomAccessFile> open({FileMode mode: FileMode.read}) => null;
-  RandomAccessFile openSync({FileMode mode: FileMode.read}) => null;
-  Stream<List<int>> openRead([int start, int end]) => null;
-  IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) =>
-      null;
-  Future<List<int>> readAsBytes() => null;
-  List<int> readAsBytesSync() => null;
-  Future<String> readAsString({Encoding encoding: utf8}) => null;
-  String readAsStringSync({Encoding encoding: utf8}) => null;
-  Future<List<String>> readAsLines({Encoding encoding: utf8}) => null;
-  List<String> readAsLinesSync({Encoding encoding: utf8}) => null;
-  Future<File> writeAsBytes(List<int> bytes,
-          {FileMode mode: FileMode.write, bool flush: false}) =>
-      null;
-  void writeAsBytesSync(List<int> bytes,
-      {FileMode mode: FileMode.write, bool flush: false}) {}
-  Future<File> writeAsString(String contents,
-          {FileMode mode: FileMode.write,
-          Encoding encoding: utf8,
-          bool flush: false}) =>
-      null;
-  void writeAsStringSync(String contents,
-      {FileMode mode: FileMode.write,
-      Encoding encoding: utf8,
-      bool flush: false}) {}
-}
-
-class FileStatMock implements FileStat {
-  final DateTime changed = null;
-  final DateTime modified = null;
-  final DateTime accessed = null;
-  final FileSystemEntityType type = null;
-  final int mode = null;
-  final int size = null;
-
-  FileStatMock();
-
-  static Future<FileStat> stat(String path) {
-    return new Future.value(new FileStatMock());
-  }
-
-  static FileStat statSync(String path) => new FileStatMock();
-
-  String modeString() => null;
-}
-
-class FileSystemEntityMock {
-  static Future<bool> identical(String path1, String path2) {
-    return new Future.value(false);
-  }
-
-  static bool identicalSync(String path1, String path2) => false;
-
-  static Future<FileSystemEntityType> getType(String path, bool followLinks) {
-    return new Future.value(FileSystemEntityType.file);
-  }
-
-  static FileSystemEntityType getTypeSync(String path, bool followLinks) {
-    return FileSystemEntityType.file;
-  }
-}
-
-class FileSystemWatcherMock {
-  static Stream<FileSystemEvent> watch(
-      String path, int events, bool recursive) {
-    return null;
-  }
-
-  static bool watchSupported() => false;
-}
-
-class LinkMock extends FileSystemEntity implements Link {
-  String get path => "/mocklink";
-
-  LinkMock(String path);
-
-  static createLink(String path) => new LinkMock(path);
-
-  Future<Link> create(String target, {bool recursive: false}) => null;
-  void createSync(String target, {bool recursive: false}) {}
-  void updateSync(String target) {}
-  Future<Link> update(String target) => null;
-  Future<bool> exists() => null;
-  bool existsSync() => false;
-  Future<String> resolveSymbolicLinks() => null;
-  String resolveSymbolicLinksSync() => null;
-  Future<Link> rename(String newPath) => null;
-  Link renameSync(String newPath) => null;
-  Link get absolute => null;
-  Future<String> target() => null;
-  String targetSync() => null;
-}
-
-Future<Socket> socketConnect(host, int port,
-    {sourceAddress, Duration timeout}) {
-  return null;
-}
-
-Future<ConnectionTask<Socket>> socketStartConnect(host, int port,
-    {sourceAddress}) {
-  return null;
-}
-
-Future<Null> ioOverridesRunTest() async {
-  Future<Null> f = IOOverrides.runZoned(
-    () async {
-      Expect.isTrue(new Directory("directory") is DirectoryMock);
-      Expect.isTrue(Directory.current is DirectoryMock);
-      Expect.isTrue(Directory.systemTemp is DirectoryMock);
-      Expect.isTrue(new File("file") is FileMock);
-      Expect.isTrue(await FileStat.stat("file") is FileStatMock);
-      Expect.isTrue(FileStat.statSync("file") is FileStatMock);
-      Expect.isFalse(await FileSystemEntity.identical("file", "file"));
-      Expect.isFalse(FileSystemEntity.identicalSync("file", "file"));
-      Expect.equals(
-          await FileSystemEntity.type("file"), FileSystemEntityType.file);
-      Expect.equals(
-          FileSystemEntity.typeSync("file"), FileSystemEntityType.file);
-      Expect.isFalse(FileSystemEntity.isWatchSupported);
-      Expect.isNull(new Directory("directory").watch());
-      Expect.isTrue(new Link("link") is LinkMock);
-      Expect.isNull(Socket.connect(null, 0));
-      Expect.isNull(Socket.startConnect(null, 0));
-    },
-    createDirectory: DirectoryMock.createDirectory,
-    getCurrentDirectory: DirectoryMock.getCurrent,
-    setCurrentDirectory: DirectoryMock.setCurrent,
-    getSystemTempDirectory: DirectoryMock.getSystemTemp,
-    createFile: FileMock.createFile,
-    stat: FileStatMock.stat,
-    statSync: FileStatMock.statSync,
-    fseIdentical: FileSystemEntityMock.identical,
-    fseIdenticalSync: FileSystemEntityMock.identicalSync,
-    fseGetType: FileSystemEntityMock.getType,
-    fseGetTypeSync: FileSystemEntityMock.getTypeSync,
-    fsWatch: FileSystemWatcherMock.watch,
-    fsWatchIsSupported: FileSystemWatcherMock.watchSupported,
-    createLink: LinkMock.createLink,
-    socketConnect: socketConnect,
-    socketStartConnect: socketStartConnect,
-  );
-  Expect.isFalse(new Directory("directory") is DirectoryMock);
-  Expect.isTrue(new Directory("directory") is Directory);
-  await f;
-}
-
-class MyIOOverrides extends IOOverrides {
-  Directory createDirectory(String path) => DirectoryMock.createDirectory(path);
-}
-
-globalIOOverridesTest() {
-  IOOverrides.global = new MyIOOverrides();
-  Expect.isTrue(new Directory("directory") is DirectoryMock);
-  IOOverrides.global = null;
-  Directory dir = new Directory("directory");
-  Expect.isTrue(dir is! DirectoryMock);
-  Expect.isTrue(dir is Directory);
-}
-
-globalIOOverridesZoneTest() {
-  IOOverrides.global = new MyIOOverrides();
-  runZoned(() {
-    runZoned(() {
-      Expect.isTrue(new Directory("directory") is DirectoryMock);
-    });
-  });
-  IOOverrides.global = null;
-  Directory dir = new Directory("directory");
-  Expect.isTrue(dir is! DirectoryMock);
-  Expect.isTrue(dir is Directory);
-}
-
-main() async {
-  await ioOverridesRunTest();
-  globalIOOverridesTest();
-  globalIOOverridesZoneTest();
-}
diff --git a/tests/standalone/io/ln.sh b/tests/standalone/io/ln.sh
deleted file mode 100755
index 9a88c90..0000000
--- a/tests/standalone/io/ln.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-ln $1 $2 $3
diff --git a/tests/standalone/io/process_environment_lib.dart b/tests/standalone/io/process_environment_lib.dart
deleted file mode 100644
index 7446236..0000000
--- a/tests/standalone/io/process_environment_lib.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.
-
-import 'dart:io';
-
-void main() {
-  print(Platform.environment);
-}
diff --git a/tests/standalone/io/process_environment_test.dart b/tests/standalone/io/process_environment_test.dart
deleted file mode 100644
index 1a6767d..0000000
--- a/tests/standalone/io/process_environment_test.dart
+++ /dev/null
@@ -1,62 +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:convert';
-import 'dart:io';
-import 'package:expect/expect.dart';
-import 'package:path/path.dart' as path;
-
-const String childFile = 'process_environment_lib.dart';
-const String fakeKey = 'Artificial';
-const String fakeValue = 'fakepath';
-
-void main() async {
-  Map<String, String> environ = Platform.environment;
-  String baseDirectory = path.dirname(Platform.script.path);
-  //DETACHED PROCESS WITHOUT includeParentEnvironment
-  var WithoutEnviron = await Process.start(
-      Platform.executable, [path.join(baseDirectory, childFile)],
-      mode: ProcessStartMode.detachedWithStdio,
-      includeParentEnvironment: false,
-      environment: <String, String>{fakeKey: fakeValue});
-
-  Map<String, String> notInclude = new Map();
-  await for (final line in WithoutEnviron.stdout
-      .transform(systemEncoding.decoder)
-      .transform(LineSplitter())) {
-    notInclude = RestoreToMap(line);
-  }
-
-  //Ensure the child process has the passed environment
-  Expect.isTrue(notInclude.length >= 1);
-  Expect.isTrue(notInclude.keys.contains(fakeKey));
-
-  //DETACHED PROCESS WITH includeParentEnvironment
-  var WithEnviron = await Process.start(
-      Platform.executable, [path.join(baseDirectory, childFile)],
-      mode: ProcessStartMode.detachedWithStdio,
-      includeParentEnvironment: true,
-      environment: <String, String>{fakeKey: fakeValue});
-
-  Map<String, String> include = new Map();
-  await for (final line in WithEnviron.stdout
-      .transform(systemEncoding.decoder)
-      .transform(LineSplitter())) {
-    include = RestoreToMap(line);
-  }
-
-  //Parent environment and one fake path
-  Expect.isTrue(include.length == environ.length + 1);
-  Expect.isTrue(include[fakeKey] == fakeValue);
-}
-
-Map<String, String> RestoreToMap(String s) {
-  s = s.substring(1, s.length - 1);
-  Map<String, String> result = new Map();
-  for (String line in s.split(", ")) {
-    var i = line.indexOf(": ");
-    result.putIfAbsent(line.substring(0, i), () => line.substring(i + 2));
-  }
-  return result;
-}
diff --git a/tests/standalone/io/process_invalid_arguments_test.dart b/tests/standalone/io/process_invalid_arguments_test.dart
deleted file mode 100644
index 113443e..0000000
--- a/tests/standalone/io/process_invalid_arguments_test.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-//
-// Process test program to test that invalid arguments throw exceptions.
-
-import "package:expect/expect.dart";
-import "dart:io";
-
-void main() {
-  Expect.throws(() => Process.start(["true"], []), (e) => e is ArgumentError);
-  Expect.throws(() => Process.start("true", "asdf"), (e) => e is ArgumentError);
-  Expect.throws(
-      () => Process.start("true", ["asdf", 1]), (e) => e is ArgumentError);
-  ;
-  Expect.throws(() => Process.start("true", [], workingDirectory: 23),
-      (e) => e is ArgumentError);
-  Expect.throws(() => Process.run("true", [], workingDirectory: 23),
-      (e) => e is ArgumentError);
-
-  Process
-      .run("true", [], stdoutEncoding: 23)
-      .then((_) => Expect.fail("expected error"), onError: (_) {});
-
-  Process
-      .run("true", [], stderrEncoding: 23)
-      .then((_) => Expect.fail("expected error"), onError: (_) {});
-}
diff --git a/tests/standalone/io/raw_secure_server_socket_argument_test.dart b/tests/standalone/io/raw_secure_server_socket_argument_test.dart
deleted file mode 100644
index fde439d..0000000
--- a/tests/standalone/io/raw_secure_server_socket_argument_test.dart
+++ /dev/null
@@ -1,45 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-import "package:expect/expect.dart";
-import "package:path/path.dart";
-import "dart:async";
-import "dart:io";
-import "dart:isolate";
-
-const SERVER_ADDRESS = "127.0.0.1";
-const CERTIFICATE = "localhost_cert";
-
-void testArguments() {
-  bool isArgOrTypeError(e) => e is ArgumentError || e is TypeError;
-  Expect.throws(() => RawSecureServerSocket.bind(SERVER_ADDRESS, 65536, null),
-      isArgOrTypeError);
-  Expect.throws(() => RawSecureServerSocket.bind(SERVER_ADDRESS, -1, null),
-      isArgOrTypeError);
-  Expect.throws(
-      () => RawSecureServerSocket.bind(SERVER_ADDRESS, 0, null, backlog: -1),
-      isArgOrTypeError);
-  Expect.throws(
-      () => RawSecureSocket.connect(SERVER_ADDRESS, null), isArgOrTypeError);
-  Expect.throws(
-      () => RawSecureSocket.connect(SERVER_ADDRESS, -1), isArgOrTypeError);
-  Expect.throws(
-      () => RawSecureSocket.connect(SERVER_ADDRESS, 345656), isArgOrTypeError);
-  Expect.throws(
-      () => RawSecureSocket.connect(SERVER_ADDRESS, 'hest'), isArgOrTypeError);
-  Expect.throws(() => RawSecureSocket.connect(null, 0), isArgOrTypeError);
-  Expect.throws(
-      () =>
-          RawSecureSocket.connect(SERVER_ADDRESS, 0, onBadCertificate: 'hund'),
-      isArgOrTypeError);
-}
-
-main() {
-  testArguments();
-}
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
deleted file mode 100644
index 0273c5d..0000000
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ /dev/null
@@ -1,669 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-// OtherResources=certificates/server_chain.pem
-// OtherResources=certificates/server_key.pem
-// OtherResources=certificates/trusted_certs.pem
-// OtherResources=certificates/untrusted_server_chain.pem
-// OtherResources=certificates/untrusted_server_key.pem
-
-import "dart:async";
-import "dart:io";
-
-import "package:async_helper/async_helper.dart";
-import "package:expect/expect.dart";
-
-InternetAddress HOST;
-String localFile(path) => Platform.script.resolve(path).toFilePath();
-
-SecurityContext serverContext = new SecurityContext()
-  ..useCertificateChain(localFile('certificates/server_chain.pem'))
-  ..usePrivateKey(localFile('certificates/server_key.pem'),
-      password: 'dartdart');
-
-SecurityContext clientContext = new SecurityContext()
-  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
-
-void testSimpleBind() {
-  print("asyncStart testSimpleBind");
-  asyncStart();
-  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
-    Expect.isTrue(s.port > 0);
-    s.close();
-    print("asyncEnd testSimpleBind");
-    asyncEnd();
-  });
-}
-
-void testInvalidBind() {
-  int count = 0;
-
-  // Bind to a unknown DNS name.
-  asyncStart();
-  print("asyncStart testInvalidBind");
-  RawSecureServerSocket.bind("ko.faar.__hest__", 0, serverContext).then((_) {
-    Expect.fail("Failure expected");
-  }).catchError((error) {
-    Expect.isTrue(error is SocketException);
-    print("asyncEnd testInvalidBind");
-    asyncEnd();
-  });
-
-  // Bind to an unavaliable IP-address.
-  asyncStart();
-  print("asyncStart testInvalidBind 2");
-  RawSecureServerSocket.bind("8.8.8.8", 0, serverContext).then((_) {
-    Expect.fail("Failure expected");
-  }).catchError((error) {
-    Expect.isTrue(error is SocketException);
-    print("asyncEnd testInvalidBind 2");
-    asyncEnd();
-  });
-
-  // Bind to a port already in use.
-  asyncStart();
-  print("asyncStart testInvalidBind 3");
-  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
-    RawSecureServerSocket.bind(HOST, s.port, serverContext).then((t) {
-      s.close();
-      t.close();
-      Expect.fail("Multiple listens on same port");
-    }).catchError((error) {
-      Expect.isTrue(error is SocketException);
-      s.close();
-      print("asyncEnd testInvalidBind 3");
-      asyncEnd();
-    });
-  });
-}
-
-void testSimpleConnect() {
-  print("asyncStart testSimpleConnect");
-  asyncStart();
-  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
-    var clientEndFuture =
-        RawSecureSocket.connect(HOST, server.port, context: clientContext);
-    server.listen((serverEnd) {
-      clientEndFuture.then((clientEnd) {
-        // TODO(whesse): Shutdown(SEND) not supported on secure sockets.
-        clientEnd.shutdown(SocketDirection.send);
-        serverEnd.shutdown(SocketDirection.send);
-        server.close();
-        print("asyncEnd testSimpleConnect");
-        asyncEnd();
-      });
-    });
-  });
-}
-
-int debugTestSimpleConnectFailCounter = 0;
-void testSimpleConnectFail(SecurityContext context, bool cancelOnError) {
-  var counter = debugTestSimpleConnectFailCounter++;
-  print("asyncStart testSimpleConnectFail $counter");
-  asyncStart();
-  RawSecureServerSocket.bind(HOST, 0, context).then((server) {
-    var clientEndFuture = RawSecureSocket
-        .connect(HOST, server.port, context: clientContext)
-        .then((clientEnd) {
-      Expect.fail("No client connection expected.");
-    }).catchError((error) {
-      Expect.isTrue(error is SocketException || error is HandshakeException);
-    });
-    server.listen((serverEnd) {
-      Expect.fail("No server connection expected.");
-    }, onError: (error) {
-      Expect.isTrue(error is SocketException || error is HandshakeException);
-      clientEndFuture.then((_) {
-        if (!cancelOnError) server.close();
-        print("asyncEnd testSimpleConnectFail $counter");
-        asyncEnd();
-      });
-    }, cancelOnError: cancelOnError);
-  });
-}
-
-void testServerListenAfterConnect() {
-  print("asyncStart testServerListenAfterConnect");
-  asyncStart();
-  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
-    Expect.isTrue(server.port > 0);
-    var clientEndFuture =
-        RawSecureSocket.connect(HOST, server.port, context: clientContext);
-    new Timer(const Duration(milliseconds: 500), () {
-      server.listen((serverEnd) {
-        clientEndFuture.then((clientEnd) {
-          clientEnd.shutdown(SocketDirection.send);
-          serverEnd.shutdown(SocketDirection.send);
-          server.close();
-          print("asyncEnd testServerListenAfterConnect");
-          asyncEnd();
-        });
-      });
-    });
-  });
-}
-
-// This test creates a server and a client connects. The client then
-// writes and the server echos. When the server has finished its echo
-// it half-closes. When the client gets the close event is closes
-// fully.
-//
-// The test can be run in different configurations based on
-// the boolean arguments:
-//
-// listenSecure
-// When this argument is true a secure server is used. When this is false
-// a non-secure server is used and the connections are secured after being
-// connected.
-//
-// connectSecure
-// When this argument is true a secure client connection is used. When this
-// is false a non-secure client connection is used and the connection is
-// secured after being connected.
-//
-// handshakeBeforeSecure
-// When this argument is true some initial clear text handshake is done
-// between client and server before the connection is secured. This argument
-// only makes sense when both listenSecure and connectSecure are false.
-//
-// postponeSecure
-// When this argument is false the securing of the server end will
-// happen as soon as the last byte of the handshake before securing
-// has been written. When this argument is true the securing of the
-// server will not happen until the first TLS handshake data has been
-// received from the client. This argument only takes effect when
-// handshakeBeforeSecure is true.
-void testSimpleReadWrite(
-    {bool listenSecure,
-    bool connectSecure,
-    bool handshakeBeforeSecure,
-    bool postponeSecure,
-    bool dropReads}) {
-  int clientReads = 0;
-  int serverReads = 0;
-  if (handshakeBeforeSecure == true &&
-      (listenSecure == true || connectSecure == true)) {
-    Expect.fail("Invalid arguments to testSimpleReadWrite");
-  }
-
-  print("asyncStart testSimpleReadWrite($listenSecure, $connectSecure, "
-      "$handshakeBeforeSecure, $postponeSecure, $dropReads");
-  asyncStart();
-
-  const messageSize = 1000;
-  const handshakeMessageSize = 100;
-
-  List<int> createTestData() {
-    List<int> data = new List<int>(messageSize);
-    for (int i = 0; i < messageSize; i++) {
-      data[i] = i & 0xff;
-    }
-    return data;
-  }
-
-  List<int> createHandshakeTestData() {
-    List<int> data = new List<int>(handshakeMessageSize);
-    for (int i = 0; i < handshakeMessageSize; i++) {
-      data[i] = i & 0xff;
-    }
-    return data;
-  }
-
-  void verifyTestData(List<int> data) {
-    Expect.equals(messageSize, data.length);
-    List<int> expected = createTestData();
-    for (int i = 0; i < messageSize; i++) {
-      Expect.equals(expected[i], data[i]);
-    }
-  }
-
-  void verifyHandshakeTestData(List<int> data) {
-    Expect.equals(handshakeMessageSize, data.length);
-    List<int> expected = createHandshakeTestData();
-    for (int i = 0; i < handshakeMessageSize; i++) {
-      Expect.equals(expected[i], data[i]);
-    }
-  }
-
-  Future runServer(RawSocket client) {
-    var completer = new Completer();
-    int bytesRead = 0;
-    int bytesWritten = 0;
-    List<int> data = new List<int>(messageSize);
-    client.writeEventsEnabled = false;
-    var subscription;
-    subscription = client.listen((event) {
-      switch (event) {
-        case RawSocketEvent.read:
-          if (dropReads) {
-            if (serverReads != 10) {
-              ++serverReads;
-              break;
-            } else {
-              serverReads = 0;
-            }
-          }
-          Expect.isTrue(bytesWritten == 0);
-          Expect.isTrue(client.available() > 0);
-          var buffer = client.read();
-          if (buffer != null) {
-            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
-            bytesRead += buffer.length;
-            for (var value in buffer) {
-              Expect.isTrue(value is int);
-              Expect.isTrue(value < 256 && value >= 0);
-            }
-          }
-          if (bytesRead == data.length) {
-            verifyTestData(data);
-            client.writeEventsEnabled = true;
-          }
-          break;
-        case RawSocketEvent.write:
-          Expect.isFalse(client.writeEventsEnabled);
-          Expect.equals(bytesRead, data.length);
-          for (int i = bytesWritten; i < data.length; ++i) {
-            Expect.isTrue(data[i] is int);
-            Expect.isTrue(data[i] < 256 && data[i] >= 0);
-          }
-          bytesWritten +=
-              client.write(data, bytesWritten, data.length - bytesWritten);
-          if (bytesWritten < data.length) {
-            client.writeEventsEnabled = true;
-          }
-          if (bytesWritten == data.length) {
-            client.shutdown(SocketDirection.send);
-          }
-          break;
-        case RawSocketEvent.readClosed:
-          completer.complete(null);
-          break;
-        default:
-          throw "Unexpected event $event";
-      }
-    });
-    return completer.future;
-  }
-
-  Future<RawSocket> runClient(RawSocket socket) {
-    var completer = new Completer();
-    int bytesRead = 0;
-    int bytesWritten = 0;
-    List<int> dataSent = createTestData();
-    List<int> dataReceived = new List<int>(dataSent.length);
-    socket.listen((event) {
-      switch (event) {
-        case RawSocketEvent.read:
-          Expect.isTrue(socket.available() > 0);
-          if (dropReads) {
-            if (clientReads != 10) {
-              ++clientReads;
-              break;
-            } else {
-              clientReads = 0;
-            }
-          }
-          var buffer = socket.read();
-          if (buffer != null) {
-            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
-            bytesRead += buffer.length;
-          }
-          break;
-        case RawSocketEvent.write:
-          Expect.isTrue(bytesRead == 0);
-          Expect.isFalse(socket.writeEventsEnabled);
-          bytesWritten += socket.write(
-              dataSent, bytesWritten, dataSent.length - bytesWritten);
-          if (bytesWritten < dataSent.length) {
-            socket.writeEventsEnabled = true;
-          }
-          break;
-        case RawSocketEvent.readClosed:
-          verifyTestData(dataReceived);
-          completer.complete(socket);
-          break;
-        default:
-          throw "Unexpected event $event";
-      }
-    });
-    return completer.future;
-  }
-
-  Future runServerHandshake(RawSocket client) {
-    var completer = new Completer();
-    int bytesRead = 0;
-    int bytesWritten = 0;
-    List<int> data = new List<int>(handshakeMessageSize);
-    client.writeEventsEnabled = false;
-    var subscription;
-    subscription = client.listen((event) {
-      switch (event) {
-        case RawSocketEvent.read:
-          if (bytesRead < data.length) {
-            Expect.isTrue(bytesWritten == 0);
-          }
-          Expect.isTrue(client.available() > 0);
-          if (dropReads) {
-            if (serverReads != 10) {
-              ++serverReads;
-              break;
-            } else {
-              serverReads = 0;
-            }
-          }
-          var buffer = client.read();
-          if (buffer != null) {
-            if (bytesRead == data.length) {
-              // Read first part of TLS handshake from client.
-              Expect.isTrue(postponeSecure);
-              completer.complete([subscription, buffer]);
-              client.readEventsEnabled = false;
-              return;
-            }
-            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
-            bytesRead += buffer.length;
-            for (var value in buffer) {
-              Expect.isTrue(value is int);
-              Expect.isTrue(value < 256 && value >= 0);
-            }
-          }
-          if (bytesRead == data.length) {
-            verifyHandshakeTestData(data);
-            client.writeEventsEnabled = true;
-          }
-          break;
-        case RawSocketEvent.write:
-          Expect.isFalse(client.writeEventsEnabled);
-          Expect.equals(bytesRead, data.length);
-          for (int i = bytesWritten; i < data.length; ++i) {
-            Expect.isTrue(data[i] is int);
-            Expect.isTrue(data[i] < 256 && data[i] >= 0);
-          }
-          bytesWritten +=
-              client.write(data, bytesWritten, data.length - bytesWritten);
-          if (bytesWritten < data.length) {
-            client.writeEventsEnabled = true;
-          }
-          if (bytesWritten == data.length) {
-            if (!postponeSecure) {
-              completer.complete([subscription, null]);
-            }
-          }
-          break;
-        case RawSocketEvent.readClosed:
-          Expect.fail("Unexpected close");
-          break;
-        default:
-          throw "Unexpected event $event";
-      }
-    });
-    return completer.future;
-  }
-
-  Future<RawSocket> runClientHandshake(RawSocket socket) {
-    var completer = new Completer();
-    int bytesRead = 0;
-    int bytesWritten = 0;
-    List<int> dataSent = createHandshakeTestData();
-    List<int> dataReceived = new List<int>(dataSent.length);
-    var subscription;
-    subscription = socket.listen((event) {
-      switch (event) {
-        case RawSocketEvent.read:
-          if (dropReads) {
-            if (clientReads != 10) {
-              ++clientReads;
-              break;
-            } else {
-              clientReads = 0;
-            }
-          }
-          Expect.isTrue(socket.available() > 0);
-          var buffer = socket.read();
-          if (buffer != null) {
-            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
-            bytesRead += buffer.length;
-            if (bytesRead == dataSent.length) {
-              verifyHandshakeTestData(dataReceived);
-              completer.complete(subscription);
-            }
-          }
-          break;
-        case RawSocketEvent.write:
-          Expect.isTrue(bytesRead == 0);
-          Expect.isFalse(socket.writeEventsEnabled);
-          bytesWritten += socket.write(
-              dataSent, bytesWritten, dataSent.length - bytesWritten);
-          if (bytesWritten < dataSent.length) {
-            socket.writeEventsEnabled = true;
-          }
-          break;
-        case RawSocketEvent.readClosed:
-          Expect.fail("Unexpected close");
-          break;
-        default:
-          throw "Unexpected event $event";
-      }
-    });
-    return completer.future;
-  }
-
-  Future<RawSecureSocket> connectClient(int port) {
-    if (connectSecure) {
-      return RawSecureSocket.connect(HOST, port, context: clientContext);
-    } else if (!handshakeBeforeSecure) {
-      return RawSocket.connect(HOST, port).then((socket) {
-        return RawSecureSocket.secure(socket, context: clientContext);
-      });
-    } else {
-      return RawSocket.connect(HOST, port).then((socket) {
-        return runClientHandshake(socket).then((subscription) {
-          return RawSecureSocket.secure(socket,
-              context: clientContext, subscription: subscription);
-        });
-      });
-    }
-  }
-
-  serverReady(server) {
-    server.listen((client) {
-      if (listenSecure) {
-        runServer(client).then((_) => server.close());
-      } else if (!handshakeBeforeSecure) {
-        RawSecureSocket.secureServer(client, serverContext).then((client) {
-          runServer(client).then((_) => server.close());
-        });
-      } else {
-        runServerHandshake(client).then((secure) {
-          RawSecureSocket
-              .secureServer(client, serverContext,
-                  subscription: secure[0], bufferedData: secure[1])
-              .then((client) {
-            runServer(client).then((_) => server.close());
-          });
-        });
-      }
-    });
-
-    connectClient(server.port).then(runClient).then((socket) {
-      socket.close();
-      print("asyncEnd testSimpleReadWrite($listenSecure, $connectSecure, "
-          "$handshakeBeforeSecure, $postponeSecure, $dropReads");
-      asyncEnd();
-    });
-  }
-
-  if (listenSecure) {
-    RawSecureServerSocket.bind(HOST, 0, serverContext).then(serverReady);
-  } else {
-    RawServerSocket.bind(HOST, 0).then(serverReady);
-  }
-}
-
-testPausedSecuringSubscription(bool pausedServer, bool pausedClient) {
-  print(
-      "asyncStart testPausedSecuringSubscription $pausedServer $pausedClient");
-  asyncStart();
-  var clientComplete = new Completer();
-  RawServerSocket.bind(HOST, 0).then((server) {
-    server.listen((client) {
-      var subscription;
-      subscription = client.listen((_) {
-        if (pausedServer) {
-          subscription.pause();
-        }
-        void done() {
-          server.close();
-          clientComplete.future.then((_) {
-            client.close();
-            print("asyncEnd testPausedSecuringSubscription "
-                "$pausedServer $pausedClient");
-            asyncEnd();
-          });
-        }
-
-        try {
-          RawSecureSocket
-              .secureServer(client, serverContext, subscription: subscription)
-              .catchError((_) {})
-              .whenComplete(() {
-            if (pausedServer) {
-              Expect.fail("secureServer succeeded with paused subscription");
-            }
-            done();
-          });
-        } catch (e) {
-          if (!pausedServer) {
-            Expect.fail("secureServer failed with non-paused subscriptions");
-          }
-          if (pausedServer) {
-            Expect.isTrue(e is ArgumentError);
-          }
-          done();
-        }
-      });
-    });
-
-    RawSocket.connect(HOST, server.port).then((socket) {
-      var subscription;
-      subscription = socket.listen((_) {
-        if (pausedClient) {
-          subscription.pause();
-        }
-        try {
-          RawSecureSocket
-              .secure(socket, subscription: subscription)
-              .catchError((_) {})
-              .whenComplete(() {
-            if (pausedClient) {
-              Expect.fail("secure succeeded with paused subscription");
-            }
-            socket.close();
-            clientComplete.complete(null);
-          });
-        } catch (e) {
-          if (!pausedClient) {
-            Expect.fail("secure failed with non-paused subscriptions ($e)");
-          }
-          if (pausedClient) {
-            Expect.isTrue(e is ArgumentError);
-          }
-          clientComplete.complete(null);
-        }
-      });
-    });
-  });
-}
-
-main() {
-  print("asyncStart main");
-  asyncStart();
-  InternetAddress.lookup("localhost").then((hosts) {
-    HOST = hosts.first;
-    runTests();
-    print("asyncEnd main");
-    asyncEnd();
-  });
-}
-
-runTests() {
-  testSimpleBind();
-  testInvalidBind();
-  testSimpleConnect();
-  SecurityContext context = new SecurityContext();
-  testSimpleConnectFail(context, false);
-  testSimpleConnectFail(context, true);
-  var chain = Platform.script
-      .resolve('certificates/untrusted_server_chain.pem')
-      .toFilePath();
-  context.useCertificateChain(chain);
-  testSimpleConnectFail(context, false);
-  testSimpleConnectFail(context, true);
-  var key = Platform.script
-      .resolve('certificates/untrusted_server_key.pem')
-      .toFilePath();
-  context.usePrivateKey(key, password: 'dartdart');
-  testSimpleConnectFail(context, false);
-  testSimpleConnectFail(context, true);
-  testServerListenAfterConnect();
-
-  testSimpleReadWrite(
-      listenSecure: true,
-      connectSecure: true,
-      handshakeBeforeSecure: false,
-      postponeSecure: false,
-      dropReads: false);
-  testSimpleReadWrite(
-      listenSecure: true,
-      connectSecure: false,
-      handshakeBeforeSecure: false,
-      postponeSecure: false,
-      dropReads: false);
-
-  testSimpleReadWrite(
-      listenSecure: false,
-      connectSecure: true,
-      handshakeBeforeSecure: false,
-      postponeSecure: false,
-      dropReads: false);
-
-  testSimpleReadWrite(
-      listenSecure: false,
-      connectSecure: false,
-      handshakeBeforeSecure: false,
-      postponeSecure: false,
-      dropReads: false);
-  testSimpleReadWrite(
-      listenSecure: false,
-      connectSecure: false,
-      handshakeBeforeSecure: true,
-      postponeSecure: true,
-      dropReads: false);
-  testSimpleReadWrite(
-      listenSecure: false,
-      connectSecure: false,
-      handshakeBeforeSecure: true,
-      postponeSecure: false,
-      dropReads: false);
-  testSimpleReadWrite(
-      listenSecure: true,
-      connectSecure: true,
-      handshakeBeforeSecure: false,
-      postponeSecure: false,
-      dropReads: true);
-  testSimpleReadWrite(
-      listenSecure: false,
-      connectSecure: false,
-      handshakeBeforeSecure: true,
-      postponeSecure: true,
-      dropReads: true);
-  testPausedSecuringSubscription(false, false);
-  testPausedSecuringSubscription(true, false);
-  testPausedSecuringSubscription(false, true);
-  testPausedSecuringSubscription(true, true);
-}
diff --git a/tests/standalone/io/read_as_text.dat b/tests/standalone/io/read_as_text.dat
deleted file mode 100644
index db2cce6..0000000
--- a/tests/standalone/io/read_as_text.dat
+++ /dev/null
@@ -1 +0,0 @@
-λx. x
diff --git a/tests/standalone/io/readline_test1.dat b/tests/standalone/io/readline_test1.dat
deleted file mode 100644
index cfbbd08..0000000
--- a/tests/standalone/io/readline_test1.dat
+++ /dev/null
@@ -1,10 +0,0 @@
-# Test file with 10 lines and terminating line feed
-#
-Line 3
-Line 4
-Line 5
-Line 6
-Line 7
-Line 8
-Line 9
-Line 10
diff --git a/tests/standalone/io/readline_test2.dat b/tests/standalone/io/readline_test2.dat
deleted file mode 100644
index 784dee2..0000000
--- a/tests/standalone/io/readline_test2.dat
+++ /dev/null
@@ -1,10 +0,0 @@
-# Test file with 10 lines without terminating line feed
-#
-Line 3
-Line 4
-Line 5
-Line 6
-Line 7
-Line 8
-Line 9
-Line 10
\ No newline at end of file
diff --git a/tests/standalone/io/readuntil_test.dat b/tests/standalone/io/readuntil_test.dat
deleted file mode 100644
index aa117d2..0000000
--- a/tests/standalone/io/readuntil_test.dat
+++ /dev/null
@@ -1,2 +0,0 @@
-Hello Dart
-wassup!
diff --git a/tests/standalone/io/secure_socket_bad_data_test.dart b/tests/standalone/io/secure_socket_bad_data_test.dart
deleted file mode 100644
index 2cf5777..0000000
--- a/tests/standalone/io/secure_socket_bad_data_test.dart
+++ /dev/null
@@ -1,152 +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.
-//
-// VMOptions=
-// VMOptions=--short_socket_read
-// VMOptions=--short_socket_write
-// VMOptions=--short_socket_read --short_socket_write
-
-import "dart:async";
-import "dart:io";
-
-import "package:async_helper/async_helper.dart";
-import "package:expect/expect.dart";
-
-InternetAddress HOST;
-const CERTIFICATE = "localhost_cert";
-
-// This test sends corrupt data in the middle of a secure network connection.
-// This tests the error handling of RawSecureSocket.
-// A RawSocket connection is upgraded to a secure connection, so that we
-// have a reference to the underlying socket.  Then we send some
-// unencrypted data on it, in the middle of an encrypted data transfer.
-
-// This test creates a server and then connects a client to the server.
-// After connecting, the connection is upgraded to a secure connection.
-// The client writes data to the server, then writes unencrypted data
-// on the underlying socket.  When the server gets the unencrypted data,
-// this causes an error in the NSS code.  When the NSS code is in debug
-// mode, bad data on the connection can cause an assertion failure, rather
-// than an exception.
-
-const messageSize = 1000;
-
-List<int> createTestData() {
-  List<int> data = new List<int>(messageSize);
-  for (int i = 0; i < messageSize; i++) {
-    data[i] = i & 0xff;
-  }
-  return data;
-}
-
-void verifyTestData(List<int> data) {
-  Expect.equals(messageSize, data.length);
-  List<int> expected = createTestData();
-  for (int i = 0; i < messageSize; i++) {
-    Expect.equals(expected[i], data[i]);
-  }
-}
-
-Future runServer(RawSocket client) {
-  final completer = new Completer();
-  final dataReceived = new List<int>(messageSize);
-  int bytesRead = 0;
-  client.writeEventsEnabled = false;
-  client.listen((event) {
-    switch (event) {
-      case RawSocketEvent.read:
-        Expect.isTrue(client.available() > 0);
-        var buffer = client.read(200);
-        dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
-        bytesRead += buffer.length;
-        if (bytesRead == dataReceived.length) {
-          verifyTestData(dataReceived);
-        }
-        break;
-      case RawSocketEvent.write:
-        Expect.fail('WRITE event received');
-        break;
-      case RawSocketEvent.readClosed:
-        Expect.fail('READ_CLOSED event received');
-        client.shutdown(SocketDirection.send);
-        completer.complete(null);
-        break;
-    }
-  }, onError: (e) {
-    Expect.isTrue(e is TlsException);
-    Expect.isTrue(e.toString().contains(
-        'received a record with an incorrect Message Authentication Code'));
-    completer.complete(null);
-  });
-  return completer.future;
-}
-
-Future<RawSocket> runClient(List sockets) {
-  final RawSocket baseSocket = sockets[0];
-  final RawSecureSocket socket = sockets[1];
-  final data = createTestData();
-  var completer = new Completer();
-  void tryComplete() {
-    if (completer != null) {
-      completer.complete(null);
-      completer = null;
-    }
-  }
-
-  int bytesWritten = 0;
-  socket.listen((event) {
-    switch (event) {
-      case RawSocketEvent.read:
-        Expect.fail('READ event received');
-        break;
-      case RawSocketEvent.write:
-        if (bytesWritten < data.length) {
-          bytesWritten += socket.write(data, bytesWritten);
-        }
-        if (bytesWritten < data.length) {
-          socket.writeEventsEnabled = true;
-        }
-        if (bytesWritten == data.length) {
-          baseSocket.write(data, 0, 300);
-          socket.shutdown(SocketDirection.send);
-        }
-        break;
-      case RawSocketEvent.readClosed:
-        tryComplete();
-        break;
-    }
-  }, onError: (e) {
-    Expect.isTrue(e is IOException);
-    tryComplete();
-  });
-  return completer.future;
-}
-
-Future<List> connectClient(int port, bool hostnameInConnect) =>
-    RawSocket.connect(HOST, port).then((socket) => (hostnameInConnect
-            ? RawSecureSocket.secure(socket)
-            : RawSecureSocket.secure(socket, host: HOST))
-        .then((secureSocket) => [socket, secureSocket]));
-
-Future test(bool hostnameInConnect) {
-  return RawServerSocket.bind(HOST, 0).then((server) {
-    server.listen((client) {
-      RawSecureSocket.secureServer(client, CERTIFICATE).then((secureClient) {
-        Expect.throws(() => client.add([0]));
-        return runServer(secureClient);
-      }, onError: (e) {
-        Expect.isTrue(e is HandshakeException);
-      }).whenComplete(server.close);
-    });
-    return connectClient(server.port, hostnameInConnect).then(runClient);
-  });
-}
-
-main() {
-  asyncStart();
-  InternetAddress.lookup("localhost").then((hosts) {
-    HOST = hosts.first;
-    return Future.wait([test(false), test(true)]);
-  }).then((_) => asyncEnd());
-}
diff --git a/tests/standalone/io/security_context_argument_test.dart b/tests/standalone/io/security_context_argument_test.dart
deleted file mode 100644
index d6f30dd..0000000
--- a/tests/standalone/io/security_context_argument_test.dart
+++ /dev/null
@@ -1,154 +0,0 @@
-// 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.
-//
-// OtherResources=certificates/server_chain.pem
-// OtherResources=certificates/server_key.pem
-// OtherResources=certificates/server_key.p12
-// OtherResources=certificates/client1_key_malformed.pem
-// OtherResources=certificates/trusted_certs_malformed.pem
-// OtherResources=certificates/server_chain_malformed1.pem
-// OtherResources=certificates/server_chain_malformed2.pem
-// OtherResources=certificates/client_authority_malformed.pem
-
-import "package:expect/expect.dart";
-import "dart:io";
-
-String localFile(path) => Platform.script.resolve(path).toFilePath();
-
-bool printException(e) {
-  print(e);
-  return true;
-}
-
-bool argumentError(e) => e is ArgumentError;
-bool argumentOrTypeError(e) => e is ArgumentError || e is TypeError;
-bool fileSystemException(e) => e is FileSystemException;
-bool tlsException(e) => e is TlsException;
-
-void testUsePrivateKeyArguments() {
-  var c = new SecurityContext();
-  c.useCertificateChain(localFile('certificates/server_chain.pem'));
-
-  // Wrong password.
-  Expect.throws(() => c.usePrivateKey(localFile('certificates/server_key.pem')),
-      tlsException);
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key.pem'),
-          password: "iHackSites"),
-      tlsException);
-  Expect.throws(() => c.usePrivateKey(localFile('certificates/server_key.p12')),
-      tlsException);
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key.p12'),
-          password: "iHackSites"),
-      tlsException);
-  Expect.throws(
-      () => c.setTrustedCertificates(localFile('certificates/server_key.p12')),
-      tlsException);
-  Expect.throws(
-      () => c.setTrustedCertificates(localFile('certificates/server_key.p12'),
-          password: "iHackSites"),
-      tlsException);
-  Expect.throws(
-      () => c.useCertificateChain(localFile('certificates/server_key.p12')),
-      tlsException);
-  Expect.throws(
-      () => c.useCertificateChain(localFile('certificates/server_key.p12'),
-          password: "iHackSites"),
-      tlsException);
-  Expect.throws(
-      () => c.setClientAuthorities(localFile('certificates/server_key.p12')),
-      tlsException);
-  Expect.throws(
-      () => c.setClientAuthorities(localFile('certificates/server_key.p12'),
-          password: "iHackSites"),
-      tlsException);
-
-  // File does not exist
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key_oops.pem'),
-          password: "dartdart"),
-      fileSystemException);
-
-  // Wrong type for file name or data
-  Expect.throws(() => c.usePrivateKey(1), argumentOrTypeError);
-  Expect.throws(() => c.usePrivateKey(null), argumentError);
-  Expect.throws(() => c.usePrivateKeyBytes(1), argumentOrTypeError);
-  Expect.throws(() => c.usePrivateKeyBytes(null), argumentError);
-
-  // Too-long passwords.
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key.pem'),
-          password: "dart" * 1000),
-      argumentError);
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key.p12'),
-          password: "dart" * 1000),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.setTrustedCertificates(localFile('certificates/server_key.p12'),
-          password: "dart" * 1000),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.useCertificateChain(localFile('certificates/server_key.p12'),
-          password: "dart" * 1000),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.setClientAuthorities(localFile('certificates/server_key.p12'),
-          password: "dart" * 1000),
-      argumentOrTypeError);
-
-  // Bad password type.
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/server_key.pem'),
-          password: 3),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.setTrustedCertificatesBytes(
-          localFile('certificates/server_key.pem'),
-          password: 3),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.useCertificateChainBytes(localFile('certificates/server_key.pem'),
-          password: 3),
-      argumentOrTypeError);
-  Expect.throws(
-      () => c.setClientAuthoritiesBytes(
-          localFile('certificates/server_key.pem'),
-          password: 3),
-      argumentOrTypeError);
-
-  // Empty data.
-  Expect.throws(
-      () => c.usePrivateKeyBytes([], password: 'dartdart'), tlsException);
-  Expect.throws(() => c.setTrustedCertificatesBytes([]), tlsException);
-  Expect.throws(() => c.useCertificateChainBytes([]), tlsException);
-  Expect.throws(() => c.setClientAuthoritiesBytes([]), tlsException);
-
-  // Malformed PEM certs.
-  Expect.throws(
-      () => c.usePrivateKey(localFile('certificates/client1_key_malformed.pem'),
-          password: "dartdart"),
-      tlsException);
-  Expect.throws(
-      () => c.setTrustedCertificates(
-          localFile('certificates/trusted_certs_malformed.pem')),
-      tlsException);
-  Expect.throws(
-      () => c.useCertificateChain(
-          localFile('certificates/server_chain_malformed1.pem')),
-      tlsException);
-  Expect.throws(
-      () => c.useCertificateChain(
-          localFile('certificates/server_chain_malformed2.pem')),
-      tlsException);
-  Expect.throws(
-      () => c.setClientAuthorities(
-          localFile('certificates/client_authority_malformed.pem')),
-      tlsException);
-}
-
-void main() {
-  testUsePrivateKeyArguments();
-}
diff --git a/tests/standalone/io/socket_invalid_arguments_test.dart b/tests/standalone/io/socket_invalid_arguments_test.dart
deleted file mode 100644
index 5da94e3..0000000
--- a/tests/standalone/io/socket_invalid_arguments_test.dart
+++ /dev/null
@@ -1,92 +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.
-
-import "dart:io";
-
-import "package:async_helper/async_helper.dart";
-import "package:expect/expect.dart";
-
-class NotAnInteger {
-  operator ==(other) => other == 1;
-  operator <(other) => other > 1;
-  operator +(other) => 1;
-}
-
-class NotAList {
-  get length => 10;
-  operator [](index) => 1;
-}
-
-testSocketCreation(host, port) {
-  asyncStart();
-  try {
-    Socket
-        .connect(host, port)
-        .then((socket) => Expect.fail("Shouldn't get connected"))
-        .catchError((e) {
-      Expect.isTrue(e is ArgumentError || e is SocketException);
-      asyncEnd();
-    });
-  } catch (e) {
-    Expect.isTrue(e is ArgumentError || e is SocketException);
-    asyncEnd();
-  }
-}
-
-testAdd(buffer) {
-  asyncStart();
-  asyncStart();
-  ServerSocket.bind("127.0.0.1", 0).then((server) {
-    server.listen((socket) => socket.destroy());
-    Socket.connect("127.0.0.1", server.port).then((socket) {
-      int errors = 0;
-      socket.done.catchError((e) {
-        errors++;
-      }).then((_) {
-        Expect.equals(1, errors);
-        asyncEnd();
-        server.close();
-      });
-      socket.listen((_) {}, onError: (error) {
-        Expect.fail("Error on stream");
-      }, onDone: () {
-        asyncEnd();
-      });
-      socket.add(buffer);
-    });
-  });
-}
-
-testServerSocketCreation(address, port, backlog) {
-  asyncStart();
-  var server;
-  try {
-    ServerSocket.bind(address, port, backlog: backlog).then((_) {
-      Expect.fail("ServerSocket bound");
-    }).catchError((e) => asyncEnd());
-  } catch (e) {
-    asyncEnd();
-  }
-}
-
-main() {
-  testSocketCreation(123, 123);
-  testSocketCreation("string", null);
-  testSocketCreation(null, null);
-  testSocketCreation("localhost", -1);
-  testSocketCreation("localhost", 65536);
-  testAdd(null);
-  testAdd(new NotAList());
-  testAdd(42);
-  // TODO(8233): Throw ArgumentError from API implementation.
-  // testAdd([-1]);
-  // testAdd([2222222222222222222222222222222]);
-  // testAdd([1, 2, 3, null]);
-  // testAdd([new NotAnInteger()]);
-  testServerSocketCreation(123, 123, 123);
-  testServerSocketCreation("string", null, null);
-  testServerSocketCreation("string", 123, null);
-  testServerSocketCreation("localhost", -1, 123);
-  testServerSocketCreation("localhost", 65536, 123);
-}
diff --git a/tests/standalone/io/stdout_bad_argument_test.dart b/tests/standalone/io/stdout_bad_argument_test.dart
deleted file mode 100644
index 24b2965..0000000
--- a/tests/standalone/io/stdout_bad_argument_test.dart
+++ /dev/null
@@ -1,13 +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.
-
-import "dart:io";
-
-main() {
-  stdout.add("Hello\n");
-  stdout.done.catchError((e) {
-    exit(0);
-  });
-  stdin.listen(print);
-}
diff --git a/tests/standalone/no_assert_test.dart b/tests/standalone/no_assert_test.dart
deleted file mode 100644
index 825578b..0000000
--- a/tests/standalone/no_assert_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-// VMOptions=--no-enable_asserts --enable_type_checks
-
-// Ensure that enabling of type checks does not automatically enable asserts.
-
-main() {
-  assert(false);
-  try {
-    int i = "String";
-    throw "FAIL";
-  } on TypeError catch (e) {
-    print("PASS");
-  }
-}
diff --git a/tests/standalone/priority_queue_stress_test.dart b/tests/standalone/priority_queue_stress_test.dart
deleted file mode 100644
index 43b3929..0000000
--- a/tests/standalone/priority_queue_stress_test.dart
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library priority_queue;
-
-import 'dart:collection';
-import 'dart:math';
-
-/**
- * A priority used for the priority queue. Subclasses only need to implement
- * the compareTo function.
- */
-abstract class Priority implements Comparable {
-  /**
-   * Return < 0 if other is bigger, >0 if other is smaller, 0 if they are equal.
-   */
-  int compareTo(Priority other);
-  bool operator <(Priority other) => compareTo(other) < 0;
-  bool operator >(Priority other) => compareTo(other) > 0;
-  bool operator ==(Priority other) => compareTo(other) == 0;
-}
-
-/**
- * Priority based on integers.
- */
-class IntPriority extends Priority {
-  int priority;
-  IntPriority(int this.priority);
-
-  int compareTo(IntPriority other) {
-    return priority - other.priority;
-  }
-
-  String toString() => "$priority";
-}
-
-/**
- * An element of a priority queue. The type is used restriction based
- * querying of the queues.
- */
-abstract class TypedElement<V> {
-  bool typeEquals(var other);
-}
-
-class StringTypedElement<V> extends TypedElement {
-  String type;
-  V value;
-  StringTypedElement(String this.type, V this.value);
-  bool typeEquals(String otherType) => otherType == type;
-  String toString() => "<Type: $type, Value: $value>";
-}
-
-/**
- * A priority node in a priority queue. A priority node contains all of the
- * values for a given priority in a given queue. It is part of a linked
- * list of nodes, with prev and next pointers.
- */
-class PriorityNode<N extends TypedElement, T extends Priority> {
-  T priority;
-  Queue<N> values;
-  PriorityNode prev;
-  PriorityNode next;
-  PriorityNode(N initialNode, T this.priority) : values = new Queue<N>() {
-    add(initialNode);
-  }
-
-  void add(N n) => values.add(n);
-
-  bool remove(N n) => values.remove(n);
-
-  N removeFirst() => values.removeFirst();
-
-  bool get isEmpty => values.isEmpty;
-
-  N get first => values.first;
-
-  String toString() => "Priority: $priority $values";
-}
-
-/**
- * A priority queue with a FIFO property for nodes with same priority.
- * The queue guarantees that nodes are returned in the same order they
- * are added for a given priority.
- * For type safety this queue is guarded by the elements being subclasses of
- * TypedElement - this is not strictly neccesary since we never actually
- * use the value or type of the nodes.
- */
-class PriorityQueue<N extends TypedElement, P extends Priority> {
-  PriorityNode<N, P> head;
-  int length = 0;
-
-  void add(N value, P priority) {
-    length++;
-    if (head == null) {
-      head = new PriorityNode<N, P>(value, priority);
-      return;
-    }
-    assert(head.next == null);
-    var node = head;
-    while (node.prev != null && node.priority > priority) {
-      node = node.prev;
-    }
-    if (node.priority == priority) {
-      node.add(value);
-    } else if (node.priority < priority) {
-      var newNode = new PriorityNode<N, P>(value, priority);
-      newNode.next = node.next;
-      if (node.next != null) node.next.prev = newNode;
-      newNode.prev = node;
-      node.next = newNode;
-      if (node == head) head = newNode;
-    } else {
-      var newNode = new PriorityNode<N, P>(value, priority);
-      node.prev = newNode;
-      newNode.next = node;
-    }
-  }
-
-  N get first => head.first;
-
-  Priority get firstPriority => head.priority;
-
-  bool get isEmpty => head == null;
-
-  N removeFirst() {
-    if (isEmpty) throw "Can't get element from empty queue";
-    var value = head.removeFirst();
-    if (head.isEmpty) {
-      if (head.prev != null) {
-        head.prev.next = null;
-      }
-      head = head.prev;
-    }
-    length--;
-    assert(head == null || head.next == null);
-    return value;
-  }
-
-  String toString() {
-    if (head == null) return "Empty priority queue";
-    var node = head;
-    var buffer = new StringBuffer();
-    while (node.prev != null) {
-      buffer.writeln(node);
-      node = node.prev;
-    }
-    buffer.writeln(node);
-    return buffer.toString();
-  }
-}
-
-/**
- * Implements a specialized priority queue that efficiently allows getting
- * the highest priorized node that adheres to a set of restrictions.
- * Most notably it allows to get the highest priority node where the node's
- * type is not in an exclude list.
- * In addition, the queue has a number of properties:
- *   The queue has fifo semantics for nodes with the same priority and type,
- *   i.e., if nodes a and b are added to the queue with priority x and type z
- *   then a is returned first iff a was added before b
- * For different types with the same priority no guarantees are given, but
- * the returned values try to be fair by returning from the biggest list of
- * tasks in case of priority clash. (This could be fixed by adding timestamps
- * to every node, that is _only_ used when collisions occur, not for
- * insertions)
- */
-class RestrictViewPriorityQueue<N extends TypedElement, P extends Priority> {
-  // We can't use the basic dart priority queue since it does not guarantee
-  // FIFO for items with the same order. This is currently not uptimized for
-  // different N, if many different N is expected here we should have a
-  // priority queue instead of a list.
-  List<PriorityQueue<N, P>> restrictedQueues = new List<PriorityQueue<N, P>>();
-  PriorityQueue<N, P> mainQueue = new PriorityQueue<N, P>();
-
-  void add(N value, P priority) {
-    for (var queue in restrictedQueues) {
-      if (queue.first.value == value) {
-        queue.add(value, priority);
-      }
-    }
-    mainQueue.add(value, priority);
-  }
-
-  bool get isEmpty => restrictedQueues.length + mainQueue.length == 0;
-
-  int get length =>
-      restrictedQueues.fold(0, (v, e) => v + e.length) + mainQueue.length;
-
-  PriorityQueue getRestricted(List<N> restrictions) {
-    var current = null;
-    // Find highest restricted priority.
-    for (var queue in restrictedQueues) {
-      if (!restrictions.any((e) => queue.head.first.typeEquals(e))) {
-        if (current == null || queue.firstPriority > current.firstPriority) {
-          current = queue;
-        } else if (current.firstPriority == queue.firstPriority) {
-          current = queue.length > current.length ? queue : current;
-        }
-      }
-    }
-    return current;
-  }
-
-  N get first {
-    if (isEmpty) throw "Trying to remove node from empty queue";
-    var candidate = getRestricted([]);
-    if (candidate != null &&
-        (mainQueue.isEmpty ||
-            mainQueue.firstPriority < candidate.firstPriority)) {
-      return candidate.first;
-    }
-    return mainQueue.isEmpty ? null : mainQueue.first;
-  }
-
-  /**
-   * Returns the node that under the given set of restrictions.
-   * If the queue is empty this function throws.
-   * If the queue is not empty, but no node exists that adheres to the
-   * restrictions we return null.
-   */
-  N removeFirst({List restrictions: const []}) {
-    if (isEmpty) throw "Trying to remove node from empty queue";
-    var candidate = getRestricted(restrictions);
-
-    if (candidate != null &&
-        (mainQueue.isEmpty ||
-            mainQueue.firstPriority < candidate.firstPriority)) {
-      var value = candidate.removeFirst();
-      if (candidate.isEmpty) restrictedQueues.remove(candidate);
-      return value;
-    }
-    while (!mainQueue.isEmpty) {
-      var currentPriority = mainQueue.firstPriority;
-      var current = mainQueue.removeFirst();
-      if (!restrictions.any((e) => current.typeEquals(e))) {
-        return current;
-      } else {
-        var restrictedQueue = restrictedQueues.firstWhere(
-            (e) => current.typeEquals(e.first.type),
-            orElse: () => null);
-        if (restrictedQueue == null) {
-          restrictedQueue = new PriorityQueue<N, P>();
-          restrictedQueues.add(restrictedQueue);
-        }
-        restrictedQueue.add(current, currentPriority);
-      }
-    }
-    return null;
-  }
-
-  String toString() {
-    if (isEmpty) return "Empty queue";
-    var buffer = new StringBuffer();
-    if (!restrictedQueues.isEmpty) {
-      buffer.writeln("Restricted queues");
-      for (var queue in restrictedQueues) {
-        buffer.writeln("$queue");
-      }
-    }
-    buffer.writeln("Main queue:");
-    buffer.writeln("$mainQueue");
-    return buffer.toString();
-  }
-}
-
-/// TEMPORARY TESTING AND PERFORMANCE
-void main([args]) {
-  stress(new RestrictViewPriorityQueue<StringTypedElement, IntPriority>());
-}
-
-void stress(queue) {
-  final int SIZE = 50000;
-  Random random = new Random(29);
-
-  var priorities = [1, 2, 3, 16, 32, 42, 56, 57, 59, 90];
-  var values = [
-    new StringTypedElement('safari', 'foo'),
-    new StringTypedElement('ie', 'bar'),
-    new StringTypedElement('ff', 'foobar'),
-    new StringTypedElement('dartium', 'barfoo'),
-    new StringTypedElement('chrome', 'hest'),
-    new StringTypedElement('drt', 'fisk')
-  ];
-
-  var restricted = ['safari', 'chrome'];
-
-  void addRandom() {
-    queue.add(values[random.nextInt(values.length)],
-        new IntPriority(priorities[random.nextInt(priorities.length)]));
-  }
-
-  var stopwatch = new Stopwatch()..start();
-  while (queue.length < SIZE) {
-    addRandom();
-  }
-
-  stopwatch.stop();
-  print("Adding took: ${stopwatch.elapsedMilliseconds}");
-  print("Queue length: ${queue.length}");
-
-  stopwatch = new Stopwatch()..start();
-  while (queue.length > 0) {
-    queue.removeFirst();
-  }
-  stopwatch.stop();
-  print("Remowing took: ${stopwatch.elapsedMilliseconds}");
-  print("Queue length: ${queue.length}");
-
-  print("Restricted add/remove");
-  while (queue.length < SIZE) {
-    addRandom();
-  }
-
-  for (int i = 0; i < SIZE; i++) {
-    if (random.nextDouble() < 0.5) {
-      queue.removeFirst(restrictions: restricted);
-    } else {
-      queue.removeFirst();
-    }
-    addRandom();
-  }
-}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
deleted file mode 100644
index ee1bf10..0000000
--- a/tests/standalone/standalone.status
+++ /dev/null
@@ -1,9 +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.
-# WARNING:
-# Tests using the multitest feature where failure is expected should *also* be
-# listed in tests/lib/analyzer/analyze_tests.status without the "standalone"
-# prefix.
-
-*: SkipByDesign # Deprecating Dart1 tests.
diff --git a/tests/standalone/verbose_gc_to_bmu_test.dart b/tests/standalone/verbose_gc_to_bmu_test.dart
deleted file mode 100644
index 884e139..0000000
--- a/tests/standalone/verbose_gc_to_bmu_test.dart
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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.
-
-// OtherResources=verbose_gc_to_bmu_script.dart
-
-// This test forks a second vm process that runs the BMU tool and verifies that
-// it produces some output. This test is mainly here to ensure that the BMU
-// tool compiles and runs.
-
-import "dart:async";
-import "dart:convert";
-import "dart:io";
-
-import "package:path/path.dart";
-
-// Tool script relative to the path of this test.
-var toolScript = Uri
-    .parse(Platform.executable)
-    .resolve("../../runtime/tools/verbose_gc_to_bmu.dart")
-    .toFilePath();
-
-// Target script relative to this test.
-var targetScript =
-    Platform.script.resolve("verbose_gc_to_bmu_script.dart").toFilePath();
-const minOutputLines = 20;
-
-void checkExitCode(targetResult) {
-  if (exitCode != 0) {
-    print("Process terminated with exit code ${exitCode}.");
-    exit(-1);
-  }
-}
-
-void main() {
-  // Compute paths for tool and target relative to the path of this script.
-  var targetResult =
-      Process.runSync(Platform.executable, ["--verbose_gc", targetScript]);
-  checkExitCode(targetResult);
-  var gcLog = targetResult.stderr;
-  Process.start(Platform.executable, [toolScript]).then((Process process) {
-    // Feed the GC log of the target to the BMU tool.
-    process.stdin.write(gcLog);
-    process.stdin.close();
-    var stdoutStringStream =
-        process.stdout.transform(utf8.decoder).transform(new LineSplitter());
-    var stderrStringStream =
-        process.stderr.transform(utf8.decoder).transform(new LineSplitter());
-    // Wait for 3 future events: stdout and stderr streams closed, and
-    // process terminated.
-    var futures = [];
-    var stdoutLines = [];
-    var stderrLines = [];
-    var subscription = stdoutStringStream.listen(stdoutLines.add);
-    futures.add(subscription.asFuture(true));
-    subscription = stderrStringStream.listen(stderrLines.add);
-    futures.add(subscription.asFuture(true));
-    futures.add(process.exitCode.then(checkExitCode));
-    Future.wait(futures).then((results) {
-      if (stderrLines.isNotEmpty) {
-        print("Unexpected output on stderr:");
-        print(stderrLines.join('\n'));
-        exit(-1);
-      }
-      if (stdoutLines.length < minOutputLines) {
-        print("Less than expected output on stdout:");
-        print(stdoutLines.join('\n'));
-        exit(-1);
-      }
-    });
-  });
-}
diff --git a/tests/standalone_2/app_snapshot_share_test.dart b/tests/standalone_2/app_snapshot_share_test.dart
deleted file mode 100644
index 27ef93d..0000000
--- a/tests/standalone_2/app_snapshot_share_test.dart
+++ /dev/null
@@ -1,95 +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 "dart:io";
-
-void main(List<String> args) {
-  if (args.contains("--child")) {
-    print("Hello, sharing world!");
-    return;
-  }
-
-  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
-    return; // Running in JIT or Windows: AOT binaries not available.
-  }
-
-  if (Platform.isAndroid) {
-    return; // SDK tree and dart_bootstrap not available on the test device.
-  }
-
-  var buildDir =
-      Platform.executable.substring(0, Platform.executable.lastIndexOf('/'));
-  var tempDir = Directory.systemTemp.createTempSync("app-shared");
-  var snapshot1Path = tempDir.uri.resolve("hello1.snapshot").toFilePath();
-  var snapshot2Path = tempDir.uri.resolve("hello2.snapshot").toFilePath();
-  var scriptPath = new Directory(buildDir)
-      .uri
-      .resolve("../../tests/standalone_2/app_snapshot_share_test.dart")
-      .toFilePath();
-  final scriptPathDill = tempDir.uri.resolve('app.dill').toFilePath();
-
-  try {
-    args = <String>[
-      '--aot',
-      '--platform=$buildDir/vm_platform_strong.dill',
-      '-o',
-      scriptPathDill,
-      scriptPath,
-    ];
-    runSync("pkg/vm/tool/gen_kernel${Platform.isWindows ? '.bat' : ''}", args);
-
-    args = <String>[
-      "--deterministic",
-      "--snapshot-kind=app-aot-blobs",
-      "--blobs_container_filename=$snapshot1Path",
-      scriptPathDill,
-    ];
-    runSync("$buildDir/gen_snapshot", args);
-
-    args = <String>[
-      "--deterministic",
-      "--snapshot-kind=app-aot-blobs",
-      "--blobs_container_filename=$snapshot2Path",
-      "--shared-blobs=$snapshot1Path",
-      scriptPathDill,
-    ];
-    runSync("$buildDir/gen_snapshot", args);
-
-    var sizeWithoutSharing = new File(snapshot1Path).statSync().size;
-    var deltaWhenSharing = new File(snapshot2Path).statSync().size;
-    print("sizeWithoutSharing: ${sizeWithoutSharing.toString().padLeft(8)}");
-    print("deltaWhenSharing:   ${deltaWhenSharing.toString().padLeft(8)}");
-    if (deltaWhenSharing >= sizeWithoutSharing) {
-      throw "Sharing did not shrink size";
-    }
-
-    args = <String>[
-      "--shared-blobs=$snapshot1Path",
-      snapshot2Path,
-      "--child",
-    ];
-    final result = runSync("$buildDir/dart_precompiled_runtime", args);
-    if (!result.stdout.contains("Hello, sharing world!")) {
-      throw "Missing output";
-    }
-  } finally {
-    tempDir.deleteSync(recursive: true);
-  }
-}
-
-ProcessResult runSync(String executable, List<String> args) {
-  print("+ $executable ${args.join(' ')}");
-
-  final result = Process.runSync(executable, args);
-  print("Exit code: ${result.exitCode}");
-  print("stdout:");
-  print(result.stdout);
-  print("stderr:");
-  print(result.stderr);
-
-  if (result.exitCode != 0) {
-    throw "Bad exit code";
-  }
-  return result;
-}
diff --git a/tests/standalone/io/disable_exit_test.dart b/tests/standalone_2/io/disable_exit_test.dart
similarity index 100%
rename from tests/standalone/io/disable_exit_test.dart
rename to tests/standalone_2/io/disable_exit_test.dart
diff --git a/tests/standalone/io/http_override_test.dart b/tests/standalone_2/io/http_override_test.dart
similarity index 100%
rename from tests/standalone/io/http_override_test.dart
rename to tests/standalone_2/io/http_override_test.dart
diff --git a/tests/standalone/io/https_bad_certificate_test.dart b/tests/standalone_2/io/https_bad_certificate_test.dart
similarity index 100%
rename from tests/standalone/io/https_bad_certificate_test.dart
rename to tests/standalone_2/io/https_bad_certificate_test.dart
diff --git a/tests/standalone_2/io/io_override_test.dart b/tests/standalone_2/io/io_override_test.dart
new file mode 100644
index 0000000..3ddb73d
--- /dev/null
+++ b/tests/standalone_2/io/io_override_test.dart
@@ -0,0 +1,251 @@
+// 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 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import "package:expect/expect.dart";
+
+class DirectoryMock extends FileSystemEntity implements Directory {
+  final String path = "/mockdir";
+
+  DirectoryMock(String path);
+
+  static DirectoryMock createDirectory(String path) => new DirectoryMock(path);
+  static DirectoryMock getCurrent() => new DirectoryMock(null);
+  static void setCurrent(String path) {}
+  static DirectoryMock getSystemTemp() => new DirectoryMock(null);
+
+  Uri get uri => null;
+  Future<Directory> create({bool recursive: false}) => null;
+  void createSync({bool recursive: false}) {}
+  Future<Directory> createTemp([String prefix]) => null;
+  Directory createTempSync([String prefix]) => null;
+  Future<bool> exists() => null;
+  bool existsSync() => false;
+  Future<String> resolveSymbolicLinks() => null;
+  String resolveSymbolicLinksSync() => null;
+  Future<Directory> rename(String newPath) => null;
+  Directory renameSync(String newPath) => null;
+  Directory get absolute => null;
+  Stream<FileSystemEntity> list(
+          {bool recursive: false, bool followLinks: true}) =>
+      null;
+  List<FileSystemEntity> listSync(
+          {bool recursive: false, bool followLinks: true}) =>
+      null;
+}
+
+class FileMock extends FileSystemEntity implements File {
+  String get path => "/mockfile";
+
+  FileMock(String path);
+
+  static FileMock createFile(String path) => new FileMock(path);
+
+  Future<File> create({bool recursive: false}) => null;
+  void createSync({bool recursive: false}) {}
+  Future<File> rename(String newPath) => null;
+  File renameSync(String newPath) => null;
+  Future<File> copy(String newPath) => null;
+  File copySync(String newPath) => null;
+  Future<bool> exists() => null;
+  bool existsSync() => false;
+  Future<int> length() => null;
+  int lengthSync() => null;
+  File get absolute => null;
+  Future<DateTime> lastAccessed() => null;
+  DateTime lastAccessedSync() => null;
+  Future setLastAccessed(DateTime time) => null;
+  void setLastAccessedSync(DateTime time) {}
+  Future<DateTime> lastModified() => null;
+  DateTime lastModifiedSync() => null;
+  Future setLastModified(DateTime time) => null;
+  void setLastModifiedSync(DateTime time) {}
+  Future<RandomAccessFile> open({FileMode mode: FileMode.read}) => null;
+  RandomAccessFile openSync({FileMode mode: FileMode.read}) => null;
+  Stream<List<int>> openRead([int start, int end]) => null;
+  IOSink openWrite({FileMode mode: FileMode.write, Encoding encoding: utf8}) =>
+      null;
+  Future<Uint8List> readAsBytes() => null;
+  Uint8List readAsBytesSync() => null;
+  Future<String> readAsString({Encoding encoding: utf8}) => null;
+  String readAsStringSync({Encoding encoding: utf8}) => null;
+  Future<List<String>> readAsLines({Encoding encoding: utf8}) => null;
+  List<String> readAsLinesSync({Encoding encoding: utf8}) => null;
+  Future<File> writeAsBytes(List<int> bytes,
+          {FileMode mode: FileMode.write, bool flush: false}) =>
+      null;
+  void writeAsBytesSync(List<int> bytes,
+      {FileMode mode: FileMode.write, bool flush: false}) {}
+  Future<File> writeAsString(String contents,
+          {FileMode mode: FileMode.write,
+          Encoding encoding: utf8,
+          bool flush: false}) =>
+      null;
+  void writeAsStringSync(String contents,
+      {FileMode mode: FileMode.write,
+      Encoding encoding: utf8,
+      bool flush: false}) {}
+}
+
+class FileStatMock implements FileStat {
+  final DateTime changed = null;
+  final DateTime modified = null;
+  final DateTime accessed = null;
+  final FileSystemEntityType type = null;
+  final int mode = null;
+  final int size = null;
+
+  FileStatMock();
+
+  static Future<FileStat> stat(String path) {
+    return new Future.value(new FileStatMock());
+  }
+
+  static FileStat statSync(String path) => new FileStatMock();
+
+  String modeString() => null;
+}
+
+class FileSystemEntityMock {
+  static Future<bool> identical(String path1, String path2) {
+    return new Future.value(false);
+  }
+
+  static bool identicalSync(String path1, String path2) => false;
+
+  static Future<FileSystemEntityType> getType(String path, bool followLinks) {
+    return new Future.value(FileSystemEntityType.file);
+  }
+
+  static FileSystemEntityType getTypeSync(String path, bool followLinks) {
+    return FileSystemEntityType.file;
+  }
+}
+
+class FileSystemWatcherMock {
+  static Stream<FileSystemEvent> watch(
+      String path, int events, bool recursive) {
+    return null;
+  }
+
+  static bool watchSupported() => false;
+}
+
+class LinkMock extends FileSystemEntity implements Link {
+  String get path => "/mocklink";
+
+  LinkMock(String path);
+
+  static Link createLink(String path) => new LinkMock(path);
+
+  Future<Link> create(String target, {bool recursive: false}) => null;
+  void createSync(String target, {bool recursive: false}) {}
+  void updateSync(String target) {}
+  Future<Link> update(String target) => null;
+  Future<bool> exists() => null;
+  bool existsSync() => false;
+  Future<String> resolveSymbolicLinks() => null;
+  String resolveSymbolicLinksSync() => null;
+  Future<Link> rename(String newPath) => null;
+  Link renameSync(String newPath) => null;
+  Link get absolute => null;
+  Future<String> target() => null;
+  String targetSync() => null;
+}
+
+Future<Socket> socketConnect(host, int port,
+    {sourceAddress, Duration timeout}) {
+  return null;
+}
+
+Future<ConnectionTask<Socket>> socketStartConnect(host, int port,
+    {sourceAddress}) {
+  return null;
+}
+
+Future<ServerSocket> serverSocketBind(address, int port,
+    {int backlog: 0, bool v6Only: false, bool shared: false}) {
+  return null;
+}
+
+Future<Null> ioOverridesRunTest() async {
+  Future<Null> f = IOOverrides.runZoned(
+    () async {
+      Expect.isTrue(new Directory("directory") is DirectoryMock);
+      Expect.isTrue(Directory.current is DirectoryMock);
+      Expect.isTrue(Directory.systemTemp is DirectoryMock);
+      Expect.isTrue(new File("file") is FileMock);
+      Expect.isTrue(await FileStat.stat("file") is FileStatMock);
+      Expect.isTrue(FileStat.statSync("file") is FileStatMock);
+      Expect.isFalse(await FileSystemEntity.identical("file", "file"));
+      Expect.isFalse(FileSystemEntity.identicalSync("file", "file"));
+      Expect.equals(
+          await FileSystemEntity.type("file"), FileSystemEntityType.file);
+      Expect.equals(
+          FileSystemEntity.typeSync("file"), FileSystemEntityType.file);
+      Expect.isFalse(FileSystemEntity.isWatchSupported);
+      Expect.isNull(new Directory("directory").watch());
+      Expect.isTrue(new Link("link") is LinkMock);
+      Expect.isNull(Socket.connect(null, 0));
+      Expect.isNull(Socket.startConnect(null, 0));
+      Expect.isNull(ServerSocket.bind(null, 0));
+    },
+    createDirectory: DirectoryMock.createDirectory,
+    getCurrentDirectory: DirectoryMock.getCurrent,
+    setCurrentDirectory: DirectoryMock.setCurrent,
+    getSystemTempDirectory: DirectoryMock.getSystemTemp,
+    createFile: FileMock.createFile,
+    stat: FileStatMock.stat,
+    statSync: FileStatMock.statSync,
+    fseIdentical: FileSystemEntityMock.identical,
+    fseIdenticalSync: FileSystemEntityMock.identicalSync,
+    fseGetType: FileSystemEntityMock.getType,
+    fseGetTypeSync: FileSystemEntityMock.getTypeSync,
+    fsWatch: FileSystemWatcherMock.watch,
+    fsWatchIsSupported: FileSystemWatcherMock.watchSupported,
+    createLink: LinkMock.createLink,
+    socketConnect: socketConnect,
+    socketStartConnect: socketStartConnect,
+    serverSocketBind: serverSocketBind,
+  );
+  Expect.isFalse(new Directory("directory") is DirectoryMock);
+  Expect.isTrue(new Directory("directory") is Directory);
+  await f;
+}
+
+class MyIOOverrides extends IOOverrides {
+  Directory createDirectory(String path) => DirectoryMock.createDirectory(path);
+}
+
+globalIOOverridesTest() {
+  IOOverrides.global = new MyIOOverrides();
+  Expect.isTrue(new Directory("directory") is DirectoryMock);
+  IOOverrides.global = null;
+  Directory dir = new Directory("directory");
+  Expect.isTrue(dir is! DirectoryMock);
+  Expect.isTrue(dir is Directory);
+}
+
+globalIOOverridesZoneTest() {
+  IOOverrides.global = new MyIOOverrides();
+  runZoned(() {
+    runZoned(() {
+      Expect.isTrue(new Directory("directory") is DirectoryMock);
+    });
+  });
+  IOOverrides.global = null;
+  Directory dir = new Directory("directory");
+  Expect.isTrue(dir is! DirectoryMock);
+  Expect.isTrue(dir is Directory);
+}
+
+main() async {
+  await ioOverridesRunTest();
+  globalIOOverridesTest();
+  globalIOOverridesZoneTest();
+}
diff --git a/tests/standalone_2/io/link_test.dart b/tests/standalone_2/io/link_test.dart
index 477d7b5..3e36111 100644
--- a/tests/standalone_2/io/link_test.dart
+++ b/tests/standalone_2/io/link_test.dart
@@ -275,10 +275,50 @@
   tempDirectory.deleteSync(recursive: true);
 }
 
+testIsDir() async {
+  // Only run on Platforms that supports file watcher
+  if (!Platform.isWindows && !Platform.isLinux && !Platform.isMacOS) return;
+  Directory sandbox = Directory.systemTemp.createTempSync();
+  Directory dir = new Directory(sandbox.path + Platform.pathSeparator + "dir");
+  dir.createSync();
+  File target = new File(sandbox.path + Platform.pathSeparator + "target");
+  target.createSync();
+
+  var eventCompleter = new Completer<FileSystemEvent>();
+  var subscription;
+  // Check for link pointing to file
+  subscription = dir.watch().listen((FileSystemEvent event) {
+    if (event.path.endsWith('link')) {
+      eventCompleter.complete(event);
+      subscription.cancel();
+    }
+  });
+  Link link = new Link(dir.path + Platform.pathSeparator + "link");
+  link.createSync(target.path);
+  var event = await eventCompleter.future;
+  Expect.isFalse(event.isDirectory);
+
+  // Check for link pointing to directory
+  eventCompleter = new Completer<FileSystemEvent>();
+  subscription = dir.watch().listen((FileSystemEvent event) {
+    if (event.path.endsWith('link2')) {
+      eventCompleter.complete(event);
+      subscription.cancel();
+    }
+  });
+  link = new Link(dir.path + Platform.pathSeparator + "link2");
+  link.createSync(dir.path);
+  event = await eventCompleter.future;
+  Expect.isFalse(event.isDirectory);
+
+  sandbox.deleteSync(recursive: true);
+}
+
 main() {
   testCreateSync();
   testCreateLoopingLink();
   testRenameSync();
   testLinkErrorSync();
   testRelativeLinksSync();
+  testIsDir();
 }
diff --git a/tests/standalone_2/io/raw_secure_server_socket_test.dart b/tests/standalone_2/io/raw_secure_server_socket_test.dart
new file mode 100644
index 0000000..51afb74
--- /dev/null
+++ b/tests/standalone_2/io/raw_secure_server_socket_test.dart
@@ -0,0 +1,668 @@
+// 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.
+//
+// VMOptions=
+// VMOptions=--short_socket_read
+// VMOptions=--short_socket_write
+// VMOptions=--short_socket_read --short_socket_write
+// OtherResources=certificates/server_chain.pem
+// OtherResources=certificates/server_key.pem
+// OtherResources=certificates/trusted_certs.pem
+// OtherResources=certificates/untrusted_server_chain.pem
+// OtherResources=certificates/untrusted_server_key.pem
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+InternetAddress HOST;
+String localFile(path) => Platform.script.resolve(path).toFilePath();
+
+SecurityContext serverContext = new SecurityContext()
+  ..useCertificateChain(localFile('certificates/server_chain.pem'))
+  ..usePrivateKey(localFile('certificates/server_key.pem'),
+      password: 'dartdart');
+
+SecurityContext clientContext = new SecurityContext()
+  ..setTrustedCertificates(localFile('certificates/trusted_certs.pem'));
+
+void testSimpleBind() {
+  print("asyncStart testSimpleBind");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    Expect.isTrue(s.port > 0);
+    s.close();
+    print("asyncEnd testSimpleBind");
+    asyncEnd();
+  });
+}
+
+void testInvalidBind() {
+  int count = 0;
+
+  // Bind to a unknown DNS name.
+  asyncStart();
+  print("asyncStart testInvalidBind");
+  RawSecureServerSocket.bind("ko.faar.__hest__", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    print("asyncEnd testInvalidBind");
+    asyncEnd();
+  });
+
+  // Bind to an unavaliable IP-address.
+  asyncStart();
+  print("asyncStart testInvalidBind 2");
+  RawSecureServerSocket.bind("8.8.8.8", 0, serverContext).then((_) {
+    Expect.fail("Failure expected");
+  }).catchError((error) {
+    Expect.isTrue(error is SocketException);
+    print("asyncEnd testInvalidBind 2");
+    asyncEnd();
+  });
+
+  // Bind to a port already in use.
+  asyncStart();
+  print("asyncStart testInvalidBind 3");
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((s) {
+    RawSecureServerSocket.bind(HOST, s.port, serverContext).then((t) {
+      s.close();
+      t.close();
+      Expect.fail("Multiple listens on same port");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException);
+      s.close();
+      print("asyncEnd testInvalidBind 3");
+      asyncEnd();
+    });
+  });
+}
+
+void testSimpleConnect() {
+  print("asyncStart testSimpleConnect");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext);
+    server.listen((serverEnd) {
+      clientEndFuture.then((clientEnd) {
+        // TODO(whesse): Shutdown(SEND) not supported on secure sockets.
+        clientEnd.shutdown(SocketDirection.send);
+        serverEnd.shutdown(SocketDirection.send);
+        server.close();
+        print("asyncEnd testSimpleConnect");
+        asyncEnd();
+      });
+    });
+  });
+}
+
+int debugTestSimpleConnectFailCounter = 0;
+void testSimpleConnectFail(SecurityContext context, bool cancelOnError) {
+  var counter = debugTestSimpleConnectFailCounter++;
+  print("asyncStart testSimpleConnectFail $counter");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, context).then((server) {
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext)
+            .then((clientEnd) {
+      Expect.fail("No client connection expected.");
+    }).catchError((error) {
+      Expect.isTrue(error is SocketException || error is HandshakeException);
+    });
+    server.listen((serverEnd) {
+      Expect.fail("No server connection expected.");
+    }, onError: (error) {
+      Expect.isTrue(error is SocketException || error is HandshakeException);
+      clientEndFuture.then((_) {
+        if (!cancelOnError) server.close();
+        print("asyncEnd testSimpleConnectFail $counter");
+        asyncEnd();
+      });
+    }, cancelOnError: cancelOnError);
+  });
+}
+
+void testServerListenAfterConnect() {
+  print("asyncStart testServerListenAfterConnect");
+  asyncStart();
+  RawSecureServerSocket.bind(HOST, 0, serverContext).then((server) {
+    Expect.isTrue(server.port > 0);
+    var clientEndFuture =
+        RawSecureSocket.connect(HOST, server.port, context: clientContext);
+    new Timer(const Duration(milliseconds: 500), () {
+      server.listen((serverEnd) {
+        clientEndFuture.then((clientEnd) {
+          clientEnd.shutdown(SocketDirection.send);
+          serverEnd.shutdown(SocketDirection.send);
+          server.close();
+          print("asyncEnd testServerListenAfterConnect");
+          asyncEnd();
+        });
+      });
+    });
+  });
+}
+
+// This test creates a server and a client connects. The client then
+// writes and the server echos. When the server has finished its echo
+// it half-closes. When the client gets the close event is closes
+// fully.
+//
+// The test can be run in different configurations based on
+// the boolean arguments:
+//
+// listenSecure
+// When this argument is true a secure server is used. When this is false
+// a non-secure server is used and the connections are secured after being
+// connected.
+//
+// connectSecure
+// When this argument is true a secure client connection is used. When this
+// is false a non-secure client connection is used and the connection is
+// secured after being connected.
+//
+// handshakeBeforeSecure
+// When this argument is true some initial clear text handshake is done
+// between client and server before the connection is secured. This argument
+// only makes sense when both listenSecure and connectSecure are false.
+//
+// postponeSecure
+// When this argument is false the securing of the server end will
+// happen as soon as the last byte of the handshake before securing
+// has been written. When this argument is true the securing of the
+// server will not happen until the first TLS handshake data has been
+// received from the client. This argument only takes effect when
+// handshakeBeforeSecure is true.
+void testSimpleReadWrite(
+    {bool listenSecure,
+    bool connectSecure,
+    bool handshakeBeforeSecure,
+    bool postponeSecure,
+    bool dropReads}) {
+  int clientReads = 0;
+  int serverReads = 0;
+  if (handshakeBeforeSecure == true &&
+      (listenSecure == true || connectSecure == true)) {
+    Expect.fail("Invalid arguments to testSimpleReadWrite");
+  }
+
+  print("asyncStart testSimpleReadWrite($listenSecure, $connectSecure, "
+      "$handshakeBeforeSecure, $postponeSecure, $dropReads");
+  asyncStart();
+
+  const messageSize = 1000;
+  const handshakeMessageSize = 100;
+
+  List<int> createTestData() {
+    List<int> data = new List<int>(messageSize);
+    for (int i = 0; i < messageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  List<int> createHandshakeTestData() {
+    List<int> data = new List<int>(handshakeMessageSize);
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      data[i] = i & 0xff;
+    }
+    return data;
+  }
+
+  void verifyTestData(List<int> data) {
+    Expect.equals(messageSize, data.length);
+    List<int> expected = createTestData();
+    for (int i = 0; i < messageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  void verifyHandshakeTestData(List<int> data) {
+    Expect.equals(handshakeMessageSize, data.length);
+    List<int> expected = createHandshakeTestData();
+    for (int i = 0; i < handshakeMessageSize; i++) {
+      Expect.equals(expected[i], data[i]);
+    }
+  }
+
+  Future runServer(RawSocket client) {
+    var completer = new Completer();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> data = new List<int>(messageSize);
+    client.writeEventsEnabled = false;
+    var subscription;
+    subscription = client.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (dropReads) {
+            if (serverReads != 10) {
+              ++serverReads;
+              break;
+            } else {
+              serverReads = 0;
+            }
+          }
+          Expect.isTrue(bytesWritten == 0);
+          Expect.isTrue(client.available() > 0);
+          var buffer = client.read();
+          if (buffer != null) {
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            for (var value in buffer) {
+              Expect.isTrue(value is int);
+              Expect.isTrue(value < 256 && value >= 0);
+            }
+          }
+          if (bytesRead == data.length) {
+            verifyTestData(data);
+            client.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isFalse(client.writeEventsEnabled);
+          Expect.equals(bytesRead, data.length);
+          for (int i = bytesWritten; i < data.length; ++i) {
+            Expect.isTrue(data[i] is int);
+            Expect.isTrue(data[i] < 256 && data[i] >= 0);
+          }
+          bytesWritten +=
+              client.write(data, bytesWritten, data.length - bytesWritten);
+          if (bytesWritten < data.length) {
+            client.writeEventsEnabled = true;
+          }
+          if (bytesWritten == data.length) {
+            client.shutdown(SocketDirection.send);
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          completer.complete(null);
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<RawSocket> runClient(RawSocket socket) {
+    var completer = new Completer<RawSocket>();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> dataSent = createTestData();
+    List<int> dataReceived = new List<int>(dataSent.length);
+    socket.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          Expect.isTrue(socket.available() > 0);
+          if (dropReads) {
+            if (clientReads != 10) {
+              ++clientReads;
+              break;
+            } else {
+              clientReads = 0;
+            }
+          }
+          var buffer = socket.read();
+          if (buffer != null) {
+            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isTrue(bytesRead == 0);
+          Expect.isFalse(socket.writeEventsEnabled);
+          bytesWritten += socket.write(
+              dataSent, bytesWritten, dataSent.length - bytesWritten);
+          if (bytesWritten < dataSent.length) {
+            socket.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          verifyTestData(dataReceived);
+          completer.complete(socket);
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future runServerHandshake(RawSocket client) {
+    var completer = new Completer();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> data = new List<int>(handshakeMessageSize);
+    client.writeEventsEnabled = false;
+    var subscription;
+    subscription = client.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (bytesRead < data.length) {
+            Expect.isTrue(bytesWritten == 0);
+          }
+          Expect.isTrue(client.available() > 0);
+          if (dropReads) {
+            if (serverReads != 10) {
+              ++serverReads;
+              break;
+            } else {
+              serverReads = 0;
+            }
+          }
+          var buffer = client.read();
+          if (buffer != null) {
+            if (bytesRead == data.length) {
+              // Read first part of TLS handshake from client.
+              Expect.isTrue(postponeSecure);
+              completer.complete([subscription, buffer]);
+              client.readEventsEnabled = false;
+              return;
+            }
+            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            for (var value in buffer) {
+              Expect.isTrue(value is int);
+              Expect.isTrue(value < 256 && value >= 0);
+            }
+          }
+          if (bytesRead == data.length) {
+            verifyHandshakeTestData(data);
+            client.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isFalse(client.writeEventsEnabled);
+          Expect.equals(bytesRead, data.length);
+          for (int i = bytesWritten; i < data.length; ++i) {
+            Expect.isTrue(data[i] is int);
+            Expect.isTrue(data[i] < 256 && data[i] >= 0);
+          }
+          bytesWritten +=
+              client.write(data, bytesWritten, data.length - bytesWritten);
+          if (bytesWritten < data.length) {
+            client.writeEventsEnabled = true;
+          }
+          if (bytesWritten == data.length) {
+            if (!postponeSecure) {
+              completer.complete([subscription, null]);
+            }
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          Expect.fail("Unexpected close");
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<StreamSubscription<RawSocketEvent>> runClientHandshake(
+      RawSocket socket) {
+    var completer = new Completer<StreamSubscription<RawSocketEvent>>();
+    int bytesRead = 0;
+    int bytesWritten = 0;
+    List<int> dataSent = createHandshakeTestData();
+    List<int> dataReceived = new List<int>(dataSent.length);
+    var subscription;
+    subscription = socket.listen((event) {
+      switch (event) {
+        case RawSocketEvent.read:
+          if (dropReads) {
+            if (clientReads != 10) {
+              ++clientReads;
+              break;
+            } else {
+              clientReads = 0;
+            }
+          }
+          Expect.isTrue(socket.available() > 0);
+          var buffer = socket.read();
+          if (buffer != null) {
+            dataReceived.setRange(bytesRead, bytesRead + buffer.length, buffer);
+            bytesRead += buffer.length;
+            if (bytesRead == dataSent.length) {
+              verifyHandshakeTestData(dataReceived);
+              completer.complete(subscription);
+            }
+          }
+          break;
+        case RawSocketEvent.write:
+          Expect.isTrue(bytesRead == 0);
+          Expect.isFalse(socket.writeEventsEnabled);
+          bytesWritten += socket.write(
+              dataSent, bytesWritten, dataSent.length - bytesWritten);
+          if (bytesWritten < dataSent.length) {
+            socket.writeEventsEnabled = true;
+          }
+          break;
+        case RawSocketEvent.readClosed:
+          Expect.fail("Unexpected close");
+          break;
+        default:
+          throw "Unexpected event $event";
+      }
+    });
+    return completer.future;
+  }
+
+  Future<RawSecureSocket> connectClient(int port) {
+    if (connectSecure) {
+      return RawSecureSocket.connect(HOST, port, context: clientContext);
+    } else if (!handshakeBeforeSecure) {
+      return RawSocket.connect(HOST, port).then((socket) {
+        return RawSecureSocket.secure(socket, context: clientContext);
+      });
+    } else {
+      return RawSocket.connect(HOST, port).then((socket) {
+        return runClientHandshake(socket).then((subscription) {
+          return RawSecureSocket.secure(socket,
+              context: clientContext, subscription: subscription);
+        });
+      });
+    }
+  }
+
+  serverReady(server) {
+    server.listen((client) {
+      if (listenSecure) {
+        runServer(client).then((_) => server.close());
+      } else if (!handshakeBeforeSecure) {
+        RawSecureSocket.secureServer(client, serverContext).then((client) {
+          runServer(client).then((_) => server.close());
+        });
+      } else {
+        runServerHandshake(client).then((secure) {
+          RawSecureSocket.secureServer(client, serverContext,
+                  subscription: secure[0], bufferedData: secure[1])
+              .then((client) {
+            runServer(client).then((_) => server.close());
+          });
+        });
+      }
+    });
+
+    connectClient(server.port).then(runClient).then((socket) {
+      socket.close();
+      print("asyncEnd testSimpleReadWrite($listenSecure, $connectSecure, "
+          "$handshakeBeforeSecure, $postponeSecure, $dropReads");
+      asyncEnd();
+    });
+  }
+
+  if (listenSecure) {
+    RawSecureServerSocket.bind(HOST, 0, serverContext).then(serverReady);
+  } else {
+    RawServerSocket.bind(HOST, 0).then(serverReady);
+  }
+}
+
+testPausedSecuringSubscription(bool pausedServer, bool pausedClient) {
+  print(
+      "asyncStart testPausedSecuringSubscription $pausedServer $pausedClient");
+  asyncStart();
+  var clientComplete = new Completer();
+  RawServerSocket.bind(HOST, 0).then((server) {
+    server.listen((client) {
+      var subscription;
+      subscription = client.listen((_) {
+        if (pausedServer) {
+          subscription.pause();
+        }
+        void done() {
+          server.close();
+          clientComplete.future.then((_) {
+            client.close();
+            print("asyncEnd testPausedSecuringSubscription "
+                "$pausedServer $pausedClient");
+            asyncEnd();
+          });
+        }
+
+        try {
+          RawSecureSocket.secureServer(client, serverContext,
+                  subscription: subscription)
+              .catchError((_) {})
+              .whenComplete(() {
+            if (pausedServer) {
+              Expect.fail("secureServer succeeded with paused subscription");
+            }
+            done();
+          });
+        } catch (e) {
+          if (!pausedServer) {
+            Expect.fail("secureServer failed with non-paused subscriptions");
+          }
+          if (pausedServer) {
+            Expect.isTrue(e is ArgumentError);
+          }
+          done();
+        }
+      });
+    });
+
+    RawSocket.connect(HOST, server.port).then((socket) {
+      var subscription;
+      subscription = socket.listen((_) {
+        if (pausedClient) {
+          subscription.pause();
+        }
+        try {
+          RawSecureSocket.secure(socket, subscription: subscription)
+              .catchError((_) {})
+              .whenComplete(() {
+            if (pausedClient) {
+              Expect.fail("secure succeeded with paused subscription");
+            }
+            socket.close();
+            clientComplete.complete(null);
+          });
+        } catch (e) {
+          if (!pausedClient) {
+            Expect.fail("secure failed with non-paused subscriptions ($e)");
+          }
+          if (pausedClient) {
+            Expect.isTrue(e is ArgumentError);
+          }
+          clientComplete.complete(null);
+        }
+      });
+    });
+  });
+}
+
+main() {
+  print("asyncStart main");
+  asyncStart();
+  InternetAddress.lookup("localhost").then((hosts) {
+    HOST = hosts.first;
+    runTests();
+    print("asyncEnd main");
+    asyncEnd();
+  });
+}
+
+runTests() {
+  testSimpleBind();
+  testInvalidBind();
+  testSimpleConnect();
+  SecurityContext context = new SecurityContext();
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  var chain = Platform.script
+      .resolve('certificates/untrusted_server_chain.pem')
+      .toFilePath();
+  context.useCertificateChain(chain);
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  var key = Platform.script
+      .resolve('certificates/untrusted_server_key.pem')
+      .toFilePath();
+  context.usePrivateKey(key, password: 'dartdart');
+  testSimpleConnectFail(context, false);
+  testSimpleConnectFail(context, true);
+  testServerListenAfterConnect();
+
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: false,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: true,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: false,
+      dropReads: false);
+  testSimpleReadWrite(
+      listenSecure: true,
+      connectSecure: true,
+      handshakeBeforeSecure: false,
+      postponeSecure: false,
+      dropReads: true);
+  testSimpleReadWrite(
+      listenSecure: false,
+      connectSecure: false,
+      handshakeBeforeSecure: true,
+      postponeSecure: true,
+      dropReads: true);
+  testPausedSecuringSubscription(false, false);
+  testPausedSecuringSubscription(true, false);
+  testPausedSecuringSubscription(false, true);
+  testPausedSecuringSubscription(true, true);
+}
diff --git a/tests/standalone/io/sleep_test.dart b/tests/standalone_2/io/sleep_test.dart
similarity index 100%
rename from tests/standalone/io/sleep_test.dart
rename to tests/standalone_2/io/sleep_test.dart
diff --git a/tests/standalone_2/io/socket_invalid_arguments_test.dart b/tests/standalone_2/io/socket_invalid_arguments_test.dart
new file mode 100644
index 0000000..3e8b889
--- /dev/null
+++ b/tests/standalone_2/io/socket_invalid_arguments_test.dart
@@ -0,0 +1,84 @@
+// 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.
+
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+import "package:expect/expect.dart";
+
+class NotAnInteger {
+  operator ==(other) => other == 1;
+  operator <(other) => other > 1;
+  operator +(other) => 1;
+}
+
+testSocketCreation(host, port) {
+  asyncStart();
+  try {
+    Socket.connect(host, port)
+        .then((socket) => Expect.fail("Shouldn't get connected"))
+        .catchError((e) {
+      Expect.isTrue(e is ArgumentError || e is SocketException);
+      asyncEnd();
+    });
+  } catch (e) {
+    Expect.isTrue(e is ArgumentError || e is SocketException);
+    asyncEnd();
+  }
+}
+
+testAdd(buffer) {
+  asyncStart();
+  asyncStart();
+  ServerSocket.bind("127.0.0.1", 0).then((server) {
+    server.listen((socket) => socket.destroy());
+    Socket.connect("127.0.0.1", server.port).then((socket) {
+      int errors = 0;
+      socket.done.catchError((e) {
+        errors++;
+      }).then((_) {
+        Expect.equals(1, errors);
+        asyncEnd();
+        server.close();
+      });
+      socket.listen((_) {}, onError: (error) {
+        Expect.fail("Error on stream");
+      }, onDone: () {
+        asyncEnd();
+      });
+      socket.add(buffer);
+    });
+  });
+}
+
+testServerSocketCreation(address, port, backlog) {
+  asyncStart();
+  var server;
+  try {
+    ServerSocket.bind(address, port, backlog: backlog).then((_) {
+      Expect.fail("ServerSocket bound");
+    }).catchError((e) => asyncEnd());
+  } catch (e) {
+    asyncEnd();
+  }
+}
+
+main() {
+  asyncStart();
+  testSocketCreation("string", null);
+  testSocketCreation(null, null);
+  testSocketCreation("localhost", -1);
+  testSocketCreation("localhost", 65536);
+  testAdd(null);
+  // TODO(8233): Throw ArgumentError from API implementation.
+  // testAdd([-1]);
+  // testAdd([2222222222222222222222222222222]);
+  // testAdd([1, 2, 3, null]);
+  // testAdd([new NotAnInteger()]);
+  testServerSocketCreation("string", null, null);
+  testServerSocketCreation("string", 123, null);
+  testServerSocketCreation("localhost", -1, 123);
+  testServerSocketCreation("localhost", 65536, 123);
+  asyncEnd();
+}
diff --git a/tests/standalone_2/io/test_extension_test.dart b/tests/standalone_2/io/test_extension_test.dart
index aa6a1c9..e69ae28 100644
--- a/tests/standalone_2/io/test_extension_test.dart
+++ b/tests/standalone_2/io/test_extension_test.dart
@@ -46,8 +46,6 @@
 String getArchFromBuildDir(String buildDirectory) {
   if (buildDirectory.endsWith('SIMARM')) return '';
   if (buildDirectory.endsWith('SIMARM64')) return '';
-  if (buildDirectory.endsWith('SIMDBC')) return '';
-  if (buildDirectory.endsWith('SIMDBC64')) return '';
   if (buildDirectory.endsWith('ARM')) return '-arm';
   if (buildDirectory.endsWith('ARM64')) return '-arm64';
   if (buildDirectory.endsWith('IA32')) return '-ia32';
diff --git a/tests/standalone_2/priority_queue_stress_test.dart b/tests/standalone_2/priority_queue_stress_test.dart
new file mode 100644
index 0000000..76119b7
--- /dev/null
+++ b/tests/standalone_2/priority_queue_stress_test.dart
@@ -0,0 +1,323 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library priority_queue;
+
+import 'dart:collection';
+import 'dart:math';
+
+/**
+ * A priority used for the priority queue. Subclasses only need to implement
+ * the compareTo function.
+ */
+abstract class Priority implements Comparable {
+  /**
+   * Return < 0 if other is bigger, >0 if other is smaller, 0 if they are equal.
+   */
+  int compareTo(dynamic other);
+  bool operator <(dynamic other) => compareTo(other) < 0;
+  bool operator >(dynamic other) => compareTo(other) > 0;
+  bool operator ==(dynamic other) => compareTo(other) == 0;
+}
+
+/**
+ * Priority based on integers.
+ */
+class IntPriority extends Priority {
+  int priority;
+  IntPriority(int this.priority);
+
+  int compareTo(dynamic other) {
+    return priority - other.priority;
+  }
+
+  String toString() => "$priority";
+}
+
+/**
+ * An element of a priority queue. The type is used restriction based
+ * querying of the queues.
+ */
+abstract class TypedElement<V> {
+  bool typeEquals(var other);
+}
+
+class StringTypedElement<V> extends TypedElement {
+  String type;
+  V value;
+  StringTypedElement(String this.type, V this.value);
+  bool typeEquals(dynamic otherType) => otherType == type;
+  String toString() => "<Type: $type, Value: $value>";
+}
+
+/**
+ * A priority node in a priority queue. A priority node contains all of the
+ * values for a given priority in a given queue. It is part of a linked
+ * list of nodes, with prev and next pointers.
+ */
+class PriorityNode<N extends TypedElement, T extends Priority> {
+  T priority;
+  Queue<N> values;
+  PriorityNode prev;
+  PriorityNode next;
+  PriorityNode(N initialNode, T this.priority) : values = new Queue<N>() {
+    add(initialNode);
+  }
+
+  void add(N n) => values.add(n);
+
+  bool remove(N n) => values.remove(n);
+
+  N removeFirst() => values.removeFirst();
+
+  bool get isEmpty => values.isEmpty;
+
+  N get first => values.first;
+
+  String toString() => "Priority: $priority $values";
+}
+
+/**
+ * A priority queue with a FIFO property for nodes with same priority.
+ * The queue guarantees that nodes are returned in the same order they
+ * are added for a given priority.
+ * For type safety this queue is guarded by the elements being subclasses of
+ * TypedElement - this is not strictly neccesary since we never actually
+ * use the value or type of the nodes.
+ */
+class PriorityQueue<N extends TypedElement, P extends Priority> {
+  PriorityNode<N, P> head;
+  int length = 0;
+
+  void add(N value, P priority) {
+    length++;
+    if (head == null) {
+      head = new PriorityNode<N, P>(value, priority);
+      return;
+    }
+    assert(head.next == null);
+    var node = head;
+    while (node.prev != null && node.priority > priority) {
+      node = node.prev;
+    }
+    if (node.priority == priority) {
+      node.add(value);
+    } else if (node.priority < priority) {
+      var newNode = new PriorityNode<N, P>(value, priority);
+      newNode.next = node.next;
+      if (node.next != null) node.next.prev = newNode;
+      newNode.prev = node;
+      node.next = newNode;
+      if (node == head) head = newNode;
+    } else {
+      var newNode = new PriorityNode<N, P>(value, priority);
+      node.prev = newNode;
+      newNode.next = node;
+    }
+  }
+
+  N get first => head.first;
+
+  Priority get firstPriority => head.priority;
+
+  bool get isEmpty => head == null;
+
+  N removeFirst() {
+    if (isEmpty) throw "Can't get element from empty queue";
+    var value = head.removeFirst();
+    if (head.isEmpty) {
+      if (head.prev != null) {
+        head.prev.next = null;
+      }
+      head = head.prev;
+    }
+    length--;
+    assert(head == null || head.next == null);
+    return value;
+  }
+
+  String toString() {
+    if (head == null) return "Empty priority queue";
+    var node = head;
+    var buffer = new StringBuffer();
+    while (node.prev != null) {
+      buffer.writeln(node);
+      node = node.prev;
+    }
+    buffer.writeln(node);
+    return buffer.toString();
+  }
+}
+
+/**
+ * Implements a specialized priority queue that efficiently allows getting
+ * the highest priorized node that adheres to a set of restrictions.
+ * Most notably it allows to get the highest priority node where the node's
+ * type is not in an exclude list.
+ * In addition, the queue has a number of properties:
+ *   The queue has fifo semantics for nodes with the same priority and type,
+ *   i.e., if nodes a and b are added to the queue with priority x and type z
+ *   then a is returned first iff a was added before b
+ * For different types with the same priority no guarantees are given, but
+ * the returned values try to be fair by returning from the biggest list of
+ * tasks in case of priority clash. (This could be fixed by adding timestamps
+ * to every node, that is _only_ used when collisions occur, not for
+ * insertions)
+ */
+class RestrictViewPriorityQueue<N extends TypedElement, P extends Priority> {
+  // We can't use the basic dart priority queue since it does not guarantee
+  // FIFO for items with the same order. This is currently not uptimized for
+  // different N, if many different N is expected here we should have a
+  // priority queue instead of a list.
+  List<PriorityQueue<N, P>> restrictedQueues = new List<PriorityQueue<N, P>>();
+  PriorityQueue<N, P> mainQueue = new PriorityQueue<N, P>();
+
+  void add(N value, P priority) {
+    for (var queue in restrictedQueues) {
+      if ((queue.first as StringTypedElement).value == value) {
+        queue.add(value, priority);
+      }
+    }
+    mainQueue.add(value, priority);
+  }
+
+  bool get isEmpty => restrictedQueues.length + mainQueue.length == 0;
+
+  int get length =>
+      restrictedQueues.fold(0, (v, e) => v + e.length) + mainQueue.length;
+
+  PriorityQueue getRestricted(List<N> restrictions) {
+    var current = null;
+    // Find highest restricted priority.
+    for (var queue in restrictedQueues) {
+      if (!restrictions.any((e) => queue.head.first.typeEquals(e))) {
+        if (current == null || queue.firstPriority > current.firstPriority) {
+          current = queue;
+        } else if (current.firstPriority == queue.firstPriority) {
+          current = queue.length > current.length ? queue : current;
+        }
+      }
+    }
+    return current;
+  }
+
+  N get first {
+    if (isEmpty) throw "Trying to remove node from empty queue";
+    var candidate = getRestricted([]);
+    if (candidate != null &&
+        (mainQueue.isEmpty ||
+            mainQueue.firstPriority < candidate.firstPriority)) {
+      return candidate.first;
+    }
+    return mainQueue.isEmpty ? null : mainQueue.first;
+  }
+
+  /**
+   * Returns the node that under the given set of restrictions.
+   * If the queue is empty this function throws.
+   * If the queue is not empty, but no node exists that adheres to the
+   * restrictions we return null.
+   */
+  N removeFirst({List<N> restrictions: const []}) {
+    if (isEmpty) throw "Trying to remove node from empty queue";
+    var candidate = getRestricted(restrictions);
+
+    if (candidate != null &&
+        (mainQueue.isEmpty ||
+            mainQueue.firstPriority < candidate.firstPriority)) {
+      var value = candidate.removeFirst();
+      if (candidate.isEmpty) restrictedQueues.remove(candidate);
+      return value;
+    }
+    while (!mainQueue.isEmpty) {
+      var currentPriority = mainQueue.firstPriority;
+      var current = mainQueue.removeFirst();
+      if (!restrictions.any((e) => current.typeEquals(e))) {
+        return current;
+      } else {
+        var restrictedQueue = restrictedQueues.firstWhere(
+            (e) => current.typeEquals((e.first as StringTypedElement).type),
+            orElse: () => null);
+        if (restrictedQueue == null) {
+          restrictedQueue = new PriorityQueue<N, P>();
+          restrictedQueues.add(restrictedQueue);
+        }
+        restrictedQueue.add(current, currentPriority);
+      }
+    }
+    return null;
+  }
+
+  String toString() {
+    if (isEmpty) return "Empty queue";
+    var buffer = new StringBuffer();
+    if (!restrictedQueues.isEmpty) {
+      buffer.writeln("Restricted queues");
+      for (var queue in restrictedQueues) {
+        buffer.writeln("$queue");
+      }
+    }
+    buffer.writeln("Main queue:");
+    buffer.writeln("$mainQueue");
+    return buffer.toString();
+  }
+}
+
+/// TEMPORARY TESTING AND PERFORMANCE
+void main([args]) {
+  stress(new RestrictViewPriorityQueue<StringTypedElement, IntPriority>());
+}
+
+void stress(queue) {
+  final int SIZE = 50000;
+  Random random = new Random(29);
+
+  var priorities = [1, 2, 3, 16, 32, 42, 56, 57, 59, 90];
+  var values = [
+    new StringTypedElement('safari', 'foo'),
+    new StringTypedElement('ie', 'bar'),
+    new StringTypedElement('ff', 'foobar'),
+    new StringTypedElement('dartium', 'barfoo'),
+    new StringTypedElement('chrome', 'hest'),
+    new StringTypedElement('drt', 'fisk')
+  ];
+
+  var restricted = [values[0], values[4]];
+
+  void addRandom() {
+    queue.add(values[random.nextInt(values.length)],
+        new IntPriority(priorities[random.nextInt(priorities.length)]));
+  }
+
+  var stopwatch = new Stopwatch()..start();
+  while (queue.length < SIZE) {
+    addRandom();
+  }
+
+  stopwatch.stop();
+  print("Adding took: ${stopwatch.elapsedMilliseconds}");
+  print("Queue length: ${queue.length}");
+
+  stopwatch = new Stopwatch()..start();
+  while (queue.length > 0) {
+    queue.removeFirst();
+  }
+  stopwatch.stop();
+  print("Remowing took: ${stopwatch.elapsedMilliseconds}");
+  print("Queue length: ${queue.length}");
+
+  print("Restricted add/remove");
+  while (queue.length < SIZE) {
+    addRandom();
+  }
+
+  for (int i = 0; i < SIZE; i++) {
+    if (random.nextDouble() < 0.5) {
+      queue.removeFirst(restrictions: restricted);
+    } else {
+      queue.removeFirst();
+    }
+    addRandom();
+  }
+}
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index 066fe56..2518819 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -55,6 +55,7 @@
 io/wait_for_event_zone_caught_error_test: SkipByDesign # Uses mirrors.
 io/wait_for_event_zone_test: SkipByDesign # Uses mirrors.
 io/wait_for_test: SkipByDesign # Uses mirrors.
+verbose_gc_to_bmu_test: Skip # Attempts to spawn dart using Platform.executable
 
 [ $builder_tag == swarming && $system == macos ]
 io/*: Skip # Issue 30618
@@ -78,8 +79,9 @@
 io/secure_server_client_certificate_test: Skip # Re-enable once the bots have been updated. Issue #26057
 io/socket_many_connections_test: Skip # This test fails with "Too many open files" on the Mac OS buildbot. This is expected as MacOS by default runs with a very low number of allowed open files ('ulimit -n' says something like 256).
 
-[ $arch == arm || $arch == arm64 || $runtime != vm || $mode == debug && $system == windows ]
-fragmentation_test: Skip
+[ $arch == arm || $arch == arm64 || $runtime != vm || $system == android ]
+fragmentation_test: SkipSlow
+fragmentation_typed_data_test: SkipSlow
 
 [ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
 *: SkipByDesign
@@ -91,7 +93,6 @@
 deferred_transitive_import_error_test: Skip
 
 [ $hot_reload || $hot_reload_rollback ]
-fragmentation_test: Crash # Issue 31421
 io/addlatexhash_test: Crash # Issue 31252
 io/many_directory_operations_test: SkipSlow
 io/many_file_operations_test: SkipSlow
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 93f0fda..b967e9f 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -4,8 +4,9 @@
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
 
-fragmentation_test: Slow # GC heavy
-io/process_sync_test: Slow # Spawns synchronously subprocesses in sequence.
+fragmentation_test: Pass, Slow # GC heavy
+fragmentation_typed_data_test: Pass, Slow # GC heavy
+io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
 
 [ $compiler == dartkb ]
 no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
@@ -85,10 +86,10 @@
 io/directory_chdir_test: Skip # Timeout
 io/echo_server_stream_test: Slow
 
-# Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which
+# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
-[ ($arch == simarm || $arch == simarm64 || $arch == simdbc64) && ($compiler == dartk || $compiler == dartkb) ]
+[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
 io/file_blocking_lock_test: Crash # Please triage.
 io/file_lock_test: Slow
 map_insert_remove_oom_test: Skip # Heap limit too low.
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 5919089..93e314f 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -47,18 +47,15 @@
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
 
-[ $arch == simdbc64 && $mode == debug && $checked ]
-io/web_socket_test: Pass, RuntimeError # Issue 26814.
-
 [ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
+[ $arch == x64 && $mode == release && $runtime == vm && $system == linux ]
+io/http_bind_test: Pass, Timeout # Issue 35192
+
 [ $compiler != dart2analyzer && $system == windows ]
 io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
 
-[ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ]
-io/http_bind_test: Pass, Timeout # Issue 35192
-
 [ $mode == release && $runtime == vm && $system == macos ]
 io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
 io/named_pipe_script_test: Pass, RuntimeError # Issue 28737
@@ -80,8 +77,3 @@
 io/dart_std_io_pipe_test: Timeout, Pass
 io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode.
 io/process_sync_test: Timeout, Pass
-
-[ $arch == simdbc || $arch == simdbc64 ]
-full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
-link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives.
-no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers
diff --git a/tests/standalone/verbose_gc_to_bmu_script.dart b/tests/standalone_2/verbose_gc_to_bmu_script.dart
similarity index 100%
rename from tests/standalone/verbose_gc_to_bmu_script.dart
rename to tests/standalone_2/verbose_gc_to_bmu_script.dart
diff --git a/tests/standalone_2/verbose_gc_to_bmu_test.dart b/tests/standalone_2/verbose_gc_to_bmu_test.dart
new file mode 100644
index 0000000..860e5eb0
--- /dev/null
+++ b/tests/standalone_2/verbose_gc_to_bmu_test.dart
@@ -0,0 +1,71 @@
+// 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.
+
+// OtherResources=verbose_gc_to_bmu_script.dart
+
+// This test forks a second vm process that runs the BMU tool and verifies that
+// it produces some output. This test is mainly here to ensure that the BMU
+// tool compiles and runs.
+
+import "dart:async";
+import "dart:convert";
+import "dart:io";
+
+import "package:path/path.dart";
+
+// Tool script relative to the path of this test.
+var toolScript = Uri.parse(Platform.executable)
+    .resolve("../../runtime/tools/verbose_gc_to_bmu.dart")
+    .toFilePath();
+
+// Target script relative to this test.
+var targetScript =
+    Platform.script.resolve("verbose_gc_to_bmu_script.dart").toFilePath();
+const minOutputLines = 20;
+
+void checkExitCode(targetResult) {
+  if (exitCode != 0) {
+    print("Process terminated with exit code ${exitCode}.");
+    exit(-1);
+  }
+}
+
+void main() {
+  // Compute paths for tool and target relative to the path of this script.
+  var targetResult =
+      Process.runSync(Platform.executable, ["--verbose_gc", targetScript]);
+  checkExitCode(targetResult);
+  var gcLog = targetResult.stderr;
+  Process.start(Platform.executable, [toolScript]).then((Process process) {
+    // Feed the GC log of the target to the BMU tool.
+    process.stdin.write(gcLog);
+    process.stdin.close();
+    var stdoutStringStream =
+        process.stdout.transform(utf8.decoder).transform(new LineSplitter());
+    var stderrStringStream =
+        process.stderr.transform(utf8.decoder).transform(new LineSplitter());
+    // Wait for 3 future events: stdout and stderr streams closed, and
+    // process terminated.
+    var futures = <Future>[];
+    var stdoutLines = [];
+    var stderrLines = [];
+    var subscription = stdoutStringStream.listen(stdoutLines.add);
+    futures.add(subscription.asFuture(true));
+    subscription = stderrStringStream.listen(stderrLines.add);
+    futures.add(subscription.asFuture(true));
+    futures.add(process.exitCode.then(checkExitCode));
+    Future.wait(futures).then((results) {
+      if (stderrLines.isNotEmpty) {
+        print("Unexpected output on stderr:");
+        print(stderrLines.join('\n'));
+        exit(-1);
+      }
+      if (stdoutLines.length < minOutputLines) {
+        print("Less than expected output on stdout:");
+        print(stdoutLines.join('\n'));
+        exit(-1);
+      }
+    });
+  });
+}
diff --git a/third_party/pkg_tested/pkg_tested.status b/third_party/pkg_tested/pkg_tested.status
index b3d8b47..47ab254 100644
--- a/third_party/pkg_tested/pkg_tested.status
+++ b/third_party/pkg_tested/pkg_tested.status
@@ -28,7 +28,7 @@
 pub/test/run/app_can_read_from_stdin_test: Fail # Issue 19448
 pub/test/run/forwards_signal_posix_test: SkipByDesign
 
-[ $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simarmv5te || $arch == simarmv6 || $builder_tag == asan || $mode == debug) ]
+[ $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simarmv6 || $builder_tag == asan || $mode == debug) ]
 dart_style/test/command_line_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators.
 dart_style/test/formatter_test: Skip # The test controller does not take into account that tests take much longer in debug mode or on simulators.
 
diff --git a/tools/VERSION b/tools/VERSION
index a6ba21a7..97be2aa 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -31,9 +31,9 @@
 #
 CHANNEL dev
 MAJOR 2
-MINOR 6
+MINOR 7
 PATCH 0
-PRERELEASE 8
-PRERELEASE_PATCH 2
-ABI_VERSION 19
-OLDEST_SUPPORTED_ABI_VERSION 18
+PRERELEASE 0
+PRERELEASE_PATCH 0
+ABI_VERSION 21
+OLDEST_SUPPORTED_ABI_VERSION 19
diff --git a/tools/approve_results.dart b/tools/approve_results.dart
index 7c409cf..3c323bb 100755
--- a/tools/approve_results.dart
+++ b/tools/approve_results.dart
@@ -18,6 +18,15 @@
 
 import 'bots/results.dart';
 
+bool isUnapprovable(Test test) {
+  String name = test.name;
+  return name == "pkg/analyzer/test/generated/parser_fasta_test" ||
+      name == "pkg/compiler/tool/generate_kernel_test" ||
+      name == "pkg/vm/test/kernel_front_end_test" ||
+      ["pkg/kernel/test/", "pkg/front_end/", "pkg/analyzer/test/src/fasta/"]
+          .any((path) => test.name.startsWith(path));
+}
+
 /// Returns whether two decoded JSON objects are identical.
 bool isIdenticalJson(dynamic a, dynamic b) {
   if (a is Map<String, dynamic> && b is Map<String, dynamic>) {
@@ -154,22 +163,6 @@
   }
 }
 
-/// TODO(https://github.com/dart-lang/sdk/issues/36015): The step name changed
-/// incompatibly, allow both temporarily to reduce the user breakage. Remove
-/// this 2019-03-25.
-Future<String> todoFallbackLoadLog(
-    String id, String primary, String secondary) async {
-  try {
-    return await loadLog(id, primary);
-  } catch (e) {
-    if (e.toString().startsWith("Exception: The log at ") &&
-        e.toString().endsWith(" doesn't exist")) {
-      return await loadLog(id, secondary);
-    }
-    rethrow;
-  }
-}
-
 /// Loads the results from the bot.
 Future<List<Test>> loadResultsFromBot(String bot, ArgResults options,
     String changeId, Map<String, dynamic> changelistBuild) async {
@@ -182,15 +175,11 @@
     // The 'latest' file contains the name of the latest build that we
     // should download. When preapproving a changelist, we instead find out
     // which build the commit queue was rebased on.
-    /// TODO(https://github.com/dart-lang/sdk/issues/36015): The step name
-    /// changed incompatibly, allow both temporarily to reduce the user
-    /// breakage. Remove this 2019-03-25.
     final build = (changeId != null
-            ? await todoFallbackLoadLog(
+            ? await loadLog(
                 changelistBuild["id"],
                 "download_previous_results/0/steps/gsutil_find_latest_build/0/logs/"
-                    "raw_io.output_text_latest_/0",
-                "gsutil_find_latest_build/0/logs/raw_io.output_text_latest_/0")
+                "raw_io.output_text_latest_/0")
             : await readFile(bot, "latest"))
         .trim();
 
@@ -218,7 +207,6 @@
       return <Test>[];
     }
 
-    // Load the run.json to find the named configuration.
     final resultsFile = new File("$buildPath/results.json");
     if (!await resultsFile.exists()) {
       print("$bot: No results.json exists");
@@ -618,8 +606,19 @@
           ? options["failures-only"]
           : options["successes-only"]))
       .toList();
-  final fixedTests = selectedTests.where((test) => test.matches).toList();
-  final brokenTests = selectedTests.where((test) => !test.matches).toList();
+
+  final fixedTests = [];
+  final brokenTests = [];
+  final blackListedTests = [];
+  for (Test test in selectedTests) {
+    if (isUnapprovable(test) && !test.matches) {
+      blackListedTests.add(test);
+    } else if (test.matches) {
+      fixedTests.add(test);
+    } else {
+      brokenTests.add(test);
+    }
+  }
 
   // Find out which bots have multiple configurations.
   final configurationsForBots = <String, Set<String>>{};
@@ -720,6 +719,16 @@
     print("");
   }
 
+  if (blackListedTests.isNotEmpty) {
+    print("Warning: The following failing test(s) cannot be approved:");
+    print("");
+    blackListedTests.forEach((test) => print("  ${test.name}"));
+    print("");
+    print(
+        "Try fixing or reverting the change that caused the failure(s) instead.");
+    print("");
+  }
+
   // Provide statistics on how well the bots are doing.
   void statistic(int numerator, int denominator, String what) {
     double percent = numerator / denominator * 100.0;
@@ -922,6 +931,7 @@
 
     // Approve the changes in test results.
     for (final test in selectedTests) {
+      if (blackListedTests.contains(test)) continue;
       final newApprovals = newApprovalsForBuilders.putIfAbsent(
           test.bot, () => new SplayTreeMap<String, Map<String, dynamic>>());
       final approvalData =
diff --git a/tools/bots/dart2js_d8_hostchecked_tests.isolate b/tools/bots/dart2js_d8_hostchecked_tests.isolate
index eae91c9..a655196 100644
--- a/tools/bots/dart2js_d8_hostchecked_tests.isolate
+++ b/tools/bots/dart2js_d8_hostchecked_tests.isolate
@@ -28,7 +28,6 @@
               'tests/lib_2/',
               'tests/light_unittest.dart',
               'tests/search/',
-              'tests/standalone/',
               'tests/standalone_2/',
               'pkg/async_helper/',
               'pkg/compiler/',
diff --git a/tools/bots/dart_tests.isolate b/tools/bots/dart_tests.isolate
index 701d270..8d72bf3 100644
--- a/tools/bots/dart_tests.isolate
+++ b/tools/bots/dart_tests.isolate
@@ -21,7 +21,6 @@
               'tests/lib_2/',
               'tests/light_unittest.dart',
               'tests/search/',
-              'tests/standalone/',
               'tests/standalone_2/',
               'pkg/async_helper/',
               'pkg/browser/',
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index fd499cb..ea209ae 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -41,7 +41,6 @@
       "tests/lib_2/",
       "tests/light_unittest.dart",
       "tests/search/",
-      "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
       "third_party/babel/babel.min.js",
@@ -79,7 +78,6 @@
       "tests/lib_2/",
       "tests/light_unittest.dart",
       "tests/search/",
-      "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
       "third_party/babel/babel.min.js",
@@ -120,7 +118,6 @@
       "tests/lib_2/",
       "tests/light_unittest.dart",
       "tests/search/",
-      "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
       "third_party/d8/",
@@ -158,7 +155,6 @@
       "tests/lib_2/",
       "tests/light_unittest.dart",
       "tests/search/",
-      "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
       "third_party/d8/",
@@ -184,6 +180,7 @@
       "third_party/pkg_tested/",
       "third_party/observatory_pub_packages/packages/",
       "tools/sdks/dart-sdk/",
+      "pkg/_fe_analyzer_shared/",
       "pkg/async_helper/",
       "pkg/build_integration/",
       "pkg/dart_internal/",
@@ -203,7 +200,6 @@
       "out/DebugSIMARM/",
       "out/DebugSIMARM64/",
       "out/DebugSIMARM_X64/",
-      "out/DebugSIMDBC64/",
       "out/DebugAndroidARM/",
       "out/DebugAndroidARM_X64/",
       "out/DebugAndroidARM64/",
@@ -212,7 +208,6 @@
       "out/ReleaseSIMARM/",
       "out/ReleaseSIMARM64/",
       "out/ReleaseSIMARM_X64/",
-      "out/ReleaseSIMDBC64/",
       "out/ReleaseAndroidARM/",
       "out/ReleaseAndroidARM_X64/",
       "out/ReleaseAndroidARM64/",
@@ -222,21 +217,18 @@
       "out/ProductSIMARM/",
       "out/ProductSIMARM64/",
       "out/ProductSIMARM_X64/",
-      "out/ProductSIMDBC64/",
       "out/ProductAndroidARM/",
       "out/ProductAndroidARM64/",
       "xcodebuild/DebugIA32/",
       "xcodebuild/DebugSIMARM/",
       "xcodebuild/DebugSIMARM64/",
       "xcodebuild/DebugSIMARM_X64/",
-      "xcodebuild/DebugSIMDBC64/",
       "xcodebuild/DebugX64/",
       "xcodebuild/ProductX64/",
       "xcodebuild/ReleaseIA32/",
       "xcodebuild/ReleaseSIMARM/",
       "xcodebuild/ReleaseSIMARM64/",
       "xcodebuild/ReleaseSIMARM_X64/",
-      "xcodebuild/ReleaseSIMDBC64/",
       "xcodebuild/ReleaseX64/",
       "samples/",
       "samples-dev/",
@@ -261,9 +253,9 @@
       "tests/lib_2/",
       "tests/light_unittest.dart",
       "tests/search/",
-      "tests/standalone/",
       "tests/standalone_2/",
       "tests/ffi/",
+      "pkg/_fe_analyzer_shared/",
       "pkg/async_helper/",
       "pkg/build_integration/",
       "pkg/dart_internal/",
@@ -451,11 +443,32 @@
         "use-elf": true
     }},
     "dartk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
+    "dartk-(linux|mac|win)-(debug|product|release)-(ia32|simarm|simarm64|x64)-ast": {
+      "options": {
+        "builder-tag": "ast",
+        "gen-kernel-options": ["--no-gen-bytecode"]
+    }},
+    "dartkp-(linux|mac)-(debug|product|release)-x64-ast": {
+      "options": {
+        "builder-tag": "ast",
+        "gen-kernel-options": ["--no-gen-bytecode"]
+    }},
+    "dartkp-(linux|mac)-(debug|product|release)-simarm64-ast": {
+       "options": {
+        "builder-tag": "ast",
+        "use-blobs": true,
+        "gen-kernel-options": ["--no-gen-bytecode"]
+    }},
+    "dartkp-linux-(debug|product|release)-simarm-crossword-ast": {
+      "options": {
+        "builder-tag": "crossword_ast",
+        "gen-kernel-options": ["--no-gen-bytecode"]
+    }},
     "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "enable-asserts": true
     }},
-    "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64|simdbc64)": { },
+    "dartk-(linux|mac|win)-(debug|product|release)-(arm64|simarm|simarm64)": { },
     "dartk-optcounter-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "builder-tag": "optimization_counter_threshold",
@@ -465,29 +478,50 @@
       "options": {
         "hot-reload": true
     }},
-    "dartk-reload-mac-(debug|product|release)-simdbc64": {
-      "options": {
-        "hot-reload": true
-    }},
     "dartk-reload-rollback-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "hot-reload-rollback": true
     }},
     "app_jitk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": { },
-    "dartkb-interpret-(linux|mac|win)-(debug|product|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
+    "dartkb-interpret-(linux|mac|win)-product-(ia32|x64|arm|arm64|simarm|simarm64)": {
       "options": {
         "builder-tag": "bytecode_interpreter",
+        "gen-kernel-options": [
+          "--gen-bytecode",
+          "--drop-ast",
+          "--bytecode-options=source-positions,annotations"
+        ],
         "vm-options": ["--enable_interpreter", "--compilation-counter-threshold=-1"]
     }},
-    "dartkb-mixed-(linux|mac|win)-(debug|product|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
+    "dartkb-interpret-(linux|mac|win)-(debug|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
+      "options": {
+        "builder-tag": "bytecode_interpreter",
+        "gen-kernel-options": [
+          "--gen-bytecode",
+          "--drop-ast",
+          "--bytecode-options=source-positions,annotations,local-var-info,debugger-stops"
+        ],
+        "vm-options": ["--enable_interpreter", "--compilation-counter-threshold=-1"]
+    }},
+    "dartkb-mixed-(linux|mac|win)-(debug|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
       "options": {
         "builder-tag": "bytecode_mixed",
+        "gen-kernel-options": [
+          "--gen-bytecode",
+          "--drop-ast",
+          "--bytecode-options=source-positions,annotations,local-var-info,debugger-stops"
+        ],
         "vm-options": ["--enable_interpreter"]
     }},
-    "dartkb-compile-(linux|mac|win)-(debug|product|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
+    "dartkb-mixed-(linux|mac|win)-product-(ia32|x64|arm|arm64|simarm|simarm64)": {
       "options": {
-        "builder-tag": "bytecode_compiler",
-        "vm-options": ["--use_bytecode_compiler"]
+        "builder-tag": "bytecode_mixed",
+        "gen-kernel-options": [
+          "--gen-bytecode",
+          "--drop-ast",
+          "--bytecode-options=source-positions,annotations"
+        ],
+        "vm-options": ["--enable_interpreter"]
     }},
     "(dartdevc|dartdevk)-checked-(linux|mac|win)-(debug|product|release)-(chrome|firefox)": {
       "options": {
@@ -498,7 +532,17 @@
       "options": {
         "checked": true,
         "use-sdk": true,
-        "enable-experiment": ["non-nullable"]
+        "enable-experiment": ["non-nullable"],
+        "enable-asserts": true
+
+    }},
+    "dartdevc-weak-linux-release-chrome": {
+      "options": {
+        "checked": true,
+        "use-sdk": true,
+        "enable-experiment": ["non-nullable"],
+        "enable-asserts": true
+
     }},
     "fasta-(linux|mac|win)": { },
     "analyzer-(linux|mac|win)": {
@@ -551,22 +595,27 @@
         },
         {
           "name": "unit tests",
-          "script": "tools/disguised_test.py",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
              "pkg/(kernel|front_end|fasta)"
           ]
+        },
+        {
+          "name": "unit tests suites",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/front_end/test/unit_test_suites.dart",
+            "-nfront-end-${system}-release-x64",
+            "--verbose"
+          ]
         }
       ]
     },
     {
       "builders": [
-        "vm-dartkb-linux-debug-x64",
         "vm-dartkb-linux-release-x64",
-        "vm-dartkb-linux-product-x64",
-        "vm-dartkb-linux-debug-simarm64",
-        "vm-dartkb-linux-release-simarm64",
-        "vm-dartkb-linux-product-simarm64"
+        "vm-dartkb-linux-release-simarm64"
       ],
       "meta": {
         "description": "This configuration is used by the vm kbc builders."
@@ -606,23 +655,6 @@
           "shards": 4
         },
         {
-          "name": "vm bytecode compiler tests",
-          "arguments": [
-            "-ndartkb-compile-linux-${mode}-${arch}"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        },
-        {
-          "name": "vm bytecode compiler co19 tests",
-          "arguments": [
-            "-ndartkb-compile-linux-${mode}-${arch}",
-            "co19_2"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        },
-        {
           "name": "vm interpreter tests",
           "arguments": [
             "-ndartkb-interpret-linux-${mode}-${arch}"
@@ -643,6 +675,92 @@
     },
     {
       "builders": [
+        "vm-kernel-ast-linux-debug-ia32",
+        "vm-kernel-ast-linux-release-ia32",
+        "vm-kernel-ast-linux-debug-x64",
+        "vm-kernel-ast-linux-release-simarm",
+        "vm-kernel-ast-linux-release-simarm64",
+        "vm-kernel-ast-linux-release-x64",
+        "vm-kernel-ast-win-debug-x64",
+        "vm-kernel-ast-win-release-x64"
+      ],
+      "meta": {
+        "description": "This configuration is used by the vm legacy AST-mode (no-bytecode) JIT builders."
+      },
+      "steps": [
+        {
+          "name": "configure dart",
+          "script": "tools/gn.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=${arch}",
+            "--no-bytecode"
+          ]
+        },
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "runtime"
+          ]
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartk-${system}-${mode}-${arch}-ast"],
+          "fileset": "vm-kernel",
+          "shards": 8
+        },
+        {
+          "name": "vm co19 tests",
+          "arguments": [
+            "-ndartk-${system}-${mode}-${arch}-ast",
+            "co19_2"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 8
+        }
+      ]
+    },
+    {
+      "builders": [
+        "vm-kernel-precomp-ast-linux-debug-x64",
+        "vm-kernel-precomp-ast-linux-release-simarm",
+        "vm-kernel-precomp-ast-linux-release-simarm64",
+        "vm-kernel-precomp-ast-linux-release-x64"
+      ],
+      "meta": {
+        "description": "This configuration is used by the vm legacy AST-mode (no-bytecode) AOT builders."
+      },
+      "steps": [
+        {
+          "name": "configure dart",
+          "script": "tools/gn.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=${arch}",
+            "--no-bytecode"
+          ]
+        },
+        {
+          "name": "build dart",
+          "script": "tools/build.py",
+          "arguments": [
+            "runtime",
+            "dart_precompiled_runtime"
+          ]
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartkp-${system}-${mode}-${arch}-ast"],
+          "fileset": "vm-kernel",
+          "shards": 8
+        }
+      ]
+    },
+    {
+      "builders": [
         "vm-canary-linux-debug"
       ],
       "meta": {
@@ -737,7 +855,6 @@
         "vm-kernel-precomp-linux-release-simarm64",
         "vm-kernel-precomp-linux-release-x64",
         "vm-kernel-precomp-mac-release-simarm64",
-        "vm-kernel-precomp-win-release-simarm64",
         "vm-kernel-precomp-win-release-x64"
       ],
       "meta": {
@@ -1057,15 +1174,11 @@
     {
       "builders": [
         "vm-kernel-linux-product-x64",
-        "vm-kernel-linux-release-simdbc64",
         "vm-kernel-linux-release-x64",
         "vm-kernel-linux-debug-ia32",
-        "vm-kernel-linux-debug-simdbc64",
         "vm-kernel-linux-debug-x64",
         "vm-kernel-mac-product-x64",
-        "vm-kernel-mac-release-simdbc64",
         "vm-kernel-mac-release-x64",
-        "vm-kernel-mac-debug-simdbc64",
         "vm-kernel-mac-debug-x64"
       ],
       "meta": {
@@ -1224,8 +1337,7 @@
           "testRunner": true,
           "arguments": [
             "pkg/dev_compiler/test/modular_ddc_suite.dart",
-            "--configuration-name",
-            "dartdevc-${system}-release",
+            "-ndartdevc-${system}-release",
             "--verbose",
             "--use-sdk"
           ]
@@ -1236,8 +1348,18 @@
           "testRunner": true,
           "arguments": [
             "pkg/dev_compiler/test/modular_suite.dart",
-            "--configuration-name",
-            "dartdevk-${system}-release",
+            "-ndartdevk-${system}-release",
+            "--verbose",
+            "--use-sdk"
+          ]
+        },
+        {
+          "name": "ddc kernel modular NNBD tests",
+          "script": "out/ReleaseX64/dart-sdk/bin/dart",
+          "testRunner": true,
+          "arguments": [
+            "pkg/dev_compiler/test/modular_suite_nnbd.dart",
+            "-ndartdevk-nnbd-${system}-release",
             "--verbose",
             "--use-sdk"
           ]
@@ -1358,9 +1480,14 @@
           "arguments": [
             "-ndartdevc-strong-linux-release-chrome",
             "dartdevc_native"
-          ],
-          "shards": 1,
-          "fileset": "dart2js_nnbd"
+          ]
+        },
+        {
+          "name": "ddc nnbd weak tests",
+          "arguments": [
+            "-ndartdevc-weak-linux-release-chrome",
+            "dartdevc_native"
+          ]
         }
       ]
     },
@@ -1393,8 +1520,7 @@
           "testRunner": true,
           "arguments": [
             "pkg/dev_compiler/test/modular_suite.dart",
-            "--configuration-name",
-            "dartdevk-${system}-release",
+            "-ndartdevk-${system}-release",
             "--verbose",
             "--use-sdk"
           ]
@@ -1465,9 +1591,7 @@
     {
       "builders": [
         "vm-kernel-reload-linux-debug-x64",
-        "vm-kernel-reload-linux-release-x64",
-        "vm-kernel-reload-mac-debug-simdbc64",
-        "vm-kernel-reload-mac-release-simdbc64"
+        "vm-kernel-reload-linux-release-x64"
       ],
       "meta": {
         "description": "This is the configuration for the kernel hot reload builders."
@@ -1529,8 +1653,7 @@
           "testRunner": true,
           "arguments": [
             "pkg/compiler/tool/modular_test_suite.dart",
-            "--configuration-name",
-            "dart2js-${system}-release-d8",
+            "-ndart2js-${system}-release-d8",
             "--verbose",
             "--use-sdk"
           ]
@@ -2360,11 +2483,6 @@
             "dart_precompiled_runtime"]
         },
         {
-          "name": "build linux-x64 simdbc for benchmarking",
-          "script": "tools/build.py",
-          "arguments": ["--mode=release", "--arch=simdbc64", "runtime"]
-        },
-        {
           "name": "archive linux-x64 for benchmarking",
           "script": "tools/bots/try_benchmarks.sh",
           "arguments": ["linux-x64-archive"]
@@ -2588,6 +2706,62 @@
           "shards": 10
         }
       ]
+    },
+    {
+      "builders": [
+        "vm-kernel-precomp-ast-linux-release-simarm_x64"
+      ],
+      "meta": {
+        "description": "This configuration runs tests for the simarm_x64 architecture in AST mode."
+      },
+      "steps": [
+        {
+          "name": "configure dart for simarm_x64",
+          "script": "tools/gn.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=simarm_x64",
+            "--no-bytecode"
+          ]
+        },
+        {
+          "name": "configure dart for simarm",
+          "script": "tools/gn.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=simarm",
+            "--no-bytecode"
+          ]
+        },
+        {
+          "name": "build dart for simarm_x64",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=simarm_x64",
+            "gen_snapshot"
+          ]
+        },
+        {
+          "name": "build dart for simarm",
+          "script": "tools/build.py",
+          "arguments": [
+            "--mode=${mode}",
+            "--arch=simarm",
+            "dart_precompiled_runtime",
+            "vm_platform"
+          ]
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartkp-${system}-${mode}-simarm-crossword-ast",
+            "--gen-snapshot=${build_root}/gen_snapshot"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 10
+        }
+      ]
     }
   ]
 }
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index 88e7753..24b87ae 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -396,6 +396,8 @@
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages hello.dart
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/precompiler2 --packages=.packages hello.dart blob.bin
     DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart_precompiled_runtime2 --profile-period=10000 blob.bin
+    DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/precompiler2 --no-gen-bytecode --packages=.packages hello.dart blob.bin
+    DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart_precompiled_runtime2 --profile-period=10000 blob.bin
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --optimization-counter-threshold=-1 hello.dart
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --enable-interpreter hello.dart
     out/ReleaseX64/dart --profile-period=10000 --packages=.packages --enable-interpreter --compilation-counter-threshold=-1 hello.dart
diff --git a/tools/build.py b/tools/build.py
index 4ff1a18..ecff331 100755
--- a/tools/build.py
+++ b/tools/build.py
@@ -17,9 +17,8 @@
 SCRIPT_DIR = os.path.dirname(sys.argv[0])
 DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
 AVAILABLE_ARCHS = [
-    'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', 'simarmv5te',
-    'armv5te', 'simarm64', 'arm64', 'simdbc', 'simdbc64', 'armsimdbc',
-    'armsimdbc64', 'simarm_x64'
+    'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', 'simarm64',
+    'arm64', 'simarm_x64'
 ]
 
 usage = """\
@@ -87,7 +86,7 @@
 
 def ProcessOptions(options, args):
     if options.arch == 'all':
-        options.arch = 'ia32,x64,simarm,simarm64,simdbc64'
+        options.arch = 'ia32,x64,simarm,simarm64'
     if options.mode == 'all':
         options.mode = 'debug,release,product'
     if options.os == 'all':
@@ -117,8 +116,7 @@
                       % (os_name, HOST_OS))
                 return False
             if not arch in [
-                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'armv5te', 'arm64', 'simdbc',
-                    'simdbc64'
+                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64'
             ]:
                 print(
                     "Cross-compilation to %s is not supported for architecture %s."
diff --git a/tools/diff_results.dart b/tools/diff_results.dart
index c0107d3..0e5ee51 100644
--- a/tools/diff_results.dart
+++ b/tools/diff_results.dart
@@ -388,7 +388,6 @@
         'simarm64',
         'arm',
         'arm64',
-        'simdbc64'
       ]);
     }
   }
diff --git a/tools/disguised_test.py b/tools/disguised_test.py
deleted file mode 100755
index e3d8f0a..0000000
--- a/tools/disguised_test.py
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-# 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 script disguises test.py so it doesn't look like test.py to the testing
-# infrastructure, which handles test.py specially. Any testing done through
-# this script will not show up on testing dashboards and in the test results
-# database.
-
-# The front-end-* builders are currently using this script to run their unit
-# tests, which must always pass and should not be approvable through the status
-# file free workflow.
-
-import os
-import subprocess
-import sys
-
-exit(
-    subprocess.call([
-        sys.executable,
-        os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.py")
-    ] + sys.argv[1:]))
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index ebe497a..9cdef06 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -269,8 +269,8 @@
   }
 
   // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
-  // Ideally we would provide a RectangleMixin class that provides this implementation.
-  // In an ideal world we would exp
+  // Ideally we would provide a RectangleMixin class that provides this
+  // implementation. In an ideal world we would exp
   /** The x-coordinate of the right edge. */
   num get right => left + width;
   /** The y-coordinate of the bottom edge. */
@@ -280,13 +280,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is! Rectangle) return false;
-    return left == other.left &&
-        top == other.top &&
-        right == other.right &&
-        bottom == other.bottom;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      right == other.right &&
+      bottom == other.bottom;
 
   int get hashCode => _JenkinsSmiHash.hash4(
       left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
diff --git a/tools/dom/templates/html/impl/impl_DOMRect.darttemplate b/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
index f99d980..a2b037d 100644
--- a/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMRect.darttemplate
@@ -11,11 +11,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is !Rectangle) return false;
-    return left == other.left && top == other.top && width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode,
       width.hashCode, height.hashCode);
diff --git a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
index 912f652..611db89 100644
--- a/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
+++ b/tools/dom/templates/html/impl/impl_DOMRectReadOnly.darttemplate
@@ -11,11 +11,12 @@
     return 'Rectangle ($left, $top) $width x $height';
   }
 
-  bool operator ==(other) {
-    if (other is !Rectangle) return false;
-    return left == other.left && top == other.top && width == other.width &&
-        height == other.height;
-  }
+  bool operator ==(other) =>
+      other is Rectangle &&
+      left == other.left &&
+      top == other.top &&
+      width == other.width &&
+      height == other.height;
 
   int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode,
       width.hashCode, height.hashCode);
diff --git a/tools/gardening/lib/src/buildbot_data.dart b/tools/gardening/lib/src/buildbot_data.dart
index ebca746..ffd29e3 100644
--- a/tools/gardening/lib/src/buildbot_data.dart
+++ b/tools/gardening/lib/src/buildbot_data.dart
@@ -12,18 +12,6 @@
     groupName: 'vm',
     subgroups: const <BuildSubgroup>[
       const BuildSubgroup(shardNames: const <String>[
-        'vm-mac-debug-simdbc64-be',
-      ], testSteps: const <String>[
-        'vm tests',
-        'checked vm tests',
-      ]),
-      const BuildSubgroup(shardNames: const <String>[
-        'vm-mac-release-simdbc64-be',
-      ], testSteps: const <String>[
-        'vm tests',
-        'checked vm tests',
-      ]),
-      const BuildSubgroup(shardNames: const <String>[
         'vm-linux-debug-x64-be',
       ], testSteps: const <String>[
         'vm tests',
@@ -287,12 +275,6 @@
         'checked vm tests',
       ]),
       const BuildSubgroup(shardNames: const <String>[
-        'vm-mac-debug-simdbc64-reload-be',
-      ], testSteps: const <String>[
-        'vm tests',
-        'checked vm tests',
-      ]),
-      const BuildSubgroup(shardNames: const <String>[
         'vm-linux-release-x64-reload-be',
       ], testSteps: const <String>[
         'vm tests',
@@ -304,12 +286,6 @@
         'vm tests',
         'checked vm tests',
       ]),
-      const BuildSubgroup(shardNames: const <String>[
-        'vm-mac-release-simdbc64-reload-be',
-      ], testSteps: const <String>[
-        'vm tests',
-        'checked vm tests',
-      ]),
     ],
   ),
   const BuildGroup(
diff --git a/tools/gardening/lib/src/results/configurations.dart b/tools/gardening/lib/src/results/configurations.dart
index 6bde17a..7d20657 100644
--- a/tools/gardening/lib/src/results/configurations.dart
+++ b/tools/gardening/lib/src/results/configurations.dart
@@ -15,14 +15,10 @@
   static const x64 = const Architecture._('x64');
   static const arm = const Architecture._('arm');
   static const armv6 = const Architecture._('armv6');
-  static const armv5te = const Architecture._('armv5te');
   static const arm64 = const Architecture._('arm64');
   static const simarm = const Architecture._('simarm');
   static const simarmv6 = const Architecture._('simarmv6');
-  static const simarmv5te = const Architecture._('simarmv5te');
   static const simarm64 = const Architecture._('simarm64');
-  static const simdbc = const Architecture._('simdbc');
-  static const simdbc64 = const Architecture._('simdbc64');
 
   static final List<String> names = _all.keys.toList();
 
@@ -31,14 +27,10 @@
     x64,
     arm,
     armv6,
-    armv5te,
     arm64,
     simarm,
     simarmv6,
-    simarmv5te,
     simarm64,
-    simdbc,
-    simdbc64
   ], key: (architecture) => (architecture as Architecture).name);
 
   static Architecture find(String name) {
diff --git a/tools/gardening/lib/src/shard_data.dart b/tools/gardening/lib/src/shard_data.dart
index ad781d8..dcb012f 100644
--- a/tools/gardening/lib/src/shard_data.dart
+++ b/tools/gardening/lib/src/shard_data.dart
@@ -8,8 +8,6 @@
 
 const Map<String, List<String>> shardGroups = const {
   'vm': const <String>[
-    'vm-mac-debug-simdbc64-be',
-    'vm-mac-release-simdbc64-be',
     'vm-linux-debug-x64-be',
     'vm-linux-release-x64-be',
     'vm-linux-debug-ia32-be',
@@ -80,10 +78,8 @@
   'vm-reload': const <String>[
     'vm-linux-debug-x64-reload-be',
     'vm-linux-debug-x64-reload-rollback-be',
-    'vm-mac-debug-simdbc64-reload-be',
     'vm-linux-release-x64-reload-be',
     'vm-linux-release-x64-reload-rollback-be',
-    'vm-mac-release-simdbc64-reload-be',
   ],
   'dart2js-d8-hostchecked': const <String>[
     'dart2js-linux-d8-hostchecked-unittest-1-5-be',
@@ -168,8 +164,6 @@
     'app-linux-product-x64-dev',
   ],
   'vm-dev': const <String>[
-    'vm-mac-debug-simdbc64-dev',
-    'vm-mac-release-simdbc64-dev',
     'vm-linux-debug-x64-dev',
     'vm-linux-release-x64-dev',
     'vm-linux-debug-ia32-dev',
@@ -235,10 +229,8 @@
   'vm-reload-dev': const <String>[
     'vm-linux-debug-x64-reload-dev',
     'vm-linux-debug-x64-reload-rollback-dev',
-    'vm-mac-debug-simdbc64-reload-dev',
     'vm-linux-release-x64-reload-dev',
     'vm-linux-release-x64-reload-rollback-dev',
-    'vm-mac-release-simdbc64-reload-dev',
   ],
   'dart2js-d8-hostchecked-dev': const <String>[
     'dart2js-linux-d8-hostchecked-unittest-1-5-dev',
@@ -371,14 +363,10 @@
   'vm-reload-stable': const <String>[
     'vm-linux-debug-x64-reload-stable',
     'vm-linux-debug-x64-reload-rollback-stable',
-    'vm-mac-debug-simdbc64-reload-stable',
     'vm-linux-release-x64-reload-stable',
     'vm-linux-release-x64-reload-rollback-stable',
-    'vm-mac-release-simdbc64-reload-stable',
   ],
   'vm-stable': const <String>[
-    'vm-mac-debug-simdbc64-stable',
-    'vm-mac-release-simdbc64-stable',
     'vm-linux-debug-x64-stable',
     'vm-linux-release-x64-stable',
     'vm-linux-debug-ia32-stable',
diff --git a/tools/generate_buildfiles.py b/tools/generate_buildfiles.py
index 0bca73d..1de6936 100755
--- a/tools/generate_buildfiles.py
+++ b/tools/generate_buildfiles.py
@@ -53,7 +53,7 @@
         '-m',
         'all',
         '-a',
-        'arm,armsimdbc,arm64,armsimdbc64',
+        'arm,arm64',
     ]
     if options.verbose:
         gn_command.append('-v')
diff --git a/tools/gn.py b/tools/gn.py
index 385a411..c98246a 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -95,32 +95,21 @@
 
 def HostCpuForArch(arch):
     if arch in [
-            'ia32', 'arm', 'armv6', 'armv5te', 'simarm', 'simarmv6',
-            'simarmv5te', 'simdbc', 'armsimdbc', 'simarm_x64'
+            'ia32', 'arm', 'armv6', 'simarm', 'simarmv6', 'simarm_x64'
     ]:
         return 'x86'
-    if arch in [
-            'x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64', 'arm_x64'
-    ]:
+    if arch in ['x64', 'arm64', 'simarm64', 'arm_x64']:
         return 'x64'
 
 
 # The C compiler's target.
 def TargetCpuForArch(arch, target_os):
-    if arch in ['ia32', 'simarm', 'simarmv6', 'simarmv5te']:
+    if arch in ['ia32', 'simarm', 'simarmv6']:
         return 'x86'
     if arch in ['x64', 'simarm64', 'simarm_x64']:
         return 'x64'
-    if arch == 'simdbc':
-        return 'arm' if target_os == 'android' else 'x86'
-    if arch in ['simdbc64']:
-        return 'arm64' if target_os == 'android' else 'x64'
     if arch == 'arm_x64':
         return 'arm'
-    if arch == 'armsimdbc':
-        return 'arm'
-    if arch == 'armsimdbc64':
-        return 'arm64'
     return arch
 
 
@@ -134,12 +123,8 @@
         return 'arm'
     if arch in ['armv6', 'simarmv6']:
         return 'armv6'
-    if arch in ['armv5te', 'simarmv5te']:
-        return 'armv5te'
     if arch in ['arm64', 'simarm64']:
         return 'arm64'
-    if arch in ['simdbc', 'simdbc64', 'armsimdbc', 'armsimdbc64']:
-        return 'dbc'
     return arch
 
 
@@ -233,8 +218,6 @@
             gn_args['target_cpu'] = 'arm'
             gn_args['arm_version'] = 6
             gn_args['arm_float_abi'] = floatabi
-        elif gn_args['target_cpu'] == 'armv5te':
-            raise Exception("GN support for armv5te unimplemented")
 
     gn_args['is_debug'] = mode == 'debug'
     gn_args['is_release'] = mode == 'release'
@@ -258,11 +241,11 @@
     enable_code_coverage = args.code_coverage and gn_args['is_clang']
     gn_args['dart_vm_code_coverage'] = enable_code_coverage
 
-    gn_args['is_asan'] = args.asan and gn_args['is_clang']
-    gn_args['is_lsan'] = args.lsan and gn_args['is_clang']
-    gn_args['is_msan'] = args.msan and gn_args['is_clang']
-    gn_args['is_tsan'] = args.tsan and gn_args['is_clang']
-    gn_args['is_ubsan'] = args.ubsan and gn_args['is_clang']
+    gn_args['is_asan'] = args.asan
+    gn_args['is_lsan'] = args.lsan
+    gn_args['is_msan'] = args.msan
+    gn_args['is_tsan'] = args.tsan
+    gn_args['is_ubsan'] = args.ubsan
 
     if not args.platform_sdk and not gn_args['target_cpu'].startswith('arm'):
         gn_args['dart_platform_sdk'] = args.platform_sdk
@@ -315,7 +298,7 @@
 
 def ProcessOptions(args):
     if args.arch == 'all':
-        args.arch = 'ia32,x64,simarm,simarm64,simdbc64'
+        args.arch = 'ia32,x64,simarm,simarm64'
     if args.mode == 'all':
         args.mode = 'debug,release,product'
     if args.os == 'all':
@@ -329,9 +312,8 @@
             return False
     for arch in args.arch:
         archs = [
-            'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6', 'simarmv5te',
-            'armv5te', 'simarm64', 'arm64', 'simdbc', 'simdbc64', 'armsimdbc',
-            'armsimdbc64', 'simarm_x64'
+            'ia32', 'x64', 'simarm', 'arm', 'arm_x64', 'simarmv6', 'armv6',
+            'simarm64', 'arm64', 'simarm_x64'
         ]
         if not arch in archs:
             print("Unknown arch %s" % arch)
@@ -350,8 +332,7 @@
                       % (os_name, HOST_OS))
                 return False
             if not arch in [
-                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'armv5te', 'arm64', 'simdbc',
-                    'simdbc64'
+                    'ia32', 'x64', 'arm', 'arm_x64', 'armv6', 'arm64'
             ]:
                 print(
                     "Cross-compilation to %s is not supported for architecture %s."
@@ -389,8 +370,8 @@
         '-a',
         type=str,
         help='Target architectures (comma-separated).',
-        metavar='[all,ia32,x64,simarm,arm,arm_x64,simarmv6,armv6,simarmv5te,armv5te,'
-        'simarm64,arm64,simdbc,armsimdbc,simarm_x64]',
+        metavar='[all,ia32,x64,simarm,arm,arm_x64,simarmv6,armv6,'
+        'simarm64,arm64,simarm_x64]',
         default='x64')
     common_group.add_argument(
         '--mode',
@@ -434,10 +415,15 @@
     other_group.add_argument(
         '--bytecode',
         '-b',
-        help='Include bytecode in the VMs platform dill',
+        help='Use bytecode in Dart VM',
         default=False,
         action="store_true")
     other_group.add_argument(
+        '--no-bytecode',
+        help='Disable bytecode in Dart VM',
+        dest='bytecode',
+        action="store_false")
+    other_group.add_argument(
         '--clang', help='Use Clang', default=True, action='store_true')
     other_group.add_argument(
         '--no-clang', help='Disable Clang', dest='clang', action='store_false')
diff --git a/tools/patches/flutter-engine/6a65ea9cad4b014f88d2f1be1b321db493725a1c.patch b/tools/patches/flutter-engine/6a65ea9cad4b014f88d2f1be1b321db493725a1c.patch
new file mode 100644
index 0000000..a565233
--- /dev/null
+++ b/tools/patches/flutter-engine/6a65ea9cad4b014f88d2f1be1b321db493725a1c.patch
@@ -0,0 +1,622 @@
+diff --git a/DEPS b/DEPS
+index 3e0e5d6dc52a..50e2d0298e18 100644
+--- a/DEPS
++++ b/DEPS
+@@ -42,8 +42,8 @@ vars = {
+   'dart_async_tag': '2.0.8',
+   'dart_bazel_worker_tag': 'bazel_worker-v0.1.20',
+   'dart_boolean_selector_tag': '1.0.4',
+-  'dart_boringssl_gen_rev': 'bbf52f18f425e29b1185f2f6753bec02ed8c5880',
+-  'dart_boringssl_rev': '702e2b6d3831486535e958f262a05c75a5cb312e',
++  'dart_boringssl_gen_rev': 'b9e27cff1ff0803e97ab1f88764a83be4aa94a6d',
++  'dart_boringssl_rev': '4dfd5af70191b068aebe567b8e29ce108cee85ce',
+   'dart_charcode_tag': 'v1.1.2',
+   'dart_cli_util_rev': '4ad7ccbe3195fd2583b30f86a86697ef61e80f41',
+   'dart_collection_tag': '1.14.11',
+diff --git a/ci/licenses_golden/licenses_third_party b/ci/licenses_golden/licenses_third_party
+index 13daa0f54247..e516f2420475 100644
+--- a/ci/licenses_golden/licenses_third_party
++++ b/ci/licenses_golden/licenses_third_party
+@@ -1,4 +1,4 @@
+-Signature: bc14a6c15e2ed1c6819d722a808248b9
++Signature: 5f2b1df54ae6e4ec5836a1d12bf7c70e
+ 
+ UNUSED LICENSES:
+ 
+@@ -3256,6 +3256,7 @@ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/bn/rsaz_exp.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/bn/rsaz_exp.h
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/p256-x86_64.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/p256-x86_64.h
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/fips_shared.lds
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/intcheck1.png
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/intcheck2.png
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/intcheck3.png
+@@ -3280,6 +3281,32 @@ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCryp
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx!/word/styles.xml
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx!/word/theme/theme1.xml
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20170615.docx!/word/webSettings.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/[Content_Types].xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/_rels/.rels
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/customXml/_rels/item1.xml.rels
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/customXml/item1.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/customXml/itemProps1.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/docProps/app.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/docProps/core.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/docProps/thumbnail.emf
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/_rels/document.xml.rels
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/document.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/endnotes.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/fontTable.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/footer1.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/footer2.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/footer3.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/footnotes.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/header1.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/header2.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/header3.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/media/image1.png
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/media/image2.png
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/numbering.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/settings.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/styles.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/theme/theme1.xml
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/policydocs/BoringCrypto-Security-Policy-20180730.docx!/word/webSettings.xml
+ FILE: ../../../third_party/boringssl/src/crypto/obj/obj_mac.num
+ FILE: ../../../third_party/boringssl/src/crypto/poly1305/poly1305_arm_asm.S
+ FILE: ../../../third_party/boringssl/src/crypto/rsa_extra/rsa_print.c
+@@ -3293,9 +3320,9 @@ FILE: ../../../third_party/boringssl/src/crypto/x509/some_names2.pem
+ FILE: ../../../third_party/boringssl/src/crypto/x509/some_names3.pem
+ FILE: ../../../third_party/boringssl/src/crypto/x509/x509_time_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/x509v3/v3_ocsp.c
+-FILE: ../../../third_party/boringssl/src/fipstools/run_cavp.go
+-FILE: ../../../third_party/boringssl/src/infra/config/cq.cfg
++FILE: ../../../third_party/boringssl/src/go.mod
+ FILE: ../../../third_party/boringssl/src/ssl/bio_ssl.cc
++FILE: ../../../third_party/boringssl/src/ssl/ssl_c_test.c
+ FILE: ../../../third_party/boringssl/src/util/all_tests.json
+ FILE: ../../../third_party/boringssl/src/util/bot/UPDATING
+ FILE: ../../../third_party/boringssl/src/util/bot/cmake-linux64.tar.gz.sha1
+@@ -3304,10 +3331,19 @@ FILE: ../../../third_party/boringssl/src/util/bot/cmake-win32.zip.sha1
+ FILE: ../../../third_party/boringssl/src/util/bot/nasm-win32.exe.sha1
+ FILE: ../../../third_party/boringssl/src/util/bot/perl-win32.zip.sha1
+ FILE: ../../../third_party/boringssl/src/util/bot/sde-linux64.tar.bz2.sha1
++FILE: ../../../third_party/boringssl/src/util/bot/sde-win32.tar.bz2.sha1
+ FILE: ../../../third_party/boringssl/src/util/bot/yasm-win32.exe.sha1
+ FILE: ../../../third_party/boringssl/src/util/doc.config
+ FILE: ../../../third_party/boringssl/src/util/doc.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/delocate.peg.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/acvp.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/acvp/acvp.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/interactive.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/parser.peg
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/parser.peg.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/hash.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/acvptool/subprocess/subprocess.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/run_cavp.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/delocate/delocate.peg.go
+ FILE: ../../../third_party/dart/sdk/lib/_internal/vm/lib/bigint_patch.dart
+ FILE: ../../../third_party/dart/sdk_nnbd/lib/_internal/vm/lib/bigint_patch.dart
+ ----------------------------------------------------------------------------------------------------
+@@ -3462,6 +3498,28 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ 
++The code in third_party/sike also carries the MIT license:
++
++Copyright (c) Microsoft Corporation. All rights reserved.
++
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++SOFTWARE
++
+ Licenses for support code
+ 
+ Parts of the TLS test suite are under the Go license. This code is not included
+@@ -4049,7 +4107,6 @@ FILE: ../../../third_party/boringssl/src/include/openssl/chacha.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/crypto.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/engine.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/hkdf.h
+-FILE: ../../../third_party/boringssl/src/include/openssl/lhash_macros.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/objects.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/opensslconf.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/opensslv.h
+@@ -4226,41 +4283,41 @@ FILE: ../../../third_party/boringssl/src/crypto/rand_extra/rand_extra.c
+ FILE: ../../../third_party/boringssl/src/crypto/x509/make_many_constraints.go
+ FILE: ../../../third_party/boringssl/src/decrepit/cfb/cfb.c
+ FILE: ../../../third_party/boringssl/src/decrepit/cfb/cfb_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_aes_gcm_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_aes_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_ctr_drbg_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_ecdsa2_keypair_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_ecdsa2_pkv_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_ecdsa2_siggen_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_ecdsa2_sigver_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_hmac_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_keywrap_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_main.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_rsa2_keygen_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_rsa2_siggen_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_rsa2_sigver_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_sha_monte_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_sha_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_tdes_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_test_util.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_test_util.h
+-FILE: ../../../third_party/boringssl/src/fipstools/test_fips.c
+ FILE: ../../../third_party/boringssl/src/include/openssl/is_boringssl.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/span.h
+ FILE: ../../../third_party/boringssl/src/ssl/span_test.cc
+ FILE: ../../../third_party/boringssl/src/ssl/ssl_versions.cc
+ FILE: ../../../third_party/boringssl/src/tool/file.cc
+ FILE: ../../../third_party/boringssl/src/tool/sign.cc
++FILE: ../../../third_party/boringssl/src/util/ar/ar.go
+ FILE: ../../../third_party/boringssl/src/util/check_imported_libraries.go
+ FILE: ../../../third_party/boringssl/src/util/convert_comments.go
+ FILE: ../../../third_party/boringssl/src/util/embed_test_data.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/ar.go
+ FILE: ../../../third_party/boringssl/src/util/fipstools/break-hash.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/const.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/delocate.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/delocate.peg
+-FILE: ../../../third_party/boringssl/src/util/fipstools/delocate_test.go
+-FILE: ../../../third_party/boringssl/src/util/fipstools/inject-hash.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_aes_gcm_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_aes_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_ctr_drbg_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_ecdsa2_keypair_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_ecdsa2_pkv_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_ecdsa2_siggen_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_ecdsa2_sigver_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_hmac_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_keywrap_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_main.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_rsa2_keygen_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_rsa2_siggen_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_rsa2_sigver_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_sha_monte_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_sha_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_tdes_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_test_util.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_test_util.h
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/test_fips.c
++FILE: ../../../third_party/boringssl/src/util/fipstools/delocate/delocate.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/delocate/delocate.peg
++FILE: ../../../third_party/boringssl/src/util/fipstools/delocate/delocate_test.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/fipscommon/const.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/inject_hash/inject_hash.go
+ ----------------------------------------------------------------------------------------------------
+ Copyright (c) 2017, Google Inc.
+ 
+@@ -4281,26 +4338,48 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ LIBRARY: boringssl
+ ORIGIN: ../../../third_party/boringssl/src/crypto/bytestring/unicode.c
+ TYPE: LicenseType.unknown
++FILE: ../../../third_party/boringssl/src/crypto/abi_self_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/bytestring/unicode.c
+ FILE: ../../../third_party/boringssl/src/crypto/chacha/internal.h
+ FILE: ../../../third_party/boringssl/src/crypto/cipher_extra/e_aesccm.c
+ FILE: ../../../third_party/boringssl/src/crypto/cpu-aarch64-fuchsia.c
++FILE: ../../../third_party/boringssl/src/crypto/cpu-arm-linux.h
++FILE: ../../../third_party/boringssl/src/crypto/cpu-arm-linux_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/bn/div_extra.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/bn/gcd_extra.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/felem.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/make_ec_scalar_base_mult_tests.go
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/make_p256-x86_64-table.go
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/make_p256-x86_64-tests.go
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/scalar.c
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/ec/simple_mul.c
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/md5/internal.h
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/md5/md5_test.cc
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/sha/internal.h
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/sha/sha_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/tls/internal.h
++FILE: ../../../third_party/boringssl/src/crypto/hrss/hrss.c
++FILE: ../../../third_party/boringssl/src/crypto/hrss/hrss_test.cc
++FILE: ../../../third_party/boringssl/src/crypto/hrss/internal.h
++FILE: ../../../third_party/boringssl/src/crypto/impl_dispatch_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/pem/pem_test.cc
++FILE: ../../../third_party/boringssl/src/crypto/rand_extra/rand_test.cc
+ FILE: ../../../third_party/boringssl/src/crypto/self_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_kas_test.cc
+-FILE: ../../../third_party/boringssl/src/fipstools/cavp_tlskdf_test.cc
++FILE: ../../../third_party/boringssl/src/crypto/stack/stack_test.cc
++FILE: ../../../third_party/boringssl/src/crypto/x509v3/internal.h
+ FILE: ../../../third_party/boringssl/src/include/openssl/e_os2.h
++FILE: ../../../third_party/boringssl/src/include/openssl/hrss.h
+ FILE: ../../../third_party/boringssl/src/ssl/handoff.cc
++FILE: ../../../third_party/boringssl/src/third_party/sike/sike_test.cc
++FILE: ../../../third_party/boringssl/src/util/ar/ar_test.go
+ FILE: ../../../third_party/boringssl/src/util/check_filenames.go
+ FILE: ../../../third_party/boringssl/src/util/convert_wycheproof.go
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_kas_test.cc
++FILE: ../../../third_party/boringssl/src/util/fipstools/cavp/cavp_tlskdf_test.cc
++FILE: ../../../third_party/boringssl/src/util/godeps.go
++FILE: ../../../third_party/boringssl/src/util/make_prefix_headers.go
++FILE: ../../../third_party/boringssl/src/util/read_symbols.go
++FILE: ../../../third_party/boringssl/src/util/testresult/testresult.go
+ ----------------------------------------------------------------------------------------------------
+ Copyright (c) 2018, Google Inc.
+ 
+@@ -5647,6 +5726,33 @@ in the file LICENSE in the source distribution or at
+ https://www.openssl.org/source/license.html
+ ====================================================================================================
+ 
++====================================================================================================
++LIBRARY: boringssl
++ORIGIN: ../../../third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c
++TYPE: LicenseType.unknown
++FILE: ../../../third_party/boringssl/src/crypto/fipsmodule/fips_shared_support.c
++FILE: ../../../third_party/boringssl/src/crypto/siphash/siphash.c
++FILE: ../../../third_party/boringssl/src/crypto/siphash/siphash_test.cc
++FILE: ../../../third_party/boringssl/src/decrepit/blowfish/blowfish_test.cc
++FILE: ../../../third_party/boringssl/src/decrepit/cast/cast_test.cc
++FILE: ../../../third_party/boringssl/src/include/openssl/siphash.h
++FILE: ../../../third_party/boringssl/src/util/fipstools/acvp/modulewrapper/modulewrapper.cc
++----------------------------------------------------------------------------------------------------
++Copyright (c) 2019, Google Inc.
++
++Permission to use, copy, modify, and/or distribute this software for any
++purpose with or without fee is hereby granted, provided that the above
++copyright notice and this permission notice appear in all copies.
++
++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++====================================================================================================
++
+ ====================================================================================================
+ LIBRARY: boringssl
+ ORIGIN: ../../../third_party/boringssl/src/crypto/fipsmodule/modes/cbc.c
+@@ -5880,6 +5986,27 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ OF THE POSSIBILITY OF SUCH DAMAGE.
+ ====================================================================================================
+ 
++====================================================================================================
++LIBRARY: boringssl
++ORIGIN: ../../../third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S
++TYPE: LicenseType.unknown
++FILE: ../../../third_party/boringssl/src/crypto/hrss/asm/poly_rq_mul.S
++----------------------------------------------------------------------------------------------------
++Copyright (c) 2017, the HRSS authors.
++
++Permission to use, copy, modify, and/or distribute this software for any
++purpose with or without fee is hereby granted, provided that the above
++copyright notice and this permission notice appear in all copies.
++
++THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
++SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
++OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
++CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++====================================================================================================
++
+ ====================================================================================================
+ LIBRARY: boringssl
+ ORIGIN: ../../../third_party/boringssl/src/crypto/pem/pem_all.c
+@@ -6620,6 +6747,10 @@ LIBRARY: boringssl
+ ORIGIN: ../../../third_party/boringssl/src/third_party/fiat/LICENSE
+ TYPE: LicenseType.mit
+ FILE: ../../../third_party/boringssl/src/third_party/fiat/METADATA
++FILE: ../../../third_party/boringssl/src/third_party/fiat/curve25519_32.h
++FILE: ../../../third_party/boringssl/src/third_party/fiat/curve25519_64.h
++FILE: ../../../third_party/boringssl/src/third_party/fiat/p256_32.h
++FILE: ../../../third_party/boringssl/src/third_party/fiat/p256_64.h
+ ----------------------------------------------------------------------------------------------------
+ The MIT License (MIT)
+ 
+@@ -6705,17 +6836,17 @@ SOFTWARE.
+ LIBRARY: boringssl
+ ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/LICENSE
+ TYPE: LicenseType.bsd
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/CHANGES
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/CONTRIBUTORS
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/METADATA
++FILE: ../../../third_party/boringssl/src/third_party/googletest/cmake/Config.cmake.in
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/cmake/gtest.pc.in
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/cmake/gtest_main.pc.in
++FILE: ../../../third_party/boringssl/src/third_party/googletest/cmake/libgtest.la.in
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/codegear/gtest.cbproj
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/codegear/gtest.groupproj
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/codegear/gtest_main.cbproj
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/codegear/gtest_unittest.cbproj
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-param-test.h
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-param-test.h.pump
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-test-part.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-filepath.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/msvc/2010/gtest-md.sln
+@@ -6823,10 +6954,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+ ====================================================================================================
+ LIBRARY: boringssl
+-ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-printers.h
++ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-matchers.h
+ TYPE: LicenseType.bsd
++FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-matchers.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-printers.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-spi.h
++FILE: ../../../third_party/boringssl/src/third_party/googletest/src/gtest-matchers.cc
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/src/gtest-printers.cc
+ ----------------------------------------------------------------------------------------------------
+ Copyright 2007, Google Inc.
+@@ -6995,47 +7128,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+ ====================================================================================================
+ LIBRARY: boringssl
+-ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-linked_ptr.h
+-TYPE: LicenseType.bsd
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-linked_ptr.h
+-----------------------------------------------------------------------------------------------------
+-Copyright 2003 Google Inc.
+-All rights reserved.
+-
+-Redistribution and use in source and binary forms, with or without
+-modification, are permitted provided that the following conditions are
+-met:
+-
+-    * Redistributions of source code must retain the above copyright
+-notice, this list of conditions and the following disclaimer.
+-    * Redistributions in binary form must reproduce the above
+-copyright notice, this list of conditions and the following disclaimer
+-in the documentation and/or other materials provided with the
+-distribution.
+-    * Neither the name of Google Inc. nor the names of its
+-contributors may be used to endorse or promote products derived from
+-this software without specific prior written permission.
+-
+-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-====================================================================================================
+-
+-====================================================================================================
+-LIBRARY: boringssl
+-ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-param-util-generated.h
++ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-param-util.h
+ TYPE: LicenseType.bsd
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/gtest-typed-test.h
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-param-util-generated.h
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-param-util-generated.h.pump
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-param-util.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-type-util.h
+ FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-type-util.h.pump
+@@ -7077,13 +7172,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+ ====================================================================================================
+ LIBRARY: boringssl
+-ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-tuple.h
++ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/samples/sample10_unittest.cc
+ TYPE: LicenseType.bsd
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-tuple.h
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/include/gtest/internal/gtest-tuple.h.pump
++FILE: ../../../third_party/boringssl/src/third_party/googletest/samples/sample10_unittest.cc
++FILE: ../../../third_party/boringssl/src/third_party/googletest/samples/sample9_unittest.cc
+ ----------------------------------------------------------------------------------------------------
+-Copyright 2009 Google Inc.
+-All Rights Reserved.
++Copyright 2009 Google Inc. All Rights Reserved.
+ 
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+@@ -7114,38 +7208,39 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ 
+ ====================================================================================================
+ LIBRARY: boringssl
+-ORIGIN: ../../../third_party/boringssl/src/third_party/googletest/samples/sample10_unittest.cc
+-TYPE: LicenseType.bsd
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/samples/sample10_unittest.cc
+-FILE: ../../../third_party/boringssl/src/third_party/googletest/samples/sample9_unittest.cc
++ORIGIN: ../../../third_party/boringssl/src/third_party/sike/LICENSE
++TYPE: LicenseType.mit
++FILE: ../../../third_party/boringssl/src/third_party/sike/asm/fp_generic.c
++FILE: ../../../third_party/boringssl/src/third_party/sike/curve_params.c
++FILE: ../../../third_party/boringssl/src/third_party/sike/fpx.c
++FILE: ../../../third_party/boringssl/src/third_party/sike/fpx.h
++FILE: ../../../third_party/boringssl/src/third_party/sike/isogeny.c
++FILE: ../../../third_party/boringssl/src/third_party/sike/isogeny.h
++FILE: ../../../third_party/boringssl/src/third_party/sike/sike.c
++FILE: ../../../third_party/boringssl/src/third_party/sike/sike.h
++FILE: ../../../third_party/boringssl/src/third_party/sike/utils.h
+ ----------------------------------------------------------------------------------------------------
+-Copyright 2009 Google Inc. All Rights Reserved.
++MIT License
+ 
+-Redistribution and use in source and binary forms, with or without
+-modification, are permitted provided that the following conditions are
+-met:
++Copyright (c) Microsoft Corporation. All rights reserved.
+ 
+-    * Redistributions of source code must retain the above copyright
+-notice, this list of conditions and the following disclaimer.
+-    * Redistributions in binary form must reproduce the above
+-copyright notice, this list of conditions and the following disclaimer
+-in the documentation and/or other materials provided with the
+-distribution.
+-    * Neither the name of Google Inc. nor the names of its
+-contributors may be used to endorse or promote products derived from
+-this software without specific prior written permission.
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
+ 
+-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++SOFTWARE
+ ====================================================================================================
+ 
+ ====================================================================================================
+@@ -7155,8 +7250,11 @@ TYPE: LicenseType.unknown
+ FILE: ../../../third_party/boringssl/ios-aarch64/crypto/chacha/chacha-armv8.S
+ FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/aesv8-armx64.S
+ FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/armv8-mont.S
++FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
+ FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/ghashv8-armx64.S
+ FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/sha1-armv8.S
++FILE: ../../../third_party/boringssl/ios-aarch64/crypto/fipsmodule/vpaes-armv8.S
++FILE: ../../../third_party/boringssl/ios-aarch64/crypto/third_party/sike/asm/fp-armv8.S
+ FILE: ../../../third_party/boringssl/ios-arm/crypto/chacha/chacha-armv4.S
+ FILE: ../../../third_party/boringssl/ios-arm/crypto/fipsmodule/aesv8-armx32.S
+ FILE: ../../../third_party/boringssl/ios-arm/crypto/fipsmodule/armv4-mont.S
+@@ -7166,8 +7264,11 @@ FILE: ../../../third_party/boringssl/ios-arm/crypto/fipsmodule/sha1-armv4-large.
+ FILE: ../../../third_party/boringssl/linux-aarch64/crypto/chacha/chacha-armv8.S
+ FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
+ FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/armv8-mont.S
++FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
+ FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
+ FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
++FILE: ../../../third_party/boringssl/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
++FILE: ../../../third_party/boringssl/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
+ FILE: ../../../third_party/boringssl/linux-arm/crypto/chacha/chacha-armv4.S
+ FILE: ../../../third_party/boringssl/linux-arm/crypto/fipsmodule/aesv8-armx32.S
+ FILE: ../../../third_party/boringssl/linux-arm/crypto/fipsmodule/armv4-mont.S
+@@ -7181,6 +7282,7 @@ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/aes-586.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/aesni-x86.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/bn-586.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/co-586.S
++FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/ghash-x86.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/md5-586.S
+ FILE: ../../../third_party/boringssl/linux-x86/crypto/fipsmodule/sha1-586.S
+@@ -7194,10 +7296,11 @@ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/cipher_extra/chacha20_p
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
+-FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/bsaes-x86_64.S
++FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
++FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
+@@ -7206,11 +7309,13 @@ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/sha512-x86_6
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
+ FILE: ../../../third_party/boringssl/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
++FILE: ../../../third_party/boringssl/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/chacha/chacha-x86.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/aes-586.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/aesni-x86.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/bn-586.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/co-586.S
++FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/ghash-ssse3-x86.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/ghash-x86.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/md5-586.S
+ FILE: ../../../third_party/boringssl/mac-x86/crypto/fipsmodule/sha1-586.S
+@@ -7224,10 +7329,11 @@ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/cipher_extra/chacha20_pol
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/aes-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/aesni-x86_64.S
+-FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/bsaes-x86_64.S
++FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/ghash-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/md5-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
++FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/rdrand-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/rsaz-avx2.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha1-x86_64.S
+@@ -7236,11 +7342,13 @@ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/sha512-x86_64.
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/vpaes-x86_64.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/x86_64-mont.S
+ FILE: ../../../third_party/boringssl/mac-x86_64/crypto/fipsmodule/x86_64-mont5.S
++FILE: ../../../third_party/boringssl/mac-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
+ FILE: ../../../third_party/boringssl/win-x86/crypto/chacha/chacha-x86.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/aes-586.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/aesni-x86.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/bn-586.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/co-586.asm
++FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/ghash-ssse3-x86.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/ghash-x86.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/md5-586.asm
+ FILE: ../../../third_party/boringssl/win-x86/crypto/fipsmodule/sha1-586.asm
+@@ -7254,10 +7362,11 @@ FILE: ../../../third_party/boringssl/win-x86_64/crypto/cipher_extra/chacha20_pol
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/aes-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/aesni-x86_64.asm
+-FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/bsaes-x86_64.asm
++FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/ghash-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/md5-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/p256-x86_64-asm.asm
++FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/rdrand-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/rsaz-avx2.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/sha1-x86_64.asm
+@@ -7266,6 +7375,7 @@ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/sha512-x86_64.
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/vpaes-x86_64.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/x86_64-mont.asm
+ FILE: ../../../third_party/boringssl/win-x86_64/crypto/fipsmodule/x86_64-mont5.asm
++FILE: ../../../third_party/boringssl/win-x86_64/crypto/third_party/sike/asm/fp-x86_64.asm
+ ----------------------------------------------------------------------------------------------------
+ <THIS BLOCK INTENTIONALLY LEFT BLANK>
+ ====================================================================================================
+@@ -23186,4 +23296,4 @@ freely, subject to the following restrictions:
+    misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+ ====================================================================================================
+-Total license count: 361
++Total license count: 362
+diff --git a/tools/licenses/lib/main.dart b/tools/licenses/lib/main.dart
+index 19117b13b4fc..3088076b8661 100644
+--- a/tools/licenses/lib/main.dart
++++ b/tools/licenses/lib/main.dart
+@@ -1889,7 +1889,7 @@ class _RepositoryBoringSSLDirectory extends _RepositoryDirectory {
+   _RepositoryDirectory createSubdirectory(fs.Directory entry) {
+     if (entry.name == 'src')
+       return _RepositoryBoringSSLSourceDirectory(this, entry);
+-    return super.createSubdirectory(entry);
++    return _RepositoryBoringSSLDirectory(this, entry);
+   }
+ }
+ 
diff --git a/tools/patches/flutter-engine/a61c775db81ef2a389d5aee6236176362b082d58.patch b/tools/patches/flutter-engine/a61c775db81ef2a389d5aee6236176362b082d58.patch
new file mode 100644
index 0000000..8e96c95
--- /dev/null
+++ b/tools/patches/flutter-engine/a61c775db81ef2a389d5aee6236176362b082d58.patch
@@ -0,0 +1,613 @@
+diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc
+index 2db8ae2c7cd5..dcbe05f66691 100644
+--- a/runtime/dart_isolate.cc
++++ b/runtime/dart_isolate.cc
+@@ -32,7 +32,6 @@ namespace flutter {
+ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
+     const Settings& settings,
+     fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-    fml::RefPtr<const DartSnapshot> shared_snapshot,
+     TaskRunners task_runners,
+     std::unique_ptr<Window> window,
+     fml::WeakPtr<IOManager> io_manager,
+@@ -58,7 +57,6 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
+       std::shared_ptr<DartIsolate>(new DartIsolate(
+           settings,                     // settings
+           std::move(isolate_snapshot),  // isolate snapshot
+-          std::move(shared_snapshot),   // shared snapshot
+           task_runners,                 // task runners
+           std::move(io_manager),        // IO manager
+           std::move(image_decoder),     // Image Decoder
+@@ -102,7 +100,6 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
+ 
+ DartIsolate::DartIsolate(const Settings& settings,
+                          fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-                         fml::RefPtr<const DartSnapshot> shared_snapshot,
+                          TaskRunners task_runners,
+                          fml::WeakPtr<IOManager> io_manager,
+                          fml::WeakPtr<ImageDecoder> image_decoder,
+@@ -123,7 +120,6 @@ DartIsolate::DartIsolate(const Settings& settings,
+                   DartVMRef::GetIsolateNameServer()),
+       settings_(settings),
+       isolate_snapshot_(std::move(isolate_snapshot)),
+-      shared_snapshot_(std::move(shared_snapshot)),
+       child_isolate_preparer_(std::move(child_isolate_preparer)),
+       isolate_create_callback_(isolate_create_callback),
+       isolate_shutdown_callback_(isolate_shutdown_callback) {
+@@ -592,7 +588,6 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
+       DartIsolate::CreateRootIsolate(
+           vm_data->GetSettings(),         // settings
+           vm_data->GetIsolateSnapshot(),  // isolate snapshot
+-          vm_data->GetSharedSnapshot(),   // shared snapshot
+           null_task_runners,              // task runners
+           nullptr,                        // window
+           {},                             // IO Manager
+@@ -705,7 +700,6 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
+         std::shared_ptr<DartIsolate>(new DartIsolate(
+             (*raw_embedder_isolate)->GetSettings(),         // settings
+             (*raw_embedder_isolate)->GetIsolateSnapshot(),  // isolate_snapshot
+-            (*raw_embedder_isolate)->GetSharedSnapshot(),   // shared_snapshot
+             null_task_runners,                              // task_runners
+             fml::WeakPtr<IOManager>{},                      // io_manager
+             fml::WeakPtr<ImageDecoder>{},                   // io_manager
+@@ -724,9 +718,7 @@ DartIsolate::CreateDartVMAndEmbedderObjectPair(
+       advisory_script_uri,         //
+       advisory_script_entrypoint,  //
+       (*embedder_isolate)->GetIsolateSnapshot()->GetDataMapping(),
+-      (*embedder_isolate)->GetIsolateSnapshot()->GetInstructionsMapping(),
+-      (*embedder_isolate)->GetSharedSnapshot()->GetDataMapping(),
+-      (*embedder_isolate)->GetSharedSnapshot()->GetInstructionsMapping(), flags,
++      (*embedder_isolate)->GetIsolateSnapshot()->GetInstructionsMapping(), flags,
+       embedder_isolate.get(),  // isolate_group_data
+       embedder_isolate.get(),  // isolate_group
+       error);
+@@ -791,10 +783,6 @@ fml::RefPtr<const DartSnapshot> DartIsolate::GetIsolateSnapshot() const {
+   return isolate_snapshot_;
+ }
+ 
+-fml::RefPtr<const DartSnapshot> DartIsolate::GetSharedSnapshot() const {
+-  return shared_snapshot_;
+-}
+-
+ std::weak_ptr<DartIsolate> DartIsolate::GetWeakIsolatePtr() {
+   return std::static_pointer_cast<DartIsolate>(shared_from_this());
+ }
+diff --git a/runtime/dart_isolate.h b/runtime/dart_isolate.h
+index e7ab9b30243c..2abaa11fe011 100644
+--- a/runtime/dart_isolate.h
++++ b/runtime/dart_isolate.h
+@@ -143,10 +143,6 @@ class DartIsolate : public UIDartState {
+   ///                                         usually obtained from the
+   ///                                         DartVMData associated with the
+   ///                                         running Dart VM instance.
+-  /// @param[in]  shared_snapshot             The shared snapshot. This is
+-  ///                                         usually obtained from the
+-  ///                                         DartVMData associated with the
+-  ///                                         running Dart VM instance.
+   /// @param[in]  task_runners                The task runners used by the
+   ///                                         isolate. Via UI bindings, the
+   ///                                         isolate will use the IO task
+@@ -192,7 +188,6 @@ class DartIsolate : public UIDartState {
+   static std::weak_ptr<DartIsolate> CreateRootIsolate(
+       const Settings& settings,
+       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<const DartSnapshot> shared_snapshot,
+       TaskRunners task_runners,
+       std::unique_ptr<Window> window,
+       fml::WeakPtr<IOManager> io_manager,
+@@ -385,14 +380,6 @@ class DartIsolate : public UIDartState {
+   ///
+   fml::RefPtr<const DartSnapshot> GetIsolateSnapshot() const;
+ 
+-  //----------------------------------------------------------------------------
+-  /// @brief      Get the shared snapshot used to launch this isolate. This is
+-  ///             referenced by any child isolates launched by the root isolate.
+-  ///
+-  /// @return     The shared snapshot.
+-  ///
+-  fml::RefPtr<const DartSnapshot> GetSharedSnapshot() const;
+-
+   //----------------------------------------------------------------------------
+   /// @brief      A weak pointer to the Dart isolate instance. This instance may
+   ///             only be used on the task runner that created the root isolate.
+@@ -428,7 +415,6 @@ class DartIsolate : public UIDartState {
+   Phase phase_ = Phase::Unknown;
+   const Settings settings_;
+   const fml::RefPtr<const DartSnapshot> isolate_snapshot_;
+-  const fml::RefPtr<const DartSnapshot> shared_snapshot_;
+   std::vector<std::shared_ptr<const fml::Mapping>> kernel_buffers_;
+   std::vector<std::unique_ptr<AutoFireClosure>> shutdown_callbacks_;
+   ChildIsolatePreparer child_isolate_preparer_ = nullptr;
+@@ -438,7 +424,6 @@ class DartIsolate : public UIDartState {
+ 
+   DartIsolate(const Settings& settings,
+               fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-              fml::RefPtr<const DartSnapshot> shared_snapshot,
+               TaskRunners task_runners,
+               fml::WeakPtr<IOManager> io_manager,
+               fml::WeakPtr<ImageDecoder> image_decoder,
+diff --git a/runtime/dart_isolate_unittests.cc b/runtime/dart_isolate_unittests.cc
+index 83a140737324..4d860f82d781 100644
+--- a/runtime/dart_isolate_unittests.cc
++++ b/runtime/dart_isolate_unittests.cc
+@@ -38,7 +38,6 @@ TEST_F(DartIsolateTest, RootIsolateCreationAndShutdown) {
+   auto weak_isolate = DartIsolate::CreateRootIsolate(
+       vm_data->GetSettings(),             // settings
+       vm_data->GetIsolateSnapshot(),      // isolate snapshot
+-      vm_data->GetSharedSnapshot(),       // shared snapshot
+       std::move(task_runners),            // task runners
+       nullptr,                            // window
+       {},                                 // io manager
+@@ -71,7 +70,6 @@ TEST_F(DartIsolateTest, IsolateShutdownCallbackIsInIsolateScope) {
+   auto weak_isolate = DartIsolate::CreateRootIsolate(
+       vm_data->GetSettings(),             // settings
+       vm_data->GetIsolateSnapshot(),      // isolate snapshot
+-      vm_data->GetSharedSnapshot(),       // shared snapshot
+       std::move(task_runners),            // task runners
+       nullptr,                            // window
+       {},                                 // io manager
+@@ -181,7 +179,6 @@ static void RunDartCodeInIsolate(DartVMRef& vm_ref,
+   auto weak_isolate = DartIsolate::CreateRootIsolate(
+       vm_data->GetSettings(),             // settings
+       vm_data->GetIsolateSnapshot(),      // isolate snapshot
+-      vm_data->GetSharedSnapshot(),       // shared snapshot
+       std::move(task_runners),            // task runners
+       nullptr,                            // window
+       {},                                 // io manager
+diff --git a/runtime/dart_lifecycle_unittests.cc b/runtime/dart_lifecycle_unittests.cc
+index 7a607b7be26f..7a35c96167e5 100644
+--- a/runtime/dart_lifecycle_unittests.cc
++++ b/runtime/dart_lifecycle_unittests.cc
+@@ -53,7 +53,6 @@ static std::shared_ptr<DartIsolate> CreateAndRunRootIsolate(
+   auto isolate_weak = DartIsolate::CreateRootIsolate(
+       vm.GetSettings(),                   // settings
+       vm.GetIsolateSnapshot(),            // isolate_snapshot
+-      vm.GetSharedSnapshot(),             // shared_snapshot
+       runners,                            // task_runners
+       {},                                 // window
+       {},                                 // io_manager
+diff --git a/runtime/dart_snapshot.cc b/runtime/dart_snapshot.cc
+index acebcd3493d8..a5df79bb136c 100644
+--- a/runtime/dart_snapshot.cc
++++ b/runtime/dart_snapshot.cc
+@@ -181,10 +181,6 @@ fml::RefPtr<DartSnapshot> DartSnapshot::IsolateSnapshotFromSettings(
+   return nullptr;
+ }
+ 
+-fml::RefPtr<DartSnapshot> DartSnapshot::Empty() {
+-  return fml::MakeRefCounted<DartSnapshot>(nullptr, nullptr);
+-}
+-
+ DartSnapshot::DartSnapshot(std::shared_ptr<const fml::Mapping> data,
+                            std::shared_ptr<const fml::Mapping> instructions)
+     : data_(std::move(data)), instructions_(std::move(instructions)) {}
+diff --git a/runtime/dart_snapshot.h b/runtime/dart_snapshot.h
+index 162710ff2a6a..97038aac4aee 100644
+--- a/runtime/dart_snapshot.h
++++ b/runtime/dart_snapshot.h
+@@ -102,17 +102,6 @@ class DartSnapshot : public fml::RefCountedThreadSafe<DartSnapshot> {
+   static fml::RefPtr<DartSnapshot> IsolateSnapshotFromSettings(
+       const Settings& settings);
+ 
+-  //----------------------------------------------------------------------------
+-  /// @brief      An empty an invalid snapshot. This is used as a placeholder
+-  ///             for certain optional snapshots.
+-  ///
+-  /// @bug        Now that shared snapshots are no longer required, consider
+-  ///             removing this constructor.
+-  ///
+-  /// @return     An invalid empty snapshot.
+-  ///
+-  static fml::RefPtr<DartSnapshot> Empty();
+-
+   //----------------------------------------------------------------------------
+   /// @brief      Determines if this snapshot contains a heap component. Since
+   ///             the instructions component is optional, the method does not
+diff --git a/runtime/dart_vm.cc b/runtime/dart_vm.cc
+index 37f8e690f737..0c18ba8da702 100644
+--- a/runtime/dart_vm.cc
++++ b/runtime/dart_vm.cc
+@@ -232,12 +232,10 @@ std::shared_ptr<DartVM> DartVM::Create(
+     Settings settings,
+     fml::RefPtr<DartSnapshot> vm_snapshot,
+     fml::RefPtr<DartSnapshot> isolate_snapshot,
+-    fml::RefPtr<DartSnapshot> shared_snapshot,
+     std::shared_ptr<IsolateNameServer> isolate_name_server) {
+   auto vm_data = DartVMData::Create(settings,                     //
+                                     std::move(vm_snapshot),       //
+-                                    std::move(isolate_snapshot),  //
+-                                    std::move(shared_snapshot)    //
++                                    std::move(isolate_snapshot)   //
+   );
+ 
+   if (!vm_data) {
+diff --git a/runtime/dart_vm.h b/runtime/dart_vm.h
+index 40b8dc4a242e..ac84fe77020d 100644
+--- a/runtime/dart_vm.h
++++ b/runtime/dart_vm.h
+@@ -162,7 +162,6 @@ class DartVM {
+       Settings settings,
+       fml::RefPtr<DartSnapshot> vm_snapshot,
+       fml::RefPtr<DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<DartSnapshot> shared_snapshot,
+       std::shared_ptr<IsolateNameServer> isolate_name_server);
+ 
+   DartVM(std::shared_ptr<const DartVMData> data,
+diff --git a/runtime/dart_vm_data.cc b/runtime/dart_vm_data.cc
+index e14c998daa74..b93d9ba9ad03 100644
+--- a/runtime/dart_vm_data.cc
++++ b/runtime/dart_vm_data.cc
+@@ -9,8 +9,7 @@ namespace flutter {
+ std::shared_ptr<const DartVMData> DartVMData::Create(
+     Settings settings,
+     fml::RefPtr<DartSnapshot> vm_snapshot,
+-    fml::RefPtr<DartSnapshot> isolate_snapshot,
+-    fml::RefPtr<DartSnapshot> shared_snapshot) {
++    fml::RefPtr<DartSnapshot> isolate_snapshot) {
+   if (!vm_snapshot || !vm_snapshot->IsValid()) {
+     // Caller did not provide a valid VM snapshot. Attempt to infer one
+     // from the settings.
+@@ -33,30 +32,19 @@ std::shared_ptr<const DartVMData> DartVMData::Create(
+     }
+   }
+ 
+-  if (!shared_snapshot || !shared_snapshot->IsValid()) {
+-    shared_snapshot = DartSnapshot::Empty();
+-    if (!shared_snapshot) {
+-      FML_LOG(ERROR) << "Shared snapshot invalid.";
+-      return {};
+-    }
+-  }
+-
+   return std::shared_ptr<const DartVMData>(new DartVMData(
+       std::move(settings),          //
+       std::move(vm_snapshot),       //
+-      std::move(isolate_snapshot),  //
+-      std::move(shared_snapshot)    //
++      std::move(isolate_snapshot)   //
+       ));
+ }
+ 
+ DartVMData::DartVMData(Settings settings,
+                        fml::RefPtr<const DartSnapshot> vm_snapshot,
+-                       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-                       fml::RefPtr<const DartSnapshot> shared_snapshot)
++                       fml::RefPtr<const DartSnapshot> isolate_snapshot)
+     : settings_(settings),
+       vm_snapshot_(vm_snapshot),
+-      isolate_snapshot_(isolate_snapshot),
+-      shared_snapshot_(shared_snapshot) {}
++      isolate_snapshot_(isolate_snapshot) {}
+ 
+ DartVMData::~DartVMData() = default;
+ 
+@@ -72,8 +60,4 @@ fml::RefPtr<const DartSnapshot> DartVMData::GetIsolateSnapshot() const {
+   return isolate_snapshot_;
+ }
+ 
+-fml::RefPtr<const DartSnapshot> DartVMData::GetSharedSnapshot() const {
+-  return shared_snapshot_;
+-}
+-
+ }  // namespace flutter
+diff --git a/runtime/dart_vm_data.h b/runtime/dart_vm_data.h
+index 95c4565e2ef7..0f054bf55f3d 100644
+--- a/runtime/dart_vm_data.h
++++ b/runtime/dart_vm_data.h
+@@ -15,8 +15,7 @@ class DartVMData {
+   static std::shared_ptr<const DartVMData> Create(
+       Settings settings,
+       fml::RefPtr<DartSnapshot> vm_snapshot,
+-      fml::RefPtr<DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<DartSnapshot> shared_snapshot);
++      fml::RefPtr<DartSnapshot> isolate_snapshot);
+ 
+   ~DartVMData();
+ 
+@@ -26,18 +25,14 @@ class DartVMData {
+ 
+   fml::RefPtr<const DartSnapshot> GetIsolateSnapshot() const;
+ 
+-  fml::RefPtr<const DartSnapshot> GetSharedSnapshot() const;
+-
+  private:
+   const Settings settings_;
+   const fml::RefPtr<const DartSnapshot> vm_snapshot_;
+   const fml::RefPtr<const DartSnapshot> isolate_snapshot_;
+-  const fml::RefPtr<const DartSnapshot> shared_snapshot_;
+ 
+   DartVMData(Settings settings,
+              fml::RefPtr<const DartSnapshot> vm_snapshot,
+-             fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-             fml::RefPtr<const DartSnapshot> shared_snapshot);
++             fml::RefPtr<const DartSnapshot> isolate_snapshot);
+ 
+   FML_DISALLOW_COPY_AND_ASSIGN(DartVMData);
+ };
+diff --git a/runtime/dart_vm_lifecycle.cc b/runtime/dart_vm_lifecycle.cc
+index 717a0546a280..41a3da606abb 100644
+--- a/runtime/dart_vm_lifecycle.cc
++++ b/runtime/dart_vm_lifecycle.cc
+@@ -43,8 +43,7 @@ DartVMRef::~DartVMRef() {
+ 
+ DartVMRef DartVMRef::Create(Settings settings,
+                             fml::RefPtr<DartSnapshot> vm_snapshot,
+-                            fml::RefPtr<DartSnapshot> isolate_snapshot,
+-                            fml::RefPtr<DartSnapshot> shared_snapshot) {
++                            fml::RefPtr<DartSnapshot> isolate_snapshot) {
+   std::scoped_lock lifecycle_lock(gVMMutex);
+ 
+   if (!settings.leak_vm) {
+@@ -78,7 +77,6 @@ DartVMRef DartVMRef::Create(Settings settings,
+   auto vm = DartVM::Create(std::move(settings),          //
+                            std::move(vm_snapshot),       //
+                            std::move(isolate_snapshot),  //
+-                           std::move(shared_snapshot),   //
+                            isolate_name_server           //
+   );
+ 
+diff --git a/runtime/dart_vm_lifecycle.h b/runtime/dart_vm_lifecycle.h
+index 5ce6cf7a5777..d89b6d7cb43d 100644
+--- a/runtime/dart_vm_lifecycle.h
++++ b/runtime/dart_vm_lifecycle.h
+@@ -29,8 +29,7 @@ class DartVMRef {
+   FML_WARN_UNUSED_RESULT
+   static DartVMRef Create(Settings settings,
+                           fml::RefPtr<DartSnapshot> vm_snapshot = nullptr,
+-                          fml::RefPtr<DartSnapshot> isolate_snapshot = nullptr,
+-                          fml::RefPtr<DartSnapshot> shared_snapshot = nullptr);
++                          fml::RefPtr<DartSnapshot> isolate_snapshot = nullptr);
+ 
+   DartVMRef(DartVMRef&&);
+ 
+diff --git a/runtime/runtime_controller.cc b/runtime/runtime_controller.cc
+index 61415ec4124c..a63843fedf66 100644
+--- a/runtime/runtime_controller.cc
++++ b/runtime/runtime_controller.cc
+@@ -18,7 +18,6 @@ RuntimeController::RuntimeController(
+     RuntimeDelegate& p_client,
+     DartVM* p_vm,
+     fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
+-    fml::RefPtr<const DartSnapshot> p_shared_snapshot,
+     TaskRunners p_task_runners,
+     fml::WeakPtr<IOManager> p_io_manager,
+     fml::WeakPtr<ImageDecoder> p_image_decoder,
+@@ -31,7 +30,6 @@ RuntimeController::RuntimeController(
+     : RuntimeController(p_client,
+                         p_vm,
+                         std::move(p_isolate_snapshot),
+-                        std::move(p_shared_snapshot),
+                         std::move(p_task_runners),
+                         std::move(p_io_manager),
+                         std::move(p_image_decoder),
+@@ -47,7 +45,6 @@ RuntimeController::RuntimeController(
+     RuntimeDelegate& p_client,
+     DartVM* p_vm,
+     fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
+-    fml::RefPtr<const DartSnapshot> p_shared_snapshot,
+     TaskRunners p_task_runners,
+     fml::WeakPtr<IOManager> p_io_manager,
+     fml::WeakPtr<ImageDecoder> p_image_decoder,
+@@ -61,7 +58,6 @@ RuntimeController::RuntimeController(
+     : client_(p_client),
+       vm_(p_vm),
+       isolate_snapshot_(std::move(p_isolate_snapshot)),
+-      shared_snapshot_(std::move(p_shared_snapshot)),
+       task_runners_(p_task_runners),
+       io_manager_(p_io_manager),
+       image_decoder_(p_image_decoder),
+@@ -78,7 +74,6 @@ RuntimeController::RuntimeController(
+   auto strong_root_isolate =
+       DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(),  //
+                                      isolate_snapshot_,                //
+-                                     shared_snapshot_,                 //
+                                      task_runners_,                    //
+                                      std::make_unique<Window>(this),   //
+                                      io_manager_,                      //
+@@ -139,7 +134,6 @@ std::unique_ptr<RuntimeController> RuntimeController::Clone() const {
+       client_,                      //
+       vm_,                          //
+       isolate_snapshot_,            //
+-      shared_snapshot_,             //
+       task_runners_,                //
+       io_manager_,                  //
+       image_decoder_,               //
+diff --git a/runtime/runtime_controller.h b/runtime/runtime_controller.h
+index 665f0e17dbb5..98a87f6f5d09 100644
+--- a/runtime/runtime_controller.h
++++ b/runtime/runtime_controller.h
+@@ -32,7 +32,6 @@ class RuntimeController final : public WindowClient {
+       RuntimeDelegate& client,
+       DartVM* vm,
+       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<const DartSnapshot> shared_snapshot,
+       TaskRunners task_runners,
+       fml::WeakPtr<IOManager> io_manager,
+       fml::WeakPtr<ImageDecoder> iamge_decoder,
+@@ -128,7 +127,6 @@ class RuntimeController final : public WindowClient {
+   RuntimeDelegate& client_;
+   DartVM* const vm_;
+   fml::RefPtr<const DartSnapshot> isolate_snapshot_;
+-  fml::RefPtr<const DartSnapshot> shared_snapshot_;
+   TaskRunners task_runners_;
+   fml::WeakPtr<IOManager> io_manager_;
+   fml::WeakPtr<ImageDecoder> image_decoder_;
+@@ -146,7 +144,6 @@ class RuntimeController final : public WindowClient {
+       RuntimeDelegate& client,
+       DartVM* vm,
+       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<const DartSnapshot> shared_snapshot,
+       TaskRunners task_runners,
+       fml::WeakPtr<IOManager> io_manager,
+       fml::WeakPtr<ImageDecoder> image_decoder,
+diff --git a/shell/common/engine.cc b/shell/common/engine.cc
+index fd424a369eeb..7ad3a432a52c 100644
+--- a/shell/common/engine.cc
++++ b/shell/common/engine.cc
+@@ -39,7 +39,6 @@ Engine::Engine(Delegate& delegate,
+                const PointerDataDispatcherMaker& dispatcher_maker,
+                DartVM& vm,
+                fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-               fml::RefPtr<const DartSnapshot> shared_snapshot,
+                TaskRunners task_runners,
+                Settings settings,
+                std::unique_ptr<Animator> animator,
+@@ -61,7 +60,6 @@ Engine::Engine(Delegate& delegate,
+       *this,                                 // runtime delegate
+       &vm,                                   // VM
+       std::move(isolate_snapshot),           // isolate snapshot
+-      std::move(shared_snapshot),            // shared snapshot
+       task_runners_,                         // task runners
+       std::move(io_manager),                 // io manager
+       image_decoder_.GetWeakPtr(),           // image decoder
+diff --git a/shell/common/engine.h b/shell/common/engine.h
+index 2e4fd41964bb..dde92dbc6d26 100644
+--- a/shell/common/engine.h
++++ b/shell/common/engine.h
+@@ -249,8 +249,6 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
+   ///                                created when the engine is created. This
+   ///                                requires access to the isolate snapshot
+   ///                                upfront.
+-  /// @param[in]  shared_snapshot    The portion of the isolate snapshot shared
+-  ///                                among multiple isolates.
+   //  TODO(chinmaygarde): This is probably redundant now that the IO manager is
+   //  it's own object.
+   /// @param[in]  task_runners       The task runners used by the shell that
+@@ -276,7 +274,6 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
+          const PointerDataDispatcherMaker& dispatcher_maker,
+          DartVM& vm,
+          fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-         fml::RefPtr<const DartSnapshot> shared_snapshot,
+          TaskRunners task_runners,
+          Settings settings,
+          std::unique_ptr<Animator> animator,
+diff --git a/shell/common/shell.cc b/shell/common/shell.cc
+index bf185a6b3661..fbc2457d56bd 100644
+--- a/shell/common/shell.cc
++++ b/shell/common/shell.cc
+@@ -45,7 +45,6 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
+     TaskRunners task_runners,
+     Settings settings,
+     fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-    fml::RefPtr<const DartSnapshot> shared_snapshot,
+     Shell::CreateCallback<PlatformView> on_create_platform_view,
+     Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
+   if (!task_runners.IsValid()) {
+@@ -124,7 +123,6 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
+                          shell = shell.get(),                             //
+                          &dispatcher_maker,                               //
+                          isolate_snapshot = std::move(isolate_snapshot),  //
+-                         shared_snapshot = std::move(shared_snapshot),    //
+                          vsync_waiter = std::move(vsync_waiter),          //
+                          &weak_io_manager_future                          //
+   ]() mutable {
+@@ -141,7 +139,6 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
+             dispatcher_maker,             //
+             *shell->GetDartVM(),          //
+             std::move(isolate_snapshot),  //
+-            std::move(shared_snapshot),   //
+             task_runners,                 //
+             shell->GetSettings(),         //
+             std::move(animator),          //
+@@ -227,7 +224,6 @@ std::unique_ptr<Shell> Shell::Create(
+   return Shell::Create(std::move(task_runners),             //
+                        std::move(settings),                 //
+                        vm_data->GetIsolateSnapshot(),       // isolate snapshot
+-                       DartSnapshot::Empty(),               // shared snapshot
+                        std::move(on_create_platform_view),  //
+                        std::move(on_create_rasterizer),     //
+                        std::move(vm)                        //
+@@ -238,7 +234,6 @@ std::unique_ptr<Shell> Shell::Create(
+     TaskRunners task_runners,
+     Settings settings,
+     fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-    fml::RefPtr<const DartSnapshot> shared_snapshot,
+     Shell::CreateCallback<PlatformView> on_create_platform_view,
+     Shell::CreateCallback<Rasterizer> on_create_rasterizer,
+     DartVMRef vm) {
+@@ -262,7 +257,6 @@ std::unique_ptr<Shell> Shell::Create(
+                          task_runners = std::move(task_runners),          //
+                          settings,                                        //
+                          isolate_snapshot = std::move(isolate_snapshot),  //
+-                         shared_snapshot = std::move(shared_snapshot),    //
+                          on_create_platform_view,                         //
+                          on_create_rasterizer                             //
+   ]() mutable {
+@@ -270,7 +264,6 @@ std::unique_ptr<Shell> Shell::Create(
+                                             std::move(task_runners),      //
+                                             settings,                     //
+                                             std::move(isolate_snapshot),  //
+-                                            std::move(shared_snapshot),   //
+                                             on_create_platform_view,      //
+                                             on_create_rasterizer          //
+         );
+diff --git a/shell/common/shell.h b/shell/common/shell.h
+index e4ee6960389a..cc3ed8fdc448 100644
+--- a/shell/common/shell.h
++++ b/shell/common/shell.h
+@@ -139,9 +139,6 @@ class Shell final : public PlatformView::Delegate,
+   /// @param[in]  isolate_snapshot         A custom isolate snapshot. Takes
+   ///                                      precedence over any snapshots
+   ///                                      specified in the settings.
+-  /// @param[in]  shared_snapshot          A custom shared snapshot. Takes
+-  ///                                      precedence over any snapshots
+-  ///                                      specified in the settings.
+   /// @param[in]  on_create_platform_view  The callback that must return a
+   ///                                      platform view. This will be called on
+   ///                                      the platform task runner before this
+@@ -164,7 +161,6 @@ class Shell final : public PlatformView::Delegate,
+       TaskRunners task_runners,
+       Settings settings,
+       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<const DartSnapshot> shared_snapshot,
+       CreateCallback<PlatformView> on_create_platform_view,
+       CreateCallback<Rasterizer> on_create_rasterizer,
+       DartVMRef vm);
+@@ -375,7 +371,6 @@ class Shell final : public PlatformView::Delegate,
+       TaskRunners task_runners,
+       Settings settings,
+       fml::RefPtr<const DartSnapshot> isolate_snapshot,
+-      fml::RefPtr<const DartSnapshot> shared_snapshot,
+       Shell::CreateCallback<PlatformView> on_create_platform_view,
+       Shell::CreateCallback<Rasterizer> on_create_rasterizer);
+ 
+diff --git a/shell/platform/fuchsia/dart_runner/dart_component_controller.cc b/shell/platform/fuchsia/dart_runner/dart_component_controller.cc
+index 37cef7bce6f7..e5bd774fc4e3 100644
+--- a/shell/platform/fuchsia/dart_runner/dart_component_controller.cc
++++ b/shell/platform/fuchsia/dart_runner/dart_component_controller.cc
+@@ -314,8 +314,7 @@ bool DartComponentController::CreateIsolate(
+ 
+   isolate_ = Dart_CreateIsolateGroup(
+       url_.c_str(), label_.c_str(), isolate_snapshot_data,
+-      isolate_snapshot_instructions, nullptr /* shared_snapshot_data */,
+-      nullptr /* shared_snapshot_instructions */, nullptr /* flags */, state,
++      isolate_snapshot_instructions, nullptr /* flags */, state,
+       state, &error);
+   if (!isolate_) {
+     FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", error);
+diff --git a/shell/platform/fuchsia/dart_runner/service_isolate.cc b/shell/platform/fuchsia/dart_runner/service_isolate.cc
+index d22c4df286b6..40719ab81c94 100644
+--- a/shell/platform/fuchsia/dart_runner/service_isolate.cc
++++ b/shell/platform/fuchsia/dart_runner/service_isolate.cc
+@@ -107,8 +107,7 @@ Dart_Isolate CreateServiceIsolate(const char* uri,
+   Dart_Isolate isolate = Dart_CreateIsolateGroup(
+       uri, DART_VM_SERVICE_ISOLATE_NAME, mapped_isolate_snapshot_data.address(),
+       mapped_isolate_snapshot_instructions.address(),
+-      nullptr /* shared_snapshot_data */,
+-      nullptr /* shared_snapshot_instructions */, nullptr /* flags */, state,
++      nullptr /* flags */, state,
+       state, error);
+   if (!isolate) {
+     FX_LOGF(ERROR, LOG_TAG, "Dart_CreateIsolateGroup failed: %s", *error);
+diff --git a/shell/platform/fuchsia/flutter/engine.cc b/shell/platform/fuchsia/flutter/engine.cc
+index 75dbf497b8d8..d002049996df 100644
+--- a/shell/platform/fuchsia/flutter/engine.cc
++++ b/shell/platform/fuchsia/flutter/engine.cc
+@@ -227,7 +227,6 @@ Engine::Engine(Delegate& delegate,
+         task_runners,                    // host task runners
+         settings_,                       // shell launch settings
+         std::move(isolate_snapshot),     // isolate snapshot
+-        flutter::DartSnapshot::Empty(),  // shared snapshot
+         on_create_platform_view,         // platform view create callback
+         on_create_rasterizer,            // rasterizer create callback
+         std::move(vm)                    // vm reference
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
index 4e1a5ad..e7bf651 100755
--- a/tools/run_offsets_extractor.sh
+++ b/tools/run_offsets_extractor.sh
@@ -31,8 +31,6 @@
 run x64 ReleaseX64
 run ia32 ReleaseIA32
 run simarm64 ReleaseSIMARM64
-run simdbc64 ReleaseSIMDBC64
-run simdbc ReleaseSIMDBC
 
 # Cleanup.
 echo "" >>"$TEMP"
diff --git a/tools/spec_parser/.gitignore b/tools/spec_parser/.gitignore
index 8f983c7..4ca29f2 100644
--- a/tools/spec_parser/.gitignore
+++ b/tools/spec_parser/.gitignore
@@ -3,4 +3,5 @@
 *Listener.java
 *.tokens
 *.class
+*.interp
 *.dot
diff --git a/tools/spec_parser/Dart.g b/tools/spec_parser/Dart.g
index 23a8f91..7d35041 100644
--- a/tools/spec_parser/Dart.g
+++ b/tools/spec_parser/Dart.g
@@ -140,6 +140,7 @@
 topLevelDefinition
     :    classDeclaration
     |    mixinDeclaration
+    |    extensionDeclaration
     |    enumType
     |    typeAlias
     |    EXTERNAL functionSignature ';'
@@ -274,26 +275,48 @@
     |    ABSTRACT? CLASS mixinApplicationClass
     ;
 
-mixinDeclaration
-    :    MIXIN typeIdentifier typeParameters?
-         (ON typeNotVoidNotFunctionList)? interfaces?
-         LBRACE (metadata mixinMemberDefinition)* RBRACE
+superclass
+    :    EXTENDS typeNotVoidNotFunction
     ;
 
 mixins
     :    WITH typeNotVoidNotFunctionList
     ;
 
+interfaces
+    :    IMPLEMENTS typeNotVoidNotFunctionList
+    ;
+
 classMemberDefinition
     :    methodSignature functionBody
     |    declaration ';'
     ;
 
+mixinApplicationClass
+    :    typeWithParameters '=' mixinApplication ';'
+    ;
+
+mixinDeclaration
+    :    MIXIN typeIdentifier typeParameters?
+         (ON typeNotVoidNotFunctionList)? interfaces?
+         LBRACE (metadata mixinMemberDefinition)* RBRACE
+    ;
+
 // TODO: We will probably want to make this more strict.
 mixinMemberDefinition
     :    classMemberDefinition
     ;
 
+extensionDeclaration
+    :    EXTENSION identifier? typeParameters? ON type
+         LBRACE (metadata extensionMemberDefinition)* RBRACE
+    ;
+
+// TODO: We might want to make this more strict.
+extensionMemberDefinition
+    :    classMemberDefinition
+    ;
+
 methodSignature
     :    constructorSignature initializers
     |    factoryConstructorSignature
@@ -414,18 +437,6 @@
     :    CONST constructorName formalParameterList
     ;
 
-superclass
-    :    EXTENDS typeNotVoidNotFunction
-    ;
-
-interfaces
-    :    IMPLEMENTS typeNotVoidNotFunctionList
-    ;
-
-mixinApplicationClass
-    :    typeWithParameters '=' mixinApplication ';'
-    ;
-
 mixinApplication
     :    typeNotVoidNotFunction mixins interfaces?
     ;
@@ -512,6 +523,7 @@
     :    (multiLineString | singleLineString)+
     ;
 
+// Not used in the specification (needed here for <uri>).
 stringLiteralWithoutInterpolation
     :    singleLineStringWithoutInterpolation+
     ;
@@ -859,6 +871,7 @@
     |    IMPLEMENTS // Built-in identifier.
     |    IMPORT // Built-in identifier.
     |    INTERFACE // Built-in identifier.
+    |    LATE // Built-in identifier.
     |    LIBRARY // Built-in identifier.
     |    MIXIN // Built-in identifier.
     |    OPERATOR // Built-in identifier.
@@ -1065,7 +1078,11 @@
     ;
 
 libraryName
-    :    metadata LIBRARY identifier ('.' identifier)* ';'
+    :    metadata LIBRARY dottedIdentifierList ';'
+    ;
+
+dottedIdentifierList
+    :    identifier ('.' identifier)*
     ;
 
 importOrExport
@@ -1078,8 +1095,8 @@
     ;
 
 importSpecification
-    :    IMPORT uri (AS identifier)? combinator* ';'
-    |    IMPORT uri DEFERRED AS identifier combinator* ';'
+    :    IMPORT configurableUri (AS identifier)? combinator* ';'
+    |    IMPORT configurableUri DEFERRED AS identifier combinator* ';'
     ;
 
 combinator
@@ -1107,10 +1124,24 @@
     :    partHeader topLevelDefinition* EOF
     ;
 
+// In the specification a plain <stringLiteral> is used.
+// TODO(eernst): Check whether it creates ambiguities to do that.
 uri
     :    stringLiteralWithoutInterpolation
     ;
 
+configurableUri
+    :    uri configurationUri*
+    ;
+
+configurationUri
+    :    IF '(' uriTest ')' uri
+    ;
+
+uriTest
+    :    dottedIdentifierList ('==' stringLiteral)?
+    ;
+
 type
     :    functionType '?'?
     |    typeNotFunction
@@ -1221,6 +1252,7 @@
     :    '#' (operator | (identifier ('.' identifier)*))
     ;
 
+// Not used in the specification (needed here for <uri>).
 singleLineStringWithoutInterpolation
     :    RAW_SINGLE_LINE_STRING
     |    SINGLE_LINE_STRING_DQ_BEGIN_END
@@ -1276,22 +1308,124 @@
     |    DIGIT
     ;
 
-FINAL
-    :    'final'
+// Reserved words.
+
+ASSERT
+    :    'assert'
     ;
 
-LATE
-    :    'late'
+BREAK
+    :    'break'
     ;
 
-REQUIRED
-    :    'required'
+CASE
+    :    'case'
+    ;
+
+CATCH
+    :    'catch'
+    ;
+
+CLASS
+    :    'class'
     ;
 
 CONST
     :    'const'
     ;
 
+CONTINUE
+    :    'continue'
+    ;
+
+DEFAULT
+    :    'default'
+    ;
+
+DO
+    :    'do'
+    ;
+
+ELSE
+    :    'else'
+    ;
+
+ENUM
+    :    'enum'
+    ;
+
+EXTENDS
+    :    'extends'
+    ;
+
+FALSE
+    :    'false'
+    ;
+
+FINAL
+    :    'final'
+    ;
+
+FINALLY
+    :    'finally'
+    ;
+
+FOR
+    :    'for'
+    ;
+
+IF
+    :    'if'
+    ;
+
+IN
+    :    'in'
+    ;
+
+IS
+    :    'is'
+    ;
+
+NEW
+    :    'new'
+    ;
+
+NULL
+    :    'null'
+    ;
+
+RETHROW
+    :    'rethrow'
+    ;
+
+RETURN
+    :    'return'
+    ;
+
+SUPER
+    :    'super'
+    ;
+
+SWITCH
+    :    'switch'
+    ;
+
+THIS
+    :    'this'
+    ;
+
+THROW
+    :    'throw'
+    ;
+
+TRUE
+    :    'true'
+    ;
+
+TRY
+    :    'try'
+    ;
+
 VAR
     :    'var'
     ;
@@ -1300,14 +1434,16 @@
     :    'void'
     ;
 
-ASYNC
-    :    'async'
+WHILE
+    :    'while'
     ;
 
-THIS
-    :    'this'
+WITH
+    :    'with'
     ;
 
+// Built-in identifiers.
+
 ABSTRACT
     :    'abstract'
     ;
@@ -1316,94 +1452,46 @@
     :    'as'
     ;
 
-SYNC
-    :    'sync'
-    ;
-
-CLASS
-    :    'class'
-    ;
-
-WITH
-    :    'with'
-    ;
-
-STATIC
-    :    'static'
-    ;
-
-DYNAMIC
-    :    'dynamic'
-    ;
-
-EXTERNAL
-    :    'external'
-    ;
-
-GET
-    :    'get'
-    ;
-
-SET
-    :    'set'
-    ;
-
-OPERATOR
-    :    'operator'
-    ;
-
-SUPER
-    :    'super'
-    ;
-
-FACTORY
-    :    'factory'
-    ;
-
-EXTENDS
-    :    'extends'
-    ;
-
-IMPLEMENTS
-    :    'implements'
-    ;
-
-ENUM
-    :    'enum'
-    ;
-
-NULL
-    :    'null'
-    ;
-
-TRUE
-    :    'true'
-    ;
-
-FALSE
-    :    'false'
-    ;
-
-THROW
-    :    'throw'
-    ;
-
-NEW
-    :    'new'
-    ;
-
-AWAIT
-    :    'await'
+COVARIANT
+    :    'covariant'
     ;
 
 DEFERRED
     :    'deferred'
     ;
 
+DYNAMIC
+    :    'dynamic'
+    ;
+
 EXPORT
     :    'export'
     ;
 
+EXTENSION
+    :    'extension'
+    ;
+
+EXTERNAL
+    :    'external'
+    ;
+
+FACTORY
+    :    'factory'
+    ;
+
+FUNCTION
+    :    'Function'
+    ;
+
+GET
+    :    'get'
+    ;
+
+IMPLEMENTS
+    :    'implements'
+    ;
+
 IMPORT
     :    'import'
     ;
@@ -1412,10 +1500,18 @@
     :    'interface'
     ;
 
+LATE
+    :    'late'
+    ;
+
 LIBRARY
     :    'library'
     ;
 
+OPERATOR
+    :    'operator'
+    ;
+
 MIXIN
     :    'mixin'
     ;
@@ -1424,88 +1520,36 @@
     :    'part'
     ;
 
+REQUIRED
+    :    'required'
+    ;
+
+SET
+    :    'set'
+    ;
+
+STATIC
+    :    'static'
+    ;
+
 TYPEDEF
     :    'typedef'
     ;
 
-IS
-    :    'is'
-    ;
+// "Contextual keywords".
 
-IF
-    :    'if'
-    ;
-
-ELSE
-    :    'else'
-    ;
-
-WHILE
-    :    'while'
-    ;
-
-FOR
-    :    'for'
-    ;
-
-IN
-    :    'in'
-    ;
-
-DO
-    :    'do'
-    ;
-
-SWITCH
-    :    'switch'
-    ;
-
-CASE
-    :    'case'
-    ;
-
-DEFAULT
-    :    'default'
-    ;
-
-RETHROW
-    :    'rethrow'
-    ;
-
-TRY
-    :    'try'
-    ;
-
-ON
-    :    'on'
-    ;
-
-CATCH
-    :    'catch'
-    ;
-
-FINALLY
-    :    'finally'
-    ;
-
-RETURN
-    :    'return'
-    ;
-
-BREAK
-    :    'break'
-    ;
-
-CONTINUE
-    :    'continue'
+AWAIT
+    :    'await'
     ;
 
 YIELD
     :    'yield'
     ;
 
-SHOW
-    :    'show'
+// Other words used in the grammar.
+
+ASYNC
+    :    'async'
     ;
 
 HIDE
@@ -1516,18 +1560,20 @@
     :    'of'
     ;
 
-ASSERT
-    :    'assert'
+ON
+    :    'on'
     ;
 
-COVARIANT
-    :    'covariant'
+SHOW
+    :    'show'
     ;
 
-FUNCTION
-    :    'Function'
+SYNC
+    :    'sync'
     ;
 
+// Lexical tokens that are not words.
+
 NUMBER
     :    DIGIT+ '.' DIGIT+ EXPONENT?
     |    DIGIT+ EXPONENT?
@@ -1555,12 +1601,37 @@
     ;
 
 fragment
-STRING_CONTENT_SQ
-    :    ~('\\' | '\'' | '$' |  '\r' | '\n')
-    |    '\\' ~( '\r' | '\n')
+ESCAPE_SEQUENCE
+    :    '\\n'
+    |    '\\r'
+    |    '\\b'
+    |    '\\t'
+    |    '\\v'
+    |    '\\x' HEX_DIGIT HEX_DIGIT
+    |    '\\u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
+    |    '\\u{' HEX_DIGIT_SEQUENCE '}'
+    ;
+
+fragment
+HEX_DIGIT_SEQUENCE
+    :    HEX_DIGIT HEX_DIGIT? HEX_DIGIT?
+         HEX_DIGIT? HEX_DIGIT? HEX_DIGIT?
+    ;
+
+fragment
+STRING_CONTENT_COMMON
+    :    ~('\\' | '\'' | '"' | '$' | '\r' | '\n')
+    |    ESCAPE_SEQUENCE
+    |    '\\' ~('n' | 'r' | 'b' | 't' | 'v' | 'x' | 'u' | '\r' | '\n')
     |    SIMPLE_STRING_INTERPOLATION
     ;
 
+fragment
+STRING_CONTENT_SQ
+    :    STRING_CONTENT_COMMON
+    |    '"'
+    ;
+
 SINGLE_LINE_STRING_SQ_BEGIN_END
     :    '\'' STRING_CONTENT_SQ* '\''
     ;
@@ -1582,9 +1653,8 @@
 
 fragment
 STRING_CONTENT_DQ
-    :    ~('\\' | '"' | '$' | '\r' | '\n')
-    |    '\\' ~('\r' | '\n')
-    |    SIMPLE_STRING_INTERPOLATION
+    :    STRING_CONTENT_COMMON
+    |    '\''
     ;
 
 SINGLE_LINE_STRING_DQ_BEGIN_END
@@ -1620,7 +1690,7 @@
 fragment
 STRING_CONTENT_TSQ
     :    QUOTES_SQ
-         (~('\\' | '$' | '\'') | '\\' . | SIMPLE_STRING_INTERPOLATION)
+         (STRING_CONTENT_COMMON | '"' | '\r' | '\n' | '\\\r' | '\\\n')
     ;
 
 MULTI_LINE_STRING_SQ_BEGIN_END
@@ -1656,7 +1726,7 @@
 fragment
 STRING_CONTENT_TDQ
     :    QUOTES_DQ
-         (~('\\' | '$' | '"') | '\\' . | SIMPLE_STRING_INTERPOLATION)
+         (STRING_CONTENT_COMMON | '\'' | '\r' | '\n' | '\\\r' | '\\\n')
     ;
 
 MULTI_LINE_STRING_DQ_BEGIN_END
diff --git a/tools/test.dart b/tools/test.dart
index 4c181a0..1e1b405 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -99,13 +99,9 @@
       (component) => [
             "arm",
             "arm64",
-            "armsimdbc",
-            "armsimdbc64",
             "ia32",
             "simarm",
             "simarm64",
-            "simdbc",
-            "simdbc64",
             "x64",
           ].contains(component),
       orElse: () => null);
diff --git a/tools/utils.py b/tools/utils.py
index 085236a..1002e37 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -79,9 +79,7 @@
 # Try to guess the host architecture.
 def GuessArchitecture():
     os_id = platform.machine()
-    if os_id.startswith('armv5te'):
-        return 'armv5te'
-    elif os_id.startswith('armv6'):
+    if os_id.startswith('armv6'):
         return 'armv6'
     elif os_id.startswith('arm'):
         return 'arm'
@@ -268,16 +266,10 @@
     'x64': 'ia32',
     'arm': 'arm',
     'armv6': 'arm',
-    'armv5te': 'arm',
     'arm64': 'arm',
     'simarm': 'ia32',
     'simarmv6': 'ia32',
-    'simarmv5te': 'ia32',
     'simarm64': 'ia32',
-    'simdbc': 'ia32',
-    'simdbc64': 'ia32',
-    'armsimdbc': 'arm',
-    'armsimdbc64': 'arm',
     'simarm_x64': 'ia32',
 }
 
diff --git a/utils/analysis_server/BUILD.gn b/utils/analysis_server/BUILD.gn
index ed5eb6a..29c34d9 100644
--- a/utils/analysis_server/BUILD.gn
+++ b/utils/analysis_server/BUILD.gn
@@ -4,12 +4,20 @@
 
 import("../application_snapshot.gni")
 
+analysis_server_files = exec_script("../../tools/list_dart_files.py",
+                                    [
+                                      "absolute",
+                                      rebase_path("../../pkg/analysis_server"),
+                                    ],
+                                    "list lines")
+
 application_snapshot("analysis_server") {
   main_dart = "../../pkg/analysis_server/bin/server.dart"
   training_args = [
-    "--help"
+    "--help",
     # TODO(34616): This is broken on Fuchsia.
     # "--sdk=" + rebase_path("../../sdk/"),
     # "--train-using=" + rebase_path("../../pkg/analyzer_cli")
   ]
+  inputs = analysis_server_files
 }
diff --git a/utils/bazel/BUILD.gn b/utils/bazel/BUILD.gn
index 6f6d3da..d674776 100644
--- a/utils/bazel/BUILD.gn
+++ b/utils/bazel/BUILD.gn
@@ -7,4 +7,7 @@
 application_snapshot("kernel_worker") {
   main_dart = "kernel_worker.dart"
   training_args = [ "--help" ]
+  deps = [
+    "../../pkg:pkg_files_stamp",
+  ]
 }
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index f80450c..ad4aec0 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -142,7 +142,8 @@
   ..addOption('used-inputs')
   ..addFlag('track-widget-creation', defaultsTo: false)
   ..addMultiOption('enable-experiment',
-      help: 'Enable a language experiment when invoking the CFE.');
+      help: 'Enable a language experiment when invoking the CFE.')
+  ..addMultiOption('define', abbr: 'D');
 
 class ComputeKernelResult {
   final bool succeeded;
@@ -166,6 +167,7 @@
     fe.InitializedCompilerState previousState}) async {
   dynamic out = outputBuffer ?? stderr;
   bool succeeded = true;
+
   var parsedArgs = summaryArgsParser.parse(args);
 
   if (parsedArgs['help']) {
@@ -244,6 +246,8 @@
   fe.InitializedCompilerState state;
   bool usingIncrementalCompiler = false;
   bool recordUsedInputs = parsedArgs["used-inputs"] != null;
+  var environmentDefines = _parseEnvironmentDefines(parsedArgs['define']);
+
   if (parsedArgs['use-incremental-compiler']) {
     usingIncrementalCompiler = true;
 
@@ -286,6 +290,7 @@
         fileSystem,
         (parsedArgs['enable-experiment'] as List<String>),
         summaryOnly,
+        environmentDefines,
         trackNeededDillLibraries: recordUsedInputs);
   } else {
     state = await fe.initializeCompiler(
@@ -298,7 +303,8 @@
         linkedInputs,
         target,
         fileSystem,
-        (parsedArgs['enable-experiment'] as List<String>));
+        parsedArgs['enable-experiment'] as List<String>,
+        environmentDefines);
   }
 
   void onDiagnostic(fe.DiagnosticMessage message) {
@@ -448,3 +454,20 @@
   // concatenated with Unix-style paths.
   return Uri.base.resolve(uriString.replaceAll("\\", "/"));
 }
+
+Map<String, String> _parseEnvironmentDefines(List<String> args) {
+  var environment = <String, String>{};
+
+  for (var arg in args) {
+    var eq = arg.indexOf('=');
+    if (eq <= 0) {
+      var kind = eq == 0 ? 'name' : 'value';
+      throw FormatException('no $kind given to -D option `$arg`');
+    }
+    var name = arg.substring(0, eq);
+    var value = arg.substring(eq + 1);
+    environment[name] = value;
+  }
+
+  return environment;
+}
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index d54c1ef..8b03d63 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -211,6 +211,16 @@
     "-o",
     rebase_path("$target_gen_dir/js/legacy/dart_sdk.js"),
   ]
+
+  # TODO(38701): Cleanup after merging the forked SDK into mainline.
+  if (use_nnbd) {
+    args += [
+      "--enable-experiment=non-nullable",
+
+      # TODO(38813): Ignore incorrect analyzer errors.
+      "--unsafe-force-compile",
+    ]
+  }
 }
 
 # Builds everything needed to run dartdevc tests using test.dart.
@@ -321,6 +331,19 @@
     "--output",
     rebase_path("$target_gen_dir"),
   ]
+
+  # TODO(38701): Cleanup after merging the forked SDK into mainline.
+  if (use_nnbd) {
+    args += [
+      "--enable-experiment=non-nullable",
+
+      # TODO(rnystrom): Most of the packages used by tests can be cleanly
+      # compiled as opted-in libraries, but js.dart has an optional parameter
+      # of type String with no default value. Changing that would be a breaking
+      # API change. For now, ignore the error.
+      "--unsafe-force-compile",
+    ]
+  }
 }
 
 prebuilt_dart_action("dartdevc_kernel_sdk_outline") {
@@ -349,14 +372,19 @@
     "--multi-root-scheme",
     "org-dartlang-sdk",
     "--multi-root",
-    rebase_path("../../sdk"),
+    "file:///" + rebase_path(sdk_root),
     "--libraries-file",
-    "file:///" + rebase_path("$sdk_root/lib/libraries.json"),
+    "org-dartlang-sdk:///lib/libraries.json",
     "--output",
     rebase_path(sdk_dill),
     "--source",
     "dart:core",
   ]
+
+  # TODO(38701): Cleanup after merging the forked SDK into mainline.
+  if (use_nnbd) {
+    args += [ "--enable-experiment=non-nullable" ]
+  }
 }
 
 copy("dartdevc_kernel_sdk_libraries_json") {
@@ -424,4 +452,9 @@
     "-o",
     rebase_path("$target_gen_dir/kernel/legacy/dart_sdk.js"),
   ]
+
+  # TODO(38701): Cleanup after merging the forked SDK into mainline.
+  if (use_nnbd) {
+    args += [ "--enable-experiment=non-nullable" ]
+  }
 }